001    package data;
002    
003    import java.util.Iterator;
004    import java.util.Set;
005    
006    import data.events.VetoException;
007    
008    /**
009     * A Stock.
010     *
011     * <p>Stocks are lists that refer to a {@link Catalog} and denote for each {@link CatalogItem} how many
012     * objects of this type are actually available. There are two basically different types of Stocks:
013     *
014     * <ol>
015     *   <li><b>{@link CountingStock}</b><br>
016     *       Stocks that store only the number of objects available for each CatalogItem.<br>
017     *       This type of Stock will be used whenever the information given by the CatalogItem sufficiently
018     *       describes the object.<br>
019     *       In general this type of Stock should be sufficient.</li>
020     *   <li><b>{@link StoringStock}</b><br>
021     *       Stocks that store a list of actual StockItems for each CatalogItem.<br>
022     *       This type of Stock is usually used to store additional information with the StockItems. E.g. to store
023     *       the 'Stock' of lent books in a library you would create {@link StockItem StockItems} that can store
024     *       the name of the borrower and the date of borrowing.<br>
025     *       This type of Stock is also needed when implementing nested Stocks.</li>
026     * </ol>
027     *
028     * <p>To suit both types of Stock, {@link StockItem StockItems} are introduced. A StockItem refers to a
029     * CatalogItem but can store additional information as well.</p>
030     *
031     * <p>Stocks work always on StockItems. They add, remove and search StockItems. They are able to return an
032     * Iterator of StockItems for a given key, but can as well just count all StockItems for the same key.</p>
033     *
034     * @author Steffen Zschaler
035     * @version 2.0 18/08/1999
036     * @since v0.5
037     */
038    public interface Stock<T extends StockItem, CT extends CatalogItem> extends StockItem, 
039                                                        DataBasketEntrySource, 
040                                                        DataBasketEntryDestination {
041    
042        /**
043         * Add an item to the Stock.
044         *
045         * <p>The item will only be visible to users of the same DataBasket. Only after a {@link DataBasket#commit}
046         * was performed on the DataBasket, the item will become visible to other users.</p>
047         *
048         * <p>For a {@link ListenableStock} a <code>addedStockItems</code> event will be fired.</p>
049         *
050         * @param si the item to be added.
051         * @param db the DataBasket relative to which the item will be added.
052         *
053         * @override Always
054         *
055         * @exception CatalogConflictException if the items key is not contained in the corresponding {@link Catalog}.
056         * @exception DataBasketConflictException if the item has already been added/removed using another DataBasket.
057         */
058        public void add(T si, DataBasket db);
059    
060        /**
061         * Add the contents of a Stock to this Stock. The method conceptually calls {@link #add} for each item in
062         * the source Stock so the same constraints apply and the same exceptions may be thrown.
063         *
064         * @override Always
065         *
066         * @param st the Stock whose contents is to be added to this Stock.
067         * @param db the DataBasket relative to which to perform the actions. <code>addStock</code> will add all
068         * items from the source Stock that are visible using this DataBasket.
069         * @param fRemove if true, the items will be removed from the source Stock prior to adding them to this
070         * Stock. Otherwise, they will be cloned prior to adding them to the Stock.
071         */
072        public void addStock(Stock<T, CT> st, DataBasket db, boolean fRemove);
073    
074        /**
075         * Iterate all items with a given key.
076         *
077         * <p>This method, together with {@link #iterator} is the only way of accessing the individual
078         * {@link StockItem StockItems} contained in a Stock. The iterator will deliver all items that have the
079         * specified key and are visible using the given DataBasket. Depending on the <code>fForEdit</code>
080         * parameter, the items will be retrieved in different ways. See {@link DataBasket} for an explanation of
081         * the different possibilities.</p>
082         *
083         * <p>For a {@link ListenableStock} <code>canEditStockItems</code> and <code>editingStockItems</code> events
084         * will be fired if <code>fForEdit</code> == true. {@link VetoException VetoExceptions} will be converted
085         * into <code>UnSupportedOperationException</code>s.</p>
086         *
087         * @override Always
088         *
089         * @param sKey the key for which to retrieve the StockItems.
090         * @param db the DataBasket relative to which to retrieve the StockItems.
091         * @param fForEdit if true, the StockItems will be retrieved for editing.
092         */
093        public Iterator<T> get(String sKey, DataBasket db, boolean fForEdit);
094    
095        /**
096         * Count the StockItems with a given key that are visible using a given DataBasket.
097         *
098         * @override Always
099         *
100         * @param sKey the key for which to count the StockItems.
101         * @param db the DataBasket that is used to determine visibility.
102         */
103        public int countItems(String sKey, DataBasket db);
104    
105        /**
106         * Check whether the Stock contains an item with the given key.
107         *
108         * <p>Equivalent to:<code>({@link #countItems} (sKey, db) > 0)</code>.</p>
109         *
110         * @override Always
111         *
112         * @param sKey the key for which to check containment.
113         * @param db the DataBasket used to check visibility.
114         */
115        public boolean contains(String sKey, DataBasket db);
116    
117        /**
118         * Check whether the Stock contains the given StockItem.
119         *
120         * <p>Return true if the Stock contains a StockItem that is equal to the given one.</p>
121         *
122         * @param si the StockItem for which to check containment.
123         * @param db the DataBasket used to check visibility.
124         *
125         * @override Always.
126         */
127        public boolean contains(T si, DataBasket db);
128    
129        /**
130         * Check whether the given Stock is completely contained in this Stock.
131         *
132         * <p>Conceptually calls {@link #contains(data.StockItem, data.DataBasket)} for each item in the given Stock.
133         * </p>
134         *
135         * @override Always
136         *
137         * @param st the Stock for which to check containment.
138         * @param db the DataBasket used to determine visibility.
139         */
140        public boolean containsStock(Stock<T, CT> st, DataBasket db);
141    
142        /**
143         * Remove one StockItem with the specified key from the Stock.
144         *
145         * <p>If there are any StockItems with the specified key, one will be removed. There is no guarantee as to
146         * which StockItem will be removed. The removed item, if any, will be returned.</p>
147         *
148         * <p>For a {@link ListenableStock} <code>canRemoveStockItems</code> and <code>removedStockItems</code>
149         * events will be fired.</p>
150         *
151         * @override Always
152         *
153         * @param sKey the key for which to remove an item.
154         * @param db the DataBasket relative to which to remove the item.
155         *
156         * @return the removed item
157         *
158         * @exception VetoException if a listener vetoed the removal.
159         * @exception DataBasketConflictException if the item cannot be removed due to conflicts from DataBasket
160         * usage.
161         */
162        public StockItem remove(String sKey, DataBasket db) throws VetoException;
163    
164        /**
165         * Remove the given StockItem from the Stock.
166         *
167         * <p>If the given StockItem is contained in the Stock, it will be removed. The removed item, if any, will
168         * be returned.</p>
169         *
170         * <p>For a {@link ListenableStock} <code>canRemoveStockItems</code> and <code>removedStockItems</code>
171         * events will be fired.</p>
172         *
173         * @override Always
174         *
175         * @param si the StockItem to be removed.
176         * @param db the DataBasket relative to which to remove the item.
177         *
178         * @return the removed item
179         *
180         * @exception VetoException if a listener vetoed the removal.
181         * @exception DataBasketConflictException if the item cannot be removed due to conflicts from DataBasket
182         * usage.
183         */
184        public StockItem remove(T si, DataBasket db) throws VetoException;
185    
186        /**
187         * Iterate all items in the Stock.
188         *
189         * <p>This method, together with {@link #get} is the only way of accessing the individual
190         * {@link StockItem StockItems} contained in a Stock. The iterator will deliver all items that are visible
191         * using the given DataBasket. Depending on the <code>fForEdit</code> parameter, the items will be retrieved
192         * in different ways. See {@link DataBasket} for an explanation of the different possibilities.</p>
193         *
194         * <p>For a {@link ListenableStock} <code>canEditStockItems</code> and <code>editingStockItems</code> events
195         * will be fired if <code>fForEdit</code> == true. {@link VetoException VetoExceptions} will be converted
196         * into <code>UnSupportedOperationException</code>s.</p>
197         *
198         * @override Always
199         *
200         * @param db the DataBasket relative to which to retrieve the StockItems.
201         * @param fForEdit if true, the StockItems will be retrieved for editing.
202         */
203        public Iterator<T> iterator(DataBasket db, boolean fForEdit);
204    
205        /**
206         * Return the set of keys for which {@link StockItem StockItems} are visible using the given DataBasket.
207         *
208         * <p>The returned set is static and gives the state of the Stock at the time of the call. It will not
209         * automatically update when the contents of the Stock changes.</p>
210         *
211         * @param db the DataBasket used for determining visibility.
212         *
213         * @override Always
214         */
215        public Set<String> keySet(DataBasket db);
216    
217        /**
218         * Sum up the Stock.
219         *
220         * <p>The method will determine the value of each {@link CatalogItem} in the associated Catalog and
221         * {@link Value#multiplyAccumulating(int) multiply} this by
222         * {@link #countItems the number of StockItems for the respective key}. These products will be
223         * {@link Value#addAccumulating added up} and the resulting total will be returned.</p>
224         *
225         * @override Always
226         *
227         * @param db the DataBasket that is used to determine visibility.
228         * @param civ the CatalogItemValue used for determining the value of a CatalogItem.
229         * @param vInit the initial value. The sum of the Stock will be added to this value.
230         *
231         * @return the resulting total. Usually the returned object is the same as the one passed as
232         * <code>vInit</code>, only with a changed value.
233         */
234        public Value sumStock(DataBasket db, CatalogItemValue civ, Value vInit);
235    
236        /**
237         * Increase the {@link #sumStock Stock's value} by a given value.
238         *
239         * <p>The method will try to break the given value as exactly as possible into StockItems that will be
240         * added to the Stock. The actual algorithm used for breaking up the value will be determined by the last
241         * parameter. The return value of the method will specify the remaining value that could not be represented
242         * by StockItems by the given algorithm.</p>
243         *
244         * @param db the DataBasket relative to which to perform the operation.
245         * @param vTarget the value by which to increase the Stock's total value.
246         * @param sfvc the strategy used to fill the Stock.
247         *
248         * @return the value that remained and could not be represented by StockItems.
249         *
250         * @override Always
251         */
252        public Value fillStockWithValue(DataBasket db, Value vTarget, StockFromValueCreator sfvc);
253    
254        /**
255         * Get the size of this Stock. I.e. calculate the number of StockItems that can be seen when using the
256         * given DataBasket.
257         *
258         * @param db the DataBasket used to determine visibility.
259         *
260         * @override Always
261         */
262        public int size(DataBasket db);
263    
264        /**
265         * Get the Catalog associated to this Stock.
266         *
267         * <p>For a substock of another stock this is essentially equivalent to
268         * <pre>
269         * Catalog cReturn = (Catalog) {@link StockItem#getAssociatedItem getAssociatedItem} (db);
270         *
271         * if (cReturn != null) {
272         *   return cReturn;
273         * }
274         * else {
275         *   throw new {@link DataBasketConflictException}();
276         * }
277         * </pre>
278         *
279         * @param db a DataBasket determinig visibility of the stock's catalog.
280         *
281         * @override Always
282         */
283        public Catalog getCatalog(DataBasket db);
284    }