package data; import java.util.*; import java.io.Serializable; import log.*; /** * An object collecting information about a activities on data objects in a * {@link sale.Shop shop}. * * <p>The DataBasket is used in the manner of a "transcation handle", * i.e. all actions with data containers (e.g. {@link Catalog Catalogs}, * {@link Stock Stocks} etc.) are processed relative to this DataBasket. The * following rules apply:</p> * * <ul> * <li><strong>Adding items to data containers:</strong><br> * All adding of items is only temporary until an explicit * {@link #commit commit} is performed on the DataBasket. Freshly added * items are only visible to the owner of the DataBasket relative to * which they were added. However, there may be cases when the temporary * adding of an entry to a data container prevents other entries (e.g., * of the same key) from being added. This is, for example, the case with * Catalogs, because there can always be at most one CatalogItem for any * given key in any given Catalog. The resulting conflict is * conventionally resolved by throwing a DataBasketConflictException that * also states the reason for the conflict in its detail message.</li> * <li><strong>Removing items from a data container:</strong><br> * All removing of items is only temporary until an explicit * {@link #commit commit} is performed on the DataBasket. Usually, adding * an item just removed using the same DataBasket, will roll back the * activity. However, this is container specific behavior that may differ * between containers.</li> * <li><strong>Looking at an item from a data container:</strong><br> * Only items that are really in the container, plus items that have been * added using the same DataBasket are visible. Usually there are two * different modes of looking at an item: just for reading or for * editing the item. These differ in several ways: * <ol> * <li>There is no guarantee that an item just got for reading will * still be in the container the next time you look. For items that * you got for editing purposes this guarantee can be given. * </li> * <li>Items you got for editing will no longer be visible for users * of different DataBaskets. This is the reason why the former * assertion can be given. The items will become visible again, * when a {@link #commit commit} is performed.</li> * <li>Although you can edit items that you just got for reading, by * doing so, you loose the ability to undo the action and, because * others can see the changing in progress, you risk * inconsistencies in your data. Therefore, such behavior is * considered bad style and is not recommended.</li> * </ol> * </li> * </ul> * * <p>DataBaskets provide the capability to undo whole blocks of activities * without having to consider the single activities. To do so, you simply call * {@link #rollback one of the rollback methods} on the DataBasket relative to * which the activities where performed. On the other hand, you will have to * call {@link #commit commit} to fix changes and make them visible to owners * of other DataBaskets. Once commited, a change can no longer be rolled back. * </p> * * <p>Additionally, you can define subsections in a DataBasket, which can be * commited or rolled back individually and independently. Also you can commit * or rollback an arbitrary subset of elements by defining a selecting * condition. These operations are, however, optional, and may not be * implemented in all concrete implementations of the DataBasket interface.</p> * * <p>In addition to their useability as "transaction handles", * DataBaskets can be inspected, thus allowing for applications where customer's * can roam the Shop freely, deciding to take things and to put them back, and * will only be charged at the end, based on the contents of their DataBasket. * To implement such strategies, see {@link #iterator}, {@link #sumBasket}.</p> * * <p>DataBaskets allow for a {@link LogContext} to be defined. Operations on * the DataBasket can be logged using the current LogContext of the DataBasket. * You can decide which actions are being logged by setting the appropriate * parameter in a call to {@link #setLogMode}.</p> * * @author Steffen Zschaler * @version 2.0 10/06/1999 * @since v2.0 */ public interface DataBasket extends Serializable { /** * Commit the entire contents of the DataBasket. * * <p>All temporarily added or removed items will be finally added or removed from their * respective containers. All items got for editing will be put back into their container * and any changes to them will be fixed. All items that have only been visible to users * of this DataBasket will henceforward be visible for every user. Every item that was * committed will be removed from the DataBasket and, thus, the DataBasket will be empty. * </p> * * @see #rollback * * @override Always */ public void commit(); /** * Roll back the entire contents of the DataBasket. * * <p>All temporarily added or removed items will be removed from, or put back into, * their respective containers, resp. All changes that where made to items that were * edited will be undone. All items will be restored to their original visibility. * Every item that was rolled back will be removed from the DataBasket and, thus, the * DataBasket will be empty.</p> * * @see #commit * * @override Always */ public void rollback(); /** * Commit the contents of the named subbasket. * * <p>All items in the named subbasket will be commited, and the subbasket will be empty * afterwards. Any item that is not in the subbasket will not be touched, unless * dependencies between the items require so. For a description of the commit process * refer to {@link #commit()}.</p> * * <p>This is an optional operation that need not be supported by concrete * implementations of the interface. To indicate that this method is not supported, such * implementations must throw a UnSupportedOperationException.</p> * * @param sName the name of the subbasket to be commited. * * @exception UnsupportedOperationException to indicate that this method is not * implemented in a certain implementation of the interface. * * @see #setCurrentSubBasket * @see #rollbackSubBasket * * @override Always */ public void commitSubBasket (String sName); /** * Commit the contents of the current subbasket. * * <p>All items in the current subbasket will be commited, and the subbasket will be empty * afterwards. Any item that is not in the subbasket will not be touched, unless * dependencies between the items require so. For a description of the commit process * refer to {@link #commit()}.</p> * * <p>This is an optional operation that need not be supported by concrete * implementations of the interface. To indicate that this method is not supported, such * implementations must throw a UnSupportedOperationException.</p> * * @exception UnsupportedOperationException to indicate that this method is not * implemented in a certain implementation of the interface. * * @see #setCurrentSubBasket * @see #rollbackCurrentSubBasket * * @override Always */ public void commitCurrentSubBasket(); /** * Roll back the contents of the named subbasket. * * <p>All items in the named subbasket will be rolled back, and the subbasket will be * empty afterwards. Any item that is not in the subbasket will not be touched, unless * dependencies between the items require so. For a description of the rollback process * refer to {@link #rollback()}.</p> * * <p>This is an optional operation that need not be supported by concrete * implementations of the interface. To indicate that this method is not supported, such * implementations must throw a UnSupportedOperationException.</p> * * @param sName the name of the subbasket to be rolled back. * * @exception UnsupportedOperationException to indicate that this method is not * implemented in a certain implementation of the interface. * * @see #setCurrentSubBasket * @see #commitSubBasket * * @override Always */ public void rollbackSubBasket (String sName); /** * Roll back the contents of the current subbasket. * * <p>All items in the current subbasket will be rolled back, and the subbasket will be * empty afterwards. Any item that is not in the subbasket will not be touched, unless * dependencies between the items require so. For a description of the rollback process * refer to {@link #rollback()}.</p> * * <p>This is an optional operation that need not be supported by concrete * implementations of the interface. To indicate that this method is not supported, such * implementations must throw a UnSupportedOperationException.</p> * * @exception UnsupportedOperationException to indicate that this method is not * implemented in a certain implementation of the interface. * * @see #setCurrentSubBasket * @see #commitCurrentSubBasket * * @override Always */ public void rollbackCurrentSubBasket(); /** * Commit all items that match the given condition. * * <p>All items matching the condition will be commited and removed from the DataBasket. * No other item will be touched, unless dependencies between the items require so. For a * description of the commit process refer to {@link #commit()}.</p> * * <p>This is an optional operation that need not be supported by concrete * implementations of the interface. To indicate that this method is not supported, such * implementations must throw a UnSupportedOperationException.</p> * * @exception UnsupportedOperationException to indicate that this method is not * implemented in a certain implementation of the interface. * * @override Always */ public void commit (DataBasketCondition dbc); /** * Roll back all items that match the given condition. * * <p>All items matching the condition will be rolled back and removed from the * DataBasket. No other item will be touched, unless dependencies between the items * require so. For a description of the rollback process refer to {@link #rollback()}. * </p> * * <p>This is an optional operation that need not be supported by concrete * implementations of the interface. To indicate that this method is not supported, such * implementations must throw a UnSupportedOperationException.</p> * * @exception UnsupportedOperationException to indicate that this method is not * implemented in a certain implementation of the interface. * * @override Always */ public void rollback (DataBasketCondition dbc); /** * Set the current subbasket. * * <p>If no SubBasket of the given name exists, an empty one will be created and made * the current SubBasket.</p> * * <p>All {@link #put put} operations put entries into the current subbasket of a * DataBasket.</p> * * <p>SubBaskets can be used to define sets of independently commitable (or rollbackable, * resp.) entries in a DataBasket. Thus you can build something similar to nested * Transactions or SafePoints. However, when using SubBaskets, it is at least partly * your responsibility to make sure, there are no dependencies between the contents of * different SubBaskets. If you don't, or if you do not take measures to resolve such * situations, using SubBaskets may result in inconsistent data in your system.</p> * * <p>This is an optional operation that need not be supported by concrete * implementations of the interface. To indicate that this method is not supported, such * implementations must throw a UnSupportedOperationException. Implementations may also * choose to implement this method (and any other methods related to SubBaskets) in part, * i.e. with more rigid preconditions defined. Such implementations would still throw an * UnsupportedOperationException if the preconditions are not met. For example, an * implementation based on relational databases might want to allow LIFO usage of * SubBaskets as this can be modelled by nesting database transactions. It will throw an * exception, however, when a client tries to use SubBaskets in a more random way.</p> * * @exception UnsupportedOperationException to indicate that this method is not * implemented in a certain implementation of the interface. * * @see #commitSubBasket * @see #rollbackSubBasket * @see #commitCurrentSubBasket * @see #rollbackCurrentSubBasket * @see #DEFAULTSUBBASKET_NAME * * @override Always */ public void setCurrentSubBasket (String sName); /** * The name of the default subbasket. * * <p>Every DataBasket has at least one SubBasket, that is used as long as no other * SubBasket has been specified. This is the default subbasket and its name is stored * in this constant.</p> * * @see #setCurrentSubBasket */ public static final String DEFAULTSUBBASKET_NAME = "__TAG:_DEFAULT_SUBBASKET"; /** * Iterate the contents of this DataBasket. * * <p>The iterator will iterate the entire contents of the DataBasket, but will return * only such items, that match the given condition.</p> * * @param dbc a condition, that items must match to be returned by the iterator. * * @override Always */ public Iterator iterator (DataBasketCondition dbc); /** * Iterate the contents of a given SubBasket. * * <p>The iterator will iterate all items in the given SubBasket that match the given * condition.</p> * * @param sName the name of the SubBasket. A {@link NullPointerException} may * be thrown if this SubBasket does not exist. * @param dbc the condition that must be matched by items that are to be returned by the * iterator * * @override Always */ public Iterator subBasketIterator (String sName, DataBasketCondition dbc); /** * Sum up the values of all items in this DataBasket that match the condition. * * @param dbc the condition that must be matched by all entries that are to be used in the * process of adding up the DataBasket. * @param bev an object helping in determining the value of a single entry. * @param vInit the value that is to be used for adding up. All adding is performed by calling * {@link Value#addAccumulating} on this object. * * @return the sum in <code>vInit</code>. * * @override Always */ public Value sumBasket (DataBasketCondition dbc, BasketEntryValue bev, Value vInit); /** * Sum up the values of all items in the given subbasket that match the condition. * * @param sName the name of the subbasket whose items are to be used. * @param dbc the condition that must be matched by all entries that are to be used in the * process of adding up the DataBasket. * @param bev an object helping in determining the value of a single entry. * @param vInit the value that is to be used for adding up. All adding is performed by calling * {@link Value#addAccumulating} on this object. * * @return the sum in <code>vInit</code>. * * @override Always */ public Value sumSubBasket (String sName, DataBasketCondition dbc, BasketEntryValue bev, Value vInit); /** * Sum up the values of all items in the current subbasket that match the condition. * * @param dbc the condition that must be matched by all entries that are to be used in the * process of adding up the DataBasket. * @param bev an object helping in determining the value of a single entry. * @param vInit the value that is to be used for adding up. All adding is performed by calling * {@link Value#addAccumulating} on this object. * * @return the sum in <code>vInit</code>. * * @override Always */ public Value sumCurrentSubBasket (DataBasketCondition dbc, BasketEntryValue bev, Value vInit); /** * Return true if the DataBasket contains an entry that matches the condition. The entire * DataBasket will be searched. * * @param dbc the condition to be matched. * * @return whether or not the DataBasket currently contains such an entry. * * @override Always */ public boolean contains (DataBasketCondition dbc); /** * Get the first entry found that matches the given condition. The entire DataBasket will * be searched. * * <p>In this context, "first" does not mean the first entry added or anything * similar; it simply refers to the first entry found when searching the DataBasket. * Although this may be the first entry added, no assertions are given.</p> * * @param dbc the condition to be matched. * * @return an entry matching the condition, if any. * * @override Always */ public DataBasketEntry get (DataBasketCondition dbc); /** * Put an entry into the DataBasket's current subbasket. * * <p>This method is vital for the correct functioning of the DataBasket and, therefore, * must never be called directly. Instead, call appropriate methods in the data containers * ({@link Stock}, {@link Catalog}, etc.) you use. These will in turn call put * on the DataBasket, thus making sure, that the DataBasket contains valid information only * at all times.</p> * * <p>The <code>put</code> method will take the given entry as is and put it into the * current subbasket. This is to say, that the caller is responsible for correctly setting * up the fields in the entry - so that the information stored is meaningful to the client. * In particular, resolving put after remove or remove after put of the same object and * with regard to the same container is the responsibility of the caller.</p> * * @param dbe the entry to be put into the DataBasket. * * @override Always */ public void put (DataBasketEntry dbe); /** * Exchange a DataBasketEntry existing in the DataBasket with a new one. * * <p>This method is vital for the correct functioning of the DataBasket and, therefore, * must never be called directly. Instead, call appropriate methods in the data containers * ({@link Stock}, {@link Catalog}, etc.) you use. These will in turn call * exchange on the DataBasket, thus making sure, that the DataBasket contains valid * information only at all times.</p> * * @param dbeOrg the original DataBasketEntry, to be replaced. If the original entry is * not found in the DataBasket, <code>exchange()</code> is equivalent to * {@link #put put (dbeNew)}. * @param dbeNew the replacement. * * @override Always */ public void exchange (DataBasketEntry dbeOrg, DataBasketEntry dbeNew); /** * Set the log context for this DataBasket. * * <p>All operations as defined through {@link #setLogMode} will be logged using the given log context. If * the current log context is <code>null</code> no logging of any kind will occur.</p> * * @param lcNew the new log context * * @return the previous log context, if any. * * @override Always */ public LogContext setLogContext (LogContext lcNew); /** * Set the log mode for this DataBasket. * * <p>The current log mode decides what operations on the DataBasket are being logged. The default value is * {@link #LOG_MODE_NONE}, indicating that no logging occurs. Other possibilities are:</p> * * <ul> * <li><strong>{@link #LOG_MODE_ALL}</strong> All operations on the DataBasket are being logged.</li> * <li><strong>{@link #LOG_MODE_COMMITS_ONLY}</strong> Only commits are being logged. There will be one * entry for each single step in the commit process.</li> * <li><strong>{@link #LOG_MODE_ROLLBACKS_ONLY}</strong> Only rollbacks are being logged. There will be * one entry for each single step in the rollback process.</li> * </ul> * * <p>For details on the concrete implementation for log entries, please refer to the concrete * implementation of the DataBasket.</p> * * @param nLogMode the new log mode. * * @return the previous log mode. * * @override Always */ public int setLogMode (int nLogMode); /** * Return the current log mode of the DataBasket. For information on the possible values and their meaning, * please refer to {@link #setLogMode}. * * @override Always */ public int getLogMode(); /** * Log mode constant. * * @see #setLogMode * @see #getLogMode */ public static final int LOG_MODE_NONE = 0; /** * Log mode constant. * * @see #setLogMode * @see #getLogMode */ public static final int LOG_MODE_ALL = 1; /** * Log mode constant. * * @see #setLogMode * @see #getLogMode */ public static final int LOG_MODE_COMMITS_ONLY = 2; /** * Log mode constant. * * @see #setLogMode * @see #getLogMode */ public static final int LOG_MODE_ROLLBACKS_ONLY = 4; }