United StatesChange Country, Oracle Worldwide Web Sites Communities I am a... I want to...
Bug ID: JDK-4353056 IndexedPropertyChangeEvent/IndexedPropertyChangeSupport missing
JDK-4353056 : IndexedPropertyChangeEvent/IndexedPropertyChangeSupport missing

Details
Type:
Enhancement
Submit Date:
2000-07-13
Status:
Resolved
Updated Date:
2003-08-15
Project Name:
JDK
Resolved Date:
2003-08-15
Component:
client-libs
OS:
generic
Sub-Component:
java.beans
CPU:
generic
Priority:
P4
Resolution:
Fixed
Affected Versions:
1.2.2
Fixed Versions:
5.0 (tiger)

Related Reports
Relates:

Sub Tasks

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
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
                                     
2001-07-26
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;
}
======================================================================
                                     
2004-06-11
CONVERTED DATA

BugTraq+ Release Management Values

COMMIT TO FIX:
tiger

FIXED IN:
tiger

INTEGRATED IN:
tiger
tiger-b16


                                     
2004-06-14



Hardware and Software, Engineered to Work Together