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 }