📄 vetoablechangesupport.java
字号:
/* VetoableChangeSupport.java -- support to manage vetoable change listeners Copyright (C) 1998, 1999, 2000, 2002 Free Software Foundation, Inc.This file is part of GNU Classpath.GNU Classpath is free software; you can redistribute it and/or modifyit under the terms of the GNU General Public License as published bythe 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, butWITHOUT ANY WARRANTY; without even the implied warranty ofMERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNUGeneral Public License for more details.You should have received a copy of the GNU General Public Licensealong with GNU Classpath; see the file COPYING. If not, write to theFree Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA02111-1307 USA.Linking this library statically or dynamically with other modules ismaking a combined work based on this library. Thus, the terms andconditions of the GNU General Public License cover the wholecombination.As a special exception, the copyright holders of this library give youpermission to link this library with independent modules to produce anexecutable, regardless of the license terms of these independentmodules, and to copy and distribute the resulting executable underterms of your choice, provided that you also meet, for each linkedindependent module, the terms and conditions of the license of thatmodule. An independent module is a module which is not derived fromor based on this library. If you modify this library, you may extendthis exception to your version of the library, but you are notobligated to do so. If you do not wish to do so, delete thisexception statement from your version. */package java.beans;import java.io.IOException;import java.io.ObjectInputStream;import java.io.ObjectOutputStream;import java.io.Serializable;import java.util.ArrayList;import java.util.Arrays;import java.util.Hashtable;import java.util.Iterator;import java.util.Map.Entry;import java.util.Vector;/** * VetoableChangeSupport makes it easy to fire vetoable change events and * handle listeners. It allows chaining of listeners, as well as filtering * by property name. In addition, it will serialize only those listeners * which are serializable, ignoring the others without problem. This class * is thread-safe. * * @author John Keiser * @author Eric Blake <ebb9@email.byu.edu> * @since 1.1 * @status updated to 1.4 */public class VetoableChangeSupport implements Serializable{ /** * Compatible with JDK 1.1+. */ private static final long serialVersionUID = -5090210921595982017L; /** * Maps property names (String) to named listeners (VetoableChangeSupport). * If this is a child instance, this field will be null. * * @serial the map of property names to named listener managers * @since 1.2 */ private Hashtable children; /** * The non-null source object for any generated events. * * @serial the event source */ private final Object source; /** * A field to compare serialization versions - this class uses version 2. * * @serial the serialization format */ private final int vetoableChangeSupportSerializedDataVersion = 2; /** * The list of all registered vetoable listeners. If this instance was * created by user code, this only holds the global listeners (ie. not tied * to a name), and may be null. If it was created by this class, as a * helper for named properties, then this vector will be non-null, and this * instance appears as a value in the <code>children</code> hashtable of * another instance, so that the listeners are tied to the key of that * hashtable entry. */ private transient Vector listeners; /** * Create a VetoableChangeSupport to work with a specific source bean. * * @param source the source bean to use * @throws NullPointerException if source is null */ public VetoableChangeSupport(Object source) { this.source = source; if (source == null) throw new NullPointerException(); } /** * Adds a VetoableChangeListener to the list of global listeners. All * vetoable change events will be sent to this listener. The listener add * is not unique: that is, <em>n</em> adds with the same listener will * result in <em>n</em> events being sent to that listener for every * vetoable change. Adding a null listener may cause a NullPointerException * down the road. This method will unwrap a VetoableChangeListenerProxy, * registering the underlying delegate to the named property list. * * @param l the listener to add */ public synchronized void addVetoableChangeListener(VetoableChangeListener l) { if (l instanceof VetoableChangeListenerProxy) { VetoableChangeListenerProxy p = (VetoableChangeListenerProxy) l; addVetoableChangeListener(p.propertyName, (VetoableChangeListener) p.getListener()); } else { if (listeners == null) listeners = new Vector(); listeners.add(l); } } /** * Removes a VetoableChangeListener from the list of global listeners. If * any specific properties are being listened on, they must be deregistered * by themselves; this will only remove the general listener to all * properties. If <code>add()</code> has been called multiple times for a * particular listener, <code>remove()</code> will have to be called the * same number of times to deregister it. This method will unwrap a * VetoableChangeListenerProxy, removing the underlying delegate from the * named property list. * * @param l the listener to remove */ public synchronized void removeVetoableChangeListener(VetoableChangeListener l) { if (l instanceof VetoableChangeListenerProxy) { VetoableChangeListenerProxy p = (VetoableChangeListenerProxy) l; removeVetoableChangeListener(p.propertyName, (VetoableChangeListener) p.getListener()); } else if (listeners != null) { listeners.remove(l); if (listeners.isEmpty()) listeners = null; } } /** * Returns an array of all registered vetoable change listeners. Those that * were registered under a name will be wrapped in a * <code>VetoableChangeListenerProxy</code>, so you must check whether the * listener is an instance of the proxy class in order to see what name the * real listener is registered under. If there are no registered listeners, * this returns an empty array. * * @return the array of registered listeners * @see VetoableChangeListenerProxy * @since 1.4 */ public synchronized VetoableChangeListener[] getVetoableChangeListeners() { ArrayList list = new ArrayList(); if (listeners != null) list.addAll(listeners); if (children != null) { int i = children.size(); Iterator iter = children.entrySet().iterator(); while (--i >= 0) { Entry e = (Entry) iter.next(); String name = (String) e.getKey(); Vector v = ((VetoableChangeSupport) e.getValue()).listeners; int j = v.size(); while (--j >= 0) list.add(new VetoableChangeListenerProxy (name, (VetoableChangeListener) v.get(j))); } } return (VetoableChangeListener[]) list.toArray(new VetoableChangeListener[list.size()]); } /** * Adds a VetoableChangeListener listening on the specified property. Events * will be sent to the listener only if the property name matches. The * listener add is not unique; that is, <em>n</em> adds on a particular * property for a particular listener will result in <em>n</em> events * being sent to that listener when that property is changed. The effect is * cumulative, too; if you are registered to listen to receive events on * all vetoable changes, and then you register on a particular property, * you will receive change events for that property twice. Adding a null * listener may cause a NullPointerException down the road. This method * will unwrap a VetoableChangeListenerProxy, registering the underlying * delegate to the named property list if the names match, and discarding * it otherwise. * * @param propertyName the name of the property to listen on * @param l the listener to add * @throws NullPointerException if propertyName is null */ public synchronized void addVetoableChangeListener(String propertyName, VetoableChangeListener l) { while (l instanceof VetoableChangeListenerProxy) { VetoableChangeListenerProxy p = (VetoableChangeListenerProxy) l; if (propertyName == null ? p.propertyName != null : ! propertyName.equals(p.propertyName)) return; l = (VetoableChangeListener) p.getListener(); } VetoableChangeSupport s = null; if (children == null) children = new Hashtable(); else s = (VetoableChangeSupport) children.get(propertyName); if (s == null) { s = new VetoableChangeSupport(source); s.listeners = new Vector(); children.put(propertyName, s); } s.listeners.add(l); } /** * Removes a VetoableChangeListener from listening to a specific property. * If <code>add()</code> has been called multiple times for a particular * listener on a property, <code>remove()</code> will have to be called the * same number of times to deregister it. This method will unwrap a * VetoableChangeListenerProxy, removing the underlying delegate from the * named property list if the names match. * * @param propertyName the property to stop listening on * @param l the listener to remove * @throws NullPointerException if propertyName is null */ public synchronized void removeVetoableChangeListener(String propertyName, VetoableChangeListener l)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -