diff options
| author | Benjamin Culkin <scorpress@gmail.com> | 2024-05-20 17:58:16 -0400 |
|---|---|---|
| committer | Benjamin Culkin <scorpress@gmail.com> | 2024-05-20 17:58:16 -0400 |
| commit | 40a9d99496e098562f090fb7ffce9e749011b131 (patch) | |
| tree | 437df24d65470582e943e494a52db8ed65a881ae /projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/MasterDetailAssociation.java | |
| parent | ff072dfe782f6f22123cd4ba050828d35c0d0fbd (diff) | |
Formatting pass
Diffstat (limited to 'projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/MasterDetailAssociation.java')
| -rw-r--r-- | projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/MasterDetailAssociation.java | 605 |
1 files changed, 264 insertions, 341 deletions
diff --git a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/MasterDetailAssociation.java b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/MasterDetailAssociation.java index 2aea8d3..54cd04e 100644 --- a/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/MasterDetailAssociation.java +++ b/projects/net.wotonomy.ui/src/main/java/net/wotonomy/ui/MasterDetailAssociation.java @@ -27,380 +27,303 @@ import net.wotonomy.foundation.NSArray; import net.wotonomy.foundation.NSMutableArray; /** -* MasterDetailAssociation binds a display group to a property -* on the selected object of another display group. -* Bindings are: -* <ul> -* <li>parent: The property on the selected object of the -* bound display group that is expected to be an indexed property.</li> -* </ul> -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 904 $ -*/ -public class MasterDetailAssociation extends EOAssociation -{ - static final NSArray aspects = - new NSArray( new Object[] { - ParentAspect - } ); - static final NSArray aspectSignatures = - new NSArray( new Object[] { - AttributeToOneAspectSignature - } ); - static final NSArray objectKeysTaken = - new NSArray( new Object[] { - "allObjects" - } ); - - /** - * Used to be notified of changes to objects in the - * controlled display group. requalify() should place - * all objects fetched into the controlled group into - * this array. - * Otherwise, the parent object is only marked as - * changed for inserts and deletes. - */ - protected NSMutableArray observableArray; - - /** - * Constructor expecting an EODisplayGroup. - * If the controlled display group does not have a data source, - * a new PropertyDataSource will be used. - */ - public MasterDetailAssociation ( Object anObject ) - { - super( anObject ); - observableArray = new ObservableArray( this ); - } - - /** - * Returns a List of aspect signatures whose contents - * correspond with the aspects list. Each element is - * a string whose characters represent a capability of - * the corresponding aspect. <ul> - * <li>"A" attribute: the aspect can be bound to - * an attribute.</li> - * <li>"1" to-one: the aspect can be bound to a - * property that returns a single object.</li> - * <li>"M" to-one: the aspect can be bound to a - * property that returns multiple objects.</li> - * </ul> - * An empty signature "" means that the aspect can - * bind without needing a key. - * This implementation returns "A1M" for each - * element in the aspects array. - */ - public static NSArray aspectSignatures () - { - return aspectSignatures; - } - - /** - * Returns a List that describes the aspects supported - * by this class. Each element in the list is the string - * name of the aspect. This implementation returns an - * empty list. - */ - public static NSArray aspects () - { - return aspects; - } - - /** - * Returns a List of EOAssociation subclasses that, - * for the objects that are usable for this association, - * are less suitable than this association. - */ - public static NSArray associationClassesSuperseded () - { - return new NSArray(); - } - - /** - * Returns whether this class can control the specified - * object. - */ - public static boolean isUsableWithObject ( Object anObject ) - { - return ( anObject instanceof EODisplayGroup ); - } - - /** - * Returns a List of properties of the controlled object - * that are controlled by this class. For example, - * "stringValue", or "selected". - */ - public static NSArray objectKeysTaken () - { - return objectKeysTaken; - } - - /** - * Returns the aspect that is considered primary - * or default. This is typically "value" or somesuch. - */ - public static String primaryAspect () - { - return ParentAspect; - } - - /** - * Returns whether this association can bind to the - * specified display group on the specified key for - * the specified aspect. - */ - public boolean canBindAspect ( - String anAspect, EODisplayGroup aDisplayGroup, String aKey) - { - return ( aspects.containsObject( anAspect ) ); - } - - /** - * Establishes a connection between this association - * and the controlled object. Subclasses should begin - * listening for events from their controlled object here. - */ - public void establishConnection () - { - //NOTE: if nothing refers to this assocation, it gets gc'd. - // otherwise, this is not needed. - component().addObserver( this ); - - EODisplayGroup displayGroup = - displayGroupForAspect( ParentAspect ); - String key = - displayGroupKeyForAspect( ParentAspect ); - - // obtain and qualify new data source from existing source if necessary - if ( component().dataSource() == null ) - { - if ( ( displayGroup != null ) && ( displayGroup.dataSource() != null ) ) - { - component().setDataSource( - displayGroup.dataSource(). - dataSourceQualifiedByKey( key ) ); - } - } - - // set up proxy data source if necessary - if ( component().dataSource() == null ) - { - // get context and class desc from master group - EOEditingContext editingContext = null; - EOClassDescription classDesc = null; - if ( displayGroup != null ) - { - EODataSource dataSource = displayGroup.dataSource(); - if ( dataSource != null ) - { - editingContext = dataSource.editingContext(); - EOClassDescription parentDesc = dataSource.classDescriptionForObjects(); - if ( parentDesc != null ) - { - classDesc = parentDesc.classDescriptionForDestinationKey( key ); - } - } - } - - //FIXME: should this be called DetailDataSource? - component().setDataSource( - new PropertyDataSource( editingContext, classDesc ) ); - } - - super.establishConnection(); + * MasterDetailAssociation binds a display group to a property on the selected + * object of another display group. Bindings are: + * <ul> + * <li>parent: The property on the selected object of the bound display group + * that is expected to be an indexed property.</li> + * </ul> + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 904 $ + */ +public class MasterDetailAssociation extends EOAssociation { + static final NSArray aspects = new NSArray(new Object[] { ParentAspect }); + static final NSArray aspectSignatures = new NSArray(new Object[] { AttributeToOneAspectSignature }); + static final NSArray objectKeysTaken = new NSArray(new Object[] { "allObjects" }); + + /** + * Used to be notified of changes to objects in the controlled display group. + * requalify() should place all objects fetched into the controlled group into + * this array. Otherwise, the parent object is only marked as changed for + * inserts and deletes. + */ + protected NSMutableArray observableArray; + + /** + * Constructor expecting an EODisplayGroup. If the controlled display group does + * not have a data source, a new PropertyDataSource will be used. + */ + public MasterDetailAssociation(Object anObject) { + super(anObject); + observableArray = new ObservableArray(this); + } + + /** + * Returns a List of aspect signatures whose contents correspond with the + * aspects list. Each element is a string whose characters represent a + * capability of the corresponding aspect. + * <ul> + * <li>"A" attribute: the aspect can be bound to an attribute.</li> + * <li>"1" to-one: the aspect can be bound to a property that returns a single + * object.</li> + * <li>"M" to-one: the aspect can be bound to a property that returns multiple + * objects.</li> + * </ul> + * An empty signature "" means that the aspect can bind without needing a key. + * This implementation returns "A1M" for each element in the aspects array. + */ + public static NSArray aspectSignatures() { + return aspectSignatures; + } + + /** + * Returns a List that describes the aspects supported by this class. Each + * element in the list is the string name of the aspect. This implementation + * returns an empty list. + */ + public static NSArray aspects() { + return aspects; + } + + /** + * Returns a List of EOAssociation subclasses that, for the objects that are + * usable for this association, are less suitable than this association. + */ + public static NSArray associationClassesSuperseded() { + return new NSArray(); + } + + /** + * Returns whether this class can control the specified object. + */ + public static boolean isUsableWithObject(Object anObject) { + return (anObject instanceof EODisplayGroup); + } + + /** + * Returns a List of properties of the controlled object that are controlled by + * this class. For example, "stringValue", or "selected". + */ + public static NSArray objectKeysTaken() { + return objectKeysTaken; + } + + /** + * Returns the aspect that is considered primary or default. This is typically + * "value" or somesuch. + */ + public static String primaryAspect() { + return ParentAspect; + } + + /** + * Returns whether this association can bind to the specified display group on + * the specified key for the specified aspect. + */ + public boolean canBindAspect(String anAspect, EODisplayGroup aDisplayGroup, String aKey) { + return (aspects.containsObject(anAspect)); + } + + /** + * Establishes a connection between this association and the controlled object. + * Subclasses should begin listening for events from their controlled object + * here. + */ + public void establishConnection() { + // NOTE: if nothing refers to this assocation, it gets gc'd. + // otherwise, this is not needed. + component().addObserver(this); + + EODisplayGroup displayGroup = displayGroupForAspect(ParentAspect); + String key = displayGroupKeyForAspect(ParentAspect); + + // obtain and qualify new data source from existing source if necessary + if (component().dataSource() == null) { + if ((displayGroup != null) && (displayGroup.dataSource() != null)) { + component().setDataSource(displayGroup.dataSource().dataSourceQualifiedByKey(key)); + } + } + + // set up proxy data source if necessary + if (component().dataSource() == null) { + // get context and class desc from master group + EOEditingContext editingContext = null; + EOClassDescription classDesc = null; + if (displayGroup != null) { + EODataSource dataSource = displayGroup.dataSource(); + if (dataSource != null) { + editingContext = dataSource.editingContext(); + EOClassDescription parentDesc = dataSource.classDescriptionForObjects(); + if (parentDesc != null) { + classDesc = parentDesc.classDescriptionForDestinationKey(key); + } + } + } + + // FIXME: should this be called DetailDataSource? + component().setDataSource(new PropertyDataSource(editingContext, classDesc)); + } + + super.establishConnection(); requalify(); - } - - /** - * Breaks the connection between this association and - * its object. Override to stop listening for events - * from the object. - */ - public void breakConnection () - { - //NOTE: if nothing refers to this assocation, it gets gc'd. - // otherwise, this is not needed. - component().deleteObserver( this ); - - super.breakConnection(); - } - - /** - * Called when either the selection or the contents - * of an associated display group have changed. - */ - public void subjectChanged () - { + } + + /** + * Breaks the connection between this association and its object. Override to + * stop listening for events from the object. + */ + public void breakConnection() { + // NOTE: if nothing refers to this assocation, it gets gc'd. + // otherwise, this is not needed. + component().deleteObserver(this); + + super.breakConnection(); + } + + /** + * Called when either the selection or the contents of an associated display + * group have changed. + */ + public void subjectChanged() { EODisplayGroup displayGroup; // parent aspect - displayGroup = displayGroupForAspect( ParentAspect ); - if ( displayGroup != null ) - { - if ( displayGroup.selectionChanged() ) - { - requalify(); + displayGroup = displayGroupForAspect(ParentAspect); + if (displayGroup != null) { + if (displayGroup.selectionChanged()) { + requalify(); + } else if (displayGroup.contentsChanged()) { + requalify(); } - else - if ( displayGroup.contentsChanged() ) - { - requalify(); + } + } + + /** + * Overridden to intercept notifications of changes to objects in the controlled + * display group and broadcast a change on the parent group's selected object. + * All other notifications are passed to the super implementation. + */ + public void objectWillChange(Object anObject) { + // if child display group is notifying + if (!(anObject instanceof EODisplayGroup)) { + // mark parent group's object as changed + EODisplayGroup displayGroup = displayGroupForAspect(ParentAspect); + if (displayGroup != null) { + Object selected = displayGroup.selectedObject(); + if (selected != null) { + // only notify if childrenKey is an attribute of parentDesc + // (and therefore not a toOne or toMany relationship) + EOClassDescription parentDesc = EOClassDescription.classDescriptionForClass(selected.getClass()); + String key = displayGroupKeyForAspect(ParentAspect); + if (key != null) { + int idx = key.indexOf('.'); + if (idx != -1) + key = key.substring(0, idx); + if (parentDesc.attributeKeys().contains(key)) { + // only notify if we are an attribute key + EOObserverCenter.notifyObserversObjectWillChange(selected); + } + } + } } + } else // display group is notifying + { + // call super so subjectChanged will be called + super.objectWillChange(anObject); } - } - - /** - * Overridden to intercept notifications of changes to objects - * in the controlled display group and broadcast a change on the - * parent group's selected object. All other notifications are - * passed to the super implementation. - */ - public void objectWillChange ( Object anObject ) - { - // if child display group is notifying - if ( ! ( anObject instanceof EODisplayGroup ) ) - { - // mark parent group's object as changed - EODisplayGroup displayGroup = displayGroupForAspect( ParentAspect ); - if ( displayGroup != null ) - { - Object selected = displayGroup.selectedObject(); - if ( selected != null ) - { - // only notify if childrenKey is an attribute of parentDesc - // (and therefore not a toOne or toMany relationship) - EOClassDescription parentDesc = - EOClassDescription.classDescriptionForClass( - selected.getClass() ); - String key = displayGroupKeyForAspect( ParentAspect ); - if ( key != null ) - { - int idx = key.indexOf( '.' ); - if ( idx != -1 ) key = key.substring( 0, idx ); - if ( parentDesc.attributeKeys().contains( key ) ) - { - // only notify if we are an attribute key - EOObserverCenter.notifyObserversObjectWillChange( selected ); - } - } - } - } - } - else // display group is notifying - { - // call super so subjectChanged will be called - super.objectWillChange( anObject ); - } - } - - /** - * Called by subjectChanged() to requalify the controlled - * display group with the selected object and the bound key. - */ - protected void requalify() - { + } + + /** + * Called by subjectChanged() to requalify the controlled display group with the + * selected object and the bound key. + */ + protected void requalify() { EODisplayGroup component = component(); - EODisplayGroup displayGroup = displayGroupForAspect( ParentAspect ); - String key = displayGroupKeyForAspect( ParentAspect ); - - if ( ( displayGroup.selectedObject() != null ) - && ( component.dataSource() != null ) ) - { - component.dataSource().qualifyWithRelationshipKey( - key, displayGroup.selectedObject() ); + EODisplayGroup displayGroup = displayGroupForAspect(ParentAspect); + String key = displayGroupKeyForAspect(ParentAspect); + + if ((displayGroup.selectedObject() != null) && (component.dataSource() != null)) { + component.dataSource().qualifyWithRelationshipKey(key, displayGroup.selectedObject()); component.fetch(); - observableArray.setArray( component.allObjects() ); - } - else // no selection or no data source, clear + observableArray.setArray(component.allObjects()); + } else // no selection or no data source, clear { - component.setObjectArray( null ); - observableArray.removeAllObjects(); + component.setObjectArray(null); + observableArray.removeAllObjects(); } - component.updateDisplayedObjects(); + component.updateDisplayedObjects(); + } + + /** + * This implementation returns ObserverPrioritySecond so that master detail + * assocations are notified before other associations. + */ + public int priority() { + return ObserverPrioritySecond; } - - /** - * This implementation returns ObserverPrioritySecond - * so that master detail assocations are notified before - * other associations. - */ - public int priority () - { - return ObserverPrioritySecond; - } // convenience - private EODisplayGroup component() - { - return (EODisplayGroup) object(); - } - + private EODisplayGroup component() { + return (EODisplayGroup) object(); + } + } /* - * $Log$ - * Revision 1.2 2006/02/18 23:14:35 cgruber - * Update imports and maven dependencies. + * $Log$ Revision 1.2 2006/02/18 23:14:35 cgruber Update imports and maven + * dependencies. * - * Revision 1.1 2006/02/16 13:22:22 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. + * Revision 1.1 2006/02/16 13:22:22 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.14 2004/02/04 20:00:49 mpowers - * Improved change notification for dotted key paths. + * Revision 1.14 2004/02/04 20:00:49 mpowers Improved change notification for + * dotted key paths. * - * Revision 1.13 2003/08/06 23:07:52 chochos - * general code cleanup (mostly, removing unused imports) + * Revision 1.13 2003/08/06 23:07:52 chochos general code cleanup (mostly, + * removing unused imports) * - * Revision 1.12 2001/10/26 18:39:05 mpowers - * Now a delayed observer with a higher priority, so that it is processed - * before other associations. + * Revision 1.12 2001/10/26 18:39:05 mpowers Now a delayed observer with a + * higher priority, so that it is processed before other associations. * - * Revision 1.11 2001/06/26 21:39:33 mpowers - * Added check for null component data source before requalifying. + * Revision 1.11 2001/06/26 21:39:33 mpowers Added check for null component data + * source before requalifying. * - * Revision 1.10 2001/05/21 14:04:15 mpowers - * No longer changing a detail group's data source if it's already specified. + * Revision 1.10 2001/05/21 14:04:15 mpowers No longer changing a detail group's + * data source if it's already specified. * - * Revision 1.9 2001/05/18 21:08:46 mpowers - * Now calling updateDisplayedObjects on detail after master changes. + * Revision 1.9 2001/05/18 21:08:46 mpowers Now calling updateDisplayedObjects + * on detail after master changes. * - * Revision 1.8 2001/05/14 15:26:42 mpowers - * Modified logic for controlled groups that have no data source already set. + * Revision 1.8 2001/05/14 15:26:42 mpowers Modified logic for controlled groups + * that have no data source already set. * - * Revision 1.7 2001/05/04 14:42:58 mpowers - * Now getting stored values in KeyValueCoding. - * MasterDetail now marks dirty based on whether it's an attribute - * or relation. - * Implemented editing context marker. + * Revision 1.7 2001/05/04 14:42:58 mpowers Now getting stored values in + * KeyValueCoding. MasterDetail now marks dirty based on whether it's an + * attribute or relation. Implemented editing context marker. * - * Revision 1.6 2001/04/29 02:29:31 mpowers - * Debugging relationship faulting. + * Revision 1.6 2001/04/29 02:29:31 mpowers Debugging relationship faulting. * - * Revision 1.4 2001/02/20 16:38:55 mpowers - * MasterDetailAssociations now observe their controlled display group's - * objects for changes to that the parent object will be marked as updated. - * Before, only inserts and deletes to an object's items are registered. - * Also, moved ObservableArray to package access. + * Revision 1.4 2001/02/20 16:38:55 mpowers MasterDetailAssociations now observe + * their controlled display group's objects for changes to that the parent + * object will be marked as updated. Before, only inserts and deletes to an + * object's items are registered. Also, moved ObservableArray to package access. * - * Revision 1.3 2001/01/18 16:57:18 mpowers - * Fixed problem with losing connection: the association was getting - * garbage collected because nothing referred to it. All other associations - * make themselves listeners of their controlled object, and that has been - * the only thing keeping them from getting gc'd. This will need to be fixed. + * Revision 1.3 2001/01/18 16:57:18 mpowers Fixed problem with losing + * connection: the association was getting garbage collected because nothing + * referred to it. All other associations make themselves listeners of their + * controlled object, and that has been the only thing keeping them from getting + * gc'd. This will need to be fixed. * - * Revision 1.2 2001/01/17 23:06:09 mpowers - * TreeAssociation now modifies the contents of the children display - * group rather than adding items to the titles display group. + * Revision 1.2 2001/01/17 23:06:09 mpowers TreeAssociation now modifies the + * contents of the children display group rather than adding items to the titles + * display group. * - * Revision 1.1.1.1 2000/12/21 15:48:23 mpowers - * Contributing wotonomy. + * Revision 1.1.1.1 2000/12/21 15:48:23 mpowers Contributing wotonomy. * - * Revision 1.5 2000/12/20 16:25:40 michael - * Added log to all files. + * Revision 1.5 2000/12/20 16:25:40 michael Added log to all files. * * */ - |
