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 }