Source Code Cross Referenced for IndexedContainer.java in  » Web-Framework » Millstone » org » millstone » base » data » util » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Framework » Millstone » org.millstone.base.data.util 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /* *************************************************************************
0002:         
0003:         Millstone(TM) 
0004:         Open Sourced User Interface Library for
0005:         Internet Development with Java
0006:
0007:         Millstone is a registered trademark of IT Mill Ltd
0008:         Copyright (C) 2000-2005 IT Mill Ltd
0009:         
0010:         *************************************************************************
0011:
0012:         This library is free software; you can redistribute it and/or
0013:         modify it under the terms of the GNU Lesser General Public
0014:         license version 2.1 as published by the Free Software Foundation.
0015:
0016:         This library is distributed in the hope that it will be useful,
0017:         but WITHOUT ANY WARRANTY; without even the implied warranty of
0018:         MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
0019:         Lesser General Public License for more details.
0020:
0021:         You should have received a copy of the GNU Lesser General Public
0022:         License along with this library; if not, write to the Free Software
0023:         Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
0024:
0025:         *************************************************************************
0026:         
0027:         For more information, contact:
0028:         
0029:         IT Mill Ltd                           phone: +358 2 4802 7180
0030:         Ruukinkatu 2-4                        fax:  +358 2 4802 7181
0031:         20540, Turku                          email: info@itmill.com
0032:         Finland                               company www: www.itmill.com
0033:         
0034:         Primary source for MillStone information and releases: www.millstone.org
0035:
0036:         ********************************************************************** */
0037:
0038:        package org.millstone.base.data.util;
0039:
0040:        import java.util.*;
0041:        import java.util.HashSet;
0042:        import java.util.LinkedList;
0043:        import java.util.Iterator;
0044:        import java.util.Hashtable;
0045:        import java.util.Collections;
0046:        import java.util.Collection;
0047:        import java.util.EventObject;
0048:        import java.lang.reflect.Constructor;
0049:        import org.millstone.base.data.Container;
0050:        import org.millstone.base.data.Item;
0051:        import org.millstone.base.data.Property;
0052:
0053:        /**
0054:         * Indexed container implementation.
0055:         * <p>
0056:         * A list implementation of the org.millstone.base.data.Container interface. A
0057:         * list is a ordered collection wherein the user has a precise control over
0058:         * where in the list each new Item is inserted. The user may access the Items by
0059:         * their integer index (position in the list) or by their Item ID.
0060:         * </p>
0061:         * 
0062:         * @see org.millstone.base.data.Container
0063:         * 
0064:         * @author IT Mill Ltd.
0065:         * @version
0066:         * 3.1.1
0067:         * @since 3.0
0068:         */
0069:
0070:        public class IndexedContainer implements  Container, Container.Indexed,
0071:                Container.ItemSetChangeNotifier,
0072:                Container.PropertySetChangeNotifier,
0073:                Property.ValueChangeNotifier, Container.Sortable, Comparator,
0074:                Cloneable {
0075:
0076:            /* Internal structure *************************************************** */
0077:
0078:            /** Linked list of ordered Item IDs */
0079:            private ArrayList itemIds = new ArrayList();
0080:
0081:            /** Linked list of ordered Property IDs */
0082:            private ArrayList propertyIds = new ArrayList();
0083:
0084:            /** Property ID to type mapping */
0085:            private Hashtable types = new Hashtable();
0086:
0087:            /**
0088:             * Hash of Items, where each Item is implemented as a mapping from Property
0089:             * ID to Property value.
0090:             */
0091:            private Hashtable items = new Hashtable();
0092:
0093:            /**
0094:             * Set of properties that are read-only.
0095:             */
0096:            private HashSet readOnlyProperties = new HashSet();
0097:
0098:            /**
0099:             * List of all Property value change event listeners listening all the
0100:             * properties
0101:             */
0102:            private LinkedList propertyValueChangeListeners = null;
0103:
0104:            /**
0105:             * Data structure containing all listeners interested in changes to single
0106:             * Properties. The data structure is a hashtable mapping Property IDs to a
0107:             * hashtable that maps Item IDs to a linked list of listeners listening
0108:             * Property identified by given Property ID and Item ID.
0109:             */
0110:            private Hashtable singlePropertyValueChangeListeners = null;
0111:
0112:            /** List of all Property set change event listeners */
0113:            private LinkedList propertySetChangeListeners = null;
0114:
0115:            /** List of all container Item set change event listeners */
0116:            private LinkedList itemSetChangeListeners = null;
0117:
0118:            /** Temporary store for sorting property ids */
0119:            private Object[] sortPropertyId;
0120:
0121:            /** Temporary store for sorting direction */
0122:            private boolean[] sortDirection;
0123:
0124:            /* Container constructors *********************************************** */
0125:
0126:            public IndexedContainer() {
0127:            }
0128:
0129:            public IndexedContainer(Collection itemIds) {
0130:                if (items != null) {
0131:                    for (Iterator i = itemIds.iterator(); i.hasNext();) {
0132:                        this .addItem(i.next());
0133:                    }
0134:                }
0135:            }
0136:
0137:            /* Container methods **************************************************** */
0138:
0139:            /**
0140:             * Gets the Item with the given Item ID from the list. If the list does not
0141:             * contain the requested Item, <code>null</code> is returned.
0142:             * 
0143:             * @param itemId
0144:             *            ID of the Item to retrieve
0145:             * @return the Item with the given ID or <code>null</code> if the Item is
0146:             *         not found in the list
0147:             */
0148:            public Item getItem(Object itemId) {
0149:                if (items.containsKey(itemId))
0150:                    return new IndexedContainerItem(itemId);
0151:                return null;
0152:            }
0153:
0154:            /**
0155:             * Gets the ID's of all Items stored in the list. The ID's are returned as a
0156:             * unmodifiable collection.
0157:             * 
0158:             * @return unmodifiable collection of Item IDs
0159:             */
0160:            public Collection getItemIds() {
0161:                return Collections.unmodifiableCollection(itemIds);
0162:            }
0163:
0164:            /**
0165:             * Gets the ID's of all Properties stored in the list. The ID's are returned
0166:             * as a unmodifiable collection.
0167:             * 
0168:             * @return unmodifiable collection of Property IDs
0169:             */
0170:            public Collection getContainerPropertyIds() {
0171:                return Collections.unmodifiableCollection(propertyIds);
0172:            }
0173:
0174:            /**
0175:             * Gets the type of a Property stored in the list.
0176:             * 
0177:             * @param id
0178:             *            ID of the Property
0179:             * @return Type of the requested Property
0180:             */
0181:            public Class getType(Object propertyId) {
0182:                return (Class) types.get(propertyId);
0183:            }
0184:
0185:            /**
0186:             * Gets the Property identified by the given Item ID and Property ID from
0187:             * the lsit. If the list does not contain the Property, <code>null</code>
0188:             * is returned.
0189:             * 
0190:             * @param itemId
0191:             *            ID of the Item which contains the requested Property
0192:             * @param propertyId
0193:             *            ID of the Property to retrieve
0194:             * @return Property with the given ID or <code>null</code>
0195:             * 
0196:             * @see org.millstone.base.data.Container#getContainerProperty(Object,
0197:             *      Object)
0198:             */
0199:            public Property getContainerProperty(Object itemId,
0200:                    Object propertyId) {
0201:                if (!items.containsKey(itemId))
0202:                    return null;
0203:                return new IndexedContainerProperty(itemId, propertyId);
0204:            }
0205:
0206:            /**
0207:             * Gets the number of Items in the list.
0208:             * 
0209:             * @return number of Items in the list
0210:             */
0211:            public int size() {
0212:                return itemIds.size();
0213:            }
0214:
0215:            /**
0216:             * Tests if the list contains the specified Item
0217:             * 
0218:             * @param itemId
0219:             *            ID the of Item to be tested for
0220:             * @return <code>true</code> if the operation succeeded,
0221:             *         <code>false</code> if not
0222:             */
0223:            public boolean containsId(Object itemId) {
0224:                return items.containsKey(itemId);
0225:            }
0226:
0227:            /**
0228:             * Add a new Property to all Items in the list. The Property ID, data type
0229:             * and default value of the new Property are given as parameters.
0230:             * 
0231:             * @param propertyId
0232:             *            ID of the new Property
0233:             * @param type
0234:             *            Data type of the new Property
0235:             * @param defaultValue
0236:             *            The value all created Properties are initialized to
0237:             * @return <code>true</code> if the operation succeeded,
0238:             *         <code>false</code> if not
0239:             */
0240:            public boolean addContainerProperty(Object propertyId, Class type,
0241:                    Object defaultValue) {
0242:
0243:                // Fails, if nulls are given
0244:                if (propertyId == null || type == null)
0245:                    return false;
0246:
0247:                // Fails if the Property is already present
0248:                if (propertyIds.contains(propertyId))
0249:                    return false;
0250:
0251:                // Add the Property to Property list and types
0252:                propertyIds.add(propertyId);
0253:                types.put(propertyId, type);
0254:
0255:                // If default value is given, set it
0256:                if (defaultValue != null)
0257:                    for (Iterator i = itemIds.iterator(); i.hasNext();)
0258:                        getItem(i.next()).getItemProperty(propertyId).setValue(
0259:                                defaultValue);
0260:
0261:                // Send a change event
0262:                fireContainerPropertySetChange();
0263:
0264:                return true;
0265:            }
0266:
0267:            /**
0268:             * Remove all Items from the list. Note that Property ID and type
0269:             * information is preserved.
0270:             * 
0271:             * @return <code>true</code> if the operation succeeded,
0272:             *         <code>false</code> if not
0273:             */
0274:            public boolean removeAllItems() {
0275:
0276:                // Remove all Items
0277:                itemIds.clear();
0278:                items.clear();
0279:
0280:                // Send a change event
0281:                fireContentsChange();
0282:
0283:                return true;
0284:            }
0285:
0286:            /**
0287:             * Create a new Item into the list, and assign it an automatic ID. The new
0288:             * ID is returned, or <code>null</code> if the operation fails. After a
0289:             * successful call you can use the
0290:             * {@link #getItem(Object ItemId) <code>getItem</code>}method to fetch the
0291:             * Item.
0292:             * 
0293:             * @return ID of the newly created Item, or <code>null</code> in case of a
0294:             *         failure
0295:             */
0296:            public Object addItem() {
0297:
0298:                // Create a new id
0299:                Object id = new Object();
0300:
0301:                // Add the Item into container
0302:                addItem(id);
0303:
0304:                return id;
0305:            }
0306:
0307:            /**
0308:             * Create a new Item with the given ID into the list. The new Item is
0309:             * returned, and it is ready to have its Properties modified. Returns
0310:             * <code>null</code> if the operation fails or the Container already
0311:             * contains a Item with the given ID.
0312:             * 
0313:             * @param itemId
0314:             *            ID of the Item to be created
0315:             * @return Created new Item, or <code>null</code> in case of a failure
0316:             */
0317:            public Item addItem(Object itemId) {
0318:
0319:                // Make sure that the Item has not been created yet
0320:                if (items.containsKey(itemId))
0321:                    return null;
0322:
0323:                // Add the Item to container
0324:                itemIds.add(itemId);
0325:                items.put(itemId, new Hashtable());
0326:
0327:                // Send the event
0328:                fireContentsChange();
0329:
0330:                return getItem(itemId);
0331:            }
0332:
0333:            /**
0334:             * Remove the Item corresponding to the given Item ID from the list.
0335:             * 
0336:             * @param itemId
0337:             *            ID of the Item to remove
0338:             * @return <code>true</code> if the operation succeeded,
0339:             *         <code>false</code> if not
0340:             */
0341:            public boolean removeItem(Object itemId) {
0342:
0343:                if (items.remove(itemId) == null)
0344:                    return false;
0345:                itemIds.remove(itemId);
0346:
0347:                fireContentsChange();
0348:
0349:                return true;
0350:            }
0351:
0352:            /**
0353:             * Remove a Property specified by the given Property ID from the list. Note
0354:             * that the Property will be removed from all Items in the list.
0355:             * 
0356:             * @param propertyId
0357:             *            ID of the Property to remove
0358:             * @return <code>true</code> if the operation succeeded,
0359:             *         <code>false</code> if not
0360:             */
0361:            public boolean removeContainerProperty(Object propertyId) {
0362:
0363:                // Fails if the Property is not present
0364:                if (!propertyIds.contains(propertyId))
0365:                    return false;
0366:
0367:                // Remove the Property to Property list and types
0368:                propertyIds.remove(propertyId);
0369:                types.remove(propertyId);
0370:
0371:                // If remove the Property from all Items
0372:                for (Iterator i = itemIds.iterator(); i.hasNext();)
0373:                    ((Hashtable) items.get(i.next())).remove(propertyId);
0374:
0375:                // Send a change event
0376:                fireContainerPropertySetChange();
0377:
0378:                return true;
0379:            }
0380:
0381:            /* Container.Ordered methods ******************************************** */
0382:
0383:            /**
0384:             * Gets the ID of the first Item in the list.
0385:             * 
0386:             * @return ID of the first Item in the list
0387:             */
0388:            public Object firstItemId() {
0389:                try {
0390:                    return itemIds.get(0);
0391:                } catch (IndexOutOfBoundsException e) {
0392:                }
0393:                return null;
0394:            }
0395:
0396:            /**
0397:             * Gets the ID of the last Item in the list.
0398:             * 
0399:             * @return ID of the last Item in the list
0400:             */
0401:            public Object lastItemId() {
0402:                try {
0403:                    return itemIds.get(itemIds.size() - 1);
0404:                } catch (IndexOutOfBoundsException e) {
0405:                }
0406:                return null;
0407:            }
0408:
0409:            /**
0410:             * Gets the ID of the Item following the Item that corresponds to
0411:             * <code>itemId</code>. If the given Item is the last or not found in the
0412:             * list, <code>null</code> is returned.
0413:             * 
0414:             * @param itemId
0415:             *            ID of an Item in the list
0416:             * @return ID of the next Item or <code>null</code>
0417:             */
0418:            public Object nextItemId(Object itemId) {
0419:                try {
0420:                    return itemIds.get(itemIds.indexOf(itemId) + 1);
0421:                } catch (IndexOutOfBoundsException e) {
0422:                    return null;
0423:                }
0424:            }
0425:
0426:            /**
0427:             * Gets the ID of the Item preceding the Item that corresponds to
0428:             * <code>itemId</code>. If the given Item is the first or not found in
0429:             * the list, <code>null</code> is returned.
0430:             * 
0431:             * @param itemId
0432:             *            ID of an Item in the list
0433:             * @return ID of the previous Item or <code>null</code>
0434:             */
0435:            public Object prevItemId(Object itemId) {
0436:                try {
0437:                    return itemIds.get(itemIds.indexOf(itemId) - 1);
0438:                } catch (IndexOutOfBoundsException e) {
0439:                    return null;
0440:                }
0441:            }
0442:
0443:            /**
0444:             * Tests if the Item corresponding to the given Item ID is the first Item in
0445:             * the list.
0446:             * 
0447:             * @param itemId
0448:             *            ID of an Item in the list
0449:             * @return <code>true</code> if the Item is first in the list,
0450:             *         <code>false</code> if not
0451:             */
0452:            public boolean isFirstId(Object itemId) {
0453:                return (size() >= 1 && itemIds.get(0).equals(itemId));
0454:            }
0455:
0456:            /**
0457:             * Tests if the Item corresponding to the given Item ID is the last Item in
0458:             * the list.
0459:             * 
0460:             * @param itemId
0461:             *            ID of an Item in the list
0462:             * @return <code>true</code> if the Item is last in the list,
0463:             *         <code>false</code> if not
0464:             */
0465:            public boolean isLastId(Object itemId) {
0466:                int s = size();
0467:                return (s >= 1 && itemIds.get(s - 1).equals(itemId));
0468:            }
0469:
0470:            /**
0471:             * @see org.millstone.base.data.Container.Ordered#addItemAfter(Object,
0472:             *      Object)
0473:             */
0474:            public Item addItemAfter(Object previousItemId, Object newItemId) {
0475:
0476:                // Get the index of the addition
0477:                int index = 0;
0478:                if (previousItemId != null) {
0479:                    index = 1 + indexOfId(previousItemId);
0480:                    if (index <= 0 || index > size())
0481:                        return null;
0482:                }
0483:
0484:                return addItemAt(index, newItemId);
0485:            }
0486:
0487:            /**
0488:             * @see org.millstone.base.data.Container.Ordered#addItemAfter(Object)
0489:             */
0490:            public Object addItemAfter(Object previousItemId) {
0491:
0492:                // Get the index of the addition
0493:                int index = 0;
0494:                if (previousItemId != null) {
0495:                    index = 1 + indexOfId(previousItemId);
0496:                    if (index <= 0 || index > size())
0497:                        return null;
0498:                }
0499:
0500:                return addItemAt(index);
0501:            }
0502:
0503:            /**
0504:             * Get ID with the index. The following is true for the index: 0 <= index <
0505:             * size().
0506:             * 
0507:             * @return ID in the given index.
0508:             * @param index
0509:             *            Index of the requested ID in the container.
0510:             */
0511:            public Object getIdByIndex(int index) {
0512:                return itemIds.get(index);
0513:            }
0514:
0515:            /**
0516:             * Get the index of an id. The following is true for the index: 0 <= index <
0517:             * size().
0518:             * 
0519:             * @return Index of the Item or -1 if the Item is not in the container.
0520:             * @param itemId
0521:             *            ID of an Item in the collection
0522:             */
0523:            public int indexOfId(Object itemId) {
0524:                return itemIds.indexOf(itemId);
0525:            }
0526:
0527:            /**
0528:             * @see org.millstone.base.data.Container.Indexed#addItemAt(int, Object)
0529:             */
0530:            public Item addItemAt(int index, Object newItemId) {
0531:
0532:                // Make sure that the Item has not been created yet
0533:                if (items.containsKey(newItemId))
0534:                    return null;
0535:
0536:                // Add the Item to container
0537:                itemIds.add(index, newItemId);
0538:                items.put(newItemId, new Hashtable());
0539:
0540:                // Send the event
0541:                fireContentsChange();
0542:
0543:                return getItem(newItemId);
0544:            }
0545:
0546:            /**
0547:             * @see org.millstone.base.data.Container.Indexed#addItemAt(int)
0548:             */
0549:            public Object addItemAt(int index) {
0550:
0551:                // Create a new id
0552:                Object id = new Object();
0553:
0554:                // Add the Item into container
0555:                addItemAt(index, id);
0556:
0557:                return id;
0558:            }
0559:
0560:            /* Event notifiers ****************************************************** */
0561:
0562:            /**
0563:             * An <code>event</code> object specifying the list whose Property set has
0564:             * changed.
0565:             * 
0566:             * @author IT Mill Ltd.
0567:             * @version
0568:             * 3.1.1
0569:             * @since 3.0
0570:             */
0571:            private class PropertySetChangeEvent extends EventObject implements 
0572:                    Container.PropertySetChangeEvent {
0573:
0574:                /**
0575:                 * Serial generated by eclipse.
0576:                 */
0577:                private static final long serialVersionUID = 3257002172528079926L;
0578:
0579:                private PropertySetChangeEvent(IndexedContainer source) {
0580:                    super (source);
0581:                }
0582:
0583:                /**
0584:                 * Gets the list whose Property set has changed.
0585:                 * 
0586:                 * @return source object of the event as a Container
0587:                 */
0588:                public Container getContainer() {
0589:                    return (Container) getSource();
0590:                }
0591:            }
0592:
0593:            /**
0594:             * An <code>event</code> object specifying the list whose Item set has
0595:             * changed.
0596:             * 
0597:             * @author IT Mill Ltd.
0598:             * @version
0599:             * 3.1.1
0600:             * @since 3.0
0601:             */
0602:            private class ItemSetChangeEvent extends EventObject implements 
0603:                    Container.ItemSetChangeEvent {
0604:
0605:                /**
0606:                 * Serial generated by eclipse.
0607:                 */
0608:                private static final long serialVersionUID = 3832616279386372147L;
0609:
0610:                private ItemSetChangeEvent(IndexedContainer source) {
0611:                    super (source);
0612:                }
0613:
0614:                /**
0615:                 * Gets the list whose Item set has changed.
0616:                 * 
0617:                 * @return source object of the event as a Container
0618:                 */
0619:                public Container getContainer() {
0620:                    return (Container) getSource();
0621:                }
0622:
0623:            }
0624:
0625:            /**
0626:             * An <code>event</code> object specifying the Propery in a list whose
0627:             * value has changed.
0628:             * 
0629:             * @author IT Mill Ltd.
0630:             * @version
0631:             * 3.1.1
0632:             * @since 3.0
0633:             */
0634:            private class PropertyValueChangeEvent extends EventObject
0635:                    implements  Property.ValueChangeEvent {
0636:
0637:                /**
0638:                 * Serial generated by eclipse.
0639:                 */
0640:                private static final long serialVersionUID = 3833749884498359857L;
0641:
0642:                private PropertyValueChangeEvent(Property source) {
0643:                    super (source);
0644:                }
0645:
0646:                /**
0647:                 * Gets the Property whose value has changed.
0648:                 * 
0649:                 * @return source object of the event as a Property
0650:                 */
0651:                public Property getProperty() {
0652:                    return (Property) getSource();
0653:                }
0654:
0655:            }
0656:
0657:            /**
0658:             * Registers a new Property set change listener for this list.
0659:             * 
0660:             * @param listener
0661:             *            the new Listener to be registered
0662:             */
0663:            public void addListener(Container.PropertySetChangeListener listener) {
0664:                if (propertySetChangeListeners == null)
0665:                    propertySetChangeListeners = new LinkedList();
0666:                propertySetChangeListeners.add(listener);
0667:            }
0668:
0669:            /**
0670:             * Removes a previously registered Property set change listener.
0671:             * 
0672:             * @param listener
0673:             *            listener to be removed
0674:             */
0675:            public void removeListener(
0676:                    Container.PropertySetChangeListener listener) {
0677:                if (propertySetChangeListeners != null)
0678:                    propertySetChangeListeners.remove(listener);
0679:            }
0680:
0681:            /**
0682:             * Adds a Item set change listener for the list.
0683:             * 
0684:             * @param listener
0685:             *            listener to be added
0686:             */
0687:            public void addListener(Container.ItemSetChangeListener listener) {
0688:                if (itemSetChangeListeners == null)
0689:                    itemSetChangeListeners = new LinkedList();
0690:                itemSetChangeListeners.add(listener);
0691:            }
0692:
0693:            /**
0694:             * Removes a Item set change listener from the object.
0695:             * 
0696:             * @param listener
0697:             *            listener to be removed
0698:             */
0699:            public void removeListener(Container.ItemSetChangeListener listener) {
0700:                if (itemSetChangeListeners != null)
0701:                    itemSetChangeListeners.remove(listener);
0702:            }
0703:
0704:            /**
0705:             * Registers a new value change listener for this object.
0706:             * 
0707:             * @param listener
0708:             *            the new Listener to be registered
0709:             */
0710:            public void addListener(Property.ValueChangeListener listener) {
0711:                if (propertyValueChangeListeners == null)
0712:                    propertyValueChangeListeners = new LinkedList();
0713:                propertyValueChangeListeners.add(listener);
0714:            }
0715:
0716:            /**
0717:             * Removes a previously registered value change listener.
0718:             * 
0719:             * @param listener
0720:             *            listener to be removed
0721:             */
0722:            public void removeListener(Property.ValueChangeListener listener) {
0723:                if (propertyValueChangeListeners != null)
0724:                    propertyValueChangeListeners.remove(listener);
0725:            }
0726:
0727:            /** Send a Property value change event to all interested listeners */
0728:            private void firePropertyValueChange(IndexedContainerProperty source) {
0729:
0730:                // Send event to listeners listening all value changes
0731:                if (propertyValueChangeListeners != null) {
0732:                    Object[] l = propertyValueChangeListeners.toArray();
0733:                    Property.ValueChangeEvent event = new IndexedContainer.PropertyValueChangeEvent(
0734:                            source);
0735:                    for (int i = 0; i < l.length; i++)
0736:                        ((Property.ValueChangeListener) l[i])
0737:                                .valueChange(event);
0738:                }
0739:
0740:                // Send event to single property value change listeners
0741:                if (singlePropertyValueChangeListeners != null) {
0742:                    Hashtable propertySetToListenerListMap = (Hashtable) singlePropertyValueChangeListeners
0743:                            .get(source.propertyId);
0744:                    if (propertySetToListenerListMap != null) {
0745:                        LinkedList listenerList = (LinkedList) propertySetToListenerListMap
0746:                                .get(source.itemId);
0747:                        if (listenerList != null) {
0748:                            Property.ValueChangeEvent event = new IndexedContainer.PropertyValueChangeEvent(
0749:                                    source);
0750:                            for (Iterator i = listenerList.iterator(); i
0751:                                    .hasNext();)
0752:                                ((Property.ValueChangeListener) i.next())
0753:                                        .valueChange(event);
0754:                        }
0755:                    }
0756:                }
0757:
0758:            }
0759:
0760:            /** Send a Property set change event to all interested listeners */
0761:            private void fireContainerPropertySetChange() {
0762:                if (propertySetChangeListeners != null) {
0763:                    Object[] l = propertySetChangeListeners.toArray();
0764:                    Container.PropertySetChangeEvent event = new IndexedContainer.PropertySetChangeEvent(
0765:                            this );
0766:                    for (int i = 0; i < l.length; i++)
0767:                        ((Container.PropertySetChangeListener) l[i])
0768:                                .containerPropertySetChange(event);
0769:                }
0770:            }
0771:
0772:            /** Send Item set change event to all registered interested listeners */
0773:            private void fireContentsChange() {
0774:                if (itemSetChangeListeners != null) {
0775:                    Object[] l = itemSetChangeListeners.toArray();
0776:                    Container.ItemSetChangeEvent event = new IndexedContainer.ItemSetChangeEvent(
0777:                            this );
0778:                    for (int i = 0; i < l.length; i++)
0779:                        ((Container.ItemSetChangeListener) l[i])
0780:                                .containerItemSetChange(event);
0781:                }
0782:            }
0783:
0784:            /** Add new single Property change listener */
0785:            private void addSinglePropertyChangeListener(Object propertyId,
0786:                    Object itemId, Property.ValueChangeListener listener) {
0787:                if (listener != null) {
0788:                    if (singlePropertyValueChangeListeners == null)
0789:                        singlePropertyValueChangeListeners = new Hashtable();
0790:                    Hashtable propertySetToListenerListMap = (Hashtable) singlePropertyValueChangeListeners
0791:                            .get(propertyId);
0792:                    if (propertySetToListenerListMap == null) {
0793:                        propertySetToListenerListMap = new Hashtable();
0794:                        singlePropertyValueChangeListeners.put(propertyId,
0795:                                propertySetToListenerListMap);
0796:                    }
0797:                    LinkedList listenerList = (LinkedList) propertySetToListenerListMap
0798:                            .get(itemId);
0799:                    if (listenerList == null) {
0800:                        listenerList = new LinkedList();
0801:                        propertySetToListenerListMap.put(itemId, listenerList);
0802:                    }
0803:                    listenerList.addLast(listener);
0804:                }
0805:            }
0806:
0807:            /** Remove a previously registered single Property change listener */
0808:            private void removeSinglePropertyChangeListener(Object propertyId,
0809:                    Object itemId, Property.ValueChangeListener listener) {
0810:                if (listener != null
0811:                        && singlePropertyValueChangeListeners != null) {
0812:                    Hashtable propertySetToListenerListMap = (Hashtable) singlePropertyValueChangeListeners
0813:                            .get(propertyId);
0814:                    if (propertySetToListenerListMap != null) {
0815:                        LinkedList listenerList = (LinkedList) propertySetToListenerListMap
0816:                                .get(itemId);
0817:                        if (listenerList != null) {
0818:                            listenerList.remove(listener);
0819:                            if (listenerList.isEmpty())
0820:                                propertySetToListenerListMap.remove(itemId);
0821:                        }
0822:                        if (propertySetToListenerListMap.isEmpty())
0823:                            singlePropertyValueChangeListeners
0824:                                    .remove(propertyId);
0825:                    }
0826:                    if (singlePropertyValueChangeListeners.isEmpty())
0827:                        singlePropertyValueChangeListeners = null;
0828:                }
0829:            }
0830:
0831:            /* Internal Item and Property implementations *************************** */
0832:
0833:            /*
0834:             * A class implementing the org.millstone.base.data.Item interface to be
0835:             * contained in the list. @author IT Mill Ltd.
0836:             * 
0837:             * @version 3.1.1
0838:             * @since 3.0
0839:             */
0840:            class IndexedContainerItem implements  Item {
0841:
0842:                /** Item ID in the host container for this Item */
0843:                private Object itemId;
0844:
0845:                /**
0846:                 * Constructs a new ListItem instance and connects it to a host
0847:                 * container.
0848:                 * 
0849:                 * @param host
0850:                 *            the list that contains this Item
0851:                 * @param itemId
0852:                 *            Item ID of the new Item
0853:                 */
0854:                private IndexedContainerItem(Object itemId) {
0855:
0856:                    // Get the item contents from the host
0857:                    if (itemId == null)
0858:                        throw new NullPointerException();
0859:                    this .itemId = itemId;
0860:                }
0861:
0862:                /**
0863:                 * Gets the Property corresponding to the given Property ID stored in
0864:                 * the Item. If the Item does not contain the Property,
0865:                 * <code>null</code> is returned.
0866:                 * 
0867:                 * @param id
0868:                 *            identifier of the Property to get
0869:                 * @return the Property with the given ID or <code>null</code>
0870:                 */
0871:                public Property getItemProperty(Object id) {
0872:                    return new IndexedContainerProperty(itemId, id);
0873:                }
0874:
0875:                /**
0876:                 * Gets the collection containing the IDs of all Properties stored in
0877:                 * the Item.
0878:                 * 
0879:                 * @return unmodifiable collection contaning IDs of the Properties
0880:                 *         stored the Item
0881:                 */
0882:                public Collection getItemPropertyIds() {
0883:                    return Collections.unmodifiableCollection(propertyIds);
0884:                }
0885:
0886:                /**
0887:                 * Gets the <code>String</code> representation of the contents of the
0888:                 * Item. The format of the string is a space separated catenation of the
0889:                 * <code>String</code> representations of the Properties contained by
0890:                 * the Item.
0891:                 * 
0892:                 * @return <code>String</code> representation of the Item contents
0893:                 */
0894:                public String toString() {
0895:                    String retValue = "";
0896:
0897:                    for (Iterator i = propertyIds.iterator(); i.hasNext();) {
0898:                        Object propertyId = i.next();
0899:                        retValue += getItemProperty(propertyId).toString();
0900:                        if (i.hasNext())
0901:                            retValue += " ";
0902:                    }
0903:
0904:                    return retValue;
0905:                }
0906:
0907:                /**
0908:                 * Calculates a integer hash-code for the Item that's unique inside the
0909:                 * list. Two Items inside the same list have always different
0910:                 * hash-codes, though Items in different lists may have identical
0911:                 * hash-codes.
0912:                 * 
0913:                 * @return A locally unique hash-code as integer
0914:                 */
0915:                public int hashCode() {
0916:                    return getHost().hashCode() ^ itemId.hashCode();
0917:                }
0918:
0919:                /**
0920:                 * Tests if the given object is the same as the this object. Two Items
0921:                 * got from a list container with the same ID are equal.
0922:                 * 
0923:                 * @param obj
0924:                 *            an object to compare with this object
0925:                 * @return <code>true</code> if the given object is the same as this
0926:                 *         object, <code>false</code> if not
0927:                 */
0928:                public boolean equals(Object obj) {
0929:                    if (obj == null
0930:                            || !obj.getClass().equals(
0931:                                    IndexedContainerItem.class))
0932:                        return false;
0933:                    IndexedContainerItem li = (IndexedContainerItem) obj;
0934:                    return getHost() == li.getHost()
0935:                            && itemId.equals(li.itemId);
0936:                }
0937:
0938:                private IndexedContainer getHost() {
0939:                    return IndexedContainer.this ;
0940:                }
0941:
0942:                /**
0943:                 * Indexed container does not support adding new properties.
0944:                 * 
0945:                 * @see org.millstone.base.data.Item#addProperty(Object, Property)
0946:                 */
0947:                public boolean addItemProperty(Object id, Property property)
0948:                        throws UnsupportedOperationException {
0949:                    throw new UnsupportedOperationException(
0950:                            "Indexed container item "
0951:                                    + "does not support adding new properties");
0952:                }
0953:
0954:                /**
0955:                 * Indexed container does not support removing properties.
0956:                 * 
0957:                 * @see org.millstone.base.data.Item#removeProperty(Object)
0958:                 */
0959:                public boolean removeItemProperty(Object id)
0960:                        throws UnsupportedOperationException {
0961:                    throw new UnsupportedOperationException(
0962:                            "Indexed container item does not support property removal");
0963:                }
0964:
0965:            }
0966:
0967:            /*
0968:             * A class implementing the org.millstone.base.data.Property interface to be
0969:             * contained in the Items contained in the list. @author IT Mill Ltd.
0970:             * 
0971:             * @version 3.1.1
0972:             * @since 3.0
0973:             */
0974:            private class IndexedContainerProperty implements  Property,
0975:                    Property.ValueChangeNotifier {
0976:
0977:                /** ID of the Item, where the Property resides */
0978:                private Object itemId;
0979:
0980:                /** Id of the Property */
0981:                private Object propertyId;
0982:
0983:                /**
0984:                 * Constructs a new ListProperty object and connect it to a ListItem and
0985:                 * a ListContainer.
0986:                 * 
0987:                 * @param itemId
0988:                 *            ID of the Item to connect the new Property to
0989:                 * @param propertyId
0990:                 *            Property ID of the new Property
0991:                 * @param host
0992:                 *            the list that contains the Item to contain the new
0993:                 *            Property
0994:                 */
0995:                private IndexedContainerProperty(Object itemId,
0996:                        Object propertyId) {
0997:                    if (itemId == null || propertyId == null)
0998:                        throw new NullPointerException();
0999:                    this .propertyId = propertyId;
1000:                    this .itemId = itemId;
1001:                }
1002:
1003:                /**
1004:                 * Return the type of the Property. The methods <code>getValue</code>
1005:                 * and <code>setValue</code> must be compatible with this type: one
1006:                 * must be able to safely cast the value returned from
1007:                 * <code>getValue</code> to the given type and pass any variable
1008:                 * assignable to this type as a parameter to <code>setValue</code.
1009:                 * 
1010:                 * @return type of the Property
1011:                 */
1012:                public Class getType() {
1013:                    return (Class) types.get(propertyId);
1014:                }
1015:
1016:                /**
1017:                 * Gets the value stored in the Property.
1018:                 * 
1019:                 * @return the value stored in the Property
1020:                 */
1021:                public Object getValue() {
1022:                    return ((Hashtable) items.get(itemId)).get(propertyId);
1023:                }
1024:
1025:                /**
1026:                 * <p>
1027:                 * Test if the Property is in read-only mode. In read-only mode calls to
1028:                 * the method <code>setValue</code> will throw
1029:                 * <code>ReadOnlyException</code> s and will not modify the value of
1030:                 * the Property.
1031:                 * </p>
1032:                 * 
1033:                 * @return <code>true</code> if the Property is in read-only mode,
1034:                 *         <code>false</code> if it's not
1035:                 */
1036:                public boolean isReadOnly() {
1037:                    return readOnlyProperties.contains(this );
1038:                }
1039:
1040:                /**
1041:                 * Set the Property's read-only mode to the specified status.
1042:                 * 
1043:                 * @param newStatus
1044:                 *            new read-only status of the Property
1045:                 */
1046:                public void setReadOnly(boolean newStatus) {
1047:                    if (newStatus)
1048:                        readOnlyProperties.add(this );
1049:                    else
1050:                        readOnlyProperties.remove(this );
1051:                }
1052:
1053:                /**
1054:                 * Sets the value of the Property. By default this method will try to
1055:                 * assign the value directly, but if it is unassignable, it will try to
1056:                 * use the <code>String</code> constructor of the internal data type
1057:                 * to assign the value,
1058:                 * 
1059:                 * @param newValue
1060:                 *            New value of the Property. This should be assignable to
1061:                 *            the Property's internal type or support
1062:                 *            <code>toString</code>.
1063:                 * 
1064:                 * @throws Property.ReadOnlyException
1065:                 *             if the object is in read-only mode
1066:                 * @throws Property.ConversionException
1067:                 *             if <code>newValue</code> can't be converted into the
1068:                 *             Property's native type directly or through
1069:                 *             <code>String</code>
1070:                 */
1071:                public void setValue(Object newValue)
1072:                        throws Property.ReadOnlyException,
1073:                        Property.ConversionException {
1074:
1075:                    // Get the Property set
1076:                    Hashtable propertySet = (Hashtable) items.get(itemId);
1077:
1078:                    // Support null values on all types
1079:                    if (newValue == null)
1080:                        propertySet.remove(propertyId);
1081:
1082:                    // Try to assign the compatible value directly
1083:                    else if (getType().isAssignableFrom(newValue.getClass()))
1084:                        propertySet.put(propertyId, newValue);
1085:
1086:                    // Otherwise try to convert the value trough string constructor
1087:                    else
1088:                        try {
1089:
1090:                            // Get the string constructor
1091:                            Constructor constr = getType().getConstructor(
1092:                                    new Class[] { String.class });
1093:
1094:                            // Create new object from the string
1095:                            propertySet.put(propertyId, constr
1096:                                    .newInstance(new Object[] { newValue
1097:                                            .toString() }));
1098:
1099:                        } catch (java.lang.Exception e) {
1100:                            throw new Property.ConversionException(
1101:                                    "Conversion for value '" + newValue
1102:                                            + "' of class "
1103:                                            + newValue.getClass().getName()
1104:                                            + " to " + getType().getName()
1105:                                            + " failed");
1106:                        }
1107:
1108:                    firePropertyValueChange(this );
1109:                }
1110:
1111:                /**
1112:                 * Return the value of the Property in human readable textual format.
1113:                 * The return value should be assignable to the <code>setValue</code>
1114:                 * method if the Property is not in read-only mode.
1115:                 * 
1116:                 * @return <code>String</code> representation of the value stored in
1117:                 *         the Property
1118:                 */
1119:                public String toString() {
1120:                    Object value = getValue();
1121:                    if (value == null)
1122:                        return null;
1123:                    return value.toString();
1124:                }
1125:
1126:                /**
1127:                 * Calculates a integer hash-code for the Property that's unique inside
1128:                 * the Item containing the Property. Two different Properties inside the
1129:                 * same Item contained in the same list always have different
1130:                 * hash-codes, though Properties in different Items may have identical
1131:                 * hash-codes.
1132:                 * 
1133:                 * @return A locally unique hash-code as integer
1134:                 */
1135:                public int hashCode() {
1136:                    return itemId.hashCode() ^ propertyId.hashCode()
1137:                            ^ IndexedContainer.this .hashCode();
1138:                }
1139:
1140:                /**
1141:                 * Tests if the given object is the same as the this object. Two
1142:                 * Properties got from an Item with the same ID are equal.
1143:                 * 
1144:                 * @param obj
1145:                 *            an object to compare with this object
1146:                 * @return <code>true</code> if the given object is the same as this
1147:                 *         object, <code>false</code> if not
1148:                 */
1149:                public boolean equals(Object obj) {
1150:                    if (obj == null
1151:                            || !obj.getClass().equals(
1152:                                    IndexedContainerProperty.class))
1153:                        return false;
1154:                    IndexedContainerProperty lp = (IndexedContainerProperty) obj;
1155:                    return lp.getHost() == getHost()
1156:                            && lp.propertyId.equals(propertyId)
1157:                            && lp.itemId.equals(itemId);
1158:                }
1159:
1160:                /**
1161:                 * Registers a new value change listener for this Property.
1162:                 * 
1163:                 * @param listener
1164:                 *            the new Listener to be registered
1165:                 * @see org.millstone.base.data.Property.ValueChangeNotifier#addListener(ValueChangeListener)
1166:                 */
1167:                public void addListener(Property.ValueChangeListener listener) {
1168:                    addSinglePropertyChangeListener(propertyId, itemId,
1169:                            listener);
1170:                }
1171:
1172:                /**
1173:                 * Removes a previously registered value change listener.
1174:                 * 
1175:                 * @param listener
1176:                 *            listener to be removed
1177:                 * @see org.millstone.base.data.Property.ValueChangeNotifier#removeListener(ValueChangeListener)
1178:                 */
1179:                public void removeListener(Property.ValueChangeListener listener) {
1180:                    removeSinglePropertyChangeListener(propertyId, itemId,
1181:                            listener);
1182:                }
1183:
1184:                private IndexedContainer getHost() {
1185:                    return IndexedContainer.this ;
1186:                }
1187:
1188:            }
1189:
1190:            /*
1191:             * (non-Javadoc)
1192:             * 
1193:             * @see org.millstone.base.data.Container.Sortable#sort(java.lang.Object[],
1194:             *      boolean[])
1195:             */
1196:            public synchronized void sort(Object[] propertyId,
1197:                    boolean[] ascending) {
1198:
1199:                // Remove any non-sortable property ids
1200:                ArrayList ids = new ArrayList();
1201:                ArrayList orders = new ArrayList();
1202:                Collection sortable = getSortableContainerPropertyIds();
1203:                for (int i = 0; i < propertyId.length; i++)
1204:                    if (sortable.contains(propertyId[i])) {
1205:                        ids.add(propertyId[i]);
1206:                        orders.add(new Boolean(
1207:                                i < ascending.length ? ascending[i] : true));
1208:                    }
1209:
1210:                if (ids.size() == 0)
1211:                    return;
1212:                sortPropertyId = ids.toArray();
1213:                sortDirection = new boolean[orders.size()];
1214:                for (int i = 0; i < sortDirection.length; i++)
1215:                    sortDirection[i] = ((Boolean) orders.get(i)).booleanValue();
1216:
1217:                // Sort
1218:                Collections.sort(this .itemIds, this );
1219:                fireContentsChange();
1220:
1221:                // Remove temporary references
1222:                sortPropertyId = null;
1223:                sortDirection = null;
1224:
1225:            }
1226:
1227:            /*
1228:             * (non-Javadoc)
1229:             * 
1230:             * @see org.millstone.base.data.Container.Sortable#getSortableContainerPropertyIds()
1231:             */
1232:            public Collection getSortableContainerPropertyIds() {
1233:
1234:                LinkedList list = new LinkedList();
1235:                for (Iterator i = this .propertyIds.iterator(); i.hasNext();) {
1236:                    Object id = i.next();
1237:                    Class type = this .getType(id);
1238:                    if (type != null && Comparable.class.isAssignableFrom(type)) {
1239:                        list.add(id);
1240:                    }
1241:                }
1242:
1243:                return list;
1244:            }
1245:
1246:            /**
1247:             * Compare two items for sorting.
1248:             * 
1249:             * @see java.util.Comparator#compare(java.lang.Object, java.lang.Object)
1250:             * @see #sort((java.lang.Object[], boolean[])
1251:             */
1252:            public int compare(Object o1, Object o2) {
1253:
1254:                for (int i = 0; i < sortPropertyId.length; i++) {
1255:
1256:                    // Get the compared properties
1257:                    Property pp1 = getContainerProperty(o1,
1258:                            this .sortPropertyId[i]);
1259:                    Property pp2 = getContainerProperty(o2,
1260:                            this .sortPropertyId[i]);
1261:
1262:                    // Get the compared values
1263:                    Object p1 = pp1 == null ? null : pp1.getValue();
1264:                    Object p2 = pp2 == null ? null : pp2.getValue();
1265:
1266:                    // Result of the comparison
1267:                    int r = 0;
1268:
1269:                    // Normal non-null comparison
1270:                    if (p1 != null && p2 != null) {
1271:                        if ((p1 instanceof  Boolean) && (p2 instanceof  Boolean))
1272:                            r = p1.equals(p2) ? 0 : ((this .sortDirection[i] ? 1
1273:                                    : -1) * (((Boolean) p1).booleanValue() ? 1
1274:                                    : -1));
1275:                        else
1276:                            r = this .sortDirection[i] ? ((Comparable) p1)
1277:                                    .compareTo(p2) : -((Comparable) p1)
1278:                                    .compareTo(p2);
1279:                    }
1280:
1281:                    // If both are nulls
1282:                    else if (p1 == p2)
1283:                        r = 0;
1284:
1285:                    // If one of the properties are null
1286:                    else
1287:                        r = p1 == null ? -1 : 1;
1288:
1289:                    // If order can be decided
1290:                    if (r != 0)
1291:                        return r;
1292:                }
1293:
1294:                return 0;
1295:            }
1296:
1297:            /* Support cloning of the IndexedContainer cleanly */
1298:            public Object clone() throws CloneNotSupportedException {
1299:
1300:                // Create the clone
1301:                IndexedContainer nc = new IndexedContainer();
1302:
1303:                // Clone the shallow properties
1304:                nc.itemIds = this .itemIds != null ? (ArrayList) this .itemIds
1305:                        .clone() : null;
1306:                nc.itemSetChangeListeners = this .itemSetChangeListeners != null ? (LinkedList) this .itemSetChangeListeners
1307:                        .clone()
1308:                        : null;
1309:                nc.propertyIds = this .propertyIds != null ? (ArrayList) this .propertyIds
1310:                        .clone()
1311:                        : null;
1312:                nc.propertySetChangeListeners = this .propertySetChangeListeners != null ? (LinkedList) this .propertySetChangeListeners
1313:                        .clone()
1314:                        : null;
1315:                nc.propertyValueChangeListeners = this .propertyValueChangeListeners != null ? (LinkedList) this .propertyValueChangeListeners
1316:                        .clone()
1317:                        : null;
1318:                nc.readOnlyProperties = this .readOnlyProperties != null ? (HashSet) this .readOnlyProperties
1319:                        .clone()
1320:                        : null;
1321:                nc.singlePropertyValueChangeListeners = this .singlePropertyValueChangeListeners != null ? (Hashtable) this .singlePropertyValueChangeListeners
1322:                        .clone()
1323:                        : null;
1324:                nc.sortDirection = this .sortDirection != null ? (boolean[]) this .sortDirection
1325:                        .clone()
1326:                        : null;
1327:                nc.sortPropertyId = this .sortPropertyId != null ? (Object[]) this .sortPropertyId
1328:                        .clone()
1329:                        : null;
1330:                nc.types = this .types != null ? (Hashtable) this .types.clone()
1331:                        : null;
1332:
1333:                // Clone property-values
1334:                if (this .items == null)
1335:                    nc.items = null;
1336:                else {
1337:                    nc.items = new Hashtable();
1338:                    for (Iterator i = this .items.keySet().iterator(); i
1339:                            .hasNext();) {
1340:                        Object id = i.next();
1341:                        Hashtable it = (Hashtable) this .items.get(id);
1342:                        nc.items.put(id, it.clone());
1343:                    }
1344:                }
1345:
1346:                return nc;
1347:            }
1348:
1349:            public boolean equals(Object obj) {
1350:
1351:                // Only ones of the objects of the same class can be equal
1352:                if (!(obj instanceof  IndexedContainer))
1353:                    return false;
1354:                IndexedContainer o = (IndexedContainer) obj;
1355:
1356:                // Check the properties one by one
1357:                if (itemIds != o.itemIds && o.itemIds != null
1358:                        && !o.itemIds.equals(this .itemIds))
1359:                    return false;
1360:                if (items != o.items && o.items != null
1361:                        && !o.items.equals(this .items))
1362:                    return false;
1363:                if (itemSetChangeListeners != o.itemSetChangeListeners
1364:                        && o.itemSetChangeListeners != null
1365:                        && !o.itemSetChangeListeners
1366:                                .equals(this .itemSetChangeListeners))
1367:                    return false;
1368:                if (propertyIds != o.propertyIds && o.propertyIds != null
1369:                        && !o.propertyIds.equals(this .propertyIds))
1370:                    return false;
1371:                if (propertySetChangeListeners != o.propertySetChangeListeners
1372:                        && o.propertySetChangeListeners != null
1373:                        && !o.propertySetChangeListeners
1374:                                .equals(this .propertySetChangeListeners))
1375:                    return false;
1376:                if (propertyValueChangeListeners != o.propertyValueChangeListeners
1377:                        && o.propertyValueChangeListeners != null
1378:                        && !o.propertyValueChangeListeners
1379:                                .equals(this .propertyValueChangeListeners))
1380:                    return false;
1381:                if (readOnlyProperties != o.readOnlyProperties
1382:                        && o.readOnlyProperties != null
1383:                        && !o.readOnlyProperties
1384:                                .equals(this .readOnlyProperties))
1385:                    return false;
1386:                if (singlePropertyValueChangeListeners != o.singlePropertyValueChangeListeners
1387:                        && o.singlePropertyValueChangeListeners != null
1388:                        && !o.singlePropertyValueChangeListeners
1389:                                .equals(this .singlePropertyValueChangeListeners))
1390:                    return false;
1391:                if (sortDirection != o.sortDirection && o.sortDirection != null
1392:                        && !o.sortDirection.equals(this .sortDirection))
1393:                    return false;
1394:                if (sortPropertyId != o.sortPropertyId
1395:                        && o.sortPropertyId != null
1396:                        && !o.sortPropertyId.equals(this .sortPropertyId))
1397:                    return false;
1398:                if (types != o.types && o.types != null
1399:                        && !o.types.equals(this .types))
1400:                    return false;
1401:
1402:                return true;
1403:            }
1404:
1405:            public int hashCode() {
1406:
1407:                // The hash-code is calculated as combination hash of the members
1408:                return (this .itemIds != null ? this .itemIds.hashCode() : 0)
1409:                        ^ (this .items != null ? this .items.hashCode() : 0)
1410:                        ^ (this .itemSetChangeListeners != null ? this .itemSetChangeListeners
1411:                                .hashCode()
1412:                                : 0)
1413:                        ^ (this .propertyIds != null ? this .propertyIds
1414:                                .hashCode() : 0)
1415:                        ^ (this .propertySetChangeListeners != null ? this .propertySetChangeListeners
1416:                                .hashCode()
1417:                                : 0)
1418:                        ^ (this .propertyValueChangeListeners != null ? this .propertyValueChangeListeners
1419:                                .hashCode()
1420:                                : 0)
1421:                        ^ (this .readOnlyProperties != null ? this .readOnlyProperties
1422:                                .hashCode()
1423:                                : 0)
1424:                        ^ (this .singlePropertyValueChangeListeners != null ? this .singlePropertyValueChangeListeners
1425:                                .hashCode()
1426:                                : 0)
1427:                        ^ (this .sortPropertyId != null ? this .sortPropertyId
1428:                                .hashCode() : 0)
1429:                        ^ (this .types != null ? this .types.hashCode() : 0)
1430:                        ^ (this .sortDirection != null ? this .sortDirection
1431:                                .hashCode() : 0);
1432:            }
1433:
1434:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.