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.util;
039:
040: import java.util.Collection;
041: import java.util.Collections;
042: import java.util.EventObject;
043: import java.util.HashMap;
044: import java.util.Iterator;
045: import java.util.LinkedList;
046:
047: import org.millstone.base.data.Item;
048: import org.millstone.base.data.Property;
049:
050: /**
051: * Class for handling a set of identified Properties. The elements contained in
052: * a</code> MapItem</code> can be referenced using locally unique identifiers.
053: * The class supports listeners who are interested in changes to the Property
054: * set managed by the class.
055: *
056: * @author IT Mill Ltd.
057: * @version
058: * 3.1.1
059: * @since 3.0
060: */
061: public class PropertysetItem implements Item,
062: Item.PropertySetChangeNotifier, Cloneable {
063:
064: /* Private representation of the item *********************************** */
065:
066: /** Mapping from property id to property */
067: private HashMap map = new HashMap();
068:
069: /** List of all property ids to maintain the order */
070: private LinkedList list = new LinkedList();
071:
072: /** List of property set modification listeners */
073: private LinkedList propertySetChangeListeners = null;
074:
075: /* Item methods ******************************************************** */
076:
077: /**
078: * Gets the Property corresponding to the given Property ID stored in the
079: * Item. If the Item does not contain the Property, <code>null</code> is
080: * returned.
081: *
082: * @param id
083: * identifier of the Property to get
084: * @return the Property with the given ID or <code>null</code>
085: */
086: public Property getItemProperty(Object id) {
087: return (Property) map.get(id);
088: }
089:
090: /**
091: * Gets the collection of IDs of all Properties stored in the Item.
092: *
093: * @return unmodifiable collection containing IDs of the Properties stored
094: * the Item
095: */
096: public Collection getItemPropertyIds() {
097: return Collections.unmodifiableCollection(list);
098: }
099:
100: /* Item.Managed methods ************************************************* */
101:
102: /**
103: * Removes the Property identified by ID from the Item. This functionality
104: * is optional. If the method is not implemented, the method always returns
105: * <code>false</code>.
106: *
107: * @param id
108: * ID of the Property to be removed
109: * @return <code>true</code> if the operation succeeded <code>false</code>
110: * if not
111: */
112: public boolean removeItemProperty(Object id) {
113:
114: // Cant remove missing properties
115: if (map.remove(id) == null) {
116: return false;
117: }
118: list.remove(id);
119:
120: // Send change events
121: fireItemPropertySetChange();
122:
123: return true;
124: }
125:
126: /**
127: * Tries to add a new Property into the Item.
128: *
129: * @param id
130: * ID of the new Property
131: * @param property
132: * the Property to be added and associated with <code>id</code>
133: * @return <code>true</code> if the operation succeeded,
134: * <code>false</code> if not
135: */
136: public boolean addItemProperty(Object id, Property property) {
137:
138: // Cant add a property twice
139: if (map.containsKey(id))
140: return false;
141:
142: // Put the property to map
143: map.put(id, property);
144: list.add(id);
145:
146: // Send event
147: fireItemPropertySetChange();
148:
149: return true;
150: }
151:
152: /**
153: * Gets the <code>String</code> representation of the contents of the
154: * Item. The format of the string is a space separated catenation of the
155: * <code>String</code> representations of the Properties contained by the
156: * Item.
157: *
158: * @return <code>String</code> representation of the Item contents
159: */
160: public String toString() {
161: String retValue = "";
162:
163: for (Iterator i = getItemPropertyIds().iterator(); i.hasNext();) {
164: Object propertyId = i.next();
165: retValue += getItemProperty(propertyId).toString();
166: if (i.hasNext())
167: retValue += " ";
168: }
169:
170: return retValue;
171: }
172:
173: /* Notifiers ************************************************************ */
174:
175: /**
176: * An <code>event</code> object specifying an Item whose Property set has
177: * changed.
178: *
179: * @author IT Mill Ltd.
180: * @version
181: * 3.1.1
182: * @since 3.0
183: */
184: private class PropertySetChangeEvent extends EventObject implements
185: Item.PropertySetChangeEvent {
186:
187: /**
188: * Serial generated by eclipse.
189: */
190: private static final long serialVersionUID = 3257562910590055991L;
191:
192: private PropertySetChangeEvent(Item source) {
193: super (source);
194: }
195:
196: /**
197: * Gets the Item whose Property set has changed.
198: *
199: * @return source object of the event as an <code>Item</code>
200: */
201: public Item getItem() {
202: return (Item) getSource();
203: }
204: }
205:
206: /**
207: * Registers a new property set change listener for this Item.
208: *
209: * @param listener
210: * The new Listener to be registered.
211: */
212: public void addListener(Item.PropertySetChangeListener listener) {
213: if (propertySetChangeListeners == null)
214: propertySetChangeListeners = new LinkedList();
215: propertySetChangeListeners.add(listener);
216: }
217:
218: /**
219: * Removes a previously registered property set change listener.
220: *
221: * @param listener
222: * Listener to be removed.
223: */
224: public void removeListener(Item.PropertySetChangeListener listener) {
225: if (propertySetChangeListeners != null)
226: propertySetChangeListeners.remove(listener);
227: }
228:
229: /** Send a Property set change event to all interested listeners */
230: private void fireItemPropertySetChange() {
231: if (propertySetChangeListeners != null) {
232: Object[] l = propertySetChangeListeners.toArray();
233: Item.PropertySetChangeEvent event = new PropertysetItem.PropertySetChangeEvent(
234: this );
235: for (int i = 0; i < l.length; i++)
236: ((Item.PropertySetChangeListener) l[i])
237: .itemPropertySetChange(event);
238: }
239: }
240:
241: public Object clone() throws CloneNotSupportedException {
242:
243: PropertysetItem npsi = new PropertysetItem();
244:
245: npsi.list = this .list != null ? (LinkedList) list.clone()
246: : null;
247: npsi.propertySetChangeListeners = this .propertySetChangeListeners != null ? (LinkedList) propertySetChangeListeners
248: .clone()
249: : null;
250: npsi.map = (HashMap) this .map.clone();
251:
252: return npsi;
253: }
254:
255: public boolean equals(Object obj) {
256:
257: if (obj == null || !(obj instanceof PropertysetItem))
258: return false;
259:
260: PropertysetItem other = (PropertysetItem) obj;
261:
262: if (other.list != this .list) {
263: if (other.list == null)
264: return false;
265: if (!other.list.equals(this .list))
266: return false;
267: }
268: if (other.map != this .map) {
269: if (other.map == null)
270: return false;
271: if (!other.map.equals(this .map))
272: return false;
273: }
274: if (other.propertySetChangeListeners != this .propertySetChangeListeners) {
275: if (other.propertySetChangeListeners == null)
276: return false;
277: if (!other.propertySetChangeListeners
278: .equals(this .propertySetChangeListeners))
279: return false;
280: }
281:
282: return true;
283: }
284:
285: public int hashCode() {
286:
287: return (list == null ? 0 : list.hashCode())
288: ^ (map == null ? 0 : map.hashCode())
289: ^ (propertySetChangeListeners == null ? 0
290: : propertySetChangeListeners.hashCode());
291: }
292: }
|