001 /*
002 * Copyright 1994-2004 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.util;
027
028 /**
029 * This class represents an observable object, or "data"
030 * in the model-view paradigm. It can be subclassed to represent an
031 * object that the application wants to have observed.
032 * <p>
033 * An observable object can have one or more observers. An observer
034 * may be any object that implements interface <tt>Observer</tt>. After an
035 * observable instance changes, an application calling the
036 * <code>Observable</code>'s <code>notifyObservers</code> method
037 * causes all of its observers to be notified of the change by a call
038 * to their <code>update</code> method.
039 * <p>
040 * The order in which notifications will be delivered is unspecified.
041 * The default implementation provided in the Observable class will
042 * notify Observers in the order in which they registered interest, but
043 * subclasses may change this order, use no guaranteed order, deliver
044 * notifications on separate threads, or may guarantee that their
045 * subclass follows this order, as they choose.
046 * <p>
047 * Note that this notification mechanism is has nothing to do with threads
048 * and is completely separate from the <tt>wait</tt> and <tt>notify</tt>
049 * mechanism of class <tt>Object</tt>.
050 * <p>
051 * When an observable object is newly created, its set of observers is
052 * empty. Two observers are considered the same if and only if the
053 * <tt>equals</tt> method returns true for them.
054 *
055 * @author Chris Warth
056 * @version 1.45, 05/05/07
057 * @see java.util.Observable#notifyObservers()
058 * @see java.util.Observable#notifyObservers(java.lang.Object)
059 * @see java.util.Observer
060 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
061 * @since JDK1.0
062 */
063 public class Observable {
064 private boolean changed = false;
065 private Vector obs;
066
067 /** Construct an Observable with zero Observers. */
068
069 public Observable() {
070 obs = new Vector();
071 }
072
073 /**
074 * Adds an observer to the set of observers for this object, provided
075 * that it is not the same as some observer already in the set.
076 * The order in which notifications will be delivered to multiple
077 * observers is not specified. See the class comment.
078 *
079 * @param o an observer to be added.
080 * @throws NullPointerException if the parameter o is null.
081 */
082 public synchronized void addObserver(Observer o) {
083 if (o == null)
084 throw new NullPointerException();
085 if (!obs.contains(o)) {
086 obs.addElement(o);
087 }
088 }
089
090 /**
091 * Deletes an observer from the set of observers of this object.
092 * Passing <CODE>null</CODE> to this method will have no effect.
093 * @param o the observer to be deleted.
094 */
095 public synchronized void deleteObserver(Observer o) {
096 obs.removeElement(o);
097 }
098
099 /**
100 * If this object has changed, as indicated by the
101 * <code>hasChanged</code> method, then notify all of its observers
102 * and then call the <code>clearChanged</code> method to
103 * indicate that this object has no longer changed.
104 * <p>
105 * Each observer has its <code>update</code> method called with two
106 * arguments: this observable object and <code>null</code>. In other
107 * words, this method is equivalent to:
108 * <blockquote><tt>
109 * notifyObservers(null)</tt></blockquote>
110 *
111 * @see java.util.Observable#clearChanged()
112 * @see java.util.Observable#hasChanged()
113 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
114 */
115 public void notifyObservers() {
116 notifyObservers(null);
117 }
118
119 /**
120 * If this object has changed, as indicated by the
121 * <code>hasChanged</code> method, then notify all of its observers
122 * and then call the <code>clearChanged</code> method to indicate
123 * that this object has no longer changed.
124 * <p>
125 * Each observer has its <code>update</code> method called with two
126 * arguments: this observable object and the <code>arg</code> argument.
127 *
128 * @param arg any object.
129 * @see java.util.Observable#clearChanged()
130 * @see java.util.Observable#hasChanged()
131 * @see java.util.Observer#update(java.util.Observable, java.lang.Object)
132 */
133 public void notifyObservers(Object arg) {
134 /*
135 * a temporary array buffer, used as a snapshot of the state of
136 * current Observers.
137 */
138 Object[] arrLocal;
139
140 synchronized (this ) {
141 /* We don't want the Observer doing callbacks into
142 * arbitrary code while holding its own Monitor.
143 * The code where we extract each Observable from
144 * the Vector and store the state of the Observer
145 * needs synchronization, but notifying observers
146 * does not (should not). The worst result of any
147 * potential race-condition here is that:
148 * 1) a newly-added Observer will miss a
149 * notification in progress
150 * 2) a recently unregistered Observer will be
151 * wrongly notified when it doesn't care
152 */
153 if (!changed)
154 return;
155 arrLocal = obs.toArray();
156 clearChanged();
157 }
158
159 for (int i = arrLocal.length - 1; i >= 0; i--)
160 ((Observer) arrLocal[i]).update(this , arg);
161 }
162
163 /**
164 * Clears the observer list so that this object no longer has any observers.
165 */
166 public synchronized void deleteObservers() {
167 obs.removeAllElements();
168 }
169
170 /**
171 * Marks this <tt>Observable</tt> object as having been changed; the
172 * <tt>hasChanged</tt> method will now return <tt>true</tt>.
173 */
174 protected synchronized void setChanged() {
175 changed = true;
176 }
177
178 /**
179 * Indicates that this object has no longer changed, or that it has
180 * already notified all of its observers of its most recent change,
181 * so that the <tt>hasChanged</tt> method will now return <tt>false</tt>.
182 * This method is called automatically by the
183 * <code>notifyObservers</code> methods.
184 *
185 * @see java.util.Observable#notifyObservers()
186 * @see java.util.Observable#notifyObservers(java.lang.Object)
187 */
188 protected synchronized void clearChanged() {
189 changed = false;
190 }
191
192 /**
193 * Tests if this object has changed.
194 *
195 * @return <code>true</code> if and only if the <code>setChanged</code>
196 * method has been called more recently than the
197 * <code>clearChanged</code> method on this object;
198 * <code>false</code> otherwise.
199 * @see java.util.Observable#clearChanged()
200 * @see java.util.Observable#setChanged()
201 */
202 public synchronized boolean hasChanged() {
203 return changed;
204 }
205
206 /**
207 * Returns the number of observers of this <tt>Observable</tt> object.
208 *
209 * @return the number of observers of this object.
210 */
211 public synchronized int countObservers() {
212 return obs.size();
213 }
214 }
|