001: /* *************************************************************************
002:
003: Millstone(TM)
004: Open Sourced User Interface Library for
005: Internet Development with Java
006:
007: Millstone is a registered trademark of IT Mill Ltd
008: Copyright (C) 2000-2005 IT Mill Ltd
009:
010: *************************************************************************
011:
012: This library is free software; you can redistribute it and/or
013: modify it under the terms of the GNU Lesser General Public
014: license version 2.1 as published by the Free Software Foundation.
015:
016: This library is distributed in the hope that it will be useful,
017: but WITHOUT ANY WARRANTY; without even the implied warranty of
018: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
019: Lesser General Public License for more details.
020:
021: You should have received a copy of the GNU Lesser General Public
022: License along with this library; if not, write to the Free Software
023: Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
024:
025: *************************************************************************
026:
027: For more information, contact:
028:
029: IT Mill Ltd phone: +358 2 4802 7180
030: Ruukinkatu 2-4 fax: +358 2 4802 7181
031: 20540, Turku email: info@itmill.com
032: Finland company www: www.itmill.com
033:
034: Primary source for MillStone information and releases: www.millstone.org
035:
036: ********************************************************************** */
037:
038: package org.millstone.base.data;
039:
040: import java.util.Collection;
041:
042: /**
043: * <p>
044: * A specialized set of identified Items. Basically the Container is a set of
045: * Items, but it imposes certain constraints on its contents. These constraints
046: * state the following:
047: * </p>
048: *
049: * <ul>
050: * <li>All Items in the Container must include the same number of Properties
051: * <li>All Items in the Container must include the same Property ID sets (see
052: * {@link Item#getItemPropertyIds()}).
053: * <li>all Properties in the Items corresponding to the same Property ID must
054: * have the same data type.
055: * </ul>
056: *
057: * <p>
058: * The Container can be visualized as a representation of a relational database
059: * table. Each Item in the Container represents a row in the table, and all
060: * cells in a column (identified by a Property ID) have the same data type. Note
061: * that as with the cells in a database table, no Property in a Container may be
062: * empty, though they may contain <code>null</code> values.
063: * </p>
064: *
065: * <p>
066: * Note that though uniquely identified, the Items in a Container are not
067: * neccessarily {@link Container.Ordered ordered}or
068: * {@link Container.Indexed indexed}.
069: * </p>
070: *
071: * <p>
072: * <img src=doc-files/Container_full.gif>
073: * </p>
074: *
075: * <p>
076: * The Container interface is split to several subinterfaces so that a class can
077: * implement only the ones it needs.
078: * </p>
079: *
080: * @author IT Mill Ltd
081: * @version 3.1.1 @since 3.0
082: */
083: public interface Container {
084:
085: public final static Object NULL_ITEM_ID = new Object();
086:
087: /**
088: * Gets the Item with the given Item ID from the Container. If the Container
089: * does not contain the requested Item, <code>null</code> is returned.
090: *
091: * @param itemId
092: * ID of the Item to retrieve
093: * @return the Item with the given ID or <code>null</code> if the Item is
094: * not found in the Container
095: */
096: public Item getItem(Object itemId);
097:
098: /**
099: * Gets the ID's of all Properties stored in the Container. The ID's are
100: * returned as a unmodifiable collection.
101: *
102: * @return unmodifiable collection of Property IDs
103: */
104: public Collection getContainerPropertyIds();
105:
106: /**
107: * Gets the ID's of all Items stored in the Container. The ID's are returned
108: * as a unmodifiable collection.
109: *
110: * @return unmodifiable collection of Item IDs
111: */
112: public Collection getItemIds();
113:
114: /**
115: * Gets the Property identified by the given itemId and propertyId from the
116: * Container. If the Container does not contain the Property,
117: * <code>null</code> is returned.
118: *
119: * @param itemId
120: * ID of the Item which contains the Property
121: * @param propertyId
122: * ID of the Property to retrieve
123: * @return Property with the given ID or <code>null</code>
124: */
125: public Property getContainerProperty(Object itemId,
126: Object propertyId);
127:
128: /**
129: * Gets the data type of all Properties identified by the given Property ID.
130: *
131: * @param propertyId
132: * ID identifying the Properties
133: * @return data type of the Properties
134: */
135: public Class getType(Object propertyId);
136:
137: /**
138: * Gets the number of Items in the Container.
139: *
140: * @return number of Items in the Container
141: */
142: public int size();
143:
144: /**
145: * Tests if the Container contains the specified Item
146: *
147: * @param itemId
148: * ID the of Item to be tested
149: * @return boolean indicating if the Container holds the specified Item
150: */
151: public boolean containsId(Object itemId);
152:
153: /**
154: * Creates a new Item with the given ID into the Container. The new
155: * <p>
156: * Item is returned, and it is ready to have its Properties modified.
157: * Returns <code>null</code> if the operation fails or the Container
158: * already contains a Item with the given ID.
159: * </p>
160: *
161: * <p>
162: * This functionality is optional.
163: * </p>
164: *
165: * @param itemId
166: * ID of the Item to be created
167: * @return Created new Item, or <code>null</code> in case of a failure
168: */
169: public Item addItem(Object itemId)
170: throws UnsupportedOperationException;
171:
172: /**
173: * Creates a new Item into the Container, and assign it an automatic ID.
174: *
175: * <p>
176: * The new ID is returned, or <code>null</code> if the operation fails.
177: * After a successful call you can use the
178: * {@link #getItem(Object ItemId) <code>getItem</code>}method to fetch the
179: * Item.
180: * </p>
181: *
182: * <p>
183: * This functionality is optional.
184: * </p>
185: *
186: * @return ID of the newly created Item, or <code>null</code> in case of a
187: * failure
188: */
189: public Object addItem() throws UnsupportedOperationException;
190:
191: /**
192: * Removes the Item identified by <code>ItemId</code> from the Container.
193: * This functionality is optional.
194: *
195: * @param itemId
196: * ID of the Item to remove
197: * @return <code>true</code> if the operation succeeded,
198: * <code>false</code> if not
199: */
200: public boolean removeItem(Object itemId)
201: throws UnsupportedOperationException;
202:
203: /**
204: * Adds a new Property to all Items in the Container. The Property ID, data
205: * type and default value of the new Property are given as parameters.
206: *
207: * This functionality is optional.
208: *
209: * @param propertyId
210: * ID of the Property
211: * @param type
212: * Data type of the new Property
213: * @param defaultValue
214: * The value all created Properties are initialized to
215: * @return <code>true</code> if the operation succeeded,
216: * <code>false</code> if not
217: */
218: public boolean addContainerProperty(Object propertyId, Class type,
219: Object defaultValue) throws UnsupportedOperationException;
220:
221: /**
222: * Removes a Property specified by the given Property ID from the Container.
223: * Note that the Property will be removed from all Items in the Container.
224: *
225: * This functionality is optional.
226: *
227: * @param propertyId
228: * ID of the Property to remove
229: * @return <code>true</code> if the operation succeeded,
230: * <code>false</code> if not
231: */
232: public boolean removeContainerProperty(Object propertyId)
233: throws UnsupportedOperationException;
234:
235: /**
236: * Removes all Items from the Container.
237: *
238: * <p>
239: * Note that Property ID and type information is preserved. This
240: * functionality is optional.
241: * </p>
242: *
243: * @return <code>true</code> if the operation succeeded,
244: * <code>false</code> if not
245: */
246: public boolean removeAllItems()
247: throws UnsupportedOperationException;
248:
249: /**
250: * Interface for Container classes whose Items can be traversed in order.
251: */
252: public interface Ordered extends Container {
253:
254: /**
255: * Gets the ID of the Item following the Item that corresponds to
256: * <code>itemId</code>. If the given Item is the last or not found in
257: * the Container, <code>null</code> is returned.
258: *
259: * @param itemId
260: * ID of an Item in the Container
261: * @return ID of the next Item or <code>null</code>
262: */
263: public Object nextItemId(Object itemId);
264:
265: /**
266: * Gets the ID of the Item preceding the Item that corresponds to
267: * <code>itemId</code>. If the given Item is the first or not found
268: * in the Container, <code>null</code> is returned.
269: *
270: * @param itemId
271: * ID of an Item in the Container
272: * @return ID of the previous Item or <code>null</code>
273: */
274: public Object prevItemId(Object itemId);
275:
276: /**
277: * Gets the ID of the first Item in the Container.
278: *
279: * @return ID of the first Item in the Container
280: */
281: public Object firstItemId();
282:
283: /**
284: * Gets the ID of the last Item in the Container..
285: *
286: * @return ID of the last Item in the Container
287: */
288: public Object lastItemId();
289:
290: /**
291: * Tests if the Item corresponding to the given Item ID is the first
292: * Item in the Container.
293: *
294: * @param itemId
295: * ID of an Item in the Container
296: * @return <code>true</code> if the Item is first in the Container,
297: * <code>false</code> if not
298: */
299: public boolean isFirstId(Object itemId);
300:
301: /**
302: * Tests if the Item corresponding to the given Item ID is the last Item
303: * in the Container.
304: *
305: * @return <code>true</code> if the Item is last in the Container,
306: * <code>false</code> if not
307: */
308: public boolean isLastId(Object itemId);
309:
310: /**
311: * Add new item after the given item.
312: * <p>
313: * Adding an item after null item adds the item as first item of the
314: * ordered container.
315: * </p>
316: *
317: * @param previousItemId
318: * Id of the previous item in ordered container.
319: * @return Returns item id the the created new item or null if the
320: * operation fails.
321: */
322: public Object addItemAfter(Object previousItemId)
323: throws UnsupportedOperationException;
324:
325: /**
326: * Add new item after the given item.
327: * <p>
328: * Adding an item after null item adds the item as first item of the
329: * ordered container.
330: * </p>
331: *
332: * @param previousItemId
333: * Id of the previous item in ordered container.
334: * @param newItemId
335: * Id of the new item to be added.
336: * @return Returns new item or null if the operation fails.
337: */
338: public Item addItemAfter(Object previousItemId, Object newItemId)
339: throws UnsupportedOperationException;
340:
341: }
342:
343: /** Interface for Container classes whose Items can be sorted. */
344: public interface Sortable extends Ordered {
345:
346: /**
347: * Sort method.
348: *
349: * Sort the container items.
350: *
351: * @param propertyId
352: * Array of container property IDs, which values are used to
353: * sort the items in container as primary, secondary, ...
354: * sorting criterion. All of the item IDs must be in the
355: * collection returned by <code>getSortableContainerPropertyIds()</code>
356: * @param ascending
357: * Array of sorting order flags corresponding to each property ID
358: * used in sorting. If this array is shorter than propertyId array,
359: * ascending order is assumed for items where the order is not
360: * specified.
361: * Use <code>true</code> to sort in ascending order,
362: * <code>false</code> to use descending order.
363: */
364: void sort(Object[] propertyId, boolean[] ascending);
365:
366: /**
367: * Get the container property IDs, which can be used to sort the item.
368: *
369: * @return The sortable field ids.
370: */
371: Collection getSortableContainerPropertyIds();
372:
373: }
374:
375: /** Interface for Container classes whose Items can be indexed. */
376: public interface Indexed extends Ordered {
377:
378: /**
379: * Gets the index of the Item corresponding to <code>itemId</code>.
380: * The following is true for the returned index: 0 <= index < size().
381: *
382: * @param itemId
383: * ID of an Item in the Container
384: * @return index of the Item, or -1 if the Container does not include
385: * the Item
386: */
387: public int indexOfId(Object itemId);
388:
389: /**
390: * Get the ID of an Item by an index number. The following is true for
391: * the index: 0 <= index < size().
392: *
393: * @param index
394: * Index of the requested id in the Container
395: * @return ID of the Item in the given index
396: */
397: public Object getIdByIndex(int index);
398:
399: /**
400: * Add new item at given index.
401: * <p>
402: * The indexes of the item currently in the given position and all the
403: * following items are incremented.
404: * </p>
405: *
406: * @param index
407: * Index to add the new item.
408: * @return Returns item id the the created new item or null if the
409: * operation fails.
410: */
411: public Object addItemAt(int index)
412: throws UnsupportedOperationException;
413:
414: /**
415: * Add new item at given index.
416: * <p>
417: * The indexes of the item currently in the given position and all the
418: * following items are incremented.
419: * </p>
420: *
421: * @param index
422: * Index to add the new item.
423: * @param newItemId
424: * Id of the new item to be added.
425: * @return Returns new item or null if the operation fails.
426: */
427: public Item addItemAt(int index, Object newItemId)
428: throws UnsupportedOperationException;
429:
430: }
431:
432: /**
433: * <p>
434: * Interface for <code>Container</code> classes whose Items can be
435: * arranged hierarchically. This means that the Items in the container
436: * belong in a tree-like structure, with the following quirks:
437: * </p>
438: *
439: * <ul>
440: * <li>The Item structure may have more than one root elements
441: * <li>The Items in the hierarchy can be declared explicitly to be able or
442: * unable to have children.
443: * </ul>
444: */
445: public interface Hierarchical extends Container {
446:
447: /**
448: * Gets the IDs of all Items that are children of the specified Item.
449: * The returned collection is unmodifiable.
450: *
451: * @param itemId
452: * ID of the Item whose children the caller is interested in
453: * @return An unmodifiable {@link java.util.Collection collection}
454: * containing the IDs of all other Items that are children in
455: * the container hierarchy
456: */
457: public Collection getChildren(Object itemId);
458:
459: /**
460: * Gets the ID of the parent Item of the specified Item.
461: *
462: * @param itemId
463: * ID of the Item whose parent the caller wishes to find out.
464: * @return the ID of the parent Item. Will be <code>null</code> if the
465: * specified Item is a root element.
466: */
467: public Object getParent(Object itemId);
468:
469: /**
470: * Gets the IDs of all Items in the container that don't have a parent.
471: * Such items are called <code>root</code> Items. The returned
472: * collection is unmodifiable.
473: *
474: * @return An unmodifiable {@link java.util.Collection collection}
475: * containing IDs of all root elements of the container
476: */
477: public Collection rootItemIds();
478:
479: /**
480: * <p>
481: * Sets the parent of an Item. The new parent item must exist and be
482: * able to have children. (
483: * <code>canHaveChildren(newParentId) == true</code>). It is also
484: * possible to detach a node from the hierarchy (and thus make it root)
485: * by setting the parent <code>null</code>.
486: * </p>
487: *
488: * <p>
489: * This operation is optional.
490: * </p>
491: *
492: * @param itemId
493: * ID of the item to be set as the child of the Item
494: * identified with <code>newParentId</code>
495: * @param newParentId
496: * ID of the Item that's to be the new parent of the Item
497: * identified with <code>itemId</code>
498: * @return <code>true</code> if the operation succeeded,
499: * <code>false</code> if not
500: */
501: public boolean setParent(Object itemId, Object newParentId)
502: throws UnsupportedOperationException;
503:
504: /**
505: * Tests if the Item with given ID can have any children. If the
506: * Container also implements the <code>Managed</code> interface, the
507: * items created with <code>newItem</code> can have children by
508: * default.
509: * </p>
510: *
511: * @param itemId
512: * ID of the Item in the container whose child capability is
513: * to be tested
514: * @return <code>true</code> if the specified Item exists in the
515: * Container and it can have children, <code>false</code> if
516: * it's not found from the container or it can't have children.
517: */
518: public boolean areChildrenAllowed(Object itemId);
519:
520: /**
521: * <p>
522: * Sets the given Item's capability to have children. If the Item
523: * identified with <code>itemId</code> already has children and
524: * <code>areChildrenAllowed</code> is false this method fails and
525: * <code>false</code> is returned; the children must be first
526: * explicitly removed with
527: * {@link #setParent(Object itemId, Object newParentId)}or
528: * {@link org.millstone.base.data.Container#removeItem(Object itemId)}.
529: * </p>
530: *
531: * <p>
532: * This operation is optional. If it is not implemented, the method
533: * always returns <code>false</code>.
534: * </p>
535: *
536: * @param itemId
537: * ID of the Item in the container whose child capability is
538: * to be set
539: * @param areChildrenAllowed
540: * boolean value specifying if the Item can have children or
541: * not
542: * @return <code>true</code> if the operation succeeded,
543: * <code>false</code> if not
544: */
545: public boolean setChildrenAllowed(Object itemId,
546: boolean areChildrenAllowed)
547: throws UnsupportedOperationException;
548:
549: /**
550: * Tests if the Item specified with <code>itemId</code> is a root
551: * Item. The hierarchical container can have more than one root and must
552: * have at least one unless it is empty. The
553: * {@link #getParent(Object itemId)}method always returns
554: * <code>null</code> for root Items.
555: *
556: * @param itemId
557: * ID of the Item whose root status is to be tested
558: * @return <code>true</code> if the specified Item is a root,
559: * <code>false</code> if not
560: */
561: public boolean isRoot(Object itemId);
562:
563: /**
564: * <p>
565: * Tests if the Item specified with <code>itemId</code> has any child
566: * Items, that is, is it a leaf Item. The
567: * {@link #getChildren(Object itemId)}method always returns
568: * <code>null</code> for leaf Items.
569: * </p>
570: *
571: * <p>
572: * Note that being a leaf does not imply whether or not an Item is
573: * allowed to have children.
574: * </p>.
575: *
576: * @param itemId
577: * ID of the Item whose leaf status is to be tested
578: * @return <code>true</code> if the specified Item is a leaf,
579: * <code>false</code> if not
580: */
581: public boolean hasChildren(Object itemId);
582: }
583:
584: /**
585: * Interface implemented by viewer classes capable of using a Container as a
586: * data source.
587: */
588: public interface Viewer {
589:
590: /**
591: * Set the Container that serves as the data source of the viewer.
592: *
593: * @param newDataSource
594: * The new data source Item
595: */
596: public void setContainerDataSource(Container newDataSource);
597:
598: /**
599: * Get the Container serving as the data source of the viewer.
600: *
601: * @return data source Container
602: */
603: public Container getContainerDataSource();
604:
605: }
606:
607: /**
608: * Interface implemented by the editor classes supporting editing the
609: * Container. Implementing this interface means that the Container serving
610: * as the data source of the editor can be modified through it. Note that
611: * not implementing the <code>Container.Editor</code> interface does not
612: * restrict the class from editing the Container contents internally.
613: */
614: public interface Editor extends Container.Viewer {
615:
616: }
617:
618: /* Contents change event ******************************************* */
619:
620: /**
621: * An <code>Event</code> object specifying the Container whose Item set
622: * has changed. Note that these events are triggered only through succesful
623: * calls to the <code>newItem()</code> and <code>removeAllItems</code>
624: * methods in the Container.Managed interface.
625: */
626: public interface ItemSetChangeEvent {
627:
628: /**
629: * Gets the Property where the event occurred.
630: *
631: * @return source of the event
632: */
633: public Container getContainer();
634: }
635:
636: /** Container Item set change listener interface. */
637: public interface ItemSetChangeListener {
638:
639: /**
640: * Lets the listener know a Containers Item set has changed.
641: *
642: * @param event
643: * change event text
644: */
645: public void containerItemSetChange(
646: Container.ItemSetChangeEvent event);
647: }
648:
649: /**
650: * The interface for adding and removing <code>ItemSetChangeEvent</code>
651: * listeners. By implementing this interface a class explicitly announces
652: * that it will generate a <code>ItemSetChangeEvent</code> when its
653: * contents are modified.
654: *
655: * Note that the general Java convention is not to explicitly declare that a
656: * class generates events, but to directly define the
657: * <code>addListener</code> and <code>removeListener</code> methods.
658: * That way the caller of these methods has no real way of finding out if
659: * the class really will send the events, or if it just defines the methods
660: * to be able to implement an interface.
661: */
662: public interface ItemSetChangeNotifier {
663:
664: /**
665: * Adds a Item set change listener for the object.
666: *
667: * @param listener
668: * listener to be added
669: */
670: public void addListener(Container.ItemSetChangeListener listener);
671:
672: /**
673: * Removes a Item set change listener from the object.
674: *
675: * @param listener
676: * listener to be removed
677: */
678: public void removeListener(
679: Container.ItemSetChangeListener listener);
680: }
681:
682: /* Property set change event ******************************************** */
683:
684: /**
685: * An <code>Event</code> object specifying the Container whose Property
686: * set has changed. Note that these events are triggered only through
687: * succesful calls to the <code>addProperty</code> and
688: * <code>removeProperty</code> methods in the Container.Managed interface.
689: */
690: public interface PropertySetChangeEvent {
691:
692: /**
693: * Retrieves the Container whose contents have been modified.
694: *
695: * @return Source Container of the event.
696: */
697: public Container getContainer();
698: }
699:
700: /**
701: * The listener interface for receiving <code>PropertySetChangeEvent</code>
702: * objects.
703: */
704: public interface PropertySetChangeListener {
705:
706: /**
707: * Notifies this listener that the Containers contents has changed.
708: *
709: * @param event
710: * Change event.
711: */
712: public void containerPropertySetChange(
713: Container.PropertySetChangeEvent event);
714: }
715:
716: /**
717: * The interface for adding and removing <code>PropertySetChangeEvent</code>
718: * listeners. By implementing this interface a class explicitly announces
719: * that it will generate a <code>PropertySetChangeEvent</code> when its
720: * contents are modified.
721: *
722: * Note that the general Java convention is not to explicitly declare that a
723: * class generates events, but to directly define the
724: * <code>addListener</code> and <code>removeListener</code> methods.
725: * That way the caller of these methods has no real way of finding out if
726: * the class really will send the events, or if it just defines the methods
727: * to be able to implement an interface.
728: */
729: public interface PropertySetChangeNotifier {
730:
731: /**
732: * Registers a new Property set change listener for this Container.
733: *
734: * @param listener
735: * The new Listener to be registered
736: */
737: public void addListener(
738: Container.PropertySetChangeListener listener);
739:
740: /**
741: * Removes a previously registered Property set change listener.
742: *
743: * @param listener
744: * Listener to be removed
745: */
746: public void removeListener(
747: Container.PropertySetChangeListener listener);
748: }
749: }
|