package data;

import java.util.*;

import data.events.VetoException;

/**
  * A Catalog.
  *
  * <p>Catalogs are - usually system global - lists of items. Each Catalog has a name unique to its scope of
  * usage. It is identified by this name. Catalogs consist of {@link CatalogItem CatalogItems}, which comprise
  * a key ({@link String}), possibly a value ({@link Value}) and any number of additional attributes as needed
  * to correctly describe the item.</p>
  *
  * <p>A Catalog is capable to test whether it contains CatalogItems with a certain key or matching a given
  * CatalogItem. It will make available for editing the CatalogItem of a given key, if this key is contained
  * in the Catalog.</p>
  *
  * <p>Catalogs support the usage of {@link DataBasket DataBaskets} so that all operations on the Catalog can
  * be performed in a transactional style.</p>
  *
  * <p>As a Catalog is itself a CatalogItem, constructing arbitrarily nested Catalogs is possible.</p>
  *
  * <p>A Catalog is serializable to allow for it to be stored to an ObjectOutputStream.</p>
  *
  * @see Stock
  *
  * @author Steffen Zschaler
  * @version 2.0 18/08/1999
  * @since v0.5
  */
public interface Catalog extends CatalogItem, DataBasketEntrySource, DataBasketEntryDestination {

  /**
    * Add a CatalogItem to the Catalog.
    *
    * <p>The added item will only be visible to users of the same DataBasket. Only after a
    * {@link DataBasket#commit() commit()} was executed on the DataBasket, the added item will become visible
    * to other users of the Catalog.</p>
    *
    * <p>For a {@link ListenableCatalog}, a <code>addedCatalogItem</code> event will be fired.</p>
    *
    * @override Always
    *
    * @param ci the CatalogItem to be added. This item must not be contained in another Catalog.
    * @param db the DataBasket relative to which the operation is to be performed.
    *
    * @exception NotEditableException if the Catalog is currently not editable.
    * @exception DuplicateKeyException if a CatalogItem of the same name does already exist in the Catalog.
    * @exception DataBasketConflictException if the CatalogItem cannot be added because an item of the same
    * name has already been added/removed using another DataBasket.
    */
  public void add (CatalogItem ci, DataBasket db);

  /**
    * Remove a CatalogItem from the Catalog.
    *
    * <p>The item's removal will be immediately visible to all users of the Catalog. However, only users of the
    * same DataBasket that was used to remove the item will be able to add an item with the same key later.
    * Only after a {@link DataBasket#commit() commit()} was executed on the DataBasket, other users of the
    * Catalog will have a chance to add an item with the same key.</p>
    *
    * <p>For a {@link ListenableCatalog}, <code>canRemoveCatalogItem</code> and
    * <code>removedCatalogItem</code> events will be fired. If one of the listeners vetos the removal, a
    * {@link data.events.VetoException} will be thrown.</p>
    *
    * @override Always
    *
    * @param ci the CatalogItem to be removed.
    * @param db the DataBasket relative to which the operation is to be performed.
    *
    * @return the item that was actually removed.
    *
    * @exception NotEditableException if the Catalog is currently not editable.
    * @exception VetoException if one of the listeners vetos the removal.
    * @exception DataBasketConflictException if the CatalogItem cannot be removed because an item of the same
    * name has already been added using another DataBasket.
    */
  public CatalogItem remove (CatalogItem ci, DataBasket db)
    throws VetoException;

  /**
    * Remove a CatalogItem from the Catalog.
    *
    * <p>The item's removal will be immediately visible to all users of the Catalog. However, only users of the
    * same DataBasket that was used to remove the item will be able to add an item with the same key later.
    * Only after a {@link DataBasket#commit() commit()} was executed on the DataBasket, other users of the
    * Catalog will have a chance to add an item with the same key.</p>
    *
    * <p>For a {@link ListenableCatalog}, <code>canRemoveCatalogItem</code> and
    * <code>removedCatalogItem</code> events will be fired. If one of the listeners vetos the removal, a
    * {@link data.events.VetoException} will be thrown.</p>
    *
    * @override Always
    *
    * @param sKey the key of the CatalogItem to be removed.
    * @param db the DataBasket relative to which the operation is to be performed.
    *
    * @return the item that was actually removed.
    *
    * @exception NotEditableException if the Catalog is currently not editable.
    * @exception VetoException if one of the listeners vetos the removal.
    * @exception DataBasketConflictException if the CatalogItem cannot be removed because an item of the same
    * name has already been added using another DataBasket.
    */
  public CatalogItem remove (String sKey, DataBasket db)
    throws VetoException;

  /**
    * Get a CatalogItem by its key.
    *
    * <p>There are two distinct possibilities when getting a CatalogItem from a Catalog:</p>
    *
    * <ol>
    *   <li><b>Just for looking at it</b> <i>(<code>fForEdit</code> == false)</i>:<br>
    *       In this case the original item is delivered if it is visible for users of the given DataBasket.
    *       However, no guarantee is given that the item will still be in the Catalog the next time you look.
    *       Also, editing the retrieved item is illegal and may result in corrupted data.
    *   </li>
    *   <li><b>For editing</b> <i>(<code>fForEdit</code> == true)</i>:<br>
    *       In this case, the item is specially prepared for editing before delivering it. The item will no
    *       longer be visible to users of other DataBaskets until a {@link DataBasket#commit()} is performed
    *       on the DataBasket. It is legal to edit the retrieved item (however, not necessarily the same item
    *       that was retrieved earlier using possibility 1 !!!), and all editing can be commited or rolled back
    *       using the DataBasket. This possibility can, however, be vetoed if this is a
    *       {@link ListenableCatalog}.<br><br>
    *       For a {@link ListenableCatalog}, <code>canEditCatalogItem</code> and
    *       <code>editingCatalogItem</code> events will be fired. If one of the listeners vetos the editing, a
    *       {@link data.events.VetoException} will be thrown.
    *   </li>
    * </ol>
    *
    * <p>&nbsp;</p>
    *
    * @override Always
    *
    * @param sKey the key of the CatalogItem to be retrieved.
    * @param db the DataBasket relative to which the operation is to be performed.
    * @param fForEdit if true, the CatalogItem will be retrieved for editing.
    *
    * @return the item that is associated with the given key.
    *
    * @exception NotEditableException if the Catalog is not currently editable, but an attempt is made to edit
    * one of its items.
    * @exception VetoException if one of the listeners vetos the editing.
    * @exception DataBasketConflictException if the CatalogItem cannot be retrieved because it is not visible
    * to users of the given DataBasket.
    */
  public CatalogItem get (String sKey, DataBasket db, boolean fForEdit)
    throws VetoException;

  /**
    * Check whether the Catalog contains a certain CatalogItem.
    *
    * <p>Will return true only if an item of the given key is contained in the Catalog and if that item is
    * visible to users of the given DataBasket.</p>
    *
    * @override Always
    *
    * @param sKey the key for which to check containment.
    * @param db the DataBasket that defines visibility of items. See {@link #add} and {@link #remove} for
    * details on visibility.
    */
  public boolean contains (String sKey, DataBasket db);

  /**
    * Return an iterator of all items in the Catalog.
    *
    * <p>The iterator will conceptually call {@link #get} for each CatalogItem, using the given parameters.
    *
    * @override Always
    *
    * @param db the DataBasket that defines visibility.
    * @param fForEdit if true, the items are retrieved for editing. VetoException will be converted into
    * <code>UnsupportedOperationException</code>s.
    */
  public Iterator iterator (DataBasket db, boolean fForEdit);

  /**
    * Get a set of all keys currently in the Catalog.
    *
    * <p>This will retrieve a static set that gives the state of the Catalog at the time of the call.</p>
    *
    * @param db the DataBasket used to determine visibility of elements.
    *
    * @override Always
    */
  public Set keySet (DataBasket db);

  /**
    * Calculate the size of the Catalog. I.e. count the CatalogItems that are visible to users of the given DataBasket.
    *
    * @override Always
    *
    * @param db the DataBasket used to determine visibility.
    */
  public int size (DataBasket db);
}