diff options
Diffstat (limited to 'projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/internal')
| -rw-r--r-- | projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/internal/Surrogate.java | 259 |
1 files changed, 259 insertions, 0 deletions
diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/internal/Surrogate.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/internal/Surrogate.java new file mode 100644 index 0000000..e12fda0 --- /dev/null +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/internal/Surrogate.java @@ -0,0 +1,259 @@ +/* +Wotonomy: OpenStep design patterns for pure Java applications. +Copyright (C) 2000 Intersect Software Corporation + +This library is free software; you can redistribute it and/or +modify it under the terms of the GNU Lesser General Public +License as published by the Free Software Foundation; either +version 2.1 of the License, or (at your option) any later version. + +This library 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 +Lesser General Public License for more details. + +You should have received a copy of the GNU Lesser General Public +License along with this library; if not, see http://www.gnu.org +*/ + +package net.wotonomy.control.internal; + +import net.wotonomy.control.EOObserverCenter; +import net.wotonomy.foundation.NSMutableDictionary; +import net.wotonomy.foundation.internal.Introspector; + +/** +* A Surrogate is a special object that can be used in a display +* group when you wish to emulate other objects or modify their +* behaviors. Because it is a Map, it makes use of Introspector's +* ability to treat keys in a map as if they were properties to +* implement the following features. +* <ul> +* <li>By default, Surrogate works like a Map, and reading and +* writing properties to a Surrogate gets and puts values in the +* Map.</li> +* <li>If one or more delegate objects are specified, property keys +* that do not exist in the map are read from and written to the +* delegate object.</li> +* <li>If a default value is specified, that value will be returned +* for all property reads that do not exist in the map or in the +* delegate object. (Subsequent writes to those properties will +* create a key in the map and then subsequent reads will read not +* read the default object.)</li> +* <li>Subclasses can override the get(Object) method to further +* customize the behavior of a Surrogate. +* </ul> +* +* @author michael@mpowers.net +* @date $Date: 2006-02-18 17:46:44 -0500 (Sat, 18 Feb 2006) $ +* @revision $Revision: 900 $ +*/ +public class Surrogate extends NSMutableDictionary +{ + protected Object[] delegates; + protected Object defaultValue; + + /** + * Default constructor with no delegate object and no default value. + */ + public Surrogate() + { + delegates = null; + defaultValue = null; + } + + /** + * Constructor specifying a delegate object. + */ + public Surrogate( Object[] aDelegateArray ) + { + setDelegates( aDelegateArray ); + } + + /** + * Constructor specifying a default value. + */ + public Surrogate( Object aDefault ) + { + setDefaultValue( aDefault ); + } + + /** + * Constructor specifying a delegate object and a default value. + */ + public Surrogate( Object[] aDelegateArray, Object aDefault ) + { + setDelegates( aDelegateArray ); + setDefaultValue( aDefault ); + } + + /** + * Returns the first delegate object, or null if no delegates exist. + */ + public Object getDelegate() + { + if ( delegates == null ) return null; + if ( delegates.length == 0 ) return null; + return delegates[0]; + } + + /** + * Sets the delegate object list to contain only the + * specified object. + */ + public void setDelegate( Object aDelegate ) + { + setDelegates( new Object[] { aDelegate } ); + } + + /** + * Returns the list of delegates in the order in which + * they are consulted. + */ + public Object[] getDelegates() + { + if ( delegates == null ) delegates = new Object[0]; + return delegates; + } + + /** + * Sets the list of delegates in the order in which they + * will be consulted. + */ + public void setDelegates( Object[] aDelegateArray ) + { + delegates = aDelegateArray; + } + + /** + * Returns the current default value, or null if no default exists. + */ + public Object getDefaultValue() + { + return defaultValue; + } + + /** + * Sets the default value. + */ + public void setDefaultValue( Object aDefault ) + { + defaultValue = aDefault; + } + + /** + * Called by get to retrieve a value from the internal map. + * This implementation simply calls super.get(). + */ + public Object directGet( Object aKey ) + { + return super.get( aKey ); + } + + /** + * Called by put to retrieve a value from the internal map. + * This implementation simply calls super.put(). + */ + public Object directPut( Object aKey, Object aValue ) + { + return super.put( aKey, aValue ); + } + + /** + * Overridden to consult each delegate before + * checking the internal list of keys. No matching + * key is found, returns the default object, or + * null if no default object exists. + */ + public Object get( Object aKey ) + { + // check all delegates in order + int i, j; + Object[] list = getDelegates(); + String[] properties; + for ( i = 0; i < list.length; i++ ) + { + // for each delegate + properties = + Introspector.getReadPropertiesForObject( list[i] ); + for ( j = 0; j < properties.length; j++ ) + { + // if delegate has property + if ( properties[j].equals( aKey ) ) + { + // use this delegate + return Introspector.get( list[i], aKey.toString() ); + } + } + } + + // return from internal map + Object result = directGet( aKey ); + if ( result == null ) + { + // if not in map, return default object + result = getDefaultValue(); + } + return result; + } + + /** + * Overridden to attempt to write each delegate, writing to + * only the first successful delegate, before storing the + * value in the internal map. + */ + public Object put( Object aKey, Object aValue ) + { + // check all delegates in order + int i, j; + Object[] list = getDelegates(); + String[] properties; + for ( i = 0; i < list.length; i++ ) + { + // for each delegate + properties = + Introspector.getWritePropertiesForObject( list[i] ); + for ( j = 0; j < properties.length; j++ ) + { + // if delegate has property + if ( properties[j].equals( aKey ) ) + { + // use this delegate + EOObserverCenter.notifyObserversObjectWillChange( list[i] ); + return Introspector.set( list[i], aKey.toString(), aValue ); + } + } + } + + // set on internal map + EOObserverCenter.notifyObserversObjectWillChange( this ); + return directPut( aKey, aValue ); + } + + /** + * Overridden to compare by reference. + */ + public boolean equals( Object anObject ) + { + return ( this == anObject ); + } + +} + +/* + * $Log$ + * Revision 1.1 2006/02/18 22:46:44 cgruber + * Add Surrogate map from .util into control's internal package, and fix imports. + * + * Revision 1.1 2006/02/16 13:22:22 cgruber + * Check in all sources in eclipse-friendly maven-enabled packages. + * + * Revision 1.1.1.1 2000/12/21 15:52:21 mpowers + * Contributing wotonomy. + * + * Revision 1.2 2000/12/20 16:25:48 michael + * Added log to all files. + * + * + */ + |
