summaryrefslogtreecommitdiff
path: root/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/KeyValueCodingUtilities.java
diff options
context:
space:
mode:
authorBenjamin Culkin <scorpress@gmail.com>2024-05-20 17:58:16 -0400
committerBenjamin Culkin <scorpress@gmail.com>2024-05-20 17:58:16 -0400
commit40a9d99496e098562f090fb7ffce9e749011b131 (patch)
tree437df24d65470582e943e494a52db8ed65a881ae /projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/KeyValueCodingUtilities.java
parentff072dfe782f6f22123cd4ba050828d35c0d0fbd (diff)
Formatting pass
Diffstat (limited to 'projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/KeyValueCodingUtilities.java')
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/KeyValueCodingUtilities.java1140
1 files changed, 484 insertions, 656 deletions
diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/KeyValueCodingUtilities.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/KeyValueCodingUtilities.java
index 1aa2147..d052fcf 100644
--- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/KeyValueCodingUtilities.java
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/KeyValueCodingUtilities.java
@@ -38,227 +38,169 @@ import net.wotonomy.foundation.internal.Duplicator;
import net.wotonomy.foundation.internal.WotonomyException;
/**
-* KeyValueCodingUtilities implements what
-* EOKeyValueCodingSupport leaves out. Importantly,
-* this class implements the deep clone and deep copy
-* operations that are essential to the functioning of
-* nested editing contexts.
-*
-* @author michael@mpowers.net
-* @author $Author: cgruber $
-* @version $Revision: 900 $
-*/
-public class KeyValueCodingUtilities
-{
- /**
- * Returns a Map of the specified keys to their values,
- * each of which is obtained by calling valueForKey
- * on the specified object if it implements EOKeyValueCoding,
- * and otherwise falling back on EOKeyValueCodingSupport.
- * Null values must be represented by NSNull.nullValue().
- */
- static public NSDictionary valuesForKeys(
- Object anObject, List aKeyList )
- {
- return valuesForKeys( anObject, aKeyList, false );
- }
-
- /**
- * Returns a Map of the specified keys to their values,
- * each of which is obtained by calling storedValueForKey
- * on the specified object if it implements EOKeyValueCoding,
- * and otherwise falling back on EOKeyValueCodingSupport.
- * Null values must be represented by NSNull.nullValue().
- */
- static public NSDictionary storedValuesForKeys(
- Object anObject, List aKeyList )
- {
- return valuesForKeys( anObject, aKeyList, true );
- }
-
- /**
- * Called by valuesForKeys and storedValuesForKeys.
- * This uses storedValueForKey if isStored is true,
- * otherwise uses valueForKey.
- */
- static private NSDictionary valuesForKeys(
- Object anObject, List aKeyList, boolean isStored )
- {
- EOKeyValueCoding coding;
- if ( anObject instanceof EOKeyValueCoding )
- {
- coding = (EOKeyValueCoding) anObject;
- }
- else
- {
- coding = null;
- }
-
- String key;
- Object value;
- NSMutableDictionary result = new NSMutableDictionary();
- Iterator it = aKeyList.iterator();
- while ( it.hasNext() )
- {
- //TODO: get rid of this try/catch - exceptions should be fatal (?)
- try
- {
- key = it.next().toString();
- if ( coding != null )
- {
- if ( isStored )
- value = coding.storedValueForKey( key );
- else
- value = coding.valueForKey( key );
- }
- else
- {
- if ( isStored )
- value = EOKeyValueCodingSupport.storedValueForKey( anObject, key );
- else
- value = EOKeyValueCodingSupport.valueForKey( anObject, key );
- }
- if ( value == null )
- {
- value = EONullValue.nullValue();
- }
- result.setObjectForKey( value, key );
- }
- catch ( RuntimeException exc )
- {
- System.out.println(
- "KeyValueCodingUtilities.valuesForKeys: "
- + isStored + " : " + exc );
- }
- }
- return result;
- }
-
- /**
- * Takes the keys from the specified Map as properties
- * and applies the corresponding values, each of which
- * might be set by calling takeValueForKey on the
- * specified object if it implements EOKeyValueCoding,
- * and otherwise falling back on EOKeyValueCodingSupport.
- * Null values must be represented by NSNull.nullValue().
- */
- static public void takeValuesFromDictionary(
- Object anObject, Map aMap )
- {
- takeStoredValuesFromDictionary( anObject, aMap, false );
- }
-
- /**
- * Takes the keys from the specified Map as properties
- * and applies the corresponding values, each of which
- * might be set by calling takeStoredValueForKey on the
- * specified object if it implements EOKeyValueCoding,
- * and otherwise falling back on EOKeyValueCodingSupport.
- * Null values must be represented by NSNull.nullValue().
- */
- static public void takeStoredValuesFromDictionary(
- Object anObject, Map aMap )
- {
- takeStoredValuesFromDictionary( anObject, aMap, true );
- }
-
- /**
- * Called by takeValuesFromDictionary and takeStoredValuesFromDictionary.
- * This uses takeStoredValueForKey if isStored is true,
- * otherwise uses takeValueForKey.
- */
- static private void takeStoredValuesFromDictionary(
- Object anObject, Map aMap, boolean isStored )
- {
- EOKeyValueCoding coding;
- if ( anObject instanceof EOKeyValueCoding )
- {
- coding = (EOKeyValueCoding) anObject;
- }
- else
- {
- coding = null;
- }
-
- String key;
- Object value;
- NSMutableDictionary result = new NSMutableDictionary();
- Iterator it = aMap.keySet().iterator();
- while ( it.hasNext() )
- {
- //TODO: get rid of this try/catch - exceptions should be fatal (?)
- try
- {
- key = it.next().toString();
- value = aMap.get( key );
- if ( value instanceof EONullValue )
- // can't use == nullValue() because of cloning/serialization
- {
- value = null;
- }
- if ( coding != null )
- {
- if ( isStored )
- coding.takeStoredValueForKey( value, key );
- else
- coding.takeValueForKey( value, key );
- }
- else
- {
- if ( isStored )
- EOKeyValueCodingSupport.takeStoredValueForKey(
- anObject, value, key );
- else
- EOKeyValueCodingSupport.takeValueForKey(
- anObject, value, key );
- }
- }
- catch ( WotonomyException exc )
- {
- System.out.println(
- "KeyValueCodingUtilities.takeStoredValuesFromDictionary: "
- + isStored + " : " + exc );
- }
- }
- }
-
- /**
- * Creates a deep clone of the specified object.
- * (Object.clone() only creates a shallow clone.)
- * Returns null if operation fails.
- */
- static public Object clone( Object aSource )
- {
- return Duplicator.deepClone( aSource );
- }
-
- /**
- * Creates a deep clone of the specified object,
- * registered in the specified source editing context,
- * transposing it into the specified destination
- * editing context.
- * Returns null if operation fails.
- */
- static public Object clone(
- EOEditingContext aSourceContext, Object aSource,
- EOEditingContext aDestinationContext )
- {
- return clone( aSourceContext, aSource, aDestinationContext, aSource );
- }
-
- /**
- * Called by clone and copy.
- * The specified root object will not be replaced
- * by an object in the destination editing context:
- * this should be the same as the source object for
- * cloning, but should be null for copying.
- * Returns null if operation fails.
- */
- static private Object clone(
- EOEditingContext aSourceContext, Object aSource,
- EOEditingContext aDestinationContext,
- Object aRootObject )
- {
+ * KeyValueCodingUtilities implements what EOKeyValueCodingSupport leaves out.
+ * Importantly, this class implements the deep clone and deep copy operations
+ * that are essential to the functioning of nested editing contexts.
+ *
+ * @author michael@mpowers.net
+ * @author $Author: cgruber $
+ * @version $Revision: 900 $
+ */
+public class KeyValueCodingUtilities {
+ /**
+ * Returns a Map of the specified keys to their values, each of which is
+ * obtained by calling valueForKey on the specified object if it implements
+ * EOKeyValueCoding, and otherwise falling back on EOKeyValueCodingSupport. Null
+ * values must be represented by NSNull.nullValue().
+ */
+ static public NSDictionary valuesForKeys(Object anObject, List aKeyList) {
+ return valuesForKeys(anObject, aKeyList, false);
+ }
+
+ /**
+ * Returns a Map of the specified keys to their values, each of which is
+ * obtained by calling storedValueForKey on the specified object if it
+ * implements EOKeyValueCoding, and otherwise falling back on
+ * EOKeyValueCodingSupport. Null values must be represented by
+ * NSNull.nullValue().
+ */
+ static public NSDictionary storedValuesForKeys(Object anObject, List aKeyList) {
+ return valuesForKeys(anObject, aKeyList, true);
+ }
+
+ /**
+ * Called by valuesForKeys and storedValuesForKeys. This uses storedValueForKey
+ * if isStored is true, otherwise uses valueForKey.
+ */
+ static private NSDictionary valuesForKeys(Object anObject, List aKeyList, boolean isStored) {
+ EOKeyValueCoding coding;
+ if (anObject instanceof EOKeyValueCoding) {
+ coding = (EOKeyValueCoding) anObject;
+ } else {
+ coding = null;
+ }
+
+ String key;
+ Object value;
+ NSMutableDictionary result = new NSMutableDictionary();
+ Iterator it = aKeyList.iterator();
+ while (it.hasNext()) {
+ // TODO: get rid of this try/catch - exceptions should be fatal (?)
+ try {
+ key = it.next().toString();
+ if (coding != null) {
+ if (isStored)
+ value = coding.storedValueForKey(key);
+ else
+ value = coding.valueForKey(key);
+ } else {
+ if (isStored)
+ value = EOKeyValueCodingSupport.storedValueForKey(anObject, key);
+ else
+ value = EOKeyValueCodingSupport.valueForKey(anObject, key);
+ }
+ if (value == null) {
+ value = EONullValue.nullValue();
+ }
+ result.setObjectForKey(value, key);
+ } catch (RuntimeException exc) {
+ System.out.println("KeyValueCodingUtilities.valuesForKeys: " + isStored + " : " + exc);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Takes the keys from the specified Map as properties and applies the
+ * corresponding values, each of which might be set by calling takeValueForKey
+ * on the specified object if it implements EOKeyValueCoding, and otherwise
+ * falling back on EOKeyValueCodingSupport. Null values must be represented by
+ * NSNull.nullValue().
+ */
+ static public void takeValuesFromDictionary(Object anObject, Map aMap) {
+ takeStoredValuesFromDictionary(anObject, aMap, false);
+ }
+
+ /**
+ * Takes the keys from the specified Map as properties and applies the
+ * corresponding values, each of which might be set by calling
+ * takeStoredValueForKey on the specified object if it implements
+ * EOKeyValueCoding, and otherwise falling back on EOKeyValueCodingSupport. Null
+ * values must be represented by NSNull.nullValue().
+ */
+ static public void takeStoredValuesFromDictionary(Object anObject, Map aMap) {
+ takeStoredValuesFromDictionary(anObject, aMap, true);
+ }
+
+ /**
+ * Called by takeValuesFromDictionary and takeStoredValuesFromDictionary. This
+ * uses takeStoredValueForKey if isStored is true, otherwise uses
+ * takeValueForKey.
+ */
+ static private void takeStoredValuesFromDictionary(Object anObject, Map aMap, boolean isStored) {
+ EOKeyValueCoding coding;
+ if (anObject instanceof EOKeyValueCoding) {
+ coding = (EOKeyValueCoding) anObject;
+ } else {
+ coding = null;
+ }
+
+ String key;
+ Object value;
+ NSMutableDictionary result = new NSMutableDictionary();
+ Iterator it = aMap.keySet().iterator();
+ while (it.hasNext()) {
+ // TODO: get rid of this try/catch - exceptions should be fatal (?)
+ try {
+ key = it.next().toString();
+ value = aMap.get(key);
+ if (value instanceof EONullValue)
+ // can't use == nullValue() because of cloning/serialization
+ {
+ value = null;
+ }
+ if (coding != null) {
+ if (isStored)
+ coding.takeStoredValueForKey(value, key);
+ else
+ coding.takeValueForKey(value, key);
+ } else {
+ if (isStored)
+ EOKeyValueCodingSupport.takeStoredValueForKey(anObject, value, key);
+ else
+ EOKeyValueCodingSupport.takeValueForKey(anObject, value, key);
+ }
+ } catch (WotonomyException exc) {
+ System.out.println("KeyValueCodingUtilities.takeStoredValuesFromDictionary: " + isStored + " : " + exc);
+ }
+ }
+ }
+
+ /**
+ * Creates a deep clone of the specified object. (Object.clone() only creates a
+ * shallow clone.) Returns null if operation fails.
+ */
+ static public Object clone(Object aSource) {
+ return Duplicator.deepClone(aSource);
+ }
+
+ /**
+ * Creates a deep clone of the specified object, registered in the specified
+ * source editing context, transposing it into the specified destination editing
+ * context. Returns null if operation fails.
+ */
+ static public Object clone(EOEditingContext aSourceContext, Object aSource, EOEditingContext aDestinationContext) {
+ return clone(aSourceContext, aSource, aDestinationContext, aSource);
+ }
+
+ /**
+ * Called by clone and copy. The specified root object will not be replaced by
+ * an object in the destination editing context: this should be the same as the
+ * source object for cloning, but should be null for copying. Returns null if
+ * operation fails.
+ */
+ static private Object clone(EOEditingContext aSourceContext, Object aSource, EOEditingContext aDestinationContext,
+ Object aRootObject) {
//System.out.println();
//System.out.println( "clone: " + aSourceContext );
@@ -266,475 +208,361 @@ public class KeyValueCodingUtilities
//System.out.println( " : " + aDestinationContext );
//System.out.println();
- // the only known way to deep copy in
- // java without native code is serialization
-
- return thaw(
- freeze( aSource, aSourceContext, aRootObject, true ),
- aDestinationContext, true );
- }
-
- /**
- * Serializes an object to a byte array containing
- * GlobalIDMarkers in place of references to other objects
- * registered in the specified context.
- * The specified root object will be serialized,
- * even if it is registered in the specified context:
- * this is typically the root object you're trying to
- * serialize.
- * Package access, as this method is used by editing
- * context for snapshots.
- */
- static public byte[] freeze(
- Object anObject, EOEditingContext aContext, Object aRootObject, boolean transpose )
- {
- try
- {
+ // the only known way to deep copy in
+ // java without native code is serialization
+
+ return thaw(freeze(aSource, aSourceContext, aRootObject, true), aDestinationContext, true);
+ }
+
+ /**
+ * Serializes an object to a byte array containing GlobalIDMarkers in place of
+ * references to other objects registered in the specified context. The
+ * specified root object will be serialized, even if it is registered in the
+ * specified context: this is typically the root object you're trying to
+ * serialize. Package access, as this method is used by editing context for
+ * snapshots.
+ */
+ static public byte[] freeze(Object anObject, EOEditingContext aContext, Object aRootObject, boolean transpose) {
+ try {
//long t = System.currentTimeMillis();
- ByteArrayOutputStream byteOutput =
- new ByteArrayOutputStream();// CloneBufferSize );
- ObjectOutputStream objectOutput;
- if ( transpose )
- {
- objectOutput =
- new TransposingContextObjectOutputStream(
- byteOutput, aContext, aRootObject );
- }
- else
- {
- objectOutput =
- new ContextObjectOutputStream(
- byteOutput, aContext );
- }
-
- objectOutput.writeObject( anObject );
- objectOutput.flush();
- objectOutput.close();
-
- return byteOutput.toByteArray();
+ ByteArrayOutputStream byteOutput = new ByteArrayOutputStream();// CloneBufferSize );
+ ObjectOutputStream objectOutput;
+ if (transpose) {
+ objectOutput = new TransposingContextObjectOutputStream(byteOutput, aContext, aRootObject);
+ } else {
+ objectOutput = new ContextObjectOutputStream(byteOutput, aContext);
+ }
+
+ objectOutput.writeObject(anObject);
+ objectOutput.flush();
+ objectOutput.close();
+
+ return byteOutput.toByteArray();
// profiling
-/*
-byte[] result = byteOutput.toByteArray();
-long size = result.length;
-long time = ( System.currentTimeMillis() - t );
-maxSize = Math.max( size, maxSize );
-minSize = Math.min( size, minSize );
-totSize += size;
-maxTime = Math.max( time, maxTime );
-minTime = Math.min( time, minTime );
-totTime += time;
-nTime++;
-System.out.println( "freeze: size = [ " + size + " : " + minSize + " : " + ( (float)totSize / (float)nTime ) + " : " + maxSize
-+ " ] time = [ " + time + " : " + minTime + " : " + ( (float)totTime / (float)nTime ) + " : " + maxTime + " ]" );
-return result;
-*/
+ /*
+ * byte[] result = byteOutput.toByteArray(); long size = result.length; long
+ * time = ( System.currentTimeMillis() - t ); maxSize = Math.max( size, maxSize
+ * ); minSize = Math.min( size, minSize ); totSize += size; maxTime = Math.max(
+ * time, maxTime ); minTime = Math.min( time, minTime ); totTime += time;
+ * nTime++; System.out.println( "freeze: size = [ " + size + " : " + minSize +
+ * " : " + ( (float)totSize / (float)nTime ) + " : " + maxSize + " ] time = [ "
+ * + time + " : " + minTime + " : " + ( (float)totTime / (float)nTime ) + " : "
+ * + maxTime + " ]" ); return result;
+ */
// end profiling
- }
- catch ( Exception exc )
- {
- throw new WotonomyException( exc );
- }
- }
-
+ } catch (Exception exc) {
+ throw new WotonomyException(exc);
+ }
+ }
+
//static long maxTime, minTime, totTime, nTime, maxSize, minSize, totSize;
//static long maxTimeThaw, minTimeThaw, totTimeThaw, nTimeThaw;
- /**
- * De-serializes an object from the specified byte
- * array, replacing GlobalIDMarkers with reference
- * to objects registered in the specified editing
- * context.
- * Package access, as this method is used by editing
- * context for snapshots.
- */
- static public Object thaw(
- byte[] aByteArray, EOEditingContext aContext, boolean transpose )
- {
- return thaw( aByteArray, aContext, null, transpose );
- }
-
- /**
- * De-serializes an object from the specified byte
- * array, replacing GlobalIDMarkers with reference
- * to objects registered in the specified editing
- * context.
- * Package access, as this method is used by editing
- * context for snapshots.
- */
- static public Object thaw(
- byte[] aByteArray, EOEditingContext aContext, ClassLoader aLoader, boolean transpose )
- {
- try
- {
+ /**
+ * De-serializes an object from the specified byte array, replacing
+ * GlobalIDMarkers with reference to objects registered in the specified editing
+ * context. Package access, as this method is used by editing context for
+ * snapshots.
+ */
+ static public Object thaw(byte[] aByteArray, EOEditingContext aContext, boolean transpose) {
+ return thaw(aByteArray, aContext, null, transpose);
+ }
+
+ /**
+ * De-serializes an object from the specified byte array, replacing
+ * GlobalIDMarkers with reference to objects registered in the specified editing
+ * context. Package access, as this method is used by editing context for
+ * snapshots.
+ */
+ static public Object thaw(byte[] aByteArray, EOEditingContext aContext, ClassLoader aLoader, boolean transpose) {
+ try {
//long t = System.currentTimeMillis();
- ByteArrayInputStream byteInput =
- new ByteArrayInputStream( aByteArray );
- ObjectInputStream objectInput;
- if ( transpose )
- {
- objectInput =
- new TransposingContextObjectInputStream(
- byteInput, aContext, aLoader );
- }
- else
- {
- objectInput =
- new ContextObjectInputStream(
- byteInput, aContext, aLoader );
- }
-
- return objectInput.readObject();
+ ByteArrayInputStream byteInput = new ByteArrayInputStream(aByteArray);
+ ObjectInputStream objectInput;
+ if (transpose) {
+ objectInput = new TransposingContextObjectInputStream(byteInput, aContext, aLoader);
+ } else {
+ objectInput = new ContextObjectInputStream(byteInput, aContext, aLoader);
+ }
+
+ return objectInput.readObject();
// profiling
-/*
-Object result = objectInput.readObject();
-long timeThaw = ( System.currentTimeMillis() - t );
-maxTimeThaw = Math.max( timeThaw, maxTimeThaw );
-minTimeThaw = Math.min( timeThaw, minTimeThaw );
-totTimeThaw += timeThaw;
-nTimeThaw++;
-System.out.println( "thaw: size = " + aByteArray.length + ", time = [ " + timeThaw + " : " + minTimeThaw + " : " + ( (float)totTimeThaw / (float)nTimeThaw ) + " : " + maxTimeThaw + " ]" );
-return result;
-*/
+ /*
+ * Object result = objectInput.readObject(); long timeThaw = (
+ * System.currentTimeMillis() - t ); maxTimeThaw = Math.max( timeThaw,
+ * maxTimeThaw ); minTimeThaw = Math.min( timeThaw, minTimeThaw ); totTimeThaw
+ * += timeThaw; nTimeThaw++; System.out.println( "thaw: size = " +
+ * aByteArray.length + ", time = [ " + timeThaw + " : " + minTimeThaw + " : " +
+ * ( (float)totTimeThaw / (float)nTimeThaw ) + " : " + maxTimeThaw + " ]" );
+ * return result;
+ */
// end profiling
- }
- catch ( Exception exc )
- {
- throw new WotonomyException( exc );
- }
- }
-
- /**
- * Copies values from one object registered in the
- * specified origin context to the specified destination
- * object
- * The values themselves are cloned, so this is a deep copy.
- * Returns the destination object, or throws exception
- * if operation fails.
- */
- static public Object copy( Object aSource, Object aDestination )
- {
- NSDictionary values = (NSDictionary)
- clone( valuesForKeys( aSource,
- EOClassDescription.classDescriptionForClass(
- aSource.getClass() ).attributeKeys() ) );
-
- takeStoredValuesFromDictionary( aDestination, values );
- return aDestination;
- }
-
- /**
- * Copies values from one object registered in the
- * specified origin context to the specified destination
- * object
- * The values themselves are cloned, so this is a deep copy.
- * Returns the destination object, or throws exception
- * if operation fails.
- */
- static public Object copy(
- EOEditingContext aSourceContext, Object aSource,
- EOEditingContext aDestinationContext, Object aDestination )
- {
- // get all keys for this object
- EOClassDescription classDesc =
- EOClassDescription.classDescriptionForClass( aSource.getClass() );
- List keys = new LinkedList();
- keys.addAll( classDesc.attributeKeys() );
- keys.addAll( classDesc.toOneRelationshipKeys() );
- keys.addAll( classDesc.toManyRelationshipKeys() );
-
- // transpose all objects registered in source context
- NSDictionary values = storedValuesForKeys( aSource, keys );
- values = (NSDictionary)
- clone( aSourceContext, values, aDestinationContext, null );
-
- // apply to destination object
- takeStoredValuesFromDictionary( aDestination, values );
- return aDestination;
- }
-
- // inner classes
-
- /**
- * An ObjectOutputStream that serializes objects with references
- * to an editing context. The specified context will not be
- * serialized but referenced, so that a ContextObjectInputStream
- * can replace the reference with another editing context.
- */
- static private class ContextObjectOutputStream extends ObjectOutputStream
- {
- private EditingContextMarker marker = new EditingContextMarker();
- protected EOEditingContext editingContext;
-
- /**
- * Specifies the output stream to wrap,
- * and the source context that should be
- * referenced but not serialized.
- */
- public ContextObjectOutputStream(
- OutputStream anOutputStream,
- EOEditingContext aContext )
- throws IOException
- {
- super( anOutputStream );
- editingContext = aContext;
- try
- {
- enableReplaceObject(true);
- }
- catch ( Exception exc )
- {
- exc.printStackTrace();
- }
- }
-
- protected Object replaceObject(Object anObject) throws IOException
- {
+ } catch (Exception exc) {
+ throw new WotonomyException(exc);
+ }
+ }
+
+ /**
+ * Copies values from one object registered in the specified origin context to
+ * the specified destination object The values themselves are cloned, so this is
+ * a deep copy. Returns the destination object, or throws exception if operation
+ * fails.
+ */
+ static public Object copy(Object aSource, Object aDestination) {
+ NSDictionary values = (NSDictionary) clone(valuesForKeys(aSource,
+ EOClassDescription.classDescriptionForClass(aSource.getClass()).attributeKeys()));
+
+ takeStoredValuesFromDictionary(aDestination, values);
+ return aDestination;
+ }
+
+ /**
+ * Copies values from one object registered in the specified origin context to
+ * the specified destination object The values themselves are cloned, so this is
+ * a deep copy. Returns the destination object, or throws exception if operation
+ * fails.
+ */
+ static public Object copy(EOEditingContext aSourceContext, Object aSource, EOEditingContext aDestinationContext,
+ Object aDestination) {
+ // get all keys for this object
+ EOClassDescription classDesc = EOClassDescription.classDescriptionForClass(aSource.getClass());
+ List keys = new LinkedList();
+ keys.addAll(classDesc.attributeKeys());
+ keys.addAll(classDesc.toOneRelationshipKeys());
+ keys.addAll(classDesc.toManyRelationshipKeys());
+
+ // transpose all objects registered in source context
+ NSDictionary values = storedValuesForKeys(aSource, keys);
+ values = (NSDictionary) clone(aSourceContext, values, aDestinationContext, null);
+
+ // apply to destination object
+ takeStoredValuesFromDictionary(aDestination, values);
+ return aDestination;
+ }
+
+ // inner classes
+
+ /**
+ * An ObjectOutputStream that serializes objects with references to an editing
+ * context. The specified context will not be serialized but referenced, so that
+ * a ContextObjectInputStream can replace the reference with another editing
+ * context.
+ */
+ static private class ContextObjectOutputStream extends ObjectOutputStream {
+ private EditingContextMarker marker = new EditingContextMarker();
+ protected EOEditingContext editingContext;
+
+ /**
+ * Specifies the output stream to wrap, and the source context that should be
+ * referenced but not serialized.
+ */
+ public ContextObjectOutputStream(OutputStream anOutputStream, EOEditingContext aContext) throws IOException {
+ super(anOutputStream);
+ editingContext = aContext;
+ try {
+ enableReplaceObject(true);
+ } catch (Exception exc) {
+ exc.printStackTrace();
+ }
+ }
+
+ protected Object replaceObject(Object anObject) throws IOException {
// if ( anObject == editingContext ) return marker;
//FIXME: this should be more strict as above
- if ( anObject instanceof EOEditingContext ) return marker;
- return anObject;
- }
-
- }
-
- /**
- * A ContextObjectOutputStream that replaces any objects registered
- * in the source editing context with markers to be used in
- * ContextObjectInputStream.
- */
- static private class TransposingContextObjectOutputStream
- extends ContextObjectOutputStream
- {
- protected Object rootObject;
-
- /**
- * Specifies the output stream to wrap,
- * the source context containing objects that
- * should be replaced if found,
- * and the object which should not be re-registered,
- * which is typically the object being cloned, but
- * may be null.
- */
- public TransposingContextObjectOutputStream(
- OutputStream anOutputStream,
- EOEditingContext aContext,
- Object anObject )
- throws IOException
- {
- super( anOutputStream, aContext );
- rootObject = anObject;
- }
-
- protected Object replaceObject(Object anObject) throws IOException
- {
- if ( anObject == rootObject ) return anObject;
- if ( editingContext != null )
- {
- EOGlobalID id = editingContext.globalIDForObject( anObject );
- if ( id != null )
- {
- Object result = new GlobalIDMarker( id );
- //System.out.println( "KeyValueCodingUtilities.replaceObject: returning: " + result );
- return result;
- }
- }
- return super.replaceObject( anObject );
- }
-
- }
-
- /**
- * A marker class so references to objects registered in editing
- * contexts get transposed rather than cloned.
- */
- static private class GlobalIDMarker implements Serializable
- {
- private EOGlobalID id;
-
- public GlobalIDMarker( EOGlobalID anID )
- {
- id = anID;
- }
-
- public EOGlobalID getID()
- {
- return id;
- }
-
- public String toString()
- {
- return "[GlobalIDMarker:"+id+"]";
- }
- }
-
- /**
- * A marker class so references an object's editing context
- * gets transposed rather than cloned.
- */
- static private class EditingContextMarker implements Serializable
- {
- // just a marker class - no implementation necessary
- }
-
- /**
- * An ObjectInputStream that replaces any markers from
- * ContextObjectOutputStream with objects registered
- * in the destination editing context.
- */
- static private class ContextObjectInputStream extends ObjectInputStream
- {
- protected EOEditingContext editingContext;
- protected ClassLoader classLoader;
-
- /**
- * Specifies the output stream to wrap,
- * the source context containing objects that
- * should be to replace any markers.
- * The class loader may be null.
- */
- public ContextObjectInputStream(
- InputStream anInputStream,
- EOEditingContext aContext,
- ClassLoader aClassLoader )
- throws IOException
- {
- super( anInputStream );
- editingContext = aContext;
- classLoader = aClassLoader;
- if ( classLoader == null )
- {
- classLoader =
- KeyValueCodingUtilities.class.getClassLoader();
- }
- try
- {
- enableResolveObject(true);
- }
- catch ( Exception exc )
- {
- exc.printStackTrace();
- }
- }
-
- protected Object resolveObject(Object anObject) throws IOException
- {
- if ( anObject instanceof EditingContextMarker )
- {
- return editingContext;
- }
- return anObject;
- }
-
- protected Class resolveClass(ObjectStreamClass v)
- throws IOException, ClassNotFoundException
- {
- return classLoader.loadClass( v.getName() );
- }
- }
-
- /**
- * A ContextObjectInputStream that replaces any markers from
- * TransposingContextObjectOutputStream with objects registered
- * in the destination editing context.
- */
- static private class TransposingContextObjectInputStream
- extends ContextObjectInputStream
- {
- /**
- * Specifies the output stream to wrap,
- * the source context containing objects that
- * should be to replace any markers.
- */
- public TransposingContextObjectInputStream(
- InputStream anInputStream,
- EOEditingContext aContext,
- ClassLoader aClassLoader )
- throws IOException
- {
- super( anInputStream, aContext, aClassLoader );
- }
-
- protected Object resolveObject(Object anObject) throws IOException
- {
- if ( anObject instanceof GlobalIDMarker )
- {
- return editingContext.faultForGlobalID(
- ((GlobalIDMarker)anObject).getID(), editingContext );
- }
- return super.resolveObject( anObject );
- }
- }
-
+ if (anObject instanceof EOEditingContext)
+ return marker;
+ return anObject;
+ }
+
+ }
+
+ /**
+ * A ContextObjectOutputStream that replaces any objects registered in the
+ * source editing context with markers to be used in ContextObjectInputStream.
+ */
+ static private class TransposingContextObjectOutputStream extends ContextObjectOutputStream {
+ protected Object rootObject;
+
+ /**
+ * Specifies the output stream to wrap, the source context containing objects
+ * that should be replaced if found, and the object which should not be
+ * re-registered, which is typically the object being cloned, but may be null.
+ */
+ public TransposingContextObjectOutputStream(OutputStream anOutputStream, EOEditingContext aContext,
+ Object anObject) throws IOException {
+ super(anOutputStream, aContext);
+ rootObject = anObject;
+ }
+
+ protected Object replaceObject(Object anObject) throws IOException {
+ if (anObject == rootObject)
+ return anObject;
+ if (editingContext != null) {
+ EOGlobalID id = editingContext.globalIDForObject(anObject);
+ if (id != null) {
+ Object result = new GlobalIDMarker(id);
+ // System.out.println( "KeyValueCodingUtilities.replaceObject: returning: " +
+ // result );
+ return result;
+ }
+ }
+ return super.replaceObject(anObject);
+ }
+
+ }
+
+ /**
+ * A marker class so references to objects registered in editing contexts get
+ * transposed rather than cloned.
+ */
+ static private class GlobalIDMarker implements Serializable {
+ private EOGlobalID id;
+
+ public GlobalIDMarker(EOGlobalID anID) {
+ id = anID;
+ }
+
+ public EOGlobalID getID() {
+ return id;
+ }
+
+ public String toString() {
+ return "[GlobalIDMarker:" + id + "]";
+ }
+ }
+
+ /**
+ * A marker class so references an object's editing context gets transposed
+ * rather than cloned.
+ */
+ static private class EditingContextMarker implements Serializable {
+ // just a marker class - no implementation necessary
+ }
+
+ /**
+ * An ObjectInputStream that replaces any markers from ContextObjectOutputStream
+ * with objects registered in the destination editing context.
+ */
+ static private class ContextObjectInputStream extends ObjectInputStream {
+ protected EOEditingContext editingContext;
+ protected ClassLoader classLoader;
+
+ /**
+ * Specifies the output stream to wrap, the source context containing objects
+ * that should be to replace any markers. The class loader may be null.
+ */
+ public ContextObjectInputStream(InputStream anInputStream, EOEditingContext aContext, ClassLoader aClassLoader)
+ throws IOException {
+ super(anInputStream);
+ editingContext = aContext;
+ classLoader = aClassLoader;
+ if (classLoader == null) {
+ classLoader = KeyValueCodingUtilities.class.getClassLoader();
+ }
+ try {
+ enableResolveObject(true);
+ } catch (Exception exc) {
+ exc.printStackTrace();
+ }
+ }
+
+ protected Object resolveObject(Object anObject) throws IOException {
+ if (anObject instanceof EditingContextMarker) {
+ return editingContext;
+ }
+ return anObject;
+ }
+
+ protected Class resolveClass(ObjectStreamClass v) throws IOException, ClassNotFoundException {
+ return classLoader.loadClass(v.getName());
+ }
+ }
+
+ /**
+ * A ContextObjectInputStream that replaces any markers from
+ * TransposingContextObjectOutputStream with objects registered in the
+ * destination editing context.
+ */
+ static private class TransposingContextObjectInputStream extends ContextObjectInputStream {
+ /**
+ * Specifies the output stream to wrap, the source context containing objects
+ * that should be to replace any markers.
+ */
+ public TransposingContextObjectInputStream(InputStream anInputStream, EOEditingContext aContext,
+ ClassLoader aClassLoader) throws IOException {
+ super(anInputStream, aContext, aClassLoader);
+ }
+
+ protected Object resolveObject(Object anObject) throws IOException {
+ if (anObject instanceof GlobalIDMarker) {
+ return editingContext.faultForGlobalID(((GlobalIDMarker) anObject).getID(), editingContext);
+ }
+ return super.resolveObject(anObject);
+ }
+ }
+
}
/*
- * $Log$
- * Revision 1.3 2006/02/18 22:46:44 cgruber
- * Add Surrogate map from .util into control's internal package, and fix imports.
+ * $Log$ Revision 1.3 2006/02/18 22:46:44 cgruber Add Surrogate map from .util
+ * into control's internal package, and fix imports.
*
- * Revision 1.2 2006/02/16 16:47:14 cgruber
- * Move some classes in to "internal" packages and re-work imports, etc.
+ * Revision 1.2 2006/02/16 16:47:14 cgruber Move some classes in to "internal"
+ * packages and re-work imports, etc.
*
- * Also use UnsupportedOperationExceptions where appropriate, instead of WotonomyExceptions.
+ * Also use UnsupportedOperationExceptions where appropriate, instead of
+ * WotonomyExceptions.
*
- * Revision 1.1 2006/02/16 13:19:57 cgruber
- * Check in all sources in eclipse-friendly maven-enabled packages.
+ * Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in
+ * eclipse-friendly maven-enabled packages.
*
- * Revision 1.15 2003/01/21 22:30:10 mpowers
- * thaw() now allows you to pass in a class loader.
+ * Revision 1.15 2003/01/21 22:30:10 mpowers thaw() now allows you to pass in a
+ * class loader.
*
- * Revision 1.14 2002/05/15 13:46:35 mpowers
- * Exposed freeze and thaw as public.
+ * Revision 1.14 2002/05/15 13:46:35 mpowers Exposed freeze and thaw as public.
*
- * Revision 1.13 2001/08/22 19:25:13 mpowers
- * Added (and commented out) profiling code for freeze.
+ * Revision 1.13 2001/08/22 19:25:13 mpowers Added (and commented out) profiling
+ * code for freeze.
*
- * Revision 1.12 2001/05/06 18:27:10 mpowers
- * More broadly catching editing contexts for now.
+ * Revision 1.12 2001/05/06 18:27:10 mpowers More broadly catching editing
+ * contexts for now.
*
- * Revision 1.11 2001/05/05 13:18:49 mpowers
- * Fixed: transposing output stream was not returning the object to replace.
+ * Revision 1.11 2001/05/05 13:18:49 mpowers Fixed: transposing output stream
+ * was not returning the object to replace.
*
- * Revision 1.10 2001/05/04 16:57:56 mpowers
- * Now correctly transposing references to editing contexts when
- * cloning/copying between editing contexts.
+ * Revision 1.10 2001/05/04 16:57:56 mpowers Now correctly transposing
+ * references to editing contexts when cloning/copying between editing contexts.
*
- * Revision 1.9 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.9 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.8 2001/05/02 15:47:40 mpowers
- * Fixed the pernicious problem with reverts: recordObject was recording
- * a snapshot of the clone before the transposition-copy happened,
- * so the revert object would lose all of its transposed relationships.
+ * Revision 1.8 2001/05/02 15:47:40 mpowers Fixed the pernicious problem with
+ * reverts: recordObject was recording a snapshot of the clone before the
+ * transposition-copy happened, so the revert object would lose all of its
+ * transposed relationships.
*
- * Revision 1.7 2001/04/30 12:33:17 mpowers
- * Fixed problem with use of EONullValue.nullValue(), which can't be used
- * when we're serializably duplicating objects.
+ * Revision 1.7 2001/04/30 12:33:17 mpowers Fixed problem with use of
+ * EONullValue.nullValue(), which can't be used when we're serializably
+ * duplicating objects.
*
- * Revision 1.6 2001/04/30 02:14:25 mpowers
- * Copying should call takeStoredValueForKeys.
+ * Revision 1.6 2001/04/30 02:14:25 mpowers Copying should call
+ * takeStoredValueForKeys.
*
- * Revision 1.5 2001/04/29 22:02:45 mpowers
- * Work on id transposing between editing contexts.
+ * Revision 1.5 2001/04/29 22:02:45 mpowers Work on id transposing between
+ * editing contexts.
*
- * Revision 1.4 2001/04/29 02:29:31 mpowers
- * Debugging relationship faulting.
+ * Revision 1.4 2001/04/29 02:29:31 mpowers Debugging relationship faulting.
*
- * Revision 1.3 2001/04/28 16:18:44 mpowers
- * Implementing relationships.
+ * Revision 1.3 2001/04/28 16:18:44 mpowers Implementing relationships.
*
- * Revision 1.2 2001/04/28 14:12:23 mpowers
- * Refactored cloning/copying into KeyValueCodingUtilities.
+ * Revision 1.2 2001/04/28 14:12:23 mpowers Refactored cloning/copying into
+ * KeyValueCodingUtilities.
*
- * Revision 1.1 2001/04/27 23:41:12 mpowers
- * Contributing file for KeyValueCodingUtilities.
+ * Revision 1.1 2001/04/27 23:41:12 mpowers Contributing file for
+ * KeyValueCodingUtilities.
*
*
*/
-
-