001    package data;
002    
003    import java.util.Iterator;
004    import java.util.Set;
005    
006    import data.events.VetoException;
007    
008    /**
009     * A Catalog.
010     *
011     * <p>Catalogs are - usually system global - lists of items. Each Catalog has a name unique to its scope of
012     * usage. It is identified by this name. Catalogs consist of {@link CatalogItem CatalogItems}, which comprise
013     * a key ({@link String}), possibly a value ({@link Value}) and any number of additional attributes as needed
014     * to correctly describe the item.</p>
015     *
016     * <p>A Catalog is capable to test whether it contains CatalogItems with a certain key or matching a given
017     * CatalogItem. It will make available for editing the CatalogItem of a given key, if this key is contained
018     * in the Catalog.</p>
019     *
020     * <p>Catalogs support the usage of {@link DataBasket DataBaskets} so that all operations on the Catalog can
021     * be performed in a transactional style.</p>
022     *
023     * <p>As a Catalog is itself a CatalogItem, constructing arbitrarily nested Catalogs is possible.</p>
024     *
025     * <p>A Catalog is serializable to allow for it to be stored to an ObjectOutputStream.</p>
026     *
027     * @see Stock
028     *
029     * @author Steffen Zschaler
030     * @version 2.0 18/08/1999
031     * @since v0.5
032     */
033    public interface Catalog<T extends CatalogItem> extends CatalogItem, DataBasketEntrySource, 
034                                                                         DataBasketEntryDestination {
035    
036        /**
037         * Add a CatalogItem to the Catalog.
038         *
039         * <p>The added item will only be visible to users of the same DataBasket. Only after a
040         * {@link DataBasket#commit() commit()} was executed on the DataBasket, the added item will become visible
041         * to other users of the Catalog.</p>
042         *
043         * <p>For a {@link ListenableCatalog}, a <code>addedCatalogItem</code> event will be fired.</p>
044         *
045         * @override Always
046         *
047         * @param ci the CatalogItem to be added. This item must not be contained in another Catalog.
048         * @param db the DataBasket relative to which the operation is to be performed.
049         *
050         * @exception NotEditableException if the Catalog is currently not editable.
051         * @exception DuplicateKeyException if a CatalogItem of the same name does already exist in the Catalog.
052         * @exception DataBasketConflictException if the CatalogItem cannot be added because an item of the same
053         * name has already been added/removed using another DataBasket.
054         */
055        public void add(T ci, DataBasket db);
056    
057        /**
058         * Remove a CatalogItem from the Catalog.
059         *
060         * <p>The item's removal will be immediately visible to all users of the Catalog. However, only users of the
061         * same DataBasket that was used to remove the item will be able to add an item with the same key later.
062         * Only after a {@link DataBasket#commit() commit()} was executed on the DataBasket, other users of the
063         * Catalog will have a chance to add an item with the same key.</p>
064         *
065         * <p>For a {@link ListenableCatalog}, <code>canRemoveCatalogItem</code> and
066         * <code>removedCatalogItem</code> events will be fired. If one of the listeners vetos the removal, a
067         * {@link data.events.VetoException} will be thrown.</p>
068         *
069         * @override Always
070         *
071         * @param ci the CatalogItem to be removed.
072         * @param db the DataBasket relative to which the operation is to be performed.
073         *
074         * @return the item that was actually removed.
075         *
076         * @exception NotEditableException if the Catalog is currently not editable.
077         * @exception VetoException if one of the listeners vetos the removal.
078         * @exception DataBasketConflictException if the CatalogItem cannot be removed because an item of the same
079         * name has already been added using another DataBasket.
080         */
081        public T remove(T ci, DataBasket db) throws VetoException;
082    
083        /**
084         * Remove a CatalogItem from the Catalog.
085         *
086         * <p>The item's removal will be immediately visible to all users of the Catalog. However, only users of the
087         * same DataBasket that was used to remove the item will be able to add an item with the same key later.
088         * Only after a {@link DataBasket#commit() commit()} was executed on the DataBasket, other users of the
089         * Catalog will have a chance to add an item with the same key.</p>
090         *
091         * <p>For a {@link ListenableCatalog}, <code>canRemoveCatalogItem</code> and
092         * <code>removedCatalogItem</code> events will be fired. If one of the listeners vetos the removal, a
093         * {@link data.events.VetoException} will be thrown.</p>
094         *
095         * @override Always
096         *
097         * @param sKey the key of the CatalogItem to be removed.
098         * @param db the DataBasket relative to which the operation is to be performed.
099         *
100         * @return the item that was actually removed.
101         *
102         * @exception NotEditableException if the Catalog is currently not editable.
103         * @exception VetoException if one of the listeners vetos the removal.
104         * @exception DataBasketConflictException if the CatalogItem cannot be removed because an item of the same
105         * name has already been added using another DataBasket.
106         */
107        public T remove(String sKey, DataBasket db) throws VetoException;
108    
109        /**
110         * Get a CatalogItem by its key.
111         *
112         * <p>There are two distinct possibilities when getting a CatalogItem from a Catalog:</p>
113         *
114         * <ol>
115         *   <li><b>Just for looking at it</b> <i>(<code>fForEdit</code> == false)</i>:<br>
116         *       In this case the original item is delivered if it is visible for users of the given DataBasket.
117         *       However, no guarantee is given that the item will still be in the Catalog the next time you look.
118         *       Also, editing the retrieved item is illegal and may result in corrupted data.
119         *   </li>
120         *   <li><b>For editing</b> <i>(<code>fForEdit</code> == true)</i>:<br>
121         *       In this case, the item is specially prepared for editing before delivering it. The item will no
122         *       longer be visible to users of other DataBaskets until a {@link DataBasket#commit()} is performed
123         *       on the DataBasket. It is legal to edit the retrieved item (however, not necessarily the same item
124         *       that was retrieved earlier using possibility 1 !!!), and all editing can be commited or rolled back
125         *       using the DataBasket. This possibility can, however, be vetoed if this is a
126         *       {@link ListenableCatalog}.<br><br>
127         *       For a {@link ListenableCatalog}, <code>canEditCatalogItem</code> and
128         *       <code>editingCatalogItem</code> events will be fired. If one of the listeners vetos the editing, a
129         *       {@link data.events.VetoException} will be thrown.
130         *   </li>
131         * </ol>
132         *
133         * <p>&nbsp;</p>
134         *
135         * @override Always
136         *
137         * @param sKey the key of the CatalogItem to be retrieved.
138         * @param db the DataBasket relative to which the operation is to be performed.
139         * @param fForEdit if true, the CatalogItem will be retrieved for editing.
140         *
141         * @return the item that is associated with the given key.
142         *
143         * @exception NotEditableException if the Catalog is not currently editable, but an attempt is made to edit
144         * one of its items.
145         * @exception VetoException if one of the listeners vetos the editing.
146         * @exception DataBasketConflictException if the CatalogItem cannot be retrieved because it is not visible
147         * to users of the given DataBasket.
148         */
149        public T get(String sKey, DataBasket db, boolean fForEdit) throws VetoException;
150    
151        /**
152         * Check whether the Catalog contains a certain CatalogItem.
153         *
154         * <p>Will return true only if an item of the given key is contained in the Catalog and if that item is
155         * visible to users of the given DataBasket.</p>
156         *
157         * @override Always
158         *
159         * @param sKey the key for which to check containment.
160         * @param db the DataBasket that defines visibility of items. See {@link #add} and {@link #remove} for
161         * details on visibility.
162         */
163        public boolean contains(String sKey, DataBasket db);
164    
165        /**
166         * Return an iterator of all items in the Catalog.
167         *
168         * <p>The iterator will conceptually call {@link #get} for each CatalogItem, using the given parameters.
169         *
170         * @override Always
171         *
172         * @param db the DataBasket that defines visibility.
173         * @param fForEdit if true, the items are retrieved for editing. VetoException will be converted into
174         * <code>UnsupportedOperationException</code>s.
175         */
176        public Iterator<T> iterator(DataBasket db, boolean fForEdit);
177    
178        /**
179         * Get a set of all keys currently in the Catalog.
180         *
181         * <p>This will retrieve a static set that gives the state of the Catalog at the time of the call.</p>
182         *
183         * @param db the DataBasket used to determine visibility of elements.
184         *
185         * @override Always
186         */
187        public Set<String> keySet(DataBasket db);
188    
189        /**
190         * Calculate the size of the Catalog. I.e. count the CatalogItems that are visible to users of the given DataBasket.
191         *
192         * @override Always
193         *
194         * @param db the DataBasket used to determine visibility.
195         */
196        public int size(DataBasket db);
197    }