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 &quot;transcation handle&quot;,
  * 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 &quot;transaction handles&quot;,
  * 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, &quot;first&quot; 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;
}