001: package org.apache.commons.events.observable;
002:
003: import java.beans.PropertyChangeEvent;
004: import java.util.Collection;
005:
006: /**
007: * <p>
008: * This event is fired to all registered listeners whenever an observed
009: * collection is altered. The inherited <code>oldValue</code> and
010: * <code>newValue</code> properties are almost always null, as populating
011: * them normally requires that two nearly identical copies of the collection
012: * be maintained. The sole exception to this rule are events which
013: * replace a value in the collection with a different value (e.g., setting
014: * a particular element of a <code>List</code>.)
015: * </p>
016: * <p>Instead, this event maintains
017: * information about <i>how</i> the collection was changed. This information
018: * includes:
019: * </p>
020: *
021: * <ol>
022: * <li>The <i>type</i> of action performed on the collection (e.g., add,
023: * remove, clear, etc.). </li>
024: * <li>The <i>element</i> participating in the action (e.g., the thing which
025: * was added, removed, etc.)</li>
026: * <li>Whether or not the collection was changed as a result of the action.
027: * For instance, attempting to remove an element which is not in a set does
028: * not change the set.</li>
029: * <li>An optional <i>parameter</i> which serves as an index or as an
030: * indicator of the number of copies affected, as appropriate for the
031: * event type.</li>
032: * </ol>
033: *
034: * <p>
035: * This event is always fired <i>after</i> the proposed action has taken place.
036: * As such, it serves as a notification of an action, not
037: * <i>pre</i>-notification of the action. This same event is fired to
038: * subscribers of <b><i>bound propertes</i></b> and <b><i>constrained
039: * properties</i></b>. Those who wish to affect whether or not the change
040: * actually occurs should use a ConstrainedCollection. Those who merely wish
041: * to be notified of changes should use an BoundCollection.
042: * </p>
043: *
044: * <p>
045: * The parent of this event is designed to monitor arbitrary properties of
046: * java beans. This class is designed to monitor only changes to
047: * collections. Therefore, the "property" field of this
048: * event is always set to "collection". Likewise, the
049: * "source" property must always be a <code>BoundCollection</code>
050: * or a <code>ConstrainedCollection</code>.
051: * </p>
052: *
053: *
054: * @see java.beans.PropertyChangeEvent
055: * @see BoundCollection
056: * @see ConstrainedCollection
057: * @see CollectionChangeType
058: * @author Bryce Nordgren / USDA Forest Service
059: */
060: public class CollectionChangeEvent extends PropertyChangeEvent {
061:
062: /** The value to which every "property" field is set. */
063: public final static String PROPERTY = "collection";
064:
065: /** A value for the "parameter" property which means
066: * that the property has not been set. */
067: public final static int NOT_SET = -1;
068:
069: /** Describes the action which caused this event. */
070: private final CollectionChangeType type;
071:
072: /** Indicates whether the collection was changed as a result of the
073: action.*/
074: private final boolean changed;
075:
076: /** A reference to the element participating in the action. */
077: private final Object element;
078:
079: /** An integer parameter used to convey either the index or the
080: * number of copies.
081: */
082: private final int parameter;
083:
084: /**
085: * Public constructor for an event which monitors changes to
086: * collections. This constructor ensures that the old and
087: * new properties are set to null. It also ensures that the
088: * property name is set to "collection", as specified
089: * by the static <code>PROPERTY</code> field of this class.
090: * @param source The collection which was modified.
091: * @param type The type of modification.
092: * @param changed Was the collection actually changed?
093: * @param element The element participating in the modification.
094: * @param parameter Used to indicate number of copies or index.
095: */
096: public CollectionChangeEvent(Object source,
097: final CollectionChangeType type, final boolean changed,
098: final Object element, final int parameter) {
099:
100: super (source, PROPERTY, null, null);
101: this .type = type;
102: this .changed = changed;
103: this .element = element;
104: this .parameter = parameter;
105: }
106:
107: public CollectionChangeEvent(Object source,
108: final CollectionChangeType type, final boolean changed,
109: final Object element) {
110:
111: this (source, type, changed, element, NOT_SET);
112: }
113:
114: public CollectionChangeEvent(Object source,
115: final CollectionChangeType type, final boolean changed) {
116:
117: this (source, type, changed, null, NOT_SET);
118: }
119:
120: /**
121: * <p>
122: * Public constructor which sets the oldValue and newValue properties
123: * of the parent object. This should be used only when an individual
124: * element of a collection is changed from one value to another. This
125: * is applicable, for instance, when a map entry is changed or a list
126: * entry is set. The constructed object will have identical values for
127: * the "element" property and the "newValue"
128: * property.
129: * </p>
130: * @param source The collection which was modified.
131: * @param type The type of modification.
132: * @param changed Was the collection actually changed?
133: * @param element The new value of the element.
134: * @param oldElement the old value of the element.
135: * @param parameter The index of the changed element.
136: */
137: public CollectionChangeEvent(Object source,
138: final CollectionChangeType type, final boolean changed,
139: final Object element, final Object oldElement,
140: final int parameter) {
141:
142: super (source, PROPERTY, oldElement, element);
143: this .type = type;
144: this .changed = changed;
145: this .element = element;
146: this .parameter = parameter;
147: }
148:
149: /**
150: * <p>
151: * Public constructor which initializes the event appropriately for
152: * reporting a <code>put()</code> event on a Map. The oldValue and
153: * newValue properties are set to the former and current values mapped
154: * to the key. The element property is set to the key.
155: * </p>
156: * @param source The collection which was modified.
157: * @param type The type of modification.
158: * @param changed Was the collection actually changed?
159: * @param oldValue The old value mapped to the key.
160: * @param newValue The new value mapped to the key.
161: * @param key The key which is being put in the Map.
162: */
163: public CollectionChangeEvent(Object source,
164: final CollectionChangeType type, final boolean changed,
165: final Object key, final Object oldValue,
166: final Object newValue) {
167:
168: super (source, PROPERTY, oldValue, newValue);
169: this .type = type;
170: this .changed = changed;
171: this .element = key;
172: this .parameter = NOT_SET;
173: }
174:
175: /** Describes the action which caused this event.
176: * @return type of action performed on the collection
177: */
178: public CollectionChangeType getType() {
179: return type;
180: }
181:
182: /** A reference to the element participating in the action. This
183: * may be <code>null</code> if the change was an operation like
184: * <code>clear()</code>.
185: * @return the element added or removed from the collection.
186: */
187: public Object getElement() {
188: return element;
189: }
190:
191: /** Indicates whether the collection was changed as a result of the
192: * action.
193: * @return <code>true</code> if the collection was changed,
194: * <code>false</code> otherwise.
195: */
196: public boolean isChanged() {
197: return changed;
198: }
199:
200: /**
201: * The "parameter" is an indication of the index into the
202: * collection or the number of copies added or removed by the operation.
203: * In many cases, the "parameter" will not be set, in which
204: * case it takes on the value <code>NOT_SET</code>.
205: * @return the index, number of copies, or <code>NOT_SET</code>
206: */
207: public int getParameter() {
208: return parameter;
209: }
210: }
|