提交 acc7457f 编写于 作者: M malenkov

6630275: The spec on VetoableChangeSupport.fireVetoableChange should be updated

Reviewed-by: peterz, rupashka
上级 91debf03
/* /*
* Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -208,91 +208,91 @@ public class PropertyChangeSupport implements Serializable { ...@@ -208,91 +208,91 @@ public class PropertyChangeSupport implements Serializable {
} }
/** /**
* Report a bound property update to any registered listeners. * Reports a bound property update to listeners
* No event is fired if old and new are equal and non-null. * that have been registered to track updates of
* * all properties or a property with the specified name.
* <p>
* No event is fired if old and new values are equal and non-null.
* <p> * <p>
* This is merely a convenience wrapper around the more general * This is merely a convenience wrapper around the more general
* firePropertyChange method that takes {@code * {@link #firePropertyChange(PropertyChangeEvent)} method.
* PropertyChangeEvent} value.
* *
* @param propertyName The programmatic name of the property * @param propertyName the programmatic name of the property that was changed
* that was changed. * @param oldValue the old value of the property
* @param oldValue The old value of the property. * @param newValue the new value of the property
* @param newValue The new value of the property.
*/ */
public void firePropertyChange(String propertyName, public void firePropertyChange(String propertyName, Object oldValue, Object newValue) {
Object oldValue, Object newValue) { if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
if (oldValue != null && newValue != null && oldValue.equals(newValue)) { firePropertyChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
return;
} }
firePropertyChange(new PropertyChangeEvent(source, propertyName,
oldValue, newValue));
} }
/** /**
* Report an int bound property update to any registered listeners. * Reports an integer bound property update to listeners
* No event is fired if old and new are equal. * that have been registered to track updates of
* all properties or a property with the specified name.
* <p>
* No event is fired if old and new values are equal.
* <p> * <p>
* This is merely a convenience wrapper around the more general * This is merely a convenience wrapper around the more general
* firePropertyChange method that takes Object values. * {@link #firePropertyChange(String, Object, Object)} method.
* *
* @param propertyName The programmatic name of the property * @param propertyName the programmatic name of the property that was changed
* that was changed. * @param oldValue the old value of the property
* @param oldValue The old value of the property. * @param newValue the new value of the property
* @param newValue The new value of the property.
*/ */
public void firePropertyChange(String propertyName, public void firePropertyChange(String propertyName, int oldValue, int newValue) {
int oldValue, int newValue) { if (oldValue != newValue) {
if (oldValue == newValue) { firePropertyChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
return;
} }
firePropertyChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
} }
/** /**
* Report a boolean bound property update to any registered listeners. * Reports a boolean bound property update to listeners
* No event is fired if old and new are equal. * that have been registered to track updates of
* all properties or a property with the specified name.
* <p>
* No event is fired if old and new values are equal.
* <p> * <p>
* This is merely a convenience wrapper around the more general * This is merely a convenience wrapper around the more general
* firePropertyChange method that takes Object values. * {@link #firePropertyChange(String, Object, Object)} method.
* *
* @param propertyName The programmatic name of the property * @param propertyName the programmatic name of the property that was changed
* that was changed. * @param oldValue the old value of the property
* @param oldValue The old value of the property. * @param newValue the new value of the property
* @param newValue The new value of the property.
*/ */
public void firePropertyChange(String propertyName, public void firePropertyChange(String propertyName, boolean oldValue, boolean newValue) {
boolean oldValue, boolean newValue) { if (oldValue != newValue) {
if (oldValue == newValue) { firePropertyChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
return;
} }
firePropertyChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
} }
/** /**
* Fire an existing PropertyChangeEvent to any registered listeners. * Fires a property change event to listeners
* No event is fired if the given event's old and new values are * that have been registered to track updates of
* equal and non-null. * all properties or a property with the specified name.
* @param evt The PropertyChangeEvent object. * <p>
* No event is fired if the given event's old and new values are equal and non-null.
*
* @param event the {@code PropertyChangeEvent} to be fired
*/ */
public void firePropertyChange(PropertyChangeEvent evt) { public void firePropertyChange(PropertyChangeEvent event) {
Object oldValue = evt.getOldValue(); Object oldValue = event.getOldValue();
Object newValue = evt.getNewValue(); Object newValue = event.getNewValue();
String propertyName = evt.getPropertyName(); if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
if (oldValue != null && newValue != null && oldValue.equals(newValue)) { String name = event.getPropertyName();
return;
}
PropertyChangeListener[] common = this.map.get(null);
PropertyChangeListener[] named = (propertyName != null)
? this.map.get(propertyName)
: null;
fire(common, evt); PropertyChangeListener[] common = this.map.get(null);
fire(named, evt); PropertyChangeListener[] named = (name != null)
? this.map.get(name)
: null;
fire(common, event);
fire(named, event);
}
} }
private void fire(PropertyChangeListener[] listeners, PropertyChangeEvent event) { private static void fire(PropertyChangeListener[] listeners, PropertyChangeEvent event) {
if (listeners != null) { if (listeners != null) {
for (PropertyChangeListener listener : listeners) { for (PropertyChangeListener listener : listeners) {
listener.propertyChange(event); listener.propertyChange(event);
...@@ -301,78 +301,69 @@ public class PropertyChangeSupport implements Serializable { ...@@ -301,78 +301,69 @@ public class PropertyChangeSupport implements Serializable {
} }
/** /**
* Report a bound indexed property update to any registered * Reports a bound indexed property update to listeners
* listeners. * that have been registered to track updates of
* all properties or a property with the specified name.
* <p> * <p>
* No event is fired if old and new values are equal * No event is fired if old and new values are equal and non-null.
* and non-null.
*
* <p> * <p>
* This is merely a convenience wrapper around the more general * This is merely a convenience wrapper around the more general
* firePropertyChange method that takes {@code PropertyChangeEvent} value. * {@link #firePropertyChange(PropertyChangeEvent)} method.
* *
* @param propertyName The programmatic name of the property that * @param propertyName the programmatic name of the property that was changed
* was changed. * @param index the index of the property element that was changed
* @param index index of the property element that was changed. * @param oldValue the old value of the property
* @param oldValue The old value of the property. * @param newValue the new value of the property
* @param newValue The new value of the property.
* @since 1.5 * @since 1.5
*/ */
public void fireIndexedPropertyChange(String propertyName, int index, public void fireIndexedPropertyChange(String propertyName, int index, Object oldValue, Object newValue) {
Object oldValue, Object newValue) { if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
firePropertyChange(new IndexedPropertyChangeEvent firePropertyChange(new IndexedPropertyChangeEvent(source, propertyName, oldValue, newValue, index));
(source, propertyName, oldValue, newValue, index)); }
} }
/** /**
* Report an <code>int</code> bound indexed property update to any registered * Reports an integer bound indexed property update to listeners
* listeners. * that have been registered to track updates of
* all properties or a property with the specified name.
* <p> * <p>
* No event is fired if old and new values are equal. * No event is fired if old and new values are equal.
* <p> * <p>
* This is merely a convenience wrapper around the more general * This is merely a convenience wrapper around the more general
* fireIndexedPropertyChange method which takes Object values. * {@link #fireIndexedPropertyChange(String, int, Object, Object)} method.
* *
* @param propertyName The programmatic name of the property that * @param propertyName the programmatic name of the property that was changed
* was changed. * @param index the index of the property element that was changed
* @param index index of the property element that was changed. * @param oldValue the old value of the property
* @param oldValue The old value of the property. * @param newValue the new value of the property
* @param newValue The new value of the property.
* @since 1.5 * @since 1.5
*/ */
public void fireIndexedPropertyChange(String propertyName, int index, public void fireIndexedPropertyChange(String propertyName, int index, int oldValue, int newValue) {
int oldValue, int newValue) { if (oldValue != newValue) {
if (oldValue == newValue) { fireIndexedPropertyChange(propertyName, index, Integer.valueOf(oldValue), Integer.valueOf(newValue));
return;
} }
fireIndexedPropertyChange(propertyName, index,
Integer.valueOf(oldValue),
Integer.valueOf(newValue));
} }
/** /**
* Report a <code>boolean</code> bound indexed property update to any * Reports a boolean bound indexed property update to listeners
* registered listeners. * that have been registered to track updates of
* all properties or a property with the specified name.
* <p> * <p>
* No event is fired if old and new values are equal. * No event is fired if old and new values are equal.
* <p> * <p>
* This is merely a convenience wrapper around the more general * This is merely a convenience wrapper around the more general
* fireIndexedPropertyChange method which takes Object values. * {@link #fireIndexedPropertyChange(String, int, Object, Object)} method.
* *
* @param propertyName The programmatic name of the property that * @param propertyName the programmatic name of the property that was changed
* was changed. * @param index the index of the property element that was changed
* @param index index of the property element that was changed. * @param oldValue the old value of the property
* @param oldValue The old value of the property. * @param newValue the new value of the property
* @param newValue The new value of the property.
* @since 1.5 * @since 1.5
*/ */
public void fireIndexedPropertyChange(String propertyName, int index, public void fireIndexedPropertyChange(String propertyName, int index, boolean oldValue, boolean newValue) {
boolean oldValue, boolean newValue) { if (oldValue != newValue) {
if (oldValue == newValue) { fireIndexedPropertyChange(propertyName, index, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
return;
} }
fireIndexedPropertyChange(propertyName, index, Boolean.valueOf(oldValue),
Boolean.valueOf(newValue));
} }
/** /**
......
/* /*
* Copyright 1996-2006 Sun Microsystems, Inc. All Rights Reserved. * Copyright 1996-2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
* *
* This code is free software; you can redistribute it and/or modify it * This code is free software; you can redistribute it and/or modify it
...@@ -208,126 +208,149 @@ public class VetoableChangeSupport implements Serializable { ...@@ -208,126 +208,149 @@ public class VetoableChangeSupport implements Serializable {
} }
/** /**
* Report a vetoable property update to any registered listeners. If * Reports a constrained property update to listeners
* anyone vetos the change, then fire a new event reverting everyone to * that have been registered to track updates of
* the old value and then rethrow the PropertyVetoException. * all properties or a property with the specified name.
* <p> * <p>
* No event is fired if old and new are equal and non-null. * Any listener can throw a {@code PropertyVetoException} to veto the update.
* If one of the listeners vetoes the update, this method passes
* a new "undo" {@code PropertyChangeEvent} that reverts to the old value
* to all listeners that already confirmed this update
* and throws the {@code PropertyVetoException} again.
* <p>
* No event is fired if old and new values are equal and non-null.
* <p>
* This is merely a convenience wrapper around the more general
* {@link #fireVetoableChange(PropertyChangeEvent)} method.
* *
* @param propertyName The programmatic name of the property * @param propertyName the programmatic name of the property that is about to change
* that is about to change.. * @param oldValue the old value of the property
* @param oldValue The old value of the property. * @param newValue the new value of the property
* @param newValue The new value of the property. * @throws PropertyVetoException if one of listeners vetoes the property update
* @exception PropertyVetoException if the recipient wishes the property
* change to be rolled back.
*/ */
public void fireVetoableChange(String propertyName, public void fireVetoableChange(String propertyName, Object oldValue, Object newValue)
Object oldValue, Object newValue) throws PropertyVetoException {
throws PropertyVetoException { if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
if (oldValue != null && newValue != null && oldValue.equals(newValue)) { fireVetoableChange(new PropertyChangeEvent(this.source, propertyName, oldValue, newValue));
return;
} }
PropertyChangeEvent evt = new PropertyChangeEvent(source, propertyName,
oldValue, newValue);
fireVetoableChange(evt);
} }
/** /**
* Report a int vetoable property update to any registered listeners. * Reports an integer constrained property update to listeners
* No event is fired if old and new are equal. * that have been registered to track updates of
* all properties or a property with the specified name.
* <p>
* Any listener can throw a {@code PropertyVetoException} to veto the update.
* If one of the listeners vetoes the update, this method passes
* a new "undo" {@code PropertyChangeEvent} that reverts to the old value
* to all listeners that already confirmed this update
* and throws the {@code PropertyVetoException} again.
* <p>
* No event is fired if old and new values are equal.
* <p> * <p>
* This is merely a convenience wrapper around the more general * This is merely a convenience wrapper around the more general
* fireVetoableChange method that takes Object values. * {@link #fireVetoableChange(String, Object, Object)} method.
* *
* @param propertyName The programmatic name of the property * @param propertyName the programmatic name of the property that is about to change
* that is about to change. * @param oldValue the old value of the property
* @param oldValue The old value of the property. * @param newValue the new value of the property
* @param newValue The new value of the property. * @throws PropertyVetoException if one of listeners vetoes the property update
*/ */
public void fireVetoableChange(String propertyName, public void fireVetoableChange(String propertyName, int oldValue, int newValue)
int oldValue, int newValue) throws PropertyVetoException {
throws PropertyVetoException { if (oldValue != newValue) {
if (oldValue == newValue) { fireVetoableChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
return;
} }
fireVetoableChange(propertyName, Integer.valueOf(oldValue), Integer.valueOf(newValue));
} }
/** /**
* Report a boolean vetoable property update to any registered listeners. * Reports a boolean constrained property update to listeners
* No event is fired if old and new are equal. * that have been registered to track updates of
* all properties or a property with the specified name.
* <p>
* Any listener can throw a {@code PropertyVetoException} to veto the update.
* If one of the listeners vetoes the update, this method passes
* a new "undo" {@code PropertyChangeEvent} that reverts to the old value
* to all listeners that already confirmed this update
* and throws the {@code PropertyVetoException} again.
* <p>
* No event is fired if old and new values are equal.
* <p> * <p>
* This is merely a convenience wrapper around the more general * This is merely a convenience wrapper around the more general
* fireVetoableChange method that takes Object values. * {@link #fireVetoableChange(String, Object, Object)} method.
* *
* @param propertyName The programmatic name of the property * @param propertyName the programmatic name of the property that is about to change
* that is about to change. * @param oldValue the old value of the property
* @param oldValue The old value of the property. * @param newValue the new value of the property
* @param newValue The new value of the property. * @throws PropertyVetoException if one of listeners vetoes the property update
*/ */
public void fireVetoableChange(String propertyName, public void fireVetoableChange(String propertyName, boolean oldValue, boolean newValue)
boolean oldValue, boolean newValue) throws PropertyVetoException {
throws PropertyVetoException { if (oldValue != newValue) {
if (oldValue == newValue) { fireVetoableChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
return;
} }
fireVetoableChange(propertyName, Boolean.valueOf(oldValue), Boolean.valueOf(newValue));
} }
/** /**
* Fire a vetoable property update to any registered listeners. If * Fires a property change event to listeners
* anyone vetos the change, then fire a new event reverting everyone to * that have been registered to track updates of
* the old value and then rethrow the PropertyVetoException. * all properties or a property with the specified name.
* <p> * <p>
* No event is fired if old and new are equal and non-null. * Any listener can throw a {@code PropertyVetoException} to veto the update.
* If one of the listeners vetoes the update, this method passes
* a new "undo" {@code PropertyChangeEvent} that reverts to the old value
* to all listeners that already confirmed this update
* and throws the {@code PropertyVetoException} again.
* <p>
* No event is fired if the given event's old and new values are equal and non-null.
* *
* @param evt The PropertyChangeEvent to be fired. * @param event the {@code PropertyChangeEvent} to be fired
* @exception PropertyVetoException if the recipient wishes the property * @throws PropertyVetoException if one of listeners vetoes the property update
* change to be rolled back.
*/ */
public void fireVetoableChange(PropertyChangeEvent evt) public void fireVetoableChange(PropertyChangeEvent event)
throws PropertyVetoException { throws PropertyVetoException {
Object oldValue = event.getOldValue();
Object newValue = event.getNewValue();
if (oldValue == null || newValue == null || !oldValue.equals(newValue)) {
String name = event.getPropertyName();
Object oldValue = evt.getOldValue(); VetoableChangeListener[] common = this.map.get(null);
Object newValue = evt.getNewValue(); VetoableChangeListener[] named = (name != null)
String propertyName = evt.getPropertyName(); ? this.map.get(name)
if (oldValue != null && newValue != null && oldValue.equals(newValue)) { : null;
return;
}
VetoableChangeListener[] common = this.map.get(null);
VetoableChangeListener[] named = (propertyName != null)
? this.map.get(propertyName)
: null;
fire(common, evt);
fire(named, evt);
}
private void fire(VetoableChangeListener[] listeners, PropertyChangeEvent event) throws PropertyVetoException { VetoableChangeListener[] listeners;
if (listeners != null) { if (common == null) {
VetoableChangeListener current = null; listeners = named;
try { }
for (VetoableChangeListener listener : listeners) { else if (named == null) {
current = listener; listeners = common;
listener.vetoableChange(event); }
} else {
} catch (PropertyVetoException veto) { listeners = new VetoableChangeListener[common.length + named.length];
// Create an event to revert everyone to the old value. System.arraycopy(common, 0, listeners, 0, common.length);
event = new PropertyChangeEvent( this.source, System.arraycopy(named, 0, listeners, common.length, named.length);
event.getPropertyName(), }
event.getNewValue(), if (listeners != null) {
event.getOldValue() ); int current = 0;
for (VetoableChangeListener listener : listeners) { try {
if (current == listener) { while (current < listeners.length) {
break; listeners[current].vetoableChange(event);
current++;
} }
try { }
listener.vetoableChange(event); catch (PropertyVetoException veto) {
} catch (PropertyVetoException ex) { event = new PropertyChangeEvent(this.source, name, newValue, oldValue);
// We just ignore exceptions that occur during reversions. for (int i = 0; i < current; i++) {
try {
listeners[i].vetoableChange(event);
}
catch (PropertyVetoException exception) {
// ignore exceptions that occur during rolling back
}
} }
throw veto; // rethrow the veto exception
} }
// And now rethrow the PropertyVetoException.
throw veto;
} }
} }
} }
......
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code 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
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
* @test
* @bug 6630275
* @summary Tests VetoableChangeSupport specification
* @author Sergey Malenkov
*/
import java.beans.PropertyChangeEvent;
import java.beans.PropertyVetoException;
import java.beans.VetoableChangeListener;
import java.beans.VetoableChangeSupport;
public class Test6630275 {
private static final String PROPERTY = "property"; // NON-NLS: predefined property name
public static void main(String[] args) {
CheckListener first = new CheckListener(false);
CheckListener second = new CheckListener(true);
CheckListener third = new CheckListener(false);
VetoableChangeSupport vcs = new VetoableChangeSupport(Test6630275.class);
vcs.addVetoableChangeListener(first);
vcs.addVetoableChangeListener(PROPERTY, first);
vcs.addVetoableChangeListener(PROPERTY, second);
vcs.addVetoableChangeListener(PROPERTY, third);
try {
vcs.fireVetoableChange(PROPERTY, true, false);
} catch (PropertyVetoException exception) {
first.validate();
second.validate();
third.validate();
return; // expected exception
}
throw new Error("exception should be thrown");
}
private static class CheckListener implements VetoableChangeListener {
private final boolean veto;
private boolean odd; // even/odd check for notification
private CheckListener(boolean veto) {
this.veto = veto;
}
private void validate() {
if (this.veto != this.odd)
throw new Error(this.odd
? "undo event expected"
: "unexpected undo event");
}
public void vetoableChange(PropertyChangeEvent event) throws PropertyVetoException {
this.odd = !this.odd;
if (this.veto)
throw new PropertyVetoException("disable all changes", event);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册