JDK-4353056 : IndexedPropertyChangeEvent/IndexedPropertyChangeSupport missing
  • Type: Enhancement
  • Component: client-libs
  • Sub-Component: java.beans
  • Affected Version: 1.2.2
  • Priority: P4
  • Status: Resolved
  • Resolution: Fixed
  • OS: generic
  • CPU: generic
  • Submitted: 2000-07-13
  • Updated: 2017-05-16
  • Resolved: 2003-08-15
The Version table provides details related to the release that this issue/RFE will be addressed.

Unresolved : Release in which this issue/RFE will be addressed.
Resolved: Release in which this issue/RFE has been resolved.
Fixed : Release in which this issue/RFE has been fixed. The release containing this fix may be available for download as an Early Access Release or a General Availability Release.

To download the current JDK release, click here.
Other
5.0 tigerFixed
Related Reports
Relates :  
Description

Name: jk109818			Date: 07/13/2000


java version "1.2.2"
Classic VM (build 1.2.2-L, green threads, nojit)


Although the index of a changed element of an indexed property is known to
setter methods, there currently is no standard way to propagate this information
to listening clients, that is, classes IndexedPropertyChangeEvent and
IndexedPropertyChangeSupport are missing. A listener has to iterate over the
whole property to identify the element that has actually changed. This is
inconvenient in general, and unacceptable if the number of property elements is
large.

Feel free to use the implementation found in the workaround section. The method
signatures already take into account that non-int (ie, key) indexed properties
maybe are allowed in future Beans specifications. See Beans 1.01 spec (Section
7.2, "Indexed Properties", pages 40/41): "Property indexes must be Java
"int"s. We may relax this restriction in the future to allow other index types."
Size of compiled class files: 1792 bytes (IndexedPropertyChangeSupport) and
1100 bytes (IndexedPropertyChangeEvent).
(Review ID: 101528) 
======================================================================

Comments
CONVERTED DATA BugTraq+ Release Management Values COMMIT TO FIX: tiger FIXED IN: tiger INTEGRATED IN: tiger tiger-b16
14-06-2004

WORK AROUND Name: jk109818 Date: 07/13/2000 /** * @author Oliver Imbusch **/ public class IndexedPropertyChangeEvent extends PropertyChangeEvent { // we extends PropertyChangeEvent so we can safely deliver this // new Event while existing code simply sees the // PropertyChangeEvent part, ignoring the additional index // information /** * Constructs a new IndexedPropertyChangeEvent object. * * @param source The bean that fired the event. * @param propertyName The programmatic name of the property that * was changed. * * @param index Indicator specifying the property element * that was changed. * * Currently this must be of type * <code>Integer</code>, but this may change * as soon as non-int property indices (keys) * are allowed. * * @param oldValue The old value of the property. * @param newValue The new value of the property. * * @throws UnsupportedOperation if index is not a non-null * <code>Integer</code> **/ public IndexedPropertyChangeEvent (Object source, String propertyName, Object index, Object oldValue, Object newValue) { // NOTE: we don't throw a NullPointerException if index is // null, and null-ness does also not mean that the index is // unknown. Hopefully, some days MappedProperties become // popular, and null keys may be allowed by the used map. // // FIXME: how to check whether null-keys are supported by the // map? How do we know that a map is used without an orgy of // instanceof checks? // // FIME: to be honest, we currently do check for null-ness of // index, and we even assure that it's of type Integer. I have // no idea how we could otherwise check whether the indexed // property elements have changed in // IndexedPropertyChangeSupport.fireIndexedPropertyChange () // methods. At least we have a future-proof interface. Note // that UnsupportedOperationException is a RuntimeException // and thus needn't appear in a throw clause. We intentionally // don't mention it in a throw clause but in the JavaDoc only // to easily remove the restriction in the future without // breaking then-existing code. super (source, propertyName, oldValue, newValue); try { this.index = ((Integer)index).intValue (); } catch (Exception e) { // ClassCastExcpetion, NullPointerException throw new UnsupportedOperationException ("index must be non-null Integer (was: " + ((null == index) ? "null" : index.getClass ().toString ())); } } private int index; /** * @return The index specifying the property element that was * changed, expressed as an Object. * * Currently this is of type <code>Integer</code>, but this may * change as soon as non-int property indices (keys) are allowed. **/ public Object getIndex () { // FIXME: return new Integer (index); } } import java.lang.reflect.Array; /** * @author Oliver Imbusch **/ public class IndexedPropertyChangeSupport extends PropertyChangeSupport { /** * Constructs an IndexedPropertyChangeSupport object. * * @param sourceBean The bean to be given as the source for any events. **/ public IndexedPropertyChangeSupport (Object sourceBean) { super (sourceBean); // PropertyChangeSupport doesn't give us access to this, we // have to store it ourselves this.source = sourceBean; } /** * Report a bound indexed property update to any registered * listeners. * * No event is fired if old and new property element at the * specified index are equal and non-null. * * @param propertyName The programmatic name of the property that * was changed. * @param index Indicator specifying the property element * that was changed. * * Currently this must be of type * <code>Integer</code>, but this may change * as soon as non-int property indices (keys) * are allowed. * * @param oldValue The old value of the property. * @param newValue The new value of the property. **/ public void fireIndexedPropertyChange (String propertyName, Object index, Object oldValue, Object newValue) { fireIndexedPropertyChange (new IndexedPropertyChangeEvent (source, propertyName, index, oldValue, newValue)); } /** * Fire an existing IndexedPropertyChangeEvent to any registered * listeners. * * No event is fired if old and new property element at the * specified index are equal and non-null. * * @param evt The IndexedPropertyChangeEvent object. **/ public void fireIndexedPropertyChange (IndexedPropertyChangeEvent evt) { Object oldValue = evt.getOldValue (); Object newValue = evt.getNewValue (); // FIXME: currently IndexedPropertyChangeEvent constructor // assures that index is of type Integer and non-null, so we // can safely cast and extract the int value; this will change // with mapped properties. int index = ((Integer)evt.getIndex ()).intValue (); if ((null == oldValue) || (null == newValue)) { // FIXME: at least one property is null, so we cannot // check whether the elements are equal. Should we // disallow this case? For the moment, we remove the // useless index information so called clients don't have // to check. PropertyChangeEvent newEvt = new PropertyChangeEvent (evt.getSource (), evt.getPropertyName (), oldValue, newValue); // why don't we have a constructor that takes the // propagationId? newEvt.setPropagationId (evt.getPropagationId ()); super.firePropertyChange (newEvt); } else { // FIXME: for now we know that old an new values are // arrays so we can easily extract the indexed property // element. But the tricky part comes when this is no // longer the case. We could still get the old element // from the source bean (using // // PropertyDescriptor pd = // new PropertyDescriptor (evt.getPropertyName (), // source.getClass); // Method getter = pd.getReadMethod (); // Object oldElement = // getter.invoke (source, new Object[] { index }); // // thus ignoring the oldValue parameter), but how do we // deal with the newValue element? Some instanceof games // could be acceptable if only a limited set of containers // from the Collection framework are allowed as property // element containers. boolean bothOutOfBounds = false; Object oldElement; if (Array.getLength (oldValue) <= index) { // this is allowed: the new property has increased in // size, that is, the element was appended and we // won't find in the old property // // FIXME: theoretically, this differs from the case // where a null-valued element was part of an Object // array property, but in practise it shouldn't make // difference oldElement = null; bothOutOfBounds = true; } else { // NOTE: if index < 0, we intentionally get an Exception here oldElement = Array.get (oldValue, index); } Object newElement; if (Array.getLength (newValue) <= index) { // equivalent, property maybe has shrunk newElement = null; } else { // NOTE: if index < 0, we intentionally get an Exception here newElement = Array.get (newValue, index); bothOutOfBounds = false; } if (bothOutOfBounds) { // this is definitely an error throw new ArrayIndexOutOfBoundsException (index); } if (!( (null != oldValue) && (null != newValue) && oldValue.equals (newValue))) { super.firePropertyChange (evt); } } } private Object source; } ======================================================================
11-06-2004

EVALUATION The implementation is great and will be done for the next major release. The design document is here (Sun Internal): http://javaweb.eng/~davidson/beans/spec/indexedproperties mark.davidson@Eng 2001-07-26
26-07-2001