You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by "Bryce Nordgren (JIRA)" <ji...@apache.org> on 2006/06/14 00:09:31 UTC

[jira] Created: (SANDBOX-149) [events] Notifying/Observable Design Choice

[events] Notifying/Observable Design Choice
-------------------------------------------

         Key: SANDBOX-149
         URL: http://issues.apache.org/jira/browse/SANDBOX-149
     Project: Commons Sandbox
        Type: Task

    Reporter: Bryce Nordgren
    Priority: Blocker


Prior to retiring the events package a couple of years ago, three different design options were articulated.  One option needs to be selected prior to expending further work.  Note that the code in the repository has a modification date somewhere in early 2005, after this message was written.  I believe that the code in the repository reflects a modified version of #3.  Choice #3 seems like the most logical to me.

The email is located here: 
http://mail-archives.apache.org/mod_mbox/jakarta-commons-dev/200306.mbox/%3c007801c32d17$3fdaafa0$083b29d9@oemcomputer%3e

{quote}
Three possible designs (so far):

Proposal #1 (Heuer/MailingList)
--------------------------------
public boolean addAll(int index, Collection coll) {
  int oldSize = backingList.size();
  boolean returnVal = backingList.addAll(index, coll);
  int newSize = backingList.size();
  if (returnVal) {
    CollectionChangeEvent e = new
CollectionChangeEvent(this,oldSize,newSize,index,coll.size(),null,coll,true)
;
    support.fireElementsAdded(e);
  }
  return returnVal;
}
- One Event class.
- Event data chosen by us (so less flexible).
- Should handle all collections, but iterators will not be fail-fast.
- Should give reasonable performance.
- Relies on accurate result boolean.
- Relatively few classes


Proposal #2 (O'Toole):
-------------------------
public boolean addAll(int index, Collection c){
  this.throwIfIndexOutOfBoundsExclusive(index);
  ModifyingCollectionEvent event =
this.listEventFactory.createAddAllEvent(index, c);
  this.doFireVetoableEvent(event); // can throw a
CollectionModificationVetoedException
  boolean result = backingList.addAll(index, c);
  if (result){
   this.incrementModCount();
   this.doFirePostModificationEvent(event);
  }
  return result;
 }
- Event implementation class chosen by factory.
- Event data is theoretically flexible, but limited in practice. In
particular, the post-event cannot contain a copy of the state of the
collection, or the size before the change occurred (ie. you can't replicate
proposal #1)
- Unsuited to certain collections (eg. LazyList)
- Should give reasonable performance.
- Relies on accurate result boolean.
- Exception thrown from vetoed pre-events.
- Quite a lot of classes and concepts


Propsal #3 (Colebourne - merged from #1 and #2):
--------------------------
public boolean addAll(int index, Collection c){
  if (preAddAll(index, c)) {
    result = backingList.addAll(index, c);
    postAddAll(index, c, result);
  }
  return result;
 }
- Event implementation class chosen by subclass.
- Event data can be chosen by subclass.
- Should handle all collections, but iterators will not be fail-fast
(although subclass could include coding for that...).
- Will perform as per how you write the subclass. (Faster or slower)
- Subclass can choose whether to believe boolean result.
- Subclass can choose whether to use Listener pattern, or something else
(eg. call a static method)
- Choice of exception or ignore for vetoed pre-events.
- Relatively few classes, but subclasses may get have more classes


#3 explanation:
The class gets changed into an abstract one, with a real implementation or
two supplied in [collections]. Thus, AbstractNotifyingList would have the
method above, with NotifyingList as a subclass, managing event creation and
dispatch (using convenience methods from the abstract class.


Any comments, views or opinions on the three designs???
I guess I believe that #3 is the best compromise between #1 and #2 I can
think of (both #1 and #2 can be built using #3).

Stephen
{quote}

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


commons-events: similarity to java.beans.PropertyChangeSupport

Posted by Bryce L Nordgren <bn...@fs.fed.us>.
Please respond with comment on
http://issues.apache.org/jira/browse/SANDBOX-149.

I am exploring re-designing collections-events using extension of the
standard property change support stuff in java.beans.  I'm trying to keep
the goals/tradeoffs mentioned in the "3 proposals" email in mind.

The main thing I don't quite understand yet is: The packages currently
support vetoable changes _and_ pre/post events.  Aren't these the same
thing?  Or should pre/post events be renamed to "change requests" and
"changes"?


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


[jira] Updated: (SANDBOX-149) [events] Notifying/Observable Design Choice

Posted by "Bryce Nordgren (JIRA)" <ji...@apache.org>.
     [ http://issues.apache.org/jira/browse/SANDBOX-149?page=all ]

Bryce Nordgren updated SANDBOX-149:
-----------------------------------

    Attachment: Observable.png

UML Diagram of the current code in the events package.

> [events] Notifying/Observable Design Choice
> -------------------------------------------
>
>          Key: SANDBOX-149
>          URL: http://issues.apache.org/jira/browse/SANDBOX-149
>      Project: Commons Sandbox
>         Type: Task

>     Reporter: Bryce Nordgren
>     Priority: Blocker
>  Attachments: Observable.png
>
> Prior to retiring the events package a couple of years ago, three different design options were articulated.  One option needs to be selected prior to expending further work.  Note that the code in the repository has a modification date somewhere in early 2005, after this message was written.  I believe that the code in the repository reflects a modified version of #3.  Choice #3 seems like the most logical to me.
> The email is located here: 
> http://mail-archives.apache.org/mod_mbox/jakarta-commons-dev/200306.mbox/%3c007801c32d17$3fdaafa0$083b29d9@oemcomputer%3e
> {quote}
> Three possible designs (so far):
> Proposal #1 (Heuer/MailingList)
> --------------------------------
> public boolean addAll(int index, Collection coll) {
>   int oldSize = backingList.size();
>   boolean returnVal = backingList.addAll(index, coll);
>   int newSize = backingList.size();
>   if (returnVal) {
>     CollectionChangeEvent e = new
> CollectionChangeEvent(this,oldSize,newSize,index,coll.size(),null,coll,true)
> ;
>     support.fireElementsAdded(e);
>   }
>   return returnVal;
> }
> - One Event class.
> - Event data chosen by us (so less flexible).
> - Should handle all collections, but iterators will not be fail-fast.
> - Should give reasonable performance.
> - Relies on accurate result boolean.
> - Relatively few classes
> Proposal #2 (O'Toole):
> -------------------------
> public boolean addAll(int index, Collection c){
>   this.throwIfIndexOutOfBoundsExclusive(index);
>   ModifyingCollectionEvent event =
> this.listEventFactory.createAddAllEvent(index, c);
>   this.doFireVetoableEvent(event); // can throw a
> CollectionModificationVetoedException
>   boolean result = backingList.addAll(index, c);
>   if (result){
>    this.incrementModCount();
>    this.doFirePostModificationEvent(event);
>   }
>   return result;
>  }
> - Event implementation class chosen by factory.
> - Event data is theoretically flexible, but limited in practice. In
> particular, the post-event cannot contain a copy of the state of the
> collection, or the size before the change occurred (ie. you can't replicate
> proposal #1)
> - Unsuited to certain collections (eg. LazyList)
> - Should give reasonable performance.
> - Relies on accurate result boolean.
> - Exception thrown from vetoed pre-events.
> - Quite a lot of classes and concepts
> Propsal #3 (Colebourne - merged from #1 and #2):
> --------------------------
> public boolean addAll(int index, Collection c){
>   if (preAddAll(index, c)) {
>     result = backingList.addAll(index, c);
>     postAddAll(index, c, result);
>   }
>   return result;
>  }
> - Event implementation class chosen by subclass.
> - Event data can be chosen by subclass.
> - Should handle all collections, but iterators will not be fail-fast
> (although subclass could include coding for that...).
> - Will perform as per how you write the subclass. (Faster or slower)
> - Subclass can choose whether to believe boolean result.
> - Subclass can choose whether to use Listener pattern, or something else
> (eg. call a static method)
> - Choice of exception or ignore for vetoed pre-events.
> - Relatively few classes, but subclasses may get have more classes
> #3 explanation:
> The class gets changed into an abstract one, with a real implementation or
> two supplied in [collections]. Thus, AbstractNotifyingList would have the
> method above, with NotifyingList as a subclass, managing event creation and
> dispatch (using convenience methods from the abstract class.
> Any comments, views or opinions on the three designs???
> I guess I believe that #3 is the best compromise between #1 and #2 I can
> think of (both #1 and #2 can be built using #3).
> Stephen
> {quote}

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


[jira] Commented: (SANDBOX-149) [events] Notifying/Observable Design Choice

Posted by "Bryce Nordgren (JIRA)" <ji...@apache.org>.
    [ http://issues.apache.org/jira/browse/SANDBOX-149?page=comments#action_12417567 ] 

Bryce Nordgren commented on SANDBOX-149:
----------------------------------------

Partially executed the design of the previous comment.  The "Observable" problem has been recast in terms of the more familiar (to me) java event pattern: a listener interface, an event, and a listener registry mechanism.  The design has evolved somewhat from the UML diagrams on this page, such that BoundCollections directly use the event factories.  

The result of this is something that's easier for me to get my mind around.  In particular, when "subLists", "subSets" and "subMaps" are made (all of which are views to a common aggrecation of data items), I believe this is a much more straightforward way to ensure that all registered listeners for all the views get an event for a change caused by any view.

I have produced a BoundMap, as well, which is not included in the original (dormant) code. 

Interested parties can check out the code as it is from the GeoTools subversion server.  It needs more work before it is complete enough to attach to this issue, but a quick checkout should give an idea of what has been done.

For something that compiles with maven 2: http://svn.geotools.org/geotools/branches/jts-wrapper
For just the commons-events source: http://svn.geotools.org/geotools/branches/jts-wrapper/module/events



> [events] Notifying/Observable Design Choice
> -------------------------------------------
>
>          Key: SANDBOX-149
>          URL: http://issues.apache.org/jira/browse/SANDBOX-149
>      Project: Commons Sandbox
>         Type: Task

>     Reporter: Bryce Nordgren
>     Priority: Blocker
>  Attachments: Observable.png, UsingPropertyChangeSupport.png
>
> Prior to retiring the events package a couple of years ago, three different design options were articulated.  One option needs to be selected prior to expending further work.  Note that the code in the repository has a modification date somewhere in early 2005, after this message was written.  I believe that the code in the repository reflects a modified version of #3.  Choice #3 seems like the most logical to me.
> The email is located here: 
> http://mail-archives.apache.org/mod_mbox/jakarta-commons-dev/200306.mbox/%3c007801c32d17$3fdaafa0$083b29d9@oemcomputer%3e
> {quote}
> Three possible designs (so far):
> Proposal #1 (Heuer/MailingList)
> --------------------------------
> public boolean addAll(int index, Collection coll) {
>   int oldSize = backingList.size();
>   boolean returnVal = backingList.addAll(index, coll);
>   int newSize = backingList.size();
>   if (returnVal) {
>     CollectionChangeEvent e = new
> CollectionChangeEvent(this,oldSize,newSize,index,coll.size(),null,coll,true)
> ;
>     support.fireElementsAdded(e);
>   }
>   return returnVal;
> }
> - One Event class.
> - Event data chosen by us (so less flexible).
> - Should handle all collections, but iterators will not be fail-fast.
> - Should give reasonable performance.
> - Relies on accurate result boolean.
> - Relatively few classes
> Proposal #2 (O'Toole):
> -------------------------
> public boolean addAll(int index, Collection c){
>   this.throwIfIndexOutOfBoundsExclusive(index);
>   ModifyingCollectionEvent event =
> this.listEventFactory.createAddAllEvent(index, c);
>   this.doFireVetoableEvent(event); // can throw a
> CollectionModificationVetoedException
>   boolean result = backingList.addAll(index, c);
>   if (result){
>    this.incrementModCount();
>    this.doFirePostModificationEvent(event);
>   }
>   return result;
>  }
> - Event implementation class chosen by factory.
> - Event data is theoretically flexible, but limited in practice. In
> particular, the post-event cannot contain a copy of the state of the
> collection, or the size before the change occurred (ie. you can't replicate
> proposal #1)
> - Unsuited to certain collections (eg. LazyList)
> - Should give reasonable performance.
> - Relies on accurate result boolean.
> - Exception thrown from vetoed pre-events.
> - Quite a lot of classes and concepts
> Propsal #3 (Colebourne - merged from #1 and #2):
> --------------------------
> public boolean addAll(int index, Collection c){
>   if (preAddAll(index, c)) {
>     result = backingList.addAll(index, c);
>     postAddAll(index, c, result);
>   }
>   return result;
>  }
> - Event implementation class chosen by subclass.
> - Event data can be chosen by subclass.
> - Should handle all collections, but iterators will not be fail-fast
> (although subclass could include coding for that...).
> - Will perform as per how you write the subclass. (Faster or slower)
> - Subclass can choose whether to believe boolean result.
> - Subclass can choose whether to use Listener pattern, or something else
> (eg. call a static method)
> - Choice of exception or ignore for vetoed pre-events.
> - Relatively few classes, but subclasses may get have more classes
> #3 explanation:
> The class gets changed into an abstract one, with a real implementation or
> two supplied in [collections]. Thus, AbstractNotifyingList would have the
> method above, with NotifyingList as a subclass, managing event creation and
> dispatch (using convenience methods from the abstract class.
> Any comments, views or opinions on the three designs???
> I guess I believe that #3 is the best compromise between #1 and #2 I can
> think of (both #1 and #2 can be built using #3).
> Stephen
> {quote}

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


[jira] Commented: (SANDBOX-149) [events] Notifying/Observable Design Choice

Posted by "Bryce Nordgren (JIRA)" <ji...@apache.org>.
    [ http://issues.apache.org/jira/browse/SANDBOX-149?page=comments#action_12416246 ] 

Bryce Nordgren commented on SANDBOX-149:
----------------------------------------

Is there any reason not to consider "ModificationEvents" to be a specialization of property change events?  There could be a property called "contents" for collection types to which clients could subscribe.  If people want "special" events, they could subclass PropertyChangeEvents and PropertyChangeSupport.

Additionally, is there any need for pre and post change events if Vetoable changes are properly supported?  I think most of the logic for this sort of thing is implemented in java.beans and doesn't need to be reinvented here...

> [events] Notifying/Observable Design Choice
> -------------------------------------------
>
>          Key: SANDBOX-149
>          URL: http://issues.apache.org/jira/browse/SANDBOX-149
>      Project: Commons Sandbox
>         Type: Task

>     Reporter: Bryce Nordgren
>     Priority: Blocker
>  Attachments: Observable.png
>
> Prior to retiring the events package a couple of years ago, three different design options were articulated.  One option needs to be selected prior to expending further work.  Note that the code in the repository has a modification date somewhere in early 2005, after this message was written.  I believe that the code in the repository reflects a modified version of #3.  Choice #3 seems like the most logical to me.
> The email is located here: 
> http://mail-archives.apache.org/mod_mbox/jakarta-commons-dev/200306.mbox/%3c007801c32d17$3fdaafa0$083b29d9@oemcomputer%3e
> {quote}
> Three possible designs (so far):
> Proposal #1 (Heuer/MailingList)
> --------------------------------
> public boolean addAll(int index, Collection coll) {
>   int oldSize = backingList.size();
>   boolean returnVal = backingList.addAll(index, coll);
>   int newSize = backingList.size();
>   if (returnVal) {
>     CollectionChangeEvent e = new
> CollectionChangeEvent(this,oldSize,newSize,index,coll.size(),null,coll,true)
> ;
>     support.fireElementsAdded(e);
>   }
>   return returnVal;
> }
> - One Event class.
> - Event data chosen by us (so less flexible).
> - Should handle all collections, but iterators will not be fail-fast.
> - Should give reasonable performance.
> - Relies on accurate result boolean.
> - Relatively few classes
> Proposal #2 (O'Toole):
> -------------------------
> public boolean addAll(int index, Collection c){
>   this.throwIfIndexOutOfBoundsExclusive(index);
>   ModifyingCollectionEvent event =
> this.listEventFactory.createAddAllEvent(index, c);
>   this.doFireVetoableEvent(event); // can throw a
> CollectionModificationVetoedException
>   boolean result = backingList.addAll(index, c);
>   if (result){
>    this.incrementModCount();
>    this.doFirePostModificationEvent(event);
>   }
>   return result;
>  }
> - Event implementation class chosen by factory.
> - Event data is theoretically flexible, but limited in practice. In
> particular, the post-event cannot contain a copy of the state of the
> collection, or the size before the change occurred (ie. you can't replicate
> proposal #1)
> - Unsuited to certain collections (eg. LazyList)
> - Should give reasonable performance.
> - Relies on accurate result boolean.
> - Exception thrown from vetoed pre-events.
> - Quite a lot of classes and concepts
> Propsal #3 (Colebourne - merged from #1 and #2):
> --------------------------
> public boolean addAll(int index, Collection c){
>   if (preAddAll(index, c)) {
>     result = backingList.addAll(index, c);
>     postAddAll(index, c, result);
>   }
>   return result;
>  }
> - Event implementation class chosen by subclass.
> - Event data can be chosen by subclass.
> - Should handle all collections, but iterators will not be fail-fast
> (although subclass could include coding for that...).
> - Will perform as per how you write the subclass. (Faster or slower)
> - Subclass can choose whether to believe boolean result.
> - Subclass can choose whether to use Listener pattern, or something else
> (eg. call a static method)
> - Choice of exception or ignore for vetoed pre-events.
> - Relatively few classes, but subclasses may get have more classes
> #3 explanation:
> The class gets changed into an abstract one, with a real implementation or
> two supplied in [collections]. Thus, AbstractNotifyingList would have the
> method above, with NotifyingList as a subclass, managing event creation and
> dispatch (using convenience methods from the abstract class.
> Any comments, views or opinions on the three designs???
> I guess I believe that #3 is the best compromise between #1 and #2 I can
> think of (both #1 and #2 can be built using #3).
> Stephen
> {quote}

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org


[jira] Updated: (SANDBOX-149) [events] Notifying/Observable Design Choice

Posted by "Bryce Nordgren (JIRA)" <ji...@apache.org>.
     [ http://issues.apache.org/jira/browse/SANDBOX-149?page=all ]

Bryce Nordgren updated SANDBOX-149:
-----------------------------------

    Attachment: UsingPropertyChangeSupport.png

Attaching design which leverages java.beans.{PropertyChangeSupport,VetoableChangeSupport}.  This design holds the sources of events fixed, but permits users to extend the event class and the event factory so that they can record different information.  This design eliminates pre and post events, providing an "isChanged()" flag in the single event fired.  The event will not be fired until the collection is changed...  Two families of decorators are provided (one based on "property change" and one based on "vetoable change".)  This is for consistency with the pre-existing infrastructure in java.beans.

> [events] Notifying/Observable Design Choice
> -------------------------------------------
>
>          Key: SANDBOX-149
>          URL: http://issues.apache.org/jira/browse/SANDBOX-149
>      Project: Commons Sandbox
>         Type: Task

>     Reporter: Bryce Nordgren
>     Priority: Blocker
>  Attachments: Observable.png, UsingPropertyChangeSupport.png
>
> Prior to retiring the events package a couple of years ago, three different design options were articulated.  One option needs to be selected prior to expending further work.  Note that the code in the repository has a modification date somewhere in early 2005, after this message was written.  I believe that the code in the repository reflects a modified version of #3.  Choice #3 seems like the most logical to me.
> The email is located here: 
> http://mail-archives.apache.org/mod_mbox/jakarta-commons-dev/200306.mbox/%3c007801c32d17$3fdaafa0$083b29d9@oemcomputer%3e
> {quote}
> Three possible designs (so far):
> Proposal #1 (Heuer/MailingList)
> --------------------------------
> public boolean addAll(int index, Collection coll) {
>   int oldSize = backingList.size();
>   boolean returnVal = backingList.addAll(index, coll);
>   int newSize = backingList.size();
>   if (returnVal) {
>     CollectionChangeEvent e = new
> CollectionChangeEvent(this,oldSize,newSize,index,coll.size(),null,coll,true)
> ;
>     support.fireElementsAdded(e);
>   }
>   return returnVal;
> }
> - One Event class.
> - Event data chosen by us (so less flexible).
> - Should handle all collections, but iterators will not be fail-fast.
> - Should give reasonable performance.
> - Relies on accurate result boolean.
> - Relatively few classes
> Proposal #2 (O'Toole):
> -------------------------
> public boolean addAll(int index, Collection c){
>   this.throwIfIndexOutOfBoundsExclusive(index);
>   ModifyingCollectionEvent event =
> this.listEventFactory.createAddAllEvent(index, c);
>   this.doFireVetoableEvent(event); // can throw a
> CollectionModificationVetoedException
>   boolean result = backingList.addAll(index, c);
>   if (result){
>    this.incrementModCount();
>    this.doFirePostModificationEvent(event);
>   }
>   return result;
>  }
> - Event implementation class chosen by factory.
> - Event data is theoretically flexible, but limited in practice. In
> particular, the post-event cannot contain a copy of the state of the
> collection, or the size before the change occurred (ie. you can't replicate
> proposal #1)
> - Unsuited to certain collections (eg. LazyList)
> - Should give reasonable performance.
> - Relies on accurate result boolean.
> - Exception thrown from vetoed pre-events.
> - Quite a lot of classes and concepts
> Propsal #3 (Colebourne - merged from #1 and #2):
> --------------------------
> public boolean addAll(int index, Collection c){
>   if (preAddAll(index, c)) {
>     result = backingList.addAll(index, c);
>     postAddAll(index, c, result);
>   }
>   return result;
>  }
> - Event implementation class chosen by subclass.
> - Event data can be chosen by subclass.
> - Should handle all collections, but iterators will not be fail-fast
> (although subclass could include coding for that...).
> - Will perform as per how you write the subclass. (Faster or slower)
> - Subclass can choose whether to believe boolean result.
> - Subclass can choose whether to use Listener pattern, or something else
> (eg. call a static method)
> - Choice of exception or ignore for vetoed pre-events.
> - Relatively few classes, but subclasses may get have more classes
> #3 explanation:
> The class gets changed into an abstract one, with a real implementation or
> two supplied in [collections]. Thus, AbstractNotifyingList would have the
> method above, with NotifyingList as a subclass, managing event creation and
> dispatch (using convenience methods from the abstract class.
> Any comments, views or opinions on the three designs???
> I guess I believe that #3 is the best compromise between #1 and #2 I can
> think of (both #1 and #2 can be built using #3).
> Stephen
> {quote}

-- 
This message is automatically generated by JIRA.
-
If you think it was sent incorrectly contact one of the administrators:
   http://issues.apache.org/jira/secure/Administrators.jspa
-
For more information on JIRA, see:
   http://www.atlassian.com/software/jira


---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org