Frames | No Frames |
1: /* Observable.java -- an object to be observed 2: Copyright (C) 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc. 3: 4: This file is part of GNU Classpath. 5: 6: GNU Classpath is free software; you can redistribute it and/or modify 7: it under the terms of the GNU General Public License as published by 8: the Free Software Foundation; either version 2, or (at your option) 9: any later version. 10: 11: GNU Classpath is distributed in the hope that it will be useful, but 12: WITHOUT ANY WARRANTY; without even the implied warranty of 13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14: General Public License for more details. 15: 16: You should have received a copy of the GNU General Public License 17: along with GNU Classpath; see the file COPYING. If not, write to the 18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 19: 02110-1301 USA. 20: 21: Linking this library statically or dynamically with other modules is 22: making a combined work based on this library. Thus, the terms and 23: conditions of the GNU General Public License cover the whole 24: combination. 25: 26: As a special exception, the copyright holders of this library give you 27: permission to link this library with independent modules to produce an 28: executable, regardless of the license terms of these independent 29: modules, and to copy and distribute the resulting executable under 30: terms of your choice, provided that you also meet, for each linked 31: independent module, the terms and conditions of the license of that 32: module. An independent module is a module which is not derived from 33: or based on this library. If you modify this library, you may extend 34: this exception to your version of the library, but you are not 35: obligated to do so. If you do not wish to do so, delete this 36: exception statement from your version. */ 37: 38: 39: package java.util; 40: 41: /** 42: * This class represents an object which is observable. Other objects may 43: * register their intent to be notified when this object changes; and when 44: * this object does change, it will trigger the <code>update</code> method 45: * of each observer. 46: * 47: * Note that the <code>notifyObservers()</code> method of this class is 48: * unrelated to the <code>notify()</code> of Object. 49: * 50: * @author Warren Levy (warrenl@cygnus.com) 51: * @author Eric Blake (ebb9@email.byu.edu) 52: * @see Observer 53: * @status updated to 1.4 54: */ 55: public class Observable 56: { 57: /** Tracks whether this object has changed. */ 58: private boolean changed; 59: 60: /* List of the Observers registered as interested in this Observable. */ 61: private LinkedHashSet observers; 62: 63: /** 64: * Constructs an Observable with zero Observers. 65: */ 66: public Observable() 67: { 68: observers = new LinkedHashSet(); 69: } 70: 71: /** 72: * Adds an Observer. If the observer was already added this method does 73: * nothing. 74: * 75: * @param observer Observer to add 76: * @throws NullPointerException if observer is null 77: */ 78: public synchronized void addObserver(Observer observer) 79: { 80: if (observer == null) 81: throw new NullPointerException("can't add null observer"); 82: observers.add(observer); 83: } 84: 85: /** 86: * Reset this Observable's state to unchanged. This is called automatically 87: * by <code>notifyObservers</code> once all observers have been notified. 88: * 89: * @see #notifyObservers() 90: */ 91: protected synchronized void clearChanged() 92: { 93: changed = false; 94: } 95: 96: /** 97: * Returns the number of observers for this object. 98: * 99: * @return number of Observers for this 100: */ 101: public synchronized int countObservers() 102: { 103: return observers.size(); 104: } 105: 106: /** 107: * Deletes an Observer of this Observable. 108: * 109: * @param victim Observer to delete 110: */ 111: public synchronized void deleteObserver(Observer victim) 112: { 113: observers.remove(victim); 114: } 115: 116: /** 117: * Deletes all Observers of this Observable. 118: */ 119: public synchronized void deleteObservers() 120: { 121: observers.clear(); 122: } 123: 124: /** 125: * True if <code>setChanged</code> has been called more recently than 126: * <code>clearChanged</code>. 127: * 128: * @return whether or not this Observable has changed 129: */ 130: public synchronized boolean hasChanged() 131: { 132: return changed; 133: } 134: 135: /** 136: * If the Observable has actually changed then tell all Observers about it, 137: * then reset state to unchanged. 138: * 139: * @see #notifyObservers(Object) 140: * @see Observer#update(Observable, Object) 141: */ 142: public void notifyObservers() 143: { 144: notifyObservers(null); 145: } 146: 147: /** 148: * If the Observable has actually changed then tell all Observers about it, 149: * then reset state to unchanged. Note that though the order of 150: * notification is unspecified in subclasses, in Observable it is in the 151: * order of registration. 152: * 153: * @param obj argument to Observer's update method 154: * @see Observer#update(Observable, Object) 155: */ 156: public void notifyObservers(Object obj) 157: { 158: if (! hasChanged()) 159: return; 160: // Create clone inside monitor, as that is relatively fast and still 161: // important to keep threadsafe, but update observers outside of the 162: // lock since update() can call arbitrary code. 163: Set s; 164: synchronized (this) 165: { 166: s = (Set) observers.clone(); 167: } 168: int i = s.size(); 169: Iterator iter = s.iterator(); 170: while (--i >= 0) 171: ((Observer) iter.next()).update(this, obj); 172: clearChanged(); 173: } 174: 175: /** 176: * Marks this Observable as having changed. 177: */ 178: protected synchronized void setChanged() 179: { 180: changed = true; 181: } 182: }