| /* Observable.java -- an object to be observed |
| Copyright (C) 1999, 2000, 2001, 2002, 2005 Free Software Foundation, Inc. |
| |
| This file is part of GNU Classpath. |
| |
| GNU Classpath is free software; you can redistribute it and/or modify |
| it under the terms of the GNU General Public License as published by |
| the Free Software Foundation; either version 2, or (at your option) |
| any later version. |
| |
| GNU Classpath is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
| General Public License for more details. |
| |
| You should have received a copy of the GNU General Public License |
| along with GNU Classpath; see the file COPYING. If not, write to the |
| Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA |
| 02111-1307 USA. |
| |
| Linking this library statically or dynamically with other modules is |
| making a combined work based on this library. Thus, the terms and |
| conditions of the GNU General Public License cover the whole |
| combination. |
| |
| As a special exception, the copyright holders of this library give you |
| permission to link this library with independent modules to produce an |
| executable, regardless of the license terms of these independent |
| modules, and to copy and distribute the resulting executable under |
| terms of your choice, provided that you also meet, for each linked |
| independent module, the terms and conditions of the license of that |
| module. An independent module is a module which is not derived from |
| or based on this library. If you modify this library, you may extend |
| this exception to your version of the library, but you are not |
| obligated to do so. If you do not wish to do so, delete this |
| exception statement from your version. */ |
| |
| |
| package java.util; |
| |
| /** |
| * This class represents an object which is observable. Other objects may |
| * register their intent to be notified when this object changes; and when |
| * this object does change, it will trigger the <code>update</code> method |
| * of each observer. |
| * |
| * Note that the <code>notifyObservers()</code> method of this class is |
| * unrelated to the <code>notify()</code> of Object. |
| * |
| * @author Warren Levy (warrenl@cygnus.com) |
| * @author Eric Blake (ebb9@email.byu.edu) |
| * @see Observer |
| * @status updated to 1.4 |
| */ |
| public class Observable |
| { |
| /** Tracks whether this object has changed. */ |
| private boolean changed; |
| |
| /* List of the Observers registered as interested in this Observable. */ |
| private LinkedHashSet observers; |
| |
| /** |
| * Constructs an Observable with zero Observers. |
| */ |
| public Observable() |
| { |
| observers = new LinkedHashSet(); |
| } |
| |
| /** |
| * Adds an Observer. If the observer was already added this method does |
| * nothing. |
| * |
| * @param observer Observer to add |
| * @throws NullPointerException if observer is null |
| */ |
| public synchronized void addObserver(Observer observer) |
| { |
| observers.add(observer); |
| } |
| |
| /** |
| * Reset this Observable's state to unchanged. This is called automatically |
| * by <code>notifyObservers</code> once all observers have been notified. |
| * |
| * @see #notifyObservers() |
| */ |
| protected synchronized void clearChanged() |
| { |
| changed = false; |
| } |
| |
| /** |
| * Returns the number of observers for this object. |
| * |
| * @return number of Observers for this |
| */ |
| public synchronized int countObservers() |
| { |
| return observers.size(); |
| } |
| |
| /** |
| * Deletes an Observer of this Observable. |
| * |
| * @param victim Observer to delete |
| */ |
| public synchronized void deleteObserver(Observer victim) |
| { |
| observers.remove(victim); |
| } |
| |
| /** |
| * Deletes all Observers of this Observable. |
| */ |
| public synchronized void deleteObservers() |
| { |
| observers.clear(); |
| } |
| |
| /** |
| * True if <code>setChanged</code> has been called more recently than |
| * <code>clearChanged</code>. |
| * |
| * @return whether or not this Observable has changed |
| */ |
| public synchronized boolean hasChanged() |
| { |
| return changed; |
| } |
| |
| /** |
| * If the Observable has actually changed then tell all Observers about it, |
| * then reset state to unchanged. |
| * |
| * @see #notifyObservers(Object) |
| * @see Observer#update(Observable, Object) |
| */ |
| public void notifyObservers() |
| { |
| notifyObservers(null); |
| } |
| |
| /** |
| * If the Observable has actually changed then tell all Observers about it, |
| * then reset state to unchanged. Note that though the order of |
| * notification is unspecified in subclasses, in Observable it is in the |
| * order of registration. |
| * |
| * @param obj argument to Observer's update method |
| * @see Observer#update(Observable, Object) |
| */ |
| public void notifyObservers(Object obj) |
| { |
| if (! hasChanged()) |
| return; |
| // Create clone inside monitor, as that is relatively fast and still |
| // important to keep threadsafe, but update observers outside of the |
| // lock since update() can call arbitrary code. |
| Set s; |
| synchronized (this) |
| { |
| s = (Set) observers.clone(); |
| } |
| int i = s.size(); |
| Iterator iter = s.iterator(); |
| while (--i >= 0) |
| ((Observer) iter.next()).update(this, obj); |
| clearChanged(); |
| } |
| |
| /** |
| * Marks this Observable as having changed. |
| */ |
| protected synchronized void setChanged() |
| { |
| changed = true; |
| } |
| } |