001    package data;
002    
003    import java.io.Serializable;
004    import java.util.Iterator;
005    
006    import log.LogContext;
007    
008    /**
009     * An object collecting information about a activities on data objects in a
010     * {@link sale.Shop shop}.
011     *
012     * <p>The DataBasket is used in the manner of a &quot;transcation handle&quot;,
013     * i.e. all actions with data containers (e.g. {@link Catalog Catalogs},
014     * {@link Stock Stocks} etc.) are processed relative to this DataBasket. The
015     * following rules apply:</p>
016     *
017     * <ul>
018     *   <li><strong>Adding items to data containers:</strong><br>
019     *       All adding of items is only temporary until an explicit
020     *       {@link #commit commit} is performed on the DataBasket. Freshly added
021     *       items are only visible to the owner of the DataBasket relative to
022     *       which they were added. However, there may be cases when the temporary
023     *       adding of an entry to a data container prevents other entries (e.g.,
024     *       of the same key) from being added. This is, for example, the case with
025     *       Catalogs, because there can always be at most one CatalogItem for any
026     *       given key in any given Catalog. The resulting conflict is
027     *       conventionally resolved by throwing a DataBasketConflictException that
028     *       also states the reason for the conflict in its detail message.</li>
029     *   <li><strong>Removing items from a data container:</strong><br>
030     *       All removing of items is only temporary until an explicit
031     *       {@link #commit commit} is performed on the DataBasket. Usually, adding
032     *       an item just removed using the same DataBasket, will roll back the
033     *       activity. However, this is container specific behavior that may differ
034     *       between containers.</li>
035     *   <li><strong>Looking at an item from a data container:</strong><br>
036     *       Only items that are really in the container, plus items that have been
037     *       added using the same DataBasket are visible. Usually there are two
038     *       different modes of looking at an item: just for reading or for
039     *       editing the item. These differ in several ways:
040     *       <ol>
041     *         <li>There is no guarantee that an item just got for reading will
042     *             still be in the container the next time you look. For items that
043     *             you got for editing purposes this guarantee can be given.
044     *         </li>
045     *         <li>Items you got for editing will no longer be visible for users
046     *             of different DataBaskets. This is the reason why the former
047     *             assertion can be given. The items will become visible again,
048     *             when a {@link #commit commit} is performed.</li>
049     *         <li>Although you can edit items that you just got for reading, by
050     *             doing so, you loose the ability to undo the action and, because
051     *             others can see the changing in progress, you risk
052     *             inconsistencies in your data. Therefore, such behavior is
053     *             considered bad style and is not recommended.</li>
054     *       </ol>
055     *   </li>
056     * </ul>
057     *
058     * <p>DataBaskets provide the capability to undo whole blocks of activities
059     * without having to consider the single activities. To do so, you simply call
060     * {@link #rollback one of the rollback methods} on the DataBasket relative to
061     * which the activities where performed. On the other hand, you will have to
062     * call {@link #commit commit} to fix changes and make them visible to owners
063     * of other DataBaskets. Once commited, a change can no longer be rolled back.
064     * </p>
065     *
066     * <p>Additionally, you can define subsections in a DataBasket, which can be
067     * commited or rolled back individually and independently. Also you can commit
068     * or rollback an arbitrary subset of elements by defining a selecting
069     * condition. These operations are, however, optional, and may not be
070     * implemented in all concrete implementations of the DataBasket interface.</p>
071     *
072     * <p>In addition to their useability as &quot;transaction handles&quot;,
073     * DataBaskets can be inspected, thus allowing for applications where customers
074     * can roam the Shop freely, deciding to take things and to put them back, and
075     * will only be charged at the end, based on the contents of their DataBasket.
076     * To implement such strategies, see {@link #iterator}, {@link #sumBasket}.</p>
077     *
078     * <p>DataBaskets allow for a {@link LogContext} to be defined. Operations on
079     * the DataBasket can be logged using the current LogContext of the DataBasket.
080     * You can decide which actions are being logged by setting the appropriate
081     * parameter in a call to {@link #setLogMode}.</p>
082     *
083     * @author Steffen Zschaler
084     * @version 2.0 10/06/1999
085     * @since v2.0
086     */
087    public interface DataBasket extends Serializable {
088    
089        /**
090         * Commit the entire contents of the DataBasket.
091         *
092         * <p>All temporarily added or removed items will be finally added or removed from their
093         * respective containers. All items got for editing will be put back into their container
094         * and any changes to them will be fixed. All items that have only been visible to users
095         * of this DataBasket will henceforward be visible for every user. Every item that was
096         * committed will be removed from the DataBasket and, thus, the DataBasket will be empty.
097         * </p>
098         *
099         * @see #rollback
100         *
101         * @override Always
102         */
103        public void commit();
104    
105        /**
106         * Roll back the entire contents of the DataBasket.
107         *
108         * <p>All temporarily added or removed items will be removed from, or put back into,
109         * their respective containers, resp. All changes that where made to items that were
110         * edited will be undone. All items will be restored to their original visibility.
111         * Every item that was rolled back will be removed from the DataBasket and, thus, the
112         * DataBasket will be empty.</p>
113         *
114         * @see #commit
115         *
116         * @override Always
117         */
118        public void rollback();
119    
120        /**
121         * Commit the contents of the named subbasket.
122         *
123         * <p>All items in the named subbasket will be commited, and the subbasket will be empty
124         * afterwards. Any item that is not in the subbasket will not be touched, unless
125         * dependencies between the items require so. For a description of the commit process
126         * refer to {@link #commit()}.</p>
127         *
128         * <p>This is an optional operation that does not need to be supported by concrete
129         * implementations of the interface. To indicate that this method is not supported, such
130         * implementations must throw an UnSupportedOperationException.</p>
131         *
132         * @param sName the name of the subbasket to be commited.
133         *
134         * @exception UnsupportedOperationException to indicate that this method is not
135         *            implemented in a certain implementation of the interface.
136         *
137         * @see #setCurrentSubBasket
138         * @see #rollbackSubBasket
139         *
140         * @override Always
141         */
142        public void commitSubBasket(String sName);
143    
144        /**
145         * Commit the contents of the current subbasket.
146         *
147         * <p>All items in the current subbasket will be commited, and the subbasket will be empty
148         * afterwards. Any item that is not in the subbasket will not be touched, unless
149         * dependencies between the items require so. For a description of the commit process
150         * refer to {@link #commit()}.</p>
151         *
152         * <p>This is an optional operation that does not need to be supported by concrete
153         * implementations of the interface. To indicate that this method is not supported, such
154         * implementations must throw an UnSupportedOperationException.</p>
155         *
156         * @exception UnsupportedOperationException to indicate that this method is not
157         *            implemented in a certain implementation of the interface.
158         *
159         * @see #setCurrentSubBasket
160         * @see #rollbackCurrentSubBasket
161         *
162         * @override Always
163         */
164        public void commitCurrentSubBasket();
165    
166        /**
167         * Roll back the contents of the named subbasket.
168         *
169         * <p>All items in the named subbasket will be rolled back, and the subbasket will be
170         * empty afterwards. Any item that is not in the subbasket will not be touched, unless
171         * dependencies between the items require so. For a description of the rollback process
172         * refer to {@link #rollback()}.</p>
173         *
174         * <p>This is an optional operation that does not need to be supported by concrete
175         * implementations of the interface. To indicate that this method is not supported, such
176         * implementations must throw a UnSupportedOperationException.</p>
177         *
178         * @param sName the name of the subbasket to be rolled back.
179         *
180         * @exception UnsupportedOperationException to indicate that this method is not
181         *            implemented in a certain implementation of the interface.
182         *
183         * @see #setCurrentSubBasket
184         * @see #commitSubBasket
185         *
186         * @override Always
187         */
188        public void rollbackSubBasket(String sName);
189    
190        /**
191         * Roll back the contents of the current subbasket.
192         *
193         * <p>All items in the current subbasket will be rolled back, and the subbasket will be
194         * empty afterwards. Any item that is not in the subbasket will not be touched, unless
195         * dependencies between the items require so. For a description of the rollback process
196         * refer to {@link #rollback()}.</p>
197         *
198         * <p>This is an optional operation that does not need to be supported by concrete
199         * implementations of the interface. To indicate that this method is not supported, such
200         * implementations must throw an UnSupportedOperationException.</p>
201         *
202         * @exception UnsupportedOperationException to indicate that this method is not
203         *            implemented in a certain implementation of the interface.
204         *
205         * @see #setCurrentSubBasket
206         * @see #commitCurrentSubBasket
207         *
208         * @override Always
209         */
210        public void rollbackCurrentSubBasket();
211    
212        /**
213         * Commit all items that match the given condition.
214         *
215         * <p>All items matching the condition will be commited and removed from the DataBasket.
216         * No other item will be touched, unless dependencies between the items require so. For a
217         * description of the commit process refer to {@link #commit()}.</p>
218         *
219         * <p>This is an optional operation that does not need to be supported by concrete
220         * implementations of the interface. To indicate that this method is not supported, such
221         * implementations must throw an UnSupportedOperationException.</p>
222         *
223         * @exception UnsupportedOperationException to indicate that this method is not
224         *            implemented in a certain implementation of the interface.
225         *
226         * @override Always
227         */
228        public void commit(DataBasketCondition dbc);
229    
230        /**
231         * Roll back all items that match the given condition.
232         *
233         * <p>All items matching the condition will be rolled back and removed from the
234         * DataBasket. No other item will be touched, unless dependencies between the items
235         * require so. For a description of the rollback process refer to {@link #rollback()}.
236         * </p>
237         *
238         * <p>This is an optional operation that does not need to be supported by concrete
239         * implementations of the interface. To indicate that this method is not supported, such
240         * implementations must throw an UnSupportedOperationException.</p>
241         *
242         * @exception UnsupportedOperationException to indicate that this method is not
243         *            implemented in a certain implementation of the interface.
244         *
245         * @override Always
246         */
247        public void rollback(DataBasketCondition dbc);
248    
249        /**
250         * Set the current subbasket.
251         *
252         * <p>If no SubBasket of the given name exists, an empty one will be created and made
253         * the current SubBasket.</p>
254         *
255         * <p>All {@link #put put} operations put entries into the current subbasket of a
256         * DataBasket.</p>
257         *
258         * <p>SubBaskets can be used to define sets of independently commitable (or rollbackable,
259         * resp.) entries in a DataBasket. Thus you can build something similar to nested
260         * Transactions or SafePoints. However, when using SubBaskets, it is at least partly
261         * your responsibility to make sure, there are no dependencies between the contents of
262         * different SubBaskets. If you don't, or if you do not take measures to resolve such
263         * situations, using SubBaskets may result in inconsistent data in your system.</p>
264         *
265         * <p>This is an optional operation that does not need to be supported by concrete
266         * implementations of the interface. To indicate that this method is not supported, such
267         * implementations must throw an UnSupportedOperationException. Implementations may also
268         * choose to implement this method (and any other methods related to SubBaskets) in part,
269         * i.e. with more rigid preconditions defined. Such implementations would still throw an
270         * UnsupportedOperationException if the preconditions are not met. For example, an
271         * implementation based on relational databases might want to allow LIFO usage of
272         * SubBaskets as this can be modelled by nesting database transactions. It will throw an
273         * exception, however, when a client tries to use SubBaskets in a more random way.</p>
274         *
275         * @exception UnsupportedOperationException to indicate that this method is not
276         *            implemented in a certain implementation of the interface.
277         *
278         * @see #commitSubBasket
279         * @see #rollbackSubBasket
280         * @see #commitCurrentSubBasket
281         * @see #rollbackCurrentSubBasket
282         * @see #DEFAULTSUBBASKET_NAME
283         *
284         * @override Always
285         */
286        public void setCurrentSubBasket(String sName);
287    
288        /**
289         * The name of the default subbasket.
290         *
291         * <p>Every DataBasket has at least one SubBasket, that is used as long as no other
292         * SubBasket has been specified. This is the default subbasket and its name is stored
293         * in this constant.</p>
294         *
295         * @see #setCurrentSubBasket
296         */
297        public static final String DEFAULTSUBBASKET_NAME = "__TAG:_DEFAULT_SUBBASKET";
298    
299        /**
300         * Iterate the contents of this DataBasket.
301         *
302         * <p>The iterator will iterate the entire contents of the DataBasket, but will return
303         * only such items, that match the given condition.</p>
304         *
305         * @param dbc a condition, that items must match to be returned by the iterator.
306         *
307         * @override Always
308         */
309        public Iterator<DataBasketEntry> iterator(DataBasketCondition dbc);
310    
311        /**
312         * Iterate the contents of a given SubBasket.
313         *
314         * <p>The iterator will iterate all items in the given SubBasket that match the given
315         * condition.</p>
316         *
317         * @param sName the name of the SubBasket. A {@link NullPointerException} may
318         * be thrown if this SubBasket does not exist.
319         * @param dbc the condition that must be matched by items that are to be returned by the
320         * iterator
321         *
322         * @override Always
323         */
324        public Iterator<DataBasketEntry> subBasketIterator(String sName, DataBasketCondition dbc);
325    
326        /**
327         * Sum up the values of all items in this DataBasket that match the condition.
328         *
329         * @param dbc the condition that must be matched by all entries that are to be used in the
330         * process of adding up the DataBasket.
331         * @param bev an object helping in determining the value of a single entry.
332         * @param vInit the value that is to be used for adding up. All adding is performed by calling
333         * {@link Value#addAccumulating} on this object.
334         *
335         * @return the sum in <code>vInit</code>.
336         *
337         * @override Always
338         */
339        public Value sumBasket(DataBasketCondition dbc, BasketEntryValue bev, Value vInit);
340    
341        /**
342         * Sum up the values of all items in the given subbasket that match the condition.
343         *
344         * @param sName the name of the subbasket whose items are to be used.
345         * @param dbc the condition that must be matched by all entries that are to be used in the
346         * process of adding up the DataBasket.
347         * @param bev an object helping in determining the value of a single entry.
348         * @param vInit the value that is to be used for adding up. All adding is performed by calling
349         * {@link Value#addAccumulating} on this object.
350         *
351         * @return the sum in <code>vInit</code>.
352         *
353         * @override Always
354         */
355        public Value sumSubBasket(String sName, DataBasketCondition dbc, BasketEntryValue bev, Value vInit);
356    
357        /**
358         * Sum up the values of all items in the current subbasket that match the condition.
359         *
360         * @param dbc the condition that must be matched by all entries that are to be used in the
361         * process of adding up the DataBasket.
362         * @param bev an object helping in determining the value of a single entry.
363         * @param vInit the value that is to be used for adding up. All adding is performed by calling
364         * {@link Value#addAccumulating} on this object.
365         *
366         * @return the sum in <code>vInit</code>.
367         *
368         * @override Always
369         */
370        public Value sumCurrentSubBasket(DataBasketCondition dbc, BasketEntryValue bev, Value vInit);
371    
372        /**
373         * Return true if the DataBasket contains an entry that matches the condition. The entire
374         * DataBasket will be searched.
375         *
376         * @param dbc the condition to be matched.
377         *
378         * @return whether or not the DataBasket currently contains such an entry.
379         *
380         * @override Always
381         */
382        public boolean contains(DataBasketCondition dbc);
383    
384        /**
385         * Get the first entry found that matches the given condition. The entire DataBasket will
386         * be searched.
387         *
388         * <p>In this context, &quot;first&quot; does not mean the first entry added or anything
389         * similar; it simply refers to the first entry found when searching the DataBasket.
390         * Although this may be the first entry added, no assertions are given.</p>
391         *
392         * @param dbc the condition to be matched.
393         *
394         * @return an entry matching the condition, if any.
395         *
396         * @override Always
397         */
398        public DataBasketEntry get(DataBasketCondition dbc);
399    
400        /**
401         * Put an entry into the DataBasket's current subbasket.
402         *
403         * <p>This method is vital for the correct functioning of the DataBasket and, therefore,
404         * must never be called directly. Instead, call appropriate methods in the data containers
405         * ({@link Stock}, {@link Catalog}, etc.) you use. These will in turn call put
406         * on the DataBasket, thus making sure, that the DataBasket contains valid information only
407         * at all times.</p>
408         *
409         * <p>The <code>put</code> method will take the given entry as is and put it into the
410         * current subbasket. This is to say, that the caller is responsible for correctly setting
411         * up the fields in the entry - so that the information stored is meaningful to the client.
412         * In particular, resolving put after remove or remove after put of the same object and
413         * with regard to the same container is the responsibility of the caller.</p>
414         *
415         * @param dbe the entry to be put into the DataBasket.
416         *
417         * @override Always
418         */
419        public void put(DataBasketEntry dbe);
420    
421        /**
422         * Exchange a DataBasketEntry existing in the DataBasket with a new one.
423         *
424         * <p>This method is vital for the correct functioning of the DataBasket and, therefore,
425         * must never be called directly. Instead, call appropriate methods in the data containers
426         * ({@link Stock}, {@link Catalog}, etc.) you use. These will in turn call
427         * exchange on the DataBasket, thus making sure, that the DataBasket contains valid
428         * information only at all times.</p>
429         *
430         * @param dbeOrg the original DataBasketEntry, to be replaced. If the original entry is
431         * not found in the DataBasket, <code>exchange()</code> is equivalent to
432         * {@link #put put (dbeNew)}.
433         * @param dbeNew the replacement.
434         *
435         * @override Always
436         */
437        public void exchange(DataBasketEntry dbeOrg, DataBasketEntry dbeNew);
438    
439        /**
440         * Set the log context for this DataBasket.
441         *
442         * <p>All operations as defined through {@link #setLogMode} will be logged using the given log context. If
443         * the current log context is <code>null</code> no logging of any kind will occur.</p>
444         *
445         * @param lcNew the new log context
446         *
447         * @return the previous log context, if any.
448         *
449         * @override Always
450         */
451        public LogContext setLogContext(LogContext lcNew);
452    
453        /**
454         * Set the log mode for this DataBasket.
455         *
456         * <p>The current log mode decides what operations on the DataBasket are being logged. The default value is
457         * {@link #LOG_MODE_NONE}, indicating that no logging occurs. Other possibilities are:</p>
458         *
459         * <ul>
460         *   <li><strong>{@link #LOG_MODE_ALL}</strong> All operations on the DataBasket are being logged.</li>
461         *   <li><strong>{@link #LOG_MODE_COMMITS_ONLY}</strong> Only commits are being logged. There will be one
462         *       entry for each single step in the commit process.</li>
463         *   <li><strong>{@link #LOG_MODE_ROLLBACKS_ONLY}</strong> Only rollbacks are being logged. There will be
464         *       one entry for each single step in the rollback process.</li>
465         * </ul>
466         *
467         * <p>For details on the concrete implementation for log entries, please refer to the concrete
468         * implementation of the DataBasket.</p>
469         *
470         * @param nLogMode the new log mode.
471         *
472         * @return the previous log mode.
473         *
474         * @override Always
475         */
476        public int setLogMode(int nLogMode);
477    
478        /**
479         * Return the current log mode of the DataBasket. For information on the possible values and their meaning,
480         * please refer to {@link #setLogMode}.
481         *
482         * @override Always
483         */
484        public int getLogMode();
485    
486        /**
487         * Log mode constant.
488         *
489         * @see #setLogMode
490         * @see #getLogMode
491         */
492        public static final int LOG_MODE_NONE = 0;
493    
494        /**
495         * Log mode constant.
496         *
497         * @see #setLogMode
498         * @see #getLogMode
499         */
500        public static final int LOG_MODE_ALL = 1;
501    
502        /**
503         * Log mode constant.
504         *
505         * @see #setLogMode
506         * @see #getLogMode
507         */
508        public static final int LOG_MODE_COMMITS_ONLY = 2;
509    
510        /**
511         * Log mode constant.
512         *
513         * @see #setLogMode
514         * @see #getLogMode
515         */
516        public static final int LOG_MODE_ROLLBACKS_ONLY = 4;
517    }