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