001: /*
002: * @(#)Observable.java 1.34 01/12/03
003: *
004: * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
005: * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
006: */
007:
008: package de.jwic.util;
009:
010: import java.io.Serializable;
011: import java.util.Vector;
012:
013: /**
014: * This is a serializable version of the java.util.Observable class. It is
015: * recommend to use this version instead of the original one as the
016: * original one does not support serialization.
017: *
018: * @author Florian Lippisch (original from Chris Warth)
019: * @see java.util.Observable
020: * @see de.jwic.util.SerObserver
021: */
022: public class SerObservable implements Serializable {
023:
024: private static final long serialVersionUID = 1L;
025:
026: private boolean changed = false;
027: private Vector obs;
028:
029: /** Construct an Observable with zero Observers. */
030:
031: public SerObservable() {
032: obs = new Vector();
033: }
034:
035: /**
036: * Adds an observer to the set of observers for this object, provided
037: * that it is not the same as some observer already in the set.
038: * The order in which notifications will be delivered to multiple
039: * observers is not specified. See the class comment.
040: *
041: * @param o an observer to be added.
042: * @throws NullPointerException if the parameter o is null.
043: */
044: public synchronized void addObserver(SerObserver o) {
045: if (o == null)
046: throw new NullPointerException();
047: if (!obs.contains(o)) {
048: obs.addElement(o);
049: }
050: }
051:
052: /**
053: * Deletes an observer from the set of observers of this object.
054: *
055: * @param o the observer to be deleted.
056: */
057: public synchronized void deleteObserver(SerObserver o) {
058: obs.removeElement(o);
059: }
060:
061: /**
062: * If this object has changed, as indicated by the
063: * <code>hasChanged</code> method, then notify all of its observers
064: * and then call the <code>clearChanged</code> method to
065: * indicate that this object has no longer changed.
066: * <p>
067: * Each observer has its <code>update</code> method called with two
068: * arguments: this observable object and <code>null</code>. In other
069: * words, this method is equivalent to:
070: * <blockquote><tt>
071: * notifyObservers(null)</tt></blockquote>
072: *
073: * @see java.util.Observable#clearChanged()
074: * @see java.util.Observable#hasChanged()
075: * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
076: */
077: public void notifyObservers() {
078: notifyObservers(null);
079: }
080:
081: /**
082: * If this object has changed, as indicated by the
083: * <code>hasChanged</code> method, then notify all of its observers
084: * and then call the <code>clearChanged</code> method to indicate
085: * that this object has no longer changed.
086: * <p>
087: * Each observer has its <code>update</code> method called with two
088: * arguments: this observable object and the <code>arg</code> argument.
089: *
090: * @param arg any object.
091: * @see java.util.Observable#clearChanged()
092: * @see java.util.Observable#hasChanged()
093: * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
094: */
095: public void notifyObservers(Object arg) {
096: /*
097: * a temporary array buffer, used as a snapshot of the state of
098: * current Observers.
099: */
100: Object[] arrLocal;
101:
102: synchronized (this ) {
103: /* We don't want the Observer doing callbacks into
104: * arbitrary code while holding its own Monitor.
105: * The code where we extract each Observable from
106: * the Vector and store the state of the Observer
107: * needs synchronization, but notifying observers
108: * does not (should not). The worst result of any
109: * potential race-condition here is that:
110: * 1) a newly-added Observer will miss a
111: * notification in progress
112: * 2) a recently unregistered Observer will be
113: * wrongly notified when it doesn't care
114: */
115: if (!changed)
116: return;
117: arrLocal = obs.toArray();
118: clearChanged();
119: }
120:
121: for (int i = arrLocal.length - 1; i >= 0; i--)
122: ((SerObserver) arrLocal[i]).update(this , arg);
123: }
124:
125: /**
126: * Clears the observer list so that this object no longer has any observers.
127: */
128: public synchronized void deleteObservers() {
129: obs.removeAllElements();
130: }
131:
132: /**
133: * Marks this <tt>Observable</tt> object as having been changed; the
134: * <tt>hasChanged</tt> method will now return <tt>true</tt>.
135: */
136: protected synchronized void setChanged() {
137: changed = true;
138: }
139:
140: /**
141: * Indicates that this object has no longer changed, or that it has
142: * already notified all of its observers of its most recent change,
143: * so that the <tt>hasChanged</tt> method will now return <tt>false</tt>.
144: * This method is called automatically by the
145: * <code>notifyObservers</code> methods.
146: *
147: * @see java.util.Observable#notifyObservers()
148: * @see java.util.Observable#notifyObservers(java.lang.Object)
149: */
150: protected synchronized void clearChanged() {
151: changed = false;
152: }
153:
154: /**
155: * Tests if this object has changed.
156: *
157: * @return <code>true</code> if and only if the <code>setChanged</code>
158: * method has been called more recently than the
159: * <code>clearChanged</code> method on this object;
160: * <code>false</code> otherwise.
161: * @see java.util.Observable#clearChanged()
162: * @see java.util.Observable#setChanged()
163: */
164: public synchronized boolean hasChanged() {
165: return changed;
166: }
167:
168: /**
169: * Returns the number of observers of this <tt>Observable</tt> object.
170: *
171: * @return the number of observers of this object.
172: */
173: public synchronized int countObservers() {
174: return obs.size();
175: }
176: }
|