From 40a9d99496e098562f090fb7ffce9e749011b131 Mon Sep 17 00:00:00 2001 From: Benjamin Culkin Date: Mon, 20 May 2024 17:58:16 -0400 Subject: Formatting pass --- .../wotonomy/access/EOAccessArrayFaultHandler.java | 40 +- .../net/wotonomy/access/EOAccessFaultHandler.java | 39 +- .../access/EOAccessGenericFaultHandler.java | 33 +- .../java/net/wotonomy/access/EOAccessLock.java | 19 +- .../main/java/net/wotonomy/access/EOAdaptor.java | 81 +- .../java/net/wotonomy/access/EOAdaptorChannel.java | 110 +- .../java/net/wotonomy/access/EOAdaptorContext.java | 39 +- .../net/wotonomy/access/EOAdaptorOperation.java | 37 +- .../main/java/net/wotonomy/access/EOAttribute.java | 114 +- .../main/java/net/wotonomy/access/EODatabase.java | 60 +- .../net/wotonomy/access/EODatabaseChannel.java | 37 +- .../net/wotonomy/access/EODatabaseContext.java | 338 +- .../net/wotonomy/access/EODatabaseOperation.java | 19 +- .../main/java/net/wotonomy/access/EOEntity.java | 202 +- .../wotonomy/access/EOEntityClassDescription.java | 55 +- .../wotonomy/access/EOGeneralAdaptorException.java | 25 +- .../src/main/java/net/wotonomy/access/EOJoin.java | 22 +- .../src/main/java/net/wotonomy/access/EOModel.java | 131 +- .../java/net/wotonomy/access/EOModelGroup.java | 79 +- .../main/java/net/wotonomy/access/EOProperty.java | 21 +- .../wotonomy/access/EOPropertyListEncoding.java | 34 +- .../wotonomy/access/EOQualifierSQLGeneration.java | 77 +- .../java/net/wotonomy/access/EORelationship.java | 113 +- .../java/net/wotonomy/access/EOSQLExpression.java | 170 +- .../wotonomy/access/EOSQLExpressionFactory.java | 44 +- .../net/wotonomy/access/EOStoredProcedure.java | 61 +- .../net/wotonomy/control/AbstractObjectStore.java | 1350 +++-- .../main/java/net/wotonomy/control/ArrayFault.java | 322 +- .../java/net/wotonomy/control/ChildDataSource.java | 282 +- .../java/net/wotonomy/control/EOAndQualifier.java | 180 +- .../net/wotonomy/control/EOClassDescription.java | 990 ++-- .../wotonomy/control/EOCooperatingObjectStore.java | 63 +- .../java/net/wotonomy/control/EOCustomObject.java | 1158 ++-- .../java/net/wotonomy/control/EODataSource.java | 230 +- .../net/wotonomy/control/EODatabaseDataSource.java | 551 +- .../net/wotonomy/control/EODeferredFaulting.java | 36 +- .../net/wotonomy/control/EODelayedObserver.java | 209 +- .../wotonomy/control/EODelayedObserverQueue.java | 446 +- .../net/wotonomy/control/EOEditingContext.java | 5547 +++++++++----------- .../net/wotonomy/control/EOEnterpriseObject.java | 352 +- .../java/net/wotonomy/control/EOFaultHandler.java | 40 +- .../main/java/net/wotonomy/control/EOFaulting.java | 97 +- .../net/wotonomy/control/EOFetchSpecification.java | 847 ++- .../java/net/wotonomy/control/EOGenericRecord.java | 214 +- .../main/java/net/wotonomy/control/EOGlobalID.java | 88 +- .../wotonomy/control/EOIntegralKeyGlobalID.java | 38 +- .../wotonomy/control/EOKeyComparisonQualifier.java | 59 +- .../java/net/wotonomy/control/EOKeyGlobalID.java | 160 +- .../net/wotonomy/control/EOKeyValueArchiver.java | 32 +- .../net/wotonomy/control/EOKeyValueArchiving.java | 21 +- .../net/wotonomy/control/EOKeyValueCoding.java | 166 +- .../control/EOKeyValueCodingAdditions.java | 245 +- .../wotonomy/control/EOKeyValueCodingSupport.java | 338 +- .../net/wotonomy/control/EOKeyValueQualifier.java | 224 +- .../net/wotonomy/control/EOKeyValueUnarchiver.java | 46 +- .../java/net/wotonomy/control/EONotQualifier.java | 124 +- .../java/net/wotonomy/control/EONullValue.java | 143 +- .../java/net/wotonomy/control/EOObjectStore.java | 465 +- .../wotonomy/control/EOObjectStoreCoordinator.java | 238 +- .../net/wotonomy/control/EOObserverCenter.java | 727 ++- .../java/net/wotonomy/control/EOObserverProxy.java | 125 +- .../java/net/wotonomy/control/EOObserving.java | 36 +- .../java/net/wotonomy/control/EOOrQualifier.java | 183 +- .../java/net/wotonomy/control/EOQualifier.java | 1089 ++-- .../wotonomy/control/EOQualifierEvaluation.java | 24 +- .../control/EORelationshipManipulation.java | 80 +- .../java/net/wotonomy/control/EOSortOrdering.java | 562 +- .../net/wotonomy/control/EOTemporaryGlobalID.java | 350 +- .../java/net/wotonomy/control/EOValidation.java | 82 +- .../net/wotonomy/control/EOVectorKeyGlobalID.java | 34 +- .../java/net/wotonomy/control/EditingContext.java | 441 +- .../wotonomy/control/KeyValueCodingUtilities.java | 1140 ++-- .../java/net/wotonomy/control/ObservableArray.java | 485 +- .../net/wotonomy/control/OrderedDataSource.java | 48 +- .../net/wotonomy/control/PropertyDataSource.java | 863 ++- .../net/wotonomy/control/internal/Surrogate.java | 279 +- 76 files changed, 10874 insertions(+), 12975 deletions(-) (limited to 'projects/net.wotonomy.persistence/src/main') diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessArrayFaultHandler.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessArrayFaultHandler.java index 1aafa13..ebb8199 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessArrayFaultHandler.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessArrayFaultHandler.java @@ -21,25 +21,31 @@ import net.wotonomy.control.EOEditingContext; import net.wotonomy.control.EOKeyGlobalID; /** -* A fault handler for to-many relationships. -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/public class EOAccessArrayFaultHandler extends EOAccessGenericFaultHandler { + * A fault handler for to-many relationships. + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public class EOAccessArrayFaultHandler extends EOAccessGenericFaultHandler { protected EOKeyGlobalID _sourceID; protected String _relation; - public EOAccessArrayFaultHandler(EOKeyGlobalID sourceID, String relationName, EODatabaseContext dbc, EOEditingContext ec) { + public EOAccessArrayFaultHandler(EOKeyGlobalID sourceID, String relationName, EODatabaseContext dbc, + EOEditingContext ec) { super(); _sourceID = sourceID; _relation = relationName; setContext(dbc, ec); } - /* (non-Javadoc) - * @see net.wotonomy.control.EOFaultHandler#completeInitializationOfObject(java.lang.Object) + /* + * (non-Javadoc) + * + * @see + * net.wotonomy.control.EOFaultHandler#completeInitializationOfObject(java.lang. + * Object) */ public void completeInitializationOfObject(Object obj) { // TODO Auto-generated method stub @@ -56,16 +62,16 @@ import net.wotonomy.control.EOKeyGlobalID; } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.1 2003/08/19 19:53:20 chochos - * EOAccess fault handlers (still incomplete) + * Revision 1.1 2003/08/19 19:53:20 chochos EOAccess fault handlers (still + * incomplete) * */ diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessFaultHandler.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessFaultHandler.java index d4cabe9..0690295 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessFaultHandler.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessFaultHandler.java @@ -21,13 +21,14 @@ import net.wotonomy.control.EOEditingContext; import net.wotonomy.control.EOKeyGlobalID; /** -* A fault handler for single objects. Usually the destinations of a -* to-one relationship. -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/public class EOAccessFaultHandler extends EOAccessGenericFaultHandler { + * A fault handler for single objects. Usually the destinations of a to-one + * relationship. + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public class EOAccessFaultHandler extends EOAccessGenericFaultHandler { protected EOKeyGlobalID _gid; @@ -37,8 +38,12 @@ import net.wotonomy.control.EOKeyGlobalID; setContext(dbc, ec); } - /* (non-Javadoc) - * @see net.wotonomy.control.EOFaultHandler#completeInitializationOfObject(java.lang.Object) + /* + * (non-Javadoc) + * + * @see + * net.wotonomy.control.EOFaultHandler#completeInitializationOfObject(java.lang. + * Object) */ public void completeInitializationOfObject(Object obj) { // TODO Auto-generated method stub @@ -51,16 +56,16 @@ import net.wotonomy.control.EOKeyGlobalID; } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.1 2003/08/19 19:53:20 chochos - * EOAccess fault handlers (still incomplete) + * Revision 1.1 2003/08/19 19:53:20 chochos EOAccess fault handlers (still + * incomplete) * */ diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessGenericFaultHandler.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessGenericFaultHandler.java index 6876151..31378f4 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessGenericFaultHandler.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessGenericFaultHandler.java @@ -21,12 +21,12 @@ import net.wotonomy.control.EOEditingContext; import net.wotonomy.control.EOFaultHandler; /** -* A generic fault handler for EOAccess. -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * A generic fault handler for EOAccess. + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public abstract class EOAccessGenericFaultHandler extends EOFaultHandler { protected EODatabaseContext _dbContext; @@ -36,7 +36,9 @@ public abstract class EOAccessGenericFaultHandler extends EOFaultHandler { super(); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see net.wotonomy.control.EOFaultHandler#faultWillFire(java.lang.Object) */ public void faultWillFire(Object obj) { @@ -59,17 +61,16 @@ public abstract class EOAccessGenericFaultHandler extends EOFaultHandler { } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.1 2003/08/19 19:53:20 chochos - * EOAccess fault handlers (still incomplete) + * Revision 1.1 2003/08/19 19:53:20 chochos EOAccess fault handlers (still + * incomplete) * */ - \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessLock.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessLock.java index 28199c5..f305579 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessLock.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessLock.java @@ -20,8 +20,8 @@ package net.wotonomy.access; import net.wotonomy.foundation.NSRecursiveLock; /** - * This class offers a very simple interface to a global locking - * mechanism to be used by the whole access layer. + * This class offers a very simple interface to a global locking mechanism to be + * used by the whole access layer. * * @author ezamudio@nasoft.com * @author $Author: cgruber $ @@ -45,16 +45,15 @@ public class EOAccessLock { } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:13 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ Revision 1.2 2006/02/16 16:47:13 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.1 2003/08/29 20:43:25 chochos - * a global access layer lock + * Revision 1.1 2003/08/29 20:43:25 chochos a global access layer lock * */ diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptor.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptor.java index 28295d1..17d6454 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptor.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptor.java @@ -26,11 +26,11 @@ import net.wotonomy.foundation.NSMutableDictionary; import net.wotonomy.foundation.NSTimestamp; /** -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public abstract class EOAdaptor { @@ -48,6 +48,7 @@ public abstract class EOAdaptor { /** * Creates an adaptor with model's adaptorName and sets its connection * dictionary to the model's connection dictionary. + * * @param model The model to take adaptorName and connectionDictionary from. * @return The adaptor specified in model. */ @@ -64,11 +65,13 @@ public abstract class EOAdaptor { } /** - * Instantiates an adaptor of a concrete EOAdaptor subclass, based on name. - * If name is a fully qualified class name, then it returns an instance of that class - * by invoking the constructor with a string argument. Otherwise, it - * tries to find a class called (name)Adaptor in a package called - * net.wotonomy.(lowercase name)adaptor; if it can't find one, an exception is raised. + * Instantiates an adaptor of a concrete EOAdaptor subclass, based on name. If + * name is a fully qualified class name, then it returns an instance of that + * class by invoking the constructor with a string argument. Otherwise, it tries + * to find a class called (name)Adaptor in a package called + * net.wotonomy.(lowercase name)adaptor; if it can't find one, an exception is + * raised. + * * @param name The name of the adaptor, or a fully qualified class name. * @return */ @@ -78,10 +81,10 @@ public abstract class EOAdaptor { if (name.endsWith("Adaptor") && name.indexOf('.') > 0) { cname = name; int lastdot = name.lastIndexOf('.'); - //take off the package and the 'Adaptor' suffix + // take off the package and the 'Adaptor' suffix name = cname.substring(lastdot, cname.length() - 7); } else { - //construct the fully qualified class name + // construct the fully qualified class name cname = "net.wotonomy." + name.toLowerCase() + "adaptor." + name + "Adaptor"; } try { @@ -92,12 +95,14 @@ public abstract class EOAdaptor { EOAdaptor adaptor = null; java.lang.reflect.Constructor callme = null; try { - callme = adaptorClass.getConstructor(new Class[]{ String.class }); - adaptor = (EOAdaptor)callme.newInstance((Object[])new String[]{ name }); + callme = adaptorClass.getConstructor(new Class[] { String.class }); + adaptor = (EOAdaptor) callme.newInstance((Object[]) new String[] { name }); } catch (ClassCastException ex) { - throw new IllegalArgumentException("Class " + adaptorClass.getName() + " must inherit from net.wotonomy.access.EOAdaptor"); - }catch (Exception ex) { - throw new IllegalArgumentException("Cannot find or invoke constructor with name argument in class " + adaptorClass.getName()); + throw new IllegalArgumentException( + "Class " + adaptorClass.getName() + " must inherit from net.wotonomy.access.EOAdaptor"); + } catch (Exception ex) { + throw new IllegalArgumentException( + "Cannot find or invoke constructor with name argument in class " + adaptorClass.getName()); } return adaptor; } @@ -105,8 +110,9 @@ public abstract class EOAdaptor { public static void setExpressionClassName(String expClassName, String adaptorClassName) { _expressionClassesByName.setObjectForKey(expClassName, adaptorClassName); } + public static String expressionClassName(String adaptorClassName) { - return (String)_expressionClassesByName.objectForKey(adaptorClassName); + return (String) _expressionClassesByName.objectForKey(adaptorClassName); } public void assignExternalInfoForAttribute(EOAttribute attribute) { @@ -126,11 +132,11 @@ public abstract class EOAdaptor { public void assignExternalInfoForEntireModel(EOModel model) { NSArray ents = model.entities(); for (int i = 0; i < ents.count(); i++) { - EOEntity e = (EOEntity)ents.objectAtIndex(i); - //TODO: check that entity is not a prototypes entity + EOEntity e = (EOEntity) ents.objectAtIndex(i); + // TODO: check that entity is not a prototypes entity NSArray atts = e.attributes(); for (int j = 0; j < atts.count(); j++) { - EOAttribute a = (EOAttribute)atts.objectAtIndex(i); + EOAttribute a = (EOAttribute) atts.objectAtIndex(i); assignExternalInfoForAttribute(a); } assignExternalInfoForEntity(e); @@ -149,6 +155,7 @@ public abstract class EOAdaptor { public void setConnectionDictionary(NSDictionary connection) { _connectionDictionary = connection; } + public NSDictionary connectionDictionary() { return _connectionDictionary; } @@ -205,19 +212,19 @@ public abstract class EOAdaptor { if (value == NSKeyValueCoding.NullValue) return value; if (value instanceof String) - return fetchedValueForStringValue((String)value, attr); + return fetchedValueForStringValue((String) value, attr); if (value instanceof NSData) - return fetchedValueForDataValue((NSData)value, attr); + return fetchedValueForDataValue((NSData) value, attr); if (value instanceof Number) - return fetchedValueForNumberValue((Number)value, attr); + return fetchedValueForNumberValue((Number) value, attr); if (value instanceof NSTimestamp) - return fetchedValueForDateValue((NSTimestamp)value, attr); + return fetchedValueForDateValue((NSTimestamp) value, attr); return value; } public void handleDroppedConnection() { for (int i = 0; i < _contexts.count(); i++) { - EOAdaptorContext c = (EOAdaptorContext)_contexts.objectAtIndex(i); + EOAdaptorContext c = (EOAdaptorContext) _contexts.objectAtIndex(i); c.transactionDidRollback(); c.handleDroppedConnection(); } @@ -226,7 +233,7 @@ public abstract class EOAdaptor { public boolean hasOpenChannels() { for (int i = 0; i < _contexts.count(); i++) { - EOAdaptorContext c = (EOAdaptorContext)_contexts.objectAtIndex(i); + EOAdaptorContext c = (EOAdaptorContext) _contexts.objectAtIndex(i); if (c.hasOpenChannels()) return true; } @@ -251,19 +258,19 @@ public abstract class EOAdaptor { } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.2 2005/12/08 06:52:32 cgruber - * Move tests, improve build.xml, and make certain casts explicit so that Java 1.5 doesn't complain about varargs. + * Revision 1.2 2005/12/08 06:52:32 cgruber Move tests, improve build.xml, and + * make certain casts explicit so that Java 1.5 doesn't complain about varargs. * - * Revision 1.1 2003/08/13 00:37:45 chochos - * an almost complete implementation of the abstract adaptor-layer classes + * Revision 1.1 2003/08/13 00:37:45 chochos an almost complete implementation of + * the abstract adaptor-layer classes * */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptorChannel.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptorChannel.java index 09b8a6d..44b3401 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptorChannel.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptorChannel.java @@ -24,11 +24,11 @@ import net.wotonomy.foundation.NSDictionary; import net.wotonomy.foundation.NSMutableDictionary; /** -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public abstract class EOAdaptorChannel { protected EOAdaptorContext _context; @@ -102,7 +102,7 @@ public abstract class EOAdaptorChannel { public NSMutableDictionary dictionaryWithObjectsForAttributes(Object[] values, NSArray attributes) { Object[] keys = new Object[attributes.count()]; for (int i = 0; i < attributes.count(); i++) - keys[i] = ((EOAttribute)attributes.objectAtIndex(i)).name(); + keys[i] = ((EOAttribute) attributes.objectAtIndex(i)).name(); return new NSMutableDictionary(values, keys); } @@ -150,57 +150,60 @@ public abstract class EOAdaptorChannel { public void performAdaptorOperation(EOAdaptorOperation operation) { int opcode = operation.adaptorOperator(); switch (opcode) { - case EODatabaseOperation.AdaptorLockOperator: - if (operation.entity() == null) - throw new EOGeneralAdaptorException("A lock operation must have an entity assigned to it.", + case EODatabaseOperation.AdaptorLockOperator: + if (operation.entity() == null) + throw new EOGeneralAdaptorException("A lock operation must have an entity assigned to it.", new NSDictionary(operation, "operation")); - if (operation.qualifier() == null) - throw new EOGeneralAdaptorException("A lock operation must have a qualifier assigned to it.", + if (operation.qualifier() == null) + throw new EOGeneralAdaptorException("A lock operation must have a qualifier assigned to it.", new NSDictionary(operation, "operation")); - if (operation.qualifier() == null) - throw new EOGeneralAdaptorException("A lock operation must have changedValues assigned to it.", + if (operation.qualifier() == null) + throw new EOGeneralAdaptorException("A lock operation must have changedValues assigned to it.", new NSDictionary(operation, "operation")); - lockRowComparingAttributes(operation.attributes(), operation.entity(), operation.qualifier(), operation.changedValues()); - break; - case EODatabaseOperation.AdaptorInsertOperator: - if (operation.entity() == null) - throw new EOGeneralAdaptorException("An insert operation must have an entity assigned to it.", + lockRowComparingAttributes(operation.attributes(), operation.entity(), operation.qualifier(), + operation.changedValues()); + break; + case EODatabaseOperation.AdaptorInsertOperator: + if (operation.entity() == null) + throw new EOGeneralAdaptorException("An insert operation must have an entity assigned to it.", new NSDictionary(operation, "operation")); - if (operation.changedValues() == null) - throw new EOGeneralAdaptorException("An insert operation must have changedValues assigned to it.", + if (operation.changedValues() == null) + throw new EOGeneralAdaptorException("An insert operation must have changedValues assigned to it.", new NSDictionary(operation, "operation")); - insertRow(operation.changedValues(), operation.entity()); - break; - case EODatabaseOperation.AdaptorUpdateOperator: - if (operation.entity() == null) - throw new EOGeneralAdaptorException("An update operation must have an entity assigned to it.", + insertRow(operation.changedValues(), operation.entity()); + break; + case EODatabaseOperation.AdaptorUpdateOperator: + if (operation.entity() == null) + throw new EOGeneralAdaptorException("An update operation must have an entity assigned to it.", new NSDictionary(operation, "operation")); - if (operation.changedValues() == null) - throw new EOGeneralAdaptorException("An update operation must have changedValues assigned to it.", + if (operation.changedValues() == null) + throw new EOGeneralAdaptorException("An update operation must have changedValues assigned to it.", new NSDictionary(operation, "operation")); - updateValuesInRowsDescribedByQualifier(operation.changedValues(), operation.qualifier(), operation.entity()); - break; - case EODatabaseOperation.AdaptorDeleteOperator: - if (operation.entity() == null) - throw new EOGeneralAdaptorException("A delete operation must have an entity assigned to it.", + updateValuesInRowsDescribedByQualifier(operation.changedValues(), operation.qualifier(), + operation.entity()); + break; + case EODatabaseOperation.AdaptorDeleteOperator: + if (operation.entity() == null) + throw new EOGeneralAdaptorException("A delete operation must have an entity assigned to it.", new NSDictionary(operation, "operation")); - deleteRowsDescribedByQualifier(operation.qualifier(), operation.entity()); - break; - case EODatabaseOperation.AdaptorStoredProcedureOperator: - if (operation.storedProcedure() == null) - throw new EOGeneralAdaptorException("A stored procedure operation must have a stored procedure assigned to it.", + deleteRowsDescribedByQualifier(operation.qualifier(), operation.entity()); + break; + case EODatabaseOperation.AdaptorStoredProcedureOperator: + if (operation.storedProcedure() == null) + throw new EOGeneralAdaptorException( + "A stored procedure operation must have a stored procedure assigned to it.", new NSDictionary(operation, "operation")); - executeStoredProcedure(operation.storedProcedure(), operation.changedValues()); - break; - default: - throw new EOGeneralAdaptorException("I don't know how to perform an operation with code " + opcode, + executeStoredProcedure(operation.storedProcedure(), operation.changedValues()); + break; + default: + throw new EOGeneralAdaptorException("I don't know how to perform an operation with code " + opcode, new NSDictionary(operation, "operation")); } } public void performAdaptorOperations(NSArray ops) { for (int i = 0; i < ops.count(); i++) { - EOAdaptorOperation adop = (EOAdaptorOperation)ops.objectAtIndex(i); + EOAdaptorOperation adop = (EOAdaptorOperation) ops.objectAtIndex(i); performAdaptorOperation(adop); } } @@ -217,28 +220,29 @@ public abstract class EOAdaptorChannel { int count = updateValuesInRowsDescribedByQualifier(row, q, entity); if (count != 1) { adaptorContext().rollbackTransaction(); - throw new EOGeneralAdaptorException("The qualifier should describe exactly one row (updated " + count + " rows)"); + throw new EOGeneralAdaptorException( + "The qualifier should describe exactly one row (updated " + count + " rows)"); } adaptorContext().commitTransaction(); } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.2 2005/05/11 15:21:53 cgruber - * Change enum to enumeration, since enum is now a keyword as of Java 5.0 + * Revision 1.2 2005/05/11 15:21:53 cgruber Change enum to enumeration, since + * enum is now a keyword as of Java 5.0 * * A few other comments in the code. * - * Revision 1.1 2003/08/13 00:37:45 chochos - * an almost complete implementation of the abstract adaptor-layer classes + * Revision 1.1 2003/08/13 00:37:45 chochos an almost complete implementation of + * the abstract adaptor-layer classes * */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptorContext.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptorContext.java index aff0ddd..35a1468 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptorContext.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptorContext.java @@ -22,11 +22,11 @@ import net.wotonomy.foundation.NSMutableArray; import net.wotonomy.foundation.NSNotificationCenter; /** -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public abstract class EOAdaptorContext { @@ -63,7 +63,7 @@ public abstract class EOAdaptorContext { public boolean hasBusyChannels() { for (int i = 0; i < _channels.count(); i++) { - EOAdaptorChannel chan = (EOAdaptorChannel)_channels.objectAtIndex(i); + EOAdaptorChannel chan = (EOAdaptorChannel) _channels.objectAtIndex(i); if (chan.isFetchInProgress()) return true; } @@ -72,7 +72,7 @@ public abstract class EOAdaptorContext { public boolean hasOpenChannels() { for (int i = 0; i < _channels.count(); i++) { - EOAdaptorChannel chan = (EOAdaptorChannel)_channels.objectAtIndex(i); + EOAdaptorChannel chan = (EOAdaptorChannel) _channels.objectAtIndex(i); if (chan.isOpen()) return true; } @@ -85,34 +85,31 @@ public abstract class EOAdaptorContext { public void transactionDidBegin() { _hasOpenTransaction = true; - NSNotificationCenter.defaultCenter().postNotification( - AdaptorContextBeginTransactionNotification, this); + NSNotificationCenter.defaultCenter().postNotification(AdaptorContextBeginTransactionNotification, this); } public void transactionDidCommit() { _hasOpenTransaction = false; - NSNotificationCenter.defaultCenter().postNotification( - AdaptorContextCommitTransactionNotification, this); + NSNotificationCenter.defaultCenter().postNotification(AdaptorContextCommitTransactionNotification, this); } public void transactionDidRollback() { _hasOpenTransaction = false; - NSNotificationCenter.defaultCenter().postNotification( - AdaptorContextRollbackTransactionNotification, this); + NSNotificationCenter.defaultCenter().postNotification(AdaptorContextRollbackTransactionNotification, this); } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.1 2003/08/13 00:37:45 chochos - * an almost complete implementation of the abstract adaptor-layer classes + * Revision 1.1 2003/08/13 00:37:45 chochos an almost complete implementation of + * the abstract adaptor-layer classes * */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptorOperation.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptorOperation.java index 818985d..6c977b9 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptorOperation.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptorOperation.java @@ -22,14 +22,13 @@ import net.wotonomy.foundation.NSArray; import net.wotonomy.foundation.NSDictionary; /** -* Represents a single primitive operation in a database server. -* Can be insert, update, delete, lock a row, or execute a -* stored procedure. -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * Represents a single primitive operation in a database server. Can be insert, + * update, delete, lock a row, or execute a stored procedure. + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public class EOAdaptorOperation { protected EOEntity _entity; @@ -48,6 +47,7 @@ public class EOAdaptorOperation { public void setAdaptorOperator(int adOp) { _adaptorOp = adOp; } + public int adaptorOperator() { return _adaptorOp; } @@ -55,6 +55,7 @@ public class EOAdaptorOperation { public void setAttributes(NSArray atts) { _attributes = atts; } + public NSArray attributes() { return _attributes; } @@ -62,6 +63,7 @@ public class EOAdaptorOperation { public void setChangedValues(NSDictionary values) { _changedValues = values; } + public NSDictionary changedValues() { return _changedValues; } @@ -85,6 +87,7 @@ public class EOAdaptorOperation { public void setException(Throwable t) { _exception = t; } + public Throwable exception() { return _exception; } @@ -92,6 +95,7 @@ public class EOAdaptorOperation { public void setQualifier(EOQualifier q) { _qualifier = q; } + public EOQualifier qualifier() { return _qualifier; } @@ -99,22 +103,23 @@ public class EOAdaptorOperation { public void setStoredProcedure(EOStoredProcedure sp) { _proc = sp; } + public EOStoredProcedure storedProcedure() { return _proc; } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:13 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ Revision 1.2 2006/02/16 16:47:13 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.1 2003/08/13 00:37:45 chochos - * an almost complete implementation of the abstract adaptor-layer classes + * Revision 1.1 2003/08/13 00:37:45 chochos an almost complete implementation of + * the abstract adaptor-layer classes * */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAttribute.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAttribute.java index 8b651ec..d77a162 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAttribute.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAttribute.java @@ -22,18 +22,18 @@ import net.wotonomy.foundation.NSMutableDictionary; import net.wotonomy.foundation.NSSelector; /** -* Represents an attribute inside an entity. Contains mapping data for -* the attribute's external name, external and internal datatypes, etc. -* It can also represent a flattened or derived attribute, or a prototype; -* and they are also used to represent parameters in a stored procedure. -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * Represents an attribute inside an entity. Contains mapping data for the + * attribute's external name, external and internal datatypes, etc. It can also + * represent a flattened or derived attribute, or a prototype; and they are also + * used to represent parameters in a stored procedure. + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { - //These are used for stored procedure parameters. + // These are used for stored procedure parameters. public static final int Void = 0; public static final int InParameter = 1; public static final int OutParameter = 2; @@ -75,26 +75,26 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { public EOAttribute(NSDictionary dict, Object obj) { super(); if (obj instanceof EOEntity) - _entity = (EOEntity)obj; - setName((String)dict.objectForKey("name")); + _entity = (EOEntity) obj; + setName((String) dict.objectForKey("name")); if (dict.objectForKey("columnName") != null) - setColumnName((String)dict.objectForKey("columnName")); + setColumnName((String) dict.objectForKey("columnName")); if (dict.objectForKey("definition") != null) - setDefinition((String)dict.objectForKey("definition")); - _prototypeName = (String)dict.objectForKey("prototypeName"); - setExternalType((String)dict.objectForKey("externalType")); - setClassName((String)dict.objectForKey("valueClassName")); - setValueType((String)dict.objectForKey("valueType")); - _writeFormat = (String)dict.objectForKey("writeFormat"); - _readFormat = (String)dict.objectForKey("readFormat"); + setDefinition((String) dict.objectForKey("definition")); + _prototypeName = (String) dict.objectForKey("prototypeName"); + setExternalType((String) dict.objectForKey("externalType")); + setClassName((String) dict.objectForKey("valueClassName")); + setValueType((String) dict.objectForKey("valueType")); + _writeFormat = (String) dict.objectForKey("writeFormat"); + _readFormat = (String) dict.objectForKey("readFormat"); if (dict.objectForKey("precision") != null) - setPrecision(Integer.parseInt((String)dict.objectForKey("precision"))); + setPrecision(Integer.parseInt((String) dict.objectForKey("precision"))); if (dict.objectForKey("scale") != null) - setScale(Integer.parseInt((String)dict.objectForKey("scale"))); + setScale(Integer.parseInt((String) dict.objectForKey("scale"))); if (dict.objectForKey("width") != null) - setWidth(Integer.parseInt((String)dict.objectForKey("width"))); + setWidth(Integer.parseInt((String) dict.objectForKey("width"))); if (dict.objectForKey("parameterDirection") != null) - setParameterDirection(Integer.parseInt((String)dict.objectForKey("parameterDirection"))); + setParameterDirection(Integer.parseInt((String) dict.objectForKey("parameterDirection"))); setAllowsNull("Y".equals(dict.objectForKey("allowsNull"))); } @@ -105,6 +105,7 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { public void setName(String name) { _name = name; } + public String name() { return _name; } @@ -112,6 +113,7 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { public void setColumnName(String name) { _columnName = name; } + public String columnName() { if (_columnName != null) return _columnName; @@ -124,6 +126,7 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { public void setClassName(String name) { _className = name; } + public String className() { if (_className != null) return _className; @@ -137,6 +140,7 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { _definition = def; _columnName = null; } + public String definition() { if (_definition != null) return _definition; @@ -149,6 +153,7 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { public void setExternalType(String type) { _externalType = type; } + public String externalType() { if (_externalType != null) return _externalType; @@ -162,6 +167,7 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { _allowsNull = flag; _has_allowsNull = true; } + public boolean allowsNull() { if (_has_allowsNull) return _allowsNull; @@ -173,6 +179,7 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { public void setReadOnly(boolean flag) { _readOnly = flag; } + public boolean readOnly() { return _readOnly; } @@ -184,6 +191,7 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { else _prototypeName = null; } + public EOAttribute prototype() { if (_prototypeName != null && _prototype == null) { try { @@ -202,6 +210,7 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { public void setPrecision(int value) { _precision = value; } + public int precision() { if (_precision > 0) return _precision; @@ -213,6 +222,7 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { public void setScale(int value) { _scale = value; } + public int scale() { if (_scale > 0) return _scale; @@ -224,10 +234,11 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { public void setWidth(int value) { _width = value; } + public int width() { if (_width > 0) return _width; - if (prototype() != null) + if (prototype() != null) return _prototype.width(); return _width; } @@ -236,6 +247,7 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { public void setValueClassName(String name) { setClassName(name); } + /** @deprecated Use className() instead. */ public String valueClassName() { return className(); @@ -244,6 +256,7 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { public void setValueType(String type) { _valueType = type; } + public String valueType() { if (_valueType != null) return _valueType; @@ -255,6 +268,7 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { public void setReadFormat(String value) { _readFormat = value; } + public String readFormat() { return _readFormat; } @@ -262,6 +276,7 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { public void setWriteFormat(String value) { _writeFormat = value; } + public String writeFormat() { return _writeFormat; } @@ -270,9 +285,11 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { return (definition() != null); } - /** Determines whether the receiver is a flattened attribute. - * A flattened attribute has as its definition a relationship - * path that can be resolved to an attribute. + /** + * Determines whether the receiver is a flattened attribute. A flattened + * attribute has as its definition a relationship path that can be resolved to + * an attribute. + * * @return true if the receiver is flattened. */ public boolean isFlattened() { @@ -292,6 +309,7 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { public void setParameterDirection(int dir) { _parameterDirection = dir; } + public int parameterDirection() { return _parameterDirection; } @@ -305,6 +323,7 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { public void setUserInfo(NSDictionary value) { _userInfo = value; } + public NSDictionary userInfo() { return _userInfo; } @@ -348,34 +367,31 @@ public class EOAttribute extends EOProperty implements EOPropertyListEncoding { } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:13 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ Revision 1.2 2006/02/16 16:47:13 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.7 2003/08/14 02:13:56 chochos - * implement and use _attributeForPath() + * Revision 1.7 2003/08/14 02:13:56 chochos implement and use + * _attributeForPath() * - * Revision 1.6 2003/08/12 01:45:04 chochos - * added some code to handle prototypes + * Revision 1.6 2003/08/12 01:45:04 chochos added some code to handle prototypes * - * Revision 1.5 2003/08/11 19:38:27 chochos - * Can now read from a file and re-write to another file. + * Revision 1.5 2003/08/11 19:38:27 chochos Can now read from a file and + * re-write to another file. * - * Revision 1.4 2003/08/09 01:35:35 chochos - * implement EOPropertyListEncoding + * Revision 1.4 2003/08/09 01:35:35 chochos implement EOPropertyListEncoding * - * Revision 1.3 2003/08/08 06:52:09 chochos - * isFlattened() works + * Revision 1.3 2003/08/08 06:52:09 chochos isFlattened() works * - * Revision 1.2 2003/08/08 02:15:03 chochos - * added parameterDirection (for use with stored procedures) + * Revision 1.2 2003/08/08 02:15:03 chochos added parameterDirection (for use + * with stored procedures) * - * Revision 1.1 2003/08/07 02:39:45 chochos - * EOAttribute. Can be initialized from a property list. + * Revision 1.1 2003/08/07 02:39:45 chochos EOAttribute. Can be initialized from + * a property list. * -*/ \ No newline at end of file + */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabase.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabase.java index a9177c5..a995290 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabase.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabase.java @@ -28,11 +28,11 @@ import net.wotonomy.foundation.NSMutableDictionary; import net.wotonomy.foundation.NSTimestamp; /** -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public class EODatabase { protected EOAdaptor _adaptor; @@ -98,10 +98,10 @@ public class EODatabase { public EOEntity entityForObject(EOEnterpriseObject eo) { String cname = eo.getClass().getName(); for (int i = 0; i < _models.count(); i++) { - EOModel m = (EOModel)_models.objectAtIndex(i); + EOModel m = (EOModel) _models.objectAtIndex(i); NSArray ents = m.entities(); for (int j = 0; j < ents.count(); j++) { - EOEntity e = (EOEntity)ents.objectAtIndex(i); + EOEntity e = (EOEntity) ents.objectAtIndex(i); if (e.className().equals(cname)) return e; } @@ -111,10 +111,10 @@ public class EODatabase { public EOEntity entityNamed(String name) { for (int i = 0; i < _models.count(); i++) { - EOModel m = (EOModel)_models.objectAtIndex(i); + EOModel m = (EOModel) _models.objectAtIndex(i); NSArray ents = m.entities(); for (int j = 0; j < ents.count(); j++) { - EOEntity e = (EOEntity)ents.objectAtIndex(i); + EOEntity e = (EOEntity) ents.objectAtIndex(i); if (e.name().equals(name)) return e; } @@ -132,13 +132,13 @@ public class EODatabase { public void forgetSnapshotsForGlobalIDs(NSArray gids) { for (int i = 0; i < gids.count(); i++) - forgetSnapshotForGlobalID((EOGlobalID)gids.objectAtIndex(i)); + forgetSnapshotForGlobalID((EOGlobalID) gids.objectAtIndex(i)); } public void handleDroppedConnection() { adaptor().handleDroppedConnection(); for (int i = 0; i < _contexts.count(); i++) { - EODatabaseContext c = (EODatabaseContext)_contexts.objectAtIndex(i); + EODatabaseContext c = (EODatabaseContext) _contexts.objectAtIndex(i); c.handleDroppedConnection(); } } @@ -160,7 +160,7 @@ public class EODatabase { } public void recordSnapshotForSourceGlobalID(NSArray gids, EOGlobalID gid, String name) { - NSMutableDictionary d = (NSMutableDictionary)_snapshots.objectForKey(gid); + NSMutableDictionary d = (NSMutableDictionary) _snapshots.objectForKey(gid); if (d == null) { d = new NSMutableDictionary(); _snapshots.setObjectForKey(d, gid); @@ -175,12 +175,12 @@ public class EODatabase { public void recordToManySnapshots(NSDictionary snaps) { Enumeration enumeration = snaps.keyEnumerator(); while (enumeration.hasMoreElements()) { - EOGlobalID gid = (EOGlobalID)enumeration.nextElement(); - NSDictionary rels = (NSDictionary)snaps.objectForKey(gid); + EOGlobalID gid = (EOGlobalID) enumeration.nextElement(); + NSDictionary rels = (NSDictionary) snaps.objectForKey(gid); Enumeration relEnum = rels.keyEnumerator(); while (relEnum.hasMoreElements()) { - String relName = (String)relEnum.nextElement(); - NSArray gids = (NSArray)rels.objectForKey(relName); + String relName = (String) relEnum.nextElement(); + NSArray gids = (NSArray) rels.objectForKey(relName); recordSnapshotForSourceGlobalID(gids, gid, relName); } } @@ -203,7 +203,7 @@ public class EODatabase { } public NSArray resultCacheForEntityNamed(String name) { - return (NSArray)_resultCache.objectForKey(name); + return (NSArray) _resultCache.objectForKey(name); } public void setResultCache(NSArray cache, String entityName) { @@ -215,7 +215,7 @@ public class EODatabase { } public NSDictionary snapshotForGlobalID(EOGlobalID gid) { - return (NSDictionary)_snapshots.objectForKey(gid); + return (NSDictionary) _snapshots.objectForKey(gid); } public NSDictionary snapshotForGlobalID(EOGlobalID gid, long l) { @@ -223,10 +223,10 @@ public class EODatabase { } public NSArray snapshotForSourceGlobalID(EOGlobalID gid, String name) { - NSDictionary d = (NSDictionary)_snapshots.objectForKey(gid); + NSDictionary d = (NSDictionary) _snapshots.objectForKey(gid); if (d == null) return null; - return (NSArray)d.objectForKey(name); + return (NSArray) d.objectForKey(name); } public NSDictionary snapshotForSourceGlobalID(EOGlobalID gid, String s, long l) { @@ -247,21 +247,21 @@ public class EODatabase { } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:13 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ Revision 1.2 2006/02/16 16:47:13 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.2 2005/05/11 15:21:53 cgruber - * Change enum to enumeration, since enum is now a keyword as of Java 5.0 + * Revision 1.2 2005/05/11 15:21:53 cgruber Change enum to enumeration, since + * enum is now a keyword as of Java 5.0 * * A few other comments in the code. * - * Revision 1.1 2003/08/19 01:54:43 chochos - * The EODatabase layer still needs a lot of work, but it's on its way... + * Revision 1.1 2003/08/19 01:54:43 chochos The EODatabase layer still needs a + * lot of work, but it's on its way... * */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabaseChannel.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabaseChannel.java index 10424e9..72427ef 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabaseChannel.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabaseChannel.java @@ -27,11 +27,11 @@ import net.wotonomy.foundation.NSDictionary; import net.wotonomy.foundation.NSMutableArray; /** -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public class EODatabaseChannel { protected EODatabaseContext _context; @@ -65,14 +65,15 @@ public class EODatabaseChannel { EOGlobalID gid = _currEntity.globalIDForRow(r); Object eo = _currEC.objectForGlobalID(gid); if (eo == null) { - eo = EOClassDescription.classDescriptionForEntityName(_currEntity.name()).createInstanceWithEditingContext(_currEC, gid); + eo = EOClassDescription.classDescriptionForEntityName(_currEntity.name()) + .createInstanceWithEditingContext(_currEC, gid); if (eo instanceof EOKeyValueCodingAdditions) - ((EOKeyValueCodingAdditions)eo).takeValuesFromDictionary(r); + ((EOKeyValueCodingAdditions) eo).takeValuesFromDictionary(r); else EOKeyValueCodingAdditions.DefaultImplementation.takeValuesFromDictionary(eo, r); } else { if (isRefreshingObjects()) { - //TODO: refresh object (how?) + // TODO: refresh object (how?) } } return eo; @@ -120,19 +121,19 @@ public class EODatabaseChannel { } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.2 2003/08/29 21:15:46 chochos - * use EOEntity's globalIDForRow method. + * Revision 1.2 2003/08/29 21:15:46 chochos use EOEntity's globalIDForRow + * method. * - * Revision 1.1 2003/08/19 01:54:43 chochos - * The EODatabase layer still needs a lot of work, but it's on its way... + * Revision 1.1 2003/08/19 01:54:43 chochos The EODatabase layer still needs a + * lot of work, but it's on its way... * */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabaseContext.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabaseContext.java index af696fe..6ee58a5 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabaseContext.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabaseContext.java @@ -42,13 +42,12 @@ import net.wotonomy.foundation.NSMutableArray; import net.wotonomy.foundation.NSMutableDictionary; /** -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public class EODatabaseContext - extends EOCooperatingObjectStore implements NSLocking { + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public class EODatabaseContext extends EOCooperatingObjectStore implements NSLocking { private static Class _contextClass; protected EODatabase _database; @@ -79,7 +78,7 @@ public class EODatabaseContext public EODatabaseChannel availableChannel() { for (int i = 0; i < _channels.count(); i++) { - EODatabaseChannel c = (EODatabaseChannel)_channels.objectAtIndex(i); + EODatabaseChannel c = (EODatabaseChannel) _channels.objectAtIndex(i); if (!c.isFetchInProgress()) return c; } @@ -94,6 +93,7 @@ public class EODatabaseContext public static void setContextClassToRegister(Class contextClass) { _contextClass = contextClass; } + public static Class contextClassToRegister() { if (_contextClass == null) _contextClass = EODatabaseContext.class; @@ -109,21 +109,28 @@ public class EODatabaseContext } public void handleDroppedConnection() { - //TODO: unregister channels + // TODO: unregister channels adaptorContext().handleDroppedConnection(); } - /* (non-Javadoc) - * @see net.wotonomy.control.EOCooperatingObjectStore#ownsGlobalID(net.wotonomy.control.EOGlobalID) + /* + * (non-Javadoc) + * + * @see net.wotonomy.control.EOCooperatingObjectStore#ownsGlobalID(net.wotonomy. + * control.EOGlobalID) */ public boolean ownsGlobalID(EOGlobalID gid) { if (!(gid instanceof EOKeyGlobalID)) return false; - return (database().entityNamed(((EOKeyGlobalID)gid).entityName()) != null); + return (database().entityNamed(((EOKeyGlobalID) gid).entityName()) != null); } - /* (non-Javadoc) - * @see net.wotonomy.control.EOCooperatingObjectStore#ownsObject(net.wotonomy.control.EOEnterpriseObject) + /* + * (non-Javadoc) + * + * @see + * net.wotonomy.control.EOCooperatingObjectStore#ownsObject(net.wotonomy.control + * .EOEnterpriseObject) */ public boolean ownsObject(EOEnterpriseObject eo) { if (eo.entityName() == null) @@ -131,8 +138,12 @@ public class EODatabaseContext return (database().entityNamed(eo.entityName()) != null); } - /* (non-Javadoc) - * @see net.wotonomy.control.EOCooperatingObjectStore#handlesFetchSpecification(net.wotonomy.control.EOFetchSpecification) + /* + * (non-Javadoc) + * + * @see + * net.wotonomy.control.EOCooperatingObjectStore#handlesFetchSpecification(net. + * wotonomy.control.EOFetchSpecification) */ public boolean handlesFetchSpecification(EOFetchSpecification fspec) { String ename = fspec.entityName(); @@ -143,8 +154,13 @@ public class EODatabaseContext return adaptorContext().hasBusyChannels(); } - /* (non-Javadoc) - * @see net.wotonomy.control.EOCooperatingObjectStore#prepareForSaveWithCoordinator(net.wotonomy.control.EOObjectStoreCoordinator, net.wotonomy.control.EOEditingContext) + /* + * (non-Javadoc) + * + * @see + * net.wotonomy.control.EOCooperatingObjectStore#prepareForSaveWithCoordinator( + * net.wotonomy.control.EOObjectStoreCoordinator, + * net.wotonomy.control.EOEditingContext) */ public void prepareForSaveWithCoordinator(EOObjectStoreCoordinator coord, EOEditingContext ec) { // TODO Auto-generated method stub @@ -152,15 +168,21 @@ public class EODatabaseContext _currEC = ec; } - /* (non-Javadoc) - * @see net.wotonomy.control.EOCooperatingObjectStore#recordChangesInEditingContext() + /* + * (non-Javadoc) + * + * @see + * net.wotonomy.control.EOCooperatingObjectStore#recordChangesInEditingContext() */ public void recordChangesInEditingContext() { // TODO insert, delete, update } - /* (non-Javadoc) - * @see net.wotonomy.control.EOCooperatingObjectStore#recordUpdateForObject(net.wotonomy.control.EOEnterpriseObject, net.wotonomy.foundation.NSDictionary) + /* + * (non-Javadoc) + * + * @see net.wotonomy.control.EOCooperatingObjectStore#recordUpdateForObject(net. + * wotonomy.control.EOEnterpriseObject, net.wotonomy.foundation.NSDictionary) */ public void recordUpdateForObject(EOEnterpriseObject eo, NSDictionary changes) { // TODO Auto-generated method stub @@ -175,7 +197,7 @@ public class EODatabaseContext public void recordSnapshotForSourceGlobalID(NSArray gids, EOGlobalID gid, String relationName) { if (_manySnaps == null) throw new IllegalArgumentException("Attempt to record a snapshot without a transaction in progress"); - NSMutableDictionary d = (NSMutableDictionary)_manySnaps.objectForKey(gid); + NSMutableDictionary d = (NSMutableDictionary) _manySnaps.objectForKey(gid); if (d == null) { d = new NSMutableDictionary(); _manySnaps.setObjectForKey(d, gid); @@ -187,13 +209,12 @@ public class EODatabaseContext if (_simpleSnaps == null) throw new IllegalArgumentException("Attempt to record snapshots without a transaction in progress."); _simpleSnaps.addEntriesFromDictionary(snaps); - /* Make sure we don't need to do this instead - Enumeration enumeration = snaps.keyEnumerator(); - while (enumeration.hasMoreElements()) { - EOGlobalID g = (EOGlobalID)enumeration.nextElement(); - NSDictionary d = (NSDictionary)snaps.objectForKey(g); - recordSnapshotForGlobalID(d, g); - }*/ + /* + * Make sure we don't need to do this instead Enumeration enumeration = + * snaps.keyEnumerator(); while (enumeration.hasMoreElements()) { EOGlobalID g = + * (EOGlobalID)enumeration.nextElement(); NSDictionary d = + * (NSDictionary)snaps.objectForKey(g); recordSnapshotForGlobalID(d, g); } + */ } public void recordToManySnapshots(NSDictionary snaps) { @@ -202,18 +223,20 @@ public class EODatabaseContext Enumeration enumeration = snaps.keyEnumerator(); while (enumeration.hasMoreElements()) { Object key = enumeration.nextElement(); - NSDictionary d = (NSDictionary)snaps.objectForKey(key); - NSMutableDictionary d2 = (NSMutableDictionary)_manySnaps.objectForKey(key); + NSDictionary d = (NSDictionary) snaps.objectForKey(key); + NSMutableDictionary d2 = (NSMutableDictionary) _manySnaps.objectForKey(key); if (d2 == null) { d2 = new NSMutableDictionary(); _manySnaps.setObjectForKey(d2, key); } - //this could also be done with many calls to recordSnapshotForSourceGID + // this could also be done with many calls to recordSnapshotForSourceGID d2.addEntriesFromDictionary(d); } } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see net.wotonomy.control.EOCooperatingObjectStore#performChanges() */ public void performChanges() { @@ -221,70 +244,92 @@ public class EODatabaseContext } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see net.wotonomy.control.EOCooperatingObjectStore#commitChanges() */ public void commitChanges() { adaptorContext().commitTransaction(); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see net.wotonomy.control.EOCooperatingObjectStore#rollbackChanges() */ public void rollbackChanges() { adaptorContext().rollbackTransaction(); } - /* (non-Javadoc) - * @see net.wotonomy.control.EOCooperatingObjectStore#valuesForKeys(net.wotonomy.foundation.NSArray, net.wotonomy.control.EOEnterpriseObject) + /* + * (non-Javadoc) + * + * @see + * net.wotonomy.control.EOCooperatingObjectStore#valuesForKeys(net.wotonomy. + * foundation.NSArray, net.wotonomy.control.EOEnterpriseObject) */ public NSDictionary valuesForKeys(NSArray keys, EOEnterpriseObject eo) { // TODO check snapshots; eo could be a fault return eo.valuesForKeys(keys); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see net.wotonomy.foundation.NSLocking#lock() */ public void lock() { EOAccessLock.lock(); } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see net.wotonomy.foundation.NSLocking#unlock() */ public void unlock() { EOAccessLock.unlock(); } - /* (non-Javadoc) - * @see net.wotonomy.control.EOObjectStore#arrayFaultWithSourceGlobalID(net.wotonomy.control.EOGlobalID, java.lang.String, net.wotonomy.control.EOEditingContext) + /* + * (non-Javadoc) + * + * @see + * net.wotonomy.control.EOObjectStore#arrayFaultWithSourceGlobalID(net.wotonomy. + * control.EOGlobalID, java.lang.String, net.wotonomy.control.EOEditingContext) */ - public NSArray arrayFaultWithSourceGlobalID( - EOGlobalID gid, String relName, EOEditingContext ec) { + public NSArray arrayFaultWithSourceGlobalID(EOGlobalID gid, String relName, EOEditingContext ec) { if (!(gid instanceof EOKeyGlobalID)) throw new IllegalArgumentException("an EOKeyGlobalID is needed."); - EOAccessArrayFaultHandler handler = new EOAccessArrayFaultHandler((EOKeyGlobalID)gid, relName, this, ec); + EOAccessArrayFaultHandler handler = new EOAccessArrayFaultHandler((EOKeyGlobalID) gid, relName, this, ec); return new NSArray(handler); } - /* (non-Javadoc) - * @see net.wotonomy.control.EOObjectStore#faultForGlobalID(net.wotonomy.control.EOGlobalID, net.wotonomy.control.EOEditingContext) + /* + * (non-Javadoc) + * + * @see + * net.wotonomy.control.EOObjectStore#faultForGlobalID(net.wotonomy.control. + * EOGlobalID, net.wotonomy.control.EOEditingContext) */ - public /*EOEnterpriseObject*/Object faultForGlobalID(EOGlobalID gid, EOEditingContext ec) { + public /* EOEnterpriseObject */Object faultForGlobalID(EOGlobalID gid, EOEditingContext ec) { if (!(gid instanceof EOKeyGlobalID)) throw new IllegalArgumentException("Cannot fault an object that doesn't have a key global ID."); - EOAccessFaultHandler handler = new EOAccessFaultHandler((EOKeyGlobalID)gid, this, ec); - EOEntity e = database().entityNamed(((EOKeyGlobalID)gid).entityName()); + EOAccessFaultHandler handler = new EOAccessFaultHandler((EOKeyGlobalID) gid, this, ec); + EOEntity e = database().entityNamed(((EOKeyGlobalID) gid).entityName()); Object o = e.classDescriptionForInstances().createInstanceWithEditingContext(ec, gid); EOFaultHandler.makeObjectIntoFault(o, handler); return o; } - /* (non-Javadoc) - * @see net.wotonomy.control.EOObjectStore#faultForRawRow(java.util.Map, java.lang.String, net.wotonomy.control.EOEditingContext) + /* + * (non-Javadoc) + * + * @see net.wotonomy.control.EOObjectStore#faultForRawRow(java.util.Map, + * java.lang.String, net.wotonomy.control.EOEditingContext) */ - public /*EOEnterpriseObject*/ Object faultForRawRow(Map row, String entityName, EOEditingContext ec) { + public /* EOEnterpriseObject */ Object faultForRawRow(Map row, String entityName, EOEditingContext ec) { EOEntity e = database().entityNamed(entityName); EOGlobalID gid = e.globalIDForRow(row); return faultForGlobalID(gid, ec); @@ -299,74 +344,81 @@ public class EODatabaseContext public void forgetSnapshotsForGlobalIDs(List gids) { for (int i = 0; i < gids.size(); i++) { - EOGlobalID g = (EOGlobalID)gids.get(i); + EOGlobalID g = (EOGlobalID) gids.get(i); forgetSnapshotForGlobalID(g); database().forgetSnapshotForGlobalID(g); } } - /* (non-Javadoc) - * @see net.wotonomy.control.EOObjectStore#initializeObject(java.lang.Object, net.wotonomy.control.EOGlobalID, net.wotonomy.control.EOEditingContext) + /* + * (non-Javadoc) + * + * @see net.wotonomy.control.EOObjectStore#initializeObject(java.lang.Object, + * net.wotonomy.control.EOGlobalID, net.wotonomy.control.EOEditingContext) */ - public void initializeObject(/*EOEnterpriseObject*/Object eo, EOGlobalID gid, EOEditingContext ec) { + public void initializeObject(/* EOEnterpriseObject */Object eo, EOGlobalID gid, EOEditingContext ec) { if (gid.isTemporary()) return; NSDictionary snap = snapshotForGlobalID(gid); Object obj = ec.objectForGlobalID(gid); - EOEntity e = database().entityNamed(((EOKeyGlobalID)gid).entityName()); + EOEntity e = database().entityNamed(((EOKeyGlobalID) gid).entityName()); NSArray props = e.classProperties(); for (int i = 0; i < props.count(); i++) { - EOProperty p = (EOProperty)props.objectAtIndex(i); + EOProperty p = (EOProperty) props.objectAtIndex(i); Object val = snap.objectForKey(p.name()); if (p instanceof EOAttribute) { - if ( eo instanceof EOKeyValueCoding ) - { - ((EOKeyValueCoding)eo).takeValueForKey(val, p.name()); - } - else - { - EOKeyValueCodingSupport.takeValueForKey( eo, val, p.name() ); - } + if (eo instanceof EOKeyValueCoding) { + ((EOKeyValueCoding) eo).takeValueForKey(val, p.name()); + } else { + EOKeyValueCodingSupport.takeValueForKey(eo, val, p.name()); + } } else if (p instanceof EORelationship) { - if (((EORelationship)p).isToMany()) { + if (((EORelationship) p).isToMany()) { val = arrayFaultWithSourceGlobalID(gid, p.name(), ec); } else { - EOEntity dest = ((EORelationship)p).destinationEntity(); - EOKeyGlobalID kgid = (EOKeyGlobalID)dest.globalIDForRow(snap); + EOEntity dest = ((EORelationship) p).destinationEntity(); + EOKeyGlobalID kgid = (EOKeyGlobalID) dest.globalIDForRow(snap); val = ec.objectForGlobalID(kgid); if (val == null) val = new EOAccessFaultHandler(kgid, this, ec); } if (val == EOKeyValueCoding.NullValue) val = null; - if ( eo instanceof EOKeyValueCoding ) - { - ((EOKeyValueCoding)eo).takeValueForKey(val, p.name()); - } - else - { - EOKeyValueCodingSupport.takeValueForKey( eo, val, p.name() ); - } + if (eo instanceof EOKeyValueCoding) { + ((EOKeyValueCoding) eo).takeValueForKey(val, p.name()); + } else { + EOKeyValueCodingSupport.takeValueForKey(eo, val, p.name()); + } } } } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see net.wotonomy.control.EOObjectStore#invalidateAllObjects() */ public void invalidateAllObjects() { invalidateObjectsWithGlobalIDs(database().snapshots().allKeys()); } - /* (non-Javadoc) - * @see net.wotonomy.control.EOObjectStore#invalidateObjectsWithGlobalIDs(java.util.List) + /* + * (non-Javadoc) + * + * @see + * net.wotonomy.control.EOObjectStore#invalidateObjectsWithGlobalIDs(java.util. + * List) */ public void invalidateObjectsWithGlobalIDs(List aList) { forgetSnapshotsForGlobalIDs(aList); } - /* (non-Javadoc) - * @see net.wotonomy.control.EOObjectStore#isObjectLockedWithGlobalID(net.wotonomy.control.EOGlobalID, net.wotonomy.control.EOEditingContext) + /* + * (non-Javadoc) + * + * @see + * net.wotonomy.control.EOObjectStore#isObjectLockedWithGlobalID(net.wotonomy. + * control.EOGlobalID, net.wotonomy.control.EOEditingContext) */ public boolean isObjectLockedWithGlobalID(EOGlobalID gid, EOEditingContext ec) { return isObjectLockedWithGlobalID(gid); @@ -376,8 +428,11 @@ public class EODatabaseContext return _lockedObjects.containsObject(gid); } - /* (non-Javadoc) - * @see net.wotonomy.control.EOObjectStore#lockObjectWithGlobalID(net.wotonomy.control.EOGlobalID, net.wotonomy.control.EOEditingContext) + /* + * (non-Javadoc) + * + * @see net.wotonomy.control.EOObjectStore#lockObjectWithGlobalID(net.wotonomy. + * control.EOGlobalID, net.wotonomy.control.EOEditingContext) */ public void lockObjectWithGlobalID(EOGlobalID gid, EOEditingContext ec) { NSDictionary snap = snapshotForGlobalID(gid); @@ -385,7 +440,7 @@ public class EODatabaseContext return; if (!(gid instanceof EOKeyGlobalID)) return; - EOEntity e = database().entityNamed(((EOKeyGlobalID)gid).entityName()); + EOEntity e = database().entityNamed(((EOKeyGlobalID) gid).entityName()); EOQualifier q = e.qualifierForPrimaryKey(snap); EOFetchSpecification fspec = new EOFetchSpecification(e.name(), q, null); fspec.setLocksObjects(true); @@ -394,48 +449,53 @@ public class EODatabaseContext throw new IllegalStateException("Cannot lock object with Global ID " + gid); } - /* (non-Javadoc) - * @see net.wotonomy.control.EOObjectStore#objectsForSourceGlobalID(net.wotonomy.control.EOGlobalID, java.lang.String, net.wotonomy.control.EOEditingContext) + /* + * (non-Javadoc) + * + * @see + * net.wotonomy.control.EOObjectStore#objectsForSourceGlobalID(net.wotonomy. + * control.EOGlobalID, java.lang.String, net.wotonomy.control.EOEditingContext) */ - public NSArray objectsForSourceGlobalID( - EOGlobalID gid, String relationName, EOEditingContext ec) { - EOEnterpriseObject eo = (EOEnterpriseObject)ec.objectForGlobalID(gid); + public NSArray objectsForSourceGlobalID(EOGlobalID gid, String relationName, EOEditingContext ec) { + EOEnterpriseObject eo = (EOEnterpriseObject) ec.objectForGlobalID(gid); if (eo == null) - throw new IllegalStateException("Cannot find object for global ID " + gid + " in specified editing context."); - //Get the source object + throw new IllegalStateException( + "Cannot find object for global ID " + gid + " in specified editing context."); + // Get the source object EOEnterpriseObject source = (EOEnterpriseObject) faultForGlobalID(gid, ec); if (source == null) throw new IllegalStateException("There is no snapshot for source global ID " + gid); - //Check if there is already a value here - NSArray value = (NSArray)source.valueForKey(relationName); + // Check if there is already a value here + NSArray value = (NSArray) source.valueForKey(relationName); EOAccessArrayFaultHandler handler = null; if (value != null) { if (EOFaultHandler.isFault(value)) { - handler = new EOAccessArrayFaultHandler((EOKeyGlobalID)gid, relationName, this, ec); - //TODO: fire the fault an return the value + handler = new EOAccessArrayFaultHandler((EOKeyGlobalID) gid, relationName, this, ec); + // TODO: fire the fault an return the value } else return value; } - //Get the relationship + // Get the relationship EOEntity entity = database().entityNamed(eo.entityName()); EORelationship rel = entity.relationshipNamed(relationName); if (rel == null) - throw new IllegalStateException("Cannot find relationship named " + relationName + " in entity " + entity.name()); + throw new IllegalStateException( + "Cannot find relationship named " + relationName + " in entity " + entity.name()); - //create a fetch specification for this + // create a fetch specification for this EOQualifier q = null; NSArray joins = rel.joins(); NSMutableArray subq = new NSMutableArray(joins.count()); for (int i = 0; i < joins.count(); i++) { - EOJoin j = (EOJoin)joins.objectAtIndex(i); + EOJoin j = (EOJoin) joins.objectAtIndex(i); String key = j.destinationAttribute().name(); Object val = eo.valueForKey(j.sourceAttribute().name()); subq.addObject(new EOKeyValueQualifier(key, EOQualifier.QualifierOperatorEqual, val)); } if (subq.count() == 1) { - q = (EOQualifier)subq.objectAtIndex(0); + q = (EOQualifier) subq.objectAtIndex(0); } else { q = new EOAndQualifier(subq); } @@ -448,8 +508,12 @@ public class EODatabaseContext return res; } - /* (non-Javadoc) - * @see net.wotonomy.control.EOObjectStore#objectsWithFetchSpecification(net.wotonomy.control.EOFetchSpecification, net.wotonomy.control.EOEditingContext) + /* + * (non-Javadoc) + * + * @see + * net.wotonomy.control.EOObjectStore#objectsWithFetchSpecification(net.wotonomy + * .control.EOFetchSpecification, net.wotonomy.control.EOEditingContext) */ public NSArray objectsWithFetchSpecification(EOFetchSpecification fspec, EOEditingContext ec) { EODatabaseChannel channel = availableChannel(); @@ -464,21 +528,28 @@ public class EODatabaseContext return arr; } - /* (non-Javadoc) - * @see net.wotonomy.control.EOObjectStore#refaultObject(java.lang.Object, net.wotonomy.control.EOGlobalID, net.wotonomy.control.EOEditingContext) + /* + * (non-Javadoc) + * + * @see net.wotonomy.control.EOObjectStore#refaultObject(java.lang.Object, + * net.wotonomy.control.EOGlobalID, net.wotonomy.control.EOEditingContext) */ public void refaultObject(Object obj, EOGlobalID gid, EOEditingContext ec) { if (!(gid instanceof EOKeyGlobalID)) throw new IllegalArgumentException("GlobalID must be an EOKeyGlobalID"); if (obj instanceof EOFaulting) - //check if it's already a fault - if (!EOFaultHandler.isFault(obj)) { - ((EOFaulting)obj).turnIntoFault(EOFaultHandler.handlerForFault(obj)); - } + // check if it's already a fault + if (!EOFaultHandler.isFault(obj)) { + ((EOFaulting) obj).turnIntoFault(EOFaultHandler.handlerForFault(obj)); + } } - /* (non-Javadoc) - * @see net.wotonomy.control.EOObjectStore#saveChangesInEditingContext(net.wotonomy.control.EOEditingContext) + /* + * (non-Javadoc) + * + * @see + * net.wotonomy.control.EOObjectStore#saveChangesInEditingContext(net.wotonomy. + * control.EOEditingContext) */ public void saveChangesInEditingContext(EOEditingContext ec) { prepareForSaveWithCoordinator(null, ec); @@ -508,7 +579,7 @@ public class EODatabaseContext public NSDictionary snapshotForGlobalID(EOGlobalID gid) { NSDictionary d = null; if (_simpleSnaps != null) { - d = (NSDictionary)_simpleSnaps.objectForKey(gid); + d = (NSDictionary) _simpleSnaps.objectForKey(gid); } if (d == null) d = database().snapshotForGlobalID(gid); @@ -518,8 +589,8 @@ public class EODatabaseContext public NSArray snapshotForSourceGlobalID(EOGlobalID gid, String name) { NSArray a = null; if (_manySnaps != null) { - NSDictionary d = (NSDictionary)_manySnaps.objectForKey(gid); - a = (NSArray)d.objectForKey(name); + NSDictionary d = (NSDictionary) _manySnaps.objectForKey(gid); + a = (NSArray) d.objectForKey(name); } if (a == null) a = database().snapshotForSourceGlobalID(gid, name); @@ -536,33 +607,32 @@ public class EODatabaseContext } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:13 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ Revision 1.2 2006/02/16 16:47:13 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.5 2005/05/11 15:21:53 cgruber - * Change enum to enumeration, since enum is now a keyword as of Java 5.0 + * Revision 1.5 2005/05/11 15:21:53 cgruber Change enum to enumeration, since + * enum is now a keyword as of Java 5.0 * * A few other comments in the code. * - * Revision 1.4 2003/12/18 15:37:38 mpowers - * Changes to retain ability to work with objects that don't necessarily - * implement EOEnterpriseObject. I would still like to preserve this case - * for general usage, however the access package is free to assume that - * those objects will be EOs and cast appropriately. + * Revision 1.4 2003/12/18 15:37:38 mpowers Changes to retain ability to work + * with objects that don't necessarily implement EOEnterpriseObject. I would + * still like to preserve this case for general usage, however the access + * package is free to assume that those objects will be EOs and cast + * appropriately. * - * Revision 1.3 2003/08/29 21:14:44 chochos - * implement a couple more methods. + * Revision 1.3 2003/08/29 21:14:44 chochos implement a couple more methods. * - * Revision 1.2 2003/08/20 01:16:22 chochos - * more methods have code now, but there's no way to test this yet. The core is still pending. + * Revision 1.2 2003/08/20 01:16:22 chochos more methods have code now, but + * there's no way to test this yet. The core is still pending. * - * Revision 1.1 2003/08/19 01:54:43 chochos - * The EODatabase layer still needs a lot of work, but it's on its way... + * Revision 1.1 2003/08/19 01:54:43 chochos The EODatabase layer still needs a + * lot of work, but it's on its way... * */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabaseOperation.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabaseOperation.java index 596180e..d8bd726 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabaseOperation.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabaseOperation.java @@ -18,11 +18,11 @@ package net.wotonomy.access; /** -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 893 $ -*/ + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 893 $ + */ public class EODatabaseOperation { public static final int AdaptorLockOperator = 0; @@ -38,11 +38,10 @@ public class EODatabaseOperation { } /* - * $Log$ - * Revision 1.1 2006/02/16 13:19:57 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. + * $Log$ Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.1 2003/08/13 00:38:47 chochos - * for the moment, this only contains some constants needed by EOAdaptorChannel and EOAdaptorOperation. + * Revision 1.1 2003/08/13 00:38:47 chochos for the moment, this only contains + * some constants needed by EOAdaptorChannel and EOAdaptorOperation. * */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOEntity.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOEntity.java index 4adc4a1..47a31c0 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOEntity.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOEntity.java @@ -42,14 +42,14 @@ import net.wotonomy.foundation.NSMutableDictionary; import net.wotonomy.foundation.NSPropertyListSerialization; /** -* An EOEntity is a mapping between a Java class and a database table or view. -* It indicates which attributes should be fetched from the table/view, what -* attributes are part of the primary key, what class the entity should map to. -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * An EOEntity is a mapping between a Java class and a database table or view. + * It indicates which attributes should be fetched from the table/view, what + * attributes are part of the primary key, what class the entity should map to. + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public class EOEntity implements EOPropertyListEncoding { protected NSMutableDictionary _attributes = new NSMutableDictionary(); @@ -80,55 +80,55 @@ public class EOEntity implements EOPropertyListEncoding { public EOEntity(NSDictionary dict, Object obj) { super(); - _model = (EOModel)obj; - setName((String)dict.objectForKey("name")); - setExternalName((String)dict.objectForKey("externalName")); - setClassName((String)dict.objectForKey("className")); + _model = (EOModel) obj; + setName((String) dict.objectForKey("name")); + setExternalName((String) dict.objectForKey("externalName")); + setClassName((String) dict.objectForKey("className")); if (dict.objectForKey("internalInfo") != null) - _internalInfo = (NSDictionary)dict.objectForKey("internalInfo"); + _internalInfo = (NSDictionary) dict.objectForKey("internalInfo"); if (dict.objectForKey("userInfo") != null) - _userInfo = (NSDictionary)dict.objectForKey("userInfo"); + _userInfo = (NSDictionary) dict.objectForKey("userInfo"); - //Read the attributes - NSArray atr = (NSArray)dict.objectForKey("attributes"); + // Read the attributes + NSArray atr = (NSArray) dict.objectForKey("attributes"); for (int i = 0; i < atr.count(); i++) { - NSDictionary d = (NSDictionary)atr.objectAtIndex(i); + NSDictionary d = (NSDictionary) atr.objectAtIndex(i); EOAttribute atrib = new EOAttribute(d, this); addAttribute(atrib); } - //Set the primary key - atr = (NSArray)dict.objectForKey("primaryKeyAttributes"); + // Set the primary key + atr = (NSArray) dict.objectForKey("primaryKeyAttributes"); NSMutableArray pka = new NSMutableArray(); for (int i = 0; i < atr.count(); i++) { - EOAttribute a = attributeNamed((String)atr.objectAtIndex(i)); + EOAttribute a = attributeNamed((String) atr.objectAtIndex(i)); pka.addObject(a); } _pkAttributes = new NSArray(pka); _pkAttributeNames = atr; - //attributes used for locking + // attributes used for locking _lockingAttributes.removeAllObjects(); - atr = (NSArray)dict.objectForKey("attributesUsedForLocking"); + atr = (NSArray) dict.objectForKey("attributesUsedForLocking"); for (int i = 0; i < atr.count(); i++) { - String x = (String)atr.objectAtIndex(i); + String x = (String) atr.objectAtIndex(i); EOAttribute a = attributeNamed(x); _lockingAttributes.addObject(a); } - //class properties - atr = (NSArray)dict.objectForKey("classProperties"); + // class properties + atr = (NSArray) dict.objectForKey("classProperties"); if (atr != null) { for (int i = 0; i < atr.count(); i++) if (!_classPropertyNames.containsObject((atr.objectAtIndex(i)))) _classPropertyNames.addObject(atr.objectAtIndex(i)); } - //Read the relationships - atr = (NSArray)dict.objectForKey("relationships"); + // Read the relationships + atr = (NSArray) dict.objectForKey("relationships"); if (atr != null) { for (int i = 0; i < atr.count(); i++) { - NSDictionary d = (NSDictionary)atr.objectAtIndex(i); + NSDictionary d = (NSDictionary) atr.objectAtIndex(i); EORelationship rel = new EORelationship(d, this); addRelationship(rel); } @@ -169,7 +169,7 @@ public class EOEntity implements EOPropertyListEncoding { public EOFetchSpecification fetchSpecificationNamed(String name) { loadFetchSpecifications(); - return (EOFetchSpecification)_fetchSpecs.objectForKey(name); + return (EOFetchSpecification) _fetchSpecs.objectForKey(name); } public NSArray fetchSpecificationNames() { @@ -177,8 +177,8 @@ public class EOEntity implements EOPropertyListEncoding { return _fetchSpecs.allKeys(); } - /** Loads fetch specifications from the .fspec file, - * if one exists. + /** + * Loads fetch specifications from the .fspec file, if one exists. */ private void loadFetchSpecifications() { if (_loadedFetchSpecs) @@ -187,7 +187,7 @@ public class EOEntity implements EOPropertyListEncoding { if (model().path() == null) return; File f = new File(model().path()); - //Read the fetch specification file, if it exists + // Read the fetch specification file, if it exists f = new File(f, name() + ".fspec"); if (!f.exists()) return; @@ -207,11 +207,11 @@ public class EOEntity implements EOPropertyListEncoding { throw new IllegalArgumentException("Cannot read dictionary from " + f); NSArray keys = fdict.allKeys(); - //Unarchive the fetch specification + // Unarchive the fetch specification EOKeyValueUnarchiver unarch = new EOKeyValueUnarchiver(fdict); for (int i = 0; i < keys.count(); i++) { - String k = (String)keys.objectAtIndex(i); - EOFetchSpecification fs = (EOFetchSpecification)unarch.decodeObjectForKey(k); + String k = (String) keys.objectAtIndex(i); + EOFetchSpecification fs = (EOFetchSpecification) unarch.decodeObjectForKey(k); if (fs != null) _fetchSpecs.setObjectForKey(fs, k); } @@ -222,7 +222,7 @@ public class EOEntity implements EOPropertyListEncoding { } public EOAttribute attributeNamed(String name) { - return (EOAttribute)_attributes.objectForKey(name); + return (EOAttribute) _attributes.objectForKey(name); } public NSArray flattenedAttributes() { @@ -232,6 +232,7 @@ public class EOEntity implements EOPropertyListEncoding { public void setClassName(String name) { _className = name; } + public String className() { return _className; } @@ -239,6 +240,7 @@ public class EOEntity implements EOPropertyListEncoding { public void setName(String name) { _name = name; } + public String name() { return _name; } @@ -246,6 +248,7 @@ public class EOEntity implements EOPropertyListEncoding { public void setExternalName(String name) { _externalName = name; } + public String externalName() { return _externalName; } @@ -274,7 +277,9 @@ public class EOEntity implements EOPropertyListEncoding { _classPropertyOneRelationships.removeObject(rel); } - /** Returns the relationships from this entity to other entities. + /** + * Returns the relationships from this entity to other entities. + * * @return An array of the relationships of this entity. */ public NSArray relationships() { @@ -282,8 +287,9 @@ public class EOEntity implements EOPropertyListEncoding { } public EORelationship relationshipNamed(String name) { - return (EORelationship)_relations.objectForKey(name); + return (EORelationship) _relations.objectForKey(name); } + public EOModel model() { return _model; } @@ -291,6 +297,7 @@ public class EOEntity implements EOPropertyListEncoding { public void setPrimaryKeyAtributes(NSArray pk) { _pkAttributes = pk; } + public NSArray primaryKeyAttributes() { return _pkAttributes; } @@ -299,7 +306,7 @@ public class EOEntity implements EOPropertyListEncoding { if (_pkAttributeNames.count() != _pkAttributes.count()) { NSMutableArray arr = new NSMutableArray(); for (int i = 0; i < _pkAttributes.count(); i++) { - EOAttribute a = (EOAttribute)_pkAttributes.objectAtIndex(i); + EOAttribute a = (EOAttribute) _pkAttributes.objectAtIndex(i); arr.addObject(a.name()); } _pkAttributeNames = new NSArray(arr); @@ -319,6 +326,7 @@ public class EOEntity implements EOPropertyListEncoding { _lockingAttributes.removeAllObjects(); _lockingAttributes.addObjectsFromArray(value); } + public NSArray attributesUsedForLocking() { return new NSArray(_lockingAttributes); } @@ -331,18 +339,19 @@ public class EOEntity implements EOPropertyListEncoding { _classPropertyOneRelationships.removeAllObjects(); _classPropertyManyRelationships.removeAllObjects(); for (int i = 0; i < value.count(); i++) { - EOProperty o = (EOProperty)value.objectAtIndex(i); + EOProperty o = (EOProperty) value.objectAtIndex(i); _classPropertyNames.addObject(o.name()); if (o instanceof EOAttribute) { _classPropertyAttributes.addObject(o); } else if (o instanceof EORelationship) { - if (((EORelationship)o).isToMany()) + if (((EORelationship) o).isToMany()) _classPropertyManyRelationships.addObject(o); else _classPropertyOneRelationships.addObject(o); } } } + public NSArray classProperties() { if (_classProperties == null) { if (_classPropertyNames == null) @@ -353,7 +362,7 @@ public class EOEntity implements EOPropertyListEncoding { NSMutableArray ones = new NSMutableArray(); NSMutableArray manies = new NSMutableArray(); for (int i = 0; i < _classPropertyNames.count(); i++) { - String name = (String)_classPropertyNames.objectAtIndex(i); + String name = (String) _classPropertyNames.objectAtIndex(i); EOAttribute a = attributeNamed(name); EORelationship r = relationshipNamed(name); if (a != null) { @@ -385,8 +394,8 @@ public class EOEntity implements EOPropertyListEncoding { if (_classPropertyAttributes == null) return NSArray.EmptyArray; NSMutableArray arr = new NSMutableArray(_classPropertyAttributes.count()); - for (int i = 0 ; i < _classPropertyAttributes.count(); i++) { - EOAttribute a = (EOAttribute)_classPropertyAttributes.objectAtIndex(i); + for (int i = 0; i < _classPropertyAttributes.count(); i++) { + EOAttribute a = (EOAttribute) _classPropertyAttributes.objectAtIndex(i); arr.addObject(a.name()); } return arr; @@ -396,8 +405,8 @@ public class EOEntity implements EOPropertyListEncoding { if (_classPropertyManyRelationships == null) return NSArray.EmptyArray; NSMutableArray arr = new NSMutableArray(_classPropertyManyRelationships.count()); - for (int i = 0 ; i < _classPropertyManyRelationships.count(); i++) { - EOAttribute a = (EOAttribute)_classPropertyManyRelationships.objectAtIndex(i); + for (int i = 0; i < _classPropertyManyRelationships.count(); i++) { + EOAttribute a = (EOAttribute) _classPropertyManyRelationships.objectAtIndex(i); arr.addObject(a.name()); } return arr; @@ -407,8 +416,8 @@ public class EOEntity implements EOPropertyListEncoding { if (_classPropertyOneRelationships == null) return NSArray.EmptyArray; NSMutableArray arr = new NSMutableArray(_classPropertyOneRelationships.count()); - for (int i = 0 ; i < _classPropertyOneRelationships.count(); i++) { - EOAttribute a = (EOAttribute)_classPropertyOneRelationships.objectAtIndex(i); + for (int i = 0; i < _classPropertyOneRelationships.count(); i++) { + EOAttribute a = (EOAttribute) _classPropertyOneRelationships.objectAtIndex(i); arr.addObject(a.name()); } return arr; @@ -417,6 +426,7 @@ public class EOEntity implements EOPropertyListEncoding { public void setIsAbstractEntity(boolean flag) { _isAbstract = flag; } + public boolean isAbstractEntity() { return _isAbstract; } @@ -424,12 +434,14 @@ public class EOEntity implements EOPropertyListEncoding { public void setReadOnly(boolean flag) { _isReadOnly = flag; } + public boolean isReadOnly() { return _isReadOnly; } public void setStoredProcedure(EOStoredProcedure proc, String operation) { } + public EOStoredProcedure storedProcedureForOperation(String operation) { return null; } @@ -462,8 +474,9 @@ public class EOEntity implements EOPropertyListEncoding { } /** - * Creates a global ID for a row. The row must have values - * for all the primary key attributes. + * Creates a global ID for a row. The row must have values for all the primary + * key attributes. + * * @param row A raw row for this entity. * @return A key global ID to identify this row. */ @@ -471,7 +484,7 @@ public class EOEntity implements EOPropertyListEncoding { NSArray pknames = primaryKeyAttributeNames(); EOKeyGlobalID gid = null; if (pknames.count() == 1 && row.get(pknames.objectAtIndex(0)) instanceof Number) { - Number n = (Number)row.get(pknames.objectAtIndex(0)); + Number n = (Number) row.get(pknames.objectAtIndex(0)); gid = new EOIntegralKeyGlobalID(name(), n); } else { Object[] vals = new Object[pknames.count()]; @@ -485,15 +498,15 @@ public class EOEntity implements EOPropertyListEncoding { } /** - * Returns a dictionary with the primary key values contained in - * the global id. + * Returns a dictionary with the primary key values contained in the global id. + * * @param gid A Key global ID. * @return A dictionary with the primary key values for gid. */ public NSDictionary primaryKeyForGlobalID(EOGlobalID gid) { if (!(gid instanceof EOKeyGlobalID)) return null; - Object[] vals = ((EOKeyGlobalID)gid).keyValues(); + Object[] vals = ((EOKeyGlobalID) gid).keyValues(); NSArray pknames = primaryKeyAttributeNames(); return new NSDictionary(vals, pknames.toArray()); } @@ -503,14 +516,14 @@ public class EOEntity implements EOPropertyListEncoding { EOQualifier q = null; NSMutableArray subq = new NSMutableArray(pknames.count()); for (int i = 0; i < pknames.count(); i++) { - String key = (String)pknames.objectAtIndex(i); + String key = (String) pknames.objectAtIndex(i); Object v = pkey.get(key); if (v == null || v == NSKeyValueCoding.NullValue) throw new IllegalArgumentException("Primary key with null values."); subq.addObject(new EOKeyValueQualifier(key, EOQualifier.QualifierOperatorEqual, v)); } if (subq.count() == 1) - q = (EOQualifier)subq.objectAtIndex(0); + q = (EOQualifier) subq.objectAtIndex(0); else q = new EOAndQualifier(subq); return q; @@ -519,6 +532,7 @@ public class EOEntity implements EOPropertyListEncoding { public void setUserInfo(NSDictionary value) { _userInfo = value; } + public NSDictionary userInfo() { return _userInfo; } @@ -531,20 +545,20 @@ public class EOEntity implements EOPropertyListEncoding { dict.setObjectForKey(externalName(), "externalName"); dict.setObjectForKey(className(), "className"); - //Encode attributes + // Encode attributes NSMutableArray arr = new NSMutableArray(_attributes.allValues()); for (int i = 0; i < _attributes.count(); i++) { - EOAttribute a = (EOAttribute)arr.objectAtIndex(i); + EOAttribute a = (EOAttribute) arr.objectAtIndex(i); NSMutableDictionary d = new NSMutableDictionary(); a.encodeIntoPropertyList(d); arr.replaceObjectAtIndex(i, d); } dict.setObjectForKey(arr, "attributes"); - //Encode relationships + // Encode relationships if (_relations.count() > 0) { arr = new NSMutableArray(_relations.allValues()); for (int i = 0; i < _relations.count(); i++) { - EORelationship r = (EORelationship)arr.objectAtIndex(i); + EORelationship r = (EORelationship) arr.objectAtIndex(i); NSMutableDictionary d = new NSMutableDictionary(); r.encodeIntoPropertyList(d); arr.replaceObjectAtIndex(i, d); @@ -552,29 +566,29 @@ public class EOEntity implements EOPropertyListEncoding { dict.setObjectForKey(arr, "relationships"); } - //Fetch specifications + // Fetch specifications NSMutableDictionary d = new NSMutableDictionary(); loadFetchSpecifications(); java.util.Enumeration enumeration = _fetchSpecs.keyEnumerator(); while (enumeration.hasMoreElements()) { - String k = (String)enumeration.nextElement(); - EOFetchSpecification f = (EOFetchSpecification)_fetchSpecs.objectForKey(k); + String k = (String) enumeration.nextElement(); + EOFetchSpecification f = (EOFetchSpecification) _fetchSpecs.objectForKey(k); EOKeyValueArchiver arch = new EOKeyValueArchiver(); f.encodeWithKeyValueArchiver(arch); d.setObjectForKey(arch.dictionary(), k); } dict.setObjectForKey(d, "fetchSpecificationDictionary"); - //Other information + // Other information dict.setObjectForKey(_classPropertyNames, "classProperties"); dict.setObjectForKey(_pkAttributeNames, "primaryKeyAttributes"); arr = new NSMutableArray(_lockingAttributes); for (int i = 0; i < arr.count(); i++) - arr.replaceObjectAtIndex(i, ((EOAttribute)arr.objectAtIndex(i)).name()); + arr.replaceObjectAtIndex(i, ((EOAttribute) arr.objectAtIndex(i)).name()); dict.setObjectForKey(arr, "attributesUsedForLocking"); - if (_userInfo != null && _userInfo.count() > 0 ) + if (_userInfo != null && _userInfo.count() > 0) dict.setObjectForKey(_userInfo, "userInfo"); - if (_internalInfo != null && _internalInfo.count() > 0 ) + if (_internalInfo != null && _internalInfo.count() > 0) dict.setObjectForKey(_internalInfo, "internalInfo"); } @@ -584,54 +598,54 @@ public class EOEntity implements EOPropertyListEncoding { return null; EORelationship r = null; EOEntity e = this; - for (int i = 0; i < comps.count()-1; i++) { - String name = (String)comps.objectAtIndex(i); + for (int i = 0; i < comps.count() - 1; i++) { + String name = (String) comps.objectAtIndex(i); r = e.relationshipNamed(name); if (r == null) return null; e = r.destinationEntity(); } - return e.attributeNamed((String)comps.lastObject()); + return e.attributeNamed((String) comps.lastObject()); } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.9 2005/05/11 15:21:53 cgruber - * Change enum to enumeration, since enum is now a keyword as of Java 5.0 + * Revision 1.9 2005/05/11 15:21:53 cgruber Change enum to enumeration, since + * enum is now a keyword as of Java 5.0 * * A few other comments in the code. * - * Revision 1.8 2003/08/19 19:47:58 chochos - * added some methods to handle EOGlobalIDs and primary keys. + * Revision 1.8 2003/08/19 19:47:58 chochos added some methods to handle + * EOGlobalIDs and primary keys. * - * Revision 1.7 2003/08/14 02:13:56 chochos - * implement and use _attributeForPath() + * Revision 1.7 2003/08/14 02:13:56 chochos implement and use + * _attributeForPath() * - * Revision 1.6 2003/08/11 19:38:27 chochos - * Can now read from a file and re-write to another file. + * Revision 1.6 2003/08/11 19:38:27 chochos Can now read from a file and + * re-write to another file. * - * Revision 1.5 2003/08/11 18:19:33 chochos - * encoding into property list seems to work fine now. + * Revision 1.5 2003/08/11 18:19:33 chochos encoding into property list seems to + * work fine now. * - * Revision 1.4 2003/08/09 01:39:04 chochos - * better handling of class properties; use EOKeyValueArchiving to encode/decode fetch specifications; implement EOPropertyListEncoding + * Revision 1.4 2003/08/09 01:39:04 chochos better handling of class properties; + * use EOKeyValueArchiving to encode/decode fetch specifications; implement + * EOPropertyListEncoding * - * Revision 1.3 2003/08/08 05:52:21 chochos - * gets the class description for the entity. + * Revision 1.3 2003/08/08 05:52:21 chochos gets the class description for the + * entity. * - * Revision 1.2 2003/08/08 02:14:20 chochos - * now it can read stored procedures. + * Revision 1.2 2003/08/08 02:14:20 chochos now it can read stored procedures. * - * Revision 1.1 2003/08/07 02:38:33 chochos - * implementation of EOEntity. What works for now is reading an entity from file. + * Revision 1.1 2003/08/07 02:38:33 chochos implementation of EOEntity. What + * works for now is reading an entity from file. * */ diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOEntityClassDescription.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOEntityClassDescription.java index a235c99..0485497 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOEntityClassDescription.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOEntityClassDescription.java @@ -26,10 +26,10 @@ import net.wotonomy.foundation.NSArray; import net.wotonomy.foundation.NSMutableArray; /** -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public class EOEntityClassDescription extends EOClassDescription { protected EOEntity _entity; @@ -47,7 +47,7 @@ public class EOEntityClassDescription extends EOClassDescription { NSArray arr = entity().attributes(); NSMutableArray a = new NSMutableArray(arr.count()); for (int i = 0; i < arr.count(); i++) { - EOAttribute atrib = (EOAttribute)arr.objectAtIndex(i); + EOAttribute atrib = (EOAttribute) arr.objectAtIndex(i); a.addObject(atrib); } return a; @@ -61,7 +61,7 @@ public class EOEntityClassDescription extends EOClassDescription { NSArray arr = entity().relationships(); NSMutableArray a = new NSMutableArray(arr.count()); for (int i = 0; i < arr.count(); i++) { - EORelationship r = (EORelationship)arr.objectAtIndex(i); + EORelationship r = (EORelationship) arr.objectAtIndex(i); if (r.isToMany()) a.addObject(r); } @@ -72,21 +72,21 @@ public class EOEntityClassDescription extends EOClassDescription { NSArray arr = entity().relationships(); NSMutableArray a = new NSMutableArray(arr.count()); for (int i = 0; i < arr.count(); i++) { - EORelationship r = (EORelationship)arr.objectAtIndex(i); + EORelationship r = (EORelationship) arr.objectAtIndex(i); if (!r.isToMany()) a.addObject(r); } return a; } - /** Returns all attributes that correspond to columns - * in a database table. + /** + * Returns all attributes that correspond to columns in a database table. */ public NSArray attributeKeys() { NSArray arr = entity().attributes(); NSMutableArray a = new NSMutableArray(arr.count()); for (int i = 0; i < arr.count(); i++) { - EOAttribute atrib = (EOAttribute)arr.objectAtIndex(i); + EOAttribute atrib = (EOAttribute) arr.objectAtIndex(i); if (!atrib.isDerived()) a.addObject(atrib); } @@ -128,7 +128,7 @@ public class EOEntityClassDescription extends EOClassDescription { NSArray arr = entity().relationships(); NSMutableArray a = new NSMutableArray(arr.count()); for (int i = 0; i < arr.count(); i++) { - EORelationship r = (EORelationship)arr.objectAtIndex(i); + EORelationship r = (EORelationship) arr.objectAtIndex(i); if (r.isToMany() && !r.isFlattened()) a.addObject(r); } @@ -139,7 +139,7 @@ public class EOEntityClassDescription extends EOClassDescription { NSArray arr = entity().relationships(); NSMutableArray a = new NSMutableArray(arr.count()); for (int i = 0; i < arr.count(); i++) { - EORelationship r = (EORelationship)arr.objectAtIndex(i); + EORelationship r = (EORelationship) arr.objectAtIndex(i); if (!r.isToMany() && !r.isFlattened()) a.addObject(r); } @@ -147,7 +147,7 @@ public class EOEntityClassDescription extends EOClassDescription { } public Object createInstanceWithEditingContext(EOEditingContext ec, EOGlobalID gid) { - if (theClass == null) { + if (theClass == null) { try { theClass = Class.forName(entity().className()); } catch (ClassNotFoundException ex) { @@ -161,25 +161,26 @@ public class EOEntityClassDescription extends EOClassDescription { } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:13 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ Revision 1.2 2006/02/16 16:47:13 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.4 2003/08/19 01:55:54 chochos - * the behavior is now more consistent with its Apple counterpart. + * Revision 1.4 2003/08/19 01:55:54 chochos the behavior is now more consistent + * with its Apple counterpart. * - * Revision 1.3 2003/08/09 01:40:31 chochos - * use EOClassDescription's methods to get a destination entity's class description. + * Revision 1.3 2003/08/09 01:40:31 chochos use EOClassDescription's methods to + * get a destination entity's class description. * - * Revision 1.2 2003/08/08 05:51:59 chochos - * createInstanceWithEditingContext now works. It sets theClass with the class from the entity className() before calling super. + * Revision 1.2 2003/08/08 05:51:59 chochos createInstanceWithEditingContext now + * works. It sets theClass with the class from the entity className() before + * calling super. * - * Revision 1.1 2003/08/08 00:36:19 chochos - * concrete implementation of EOClassDescription that uses an EOEntity + * Revision 1.1 2003/08/08 00:36:19 chochos concrete implementation of + * EOClassDescription that uses an EOEntity * */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOGeneralAdaptorException.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOGeneralAdaptorException.java index 6c48a3f..435d6a1 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOGeneralAdaptorException.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOGeneralAdaptorException.java @@ -20,12 +20,12 @@ package net.wotonomy.access; import net.wotonomy.foundation.NSDictionary; /** -* Generic exception thrown by wotonomy.access. -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 893 $ -*/ + * Generic exception thrown by wotonomy.access. + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 893 $ + */ public class EOGeneralAdaptorException extends RuntimeException implements java.io.Serializable { private NSDictionary _userInfo; @@ -41,9 +41,8 @@ public class EOGeneralAdaptorException extends RuntimeException implements java. public EOGeneralAdaptorException(String selectorName, String className, String msg) { super(msg); - _userInfo = new NSDictionary( - new Object[]{ selectorName, className }, - new Object[]{ "selectorName", "className" }); + _userInfo = new NSDictionary(new Object[] { selectorName, className }, + new Object[] { "selectorName", "className" }); } public NSDictionary userInfo() { @@ -52,11 +51,9 @@ public class EOGeneralAdaptorException extends RuntimeException implements java. } /* - * $Log$ - * Revision 1.1 2006/02/16 13:19:57 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. + * $Log$ Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.1 2003/08/13 00:41:50 chochos - * general adaptor exception + * Revision 1.1 2003/08/13 00:41:50 chochos general adaptor exception * */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOJoin.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOJoin.java index 693a7d0..01326ac 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOJoin.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOJoin.java @@ -18,13 +18,13 @@ package net.wotonomy.access; /** -* An EOJoin represents a connection between two attributes in -* different entities. -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 893 $ -*/ + * An EOJoin represents a connection between two attributes in different + * entities. + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 893 $ + */ public class EOJoin { protected EOAttribute _source; @@ -45,12 +45,10 @@ public class EOJoin { } /* - * $Log$ - * Revision 1.1 2006/02/16 13:19:57 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. + * $Log$ Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.1 2003/08/07 02:41:04 chochos - * these don't do much for now. + * Revision 1.1 2003/08/07 02:41:04 chochos these don't do much for now. * */ } diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOModel.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOModel.java index 46fc8d0..9c77d45 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOModel.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOModel.java @@ -31,18 +31,18 @@ import net.wotonomy.foundation.NSMutableDictionary; import net.wotonomy.foundation.NSPropertyListSerialization; /** -* An EOModel is a set of entities and stored procedures, along with a connection -* dictionary to connect to a database. -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * An EOModel is a set of entities and stored procedures, along with a + * connection dictionary to connect to a database. + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public class EOModel { protected static final String IDX_NAME = "index.eomodeld"; - //This array contains dictionaries with "className" and "name" + // This array contains dictionaries with "className" and "name" protected NSMutableArray _entities = new NSMutableArray(); protected NSMutableDictionary _entitiesByName = new NSMutableDictionary(); protected NSMutableDictionary _entitiesByClass = new NSMutableDictionary(); @@ -86,24 +86,25 @@ public class EOModel { throw new IllegalArgumentException("Cannot read index.eomodeld"); } NSDictionary d = NSPropertyListSerialization.dictionaryForString(x); - String version = (String)d.objectForKey("EOModelVersion"); + String version = (String) d.objectForKey("EOModelVersion"); if (version == null || !version.startsWith("2.")) throw new IllegalArgumentException("Invalid eomodel version: " + version); - setAdaptorName((String)d.objectForKey("adaptorName")); - setConnectionDictionary((NSDictionary)d.objectForKey("connectionDictionary")); - _entities = ((NSArray)d.objectForKey("entities")).mutableClone(); + setAdaptorName((String) d.objectForKey("adaptorName")); + setConnectionDictionary((NSDictionary) d.objectForKey("connectionDictionary")); + _entities = ((NSArray) d.objectForKey("entities")).mutableClone(); if (d.objectForKey("storedProcedures") != null) - _storedProcedureNames.addObjectsFromArray((NSArray)d.objectForKey("storedProcedures")); + _storedProcedureNames.addObjectsFromArray((NSArray) d.objectForKey("storedProcedures")); if (d.objectForKey("internalInfo") != null) - _internalInfo = (NSDictionary)d.objectForKey("internalInfo"); + _internalInfo = (NSDictionary) d.objectForKey("internalInfo"); if (d.objectForKey("userInfo") != null) - _userInfo = (NSDictionary)d.objectForKey("userInfo"); + _userInfo = (NSDictionary) d.objectForKey("userInfo"); entityNamed("EOPrototypes"); } public void setConnectionDictionary(NSDictionary dict) { _connectionDictionary = dict; } + public NSDictionary connectionDictionary() { return _connectionDictionary; } @@ -130,10 +131,10 @@ public class EOModel { } public EOStoredProcedure storedProcedureNamed(String name) { - EOStoredProcedure proc = (EOStoredProcedure)_storedProcedures.objectForKey(name); - //if we can't find it, check if we should load it + EOStoredProcedure proc = (EOStoredProcedure) _storedProcedures.objectForKey(name); + // if we can't find it, check if we should load it if (proc == null && _path != null && _storedProcedureNames.containsObject(name)) { - //try to read it from file + // try to read it from file File f = new File(new File(_path), name + ".storedProcedure"); if (!f.exists()) return null; @@ -149,9 +150,10 @@ public class EOModel { } NSDictionary plist = NSPropertyListSerialization.dictionaryForString(sdict); if (plist == null) - throw new IllegalArgumentException("File " + f + " does not contain a valid stored procedure property list."); + throw new IllegalArgumentException( + "File " + f + " does not contain a valid stored procedure property list."); proc = new EOStoredProcedure(plist, this); - //add it to our collection + // add it to our collection _storedProcedures.setObjectForKey(proc, proc.name()); } return proc; @@ -159,8 +161,8 @@ public class EOModel { public NSArray storedProcedures() { if (_storedProcedures.count() < _storedProcedureNames.count()) { - for (int i=0; i<_storedProcedureNames.count(); i++) - storedProcedureNamed((String)_storedProcedureNames.objectAtIndex(i)); + for (int i = 0; i < _storedProcedureNames.count(); i++) + storedProcedureNamed((String) _storedProcedureNames.objectAtIndex(i)); } return _storedProcedures.allValues(); } @@ -172,6 +174,7 @@ public class EOModel { public void setAdaptorName(String value) { _adaptorName = value; } + public String adaptorName() { return _adaptorName; } @@ -181,8 +184,8 @@ public class EOModel { return _entitiesByName.allValues(); NSMutableArray es = new NSMutableArray(); for (int i = 0; i < _entities.count(); i++) { - NSDictionary d = (NSDictionary)_entities.objectAtIndex(i); - es.addObject(entityNamed((String)d.objectForKey("name"))); + NSDictionary d = (NSDictionary) _entities.objectAtIndex(i); + es.addObject(entityNamed((String) d.objectForKey("name"))); } return es; } @@ -192,18 +195,18 @@ public class EOModel { return _entitiesByName.allKeys(); NSMutableArray names = new NSMutableArray(); for (int i = 0; i < _entities.count(); i++) { - NSDictionary d = (NSDictionary)_entities.objectAtIndex(i); + NSDictionary d = (NSDictionary) _entities.objectAtIndex(i); names.addObject(d.objectForKey("name")); } return names; } public EOEntity entityNamed(String name) { - EOEntity e = (EOEntity)_entitiesByName.objectForKey(name); + EOEntity e = (EOEntity) _entitiesByName.objectForKey(name); if (e == null && path() != null) { boolean exists = false; for (int i = 0; i < _entities.count(); i++) { - NSDictionary d = (NSDictionary)_entities.objectAtIndex(i); + NSDictionary d = (NSDictionary) _entities.objectAtIndex(i); if (d.objectForKey("name").equals(name)) exists = true; } @@ -242,6 +245,7 @@ public class EOModel { public void setModelGroup(EOModelGroup group) { _group = group; } + public EOModelGroup modelGroup() { return _group; } @@ -266,7 +270,8 @@ public class EOModel { File[] kids = f.listFiles(); for (int i = 0; i < kids.length; i++) { String fname = kids[i].getName(); - if (kids[i].isFile() && (fname.endsWith(".plist") || fname.endsWith(".eomodeld") || fname.endsWith(".fspec") || fname.endsWith(".storedProcedure"))) + if (kids[i].isFile() && (fname.endsWith(".plist") || fname.endsWith(".eomodeld") + || fname.endsWith(".fspec") || fname.endsWith(".storedProcedure"))) kids[i].delete(); } } else @@ -275,7 +280,7 @@ public class EOModel { f.mkdirs(); File kid = new File(f, "index.eomodeld"); - //encode the index file + // encode the index file NSMutableDictionary d = new NSMutableDictionary(); d.setObjectForKey(_adaptorName, "adaptorName"); d.setObjectForKey("2.1", "EOModelVersion"); @@ -287,23 +292,24 @@ public class EOModel { if (_storedProcedureNames.count() > 0) d.setObjectForKey(_storedProcedureNames, "storedProcedures"); - //encode the entity list + // encode the entity list entities(); storedProcedures(); NSMutableArray arr = new NSMutableArray(_entitiesByName.count()); Enumeration enumeration = _entitiesByName.keyEnumerator(); NSMutableDictionary md = new NSMutableDictionary(); while (enumeration.hasMoreElements()) { - String key = (String)enumeration.nextElement(); - EOEntity ent = (EOEntity)_entitiesByName.objectForKey(key); + String key = (String) enumeration.nextElement(); + EOEntity ent = (EOEntity) _entitiesByName.objectForKey(key); md.removeAllObjects(); ent.encodeIntoPropertyList(md); File plist; - NSDictionary fetchSpecs = (NSDictionary)md.objectForKey("fetchSpecificationDictionary"); + NSDictionary fetchSpecs = (NSDictionary) md.objectForKey("fetchSpecificationDictionary"); if (fetchSpecs != null) { if (fetchSpecs.count() > 0) { plist = new File(f, key + ".fspec"); - String ps = NSPropertyListSerialization.stringForPropertyList(md.objectForKey("fetchSpecificationDictionary")); + String ps = NSPropertyListSerialization + .stringForPropertyList(md.objectForKey("fetchSpecificationDictionary")); try { PrintStream stream = new PrintStream(new FileOutputStream(plist)); stream.println(ps); @@ -321,14 +327,13 @@ public class EOModel { stream.close(); } catch (IOException ex) { } - //add to the entity list for the index - arr.addObject(new NSDictionary( - new Object[]{ ent.name(), ent.className() }, - new Object[]{ "name", "className" })); + // add to the entity list for the index + arr.addObject(new NSDictionary(new Object[] { ent.name(), ent.className() }, + new Object[] { "name", "className" })); } d.setObjectForKey(arr, "entities"); - //write the index file + // write the index file String s = NSPropertyListSerialization.stringForPropertyList(d); try { PrintStream stream = new PrintStream(new FileOutputStream(kid)); @@ -338,9 +343,10 @@ public class EOModel { throw new RuntimeException("Cannot write index.eomodeld"); } - //write the stored procedures + // write the stored procedures for (int i = 0; i < _storedProcedureNames.count(); i++) { - EOStoredProcedure proc = (EOStoredProcedure)_storedProcedures.objectForKey(_storedProcedureNames.objectAtIndex(i)); + EOStoredProcedure proc = (EOStoredProcedure) _storedProcedures + .objectForKey(_storedProcedureNames.objectAtIndex(i)); kid = new File(f, proc.name() + ".storedProcedure"); d.removeAllObjects(); proc.encodeIntoPropertyList(d); @@ -358,39 +364,36 @@ public class EOModel { } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.8 2005/05/11 15:21:53 cgruber - * Change enum to enumeration, since enum is now a keyword as of Java 5.0 + * Revision 1.8 2005/05/11 15:21:53 cgruber Change enum to enumeration, since + * enum is now a keyword as of Java 5.0 * * A few other comments in the code. * - * Revision 1.7 2003/08/13 20:46:12 chochos - * entityNamed() only throws if the searched entity is in the entities array and not in a file. + * Revision 1.7 2003/08/13 20:46:12 chochos entityNamed() only throws if the + * searched entity is in the entities array and not in a file. * - * Revision 1.6 2003/08/12 01:45:04 chochos - * added some code to handle prototypes + * Revision 1.6 2003/08/12 01:45:04 chochos added some code to handle prototypes * - * Revision 1.5 2003/08/11 19:38:27 chochos - * Can now read from a file and re-write to another file. + * Revision 1.5 2003/08/11 19:38:27 chochos Can now read from a file and + * re-write to another file. * - * Revision 1.4 2003/08/11 18:20:08 chochos - * saving to a file seems to work now. + * Revision 1.4 2003/08/11 18:20:08 chochos saving to a file seems to work now. * - * Revision 1.3 2003/08/08 02:16:55 chochos - * can now read stored procedures from file. + * Revision 1.3 2003/08/08 02:16:55 chochos can now read stored procedures from + * file. * - * Revision 1.2 2003/08/08 00:37:00 chochos - * add stored procedure functionality + * Revision 1.2 2003/08/08 00:37:00 chochos add stored procedure functionality * - * Revision 1.1 2003/08/07 02:42:28 chochos - * EOModel can read an .eomodeld file. EOModelGroup doesn't do much for now. + * Revision 1.1 2003/08/07 02:42:28 chochos EOModel can read an .eomodeld file. + * EOModelGroup doesn't do much for now. * -*/ \ No newline at end of file + */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOModelGroup.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOModelGroup.java index dbab09d..70c1088 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOModelGroup.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOModelGroup.java @@ -24,14 +24,14 @@ import net.wotonomy.foundation.NSDictionary; import net.wotonomy.foundation.NSMutableDictionary; /** -* A group of models that connect to the same database. Entities in -* these models can have relationships that point to other entities -* in any model of the same group. -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * A group of models that connect to the same database. Entities in these models + * can have relationships that point to other entities in any model of the same + * group. + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public class EOModelGroup { private static EOModelGroup _defaultGroup; @@ -46,14 +46,14 @@ public class EOModelGroup { if (model.name() == null) throw new IllegalArgumentException("Cannot add an unnamed model to a group."); if (_models.objectForKey(model.name()) != null) - throw new IllegalArgumentException("Cannot add model " + model.name() + - " to group because it already contains a model with the same name."); + throw new IllegalArgumentException("Cannot add model " + model.name() + + " to group because it already contains a model with the same name."); NSArray ents = model.entityNames(); for (int i = 0; i < ents.count(); i++) { - String ename = (String)ents.objectAtIndex(i); + String ename = (String) ents.objectAtIndex(i); if (entityNamed(ename) != null) - throw new IllegalArgumentException("Cannot add model " + model.name() + - " to group because it contains entity named " + ename); + throw new IllegalArgumentException( + "Cannot add model " + model.name() + " to group because it contains entity named " + ename); } _models.setObjectForKey(model, model.name()); } @@ -73,6 +73,7 @@ public class EOModelGroup { public static void setDefaultGroup(EOModelGroup group) { _defaultGroup = group; } + public static EOModelGroup defaultGroup() { if (_defaultGroup == null) { _defaultGroup = globalModelGroup(); @@ -83,7 +84,7 @@ public class EOModelGroup { public static EOModelGroup globalModelGroup() { if (_globalGroup == null) { _globalGroup = new EOModelGroup(); - //TODO: read all frameworks and get models from them + // TODO: read all frameworks and get models from them } return _globalGroup; } @@ -95,7 +96,7 @@ public class EOModelGroup { public EOEntity entityNamed(String name) { java.util.Enumeration enumeration = _models.objectEnumerator(); while (enumeration.hasMoreElements()) { - EOModel m = (EOModel)enumeration.nextElement(); + EOModel m = (EOModel) enumeration.nextElement(); if (m.entityNamed(name) != null) return m.entityNamed(name); } @@ -103,7 +104,7 @@ public class EOModelGroup { } public EOModel modelNamed(String name) { - return (EOModel)_models.objectForKey(name); + return (EOModel) _models.objectForKey(name); } public NSArray modelNames() { @@ -117,7 +118,7 @@ public class EOModelGroup { public EOModel modelWithPath(String path) { java.util.Enumeration enumeration = _models.objectEnumerator(); while (enumeration.hasMoreElements()) { - EOModel m = (EOModel)enumeration.nextElement(); + EOModel m = (EOModel) enumeration.nextElement(); if (m.path() != null && m.path().equals(path)) return m; } @@ -127,7 +128,7 @@ public class EOModelGroup { public EOStoredProcedure storedProcedureNamed(String name) { java.util.Enumeration enumeration = _models.objectEnumerator(); while (enumeration.hasMoreElements()) { - EOModel m = (EOModel)enumeration.nextElement(); + EOModel m = (EOModel) enumeration.nextElement(); if (m.storedProcedureNamed(name) != null) return m.storedProcedureNamed(name); } @@ -144,12 +145,12 @@ public class EOModelGroup { public void loadAllModelObjects() { java.util.Enumeration enumeration = _models.objectEnumerator(); while (enumeration.hasMoreElements()) { - EOModel m = (EOModel)enumeration.nextElement(); - //this causes all entities to be loaded + EOModel m = (EOModel) enumeration.nextElement(); + // this causes all entities to be loaded NSArray ents = m.entities(); - for (int i=0; i 1) { @@ -189,16 +191,16 @@ public interface EOQualifierSQLGeneration { } public String sqlStringForSQLExpression(EOQualifier qualifier, EOSQLExpression exp) { - EOOrQualifier q = (EOOrQualifier)qualifier; + EOOrQualifier q = (EOOrQualifier) qualifier; NSArray qus = q.qualifiers(); StringBuffer buf = new StringBuffer(); for (int i = 0; i < qus.count(); i++) { - EOQualifier sub = (EOQualifier)qus.objectAtIndex(i); + EOQualifier sub = (EOQualifier) qus.objectAtIndex(i); EOQualifierSQLGeneration.Support sup = EOQualifierSQLGeneration.Support.supportForClass(sub.getClass()); if (sup == null) throw new IllegalStateException("Cannot find support class for " + sub.getClass().getName()); buf.append(sup.sqlStringForSQLExpression(sub, exp)); - if (i < qus.count()-1) + if (i < qus.count() - 1) buf.append(" OR "); } if (qus.count() > 1) { @@ -220,22 +222,23 @@ public interface EOQualifierSQLGeneration { } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.3 2003/08/14 02:13:10 chochos - * KeyValueQualifierSupport generates proper SQL + * Revision 1.3 2003/08/14 02:13:10 chochos KeyValueQualifierSupport generates + * proper SQL * - * Revision 1.2 2003/08/14 01:05:51 chochos - * added abstract Support inner class, with incomplete implementations for the main qualifiers (not, and, or, key-value, key-comparison) + * Revision 1.2 2003/08/14 01:05:51 chochos added abstract Support inner class, + * with incomplete implementations for the main qualifiers (not, and, or, + * key-value, key-comparison) * - * Revision 1.1 2003/08/12 01:45:49 chochos - * interface to be implemented by qualifiers (or support classes) to indicate they can generate SQL + * Revision 1.1 2003/08/12 01:45:49 chochos interface to be implemented by + * qualifiers (or support classes) to indicate they can generate SQL * */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EORelationship.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EORelationship.java index a5a207f..4efd068 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EORelationship.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EORelationship.java @@ -21,13 +21,15 @@ import net.wotonomy.foundation.NSArray; import net.wotonomy.foundation.NSDictionary; import net.wotonomy.foundation.NSMutableArray; import net.wotonomy.foundation.NSMutableDictionary; + /** -* Represents a relationship from one entity to another. Relationships are unidirectional. -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * Represents a relationship from one entity to another. Relationships are + * unidirectional. + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public class EORelationship extends EOProperty implements EOPropertyListEncoding { public static final int InnerJoin = 0; @@ -60,14 +62,14 @@ public class EORelationship extends EOProperty implements EOPropertyListEncoding public EORelationship(NSDictionary dict, Object obj) { super(); - _entity = (EOEntity)obj; - setName((String)dict.objectForKey("name")); + _entity = (EOEntity) obj; + setName((String) dict.objectForKey("name")); setToMany("Y".equals(dict.objectForKey("isToMany"))); setPropagatesPrimaryKey("Y".equals(dict.objectForKey("propagatesPrimaryKey"))); setIsMandatory("Y".equals(dict.objectForKey("isMandatory"))); setOwnsDestination("Y".equals(dict.objectForKey("ownsDestination"))); - setDefinition((String)dict.objectForKey("definition")); - String delrule = (String)dict.objectForKey("deleteRule"); + setDefinition((String) dict.objectForKey("definition")); + String delrule = (String) dict.objectForKey("deleteRule"); if (delrule != null) { if (delrule.equals("EODeleteRuleCascade")) setDeleteRule(0); @@ -78,7 +80,7 @@ public class EORelationship extends EOProperty implements EOPropertyListEncoding else if (delrule.equals("EODeleteRuleNullify")) setDeleteRule(0); } - delrule = (String)dict.objectForKey("joinSemantic"); + delrule = (String) dict.objectForKey("joinSemantic"); if (delrule != null) { if (delrule.equals("EOInnerJoin")) setJoinSemantic(InnerJoin); @@ -89,13 +91,13 @@ public class EORelationship extends EOProperty implements EOPropertyListEncoding else if (delrule.equals("EORightOuterJoin")) setJoinSemantic(RightOuterJoin); } - delrule = (String)dict.objectForKey("batchCount"); + delrule = (String) dict.objectForKey("batchCount"); if (delrule != null) setNumberOfToManyFaultsToBatchFetch(Integer.parseInt(delrule)); - NSDictionary d = (NSDictionary)dict.objectForKey("userInfo"); + NSDictionary d = (NSDictionary) dict.objectForKey("userInfo"); if (d != null) _userInfo = d; - d = (NSDictionary)dict.objectForKey("internalInfo"); + d = (NSDictionary) dict.objectForKey("internalInfo"); if (d != null) _internalInfo = d; plist = dict; @@ -104,6 +106,7 @@ public class EORelationship extends EOProperty implements EOPropertyListEncoding public void setName(String name) { _name = name; } + public String name() { return _name; } @@ -125,7 +128,7 @@ public class EORelationship extends EOProperty implements EOPropertyListEncoding if (_destination == null && plist != null) { EOModel model = _entity.model(); EOModelGroup group = model.modelGroup(); - String destEntity = (String)plist.objectForKey("destination"); + String destEntity = (String) plist.objectForKey("destination"); if (group != null) _destination = group.entityNamed(destEntity); else @@ -137,6 +140,7 @@ public class EORelationship extends EOProperty implements EOPropertyListEncoding public void setOwnsDestination(boolean flag) { _ownsDestination = flag; } + public boolean ownsDestination() { return _ownsDestination; } @@ -144,6 +148,7 @@ public class EORelationship extends EOProperty implements EOPropertyListEncoding public void setToMany(boolean flag) { _isToMany = flag; } + public boolean isToMany() { return _isToMany; } @@ -151,6 +156,7 @@ public class EORelationship extends EOProperty implements EOPropertyListEncoding public void setIsMandatory(boolean flag) { _isMandatory = flag; } + public boolean isMandatory() { return _isMandatory; } @@ -158,6 +164,7 @@ public class EORelationship extends EOProperty implements EOPropertyListEncoding public void setPropagatesPrimaryKey(boolean flag) { _propagatesPrimaryKey = flag; } + public boolean propagatesPrimaryKey() { return _propagatesPrimaryKey; } @@ -165,6 +172,7 @@ public class EORelationship extends EOProperty implements EOPropertyListEncoding public void setDeleteRule(int value) { _deleteRule = value; } + public int deleteRule() { return _deleteRule; } @@ -172,6 +180,7 @@ public class EORelationship extends EOProperty implements EOPropertyListEncoding public void setJoinSemantic(int value) { _joinSemantic = value; } + public int joinSemantic() { return _joinSemantic; } @@ -179,17 +188,18 @@ public class EORelationship extends EOProperty implements EOPropertyListEncoding public void setNumberOfToManyFaultsToBatchFetch(int count) { _batchCount = count; } + public int numberOfToManyFaultsToBatchFetch() { return _batchCount; } public NSArray joins() { if (_joins.count() == 0 && plist != null) { - NSArray joins = (NSArray)plist.objectForKey("joins"); + NSArray joins = (NSArray) plist.objectForKey("joins"); for (int i = 0; i < joins.count(); i++) { - NSDictionary d = (NSDictionary)joins.objectAtIndex(i); - String srcName = (String)d.objectForKey("sourceAttribute"); - String dstName = (String)d.objectForKey("destinationAttribute"); + NSDictionary d = (NSDictionary) joins.objectAtIndex(i); + String srcName = (String) d.objectForKey("sourceAttribute"); + String dstName = (String) d.objectForKey("destinationAttribute"); EOAttribute a1 = _entity.attributeNamed(srcName); EOAttribute a2 = destinationEntity().attributeNamed(dstName); EOJoin j = new EOJoin(a1, a2); @@ -202,6 +212,7 @@ public class EORelationship extends EOProperty implements EOPropertyListEncoding public void setDefinition(String def) { _definition = def; } + public String definition() { return _definition; } @@ -218,7 +229,7 @@ public class EORelationship extends EOProperty implements EOPropertyListEncoding EORelationship r = null; EOEntity e = entity(); for (int i = 0; i < comps.count(); i++) { - String name = (String)comps.objectAtIndex(i); + String name = (String) comps.objectAtIndex(i); r = e.relationshipNamed(name); if (r == null) return false; @@ -242,6 +253,7 @@ public class EORelationship extends EOProperty implements EOPropertyListEncoding public void setUserInfo(NSDictionary value) { _userInfo = value; } + public NSDictionary userInfo() { return _userInfo; } @@ -260,18 +272,18 @@ public class EORelationship extends EOProperty implements EOPropertyListEncoding if (isToMany()) dict.setObjectForKey("Y", "isToMany"); switch (_joinSemantic) { - case InnerJoin: - dict.setObjectForKey("EOInnerJoin", "joinSemantic"); - break; - case FullOuterJoin: - dict.setObjectForKey("EOFullOuterJoin", "joinSemantic"); - break; - case LeftOuterJoin: - dict.setObjectForKey("EOLefOuterJoin", "joinSemantic"); - break; - case RightOuterJoin: - dict.setObjectForKey("EORightOuterJoin", "joinSemantic"); - break; + case InnerJoin: + dict.setObjectForKey("EOInnerJoin", "joinSemantic"); + break; + case FullOuterJoin: + dict.setObjectForKey("EOFullOuterJoin", "joinSemantic"); + break; + case LeftOuterJoin: + dict.setObjectForKey("EOLefOuterJoin", "joinSemantic"); + break; + case RightOuterJoin: + dict.setObjectForKey("EORightOuterJoin", "joinSemantic"); + break; } if (_batchCount > 0) dict.setObjectForKey(new Integer(_batchCount), "batchCount"); @@ -280,10 +292,10 @@ public class EORelationship extends EOProperty implements EOPropertyListEncoding else { NSMutableArray jarr = new NSMutableArray(joins().count()); for (int i = 0; i < _joins.count(); i++) { - EOJoin j = (EOJoin)_joins.objectAtIndex(i); + EOJoin j = (EOJoin) _joins.objectAtIndex(i); NSDictionary d = new NSDictionary( - new Object[]{ j.sourceAttribute().name(), j.destinationAttribute().name() }, - new Object[]{ "sourceAttribute", "destinationAttribute" }); + new Object[] { j.sourceAttribute().name(), j.destinationAttribute().name() }, + new Object[] { "sourceAttribute", "destinationAttribute" }); jarr.addObject(d); } dict.setObjectForKey(jarr, "joins"); @@ -292,28 +304,25 @@ public class EORelationship extends EOProperty implements EOPropertyListEncoding } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:13 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ Revision 1.2 2006/02/16 16:47:13 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.5 2003/08/11 19:38:27 chochos - * Can now read from a file and re-write to another file. + * Revision 1.5 2003/08/11 19:38:27 chochos Can now read from a file and + * re-write to another file. * - * Revision 1.4 2003/08/09 01:35:35 chochos - * implement EOPropertyListEncoding + * Revision 1.4 2003/08/09 01:35:35 chochos implement EOPropertyListEncoding * - * Revision 1.3 2003/08/08 06:51:53 chochos - * isFlattened() works + * Revision 1.3 2003/08/08 06:51:53 chochos isFlattened() works * - * Revision 1.2 2003/08/08 02:17:43 chochos - * main accessors are in place. + * Revision 1.2 2003/08/08 02:17:43 chochos main accessors are in place. * - * Revision 1.1 2003/08/07 02:41:30 chochos - * a relationship that for the moment can be created from a property list. + * Revision 1.1 2003/08/07 02:41:30 chochos a relationship that for the moment + * can be created from a property list. * -*/ \ No newline at end of file + */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOSQLExpression.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOSQLExpression.java index 4cb15e5..c2b6e76 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOSQLExpression.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOSQLExpression.java @@ -37,10 +37,10 @@ import net.wotonomy.foundation.NSTimestamp; import net.wotonomy.foundation.NSTimestampFormatter; /** -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public abstract class EOSQLExpression { public static final String BindVariableAttributeKey = "BindVariableAttribute"; @@ -54,9 +54,8 @@ public abstract class EOSQLExpression { private static final int _DefaultOrderByStringLength = 128; private static final int _DefaultPathLength = 128; private static final int _DefaultTableListLength = 128; - protected static final char[] _hexChars = new char[]{ - '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' - }; + protected static final char[] _hexChars = new char[] { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', + 'C', 'D', 'E', 'F' }; private static final int _ValueLengthLimit = 40; protected NSMutableDictionary _aliasesByRelationshipPath; protected NSMutableDictionary _aliasesByEntityName; @@ -77,7 +76,7 @@ public abstract class EOSQLExpression { private EOSQLExpression() { super(); } - + public EOSQLExpression(EOEntity entity) { super(); _entity = entity; @@ -88,7 +87,7 @@ public abstract class EOSQLExpression { } public String _aliasForRelationshipPath(String path) { - return (String)_aliasesByRelationshipPath.objectForKey(path); + return (String) _aliasesByRelationshipPath.objectForKey(path); } protected NSTimestampFormatter _defaultDateFormatter() { @@ -115,7 +114,7 @@ public abstract class EOSQLExpression { _entity = value; } - public String _sqlStringForJoinSemanticMatchSemantic(int semantic,int match) { + public String _sqlStringForJoinSemanticMatchSemantic(int semantic, int match) { return null; } @@ -129,11 +128,13 @@ public abstract class EOSQLExpression { return _valueListString; } - public void addBindVariableDictionary( NSDictionary dict ) { + public void addBindVariableDictionary(NSDictionary dict) { } - /** Adds the SQL to create the attribute to the attribute list. - * The appended text is of the form attr_name attr_type allow_null + /** + * Adds the SQL to create the attribute to the attribute list. The appended text + * is of the form attr_name attr_type allow_null + * * @param attr The attribute to create the SQL for. */ public void addCreateClauseForAttribute(EOAttribute attr) { @@ -158,9 +159,11 @@ public abstract class EOSQLExpression { public void addOrderByAttributeOrdering(EOSortOrdering order) { String sql = sqlStringForAttributeNamed(order.key()); - if (order.selector().equals(EOSortOrdering.CompareCaseInsensitiveAscending) || order.selector().equals(EOSortOrdering.CompareCaseInsensitiveDescending)) + if (order.selector().equals(EOSortOrdering.CompareCaseInsensitiveAscending) + || order.selector().equals(EOSortOrdering.CompareCaseInsensitiveDescending)) sql = "UPPER(" + sql + ")"; - if (order.selector().equals(EOSortOrdering.CompareCaseInsensitiveAscending) || order.selector().equals(EOSortOrdering.CompareAscending)) + if (order.selector().equals(EOSortOrdering.CompareCaseInsensitiveAscending) + || order.selector().equals(EOSortOrdering.CompareAscending)) sql += " ASC"; else sql += " DESC"; @@ -205,8 +208,8 @@ public abstract class EOSQLExpression { return s; } - public String assembleInsertStatementWithRow(NSDictionary row, - String tableList, String columnList, String valueList) { + public String assembleInsertStatementWithRow(NSDictionary row, String tableList, String columnList, + String valueList) { String sql = "INSERT INTO " + tableList; if (columnList != null) sql += " (" + columnList + ")"; @@ -223,9 +226,9 @@ public abstract class EOSQLExpression { return leftName + op + rightName; } - public String assembleSelectStatementWithAttributes(NSArray attributes, - boolean lock, EOQualifier q, NSArray fetchOrder, String selectString, String columnList, - String tableList, String whereClause, String joinClause, String orderByClause, String lockClause) { + public String assembleSelectStatementWithAttributes(NSArray attributes, boolean lock, EOQualifier q, + NSArray fetchOrder, String selectString, String columnList, String tableList, String whereClause, + String joinClause, String orderByClause, String lockClause) { String sql = selectString + " " + columnList + " FROM " + tableList; if (lockClause != null) sql += " " + lockClause; @@ -242,7 +245,8 @@ public abstract class EOSQLExpression { return sql; } - public String assembleUpdateStatementWithRow(NSDictionary row, EOQualifier q, String tableList, String updateList, String whereClause) { + public String assembleUpdateStatementWithRow(NSDictionary row, EOQualifier q, String tableList, String updateList, + String whereClause) { String s = "UPDATE " + tableList + " SET " + updateList; if (whereClause != null && whereClause.length() > 0) s += " WHERE " + whereClause; @@ -280,14 +284,14 @@ public abstract class EOSQLExpression { } /** - * Returns the received string wrapped in single quotes, - * with any quotes or escape chars found inside it - * properly escaped. + * Returns the received string wrapped in single quotes, with any quotes or + * escape chars found inside it properly escaped. + * * @param s The string to format. */ public String formatStringValue(String s) { StringBuffer buf = new StringBuffer(s); - for (int i = buf.length()-1; i >= 0; i--) { + for (int i = buf.length() - 1; i >= 0; i--) { if (buf.charAt(i) == sqlEscapeChar()) { buf.insert(i, sqlEscapeChar()); i++; @@ -306,10 +310,10 @@ public abstract class EOSQLExpression { if (value == null || value == NSKeyValueCoding.NullValue) return "NULL"; if (value instanceof String) - return formatStringValue((String)value); + return formatStringValue((String) value); if (value instanceof Number) - return sqlStringForNumber((Number)value); - //TODO: format timestamps + return sqlStringForNumber((Number) value); + // TODO: format timestamps return value.toString(); } @@ -338,7 +342,7 @@ public abstract class EOSQLExpression { } public String orderByString() { - if (_orderByString == null) + if (_orderByString == null) return null; return _orderByString.toString(); } @@ -356,7 +360,7 @@ public abstract class EOSQLExpression { StringBuffer values = new StringBuffer("("); Enumeration enumeration = row.keyEnumerator(); while (enumeration.hasMoreElements()) { - String key = (String)enumeration.nextElement(); + String key = (String) enumeration.nextElement(); EOAttribute a = _entity.attributeNamed(key); cols.append(a.columnName()); values.append(formatValueForAttribute(row.objectForKey(key), a)); @@ -379,30 +383,31 @@ public abstract class EOSQLExpression { q = fspec.qualifier(); order = fspec.sortOrderings(); } - //Assemble the column list (this yields the alias list) + // Assemble the column list (this yields the alias list) for (int i = 0; i < atts.count(); i++) - addSelectListAttribute((EOAttribute)atts.objectAtIndex(i)); - //assemble the where string + addSelectListAttribute((EOAttribute) atts.objectAtIndex(i)); + // assemble the where string if (q != null) { if (q instanceof EOQualifierSQLGeneration) - setWhereClauseString(sqlStringForQualifier((EOQualifierSQLGeneration)q)); + setWhereClauseString(sqlStringForQualifier((EOQualifierSQLGeneration) q)); else { EOQualifierSQLGeneration.Support sup = EOQualifierSQLGeneration.Support.supportForClass(q.getClass()); setWhereClauseString(sup.sqlStringForSQLExpression(q, this)); } } - //assemble the join string + // assemble the join string joinExpression(); - //assemble the order by string + // assemble the order by string if (order != null && order.count() > 0) { for (int i = 0; i < order.count(); i++) { - EOSortOrdering so = (EOSortOrdering)order.objectAtIndex(i); + EOSortOrdering so = (EOSortOrdering) order.objectAtIndex(i); addOrderByAttributeOrdering(so); } } - //create the statement + // create the statement setStatement(assembleSelectStatementWithAttributes(atts, lock, q, order, "SELECT", listString(), - tableListWithRootEntity(_entity), whereClauseString(), joinClauseString(), orderByString(), lockClause())); + tableListWithRootEntity(_entity), whereClauseString(), joinClauseString(), orderByString(), + lockClause())); } /** Build an UPDATE statement with the given information. */ @@ -410,10 +415,11 @@ public abstract class EOSQLExpression { StringBuffer buf = new StringBuffer(); Enumeration enumeration = row.keyEnumerator(); while (enumeration.hasMoreElements()) { - String key = (String)enumeration.nextElement(); + String key = (String) enumeration.nextElement(); EOAttribute a = _entity.attributeNamed(key); if (a == null) - throw new EOGeneralAdaptorException("Cannot find attribute named " + key + " in entity " + _entity.name()); + throw new EOGeneralAdaptorException( + "Cannot find attribute named " + key + " in entity " + _entity.name()); buf.append(a.columnName()); buf.append('='); buf.append(formatValueForAttribute(row.objectForKey(key), a)); @@ -423,7 +429,8 @@ public abstract class EOSQLExpression { if (q != null) { setWhereClauseString(sqlStringForQualifier(null)); } - setStatement(assembleUpdateStatementWithRow(row, q, _entity.externalName(), buf.toString(), whereClauseString())); + setStatement( + assembleUpdateStatementWithRow(row, q, _entity.externalName(), buf.toString(), whereClauseString())); } public void setStatement(String statement) { @@ -453,6 +460,7 @@ public abstract class EOSQLExpression { public static void setUseQuotedExternalNames(boolean flag) { _quoteExternalNames = flag; } + /** @deprecated Use the instance method externalNameQuoteCharacter instead. */ public static boolean useQuotedExternalNames() { return _quoteExternalNames; @@ -481,33 +489,33 @@ public abstract class EOSQLExpression { public String sqlPatternFromShellPatternWithEscapeCharacter(String pattern, char escape) { StringBuffer buf = new StringBuffer(pattern); int idx = 0; - //escape all '%' + // escape all '%' do { idx = buf.indexOf("%"); if (idx == 0) buf.insert(escape, 0); - else if (idx > 0 && buf.charAt(idx-1) != escape) + else if (idx > 0 && buf.charAt(idx - 1) != escape) buf.insert(escape, idx); } while (idx >= 0); - //escape all '_' + // escape all '_' do { idx = buf.indexOf("_"); if (idx == 0) buf.insert(escape, 0); - else if (idx > 0 && buf.charAt(idx-1) != escape) + else if (idx > 0 && buf.charAt(idx - 1) != escape) buf.insert(escape, idx); } while (idx >= 0); - //substitute all '*' + // substitute all '*' do { idx = buf.indexOf("*"); if (idx >= 0) - buf.replace(idx, idx+1, "%"); + buf.replace(idx, idx + 1, "%"); } while (idx >= 0); - //substitute all '?' + // substitute all '?' do { idx = buf.indexOf("?"); if (idx >= 0) - buf.replace(idx, idx+1, "_"); + buf.replace(idx, idx + 1, "_"); } while (idx >= 0); return buf.toString(); } @@ -515,7 +523,7 @@ public abstract class EOSQLExpression { public String sqlStringForAttribute(EOAttribute attr) { if (_aliasesByEntityName == null) _aliasesByEntityName = new NSMutableDictionary(); - String alias = (String)_aliasesByEntityName.objectForKey(attr.entity().name()); + String alias = (String) _aliasesByEntityName.objectForKey(attr.entity().name()); if (alias == null) { alias = "t" + (_aliasesByEntityName.count() + 1); _aliasesByEntityName.setObjectForKey(alias, attr.entity().name()); @@ -531,20 +539,21 @@ public abstract class EOSQLExpression { return sqlStringForAttribute(_entity._attributeForPath(name)); } return sqlStringForAttribute(_entity.attributeNamed(name)); - + } /** - * Returns a string representing the path from the first - * relationship in the array to the last one. + * Returns a string representing the path from the first relationship in the + * array to the last one. + * * @param path An array of EORelationship objects. - * @return A string consisting of the names of the relationships - * separated by dots. + * @return A string consisting of the names of the relationships separated by + * dots. */ public String sqlStringForAttributePath(NSArray path) { StringBuffer buf = new StringBuffer(); for (int i = 0; i < path.count(); i++) { - EORelationship rel = (EORelationship)path.objectAtIndex(i); + EORelationship rel = (EORelationship) path.objectAtIndex(i); if (i > 0) buf.append('.'); buf.append(rel.name()); @@ -558,7 +567,8 @@ public abstract class EOSQLExpression { public String sqlStringForConjoinedQualifiers(NSArray qualifiers) { EOAndQualifier q = new EOAndQualifier(qualifiers); - return EOQualifierSQLGeneration.Support.supportForClass(EOAndQualifier.class).sqlStringForSQLExpression(q, this); + return EOQualifierSQLGeneration.Support.supportForClass(EOAndQualifier.class).sqlStringForSQLExpression(q, + this); } public String sqlStringForData(NSData data) { @@ -580,11 +590,13 @@ public abstract class EOSQLExpression { } public String sqlStringForKeyComparisonQualifier(EOKeyComparisonQualifier q) { - return EOQualifierSQLGeneration.Support.supportForClass(EOKeyComparisonQualifier.class).sqlStringForSQLExpression(q, this); + return EOQualifierSQLGeneration.Support.supportForClass(EOKeyComparisonQualifier.class) + .sqlStringForSQLExpression(q, this); } public String sqlStringForKeyValueQualifier(EOKeyValueQualifier q) { - return EOQualifierSQLGeneration.Support.supportForClass(EOKeyValueQualifier.class).sqlStringForSQLExpression(q, this); + return EOQualifierSQLGeneration.Support.supportForClass(EOKeyValueQualifier.class).sqlStringForSQLExpression(q, + this); } public String sqlStringForNegatedQualifier(EOQualifier q) { @@ -622,7 +634,8 @@ public abstract class EOSQLExpression { return "<="; } else if (sel == EOQualifier.QualifierOperatorGreaterThanOrEqualTo) { return ">="; - } else if (sel == EOQualifier.QualifierOperatorLike || sel == EOQualifier.QualifierOperatorCaseInsensitiveLike) { + } else if (sel == EOQualifier.QualifierOperatorLike + || sel == EOQualifier.QualifierOperatorCaseInsensitiveLike) { return " like "; } return sel.name(); @@ -646,7 +659,7 @@ public abstract class EOSQLExpression { if (_aliasesByEntityName.count() > 0) { Enumeration enumeration = _aliasesByEntityName.keyEnumerator(); while (enumeration.hasMoreElements()) { - String key = (String)enumeration.nextElement(); + String key = (String) enumeration.nextElement(); if (!key.equals(root.name())) { buf.append(", "); buf.append(key); @@ -668,30 +681,31 @@ public abstract class EOSQLExpression { } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.5 2005/05/11 15:21:53 cgruber - * Change enum to enumeration, since enum is now a keyword as of Java 5.0 + * Revision 1.5 2005/05/11 15:21:53 cgruber Change enum to enumeration, since + * enum is now a keyword as of Java 5.0 * * A few other comments in the code. * - * Revision 1.4 2003/08/29 21:14:18 chochos - * fix the algorithm in formatStringValue. + * Revision 1.4 2003/08/29 21:14:18 chochos fix the algorithm in + * formatStringValue. * - * Revision 1.3 2003/08/14 02:12:32 chochos - * implemented use of (simple) qualifiers + * Revision 1.3 2003/08/14 02:12:32 chochos implemented use of (simple) + * qualifiers * - * Revision 1.2 2003/08/13 22:59:39 chochos - * Can now generate simple one-entity select statements. + * Revision 1.2 2003/08/13 22:59:39 chochos Can now generate simple one-entity + * select statements. * - * Revision 1.1 2003/08/13 01:04:32 chochos - * the SQL generation classes. EOSQLExpression still needs a lot of work, but the factory is pretty much done. + * Revision 1.1 2003/08/13 01:04:32 chochos the SQL generation classes. + * EOSQLExpression still needs a lot of work, but the factory is pretty much + * done. * */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOSQLExpressionFactory.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOSQLExpressionFactory.java index 6bdbffe..4e20a7a 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOSQLExpressionFactory.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOSQLExpressionFactory.java @@ -25,11 +25,11 @@ import net.wotonomy.foundation.NSArray; import net.wotonomy.foundation.NSDictionary; /** -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public class EOSQLExpressionFactory { protected EOAdaptor _adaptor; @@ -49,8 +49,9 @@ public class EOSQLExpressionFactory { } /** - * Creates an instance of the adaptor's expression class, - * with entity assigned to it. + * Creates an instance of the adaptor's expression class, with entity assigned + * to it. + * * @param entity The entity with which to initialize the expression. * @return An EOSQLExpression. */ @@ -58,13 +59,14 @@ public class EOSQLExpressionFactory { EOSQLExpression expr = null; if (_instantiator == null) { try { - _instantiator = _expressionClass.getConstructor(new Class[]{ EOEntity.class }); + _instantiator = _expressionClass.getConstructor(new Class[] { EOEntity.class }); } catch (Exception ex) { - throw new IllegalArgumentException("The expression class " + _expressionClass.getName() + " has no constructor with an entity parameter."); + throw new IllegalArgumentException("The expression class " + _expressionClass.getName() + + " has no constructor with an entity parameter."); } } try { - expr = (EOSQLExpression)_instantiator.newInstance(new Object[]{ entity }); + expr = (EOSQLExpression) _instantiator.newInstance(new Object[] { entity }); } catch (Exception ex) { throw new IllegalArgumentException("Cannot create new expression of class " + _expressionClass.getName()); } @@ -87,7 +89,8 @@ public class EOSQLExpressionFactory { return expr; } - public EOSQLExpression selectStatementForAttributes(NSArray atts, boolean lock, EOFetchSpecification fspec, EOEntity entity) { + public EOSQLExpression selectStatementForAttributes(NSArray atts, boolean lock, EOFetchSpecification fspec, + EOEntity entity) { EOSQLExpression expr = createExpression(entity); expr.prepareSelectExpressionWithAttributes(atts, lock, fspec); return expr; @@ -102,7 +105,7 @@ public class EOSQLExpressionFactory { public EOSQLExpression expressionForString(String sql) { EOSQLExpression expr = null; try { - expr = (EOSQLExpression)_expressionClass.newInstance(); + expr = (EOSQLExpression) _expressionClass.newInstance(); } catch (Exception e) { return null; } @@ -116,16 +119,17 @@ public class EOSQLExpressionFactory { } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.1 2003/08/13 01:04:32 chochos - * the SQL generation classes. EOSQLExpression still needs a lot of work, but the factory is pretty much done. + * Revision 1.1 2003/08/13 01:04:32 chochos the SQL generation classes. + * EOSQLExpression still needs a lot of work, but the factory is pretty much + * done. * */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOStoredProcedure.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOStoredProcedure.java index f38ec2a..6fab43a 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOStoredProcedure.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOStoredProcedure.java @@ -22,13 +22,14 @@ import net.wotonomy.foundation.NSArray; import net.wotonomy.foundation.NSDictionary; import net.wotonomy.foundation.NSMutableArray; import net.wotonomy.foundation.NSMutableDictionary; + /** -* Represents a stored procedure in a database. -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * Represents a stored procedure in a database. + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public class EOStoredProcedure implements EOPropertyListEncoding { protected String _name; @@ -42,23 +43,23 @@ public class EOStoredProcedure implements EOPropertyListEncoding { public EOStoredProcedure(NSDictionary dict, Object obj) { super(); if (obj instanceof EOModel) - _model = (EOModel)obj; - NSArray a = (NSArray)dict.objectForKey("arguments"); + _model = (EOModel) obj; + NSArray a = (NSArray) dict.objectForKey("arguments"); if (a != null) { NSMutableArray args = new NSMutableArray(a.count()); for (int i = 0; i < a.count(); i++) { - NSDictionary ad = (NSDictionary)a.objectAtIndex(i); + NSDictionary ad = (NSDictionary) a.objectAtIndex(i); EOAttribute arg = new EOAttribute(ad, this); args.addObject(arg); } _arguments = args; } - setName((String)dict.objectForKey("name")); - setExternalName((String)dict.objectForKey("externalName")); + setName((String) dict.objectForKey("name")); + setExternalName((String) dict.objectForKey("externalName")); if (dict.objectForKey("userInfo") != null) - setUserInfo((NSDictionary)dict.objectForKey("userInfo")); + setUserInfo((NSDictionary) dict.objectForKey("userInfo")); if (dict.objectForKey("internalInfo") != null) - _internalInfo = (NSDictionary)dict.objectForKey("internalInfo"); + _internalInfo = (NSDictionary) dict.objectForKey("internalInfo"); } public EOStoredProcedure(String withName) { @@ -69,6 +70,7 @@ public class EOStoredProcedure implements EOPropertyListEncoding { public void setName(String value) { _name = value; } + public String name() { return _name; } @@ -76,6 +78,7 @@ public class EOStoredProcedure implements EOPropertyListEncoding { public void setExternalName(String value) { _externalName = value; } + public String externalName() { return _externalName; } @@ -83,6 +86,7 @@ public class EOStoredProcedure implements EOPropertyListEncoding { public void setArguments(NSArray value) { _arguments = value; } + public NSArray arguments() { return _arguments; } @@ -94,6 +98,7 @@ public class EOStoredProcedure implements EOPropertyListEncoding { public void setUserInfo(NSDictionary info) { _userInfo = info; } + public NSDictionary userInfo() { return _userInfo; } @@ -107,7 +112,7 @@ public class EOStoredProcedure implements EOPropertyListEncoding { NSMutableArray arr = new NSMutableArray(_arguments.count()); NSMutableDictionary d = null; for (int i = 0; i < _arguments.count(); i++) { - EOAttribute a = (EOAttribute)_arguments.objectAtIndex(i); + EOAttribute a = (EOAttribute) _arguments.objectAtIndex(i); d = new NSMutableDictionary(); a.encodeIntoPropertyList(d); arr.addObject(d); @@ -117,25 +122,23 @@ public class EOStoredProcedure implements EOPropertyListEncoding { } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.4 2003/08/11 19:38:27 chochos - * Can now read from a file and re-write to another file. + * Revision 1.4 2003/08/11 19:38:27 chochos Can now read from a file and + * re-write to another file. * - * Revision 1.3 2003/08/09 01:36:32 chochos - * implement EOPropertyListEncoding + * Revision 1.3 2003/08/09 01:36:32 chochos implement EOPropertyListEncoding * - * Revision 1.2 2003/08/08 02:14:43 chochos - * can create a stored procedure from a property list. main accessors are in place. + * Revision 1.2 2003/08/08 02:14:43 chochos can create a stored procedure from a + * property list. main accessors are in place. * - * Revision 1.1 2003/08/07 02:41:04 chochos - * these don't do much for now. + * Revision 1.1 2003/08/07 02:41:04 chochos these don't do much for now. * -*/ \ No newline at end of file + */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/AbstractObjectStore.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/AbstractObjectStore.java index ddaacf5..1989582 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/AbstractObjectStore.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/AbstractObjectStore.java @@ -35,728 +35,638 @@ import net.wotonomy.foundation.NSSelector; import net.wotonomy.foundation.internal.WotonomyException; /** -* An abstract implementation of object store that -* implements common functionality. Subclasses must -* implement data object creation, initialization, and -* refault logic, as well as logic to commit an editing -* context. -*/ -public abstract class AbstractObjectStore extends EOObjectStore -{ - private NSMutableArray insertedIDsBuffer; - private NSMutableArray updatedIDsBuffer; - private NSMutableArray deletedIDsBuffer; - private NSMutableArray invalidatedIDsBuffer; - - private Map snapshots; - private List exceptionList; - - /** - * Constructs a new instance of this object store. - */ - public AbstractObjectStore() - { - snapshots = new HashMap(); - exceptionList = null; - - insertedIDsBuffer = new NSMutableArray(); - updatedIDsBuffer = new NSMutableArray(); - deletedIDsBuffer = new NSMutableArray(); - invalidatedIDsBuffer = new NSMutableArray(); - - // register for notifications - NSSelector handleNotification = - new NSSelector( "handleNotification", - new Class[] { NSNotification.class } ); - NSNotificationCenter.defaultCenter().addObserver( - this, - handleNotification, - EOClassDescription.ClassDescriptionNeededForEntityNameNotification, - null ); - } - - /** - * This implementation returns an appropriately configured array fault. - */ - public NSArray arrayFaultWithSourceGlobalID( EOGlobalID aGlobalID, - String aRelationship, EOEditingContext aContext ) - { // System.out.println( "arrayFaultWithSourceGlobalID: " + aGlobalID + " : " + aRelationship ); - return new ArrayFault( - aGlobalID, aRelationship, aContext ); - } - - /** - * This implementation returns the actual object for the specified id. - */ - public /*EOEnterpriseObject*/Object faultForGlobalID( EOGlobalID aGlobalID, - EOEditingContext aContext ) - { // System.out.println( "faultForGlobalID: " + aGlobalID ); - return /*(EOEnterpriseObject)*/createInstanceWithEditingContext( aGlobalID, aContext ); - } - - /** - * Returns a fault representing an object of the specified entity type with - * values from the specified dictionary. The fault should belong to the - * specified editing context. - * NOTE: Faults are not supported yet. - */ - public /*EOEnterpriseObject*/Object faultForRawRow( Map aDictionary, String anEntityName, - EOEditingContext aContext ) - { - //TODO: raw rows are not yet supported - throw new WotonomyException( "Faults are not yet supported." ); - } - - /** - * Given a newly instantiated object, this method initializes its - * properties to values appropriate for the specified id. The object - * should belong to the specified editing context. This method is called - * to populate faults. - */ - public void initializeObject( Object anObject, EOGlobalID aGlobalID, - EOEditingContext aContext ) - { //System.out.println( "initializeObject: " + aGlobalID ); - try - { - String entity = entityForGlobalIDOrObject( aGlobalID, null ); - EOClassDescription classDesc = - EOClassDescription.classDescriptionForEntityName( entity ); - if ( classDesc == null ) - { - throw new WotonomyException( "Unknown entity type: " + entity ); - } - - Collection attributes = classDesc.attributeKeys(); - Map data = readFromCache( aGlobalID, attributes ); - String key; - Iterator iterator = attributes.iterator(); - while ( iterator.hasNext() ) - { - key = iterator.next().toString(); - - // write the snapshot's reference into the object - if ( anObject instanceof EOKeyValueCoding ) - { - ((EOKeyValueCoding)anObject).takeStoredValueForKey( data.get( key ), key ); - } - else - { - EOKeyValueCodingSupport.takeStoredValueForKey( anObject, data.get( key ), key ); - } - - //NOTE: our objects are expected to make a copy - // of their data before it is modified, so it's okay - // to return them our copy of the data: - // we trust that they will not modify it. - } - } - catch ( Exception exc ) - { - exc.printStackTrace(); - } - } - - /** - * Reads the local data snapshot for the specified id. - * If no snapshot exists, a new snapshot is created. - * If the specified keys are not in the snapshot, - * new data is fetched into the snapshot. - * If null is specified, all known keys are returned. - * Will not return null. - * Result will have values for those keys and only - * those keys requested. Missing keys indicate an - * error occurred. - */ - protected Map readFromCache( EOGlobalID aGlobalID, Collection keys ) - { - Map snapshot = (Map) snapshots.get( aGlobalID ); - - // if no snapshot for this id, create an empty one - if ( snapshot == null ) - { - snapshot = new HashMap(); - snapshots.put( aGlobalID, snapshot ); - } - - // if we don't have all the necessary keys - if ( ( keys == null ) || ( ! snapshot.keySet().containsAll( keys ) ) ) - { - // we need to make a server call - try - { - Map data = readObject( aGlobalID, keys ); - - // compare timestamps - Comparable localTimestamp = (Comparable) timestampForData( snapshot ); - // if our local snapshot has an timestamp (new snapshots don't have timestamp) - if ( localTimestamp != null ) - { - Comparable incomingTimestamp = (Comparable) timestampForData( data ); - if ( incomingTimestamp == null ) - { - // not allowed to happen - new RuntimeException( "Server returned data without an timestamp" ).printStackTrace(); - // however, we can just assume it's a newer timestamp and continue - } - - // if timestamps don't match - if ( ( incomingTimestamp == null ) || ( ! incomingTimestamp.equals( localTimestamp ) ) ) - { - // dump our existing snapshot's data - snapshot.clear(); - // queue for a notification on this oid as updated - //TODO: implement this - } - } - - // copy new data into our local snapshot - snapshot.putAll( data ); - } - catch ( Exception exc ) - { - exc.printStackTrace(); - } - } - - // return just the requested keys from our updated snapshot - Map result = new HashMap(); - if ( keys == null ) - { - result.putAll( snapshot ); - } - else - { - Object key; - Iterator iterator = keys.iterator(); - while ( iterator.hasNext() ) - { - key = iterator.next(); - result.put( key, snapshot.get( key ) ); - } - } - return snapshot; - } - - /** - * Returns a comparable object (typically a Date or Long) for - * the given data map or snapshot. This is used to determine - * whether a local snapshot should be dumped in favor of fetched - * data from the server. - * Returns null if no timestamp can be determined, in which - * case the fetched data will assumed to be more recent than - * any local snapshot. - */ - abstract protected Comparable timestampForData( Map aDataMap ); - - /** - * Extracts the global id for the fetched data or snapshot. - * Some entities have multi-attribute keys that would be - * assembled into a single instance of EOGlobalID. - */ - abstract protected EOGlobalID globalIDForData( Map aDataMap ); - - /** - * Returns the entity that corresponds to the specified global id - * and/or object. Either may be null, but both will not be null. - * //FIXME: This is less than elegant. - */ - abstract protected String entityForGlobalIDOrObject( - EOGlobalID aGlobalID, Object anObject ); - - /** - * Returns the keys that have changed on the specified object. - * If null, all keys are presumed changed, including relationships. - */ - abstract protected Collection changedKeysForObject( Object anObject ); - - /** - * Returns the data for the row corresponding to the specified id - * containing at least the specified keys. Implementations are allowed - * to return more data than requested, and callers are advised to take - * advantage of the returned data. - */ - abstract protected Map readObject( EOGlobalID aGlobalID, Collection keys ); - - /** - * Returns the data for the row corresponding to the specified id. - * //TODO: Need a better return value? How to return invalidated list? - */ - abstract protected Map insertObject( EOGlobalID aGlobalID, Map aDataMap ); - - /** - * Returns the data for the row corresponding to the specified id. - * //TODO: Need a better return value? How to return invalidated list? - */ - abstract protected Object updateObject( EOGlobalID aGlobalID, Map aDataMap ); - - /** - * Returns the data for the row corresponding to the specified id. - * //TODO: Need a better return value? How to return invalidated list? - */ - abstract protected Object deleteObject( EOGlobalID aGlobalID ); - - /** - * Creates a new instance of an object that corresponds to the - * specified global id and is registered in the specified context. - * This implementation extracts the entity type from getEntityForGlobaID - * and construct a new instance from the class description that - * corresponds to the entity type. Override to change this behavior. - */ - protected Object createInstanceWithEditingContext( - EOGlobalID aGlobalID, EOEditingContext aContext ) - { - String entity = entityForGlobalIDOrObject( aGlobalID, null ); - EOClassDescription classDesc = - EOClassDescription.classDescriptionForEntityName( entity ); - if ( classDesc == null ) - { - throw new WotonomyException( "Unknown entity type: " + entity ); - } - - Object result = classDesc.createInstanceWithEditingContext( aContext, aGlobalID ); - if ( result instanceof EOFaulting ) - { - ((EOFaulting)result).turnIntoFault( null ); - } - return result; - } - - /** - * Dumps the snapshot corresponding to the specified id. - */ - protected void invalidateObject( EOGlobalID aGlobalID ) - { - snapshots.remove( aGlobalID ); - } - - /** - * Dumps all snapshots. - */ - protected void invalidateAllCache() - { - snapshots.clear(); - } - - /** - * Remove all values from all objects in memory, turning them into faults, - * and posts a notification that all objects have been invalidated. - */ - public void invalidateAllObjects() - { - invalidateAllCache(); - - // post notification - NSNotificationQueue.defaultQueue().enqueueNotification( - new NSNotification( - InvalidatedAllObjectsInStoreNotification, this ), - NSNotificationQueue.PostNow ); - } - - /** - * Removes values with the specified ids from memory, turning them into - * faults, and posts a notification that those objects have been invalidated. - */ - public void invalidateObjectsWithGlobalIDs( List aList ) - { - NSArray empty = new NSArray(); - NSMutableArray invalidated = new NSMutableArray(); - - Object object; - Iterator iterator = aList.iterator(); - while ( iterator.hasNext() ) - { - object = iterator.next(); - invalidateObject( (EOGlobalID) object ); - invalidated.addObject( object ); - } - - NSMutableDictionary info = new NSMutableDictionary(); - info.setObjectForKey( empty, InsertedKey ); - info.setObjectForKey( empty, UpdatedKey ); - info.setObjectForKey( empty, DeletedKey ); - info.setObjectForKey( invalidated, InvalidatedKey ); - - // post notification - NSNotificationQueue.defaultQueue(). - enqueueNotificationWithCoalesceMaskForModes( new NSNotification( - ObjectsChangedInStoreNotification, this, info ), - NSNotificationQueue.PostNow, - NSNotificationQueue.NotificationNoCoalescing, null ); - } - - /** - * Returns false because locking is not currently permitted. - */ - public boolean isObjectLockedWithGlobalID( EOGlobalID aGlobalID, - EOEditingContext aContext ) - { - return false; - } - - /** - * Does nothing because locking is not currently permitted. - */ - public void lockObjectWithGlobalID( EOGlobalID aGlobalID, - EOEditingContext aContext ) - { - // does nothing - } - - /** - * Returns a List of objects associated with the object - * with the specified id for the specified property - * relationship. This method may not return an array fault - * because array faults call this method to fetch on demand. - * All objects must be registered the specified editing context. - * The specified relationship key must produce a result of - * type Collection for the source object or an exception is thrown. - */ - public NSArray objectsForSourceGlobalID( EOGlobalID aGlobalID, - String aRelationship, EOEditingContext aContext ) - { // System.out.println( "objectsForSourceGlobalID: " + aGlobalID + " : " + aRelationship + " : " ); - - Map snapshot = readFromCache( aGlobalID, new NSArray( aRelationship ) ); - Object value = snapshot.get( aRelationship ); - if ( value == null ) value = new NSArray(); // empty list - if ( ! ( value instanceof Collection ) ) - { - throw new RuntimeException( "Specified relationship is not a collection: " - + aRelationship + " : " + aGlobalID + " : " + value ); - } - - NSArray result = new NSMutableArray(); - - // get fault for each id - EOGlobalID id; - Object fault; - Iterator iterator = ((Collection)value).iterator(); - while ( iterator.hasNext() ) - { - id = (EOGlobalID) iterator.next(); - - // get registered fault - fault = aContext.faultForGlobalID( id, aContext ); - - // assert fault - if ( fault == null ) - { - // this should never happen - throw new RuntimeException( - "Could not find fault for ID: " + id ); - } - - result.add( fault ); - } - - fireObjectsChangedInStore(); + * An abstract implementation of object store that implements common + * functionality. Subclasses must implement data object creation, + * initialization, and refault logic, as well as logic to commit an editing + * context. + */ +public abstract class AbstractObjectStore extends EOObjectStore { + private NSMutableArray insertedIDsBuffer; + private NSMutableArray updatedIDsBuffer; + private NSMutableArray deletedIDsBuffer; + private NSMutableArray invalidatedIDsBuffer; + + private Map snapshots; + private List exceptionList; + + /** + * Constructs a new instance of this object store. + */ + public AbstractObjectStore() { + snapshots = new HashMap(); + exceptionList = null; + + insertedIDsBuffer = new NSMutableArray(); + updatedIDsBuffer = new NSMutableArray(); + deletedIDsBuffer = new NSMutableArray(); + invalidatedIDsBuffer = new NSMutableArray(); + + // register for notifications + NSSelector handleNotification = new NSSelector("handleNotification", new Class[] { NSNotification.class }); + NSNotificationCenter.defaultCenter().addObserver(this, handleNotification, + EOClassDescription.ClassDescriptionNeededForEntityNameNotification, null); + } + + /** + * This implementation returns an appropriately configured array fault. + */ + public NSArray arrayFaultWithSourceGlobalID(EOGlobalID aGlobalID, String aRelationship, EOEditingContext aContext) { // System.out.println( + // "arrayFaultWithSourceGlobalID: + // " + // + + // aGlobalID + // + + // " + // : + // " + // + + // aRelationship + // ); + return new ArrayFault(aGlobalID, aRelationship, aContext); + } + + /** + * This implementation returns the actual object for the specified id. + */ + public /* EOEnterpriseObject */Object faultForGlobalID(EOGlobalID aGlobalID, EOEditingContext aContext) { // System.out.println( + // "faultForGlobalID: + // " + + // aGlobalID + // ); + return /* (EOEnterpriseObject) */createInstanceWithEditingContext(aGlobalID, aContext); + } + + /** + * Returns a fault representing an object of the specified entity type with + * values from the specified dictionary. The fault should belong to the + * specified editing context. NOTE: Faults are not supported yet. + */ + public /* EOEnterpriseObject */Object faultForRawRow(Map aDictionary, String anEntityName, + EOEditingContext aContext) { + // TODO: raw rows are not yet supported + throw new WotonomyException("Faults are not yet supported."); + } + + /** + * Given a newly instantiated object, this method initializes its properties to + * values appropriate for the specified id. The object should belong to the + * specified editing context. This method is called to populate faults. + */ + public void initializeObject(Object anObject, EOGlobalID aGlobalID, EOEditingContext aContext) { // System.out.println( + // "initializeObject: + // " + aGlobalID + // ); + try { + String entity = entityForGlobalIDOrObject(aGlobalID, null); + EOClassDescription classDesc = EOClassDescription.classDescriptionForEntityName(entity); + if (classDesc == null) { + throw new WotonomyException("Unknown entity type: " + entity); + } + + Collection attributes = classDesc.attributeKeys(); + Map data = readFromCache(aGlobalID, attributes); + String key; + Iterator iterator = attributes.iterator(); + while (iterator.hasNext()) { + key = iterator.next().toString(); + + // write the snapshot's reference into the object + if (anObject instanceof EOKeyValueCoding) { + ((EOKeyValueCoding) anObject).takeStoredValueForKey(data.get(key), key); + } else { + EOKeyValueCodingSupport.takeStoredValueForKey(anObject, data.get(key), key); + } + + // NOTE: our objects are expected to make a copy + // of their data before it is modified, so it's okay + // to return them our copy of the data: + // we trust that they will not modify it. + } + } catch (Exception exc) { + exc.printStackTrace(); + } + } + + /** + * Reads the local data snapshot for the specified id. If no snapshot exists, a + * new snapshot is created. If the specified keys are not in the snapshot, new + * data is fetched into the snapshot. If null is specified, all known keys are + * returned. Will not return null. Result will have values for those keys and + * only those keys requested. Missing keys indicate an error occurred. + */ + protected Map readFromCache(EOGlobalID aGlobalID, Collection keys) { + Map snapshot = (Map) snapshots.get(aGlobalID); + + // if no snapshot for this id, create an empty one + if (snapshot == null) { + snapshot = new HashMap(); + snapshots.put(aGlobalID, snapshot); + } + + // if we don't have all the necessary keys + if ((keys == null) || (!snapshot.keySet().containsAll(keys))) { + // we need to make a server call + try { + Map data = readObject(aGlobalID, keys); + + // compare timestamps + Comparable localTimestamp = (Comparable) timestampForData(snapshot); + // if our local snapshot has an timestamp (new snapshots don't have timestamp) + if (localTimestamp != null) { + Comparable incomingTimestamp = (Comparable) timestampForData(data); + if (incomingTimestamp == null) { + // not allowed to happen + new RuntimeException("Server returned data without an timestamp").printStackTrace(); + // however, we can just assume it's a newer timestamp and continue + } + + // if timestamps don't match + if ((incomingTimestamp == null) || (!incomingTimestamp.equals(localTimestamp))) { + // dump our existing snapshot's data + snapshot.clear(); + // queue for a notification on this oid as updated + // TODO: implement this + } + } + + // copy new data into our local snapshot + snapshot.putAll(data); + } catch (Exception exc) { + exc.printStackTrace(); + } + } + + // return just the requested keys from our updated snapshot + Map result = new HashMap(); + if (keys == null) { + result.putAll(snapshot); + } else { + Object key; + Iterator iterator = keys.iterator(); + while (iterator.hasNext()) { + key = iterator.next(); + result.put(key, snapshot.get(key)); + } + } + return snapshot; + } + + /** + * Returns a comparable object (typically a Date or Long) for the given data map + * or snapshot. This is used to determine whether a local snapshot should be + * dumped in favor of fetched data from the server. Returns null if no timestamp + * can be determined, in which case the fetched data will assumed to be more + * recent than any local snapshot. + */ + abstract protected Comparable timestampForData(Map aDataMap); + + /** + * Extracts the global id for the fetched data or snapshot. Some entities have + * multi-attribute keys that would be assembled into a single instance of + * EOGlobalID. + */ + abstract protected EOGlobalID globalIDForData(Map aDataMap); + + /** + * Returns the entity that corresponds to the specified global id and/or object. + * Either may be null, but both will not be null. //FIXME: This is less than + * elegant. + */ + abstract protected String entityForGlobalIDOrObject(EOGlobalID aGlobalID, Object anObject); + + /** + * Returns the keys that have changed on the specified object. If null, all keys + * are presumed changed, including relationships. + */ + abstract protected Collection changedKeysForObject(Object anObject); + + /** + * Returns the data for the row corresponding to the specified id containing at + * least the specified keys. Implementations are allowed to return more data + * than requested, and callers are advised to take advantage of the returned + * data. + */ + abstract protected Map readObject(EOGlobalID aGlobalID, Collection keys); + + /** + * Returns the data for the row corresponding to the specified id. //TODO: Need + * a better return value? How to return invalidated list? + */ + abstract protected Map insertObject(EOGlobalID aGlobalID, Map aDataMap); + + /** + * Returns the data for the row corresponding to the specified id. //TODO: Need + * a better return value? How to return invalidated list? + */ + abstract protected Object updateObject(EOGlobalID aGlobalID, Map aDataMap); + + /** + * Returns the data for the row corresponding to the specified id. //TODO: Need + * a better return value? How to return invalidated list? + */ + abstract protected Object deleteObject(EOGlobalID aGlobalID); + + /** + * Creates a new instance of an object that corresponds to the specified global + * id and is registered in the specified context. This implementation extracts + * the entity type from getEntityForGlobaID and construct a new instance from + * the class description that corresponds to the entity type. Override to change + * this behavior. + */ + protected Object createInstanceWithEditingContext(EOGlobalID aGlobalID, EOEditingContext aContext) { + String entity = entityForGlobalIDOrObject(aGlobalID, null); + EOClassDescription classDesc = EOClassDescription.classDescriptionForEntityName(entity); + if (classDesc == null) { + throw new WotonomyException("Unknown entity type: " + entity); + } + + Object result = classDesc.createInstanceWithEditingContext(aContext, aGlobalID); + if (result instanceof EOFaulting) { + ((EOFaulting) result).turnIntoFault(null); + } + return result; + } + + /** + * Dumps the snapshot corresponding to the specified id. + */ + protected void invalidateObject(EOGlobalID aGlobalID) { + snapshots.remove(aGlobalID); + } + + /** + * Dumps all snapshots. + */ + protected void invalidateAllCache() { + snapshots.clear(); + } + + /** + * Remove all values from all objects in memory, turning them into faults, and + * posts a notification that all objects have been invalidated. + */ + public void invalidateAllObjects() { + invalidateAllCache(); + + // post notification + NSNotificationQueue.defaultQueue().enqueueNotification( + new NSNotification(InvalidatedAllObjectsInStoreNotification, this), NSNotificationQueue.PostNow); + } + + /** + * Removes values with the specified ids from memory, turning them into faults, + * and posts a notification that those objects have been invalidated. + */ + public void invalidateObjectsWithGlobalIDs(List aList) { + NSArray empty = new NSArray(); + NSMutableArray invalidated = new NSMutableArray(); + + Object object; + Iterator iterator = aList.iterator(); + while (iterator.hasNext()) { + object = iterator.next(); + invalidateObject((EOGlobalID) object); + invalidated.addObject(object); + } + + NSMutableDictionary info = new NSMutableDictionary(); + info.setObjectForKey(empty, InsertedKey); + info.setObjectForKey(empty, UpdatedKey); + info.setObjectForKey(empty, DeletedKey); + info.setObjectForKey(invalidated, InvalidatedKey); + + // post notification + NSNotificationQueue.defaultQueue().enqueueNotificationWithCoalesceMaskForModes( + new NSNotification(ObjectsChangedInStoreNotification, this, info), NSNotificationQueue.PostNow, + NSNotificationQueue.NotificationNoCoalescing, null); + } + + /** + * Returns false because locking is not currently permitted. + */ + public boolean isObjectLockedWithGlobalID(EOGlobalID aGlobalID, EOEditingContext aContext) { + return false; + } + + /** + * Does nothing because locking is not currently permitted. + */ + public void lockObjectWithGlobalID(EOGlobalID aGlobalID, EOEditingContext aContext) { + // does nothing + } + + /** + * Returns a List of objects associated with the object with the specified id + * for the specified property relationship. This method may not return an array + * fault because array faults call this method to fetch on demand. All objects + * must be registered the specified editing context. The specified relationship + * key must produce a result of type Collection for the source object or an + * exception is thrown. + */ + public NSArray objectsForSourceGlobalID(EOGlobalID aGlobalID, String aRelationship, EOEditingContext aContext) { // System.out.println( + // "objectsForSourceGlobalID: + // " + // + + // aGlobalID + // + + // " + // : + // " + // + + // aRelationship + // + + // " + // : + // " + // ); + + Map snapshot = readFromCache(aGlobalID, new NSArray(aRelationship)); + Object value = snapshot.get(aRelationship); + if (value == null) + value = new NSArray(); // empty list + if (!(value instanceof Collection)) { + throw new RuntimeException( + "Specified relationship is not a collection: " + aRelationship + " : " + aGlobalID + " : " + value); + } + + NSArray result = new NSMutableArray(); + + // get fault for each id + EOGlobalID id; + Object fault; + Iterator iterator = ((Collection) value).iterator(); + while (iterator.hasNext()) { + id = (EOGlobalID) iterator.next(); + + // get registered fault + fault = aContext.faultForGlobalID(id, aContext); + + // assert fault + if (fault == null) { + // this should never happen + throw new RuntimeException("Could not find fault for ID: " + id); + } + + result.add(fault); + } + + fireObjectsChangedInStore(); //System.out.println( "done" ); - return result; - } - - /** - * Returns a List of objects the meet the criteria of - * the supplied specification. Faults are not allowed in the array. - * Each object is registered with the specified editing context. - * If any object is already fetched in the specified context, - * it is not refetched and that object should be used in the array. - */ - public NSArray objectsWithFetchSpecification( - EOFetchSpecification aFetchSpec, EOEditingContext aContext ) - { - NSMutableArray result = new NSMutableArray(); - - //TODO: implement this - - return result; - } - - /** - * Fires ObjectsChangedInStoreNotification - * with contents of buffers and then clears buffers. - * If buffers are empty, does nothing. - */ - private void fireObjectsChangedInStore() - { - // check for changes to broadcast - if ( insertedIDsBuffer.size() + updatedIDsBuffer.size() + - deletedIDsBuffer.size() + invalidatedIDsBuffer.size() == 0 ) - { - return; - } - - // broadcast ObjectsChangedInStoreNotification - // for the benefit of child editing contexts - - NSMutableDictionary storeInfo = new NSMutableDictionary(); - - storeInfo.setObjectForKey( - new NSArray( (Collection) insertedIDsBuffer ), - EOObjectStore.InsertedKey ); - storeInfo.setObjectForKey( - new NSArray( (Collection) updatedIDsBuffer ), - EOObjectStore.UpdatedKey ); - storeInfo.setObjectForKey( - new NSArray( (Collection) deletedIDsBuffer ), - EOObjectStore.DeletedKey ); - storeInfo.setObjectForKey( - new NSArray( (Collection) invalidatedIDsBuffer ), - EOObjectStore.InvalidatedKey ); - - // clear buffers - - insertedIDsBuffer.removeAllObjects(); - updatedIDsBuffer.removeAllObjects(); - deletedIDsBuffer.removeAllObjects(); - invalidatedIDsBuffer.removeAllObjects(); - - // post notification - NSNotificationQueue.defaultQueue(). - enqueueNotificationWithCoalesceMaskForModes( new NSNotification( - ObjectsChangedInStoreNotification, this, storeInfo ), - NSNotificationQueue.PostNow, - NSNotificationQueue.NotificationNoCoalescing, null ); - } - - /** - * Removes all values from the specified object, - * converting it into a fault for the specified id. - * New or deleted objects should not be refaulted. - */ - public void refaultObject( Object anObject, EOGlobalID aGlobalID, - EOEditingContext aContext ) - { + return result; + } + + /** + * Returns a List of objects the meet the criteria of the supplied + * specification. Faults are not allowed in the array. Each object is registered + * with the specified editing context. If any object is already fetched in the + * specified context, it is not refetched and that object should be used in the + * array. + */ + public NSArray objectsWithFetchSpecification(EOFetchSpecification aFetchSpec, EOEditingContext aContext) { + NSMutableArray result = new NSMutableArray(); + + // TODO: implement this + + return result; + } + + /** + * Fires ObjectsChangedInStoreNotification with contents of buffers and then + * clears buffers. If buffers are empty, does nothing. + */ + private void fireObjectsChangedInStore() { + // check for changes to broadcast + if (insertedIDsBuffer.size() + updatedIDsBuffer.size() + deletedIDsBuffer.size() + + invalidatedIDsBuffer.size() == 0) { + return; + } + + // broadcast ObjectsChangedInStoreNotification + // for the benefit of child editing contexts + + NSMutableDictionary storeInfo = new NSMutableDictionary(); + + storeInfo.setObjectForKey(new NSArray((Collection) insertedIDsBuffer), EOObjectStore.InsertedKey); + storeInfo.setObjectForKey(new NSArray((Collection) updatedIDsBuffer), EOObjectStore.UpdatedKey); + storeInfo.setObjectForKey(new NSArray((Collection) deletedIDsBuffer), EOObjectStore.DeletedKey); + storeInfo.setObjectForKey(new NSArray((Collection) invalidatedIDsBuffer), EOObjectStore.InvalidatedKey); + + // clear buffers + + insertedIDsBuffer.removeAllObjects(); + updatedIDsBuffer.removeAllObjects(); + deletedIDsBuffer.removeAllObjects(); + invalidatedIDsBuffer.removeAllObjects(); + + // post notification + NSNotificationQueue.defaultQueue().enqueueNotificationWithCoalesceMaskForModes( + new NSNotification(ObjectsChangedInStoreNotification, this, storeInfo), NSNotificationQueue.PostNow, + NSNotificationQueue.NotificationNoCoalescing, null); + } + + /** + * Removes all values from the specified object, converting it into a fault for + * the specified id. New or deleted objects should not be refaulted. + */ + public void refaultObject(Object anObject, EOGlobalID aGlobalID, EOEditingContext aContext) { //System.out.println( "refaultObject: " + aGlobalID ); //new net.wotonomy.ui.swing.util.StackTraceInspector(); - if ( anObject instanceof EOFaulting ) - { - ((EOFaulting)anObject).turnIntoFault( null ); - } - } - - /** - * Writes all changes in the specified editing context - * to the respository. - */ - public void saveChangesInEditingContext ( EOEditingContext aContext ) - { - Object result; // need a container result? - Map updateMap; - Object object; - EOGlobalID id; - Iterator iterator; - - //TODO: the ordering of operations here - // needs to be a lot more sophisticated. - - // process deletes first - iterator = aContext.deletedObjects().iterator(); - while ( iterator.hasNext() ) - { - object = iterator.next(); - id = aContext.globalIDForObject( object ); - try - { - result = deleteObject( id ); - } - catch ( Exception exc ) - { - System.out.println( "Error deleting object: " + id ); - exc.printStackTrace(); - } - } - - // process inserts next - iterator = aContext.insertedObjects().iterator(); - while ( iterator.hasNext() ) - { - object = iterator.next(); - processInsert( aContext, object ); - } - - // process updates last - iterator = aContext.updatedObjects().iterator(); - while ( iterator.hasNext() ) - { - object = iterator.next(); - id = aContext.globalIDForObject( object ); - try - { - updateMap = getUpdateMap( aContext, object ); - result = updateObject( id, updateMap ); - } - catch ( Exception exc ) - { - System.out.println( "Error updating object: " + id ); - exc.printStackTrace(); - } - } - - //aContext.invalidateAllObjects(); - } - - protected Object processInsert( EOEditingContext aContext, Object object ) - { - Map result = null; - EOGlobalID id = aContext.globalIDForObject( object ); - try - { - Map updateMap; - updateMap = getUpdateMap( aContext, object ); - result = insertObject( id, updateMap ); - id = globalIDForData( result ); // read new permanent id - - // broadcast that the global id has changed. - NSMutableDictionary userInfo = new NSMutableDictionary(); - userInfo.setObjectForKey( id, aContext.globalIDForObject( object ) ); - NSNotificationQueue.defaultQueue().enqueueNotification( - new NSNotification( EOGlobalID.GlobalIDChangedNotification, - null , userInfo ), NSNotificationQueue.PostNow ); - - } - catch ( Exception exc ) - { - System.out.println( "Error inserting object: " + id ); - exc.printStackTrace(); - } - return result; - } - - /** - * This method returns a map containing just the keys that are modified - * for a given object, converting any to-one or to-many relationships - * to id references. - */ - protected Map getUpdateMap( EOEditingContext aContext, Object anObject ) - { - Map result = new HashMap(); - EOEditingContext context = aContext; - - String entity = entityForGlobalIDOrObject( null, anObject ); - EOClassDescription classDesc = - EOClassDescription.classDescriptionForEntityName( entity ); - if ( classDesc == null ) - { - throw new WotonomyException( "Unknown entity type: " + entity ); - } - - NSArray oneKeys = classDesc.toOneRelationshipKeys(); - NSArray manyKeys = classDesc.toManyRelationshipKeys(); - - String key; - Object value; - EOGlobalID id; - - Collection changedKeys = changedKeysForObject( anObject ); - if ( changedKeys == null ) - { - // assume all keys changed - changedKeys = classDesc.attributeKeys(); - changedKeys.addAll( oneKeys ); - changedKeys.addAll( manyKeys ); - } - Iterator iterator = changedKeys.iterator(); - while ( iterator.hasNext() ) - { - key = iterator.next().toString(); - if ( anObject instanceof EOKeyValueCoding ) - { - value = ((EOKeyValueCoding)anObject).storedValueForKey( key ); - } - else - { - value = EOKeyValueCodingSupport.storedValueForKey( anObject, key ); - } - - // convert to-one relationship to oid - if ( oneKeys.contains( key ) ) - { - id = context.globalIDForObject( value ); - - // if this id hasn't been persisted, save it first - // NOTE: this won't work for self-referential graphs of objects! - if ( id.isTemporary() ) - { - processInsert( aContext, value ); - id = context.globalIDForObject( value ); - } - - value = id; - } - else - // convert to-many relationship list to oid list - if ( manyKeys.contains( key ) ) - { - //NOTE: we can assume that array faults that - // are marked as changed have been fired. - if ( value instanceof Collection ) - { - Object object; - Collection newValue = new LinkedList(); - Iterator jiterator = ((Collection)value).iterator(); - while ( jiterator.hasNext() ) - { - object = jiterator.next(); - id = context.globalIDForObject( object ); - - // if this id hasn't been persisted, save it first - // NOTE: this won't work for self-referential graphs of objects! - if ( id.isTemporary() ) - { - processInsert( aContext, object ); - id = context.globalIDForObject( object ); - } - newValue.add( id ); - } - value = newValue; - } - else - { - // should never happen - new RuntimeException( - "Can't update to-many relationship because it's not a Collection." ) - .printStackTrace(); - } - } - - // place value in map - result.put( key, value ); - } - -System.out.println( result ); - return result; - } - -/* - * $Log$ - * 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. - * - * Revision 1.1 2006/02/16 13:19:57 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. - * - * Revision 1.5 2003/12/18 15:37:38 mpowers - * Changes to retain ability to work with objects that don't necessarily - * implement EOEnterpriseObject. I would still like to preserve this case - * for general usage, however the access package is free to assume that - * those objects will be EOs and cast appropriately. - * - * Revision 1.4 2003/08/19 01:53:12 chochos - * EOObjectStore had some incompatible return types (Object instead of EOEnterpriseObject, in fault methods mostly). It's internally consistent but I hope it doesn't break anything based on this, even though fault methods mostly throw exceptions for now. - * - * Revision 1.3 2002/10/24 18:18:12 mpowers - * NSArray's are now considered read-only, so we can return our internal - * representation to reduce unnecessary object allocation. - * - * Revision 1.2 2002/01/19 17:27:49 mpowers - * Implemented most of it. - * - * Revision 1.1 2001/11/25 22:44:02 mpowers - * Contributing draft of AbstractObjectStore. - * - * - */ + if (anObject instanceof EOFaulting) { + ((EOFaulting) anObject).turnIntoFault(null); + } + } + + /** + * Writes all changes in the specified editing context to the respository. + */ + public void saveChangesInEditingContext(EOEditingContext aContext) { + Object result; // need a container result? + Map updateMap; + Object object; + EOGlobalID id; + Iterator iterator; + + // TODO: the ordering of operations here + // needs to be a lot more sophisticated. + + // process deletes first + iterator = aContext.deletedObjects().iterator(); + while (iterator.hasNext()) { + object = iterator.next(); + id = aContext.globalIDForObject(object); + try { + result = deleteObject(id); + } catch (Exception exc) { + System.out.println("Error deleting object: " + id); + exc.printStackTrace(); + } + } + + // process inserts next + iterator = aContext.insertedObjects().iterator(); + while (iterator.hasNext()) { + object = iterator.next(); + processInsert(aContext, object); + } + + // process updates last + iterator = aContext.updatedObjects().iterator(); + while (iterator.hasNext()) { + object = iterator.next(); + id = aContext.globalIDForObject(object); + try { + updateMap = getUpdateMap(aContext, object); + result = updateObject(id, updateMap); + } catch (Exception exc) { + System.out.println("Error updating object: " + id); + exc.printStackTrace(); + } + } + + // aContext.invalidateAllObjects(); + } + + protected Object processInsert(EOEditingContext aContext, Object object) { + Map result = null; + EOGlobalID id = aContext.globalIDForObject(object); + try { + Map updateMap; + updateMap = getUpdateMap(aContext, object); + result = insertObject(id, updateMap); + id = globalIDForData(result); // read new permanent id + + // broadcast that the global id has changed. + NSMutableDictionary userInfo = new NSMutableDictionary(); + userInfo.setObjectForKey(id, aContext.globalIDForObject(object)); + NSNotificationQueue.defaultQueue().enqueueNotification( + new NSNotification(EOGlobalID.GlobalIDChangedNotification, null, userInfo), + NSNotificationQueue.PostNow); + + } catch (Exception exc) { + System.out.println("Error inserting object: " + id); + exc.printStackTrace(); + } + return result; + } + + /** + * This method returns a map containing just the keys that are modified for a + * given object, converting any to-one or to-many relationships to id + * references. + */ + protected Map getUpdateMap(EOEditingContext aContext, Object anObject) { + Map result = new HashMap(); + EOEditingContext context = aContext; + + String entity = entityForGlobalIDOrObject(null, anObject); + EOClassDescription classDesc = EOClassDescription.classDescriptionForEntityName(entity); + if (classDesc == null) { + throw new WotonomyException("Unknown entity type: " + entity); + } + + NSArray oneKeys = classDesc.toOneRelationshipKeys(); + NSArray manyKeys = classDesc.toManyRelationshipKeys(); + + String key; + Object value; + EOGlobalID id; + + Collection changedKeys = changedKeysForObject(anObject); + if (changedKeys == null) { + // assume all keys changed + changedKeys = classDesc.attributeKeys(); + changedKeys.addAll(oneKeys); + changedKeys.addAll(manyKeys); + } + Iterator iterator = changedKeys.iterator(); + while (iterator.hasNext()) { + key = iterator.next().toString(); + if (anObject instanceof EOKeyValueCoding) { + value = ((EOKeyValueCoding) anObject).storedValueForKey(key); + } else { + value = EOKeyValueCodingSupport.storedValueForKey(anObject, key); + } + + // convert to-one relationship to oid + if (oneKeys.contains(key)) { + id = context.globalIDForObject(value); + + // if this id hasn't been persisted, save it first + // NOTE: this won't work for self-referential graphs of objects! + if (id.isTemporary()) { + processInsert(aContext, value); + id = context.globalIDForObject(value); + } + + value = id; + } else + // convert to-many relationship list to oid list + if (manyKeys.contains(key)) { + // NOTE: we can assume that array faults that + // are marked as changed have been fired. + if (value instanceof Collection) { + Object object; + Collection newValue = new LinkedList(); + Iterator jiterator = ((Collection) value).iterator(); + while (jiterator.hasNext()) { + object = jiterator.next(); + id = context.globalIDForObject(object); + + // if this id hasn't been persisted, save it first + // NOTE: this won't work for self-referential graphs of objects! + if (id.isTemporary()) { + processInsert(aContext, object); + id = context.globalIDForObject(object); + } + newValue.add(id); + } + value = newValue; + } else { + // should never happen + new RuntimeException("Can't update to-many relationship because it's not a Collection.") + .printStackTrace(); + } + } + + // place value in map + result.put(key, value); + } + + System.out.println(result); + return result; + } + + /* + * $Log$ 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. + * + * Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. + * + * Revision 1.5 2003/12/18 15:37:38 mpowers Changes to retain ability to work + * with objects that don't necessarily implement EOEnterpriseObject. I would + * still like to preserve this case for general usage, however the access + * package is free to assume that those objects will be EOs and cast + * appropriately. + * + * Revision 1.4 2003/08/19 01:53:12 chochos EOObjectStore had some incompatible + * return types (Object instead of EOEnterpriseObject, in fault methods mostly). + * It's internally consistent but I hope it doesn't break anything based on + * this, even though fault methods mostly throw exceptions for now. + * + * Revision 1.3 2002/10/24 18:18:12 mpowers NSArray's are now considered + * read-only, so we can return our internal representation to reduce unnecessary + * object allocation. + * + * Revision 1.2 2002/01/19 17:27:49 mpowers Implemented most of it. + * + * Revision 1.1 2001/11/25 22:44:02 mpowers Contributing draft of + * AbstractObjectStore. + * + * + */ } - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/ArrayFault.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/ArrayFault.java index 59e135b..3a2bcaf 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/ArrayFault.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/ArrayFault.java @@ -25,195 +25,165 @@ import java.util.ListIterator; import net.wotonomy.foundation.NSArray; /** -* A class that extends NSArray to intercept any accessor calls -* in order to defer loading until the last possible moment.

-* -* Because ArrayFault inherits from NSArray which implements -* List which implements Collection, data objects may declare -* their relationships to be of type NSArray, List, or Collection.

-* -* This class should be returned by implementations of -* EOObjectStore.arrayFaultForSourceGlobalID(). -*/ -public class ArrayFault extends NSArray -{ - private EOEditingContext editingContext; - private EOGlobalID sourceID; - private String relationshipKey; - private boolean fetched; - - public ArrayFault( - EOGlobalID aSourceID, - String aRelationshipKey, - EOEditingContext aContext ) - { - super(); - editingContext = aContext; - sourceID = aSourceID; - relationshipKey = aRelationshipKey; - fetched = false; - } - - public boolean isFetched() - { - return fetched; - } - - protected void fireFault() - { - if ( !fetched ) - { + * A class that extends NSArray to intercept any accessor calls in order to + * defer loading until the last possible moment.
+ *
+ * + * Because ArrayFault inherits from NSArray which implements List which + * implements Collection, data objects may declare their relationships to be of + * type NSArray, List, or Collection.
+ *
+ * + * This class should be returned by implementations of + * EOObjectStore.arrayFaultForSourceGlobalID(). + */ +public class ArrayFault extends NSArray { + private EOEditingContext editingContext; + private EOGlobalID sourceID; + private String relationshipKey; + private boolean fetched; + + public ArrayFault(EOGlobalID aSourceID, String aRelationshipKey, EOEditingContext aContext) { + super(); + editingContext = aContext; + sourceID = aSourceID; + relationshipKey = aRelationshipKey; + fetched = false; + } + + public boolean isFetched() { + return fetched; + } + + protected void fireFault() { + if (!fetched) { //new net.wotonomy.ui.swing.util.StackTraceInspector(); //System.out.println( "ArrayFault.fireFault: before:" + this ); - fetched = true; - super.protectedAddAll( - editingContext.parentObjectStore().objectsForSourceGlobalID( - sourceID, - relationshipKey, - editingContext ) ); + fetched = true; + super.protectedAddAll(editingContext.parentObjectStore().objectsForSourceGlobalID(sourceID, relationshipKey, + editingContext)); //System.out.println( "ArrayFault.fireFault: after:" + this ); - } - } - - public Object clone() - { - fireFault(); - return super.clone(); - } - - public boolean contains(Object elem) - { - fireFault(); - return super.contains( elem ); - } - - public boolean equals(Object o) - { - fireFault(); - return super.equals( o ); - } - - public Object get(int index) - { - fireFault(); - return super.get( index ); - } - - /** - * Overridden to return the identity hash. - * This somewhat violates the List contract, - * but otherwise calling hash code would - * fire the fault. Bottom line: don't use - * array faults as keys in hash maps. - */ - public int hashCode() - { - return System.identityHashCode( this ); - } - - public int indexOf(Object o) - { - fireFault(); - return super.indexOf( o ); - } - - public boolean isEmpty() - { - fireFault(); - return super.isEmpty(); - } - - public Iterator iterator() - { - fireFault(); - return super.iterator(); - } - - public int lastIndexOf(Object o) - { - fireFault(); - return super.lastIndexOf( o ); - } - - public ListIterator listIterator() - { - fireFault(); - return super.listIterator(); - } - - public ListIterator listIterator(int index) - { - fireFault(); - return super.listIterator( index ); - } - - public int size() - { - fireFault(); - return super.size(); - } - - public List subList(int fromIndex, int toIndex) - { - fireFault(); - return super.subList( fromIndex, toIndex ); - } - - public Object[] toArray() - { - fireFault(); - return super.toArray(); - } - - public Object[] toArray(Object[] a) - { - fireFault(); - return super.toArray( a ); - } - - /** - * Overridden to display information about - * the fault only if not fetched. - * Calls to super if fetched. - */ - public String toString() - { - if ( isFetched() ) - { - return super.toString(); - } - return "[ArrayFault@"+Integer.toHexString( System.identityHashCode( this ) )+":"+sourceID+":"+relationshipKey+"]"; - } + } + } + + public Object clone() { + fireFault(); + return super.clone(); + } + + public boolean contains(Object elem) { + fireFault(); + return super.contains(elem); + } + + public boolean equals(Object o) { + fireFault(); + return super.equals(o); + } + + public Object get(int index) { + fireFault(); + return super.get(index); + } + + /** + * Overridden to return the identity hash. This somewhat violates the List + * contract, but otherwise calling hash code would fire the fault. Bottom line: + * don't use array faults as keys in hash maps. + */ + public int hashCode() { + return System.identityHashCode(this); + } + + public int indexOf(Object o) { + fireFault(); + return super.indexOf(o); + } + + public boolean isEmpty() { + fireFault(); + return super.isEmpty(); + } + + public Iterator iterator() { + fireFault(); + return super.iterator(); + } + + public int lastIndexOf(Object o) { + fireFault(); + return super.lastIndexOf(o); + } + + public ListIterator listIterator() { + fireFault(); + return super.listIterator(); + } + + public ListIterator listIterator(int index) { + fireFault(); + return super.listIterator(index); + } + + public int size() { + fireFault(); + return super.size(); + } + + public List subList(int fromIndex, int toIndex) { + fireFault(); + return super.subList(fromIndex, toIndex); + } + + public Object[] toArray() { + fireFault(); + return super.toArray(); + } + + public Object[] toArray(Object[] a) { + fireFault(); + return super.toArray(a); + } + + /** + * Overridden to display information about the fault only if not fetched. Calls + * to super if fetched. + */ + public String toString() { + if (isFetched()) { + return super.toString(); + } + return "[ArrayFault@" + Integer.toHexString(System.identityHashCode(this)) + ":" + sourceID + ":" + + relationshipKey + "]"; + } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.5 2003/12/18 15:37:38 mpowers - * Changes to retain ability to work with objects that don't necessarily - * implement EOEnterpriseObject. I would still like to preserve this case - * for general usage, however the access package is free to assume that - * those objects will be EOs and cast appropriately. + * Revision 1.5 2003/12/18 15:37:38 mpowers Changes to retain ability to work + * with objects that don't necessarily implement EOEnterpriseObject. I would + * still like to preserve this case for general usage, however the access + * package is free to assume that those objects will be EOs and cast + * appropriately. * - * Revision 1.4 2003/08/19 01:53:12 chochos - * EOObjectStore had some incompatible return types (Object instead of EOEnterpriseObject, in fault methods mostly). It's internally consistent but I hope it doesn't break anything based on this, even though fault methods mostly throw exceptions for now. + * Revision 1.4 2003/08/19 01:53:12 chochos EOObjectStore had some incompatible + * return types (Object instead of EOEnterpriseObject, in fault methods mostly). + * It's internally consistent but I hope it doesn't break anything based on + * this, even though fault methods mostly throw exceptions for now. * - * Revision 1.3 2002/10/24 18:17:37 mpowers - * ArrayFaults are now read-only. + * Revision 1.3 2002/10/24 18:17:37 mpowers ArrayFaults are now read-only. * - * Revision 1.2 2001/05/06 22:22:55 mpowers - * Debugging. + * Revision 1.2 2001/05/06 22:22:55 mpowers Debugging. * - * Revision 1.1 2001/05/05 23:05:42 mpowers - * Implemented Array Faults. + * Revision 1.1 2001/05/05 23:05:42 mpowers Implemented Array Faults. * * */ - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/ChildDataSource.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/ChildDataSource.java index 8123668..1d62881 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/ChildDataSource.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/ChildDataSource.java @@ -7,181 +7,137 @@ import net.wotonomy.foundation.NSArray; import net.wotonomy.foundation.NSMutableArray; /** -* A data source that automates the process of -* creating a child editing context and copying -* objects from a parent context into it. -* Attach this data source to a display group -* that represents a "detail" or "drill-down" -* view.

-* -* Once created, editingContext() will return the -* child context, and fetch() will return the objects -* that were copied into the child context. -*/ -public class ChildDataSource extends EODataSource -{ - private EODataSource parent; - private EOEditingContext context; - private EOClassDescription classDescription; - private NSMutableArray objects; - - /** - * Creates a child editing context for the - * specified parent's context and copies the - * specified object into the child context. - * The object must exist in the parent context. - * fetch() will return the child's object. - */ - public ChildDataSource( - EODataSource aParentSource, - Object anObject ) - { - this( aParentSource, new NSArray( (Object) anObject ) ); + * A data source that automates the process of creating a child editing context + * and copying objects from a parent context into it. Attach this data source to + * a display group that represents a "detail" or "drill-down" view.
+ *
+ * + * Once created, editingContext() will return the child context, and fetch() + * will return the objects that were copied into the child context. + */ +public class ChildDataSource extends EODataSource { + private EODataSource parent; + private EOEditingContext context; + private EOClassDescription classDescription; + private NSMutableArray objects; + + /** + * Creates a child editing context for the specified parent's context and copies + * the specified object into the child context. The object must exist in the + * parent context. fetch() will return the child's object. + */ + public ChildDataSource(EODataSource aParentSource, Object anObject) { + this(aParentSource, new NSArray((Object) anObject)); } - - /** - * Creates a child editing context for the - * specified parent's context and copies the - * specified objects into the child context. - * The objects must exist in the parent context. - * The order of the parent's objects in the - * collection will determine the order in - * which the child objects are returned from - * fetch(). - */ - public ChildDataSource( - EODataSource aParentSource, - Collection anObjectList ) - { - EOEditingContext parentContext = - aParentSource.editingContext(); - - parent = aParentSource; - context = new EOEditingContext( parentContext ); + + /** + * Creates a child editing context for the specified parent's context and copies + * the specified objects into the child context. The objects must exist in the + * parent context. The order of the parent's objects in the collection will + * determine the order in which the child objects are returned from fetch(). + */ + public ChildDataSource(EODataSource aParentSource, Collection anObjectList) { + EOEditingContext parentContext = aParentSource.editingContext(); + + parent = aParentSource; + context = new EOEditingContext(parentContext); //!new net.wotonomy.ui.swing.util.ObjectInspector( context ); - objects = new NSMutableArray(); - classDescription = null; - - Object o; - Object copy; - boolean allSameClass = true; - Iterator it = anObjectList.iterator(); - while ( it.hasNext() ) - { - o = it.next(); - - // determine class - if ( allSameClass == true ) - { - Class c = o.getClass(); - if ( classDescription == null ) - { - classDescription = - EOClassDescription.classDescriptionForClass( c ); - } - else - { - if ( c != classDescription.getDescribedClass() ) - { - allSameClass = false; - classDescription = null; - } - } - } - - // copy and add to list - objects.addObject( parentContext.faultForGlobalID( - parentContext.globalIDForObject( o ), context ) ); - } + objects = new NSMutableArray(); + classDescription = null; + + Object o; + Object copy; + boolean allSameClass = true; + Iterator it = anObjectList.iterator(); + while (it.hasNext()) { + o = it.next(); + + // determine class + if (allSameClass == true) { + Class c = o.getClass(); + if (classDescription == null) { + classDescription = EOClassDescription.classDescriptionForClass(c); + } else { + if (c != classDescription.getDescribedClass()) { + allSameClass = false; + classDescription = null; + } + } + } + + // copy and add to list + objects.addObject(parentContext.faultForGlobalID(parentContext.globalIDForObject(o), context)); + } } - - /** - * Returns the editing context for this data source, - * which was created in the constructor and whose - * parent is the editing context specified in the - * constructor. - */ - public EOEditingContext editingContext() - { - return context; - } - - /** - * This implementation does nothing. - */ - public void insertObject ( Object anObject ) - { + /** + * Returns the editing context for this data source, which was created in the + * constructor and whose parent is the editing context specified in the + * constructor. + */ + public EOEditingContext editingContext() { + return context; } - /** - * This implementation does nothing. - */ - public void deleteObject ( Object anObject ) - { + /** + * This implementation does nothing. + */ + public void insertObject(Object anObject) { } - /** - * Returns a List containing the objects in this - * data source. This implementation returns all - * TestObjects that have been persisted to the - * datastore in the data directory. - */ - public NSArray fetchObjects () - { - return new NSArray( (Collection) objects ); - } - - /** - * Returns a data source that is capable of - * manipulating objects of the type returned by - * applying the specified key to objects - * vended by this data source. - * This implementation forwards the call to - * the parent data source. - * @see #qualifyWithRelationshipKey - */ - public EODataSource - dataSourceQualifiedByKey ( String aKey ) - { - //FIXME: This is fundamentally broken. - // Objects vended from the returned source - // are not registered in our editing context. - // We probably need yet another utility data - // source class that would wrap another source - // and convert vended objects into a different - // context. - - return parent.dataSourceQualifiedByKey( aKey ); + /** + * This implementation does nothing. + */ + public void deleteObject(Object anObject) { + } - /** - * Restricts this data source to vend those - * objects that are associated with the specified - * key on the specified object. - * This implementation forwards the call to - * the parent data source. - */ - public void - qualifyWithRelationshipKey ( - String aKey, Object anObject ) - { - parent.qualifyWithRelationshipKey( aKey, anObject ); + /** + * Returns a List containing the objects in this data source. This + * implementation returns all TestObjects that have been persisted to the + * datastore in the data directory. + */ + public NSArray fetchObjects() { + return new NSArray((Collection) objects); } - /** - * Returns the description of the class of the - * objects that is vended by this data source, - * or null if this cannot be determined. - * This implementation returns the class of the - * objects passed to the constructor if they are - * all the same class, otherwise returns null. - */ - public EOClassDescription - classDescriptionForObjects () - { - return classDescription; - } + /** + * Returns a data source that is capable of manipulating objects of the type + * returned by applying the specified key to objects vended by this data source. + * This implementation forwards the call to the parent data source. + * + * @see #qualifyWithRelationshipKey + */ + public EODataSource dataSourceQualifiedByKey(String aKey) { + // FIXME: This is fundamentally broken. + // Objects vended from the returned source + // are not registered in our editing context. + // We probably need yet another utility data + // source class that would wrap another source + // and convert vended objects into a different + // context. + + return parent.dataSourceQualifiedByKey(aKey); + } + + /** + * Restricts this data source to vend those objects that are associated with the + * specified key on the specified object. This implementation forwards the call + * to the parent data source. + */ + public void qualifyWithRelationshipKey(String aKey, Object anObject) { + parent.qualifyWithRelationshipKey(aKey, anObject); + } + + /** + * Returns the description of the class of the objects that is vended by this + * data source, or null if this cannot be determined. This implementation + * returns the class of the objects passed to the constructor if they are all + * the same class, otherwise returns null. + */ + public EOClassDescription classDescriptionForObjects() { + return classDescription; + } } diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOAndQualifier.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOAndQualifier.java index 049eb33..9d8eb96 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOAndQualifier.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOAndQualifier.java @@ -28,88 +28,75 @@ import net.wotonomy.foundation.NSMutableArray; import net.wotonomy.foundation.internal.WotonomyException; /** -* EOAndQualifier contains other EOQualifiers, -* evaluating as true only if all of the contained -* qualifiers evaluate as true. -* -* @author michael@mpowers.net -* @author yjcheung@intersectsoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public class EOAndQualifier extends EOQualifier - implements EOKeyValueArchiving, EOQualifierEvaluation -{ - private List qualifiers; - - public EOAndQualifier( - List aQualifierList ) - { - qualifiers = new LinkedList( aQualifierList ); - } - - /** - * Returns a List of qualifiers contained by this qualifier. - */ - public NSArray qualifiers() - { - return new NSArray( qualifiers ); - } - - /** - * Add a new qualifier to the list. - */ - public void addQualifier(EOQualifier qualifier) - { - qualifiers.add(qualifier); - } - - /** - * Evaluates this qualifier for the specified object, - * and returns whether the object is qualified. - * selector() is invoked on the value for key() on the - * specified object, with value() as the parameter. - * - * Note: this has the lazy "and" implementation. Ex. - * Qal1 and Qal2. If the Qal1 is evaluated to be false, then it returns - * false without evaluating Qa12. - */ - public boolean evaluateWithObject( Object anObject ) - { - boolean retVal = true; - Iterator it = qualifiers.iterator(); - while (it.hasNext() && retVal) - { - retVal = ((EOQualifier) it.next()).evaluateWithObject(anObject); - } - return retVal; - } - - /** - * Returns a string representation of this qualifier. - */ - public String toString() - { - StringBuffer myBuf = new StringBuffer("("); - Iterator it = qualifiers.iterator(); - while (it.hasNext()) - { - myBuf = myBuf.append(((EOQualifier) it.next()).toString()).append(" and "); - } - String myStr = myBuf.toString(); - myStr = myStr.substring(0, myStr.lastIndexOf(" and")).concat(")"); - return myStr; - } + * EOAndQualifier contains other EOQualifiers, evaluating as true only if all of + * the contained qualifiers evaluate as true. + * + * @author michael@mpowers.net + * @author yjcheung@intersectsoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public class EOAndQualifier extends EOQualifier implements EOKeyValueArchiving, EOQualifierEvaluation { + private List qualifiers; + + public EOAndQualifier(List aQualifierList) { + qualifiers = new LinkedList(aQualifierList); + } + + /** + * Returns a List of qualifiers contained by this qualifier. + */ + public NSArray qualifiers() { + return new NSArray(qualifiers); + } + + /** + * Add a new qualifier to the list. + */ + public void addQualifier(EOQualifier qualifier) { + qualifiers.add(qualifier); + } + + /** + * Evaluates this qualifier for the specified object, and returns whether the + * object is qualified. selector() is invoked on the value for key() on the + * specified object, with value() as the parameter. + * + * Note: this has the lazy "and" implementation. Ex. Qal1 and Qal2. If the Qal1 + * is evaluated to be false, then it returns false without evaluating Qa12. + */ + public boolean evaluateWithObject(Object anObject) { + boolean retVal = true; + Iterator it = qualifiers.iterator(); + while (it.hasNext() && retVal) { + retVal = ((EOQualifier) it.next()).evaluateWithObject(anObject); + } + return retVal; + } + + /** + * Returns a string representation of this qualifier. + */ + public String toString() { + StringBuffer myBuf = new StringBuffer("("); + Iterator it = qualifiers.iterator(); + while (it.hasNext()) { + myBuf = myBuf.append(((EOQualifier) it.next()).toString()).append(" and "); + } + String myStr = myBuf.toString(); + myStr = myStr.substring(0, myStr.lastIndexOf(" and")).concat(")"); + return myStr; + } public static Object decodeWithKeyValueUnarchiver(EOKeyValueUnarchiver arch) { - NSArray a = (NSArray)arch.decodeObjectForKey("qualifiers"); + NSArray a = (NSArray) arch.decodeObjectForKey("qualifiers"); if (a == null) return null; NSMutableArray l = new NSMutableArray(); for (int i = 0; i < a.count(); i++) { - NSDictionary d = (NSDictionary)a.objectAtIndex(i); + NSDictionary d = (NSDictionary) a.objectAtIndex(i); EOKeyValueUnarchiver ua = new EOKeyValueUnarchiver(d); - EOQualifier q = (EOQualifier)EOQualifier.decodeWithKeyValueUnarchiver(ua); + EOQualifier q = (EOQualifier) EOQualifier.decodeWithKeyValueUnarchiver(ua); if (q != null) l.addObject(q); } @@ -119,11 +106,11 @@ public class EOAndQualifier extends EOQualifier public void encodeWithKeyValueArchiver(EOKeyValueArchiver arch) { arch.encodeObject("EOAndQualifier", "class"); NSMutableArray arr = new NSMutableArray(qualifiers.size()); - for (int i = 0; i < qualifiers.size(); i++) { - EOQualifier q = (EOQualifier)qualifiers.get(i); + for (int i = 0; i < qualifiers.size(); i++) { + EOQualifier q = (EOQualifier) qualifiers.get(i); if (q instanceof EOKeyValueArchiving) { EOKeyValueArchiver ar2 = new EOKeyValueArchiver(); - ((EOKeyValueArchiving)q).encodeWithKeyValueArchiver(ar2); + ((EOKeyValueArchiving) q).encodeWithKeyValueArchiver(ar2); arr.addObject(ar2.dictionary()); } else throw new WotonomyException("Cannot archive instance of " + q.getClass().getName()); @@ -134,34 +121,31 @@ public class EOAndQualifier extends EOQualifier } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.6 2003/08/12 01:43:04 chochos - * formally implement EOQualifierEvaluation + * Revision 1.6 2003/08/12 01:43:04 chochos formally implement + * EOQualifierEvaluation * - * Revision 1.5 2003/08/09 01:22:51 chochos - * qualifiers implement EOKeyValueArchiving + * Revision 1.5 2003/08/09 01:22:51 chochos qualifiers implement + * EOKeyValueArchiving * - * Revision 1.4 2003/08/06 23:07:52 chochos - * general code cleanup (mostly, removing unused imports) + * Revision 1.4 2003/08/06 23:07:52 chochos general code cleanup (mostly, + * removing unused imports) * - * Revision 1.3 2001/10/31 15:25:14 mpowers - * Cleanup of qualifiers. + * Revision 1.3 2001/10/31 15:25:14 mpowers Cleanup of qualifiers. * - * Revision 1.2 2001/10/30 22:57:28 mpowers - * EOQualifier framework is now working. + * Revision 1.2 2001/10/30 22:57:28 mpowers EOQualifier framework is now + * working. * - * Revision 1.1 2001/09/13 15:25:56 mpowers - * Started implementation of the EOQualifier framework. + * Revision 1.1 2001/09/13 15:25:56 mpowers Started implementation of the + * EOQualifier framework. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOClassDescription.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOClassDescription.java index cd07ebb..79019de 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOClassDescription.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOClassDescription.java @@ -28,574 +28,476 @@ import net.wotonomy.foundation.internal.Introspector; import net.wotonomy.foundation.internal.WotonomyException; /** -* EOClassDescription provides meta-information about a class -* and is used to customize certain behaviors within wotonomy -* and specifically within editing contexts and object stores. -*

-* -* The default implementation works for most well-formed java beans, -* but you will want to create your own subclass most typically -* to customize the toOne and toMany relationships for your -* class to ensure that an entire graph of objects is not -* persisted in order to perist a single object. -*

-* -* The easiest way to register your subclass is to create it -* in the same package as the class it describes but with -* a "ClassDesc" suffix. For example, "my.package.MyEntity" -* would be described by "my.package.MyEntityClassDesc".

-* -* Note that while the interface is the same, the implementation -* of this class differs substantially from the specification -* in order to be more useful for java classes. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 900 $ -*/ -public class EOClassDescription -{ - /** - * A delete rule specifying that object(s) that reference - * this object should have those references set to null - * when this object is deleted. - */ - public static final int DeleteRuleNullify = 0; - - /** - * A delete rule specifying that object(s) referenced by - * this object should also be deleted when this object - * is deleted. - */ - public static final int DeleteRuleCascade = 1; - - /** - * A delete rule specicying that this object should - * not be allowed to be deleted if it references any - * object(s). - */ - public static final int DeleteRuleDeny = 2; - - /** - * A delete rule specifying that no action be taken - * when this object is deleted. This is the default. - */ - public static final int DeleteRuleNoAction = 3; - - /** - * Notification fired when a class description has been requested - * for a class. Observers should watch for this notification and - * call registerClassDescription so that class descriptions can be - * loaded on-demand. - * The notification's object is the requested class and the - * user info dictionary is null. - */ - public static final String ClassDescriptionNeededForClassNotification = - "ClassDescriptionNeededForClassNotification"; - - /** - * Notification fired when a class description has been requested - * for an entity name. Observers should watch for this notification and - * call registerClassDescription so that class descriptions can be - * loaded on-demand. - * The notification's object is the requested name and the - * user info dictionary is null. - */ - public static final String ClassDescriptionNeededForEntityNameNotification = - "ClassDescriptionNeededForEntityNameNotification"; + * EOClassDescription provides meta-information about a class and is used to + * customize certain behaviors within wotonomy and specifically within editing + * contexts and object stores.
+ *
+ * + * The default implementation works for most well-formed java beans, but you + * will want to create your own subclass most typically to customize the toOne + * and toMany relationships for your class to ensure that an entire graph of + * objects is not persisted in order to perist a single object.
+ *
+ * + * The easiest way to register your subclass is to create it in the same package + * as the class it describes but with a "ClassDesc" suffix. For example, + * "my.package.MyEntity" would be described by "my.package.MyEntityClassDesc". + *
+ *
+ * + * Note that while the interface is the same, the implementation of this class + * differs substantially from the specification in order to be more useful for + * java classes. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 900 $ + */ +public class EOClassDescription { + /** + * A delete rule specifying that object(s) that reference this object should + * have those references set to null when this object is deleted. + */ + public static final int DeleteRuleNullify = 0; + + /** + * A delete rule specifying that object(s) referenced by this object should also + * be deleted when this object is deleted. + */ + public static final int DeleteRuleCascade = 1; + + /** + * A delete rule specicying that this object should not be allowed to be deleted + * if it references any object(s). + */ + public static final int DeleteRuleDeny = 2; + + /** + * A delete rule specifying that no action be taken when this object is deleted. + * This is the default. + */ + public static final int DeleteRuleNoAction = 3; + + /** + * Notification fired when a class description has been requested for a class. + * Observers should watch for this notification and call + * registerClassDescription so that class descriptions can be loaded on-demand. + * The notification's object is the requested class and the user info dictionary + * is null. + */ + public static final String ClassDescriptionNeededForClassNotification = "ClassDescriptionNeededForClassNotification"; + + /** + * Notification fired when a class description has been requested for an entity + * name. Observers should watch for this notification and call + * registerClassDescription so that class descriptions can be loaded on-demand. + * The notification's object is the requested name and the user info dictionary + * is null. + */ + public static final String ClassDescriptionNeededForEntityNameNotification = "ClassDescriptionNeededForEntityNameNotification"; public EOClassDescription() { super(); } - /** - * Returns the class description that corresponds to the specified class. - * If the class description has not already been loaded, a - * ClassDescriptionNeededForClassNotification is posted. - * If the class description is still not found, the class' loader - * is consulted for a class in the same package and named the same as the - * specified class but appended with "ClassDesc", e.g. "EmployeeObjectClassDesc". - * If the class description is still not found, a class description is - * returned that uses java bean introspection to provide reasonable values. - */ - public static EOClassDescription classDescriptionForClass( - Class aClass ) - { - if ( classMap == null ) classMap = new HashMap(); - EOClassDescription result = (EOClassDescription) classMap.get( aClass ); - if ( result == null ) - { - // if not found, post notification - NSNotificationCenter.defaultCenter().postNotification( - ClassDescriptionNeededForClassNotification, aClass, null ); - result = (EOClassDescription) classMap.get( aClass ); - } - if ( result == null ) - { - // if not found, look for similarly named class - String className = aClass.getName() + ClassNameSuffix; - Class classDesc; - try - { - classDesc = aClass.getClassLoader().loadClass( className ); - if ( classDesc != null ) - { - result = (EOClassDescription) classDesc.newInstance(); - registerClassDescription( result, aClass ); - } - } - catch ( Exception exc ) - { - // ignore exceptions and resume - } - } - if ( result == null ) - { - // if not found, default to this class - result = new EOClassDescription( aClass ); - registerClassDescription( result, aClass ); - } - return result; - } - - /** - * Returns the class description that corresponds to the specified - * entity name. If the class description has not already been - * loaded, a ClassDescriptionNeededForEntityNameNotification is posted. - * Returns null if no class description can be found for the entity name. - */ - public static EOClassDescription classDescriptionForEntityName( - String aName ) - { - if ( entityMap == null ) entityMap = new HashMap(); - EOClassDescription result = (EOClassDescription) entityMap.get( aName ); - if ( result == null ) - { - // if not found, post notification - NSNotificationCenter.defaultCenter().postNotification( - ClassDescriptionNeededForEntityNameNotification, aName, null ); - result = (EOClassDescription) entityMap.get( aName ); - } - return result; - } - - /** - * Clears all cached class descriptions so that new requests - * for class descriptions will be re-loaded on-demand. - */ - public static void invalidateClassDescriptionCache() - { - classMap.clear(); - entityMap.clear(); - } - - /** - * Registers the specified class descriptiong for the specified class. - * Nulls are not allowed - to clear the cache call invalidateClassDescriptionCache(). - */ - public static void registerClassDescription( - EOClassDescription description, - Class aClass ) - { - if ( classMap == null ) classMap = new HashMap(); - if ( entityMap == null ) entityMap = new HashMap(); - description.theClass = aClass; - classMap.put( aClass, description ); - entityMap.put( description.entityName(), description ); - } + /** + * Returns the class description that corresponds to the specified class. If the + * class description has not already been loaded, a + * ClassDescriptionNeededForClassNotification is posted. If the class + * description is still not found, the class' loader is consulted for a class in + * the same package and named the same as the specified class but appended with + * "ClassDesc", e.g. "EmployeeObjectClassDesc". If the class description is + * still not found, a class description is returned that uses java bean + * introspection to provide reasonable values. + */ + public static EOClassDescription classDescriptionForClass(Class aClass) { + if (classMap == null) + classMap = new HashMap(); + EOClassDescription result = (EOClassDescription) classMap.get(aClass); + if (result == null) { + // if not found, post notification + NSNotificationCenter.defaultCenter().postNotification(ClassDescriptionNeededForClassNotification, aClass, + null); + result = (EOClassDescription) classMap.get(aClass); + } + if (result == null) { + // if not found, look for similarly named class + String className = aClass.getName() + ClassNameSuffix; + Class classDesc; + try { + classDesc = aClass.getClassLoader().loadClass(className); + if (classDesc != null) { + result = (EOClassDescription) classDesc.newInstance(); + registerClassDescription(result, aClass); + } + } catch (Exception exc) { + // ignore exceptions and resume + } + } + if (result == null) { + // if not found, default to this class + result = new EOClassDescription(aClass); + registerClassDescription(result, aClass); + } + return result; + } -/* - public static Object classDelegate() - { - throw new WotonomyException( "Not implemented yet." ); - } - - public static void setClassDelegate( - Object aDelegate) - { - throw new WotonomyException( "Not implemented yet." ); - } -*/ - - /** - * The string appended to the java class name when - * searching the class path for an appropriate description. - */ - private final static String ClassNameSuffix = "ClassDesc"; - - private static Map classMap; - private static Map entityMap; - - protected Class theClass; - private NSMutableArray attributes; - - /** - * Constructor may only be called by subclasses. - */ - protected EOClassDescription( Class aClass ) - { - theClass = aClass; - } - - /** - * Returns a List of all the attributes for this class. - * This implementation reflects on the java class to produce - * a list of attributes, and then removes those keys that - * are returned by toOneRelationshipKeys and toManyRelationhipKeys. - */ - public NSArray attributeKeys() - { - if ( attributes == null ) - { - NSMutableArray readProperties = new NSMutableArray(); - String[] read = Introspector.getReadPropertiesForClass( theClass ); - for ( int i = 0; i < read.length; i++ ) - { - readProperties.addObject( read[i] ); - } - - attributes = new NSMutableArray(); - String[] write = Introspector.getWritePropertiesForClass( theClass ); - for ( int i = 0; i < write.length; i++ ) - { - attributes.addObject( write[i] ); - } - - // only use properties on both lists: read/write - attributes.retainAll( readProperties ); - - // remove relationship keys - attributes.removeAll( toOneRelationshipKeys() ); - attributes.removeAll( toManyRelationshipKeys() ); - } - return attributes; - } - - /** - * This method is called when the specified object has been - * fetched into the specified editing context. Fetch means - * an object was fetched using a fetch specification - it is - * not the same thing as an insertion. - * This implementation does nothing. - */ - public void awakeObjectFromFetch( - Object object, - EOEditingContext anEditingContext ) - { - } - - /** - * This method is called when the specified object has been - * inserted into the specified editing context. Insertion - * means an object was inserted by a display group - it does - * not mean the same thing as a fetch. - * This implementation does nothing. - */ - public void awakeObjectFromInsertion( - Object object, - EOEditingContext anEditingContext ) - { - // does nothing - } - - /** - * Returns the class decription for the object referenced - * by the specified relationship key, or null if the - * class description cannot be determined for that key. - * This implementation returns null. - */ - public EOClassDescription classDescriptionForDestinationKey( - String detailKey ) - { - return null; - } - - /** - * Creates a new instance of the class represented by this - * class description, registering it with the specified - * editing context and global id. The class description - * may not keep references to the newly created object. - * The editing context and/or the id may be null. - * This implementation constructs a new instance of the class - * and registers it with the specified editing context. - * If the global id is specified, the object will be populated - * with the appropriate data, otherwise the object will be - * treated as a newly inserted object. - * If no editing context is specified, the global id is - * ignored and the new instance of the class is returned. - */ - public Object createInstanceWithEditingContext( - EOEditingContext anEditingContext, - EOGlobalID globalID ) - { + /** + * Returns the class description that corresponds to the specified entity name. + * If the class description has not already been loaded, a + * ClassDescriptionNeededForEntityNameNotification is posted. Returns null if no + * class description can be found for the entity name. + */ + public static EOClassDescription classDescriptionForEntityName(String aName) { + if (entityMap == null) + entityMap = new HashMap(); + EOClassDescription result = (EOClassDescription) entityMap.get(aName); + if (result == null) { + // if not found, post notification + NSNotificationCenter.defaultCenter().postNotification(ClassDescriptionNeededForEntityNameNotification, + aName, null); + result = (EOClassDescription) entityMap.get(aName); + } + return result; + } + + /** + * Clears all cached class descriptions so that new requests for class + * descriptions will be re-loaded on-demand. + */ + public static void invalidateClassDescriptionCache() { + classMap.clear(); + entityMap.clear(); + } + + /** + * Registers the specified class descriptiong for the specified class. Nulls are + * not allowed - to clear the cache call invalidateClassDescriptionCache(). + */ + public static void registerClassDescription(EOClassDescription description, Class aClass) { + if (classMap == null) + classMap = new HashMap(); + if (entityMap == null) + entityMap = new HashMap(); + description.theClass = aClass; + classMap.put(aClass, description); + entityMap.put(description.entityName(), description); + } + + /* + * public static Object classDelegate() { throw new WotonomyException( + * "Not implemented yet." ); } + * + * public static void setClassDelegate( Object aDelegate) { throw new + * WotonomyException( "Not implemented yet." ); } + */ + + /** + * The string appended to the java class name when searching the class path for + * an appropriate description. + */ + private final static String ClassNameSuffix = "ClassDesc"; + + private static Map classMap; + private static Map entityMap; + + protected Class theClass; + private NSMutableArray attributes; + + /** + * Constructor may only be called by subclasses. + */ + protected EOClassDescription(Class aClass) { + theClass = aClass; + } + + /** + * Returns a List of all the attributes for this class. This implementation + * reflects on the java class to produce a list of attributes, and then removes + * those keys that are returned by toOneRelationshipKeys and + * toManyRelationhipKeys. + */ + public NSArray attributeKeys() { + if (attributes == null) { + NSMutableArray readProperties = new NSMutableArray(); + String[] read = Introspector.getReadPropertiesForClass(theClass); + for (int i = 0; i < read.length; i++) { + readProperties.addObject(read[i]); + } + + attributes = new NSMutableArray(); + String[] write = Introspector.getWritePropertiesForClass(theClass); + for (int i = 0; i < write.length; i++) { + attributes.addObject(write[i]); + } + + // only use properties on both lists: read/write + attributes.retainAll(readProperties); + + // remove relationship keys + attributes.removeAll(toOneRelationshipKeys()); + attributes.removeAll(toManyRelationshipKeys()); + } + return attributes; + } + + /** + * This method is called when the specified object has been fetched into the + * specified editing context. Fetch means an object was fetched using a fetch + * specification - it is not the same thing as an insertion. This implementation + * does nothing. + */ + public void awakeObjectFromFetch(Object object, EOEditingContext anEditingContext) { + } + + /** + * This method is called when the specified object has been inserted into the + * specified editing context. Insertion means an object was inserted by a + * display group - it does not mean the same thing as a fetch. This + * implementation does nothing. + */ + public void awakeObjectFromInsertion(Object object, EOEditingContext anEditingContext) { + // does nothing + } + + /** + * Returns the class decription for the object referenced by the specified + * relationship key, or null if the class description cannot be determined for + * that key. This implementation returns null. + */ + public EOClassDescription classDescriptionForDestinationKey(String detailKey) { + return null; + } + + /** + * Creates a new instance of the class represented by this class description, + * registering it with the specified editing context and global id. The class + * description may not keep references to the newly created object. The editing + * context and/or the id may be null. This implementation constructs a new + * instance of the class and registers it with the specified editing context. If + * the global id is specified, the object will be populated with the appropriate + * data, otherwise the object will be treated as a newly inserted object. If no + * editing context is specified, the global id is ignored and the new instance + * of the class is returned. + */ + public Object createInstanceWithEditingContext(EOEditingContext anEditingContext, EOGlobalID globalID) { //System.out.println( "createInstanceWithEditingContext: " + this + " : " + theClass ); - Object result = null; - try - { - result = theClass.newInstance(); - if ( anEditingContext != null ) - { - if ( globalID != null ) - { - if ( result instanceof EOEnterpriseObject ) - { - ((EOEnterpriseObject)result).awakeFromFetch( anEditingContext ); - } - // register in editing context - anEditingContext.recordObject( result, globalID ); - } - else // no global id specified - { - if ( result instanceof EOEnterpriseObject ) - { - ((EOEnterpriseObject)result).awakeFromInsertion( anEditingContext ); - } - // register as new object in editing context - anEditingContext.insertObject( result ); - } - } - } - catch ( Exception exc ) - { - // error instantiating - throw new WotonomyException( exc ); - } - return result; - } - -/* - public NSFormatter defaultFormatterForKey( - String key ) - { - throw new WotonomyException( "Not implemented yet." ); - } -*/ - - /** - * Returns the delete rule to be used for the specified - * relationship key. - * This implementation returns DeleteRuleNoAction. - */ - public int deleteRuleForRelationshipKey( - String relationshipKey ) - { - return DeleteRuleNoAction; - } - - /** - * Returns a human-readable title for the specified key. - * For example, displayNameForKey( "firstName" ) might - * return "First Name". - * This implementation attempts to construct such a string - * from the key, uppercasing the first character and - * inserting spaces before subsequent uppercase characters. - */ - public String displayNameForKey( - String key ) - { - if ( key == null ) return ""; - if ( key.length() == 0 ) return ""; - - StringBuffer result = new StringBuffer(); - result.append( Character.toUpperCase( key.charAt(0) ) ); - - char c; - int len = key.length(); - for ( int i = 1; i < len; i++ ) - { - c = key.charAt(i); - if ( Character.isUpperCase( c ) ) - { - result.append( ' ' ); - } - result.append( c ); - } - - return result.toString(); - } - - /** - * Returns a human-readable title for the class of objects - * that this class description represents. For example, - * class CustomerObject might return "Customer". - * This implementation returns the class name. - */ - public String entityName() - { - String result = theClass.getName(); - int index = result.lastIndexOf( "." ); - if ( index == -1 ) return result; - return result.substring( index+1 ); - } - - /** - * Returns the fetch specification associated with this - * class description that corresponds to the specified name, - * or null if not found. - * This implementation returns null. - */ - public EOFetchSpecification fetchSpecificationNamed( - String aString ) - { - return null; - } - - /** - * Returns the relationship key by which the object at the - * other end of the specified relationship key refers to - * this object, or null if not found. - * This implementation returns null. - */ - public String inverseForRelationshipKey( - String relationshipKey ) - { - return null; - } - - public boolean ownsDestinationObjectsForRelationshipKey( - String relationshipKey ) - { - throw new WotonomyException( "Not implemented yet." ); - } - - /** - * Called when this object has been deleted from the - * specified editing context. The delete rules for this - * object's relationships should be executed. - */ - public void propagateDeleteForObject( - Object object, - EOEditingContext anEditingContext ) - { - throw new WotonomyException( "Not implemented yet." ); - } - - /** - * Returns a List of the "to many" relationships for - * this class. - * This implementation returns an empty list. - */ - public NSArray toManyRelationshipKeys() - { - return NSArray.EmptyArray; - } - - /** - * Returns a List of the "to one" relationships for - * this class. - * This implementation returns an empty list. - */ - public NSArray toOneRelationshipKeys() - { - return NSArray.EmptyArray; - } - - /** - * Returns a human-readable description of the specified object - * that should not exceed 60 characters. - * This implementation returns anObject.toString(). - */ - public String userPresentableDescriptionForObject( - Object anObject ) - { - return anObject.toString(); - } - - /** - * Verifies that the specified object may be deleted. - * Throws an exception with a user-readable error message - * if the delete operation should not be allowed. - * This implementation does nothing. - */ - public void validateObjectForDelete( - Object object ) - { - // does nothing - } - - /** - * Verifies that the specified object may be saved. - * Throws an exception with a user-readable error message - * if the save operation should not be allowed. - * This implementation does nothing. - */ - public void validateObjectForSave( - Object object ) - { - // does nothing - } - - /** - * Validates the specified value for the specified key on this - * this class. Returns null if the value is acceptable, or - * returns an object that should be used in place of the specified - * object, or throws an exception with a user-readable error message - * if no acceptable value can be determined. - * This implementation returns null. - */ - public Object validateValueForKey( Object value, String key) - { - return null; - } - - /** - * Returns the Java Class that this description describes. - * NOTE: This method is not in the specification. - */ - public Class getDescribedClass() - { - return theClass; - } - + Object result = null; + try { + result = theClass.newInstance(); + if (anEditingContext != null) { + if (globalID != null) { + if (result instanceof EOEnterpriseObject) { + ((EOEnterpriseObject) result).awakeFromFetch(anEditingContext); + } + // register in editing context + anEditingContext.recordObject(result, globalID); + } else // no global id specified + { + if (result instanceof EOEnterpriseObject) { + ((EOEnterpriseObject) result).awakeFromInsertion(anEditingContext); + } + // register as new object in editing context + anEditingContext.insertObject(result); + } + } + } catch (Exception exc) { + // error instantiating + throw new WotonomyException(exc); + } + return result; + } + + /* + * public NSFormatter defaultFormatterForKey( String key ) { throw new + * WotonomyException( "Not implemented yet." ); } + */ + + /** + * Returns the delete rule to be used for the specified relationship key. This + * implementation returns DeleteRuleNoAction. + */ + public int deleteRuleForRelationshipKey(String relationshipKey) { + return DeleteRuleNoAction; + } + + /** + * Returns a human-readable title for the specified key. For example, + * displayNameForKey( "firstName" ) might return "First Name". This + * implementation attempts to construct such a string from the key, uppercasing + * the first character and inserting spaces before subsequent uppercase + * characters. + */ + public String displayNameForKey(String key) { + if (key == null) + return ""; + if (key.length() == 0) + return ""; + + StringBuffer result = new StringBuffer(); + result.append(Character.toUpperCase(key.charAt(0))); + + char c; + int len = key.length(); + for (int i = 1; i < len; i++) { + c = key.charAt(i); + if (Character.isUpperCase(c)) { + result.append(' '); + } + result.append(c); + } + + return result.toString(); + } + + /** + * Returns a human-readable title for the class of objects that this class + * description represents. For example, class CustomerObject might return + * "Customer". This implementation returns the class name. + */ + public String entityName() { + String result = theClass.getName(); + int index = result.lastIndexOf("."); + if (index == -1) + return result; + return result.substring(index + 1); + } + + /** + * Returns the fetch specification associated with this class description that + * corresponds to the specified name, or null if not found. This implementation + * returns null. + */ + public EOFetchSpecification fetchSpecificationNamed(String aString) { + return null; + } + + /** + * Returns the relationship key by which the object at the other end of the + * specified relationship key refers to this object, or null if not found. This + * implementation returns null. + */ + public String inverseForRelationshipKey(String relationshipKey) { + return null; + } + + public boolean ownsDestinationObjectsForRelationshipKey(String relationshipKey) { + throw new WotonomyException("Not implemented yet."); + } + + /** + * Called when this object has been deleted from the specified editing context. + * The delete rules for this object's relationships should be executed. + */ + public void propagateDeleteForObject(Object object, EOEditingContext anEditingContext) { + throw new WotonomyException("Not implemented yet."); + } + + /** + * Returns a List of the "to many" relationships for this class. This + * implementation returns an empty list. + */ + public NSArray toManyRelationshipKeys() { + return NSArray.EmptyArray; + } + + /** + * Returns a List of the "to one" relationships for this class. This + * implementation returns an empty list. + */ + public NSArray toOneRelationshipKeys() { + return NSArray.EmptyArray; + } + + /** + * Returns a human-readable description of the specified object that should not + * exceed 60 characters. This implementation returns anObject.toString(). + */ + public String userPresentableDescriptionForObject(Object anObject) { + return anObject.toString(); + } + + /** + * Verifies that the specified object may be deleted. Throws an exception with a + * user-readable error message if the delete operation should not be allowed. + * This implementation does nothing. + */ + public void validateObjectForDelete(Object object) { + // does nothing + } + + /** + * Verifies that the specified object may be saved. Throws an exception with a + * user-readable error message if the save operation should not be allowed. This + * implementation does nothing. + */ + public void validateObjectForSave(Object object) { + // does nothing + } + + /** + * Validates the specified value for the specified key on this this class. + * Returns null if the value is acceptable, or returns an object that should be + * used in place of the specified object, or throws an exception with a + * user-readable error message if no acceptable value can be determined. This + * implementation returns null. + */ + public Object validateValueForKey(Object value, String key) { + return null; + } + + /** + * Returns the Java Class that this description describes. NOTE: This method is + * not in the specification. + */ + public Class getDescribedClass() { + return theClass; + } + } /* - * $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.11 2003/08/08 05:50:32 chochos - * theClass is protected instead of private + * Revision 1.11 2003/08/08 05:50:32 chochos theClass is protected instead of + * private * - * Revision 1.10 2003/08/08 00:37:44 chochos - * default constructor is needed by subclasses + * Revision 1.10 2003/08/08 00:37:44 chochos default constructor is needed by + * subclasses * - * Revision 1.9 2001/12/20 18:55:46 mpowers - * Hooks for awakeFromInsertion and awakeFromFetch. + * Revision 1.9 2001/12/20 18:55:46 mpowers Hooks for awakeFromInsertion and + * awakeFromFetch. * - * Revision 1.8 2001/12/01 23:51:45 mpowers - * Corrected createWithEditingContext. + * Revision 1.8 2001/12/01 23:51:45 mpowers Corrected createWithEditingContext. * - * Revision 1.7 2001/11/25 22:43:38 mpowers - * Corrected createInstanceWithEditingContext. + * Revision 1.7 2001/11/25 22:43:38 mpowers Corrected + * createInstanceWithEditingContext. * - * 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.5 2001/04/28 22:17:51 mpowers - * Revised PropertyDataSource to be EOClassDescription-aware. + * Revision 1.5 2001/04/28 22:17:51 mpowers Revised PropertyDataSource to be + * EOClassDescription-aware. * - * Revision 1.4 2001/04/28 14:12:23 mpowers - * Refactored cloning/copying into KeyValueCodingUtilities. + * Revision 1.4 2001/04/28 14:12:23 mpowers Refactored cloning/copying into + * KeyValueCodingUtilities. * - * Revision 1.3 2001/04/27 23:37:20 mpowers - * Now using EOClassDescription in the EODataSource class, as we should. + * Revision 1.3 2001/04/27 23:37:20 mpowers Now using EOClassDescription in the + * EODataSource class, as we should. * - * Revision 1.2 2001/04/27 00:27:42 mpowers - * Partial implementation. + * Revision 1.2 2001/04/27 00:27:42 mpowers Partial implementation. * - * Revision 1.1 2001/03/29 03:29:49 mpowers - * Now using KeyValueCoding and Support instead of Introspector. + * Revision 1.1 2001/03/29 03:29:49 mpowers Now using KeyValueCoding and Support + * instead of Introspector. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOCooperatingObjectStore.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOCooperatingObjectStore.java index 072f867..98a8a60 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOCooperatingObjectStore.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOCooperatingObjectStore.java @@ -24,59 +24,58 @@ package net.wotonomy.control; import net.wotonomy.foundation.NSArray; import net.wotonomy.foundation.NSDictionary; import net.wotonomy.foundation.NSLocking; + /** -* A representation of a channel of communication to the database. -* -* @author cgruber@israfil.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * A representation of a channel of communication to the database. + * + * @author cgruber@israfil.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ -public abstract class EOCooperatingObjectStore extends EOObjectStore - implements NSLocking { +public abstract class EOCooperatingObjectStore extends EOObjectStore implements NSLocking { - public EOCooperatingObjectStore() { - } + public EOCooperatingObjectStore() { + } - public abstract boolean ownsGlobalID(EOGlobalID eoglobalid); + public abstract boolean ownsGlobalID(EOGlobalID eoglobalid); - public abstract boolean ownsObject(EOEnterpriseObject eoenterpriseobject); + public abstract boolean ownsObject(EOEnterpriseObject eoenterpriseobject); - public abstract boolean handlesFetchSpecification(EOFetchSpecification eofetchspecification); + public abstract boolean handlesFetchSpecification(EOFetchSpecification eofetchspecification); - public abstract void prepareForSaveWithCoordinator(EOObjectStoreCoordinator eoobjectstorecoordinator, EOEditingContext eoeditingcontext); + public abstract void prepareForSaveWithCoordinator(EOObjectStoreCoordinator eoobjectstorecoordinator, + EOEditingContext eoeditingcontext); - public abstract void recordChangesInEditingContext(); + public abstract void recordChangesInEditingContext(); - public abstract void recordUpdateForObject(EOEnterpriseObject eoenterpriseobject, NSDictionary nsdictionary); + public abstract void recordUpdateForObject(EOEnterpriseObject eoenterpriseobject, NSDictionary nsdictionary); - public abstract void performChanges(); + public abstract void performChanges(); - public abstract void commitChanges(); + public abstract void commitChanges(); - public abstract void rollbackChanges(); + public abstract void rollbackChanges(); - public abstract NSDictionary valuesForKeys(NSArray nsarray, EOEnterpriseObject eoenterpriseobject); + public abstract NSDictionary valuesForKeys(NSArray nsarray, EOEnterpriseObject eoenterpriseobject); - public abstract void lock(); + public abstract void lock(); - public abstract void unlock(); + public abstract void unlock(); } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.1 2002/07/14 21:59:06 mpowers - * Contributions from cgruber. + * Revision 1.1 2002/07/14 21:59:06 mpowers Contributions from cgruber. * - * Revision 1.2 2002/06/21 22:14:30 cgruber - * Add a log trail + * Revision 1.2 2002/06/21 22:14:30 cgruber Add a log trail * */ diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOCustomObject.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOCustomObject.java index 6b262cb..4c7ca40 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOCustomObject.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOCustomObject.java @@ -28,646 +28,540 @@ import net.wotonomy.foundation.NSSet; import net.wotonomy.foundation.internal.WotonomyException; /** -* EOCustomObject implements all the necessary interfaces to -* receive first-class treatment from the control framework. -* The implementation delegates as much class meta-behavior as -* possible to EOClassDescription, letting subclasses -* focus exclusively on business logic while still allowing -* them to customize as much class behavior as needed. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public class EOCustomObject - implements EOEnterpriseObject, - EOKeyValueCodingAdditions, - EODeferredFaulting, - EORelationshipManipulation, - EOValidation -{ - private transient static EOClassDescription classDescription; - private transient EOEditingContext editingContext; - - // static configuration - - /** - * Specifies whether the implementation of EOKeyValueCoding - * is permitted to access field directly. This implementation - * returns true; subclasses may override to customize this behavior. - */ - public static boolean canAccessFieldsDirectly() - { - return true; - } - - /** - * Specifies whether the implementation of EOKeyValueCoding - * is permitted to access private accessors. This implementation - * returns true; subclasses may override to customize this behavior. - */ - public static boolean shouldUseStoredAccessors() - { - return true; - } - - /** - * Specifies whether deferred faults should be used. This implementation - * returns false; subclasses may override to customize this behavior. - */ - public static boolean usesDeferredFaultCreation() - { - return false; - } - - // constructors - - /** - * Default constructor initializes private state. - * EditingContext and ClassDescription are set to null. - */ - public EOCustomObject() - { - editingContext = null; - classDescription = null; - } - - /** - * Preferred constructor, specifying an editing context, - * a class description, and a global id, any or all of which - * may be null. Subclasses should invoke this constructor. - */ - public EOCustomObject( - EOEditingContext aContext, - EOClassDescription aClassDescription, - EOGlobalID aGlobalID ) - { - editingContext = aContext; - classDescription = aClassDescription; - } - - // interface EOEnterpriseObject - - /** - * Returns a List of all property keys defined on this object. - * This includes both attributes and relationships. - * This implementation returns the union of attributeKeys, - * toOneRelationshipKeys, and toManyRelationshipKeys. - */ - public NSArray allPropertyKeys() - { - NSSet union = new NSSet(); - union.addAll( attributeKeys() ); - union.addAll( toOneRelationshipKeys() ); - union.addAll( toManyRelationshipKeys() ); - return new NSArray( (Collection) union ); - } - - /** - * Returns a list of all attributes defined on this object. - * Attributes are all properties that are not relationships. - * This implementation retrieves the keys from the class - * description. - */ - public NSArray attributeKeys() - { - return classDescription().attributeKeys(); - } - - //void awakeFromClientUpdate(EOEditingContext aContext) - - /** - * Called when the object has first been fetched into the - * specified editing context. This implementation calls - * awakeObjectFromFetch on the class description. - */ - public void awakeFromFetch(EOEditingContext anEditingContext) - { - classDescription().awakeObjectFromFetch( this, anEditingContext ); - } - - /** - * Called when the object has been inserted into the - * specified editing context. This implementation calls - * awakeObjectFromInsertion on the class description. - */ - public void awakeFromInsertion(EOEditingContext anEditingContext) - { - classDescription().awakeObjectFromInsertion( this, anEditingContext ); - } - - /** - * Returns a Map representing the delta of the current state - * from the state represented in the specified snapshot. - * The result will contain only the keys that have changed - * and their values. Relationship keys will map to an NSArray - * that contains an NSArray of added objects and an NSArray - * of removed objects, in that order. - */ - public NSDictionary changesFromSnapshot(NSDictionary snapshot) - { - throw new WotonomyException( "Not implemented yet." ); - } - - /** - * Returns a class description for this object. - * Calls EOClassDescription.classDescriptionForClass. - */ - public EOClassDescription classDescription() - { - if ( classDescription == null ) - { - classDescription = EOClassDescription.classDescriptionForClass( getClass() ); - if ( classDescription == null ) - { - throw new WotonomyException( - "No class description found for class: " + getClass() ); - } - } - return classDescription; - } - - /** - * Returns a class description for the object at the - * other end of the specified relationship key. - * This implementation calls to the classDescription. - */ - public EOClassDescription classDescriptionForDestinationKey(String aKey) - { - return classDescription().classDescriptionForDestinationKey( aKey ); - } - - /** - * Clears all property values for this object. - * This method is called to clean-up an object that - * will no longer be used, and implementations should - * ensure that all references are set to null to - * prevent problems with garbage-collection. - */ - public void clearProperties() - { - //FIXME: clear properties here - } - - /** - * Returns the delete rule constant defined on EOClassDescription - * for the relationship defined by the specified key. - * This implementation calls to the classDescription. - */ - public int deleteRuleForRelationshipKey(String aRelationshipKey) - { - return classDescription().deleteRuleForRelationshipKey( aRelationshipKey ); - } - - /** - * Returns the editing context in which this object is registered. - */ - public EOEditingContext editingContext() - { - return editingContext; - } - - /** - * Returns the name of the entity that this object represents. - */ - public String entityName() - { - return classDescription().entityName(); - } - - /** - * Returns a String containing all property keys and values for - * this object. Relationships should be represented by calling - * eoShallowDescription() on the object. - */ - public String eoDescription() - { - throw new WotonomyException( "Not implemented yet." ); - } - - /** - * Returns a String containing all attribute keys and values for - * this object. Relationships are not included. - */ - public String eoShallowDescription() - { - throw new WotonomyException( "Not implemented yet." ); - } - - /** - * Returns the key used to reference this object on the - * object at the other end of the specified relationship. - * This implementation calls to the class description. - */ - public String inverseForRelationshipKey(String aRelationshipKey) - { - return classDescription().inverseForRelationshipKey( aRelationshipKey ); - } - - //Object invokeRemoteMethod( - // String aMethodName, Class[] aTypeArray Object[] anArgumentArray) - - /** - * Returns whether the specified relationship key represents - * a to-many relationship. - */ - public boolean isToManyKey(String aKey) - { - return toManyRelationshipKeys().containsObject( aKey ); - } - - /** - * Returns whether the objects at the other end of the specified - * relationship should be deleted when this object is deleted. - * This implementation calls to the class description. - */ - public boolean ownsDestinationObjectsForRelationshipKey(String aKey) - { - return classDescription().ownsDestinationObjectsForRelationshipKey( aKey ); - } - - //void prepareValuesForClient() - - /** - * Called to perform the delete propagation for this object - * on the specified editing context. All relationships - * should be processed according to their corresponding - * delete rule. - * This implementation calls to the class description. - */ - public void propagateDeleteWithEditingContext(EOEditingContext aContext) - { - classDescription().propagateDeleteForObject( this, aContext ); - } - - /** - * Applies the changes from the specified snapshot to - * this object. - * @see #changesFromSnapshot(NSDictionary) - */ - public void reapplyChangesFromDictionary(NSDictionary aDeltaSnapshot) - { - throw new WotonomyException( "Not implemented yet." ); - } - - /** - * Returns a snapshot of the current state of this object. - * All property keys are mapped to their values; nulls are - * represented by NSNull. - */ - public NSDictionary snapshot() - { - throw new WotonomyException( "Not implemented yet." ); - } - - /** - * Returns a List of the to-many relationship keys - * for this object. - * This implementation calls to the class description. - */ - public NSArray toManyRelationshipKeys() - { - return classDescription().toManyRelationshipKeys(); - } - - /** - * Returns a List of the to-one relationship keys - * for this object. - * This implementation calls to the class description. - */ - public NSArray toOneRelationshipKeys() - { - return classDescription().toOneRelationshipKeys(); - } - - /** - * Applies the specified snapshot to this object, - * converting NSNulls to null and calling - * takeStoredValueForKey for each key in the Map. - */ - public void updateFromSnapshot(NSDictionary aSnapshot) - { - throw new WotonomyException( "Not implemented yet." ); - } - - /** - * Returns a short, stateful string representation - * of this object. - * This implementation calls to the class description. - */ - public String userPresentableDescription() - { - return classDescription().userPresentableDescriptionForObject( this ); - } - - /** - * This method should be called by each setter method - * on this object before changes are made to the - * object's internal state. This implementation calls - * EOObserverCenter.notifyObserversObjectWillChange( this ), - */ - public void willChange() - { - EOObserverCenter.notifyObserversObjectWillChange( this ); - } - - // interface EOKeyValueCoding - - /** - * Returns the value for the specified property. - * If the property does not exist, this method should - * call handleQueryWithUnboundKey. - */ - public Object valueForKey( String aKey ) - { - return EOKeyValueCodingSupport.valueForKey( this, aKey ); - } - - /** - * Sets the property to the specified value. - * If the property does not exist, this method should - * call handleTakeValueForUnboundKey. - * If the property is of a type that cannot allow - * null (e.g. primitive types) and aValue is null, - * this method should call unableToSetNullForKey. - */ - public void takeValueForKey( Object aValue, String aKey ) - { - EOKeyValueCodingSupport.takeValueForKey( this, aValue, aKey ); - } - - /** - * Returns the value for the private field that - * corresponds to the specified property. - */ - public Object storedValueForKey( String aKey ) - { - return EOKeyValueCodingSupport.storedValueForKey( this, aKey ); - } - - /** - * Sets the the private field that corresponds to the - * specified property to the specified value. - */ - public void takeStoredValueForKey( Object aValue, String aKey ) - { - EOKeyValueCodingSupport.takeStoredValueForKey( this, aValue, aKey ); - } - - /** - * Called by valueForKey when the specified key is - * not found on this object. Implementing classes - * should handle the specified value or otherwise - * throw an exception. - */ - public Object handleQueryWithUnboundKey( String aKey ) - { - return EOKeyValueCodingSupport.handleQueryWithUnboundKey( this, aKey ); - } - - /** - * Called by takeValueForKey when the specified key - * is not found on this object. Implementing classes - * should handle the specified value or otherwise - * throw an exception. - */ - public void handleTakeValueForUnboundKey( Object aValue, String aKey ) - { - EOKeyValueCodingSupport.handleTakeValueForUnboundKey( this, aValue, aKey ); - } - - /** - * Called by takeValueForKey when the type of the - * specified key is not allowed to be null, as is - * the case with primitive types. Implementing - * classes should handle this case appropriately - * or otherwise throw an exception. - */ - public void unableToSetNullForKey( String aKey ) - { - EOKeyValueCodingSupport.unableToSetNullForKey( this, aKey ); - } - - // interface EOKeyValueCodingAdditions - - /** - * Returns the value for the specified key path, which is - * a series of keys delimited by ".", for example: - * "createTime.year.length". - */ - public Object valueForKeyPath( String aKeyPath ) - { - throw new WotonomyException( "Not implemented yet." ); - } - - /** - * Sets the value for the specified key path, which is - * a series of keys delimited by ".", for example: - * "createTime.year.length". - * The value is set for the last object referenced by - * the key path. - */ - public void takeValueForKeyPath( Object aValue, String aKeyPath ) - { - throw new WotonomyException( "Not implemented yet." ); - } - - /** - * Returns a Map of the specified keys to their values, - * each of which might be obtained by calling valueForKey. - */ - public NSDictionary valuesForKeys( List aKeyList ) - { - return KeyValueCodingUtilities.valuesForKeys( this, aKeyList ); - } - - /** - * Takes the keys from the specified map as properties - * and applies the corresponding values, each of which - * might be set by calling takeValueForKey. - */ - public void takeValuesFromDictionary( Map aMap ) - { - KeyValueCodingUtilities.takeValuesFromDictionary( this, aMap ); - } - - // interface EOFaulting - - /** - * Called by EOFaultHandler to prepare the object to be turned into a fault. - */ - public void clearFault() - { - throw new WotonomyException( "Not implemented yet." ); - } - - /** - * Returns this object's EOFaultHandler. - */ - public EOFaultHandler faultHandler() - { - throw new WotonomyException( "Not implemented yet." ); - } - - /** - * Returns whether this object is currently a fault. - * Returns true if this object has not yet retrieved any values. - */ - public boolean isFault() - { - throw new WotonomyException( "Not implemented yet." ); - } - - /** - * Turns this object into a fault using the specified fault handler. - */ - public void turnIntoFault( EOFaultHandler aFaultHandler ) - { - throw new WotonomyException( "Not implemented yet." ); - } - - /** - * Called to completely fire the fault, reading all attributes. - * This method may be implemented to call willRead(null). - */ - public void willRead() - { - throw new WotonomyException( "Not implemented yet." ); - } - - /** - * Called to fire the fault for the specified key. - * The fault manager is required to populate the specified key - * with a value, and may populate any or all of the other values - * on this object. A null key will populate all values on the object. - * NOTE: This method is not part of the specification. - */ - public void willRead( String aKey ) - { - throw new WotonomyException( "Not implemented yet." ); - } - - // interface EODeferredFaulting - - /** - * Returns a fault for the specified deferred fault. - */ - public Object willReadRelationship( Object anObject ) - { - throw new WotonomyException( "Not implemented yet." ); - } - - // interface EORelationshipManipulation - - /** - * Adds the specified object to the relationship on this - * object specified by the key. For to-one relationships, - * this operation is the same as valueForKey. - */ - public void addObjectToPropertyWithKey( - Object anObject, String aKey ) - { - throw new WotonomyException( "Not implemented yet." ); - } - - /** - * Removes the specified object from the relationship on - * this object specified by the key. For to-one relationships, - * this operation is the same as takeValueForKey with a null - * value. - */ - public void removeObjectFromPropertyWithKey( - Object anObject, String aKey ) - { - throw new WotonomyException( "Not implemented yet." ); - } - - /** - * As addObjectToProperty with key, but also performs the - * reciprocal operation on the other side of the relationship. - */ - public void addObjectToBothSidesOfRelationshipWithKey( - EORelationshipManipulation anObject, String aKey ) - { - throw new WotonomyException( "Not implemented yet." ); - } - - /** - * As removeObjectFromPropertyWithKey with key, but also performs the - * reciprocal operation on the other side of the relationship. - */ - public void removeObjectFromBothSidesOfRelationshipWithKey( - EORelationshipManipulation anObject, String aKey ) - { - throw new WotonomyException( "Not implemented yet." ); - } - - // interface EOValidation - - /** - * Validates this object for delete. - * Throws an exception if this object cannot be deleted. - * This implementation calls to the class description. - */ - public void validateForDelete() - { - classDescription().validateObjectForDelete( this ); - } - - /** - * Validates this object for insertion into the external store. - * Throws an exception if this object cannot be inserted. - * Validations here should be specific to insertion. - * This implementation calls validateForSave(). - */ - public void validateForInsert() - { - validateForSave(); - } - - /** - * Validates this object for a commit to the external store. - * Throws an exception if this object cannot be committed. - * Validations here are not specific to either inserts or updates. - * This implementation calls to the class description. - */ - public void validateForSave() - { - classDescription().validateObjectForSave( this ); - } - - /** - * Validates this object for update to the external store. - * Throws an exception if this object cannot be updated. - * Validations here should be specific to updates. - * This implementation calls validateForSave(). - */ - public void validateForUpdate() - { - validateForSave(); - } + * EOCustomObject implements all the necessary interfaces to receive first-class + * treatment from the control framework. The implementation delegates as much + * class meta-behavior as possible to EOClassDescription, letting subclasses + * focus exclusively on business logic while still allowing them to customize as + * much class behavior as needed. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public class EOCustomObject implements EOEnterpriseObject, EOKeyValueCodingAdditions, EODeferredFaulting, + EORelationshipManipulation, EOValidation { + private transient static EOClassDescription classDescription; + private transient EOEditingContext editingContext; + + // static configuration + + /** + * Specifies whether the implementation of EOKeyValueCoding is permitted to + * access field directly. This implementation returns true; subclasses may + * override to customize this behavior. + */ + public static boolean canAccessFieldsDirectly() { + return true; + } + + /** + * Specifies whether the implementation of EOKeyValueCoding is permitted to + * access private accessors. This implementation returns true; subclasses may + * override to customize this behavior. + */ + public static boolean shouldUseStoredAccessors() { + return true; + } + + /** + * Specifies whether deferred faults should be used. This implementation returns + * false; subclasses may override to customize this behavior. + */ + public static boolean usesDeferredFaultCreation() { + return false; + } + + // constructors + + /** + * Default constructor initializes private state. EditingContext and + * ClassDescription are set to null. + */ + public EOCustomObject() { + editingContext = null; + classDescription = null; + } + + /** + * Preferred constructor, specifying an editing context, a class description, + * and a global id, any or all of which may be null. Subclasses should invoke + * this constructor. + */ + public EOCustomObject(EOEditingContext aContext, EOClassDescription aClassDescription, EOGlobalID aGlobalID) { + editingContext = aContext; + classDescription = aClassDescription; + } + + // interface EOEnterpriseObject + + /** + * Returns a List of all property keys defined on this object. This includes + * both attributes and relationships. This implementation returns the union of + * attributeKeys, toOneRelationshipKeys, and toManyRelationshipKeys. + */ + public NSArray allPropertyKeys() { + NSSet union = new NSSet(); + union.addAll(attributeKeys()); + union.addAll(toOneRelationshipKeys()); + union.addAll(toManyRelationshipKeys()); + return new NSArray((Collection) union); + } + + /** + * Returns a list of all attributes defined on this object. Attributes are all + * properties that are not relationships. This implementation retrieves the keys + * from the class description. + */ + public NSArray attributeKeys() { + return classDescription().attributeKeys(); + } + + // void awakeFromClientUpdate(EOEditingContext aContext) + + /** + * Called when the object has first been fetched into the specified editing + * context. This implementation calls awakeObjectFromFetch on the class + * description. + */ + public void awakeFromFetch(EOEditingContext anEditingContext) { + classDescription().awakeObjectFromFetch(this, anEditingContext); + } + + /** + * Called when the object has been inserted into the specified editing context. + * This implementation calls awakeObjectFromInsertion on the class description. + */ + public void awakeFromInsertion(EOEditingContext anEditingContext) { + classDescription().awakeObjectFromInsertion(this, anEditingContext); + } + + /** + * Returns a Map representing the delta of the current state from the state + * represented in the specified snapshot. The result will contain only the keys + * that have changed and their values. Relationship keys will map to an NSArray + * that contains an NSArray of added objects and an NSArray of removed objects, + * in that order. + */ + public NSDictionary changesFromSnapshot(NSDictionary snapshot) { + throw new WotonomyException("Not implemented yet."); + } + + /** + * Returns a class description for this object. Calls + * EOClassDescription.classDescriptionForClass. + */ + public EOClassDescription classDescription() { + if (classDescription == null) { + classDescription = EOClassDescription.classDescriptionForClass(getClass()); + if (classDescription == null) { + throw new WotonomyException("No class description found for class: " + getClass()); + } + } + return classDescription; + } + + /** + * Returns a class description for the object at the other end of the specified + * relationship key. This implementation calls to the classDescription. + */ + public EOClassDescription classDescriptionForDestinationKey(String aKey) { + return classDescription().classDescriptionForDestinationKey(aKey); + } + + /** + * Clears all property values for this object. This method is called to clean-up + * an object that will no longer be used, and implementations should ensure that + * all references are set to null to prevent problems with garbage-collection. + */ + public void clearProperties() { + // FIXME: clear properties here + } + + /** + * Returns the delete rule constant defined on EOClassDescription for the + * relationship defined by the specified key. This implementation calls to the + * classDescription. + */ + public int deleteRuleForRelationshipKey(String aRelationshipKey) { + return classDescription().deleteRuleForRelationshipKey(aRelationshipKey); + } + + /** + * Returns the editing context in which this object is registered. + */ + public EOEditingContext editingContext() { + return editingContext; + } + + /** + * Returns the name of the entity that this object represents. + */ + public String entityName() { + return classDescription().entityName(); + } + + /** + * Returns a String containing all property keys and values for this object. + * Relationships should be represented by calling eoShallowDescription() on the + * object. + */ + public String eoDescription() { + throw new WotonomyException("Not implemented yet."); + } + + /** + * Returns a String containing all attribute keys and values for this object. + * Relationships are not included. + */ + public String eoShallowDescription() { + throw new WotonomyException("Not implemented yet."); + } + + /** + * Returns the key used to reference this object on the object at the other end + * of the specified relationship. This implementation calls to the class + * description. + */ + public String inverseForRelationshipKey(String aRelationshipKey) { + return classDescription().inverseForRelationshipKey(aRelationshipKey); + } + + // Object invokeRemoteMethod( + // String aMethodName, Class[] aTypeArray Object[] anArgumentArray) + + /** + * Returns whether the specified relationship key represents a to-many + * relationship. + */ + public boolean isToManyKey(String aKey) { + return toManyRelationshipKeys().containsObject(aKey); + } + + /** + * Returns whether the objects at the other end of the specified relationship + * should be deleted when this object is deleted. This implementation calls to + * the class description. + */ + public boolean ownsDestinationObjectsForRelationshipKey(String aKey) { + return classDescription().ownsDestinationObjectsForRelationshipKey(aKey); + } + + // void prepareValuesForClient() + + /** + * Called to perform the delete propagation for this object on the specified + * editing context. All relationships should be processed according to their + * corresponding delete rule. This implementation calls to the class + * description. + */ + public void propagateDeleteWithEditingContext(EOEditingContext aContext) { + classDescription().propagateDeleteForObject(this, aContext); + } + + /** + * Applies the changes from the specified snapshot to this object. + * + * @see #changesFromSnapshot(NSDictionary) + */ + public void reapplyChangesFromDictionary(NSDictionary aDeltaSnapshot) { + throw new WotonomyException("Not implemented yet."); + } + + /** + * Returns a snapshot of the current state of this object. All property keys are + * mapped to their values; nulls are represented by NSNull. + */ + public NSDictionary snapshot() { + throw new WotonomyException("Not implemented yet."); + } + + /** + * Returns a List of the to-many relationship keys for this object. This + * implementation calls to the class description. + */ + public NSArray toManyRelationshipKeys() { + return classDescription().toManyRelationshipKeys(); + } + + /** + * Returns a List of the to-one relationship keys for this object. This + * implementation calls to the class description. + */ + public NSArray toOneRelationshipKeys() { + return classDescription().toOneRelationshipKeys(); + } + + /** + * Applies the specified snapshot to this object, converting NSNulls to null and + * calling takeStoredValueForKey for each key in the Map. + */ + public void updateFromSnapshot(NSDictionary aSnapshot) { + throw new WotonomyException("Not implemented yet."); + } + + /** + * Returns a short, stateful string representation of this object. This + * implementation calls to the class description. + */ + public String userPresentableDescription() { + return classDescription().userPresentableDescriptionForObject(this); + } + + /** + * This method should be called by each setter method on this object before + * changes are made to the object's internal state. This implementation calls + * EOObserverCenter.notifyObserversObjectWillChange( this ), + */ + public void willChange() { + EOObserverCenter.notifyObserversObjectWillChange(this); + } + + // interface EOKeyValueCoding + + /** + * Returns the value for the specified property. If the property does not exist, + * this method should call handleQueryWithUnboundKey. + */ + public Object valueForKey(String aKey) { + return EOKeyValueCodingSupport.valueForKey(this, aKey); + } + + /** + * Sets the property to the specified value. If the property does not exist, + * this method should call handleTakeValueForUnboundKey. If the property is of a + * type that cannot allow null (e.g. primitive types) and aValue is null, this + * method should call unableToSetNullForKey. + */ + public void takeValueForKey(Object aValue, String aKey) { + EOKeyValueCodingSupport.takeValueForKey(this, aValue, aKey); + } + + /** + * Returns the value for the private field that corresponds to the specified + * property. + */ + public Object storedValueForKey(String aKey) { + return EOKeyValueCodingSupport.storedValueForKey(this, aKey); + } + + /** + * Sets the the private field that corresponds to the specified property to the + * specified value. + */ + public void takeStoredValueForKey(Object aValue, String aKey) { + EOKeyValueCodingSupport.takeStoredValueForKey(this, aValue, aKey); + } + + /** + * Called by valueForKey when the specified key is not found on this object. + * Implementing classes should handle the specified value or otherwise throw an + * exception. + */ + public Object handleQueryWithUnboundKey(String aKey) { + return EOKeyValueCodingSupport.handleQueryWithUnboundKey(this, aKey); + } + + /** + * Called by takeValueForKey when the specified key is not found on this object. + * Implementing classes should handle the specified value or otherwise throw an + * exception. + */ + public void handleTakeValueForUnboundKey(Object aValue, String aKey) { + EOKeyValueCodingSupport.handleTakeValueForUnboundKey(this, aValue, aKey); + } + + /** + * Called by takeValueForKey when the type of the specified key is not allowed + * to be null, as is the case with primitive types. Implementing classes should + * handle this case appropriately or otherwise throw an exception. + */ + public void unableToSetNullForKey(String aKey) { + EOKeyValueCodingSupport.unableToSetNullForKey(this, aKey); + } + + // interface EOKeyValueCodingAdditions + + /** + * Returns the value for the specified key path, which is a series of keys + * delimited by ".", for example: "createTime.year.length". + */ + public Object valueForKeyPath(String aKeyPath) { + throw new WotonomyException("Not implemented yet."); + } + + /** + * Sets the value for the specified key path, which is a series of keys + * delimited by ".", for example: "createTime.year.length". The value is set for + * the last object referenced by the key path. + */ + public void takeValueForKeyPath(Object aValue, String aKeyPath) { + throw new WotonomyException("Not implemented yet."); + } + + /** + * Returns a Map of the specified keys to their values, each of which might be + * obtained by calling valueForKey. + */ + public NSDictionary valuesForKeys(List aKeyList) { + return KeyValueCodingUtilities.valuesForKeys(this, aKeyList); + } + + /** + * Takes the keys from the specified map as properties and applies the + * corresponding values, each of which might be set by calling takeValueForKey. + */ + public void takeValuesFromDictionary(Map aMap) { + KeyValueCodingUtilities.takeValuesFromDictionary(this, aMap); + } + + // interface EOFaulting + + /** + * Called by EOFaultHandler to prepare the object to be turned into a fault. + */ + public void clearFault() { + throw new WotonomyException("Not implemented yet."); + } + + /** + * Returns this object's EOFaultHandler. + */ + public EOFaultHandler faultHandler() { + throw new WotonomyException("Not implemented yet."); + } + + /** + * Returns whether this object is currently a fault. Returns true if this object + * has not yet retrieved any values. + */ + public boolean isFault() { + throw new WotonomyException("Not implemented yet."); + } + + /** + * Turns this object into a fault using the specified fault handler. + */ + public void turnIntoFault(EOFaultHandler aFaultHandler) { + throw new WotonomyException("Not implemented yet."); + } + + /** + * Called to completely fire the fault, reading all attributes. This method may + * be implemented to call willRead(null). + */ + public void willRead() { + throw new WotonomyException("Not implemented yet."); + } + + /** + * Called to fire the fault for the specified key. The fault manager is required + * to populate the specified key with a value, and may populate any or all of + * the other values on this object. A null key will populate all values on the + * object. NOTE: This method is not part of the specification. + */ + public void willRead(String aKey) { + throw new WotonomyException("Not implemented yet."); + } + + // interface EODeferredFaulting + + /** + * Returns a fault for the specified deferred fault. + */ + public Object willReadRelationship(Object anObject) { + throw new WotonomyException("Not implemented yet."); + } + + // interface EORelationshipManipulation + + /** + * Adds the specified object to the relationship on this object specified by the + * key. For to-one relationships, this operation is the same as valueForKey. + */ + public void addObjectToPropertyWithKey(Object anObject, String aKey) { + throw new WotonomyException("Not implemented yet."); + } + + /** + * Removes the specified object from the relationship on this object specified + * by the key. For to-one relationships, this operation is the same as + * takeValueForKey with a null value. + */ + public void removeObjectFromPropertyWithKey(Object anObject, String aKey) { + throw new WotonomyException("Not implemented yet."); + } + + /** + * As addObjectToProperty with key, but also performs the reciprocal operation + * on the other side of the relationship. + */ + public void addObjectToBothSidesOfRelationshipWithKey(EORelationshipManipulation anObject, String aKey) { + throw new WotonomyException("Not implemented yet."); + } + + /** + * As removeObjectFromPropertyWithKey with key, but also performs the reciprocal + * operation on the other side of the relationship. + */ + public void removeObjectFromBothSidesOfRelationshipWithKey(EORelationshipManipulation anObject, String aKey) { + throw new WotonomyException("Not implemented yet."); + } + + // interface EOValidation + + /** + * Validates this object for delete. Throws an exception if this object cannot + * be deleted. This implementation calls to the class description. + */ + public void validateForDelete() { + classDescription().validateObjectForDelete(this); + } + + /** + * Validates this object for insertion into the external store. Throws an + * exception if this object cannot be inserted. Validations here should be + * specific to insertion. This implementation calls validateForSave(). + */ + public void validateForInsert() { + validateForSave(); + } + + /** + * Validates this object for a commit to the external store. Throws an exception + * if this object cannot be committed. Validations here are not specific to + * either inserts or updates. This implementation calls to the class + * description. + */ + public void validateForSave() { + classDescription().validateObjectForSave(this); + } + + /** + * Validates this object for update to the external store. Throws an exception + * if this object cannot be updated. Validations here should be specific to + * updates. This implementation calls validateForSave(). + */ + public void validateForUpdate() { + validateForSave(); + } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.3 2001/12/06 16:42:29 mpowers - * Added appropriate constructor. + * Revision 1.3 2001/12/06 16:42:29 mpowers Added appropriate constructor. * - * Revision 1.2 2001/11/24 17:37:29 mpowers - * Implemented static methods. + * Revision 1.2 2001/11/24 17:37:29 mpowers Implemented static methods. * - * Revision 1.1 2001/11/17 17:18:15 mpowers - * Initial implementation of EOCustomObject. + * Revision 1.1 2001/11/17 17:18:15 mpowers Initial implementation of + * EOCustomObject. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODataSource.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODataSource.java index c7e5284..9d3c255 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODataSource.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODataSource.java @@ -21,144 +21,122 @@ package net.wotonomy.control; import net.wotonomy.foundation.NSArray; /** -* EODataSource is used by EODisplayGroup.fetch() to retrieve -* a list of objects to display. When a display group has a -* data source, the display group will use the data source to -* populate the object list and to create new objects to be -* displayed in the list, and will update the data source when -* objects are inserted or removed from the list.

-* -* In certain cases, as when a display group needs to populate -* a child display group to show a one-to-many relationship, -* the display group will call dataSourceQualifiedByKey to -* return a new data source that can vend objects associated -* with the specified key and then call qualifyWithRelationshipKey -* to specify the object and key that are the source of the -* child relationship.

-* -* Concrete subclasses are expected to override fetch() and -* are required to override insertObject and removeObject. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public abstract class EODataSource -{ - /** - * Creates a new object. You should call - * insertObject() to insert the new object into - * this data source. - * This implementation attempts to create a new - * instance of the class returned by - * classDescriptionForObjects(). - * Override to return an object specific to - * your implementation. - * @return The newly created object, or null if - * new objects are not supported by this data source. - * @see #classDescriptionForObjects - */ - public Object createObject () - { - Object result = null; - EOClassDescription c = classDescriptionForObjects(); - if ( c != null ) - { - result = c.createInstanceWithEditingContext( editingContext(), null ); - } - return result; - } - - /** - * Inserts the specified object into this data source. - */ - public abstract void insertObject ( Object anObject ); - - /** - * Deletes the specified object from this data source. - */ - public abstract void deleteObject ( Object anObject ); - - /** - * Returns the editing context for this data source, - * or null if no editing context is used. - * This implementation returns null. - */ - public EOEditingContext editingContext () - { - return null; - } - - /** - * Returns a List containing the objects in this - * data source. This implementation returns null. - */ - public NSArray fetchObjects () - { - return null; - } - - /** - * Returns a data source that is capable of - * manipulating objects of the type returned by - * applying the specified key to objects - * vended by this data source. - * @see #qualifyWithRelationshipKey - */ - public abstract EODataSource - dataSourceQualifiedByKey ( String aKey ); - - /** - * Restricts this data source to vend those - * objects that are associated with the specified - * key on the specified object. - */ - public abstract void - qualifyWithRelationshipKey ( - String aKey, Object anObject ); - - /** - * Returns the description of the class of the - * objects that is vended by this data source, - * or null if this cannot be determined. - * This implementation returns null. - */ - public EOClassDescription - classDescriptionForObjects () - { - return null; - } + * EODataSource is used by EODisplayGroup.fetch() to retrieve a list of objects + * to display. When a display group has a data source, the display group will + * use the data source to populate the object list and to create new objects to + * be displayed in the list, and will update the data source when objects are + * inserted or removed from the list.
+ *
+ * + * In certain cases, as when a display group needs to populate a child display + * group to show a one-to-many relationship, the display group will call + * dataSourceQualifiedByKey to return a new data source that can vend objects + * associated with the specified key and then call qualifyWithRelationshipKey to + * specify the object and key that are the source of the child relationship. + *
+ *
+ * + * Concrete subclasses are expected to override fetch() and are required to + * override insertObject and removeObject. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public abstract class EODataSource { + /** + * Creates a new object. You should call insertObject() to insert the new object + * into this data source. This implementation attempts to create a new instance + * of the class returned by classDescriptionForObjects(). Override to return an + * object specific to your implementation. + * + * @return The newly created object, or null if new objects are not supported by + * this data source. + * @see #classDescriptionForObjects + */ + public Object createObject() { + Object result = null; + EOClassDescription c = classDescriptionForObjects(); + if (c != null) { + result = c.createInstanceWithEditingContext(editingContext(), null); + } + return result; + } + + /** + * Inserts the specified object into this data source. + */ + public abstract void insertObject(Object anObject); + + /** + * Deletes the specified object from this data source. + */ + public abstract void deleteObject(Object anObject); + + /** + * Returns the editing context for this data source, or null if no editing + * context is used. This implementation returns null. + */ + public EOEditingContext editingContext() { + return null; + } + + /** + * Returns a List containing the objects in this data source. This + * implementation returns null. + */ + public NSArray fetchObjects() { + return null; + } + + /** + * Returns a data source that is capable of manipulating objects of the type + * returned by applying the specified key to objects vended by this data source. + * + * @see #qualifyWithRelationshipKey + */ + public abstract EODataSource dataSourceQualifiedByKey(String aKey); + + /** + * Restricts this data source to vend those objects that are associated with the + * specified key on the specified object. + */ + public abstract void qualifyWithRelationshipKey(String aKey, Object anObject); + + /** + * Returns the description of the class of the objects that is vended by this + * data source, or null if this cannot be determined. This implementation + * returns null. + */ + public EOClassDescription classDescriptionForObjects() { + return null; + } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.5 2001/05/21 14:02:44 mpowers - * Corrected javadoc. + * Revision 1.5 2001/05/21 14:02:44 mpowers Corrected javadoc. * - * Revision 1.4 2001/04/27 23:37:20 mpowers - * Now using EOClassDescription in the EODataSource class, as we should. + * Revision 1.4 2001/04/27 23:37:20 mpowers Now using EOClassDescription in the + * EODataSource class, as we should. * - * Revision 1.3 2001/02/27 23:11:07 mpowers - * Removed object registration from createObject(). + * Revision 1.3 2001/02/27 23:11:07 mpowers Removed object registration from + * createObject(). * - * Revision 1.2 2001/02/16 18:34:19 mpowers - * Implementing nested contexts. + * Revision 1.2 2001/02/16 18:34:19 mpowers Implementing nested contexts. * - * Revision 1.1.1.1 2000/12/21 15:46:38 mpowers - * Contributing wotonomy. + * Revision 1.1.1.1 2000/12/21 15:46:38 mpowers Contributing wotonomy. * - * Revision 1.3 2000/12/20 16:25:34 michael - * Added log to all files. + * Revision 1.3 2000/12/20 16:25:34 michael Added log to all files. * * */ - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODatabaseDataSource.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODatabaseDataSource.java index 2e350f1..489d779 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODatabaseDataSource.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODatabaseDataSource.java @@ -28,312 +28,267 @@ import net.wotonomy.foundation.NSSet; import net.wotonomy.foundation.internal.WotonomyException; /** -* EODatabaseSource is a general-purpose implementation -* of EODataSource that is EOClassDescription-aware and -* that can vend appropriate EODetailDataSources. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public abstract class EODatabaseDataSource -{ - EOQualifier auxiliaryQualifier; - EOEditingContext editingContext; - String entityName; - String fetchSpecificationName; - EOFetchSpecification fetchSpecification; - NSDictionary qualifierBindings; - EOClassDescription classDescription; - boolean fetchEnabled; - - /** - * Constructs a data source that fetches all objects of - * the specified entity type. - */ - public EODatabaseDataSource( - EOEditingContext aContext, String anEntityName) - { - this( aContext, anEntityName, null ); - } - - /** - * Constructs a data source that fetches objects of the - * specified entity type according to the fetch specification - * with the specified name. - */ - public EODatabaseDataSource( - EOEditingContext aContext, String anEntityName, String aFetchSpecName) - { - fetchEnabled = true; - editingContext = aContext; - entityName = anEntityName; - setFetchSpecificationByName( fetchSpecificationName ); - } - - /** - * Returns the qualifier that is applied to the results fetched by the fetch - * specification before objects are returned by fetch objects, or null if no - * such qualifier has been specified. - */ - public EOQualifier auxiliaryQualifier() - { - return auxiliaryQualifier; - } - - /** - * Returns the description of the class of the - * objects that is vended by this data source, - * or null if no entity name is specified. - */ - public EOClassDescription classDescriptionForObjects () - { - if ( entityName == null ) return null; - return EOClassDescription.classDescriptionForEntityName( entityName ); - } - - /** - * Returns the object store at the root of the - * editing context's editing hierarchy. - */ - public EOObjectStore databaseContext() - { - EOObjectStore store = editingContext(); - while ( store instanceof EOEditingContext ) - { - store = ((EOEditingContext)store).parentObjectStore(); - } - return store; - } - - /** - * Returns a detail data source that is capable of - * manipulating objects of the type returned by - * applying the specified key to objects - * vended by this data source. - * @see #qualifyWithRelationshipKey - */ - public EODataSource dataSourceQualifiedByKey ( String aKey ) - { - throw new WotonomyException( "Not implemented yet." ); - } - - /** - * Deletes the specified object from this data source. - * This implementation deletes the specified object from - * the editing context. - */ - public void deleteObject ( Object anObject ) - { - editingContext.deleteObject( anObject ); - } - - /** - * Returns the editing context for this data source, - * or null if no editing context was specified. - */ - public EOEditingContext editingContext () - { - return editingContext; - } + * EODatabaseSource is a general-purpose implementation of EODataSource that is + * EOClassDescription-aware and that can vend appropriate EODetailDataSources. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public abstract class EODatabaseDataSource { + EOQualifier auxiliaryQualifier; + EOEditingContext editingContext; + String entityName; + String fetchSpecificationName; + EOFetchSpecification fetchSpecification; + NSDictionary qualifierBindings; + EOClassDescription classDescription; + boolean fetchEnabled; -/* - public EOEntity entity() {} -*/ + /** + * Constructs a data source that fetches all objects of the specified entity + * type. + */ + public EODatabaseDataSource(EOEditingContext aContext, String anEntityName) { + this(aContext, anEntityName, null); + } + + /** + * Constructs a data source that fetches objects of the specified entity type + * according to the fetch specification with the specified name. + */ + public EODatabaseDataSource(EOEditingContext aContext, String anEntityName, String aFetchSpecName) { + fetchEnabled = true; + editingContext = aContext; + entityName = anEntityName; + setFetchSpecificationByName(fetchSpecificationName); + } + + /** + * Returns the qualifier that is applied to the results fetched by the fetch + * specification before objects are returned by fetch objects, or null if no + * such qualifier has been specified. + */ + public EOQualifier auxiliaryQualifier() { + return auxiliaryQualifier; + } + + /** + * Returns the description of the class of the objects that is vended by this + * data source, or null if no entity name is specified. + */ + public EOClassDescription classDescriptionForObjects() { + if (entityName == null) + return null; + return EOClassDescription.classDescriptionForEntityName(entityName); + } + + /** + * Returns the object store at the root of the editing context's editing + * hierarchy. + */ + public EOObjectStore databaseContext() { + EOObjectStore store = editingContext(); + while (store instanceof EOEditingContext) { + store = ((EOEditingContext) store).parentObjectStore(); + } + return store; + } + + /** + * Returns a detail data source that is capable of manipulating objects of the + * type returned by applying the specified key to objects vended by this data + * source. + * + * @see #qualifyWithRelationshipKey + */ + public EODataSource dataSourceQualifiedByKey(String aKey) { + throw new WotonomyException("Not implemented yet."); + } + + /** + * Deletes the specified object from this data source. This implementation + * deletes the specified object from the editing context. + */ + public void deleteObject(Object anObject) { + editingContext.deleteObject(anObject); + } + + /** + * Returns the editing context for this data source, or null if no editing + * context was specified. + */ + public EOEditingContext editingContext() { + return editingContext; + } + + /* + * public EOEntity entity() {} + */ + + /** + * Returns a List containing the objects of the current entity type that conform + * to the specified fetch specification. If an auxiliary qualifier has been + * specified, that qualifier is applied to the objects before returning the + * result. If fetch is not enabled, this method returns null. + */ + public NSArray fetchObjects() { + if (!isFetchEnabled()) + return null; + NSArray result = editingContext.objectsWithFetchSpecification(fetchSpecification()); + if (auxiliaryQualifier() != null) { + result = EOQualifier.filteredArrayWithQualifier(result, auxiliaryQualifier()); + } + return result; + } - /** - * Returns a List containing the objects of the current - * entity type that conform to the specified fetch specification. - * If an auxiliary qualifier has been specified, that qualifier - * is applied to the objects before returning the result. - * If fetch is not enabled, this method returns null. - */ - public NSArray fetchObjects () - { - if ( ! isFetchEnabled() ) return null; - NSArray result = - editingContext.objectsWithFetchSpecification( fetchSpecification() ); - if ( auxiliaryQualifier() != null ) - { - result = EOQualifier.filteredArrayWithQualifier( result, auxiliaryQualifier() ); - } - return result; - } - - /** - * Returns the fetch specification currently used by this data - * source to fetch objects, or null if none is specified. - * If null, this fetchObjects() will return all objects of the - * specified entity type. - */ - public EOFetchSpecification fetchSpecification() - { - return fetchSpecification; - } - - /** - * Returns a copy of the fetch specification that will be used to - * determine fetch for this data source. If this data source has - * an auxiliary qualifier, that qualifier will be inserted into - * the returned fetch specification's qualifier. - */ - public EOFetchSpecification fetchSpecificationForFetch() - { - EOFetchSpecification result = (EOFetchSpecification) fetchSpecification.clone(); - if ( auxiliaryQualifier() != null ) - { - NSMutableArray join = new NSMutableArray(); - join.addObject( fetchSpecification.qualifier() ); - join.addObject( auxiliaryQualifier() ); - result.setQualifier( new EOAndQualifier( join ) ); - } - return result; - } - - /** - * Returns the name of the current fetch specification, or null - * if no name has been specified. - */ - public String fetchSpecificationName() - { - return fetchSpecificationName; - } - - /** - * Inserts the specified object into this data source. - * This implementation registers the object as an inserted - * object with the editing context. - */ - public void insertObject ( Object anObject ) - { - editingContext.insertObject( anObject ); - } - - /** - * Returns whether fetching is currently allowed. - * If false, fetchObjects() will return null. - * Default is true. - */ - public boolean isFetchEnabled() - { - return fetchEnabled; - } - - /** - * Returns a List of the union of the binding keys for the fetch spec's - * qualifier and the auxiliary qualifier. - */ - public NSArray qualifierBindingKeys() - { - NSSet union = new NSSet(); - if ( ( fetchSpecification != null ) - && ( fetchSpecification.qualifier() != null ) ) - { - union.addAll( fetchSpecification.qualifier().bindingKeys() ); - } - if ( auxiliaryQualifier() != null ) - { - union.addAll( auxiliaryQualifier().bindingKeys() ); - } - return new NSArray( (Collection) union ); - } - - /** - * Returns a Map of the bindings that will be applied against - * the fetch spec's qualifier and the auxiliary qualifier, - * or null if no bindings exist. - */ - public NSDictionary qualifierBindings() - { - if ( qualifierBindings == null ) return null; - return new NSDictionary( (Map) qualifierBindings ); - } - - /** - * Restricts this data source to vend those - * objects that are associated with the specified - * key on the specified object. - */ - public void qualifyWithRelationshipKey ( - String aKey, Object anObject ) - { - throw new WotonomyException( "Not implemented yet" ); - } - - /** - * Sets the auxiliary qualifier that will be applied to - * objects returned from the fetch described by the fetch specification. - */ - public void setAuxiliaryQualifier(EOQualifier aQualifier) - { - auxiliaryQualifier = aQualifier; - } - - /** - * Sets whether fetches are currently allowed. - * If false, fetchObjects() will return null. - */ - public void setFetchEnabled(boolean isFetchEnabled) - { - fetchEnabled = isFetchEnabled; - } - - /** - * Sets the fetch specification used by this data source. - * If null, all objects of the specified entity type will - * be returned by fetchObjects(). - */ - public void setFetchSpecification( EOFetchSpecification aFetchSpec) - { - fetchSpecificationName = null; - fetchSpecification = aFetchSpec; - } - - /** - * Sets the fetch specification used by this data source, - * requesting it from the class description for this data source's - * entity class description, if any. If the name cannot be resolved, - * the fetch specification will be set to null. - */ - public void setFetchSpecificationByName(String aName) - { - fetchSpecificationName = aName; - fetchSpecification = EOFetchSpecification.fetchSpecificationNamed( aName, entityName ); - } - - /* - public void setParentDataSourceRelationshipKey( EODataSource aDataSource, String aKey) - */ - - /** - * Sets the bindings to be applied to the fetch specification and the auxiliary qualifier. - */ - public void setQualifierBindings(Map aBindingMap) - { - if ( aBindingMap == null ) - { - qualifierBindings = null; - } - else - { - qualifierBindings = new NSDictionary( (Map) aBindingMap ); - } - } + /** + * Returns the fetch specification currently used by this data source to fetch + * objects, or null if none is specified. If null, this fetchObjects() will + * return all objects of the specified entity type. + */ + public EOFetchSpecification fetchSpecification() { + return fetchSpecification; + } + + /** + * Returns a copy of the fetch specification that will be used to determine + * fetch for this data source. If this data source has an auxiliary qualifier, + * that qualifier will be inserted into the returned fetch specification's + * qualifier. + */ + public EOFetchSpecification fetchSpecificationForFetch() { + EOFetchSpecification result = (EOFetchSpecification) fetchSpecification.clone(); + if (auxiliaryQualifier() != null) { + NSMutableArray join = new NSMutableArray(); + join.addObject(fetchSpecification.qualifier()); + join.addObject(auxiliaryQualifier()); + result.setQualifier(new EOAndQualifier(join)); + } + return result; + } + + /** + * Returns the name of the current fetch specification, or null if no name has + * been specified. + */ + public String fetchSpecificationName() { + return fetchSpecificationName; + } + + /** + * Inserts the specified object into this data source. This implementation + * registers the object as an inserted object with the editing context. + */ + public void insertObject(Object anObject) { + editingContext.insertObject(anObject); + } + + /** + * Returns whether fetching is currently allowed. If false, fetchObjects() will + * return null. Default is true. + */ + public boolean isFetchEnabled() { + return fetchEnabled; + } + + /** + * Returns a List of the union of the binding keys for the fetch spec's + * qualifier and the auxiliary qualifier. + */ + public NSArray qualifierBindingKeys() { + NSSet union = new NSSet(); + if ((fetchSpecification != null) && (fetchSpecification.qualifier() != null)) { + union.addAll(fetchSpecification.qualifier().bindingKeys()); + } + if (auxiliaryQualifier() != null) { + union.addAll(auxiliaryQualifier().bindingKeys()); + } + return new NSArray((Collection) union); + } + + /** + * Returns a Map of the bindings that will be applied against the fetch spec's + * qualifier and the auxiliary qualifier, or null if no bindings exist. + */ + public NSDictionary qualifierBindings() { + if (qualifierBindings == null) + return null; + return new NSDictionary((Map) qualifierBindings); + } + + /** + * Restricts this data source to vend those objects that are associated with the + * specified key on the specified object. + */ + public void qualifyWithRelationshipKey(String aKey, Object anObject) { + throw new WotonomyException("Not implemented yet"); + } + + /** + * Sets the auxiliary qualifier that will be applied to objects returned from + * the fetch described by the fetch specification. + */ + public void setAuxiliaryQualifier(EOQualifier aQualifier) { + auxiliaryQualifier = aQualifier; + } + + /** + * Sets whether fetches are currently allowed. If false, fetchObjects() will + * return null. + */ + public void setFetchEnabled(boolean isFetchEnabled) { + fetchEnabled = isFetchEnabled; + } + + /** + * Sets the fetch specification used by this data source. If null, all objects + * of the specified entity type will be returned by fetchObjects(). + */ + public void setFetchSpecification(EOFetchSpecification aFetchSpec) { + fetchSpecificationName = null; + fetchSpecification = aFetchSpec; + } + + /** + * Sets the fetch specification used by this data source, requesting it from the + * class description for this data source's entity class description, if any. If + * the name cannot be resolved, the fetch specification will be set to null. + */ + public void setFetchSpecificationByName(String aName) { + fetchSpecificationName = aName; + fetchSpecification = EOFetchSpecification.fetchSpecificationNamed(aName, entityName); + } + + /* + * public void setParentDataSourceRelationshipKey( EODataSource aDataSource, + * String aKey) + */ + + /** + * Sets the bindings to be applied to the fetch specification and the auxiliary + * qualifier. + */ + public void setQualifierBindings(Map aBindingMap) { + if (aBindingMap == null) { + qualifierBindings = null; + } else { + qualifierBindings = new NSDictionary((Map) aBindingMap); + } + } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.1 2001/11/24 17:38:00 mpowers - * Contributing EODatabaseDataSource. + * Revision 1.1 2001/11/24 17:38:00 mpowers Contributing EODatabaseDataSource. * * */ - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODeferredFaulting.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODeferredFaulting.java index c87a097..6ce9808 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODeferredFaulting.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODeferredFaulting.java @@ -19,30 +19,26 @@ License along with this library; if not, see http://www.gnu.org package net.wotonomy.control; /** -* EODeferredFaulting defines a method -* to handle relationships that are deferred faults. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 893 $ -*/ -public interface EODeferredFaulting extends EOFaulting -{ - /** - * Returns a fault for the specified deferred fault. - */ - Object willReadRelationship( Object anObject ); + * EODeferredFaulting defines a method to handle relationships that are deferred + * faults. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 893 $ + */ +public interface EODeferredFaulting extends EOFaulting { + /** + * Returns a fault for the specified deferred fault. + */ + Object willReadRelationship(Object anObject); } /* - * $Log$ - * Revision 1.1 2006/02/16 13:19:57 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. + * $Log$ Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.1 2001/11/13 04:13:59 mpowers - * Added interfaces needed to begin work on EOCustomObject. + * Revision 1.1 2001/11/13 04:13:59 mpowers Added interfaces needed to begin + * work on EOCustomObject. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODelayedObserver.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODelayedObserver.java index 758fb40..b947a82 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODelayedObserver.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODelayedObserver.java @@ -22,131 +22,108 @@ import java.util.Observable; import java.util.Observer; /** -* This is an abstract class for receiving coalesced -* notifications of changes from objects. -* This class also implements Observer for greater -* compatibility. -* The point of EODelayedObservers is that when -* they receive a willChange message, they -* queue themselves with a EODelayedObserverQueue -* so they can receive a single subjectChanged() -* after all changes from an observed object take -* place. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public abstract class EODelayedObserver - implements EOObserving, Observer -{ - /** - * Notified immediately. - */ - public static final int ObserverPriorityImmediate = 0; - public static final int ObserverPriorityFirst = 1; - public static final int ObserverPrioritySecond = 2; - public static final int ObserverPriorityThird = 3; - public static final int ObserverPriorityFourth = 4; - public static final int ObserverPriorityFifth = 5; - public static final int ObserverPrioritySixth = 6; - public static final int ObserverPriorityLater = 7; - public static final int ObserverNumberOfPriorities = 8; - - /** - * Default constructor. - */ - public EODelayedObserver () - { - } - - /** - * Removes this observer from the observer queue - * for a currently pending notification. - */ - public void discardPendingNotification () - { - observerQueue().dequeueObserver( this ); - } - - /** - * Returns the observer queue to which this observer - * belongs. This implementation returns the default - * EODelayedObserverQueue. - * Override to use a different one. - */ - public EODelayedObserverQueue observerQueue () - { - return EODelayedObserverQueue.defaultObserverQueue(); - } - - /** - * Returns the priority of this observer in the queue. - * This implementation returns ObserverPriorityThird. - * Override to be notified before other observers. - */ - public int priority () - { - return ObserverPriorityThird; - } - - /** - * Notifies observer that one or more objects that - * it is observing have changed. The observer should - * check all objects it is observing for changes. - */ - public abstract void subjectChanged (); - - // interface EOObserving - - /** - * Called when the specified object is about to change. - * This implementation puts this observer on a - * notification queue. - */ - public void objectWillChange ( Object anObject ) - { - observerQueue().enqueueObserver( this ); - } - - // interface Observer - - /** - * Called when the specified object has changed, - * with the specified argument. - * This method is included for interacting with - * the java.lang.Observer pattern. - * This implementation simply objectWillChange(anObject) - * so that the observer still gets a single subjectChanged - * call in response to multiple changes. - */ - public void update ( Observable anObject, Object aValue ) - { - objectWillChange( anObject ); - } + * This is an abstract class for receiving coalesced notifications of changes + * from objects. This class also implements Observer for greater compatibility. + * The point of EODelayedObservers is that when they receive a willChange + * message, they queue themselves with a EODelayedObserverQueue so they can + * receive a single subjectChanged() after all changes from an observed object + * take place. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public abstract class EODelayedObserver implements EOObserving, Observer { + /** + * Notified immediately. + */ + public static final int ObserverPriorityImmediate = 0; + public static final int ObserverPriorityFirst = 1; + public static final int ObserverPrioritySecond = 2; + public static final int ObserverPriorityThird = 3; + public static final int ObserverPriorityFourth = 4; + public static final int ObserverPriorityFifth = 5; + public static final int ObserverPrioritySixth = 6; + public static final int ObserverPriorityLater = 7; + public static final int ObserverNumberOfPriorities = 8; + + /** + * Default constructor. + */ + public EODelayedObserver() { + } + + /** + * Removes this observer from the observer queue for a currently pending + * notification. + */ + public void discardPendingNotification() { + observerQueue().dequeueObserver(this); + } + + /** + * Returns the observer queue to which this observer belongs. This + * implementation returns the default EODelayedObserverQueue. Override to use a + * different one. + */ + public EODelayedObserverQueue observerQueue() { + return EODelayedObserverQueue.defaultObserverQueue(); + } + + /** + * Returns the priority of this observer in the queue. This implementation + * returns ObserverPriorityThird. Override to be notified before other + * observers. + */ + public int priority() { + return ObserverPriorityThird; + } + + /** + * Notifies observer that one or more objects that it is observing have changed. + * The observer should check all objects it is observing for changes. + */ + public abstract void subjectChanged(); + + // interface EOObserving + + /** + * Called when the specified object is about to change. This implementation puts + * this observer on a notification queue. + */ + public void objectWillChange(Object anObject) { + observerQueue().enqueueObserver(this); + } + + // interface Observer + + /** + * Called when the specified object has changed, with the specified argument. + * This method is included for interacting with the java.lang.Observer pattern. + * This implementation simply objectWillChange(anObject) so that the observer + * still gets a single subjectChanged call in response to multiple changes. + */ + public void update(Observable anObject, Object aValue) { + objectWillChange(anObject); + } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.2 2001/10/26 18:38:10 mpowers - * Reordered priorities. + * Revision 1.2 2001/10/26 18:38:10 mpowers Reordered priorities. * - * Revision 1.1.1.1 2000/12/21 15:46:38 mpowers - * Contributing wotonomy. + * Revision 1.1.1.1 2000/12/21 15:46:38 mpowers Contributing wotonomy. * - * Revision 1.3 2000/12/20 16:25:35 michael - * Added log to all files. + * Revision 1.3 2000/12/20 16:25:35 michael Added log to all files. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODelayedObserverQueue.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODelayedObserverQueue.java index 6b9b9c3..cea0d9e 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODelayedObserverQueue.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EODelayedObserverQueue.java @@ -26,298 +26,246 @@ import net.wotonomy.foundation.NSRunLoop; import net.wotonomy.foundation.NSSelector; /** -* EODelayedObserverQueue allows EODelayedObservers -* to receive only one subjectChanged() message -* after numerous willChange() messages have -* been sent. Observers are then notified in order -* of their priority property, -* so that certain observers can be notified before -* others for whatever application-specific purpose. -* This class is not thread-safe and should be used -* only for single-threaded GUI clients (AWT and Swing). -*

-* -* Important note: because AWT's event queue does -* not allow for priority-based scheduling, this -* class installs a custom event queue, replacing -* the existing queue on the AWT dispatch thread. -* We know of no way around this problem. -*

-* -* Implementation note: this queue relies on the -* result of equals() for maintaining a set of -* objects on the queue. If two EODelayedObservers -* evaluate to the same value using equals(), only -* one of them will exist on the queue. If this, -* starts to suck, we can change it. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * EODelayedObserverQueue allows EODelayedObservers to receive only one + * subjectChanged() message after numerous willChange() messages have been sent. + * Observers are then notified in order of their priority property, so that + * certain observers can be notified before others for whatever + * application-specific purpose. This class is not thread-safe and should be + * used only for single-threaded GUI clients (AWT and Swing).
+ *
+ * + * Important note: because AWT's event queue does not allow for priority-based + * scheduling, this class installs a custom event queue, replacing the existing + * queue on the AWT dispatch thread. We know of no way around this problem.
+ *
+ * + * Implementation note: this queue relies on the result of equals() for + * maintaining a set of objects on the queue. If two EODelayedObservers evaluate + * to the same value using equals(), only one of them will exist on the queue. + * If this, starts to suck, we can change it. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ -public class EODelayedObserverQueue -{ - /** - * The default run loop ordering flushes the delayed observers - * up to ObserverPrioritySixth before dispatching the AWT event - * queue. ObserverPriorityLater is run last. - */ - public static int FlushDelayedObserversRunLoopOrdering = 400000; - - private static EODelayedObserverQueue - defaultObserverQueue = null; - - private static NSSelector runLaterSelector = - new NSSelector( "flushObserverQueue", - new Class[] { Object.class } ); +public class EODelayedObserverQueue { + /** + * The default run loop ordering flushes the delayed observers up to + * ObserverPrioritySixth before dispatching the AWT event queue. + * ObserverPriorityLater is run last. + */ + public static int FlushDelayedObserversRunLoopOrdering = 400000; + + private static EODelayedObserverQueue defaultObserverQueue = null; + + private static NSSelector runLaterSelector = new NSSelector("flushObserverQueue", new Class[] { Object.class }); private boolean willRunLater; - private LinkedList priorityQueue; - - /** - * Default constructor. - */ - public EODelayedObserverQueue () - { + private LinkedList priorityQueue; + + /** + * Default constructor. + */ + public EODelayedObserverQueue() { willRunLater = false; - priorityQueue = new LinkedList(); - } + priorityQueue = new LinkedList(); + } - /** - * Returns the system default observer queue. - */ - public static EODelayedObserverQueue defaultObserverQueue () - { - if ( defaultObserverQueue == null ) - { - defaultObserverQueue = new EODelayedObserverQueue(); + /** + * Returns the system default observer queue. + */ + public static EODelayedObserverQueue defaultObserverQueue() { + if (defaultObserverQueue == null) { + defaultObserverQueue = new EODelayedObserverQueue(); } return defaultObserverQueue; - } + } - /** - * Removes the specified observer from the queue. - */ - public void dequeueObserver ( - EODelayedObserver anObserver ) - { + /** + * Removes the specified observer from the queue. + */ + public void dequeueObserver(EODelayedObserver anObserver) { //System.out.println( "dequeueObserver: " + anObserver ); - //synchronized ( priorityQueue ) - //{ - priorityQueue.remove( anObserver ); - //} - } + // synchronized ( priorityQueue ) + // { + priorityQueue.remove(anObserver); + // } + } - /** - * Adds the specified observer to the queue. - * An already enqueued observer will not be - * added again. - * If the observer's priority is - * ObserverPriorityImmediate, it will be - * notified immediately and not added to the - * queue. - * Otherwise, the queue sets itself up to - * call notifyObserversUpToPriority during the - * run loop as specified by - * FlushDelayedObserversRunLoopOrdering. - */ - public void enqueueObserver ( - EODelayedObserver anObserver ) - { - // syntactic glue for Runnables - final EODelayedObserver observer = anObserver; - - if ( observer.priority() == - EODelayedObserver.ObserverPriorityImmediate ) - { - // invoke immediately + /** + * Adds the specified observer to the queue. An already enqueued observer will + * not be added again. If the observer's priority is ObserverPriorityImmediate, + * it will be notified immediately and not added to the queue. Otherwise, the + * queue sets itself up to call notifyObserversUpToPriority during the run loop + * as specified by FlushDelayedObserversRunLoopOrdering. + */ + public void enqueueObserver(EODelayedObserver anObserver) { + // syntactic glue for Runnables + final EODelayedObserver observer = anObserver; + + if (observer.priority() == EODelayedObserver.ObserverPriorityImmediate) { + // invoke immediately observer.subjectChanged(); - } - else - { - // place in the delayed observer queue - - //synchronized ( priorityQueue ) - //{ - int i = 0; - int priority = observer.priority(); - Object o; + } else { + // place in the delayed observer queue + + // synchronized ( priorityQueue ) + // { + int i = 0; + int priority = observer.priority(); + Object o; - Iterator iterator = priorityQueue.iterator(); + Iterator iterator = priorityQueue.iterator(); - // scan entire list to ensure we're not already queued - while ( iterator.hasNext() ) - { - o = iterator.next(); - if ( o == observer ) - { - // already queued - return; - } - if ( ((EODelayedObserver)o).priority() > priority ) - { - // insert at this index: break now - break; - } - i++; - } - - // if we broke early, we found a threshhold: - // continue scanning to ensure we're not already queued - while ( iterator.hasNext() ) - { - if ( iterator.next() == observer ) - { - // already queued - return; - } - } - - // insert before items of lower priority, - // otherwise insert at end of list. - priorityQueue.add( i, observer ); - - //} + // scan entire list to ensure we're not already queued + while (iterator.hasNext()) { + o = iterator.next(); + if (o == observer) { + // already queued + return; + } + if (((EODelayedObserver) o).priority() > priority) { + // insert at this index: break now + break; + } + i++; + } + + // if we broke early, we found a threshhold: + // continue scanning to ensure we're not already queued + while (iterator.hasNext()) { + if (iterator.next() == observer) { + // already queued + return; + } + } + + // insert before items of lower priority, + // otherwise insert at end of list. + priorityQueue.add(i, observer); + + // } runLater(); } //System.out.println( "enqueueObserver: " + anObserver + " : " + priorityQueue ); - } + } - /** - * Notifies all observers with priority equal to - * or greater than the specified priority. - */ - public void notifyObserversUpToPriority ( int priority ) - { + /** + * Notifies all observers with priority equal to or greater than the specified + * priority. + */ + public void notifyObserversUpToPriority(int priority) { //System.out.println( "notifyObserversUpToPriority: priorityQueue size = " + priorityQueue.size() ); EODelayedObserver o; - while ( ! priorityQueue.isEmpty() ) - { + while (!priorityQueue.isEmpty()) { o = (EODelayedObserver) priorityQueue.getFirst(); - if ( o.priority() > priority ) break; - priorityQueue.removeFirst(); - - try - { - o.subjectChanged(); - } - catch ( Exception exc ) - { - System.out.println( "Error notifying observer: " + o ); - exc.printStackTrace(); - } + if (o.priority() > priority) + break; + priorityQueue.removeFirst(); + + try { + o.subjectChanged(); + } catch (Exception exc) { + System.out.println("Error notifying observer: " + o); + exc.printStackTrace(); + } } } - + /** - * Called to ensure that notifyObserversUpToPriority - * will be called on the next event loop. - */ - private void runLater() - { - if ( ! willRunLater ) - { + * Called to ensure that notifyObserversUpToPriority will be called on the next + * event loop. + */ + private void runLater() { + if (!willRunLater) { willRunLater = true; - NSRunLoop.currentRunLoop().performSelectorWithOrder( - runLaterSelector, this, null, FlushDelayedObserversRunLoopOrdering, null ); + NSRunLoop.currentRunLoop().performSelectorWithOrder(runLaterSelector, this, null, + FlushDelayedObserversRunLoopOrdering, null); } } - + /** - * This method is called by the event queue run loop - * and calls notifyObserversUpToPriority with - * ObserverPriorityLater. - * NOTE: This method is not part of the specification. - */ - public void flushObserverQueue( Object anObject ) - { + * This method is called by the event queue run loop and calls + * notifyObserversUpToPriority with ObserverPriorityLater. NOTE: This method is + * not part of the specification. + */ + public void flushObserverQueue(Object anObject) { //System.out.println( "EODelayedObserverQueue: running" ); - notifyObserversUpToPriority( EODelayedObserver.ObserverPrioritySixth ); - if ( ! priorityQueue.isEmpty() ) - { - // assumes all remaining on queue are ObserverPriorityLater - NSRunLoop.invokeLater( - new PriorityLaterRunnable( new LinkedList( priorityQueue ) ) ); - priorityQueue.clear(); - } + notifyObserversUpToPriority(EODelayedObserver.ObserverPrioritySixth); + if (!priorityQueue.isEmpty()) { + // assumes all remaining on queue are ObserverPriorityLater + NSRunLoop.invokeLater(new PriorityLaterRunnable(new LinkedList(priorityQueue))); + priorityQueue.clear(); + } willRunLater = false; } - - /** - * A runnable for dispatching remaining observers running at ObserverPriorityLater. - */ - class PriorityLaterRunnable implements Runnable - { - List observers; - - public PriorityLaterRunnable( List anObserverList ) - { - observers = anObserverList; - } - - public void run() - { - EODelayedObserver o = null; - Iterator i = observers.iterator(); - while ( i.hasNext() ) - { - try - { - o = (EODelayedObserver) i.next(); - o.subjectChanged(); - } - catch ( Exception exc ) - { - System.out.println( "Error notifying observer: " + o ); - exc.printStackTrace(); - } - } - } - } - -} + + /** + * A runnable for dispatching remaining observers running at + * ObserverPriorityLater. + */ + class PriorityLaterRunnable implements Runnable { + List observers; + + public PriorityLaterRunnable(List anObserverList) { + observers = anObserverList; + } + + public void run() { + EODelayedObserver o = null; + Iterator i = observers.iterator(); + while (i.hasNext()) { + try { + o = (EODelayedObserver) i.next(); + o.subjectChanged(); + } catch (Exception exc) { + System.out.println("Error notifying observer: " + o); + exc.printStackTrace(); + } + } + } + } + +} /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.8 2003/08/19 01:53:12 chochos - * EOObjectStore had some incompatible return types (Object instead of EOEnterpriseObject, in fault methods mostly). It's internally consistent but I hope it doesn't break anything based on this, even though fault methods mostly throw exceptions for now. + * Revision 1.8 2003/08/19 01:53:12 chochos EOObjectStore had some incompatible + * return types (Object instead of EOEnterpriseObject, in fault methods mostly). + * It's internally consistent but I hope it doesn't break anything based on + * this, even though fault methods mostly throw exceptions for now. * - * Revision 1.7 2002/05/20 15:08:35 mpowers - * Optimization for enqueueObserver: we were scanning the entire list anyway; - * now we compare priorities and ensure we're not double-queued on same pass. + * Revision 1.7 2002/05/20 15:08:35 mpowers Optimization for enqueueObserver: we + * were scanning the entire list anyway; now we compare priorities and ensure + * we're not double-queued on same pass. * - * Revision 1.6 2002/05/15 13:45:57 mpowers - * RunLater now appropriately runs later: at the end of the current awt queue. + * Revision 1.6 2002/05/15 13:45:57 mpowers RunLater now appropriately runs + * later: at the end of the current awt queue. * - * Revision 1.5 2002/03/11 03:18:39 mpowers - * Now properly handling ObserverChangesLater. + * Revision 1.5 2002/03/11 03:18:39 mpowers Now properly handling + * ObserverChangesLater. * - * Revision 1.4 2001/10/26 18:37:15 mpowers - * Now using NSRunLoop instead of AWT EventQueue. + * Revision 1.4 2001/10/26 18:37:15 mpowers Now using NSRunLoop instead of AWT + * EventQueue. * - * Revision 1.3 2001/10/22 21:54:16 mpowers - * Removed swing dependency in favor of jdk1.3 event queue. - * Optimized priority queue population. + * Revision 1.3 2001/10/22 21:54:16 mpowers Removed swing dependency in favor of + * jdk1.3 event queue. Optimized priority queue population. * - * Revision 1.2 2001/10/12 18:01:59 mpowers - * Now catching exceptions before they disrupt the awt event queue. + * Revision 1.2 2001/10/12 18:01:59 mpowers Now catching exceptions before they + * disrupt the awt event queue. * - * Revision 1.1.1.1 2000/12/21 15:46:42 mpowers - * Contributing wotonomy. + * Revision 1.1.1.1 2000/12/21 15:46:42 mpowers Contributing wotonomy. * - * Revision 1.5 2000/12/20 16:25:35 michael - * Added log to all files. + * Revision 1.5 2000/12/20 16:25:35 michael Added log to all files. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOEditingContext.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOEditingContext.java index b01727d..3a39035 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOEditingContext.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOEditingContext.java @@ -42,3206 +42,2593 @@ import net.wotonomy.foundation.internal.WotonomyException; //import javax.swing.undo.UndoManager; /** -* EOEditingContext provides transactional support for -* fetching, editing, and committing changes made on a -* collection of objects to a parent object store.

-* -* EOEditingContext is itself a subclass of EOObjectStore, -* and this means that EOEditingContexts can use other -* EOEditingContexts as their parent. However, there -* still must exist an EOObjectStore as the root of the -* editing hierarchy that can maintain persistent state. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public class EOEditingContext - extends EOObjectStore - implements EOObserving -{ - /** - * Key for the NSNotification posted after this editing context - * saves changes. Object of the notification will be this editing - * context, and user info will contain InsertedKey, UpdatedKey, - * and DeletedKey (keys are defined in EOObjectStore). - */ - public static final String - EditingContextDidSaveChangesNotification = - "EOEditingContextDidSaveChangesNotification"; - - /** - * Key for the NSNotification posted after this editing context - * observes changes. Object of the notification will be this editing - * context, and user info will contain InsertedKey, UpdatedKey, InvalidatedKey, - * and DeletedKey (keys are defined in EOObjectStore), however - * the objects in the corresponding Lists will be the actual - * objects, not their ids. - */ - public static final String - ObjectsChangedInEditingContextNotification = - "EOObjectsChangedInEditingContextNotification"; - - /** - * The default run loop ordering processes recent changes - * before delayed observers are notified and before dispatching - * the AWT event queue. - */ - public static int - EditingContextFlushChangesRunLoopOrdering = 300000; - - private static NSSelector runLaterSelector = - new NSSelector( "flushRecentChanges", - new Class[] { Object.class } ); - - private static EOObjectStore defaultParentObjectStore = null; - private static double defaultFetchTimestampLag = 0; - private static boolean retainsRegisteredObjects = true; - - private EOObjectStore parentStore; - private WeakReference delegate; - private WeakReference messageHandler; - private List editorSet; - private double fetchTimestamp; - private boolean lockBeforeModify; - private boolean propagateDeletesAfterEvent; - private boolean stopValidationAfterError; - private NSMutableArray insertedObjects; - private NSMutableArray insertedObjectsBuffer; - private NSArray insertedObjectsProxy; - private NSMutableArray updatedObjects; - private NSMutableArray updatedObjectsBuffer; - private NSArray updatedObjectsProxy; - private NSMutableArray deletedObjects; - private NSMutableArray deletedObjectsBuffer; - private NSArray deletedObjectsProxy; - private NSMutableArray deletedIDsBuffer; - private NSMutableArray invalidatedObjectsBuffer; - private NSMutableArray invalidatedIDsBuffer; - private Registrar registrar; + * EOEditingContext provides transactional support for fetching, editing, and + * committing changes made on a collection of objects to a parent object store. + *
+ *
+ * + * EOEditingContext is itself a subclass of EOObjectStore, and this means that + * EOEditingContexts can use other EOEditingContexts as their parent. However, + * there still must exist an EOObjectStore as the root of the editing hierarchy + * that can maintain persistent state. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public class EOEditingContext extends EOObjectStore implements EOObserving { + /** + * Key for the NSNotification posted after this editing context saves changes. + * Object of the notification will be this editing context, and user info will + * contain InsertedKey, UpdatedKey, and DeletedKey (keys are defined in + * EOObjectStore). + */ + public static final String EditingContextDidSaveChangesNotification = "EOEditingContextDidSaveChangesNotification"; + + /** + * Key for the NSNotification posted after this editing context observes + * changes. Object of the notification will be this editing context, and user + * info will contain InsertedKey, UpdatedKey, InvalidatedKey, and DeletedKey + * (keys are defined in EOObjectStore), however the objects in the corresponding + * Lists will be the actual objects, not their ids. + */ + public static final String ObjectsChangedInEditingContextNotification = "EOObjectsChangedInEditingContextNotification"; + + /** + * The default run loop ordering processes recent changes before delayed + * observers are notified and before dispatching the AWT event queue. + */ + public static int EditingContextFlushChangesRunLoopOrdering = 300000; + + private static NSSelector runLaterSelector = new NSSelector("flushRecentChanges", new Class[] { Object.class }); + + private static EOObjectStore defaultParentObjectStore = null; + private static double defaultFetchTimestampLag = 0; + private static boolean retainsRegisteredObjects = true; + + private EOObjectStore parentStore; + private WeakReference delegate; + private WeakReference messageHandler; + private List editorSet; + private double fetchTimestamp; + private boolean lockBeforeModify; + private boolean propagateDeletesAfterEvent; + private boolean stopValidationAfterError; + private NSMutableArray insertedObjects; + private NSMutableArray insertedObjectsBuffer; + private NSArray insertedObjectsProxy; + private NSMutableArray updatedObjects; + private NSMutableArray updatedObjectsBuffer; + private NSArray updatedObjectsProxy; + private NSMutableArray deletedObjects; + private NSMutableArray deletedObjectsBuffer; + private NSArray deletedObjectsProxy; + private NSMutableArray deletedIDsBuffer; + private NSMutableArray invalidatedObjectsBuffer; + private NSMutableArray invalidatedIDsBuffer; + private Registrar registrar; // private UndoManager undoManager; - // so we don't have to trouble EOObserverCenter - private boolean ignoreChanges; - - // for delayed handling of processRecentChanges - private boolean willRunLater; - - // for handling of notifications posted - // while we're in the saveChanges method - private boolean isInvalidating; - - // for i18n or other customization - static protected String MessageChangeConflict = - "Another user changed an object you are editing: "; - - /** - * Default constructor creates a new editing context - * that uses the default object store. If the default - * object store has not been set, an exception is thrown. - */ - public EOEditingContext() - { - this( defaultParentObjectStore() ); - } - - /** - * Creates a new editing context that uses the specified - * object store as its parent object store. - */ - public EOEditingContext( EOObjectStore anObjectStore ) - { - if ( anObjectStore == null ) - { - throw new IllegalArgumentException( - "A parent object store must be specified." ); - } - - parentStore = anObjectStore; - delegate = null; - messageHandler = null; - editorSet = new LinkedList(); - fetchTimestamp = 0; - lockBeforeModify = false; - propagateDeletesAfterEvent = true; - stopValidationAfterError = true; - insertedObjects = new NSMutableArray(); - insertedObjectsBuffer = new NSMutableArray(); - insertedObjectsProxy = NSArray.arrayBackedByList( insertedObjects ); - updatedObjects = new NSMutableArray(); - updatedObjectsBuffer = new NSMutableArray(); - updatedObjectsProxy = NSArray.arrayBackedByList( updatedObjects ); - deletedObjects = new NSMutableArray(); - deletedObjectsBuffer = new NSMutableArray(); - deletedObjectsProxy = NSArray.arrayBackedByList( deletedObjects ); - deletedIDsBuffer = new NSMutableArray(); - invalidatedObjectsBuffer = new NSMutableArray(); - invalidatedIDsBuffer = new NSMutableArray(); - - if ( instancesRetainRegisteredObjects() ) - { - registrar = new Registrar( this ); - } - else - { - registrar = new WeakRegistrar( this ); - } - - ignoreChanges = false; - willRunLater = false; - isInvalidating = false; - - // create undo manager - //TODO: this should be NSUndoManager + // so we don't have to trouble EOObserverCenter + private boolean ignoreChanges; + + // for delayed handling of processRecentChanges + private boolean willRunLater; + + // for handling of notifications posted + // while we're in the saveChanges method + private boolean isInvalidating; + + // for i18n or other customization + static protected String MessageChangeConflict = "Another user changed an object you are editing: "; + + /** + * Default constructor creates a new editing context that uses the default + * object store. If the default object store has not been set, an exception is + * thrown. + */ + public EOEditingContext() { + this(defaultParentObjectStore()); + } + + /** + * Creates a new editing context that uses the specified object store as its + * parent object store. + */ + public EOEditingContext(EOObjectStore anObjectStore) { + if (anObjectStore == null) { + throw new IllegalArgumentException("A parent object store must be specified."); + } + + parentStore = anObjectStore; + delegate = null; + messageHandler = null; + editorSet = new LinkedList(); + fetchTimestamp = 0; + lockBeforeModify = false; + propagateDeletesAfterEvent = true; + stopValidationAfterError = true; + insertedObjects = new NSMutableArray(); + insertedObjectsBuffer = new NSMutableArray(); + insertedObjectsProxy = NSArray.arrayBackedByList(insertedObjects); + updatedObjects = new NSMutableArray(); + updatedObjectsBuffer = new NSMutableArray(); + updatedObjectsProxy = NSArray.arrayBackedByList(updatedObjects); + deletedObjects = new NSMutableArray(); + deletedObjectsBuffer = new NSMutableArray(); + deletedObjectsProxy = NSArray.arrayBackedByList(deletedObjects); + deletedIDsBuffer = new NSMutableArray(); + invalidatedObjectsBuffer = new NSMutableArray(); + invalidatedIDsBuffer = new NSMutableArray(); + + if (instancesRetainRegisteredObjects()) { + registrar = new Registrar(this); + } else { + registrar = new WeakRegistrar(this); + } + + ignoreChanges = false; + willRunLater = false; + isInvalidating = false; + + // create undo manager + // TODO: this should be NSUndoManager // undoManager = new UndoManager(); - // register for notifications - NSSelector handleNotification = - new NSSelector( "handleNotification", - new Class[] { NSNotification.class } ); - // any from parent store - NSNotificationCenter.defaultCenter().addObserver( - this, handleNotification, null, parentStore ); - // global id change from any - NSNotificationCenter.defaultCenter().addObserver( - this, handleNotification, EOGlobalID.GlobalIDChangedNotification, null ); + // register for notifications + NSSelector handleNotification = new NSSelector("handleNotification", new Class[] { NSNotification.class }); + // any from parent store + NSNotificationCenter.defaultCenter().addObserver(this, handleNotification, null, parentStore); + // global id change from any + NSNotificationCenter.defaultCenter().addObserver(this, handleNotification, + EOGlobalID.GlobalIDChangedNotification, null); //new net.wotonomy.ui.swing.NotificationInspector( null, parentStore ); - } - - /** - * Registers the specified object as an editor for this - * context. The object is expected to implement - * EOEditingContext.Editor. - */ - public void addEditor ( Object anEditor ) - { - if ( anEditor == null ) return; - editorSet.add( new WeakReference( anEditor ) ); - } - - /** - * Returns a read-only List of objects associated with the object - * with the specified id for the specified property - * relationship, or may return a placeholder array that - * will defer the fetch until needed (aka an array fault). - * All objects must be registered in the specified editing context. - * This implementation calls to its parent object store's - * implementation if the requested source object is not - * registered in this editing context. - * The specified relationship key must produce a result of - * type Collection for the source object or an exception is thrown. - */ - public NSArray arrayFaultWithSourceGlobalID ( - EOGlobalID aGlobalID, - String aRelationshipKey, - EOEditingContext aContext ) - { - NSArray result = null; - Object source = registrar.objectForGlobalID( aGlobalID ); - - // if not registered in our context - if ( source == null ) - { - // get the object registered into our context - result = parentStore.arrayFaultWithSourceGlobalID( - aGlobalID, aRelationshipKey, this ); - } - else // source is registered in our context - { - // get existing value - Object value; - if ( source instanceof EOKeyValueCoding ) - { - value = ((EOKeyValueCoding)source).storedValueForKey( - aRelationshipKey ); - } - else // handle directly - { - value = EOKeyValueCodingSupport.storedValueForKey( - source, aRelationshipKey ); - } - - if ( value == null ) - { - // do the same as if the source was null - result = parentStore.arrayFaultWithSourceGlobalID( - aGlobalID, aRelationshipKey, this ); - } - else - if ( value instanceof NSArray ) - { - result = (NSArray) value; - } - else // not NSArray - if ( value instanceof Collection ) - { - // convert to NSArray - result = new NSArray( (Collection) value ); - } - else - { - throw new WotonomyException( - "Relationship key did not return a collection: " - + aGlobalID + " : " + aRelationshipKey ); - } - } - - // if our context is not the specified context - if ( aContext != this ) - { - result = (NSArray) clone( this, result, aContext ); - } - - return result; - } - - /** - * Returns a snapshot of the specified object as it - * existed when it was last read or committed to the - * parent object store. - */ - public NSDictionary committedSnapshotForObject ( - Object anObject ) - { - byte[] snapshot = (byte[]) - registrar.getCommitSnapshot( anObject ); - if ( snapshot == null ) - { - // this object not modified: take a current snapshot - snapshot = takeSnapshot( anObject ); - } - return convertSnapshotToDictionary( snapshot ); - } - - /** - * Returns a snapshot of the specified object as it - * existed before the edits triggered by the current - * event loop were processed. - */ - public NSDictionary currentEventSnapshotForObject ( - Object anObject ) - { - byte[] result = (byte[]) - registrar.getCurrentSnapshot( anObject ); - if ( result == null ) - { - return committedSnapshotForObject( anObject ); - } - return convertSnapshotToDictionary( result ); - } - - /** - * Returns the delegate for this editing context, - * or null if no delegate has been set. - */ - public Object delegate () - { - if ( delegate == null ) return null; - return delegate.get(); - } - - /** - * Deletes the specified object from this editing context. - * The editing context marks the object as deleted and - * will notify the parent store when changes are committed. - */ - public void deleteObject ( - Object anObject ) - { - willChange(); + } + + /** + * Registers the specified object as an editor for this context. The object is + * expected to implement EOEditingContext.Editor. + */ + public void addEditor(Object anEditor) { + if (anEditor == null) + return; + editorSet.add(new WeakReference(anEditor)); + } + + /** + * Returns a read-only List of objects associated with the object with the + * specified id for the specified property relationship, or may return a + * placeholder array that will defer the fetch until needed (aka an array + * fault). All objects must be registered in the specified editing context. This + * implementation calls to its parent object store's implementation if the + * requested source object is not registered in this editing context. The + * specified relationship key must produce a result of type Collection for the + * source object or an exception is thrown. + */ + public NSArray arrayFaultWithSourceGlobalID(EOGlobalID aGlobalID, String aRelationshipKey, + EOEditingContext aContext) { + NSArray result = null; + Object source = registrar.objectForGlobalID(aGlobalID); + + // if not registered in our context + if (source == null) { + // get the object registered into our context + result = parentStore.arrayFaultWithSourceGlobalID(aGlobalID, aRelationshipKey, this); + } else // source is registered in our context + { + // get existing value + Object value; + if (source instanceof EOKeyValueCoding) { + value = ((EOKeyValueCoding) source).storedValueForKey(aRelationshipKey); + } else // handle directly + { + value = EOKeyValueCodingSupport.storedValueForKey(source, aRelationshipKey); + } + + if (value == null) { + // do the same as if the source was null + result = parentStore.arrayFaultWithSourceGlobalID(aGlobalID, aRelationshipKey, this); + } else if (value instanceof NSArray) { + result = (NSArray) value; + } else // not NSArray + if (value instanceof Collection) { + // convert to NSArray + result = new NSArray((Collection) value); + } else { + throw new WotonomyException( + "Relationship key did not return a collection: " + aGlobalID + " : " + aRelationshipKey); + } + } + + // if our context is not the specified context + if (aContext != this) { + result = (NSArray) clone(this, result, aContext); + } + + return result; + } + + /** + * Returns a snapshot of the specified object as it existed when it was last + * read or committed to the parent object store. + */ + public NSDictionary committedSnapshotForObject(Object anObject) { + byte[] snapshot = (byte[]) registrar.getCommitSnapshot(anObject); + if (snapshot == null) { + // this object not modified: take a current snapshot + snapshot = takeSnapshot(anObject); + } + return convertSnapshotToDictionary(snapshot); + } + + /** + * Returns a snapshot of the specified object as it existed before the edits + * triggered by the current event loop were processed. + */ + public NSDictionary currentEventSnapshotForObject(Object anObject) { + byte[] result = (byte[]) registrar.getCurrentSnapshot(anObject); + if (result == null) { + return committedSnapshotForObject(anObject); + } + return convertSnapshotToDictionary(result); + } + + /** + * Returns the delegate for this editing context, or null if no delegate has + * been set. + */ + public Object delegate() { + if (delegate == null) + return null; + return delegate.get(); + } + + /** + * Deletes the specified object from this editing context. The editing context + * marks the object as deleted and will notify the parent store when changes are + * committed. + */ + public void deleteObject(Object anObject) { + willChange(); int i; // remove from added objects if necessary - i = insertedObjects.indexOfIdenticalObject( anObject ); - if ( i != NSArray.NotFound ) + i = insertedObjects.indexOfIdenticalObject(anObject); + if (i != NSArray.NotFound) { + insertedObjects.removeObjectAtIndex(i); + + // if in the inserted objects buffer + int index = insertedObjectsBuffer.indexOfIdenticalObject(anObject); + if (index != NSArray.NotFound) { + // remove from inserted objects buffer + insertedObjectsBuffer.removeObjectAtIndex(index); + } + + // now forget the object ever existed. + forgetObject(anObject); + + // we're done + return; + } else // otherwise add to deleted objects list { - insertedObjects.removeObjectAtIndex( i ); - - // if in the inserted objects buffer - int index = insertedObjectsBuffer.indexOfIdenticalObject( anObject ); - if ( index != NSArray.NotFound ) - { - // remove from inserted objects buffer - insertedObjectsBuffer.removeObjectAtIndex( index ); - } - - // now forget the object ever existed. - forgetObject( anObject ); - - // we're done - return; - } - else // otherwise add to deleted objects list - { - deletedObjects.addObject( anObject ); + deletedObjects.addObject(anObject); } - + // remove from updated objects if necessary - i = updatedObjects.indexOfIdenticalObject( anObject ); - if ( i != NSArray.NotFound ) - { - updatedObjects.removeObjectAtIndex( i ); - } - - // add to buffer - deletedObjectsBuffer.addObject( anObject ); - deletedIDsBuffer.addObject( globalIDForObject( anObject ) ); - } - - /** - * Returns a read-only List of all objects marked as deleted - * in this editing context. - */ - public NSArray deletedObjects () - { - return deletedObjectsProxy; - } - - /** - * Called by child editing contexts when they no longer - * need to track the specified id. - * This implementation forwards the call to the parent store. - */ - public void editingContextDidForgetObjectWithGlobalID ( - EOEditingContext aContext, - EOGlobalID aGlobalID ) - { - parentStore.editingContextDidForgetObjectWithGlobalID( - aContext, aGlobalID ); - } - - /** - * Returns a read-only List of registered editors of this - * editing context. - */ - public NSArray editors () - { - NSMutableArray result = new NSMutableArray(); - Object o; - Iterator i = editorSet.iterator(); - while ( i.hasNext() ) - { - o = ((WeakReference)i.next()).get(); - if ( o != null ) - { - result.addObject( o ); - } - else - { - i.remove(); - } - } - return result; - } - -/* - public static void encodeObjectWithCoder ( - Object anObject, - NSCoder aCoder ) - { - throw new net.wotonomy.util.WotonomyException("Not implemented yet."); - } -*/ + i = updatedObjects.indexOfIdenticalObject(anObject); + if (i != NSArray.NotFound) { + updatedObjects.removeObjectAtIndex(i); + } - /** - * Returns the object for the specified id. - * If the object is registered in in this context - * but not in the specified context, - * this implementation will create a copy of the object - * and register it in the specified context. - * Otherwise it will forward the call to the parent - * object store. - */ - public /*EOEnterpriseObject*/ Object faultForGlobalID ( - EOGlobalID aGlobalID, - EOEditingContext aContext ) - { - Object result = registrar.objectForGlobalID( aGlobalID ); - - // if not registered in our context - if ( result == null ) - { - // get the object registered into our context - result = parentStore.faultForGlobalID( aGlobalID, this ); - } - - // if our context is not the specified context - if ( aContext != this ) - { - result = registerClone( aGlobalID, this, result, aContext ); - } - - return result; - } - - /** - * Returns a fault representing an object of - * the specified entity type with values from - * the specified dictionary. - * This implementation calls faultForRawRow - * on the parent store. - */ - public Object faultForRawRow ( - Map aDictionary, - String anEntityName ) - { - return parentStore.faultForRawRow( - aDictionary, anEntityName, this ); - } - - /** - * Returns a fault representing an object of - * the specified entity type with values from - * the specified dictionary. The fault should - * belong to the specified editing context. - * This implementation forwards the call to - * the parent store. - */ - public /*EOEnterpriseObject*/ Object faultForRawRow ( - Map aDictionary, - String anEntityName, - EOEditingContext aContext ) - { - return parentStore.faultForRawRow( - aDictionary, anEntityName, aContext ); - } - - /** - * Returns the fetch timestamp for this editing context. - */ - public double fetchTimestamp () - { - return fetchTimestamp; - } - - /** - * Unregisters the specified object from this editing context, - * removing all references to it. Use this method to remove - * an object from the context without marking it for deletion. - */ - public void forgetObject ( - Object anObject ) - { - EOGlobalID id = registrar.globalIDForObject( anObject ); - if ( id == null ) - { - System.err.println( - "EOEditingContext.forgetObject: not registered: " + anObject ); - return; - } - - // unregister object - registrar.forgetObject( anObject ); - - // remove from all, inserted, updated, and deleted lists - int index; - index = updatedObjects.indexOfIdenticalObject( anObject ); - if ( index != NSArray.NotFound ) - { - updatedObjects.removeObjectAtIndex( index ); - } - index = insertedObjects.indexOfIdenticalObject( anObject ); - if ( index != NSArray.NotFound ) - { - insertedObjects.removeObjectAtIndex( index ); - return; - } - index = deletedObjects.indexOfIdenticalObject( anObject ); - if ( index != NSArray.NotFound ) - { - deletedObjects.removeObjectAtIndex( index ); - return; - } - - // notify parent context - parentStore.editingContextDidForgetObjectWithGlobalID( this, id ); - } - - /** - * Returns the id for the specified object, or null - * if the object is not registered in this context. - */ - public EOGlobalID globalIDForObject ( - Object anObject ) - { - return registrar.globalIDForObject( anObject ); - } - - /** - * Returns an array of ids for an array of objects. - */ - private NSArray globalIDsForObjects( - List anObjectList ) - { - NSMutableArray result = new NSMutableArray(); - Iterator it = anObjectList.iterator(); - while ( it.hasNext() ) - { - result.add( globalIDForObject( it.next() ) ); - } - return result; - } - - /** - * Returns whether this editing context has changes that - * have not yet been committed to the parent object store. - */ - public boolean hasChanges () - { - if ( updatedObjects.count() > 0 ) return true; - if ( insertedObjects.count() > 0 ) return true; - if ( deletedObjects.count() > 0 ) return true; - return false; - } - - /** - * Given a newly instantiated object, this method - * initializes its properties to values appropriate - * for the specified id. The object should already - * belong to the specified editing context. - * This method is called to populate faults. - * This implementation will try to apply the values - * from an object with a matching id in this editing - * context if possible, calling to the parent object - * store only if such an object is not found. - */ - public void initializeObject ( - /*EOEnterpriseObject*/ Object anObject, - EOGlobalID aGlobalID, - EOEditingContext aContext ) - { - Object existingObject = registrar.objectForGlobalID( aGlobalID ); - - // if not registered in our context - if ( existingObject == null ) - { - // get the object registered into our context - existingObject = parentStore.faultForGlobalID( aGlobalID, this ); - } - - if ( aContext == this ) - { - // initialize the object - parentStore.initializeObject( - /*(EOEnterpriseObject)*/existingObject, aGlobalID, this ); - } - else // ( aContext != this ) - { - // translates child relationships - copy( this, existingObject, aContext, anObject ); - } - - aContext.registrar.setCommitSnapshot( anObject, null ); - aContext.registrar.setCurrentSnapshot( anObject, null ); - } - - /** - * Inserts the specified object into this editing context. - * This implementation calls insertObjectWithGlobalID - * with an EOTemporaryGlobalID. - */ - public void insertObject ( Object anObject ) - { - insertObjectWithGlobalID( - anObject, new EOTemporaryGlobalID() ); - } - - /** - * Inserts the specified object into this editing context - * with the specified id, which is expected to be a - * temporary id. - */ - public void insertObjectWithGlobalID ( - Object anObject, - EOGlobalID aGlobalID ) - { - willChange(); - - // if this object was marked for deletion - int index = deletedObjects.indexOfIdenticalObject( anObject ); - if ( index != NSArray.NotFound ) - { - // don't need to re-register: just update the lists - - // remove from deleted list - deletedObjects.removeObjectAtIndex( index ); - - // if in the deleted ids buffer - index = deletedIDsBuffer.indexOfIdenticalObject( anObject ); - if ( index != NSArray.NotFound ) - { - // remove from deleted ids buffer - deletedIDsBuffer.removeObjectAtIndex( index ); - } - - // if in the deleted objects buffer - index = deletedObjectsBuffer.indexOfIdenticalObject( anObject ); - if ( index != NSArray.NotFound ) - { - // remove from deleted objects buffer - deletedObjectsBuffer.removeObjectAtIndex( index ); - } - else // not in the deleted objects buffer - { - // add to the inserted objects buffer - insertedObjectsBuffer.addObject( anObject ); - } - - // we're done - return; - } - - // make sure object is not already in editing context - if ( objectForGlobalID( aGlobalID ) != null ) - { - throw new WotonomyException( - "Tried to insert but object was already registered:" - + aGlobalID ); - } - - // register object - recordObject( anObject, aGlobalID ); - - // add to inserted list - insertedObjects.addObject( anObject ); - // add to buffer - insertedObjectsBuffer.addObject( anObject ); - } - - /** - * Returns a read-only List of the objects that have been - * inserted into this editing context. - */ - public NSArray insertedObjects () - { - return insertedObjectsProxy; - } - - /** - * Turn all objects in this editing context into faults, - * so that they will be fetched the next time they are - * accessed, and calls invalidateObjectsWithGlobalIDs - * on the parent object store. - */ - public void invalidateAllObjects () - { - // register change so processRecentChanges is called - willChange(); - - invalidateAllObjectsQuietly(); - - // post notification - NSNotificationCenter.defaultCenter().postNotification( - new NSNotification( - InvalidatedAllObjectsInStoreNotification, this ) ); - } - - /** - * Only refaults all objects, does not notify will change - * nor post notification, but does call parent store. - * Called by invalidateAllObjects() and handleNotification(). - */ - private void invalidateAllObjectsQuietly() - { - // remember the ids - NSMutableArray ids = new NSMutableArray( registrar.registeredGlobalIDs() ); - - // track of discarded IDs (from inserted objects) - NSMutableArray discardedIDs = new NSMutableArray(); - - // refault all objects - EOGlobalID id; - Object o; - Enumeration e = ids.objectEnumerator(); - while ( e.hasMoreElements() ) - { - id = (EOGlobalID) e.nextElement(); - o = objectForGlobalID( id ); - - // some objects may have been manually discarded - if ( o != null ) - { - // don't refault newly inserted objects - if ( insertedObjects.indexOfIdenticalObject( o ) == NSArray.NotFound ) - { - refaultObject( o, id, this ); - } - else - { - // discard inserted objects - forgetObject( o ); - discardedIDs.add( id ); - } - invalidatedObjectsBuffer.add( o ); - } - invalidatedIDsBuffer.add( id ); - } - ids.removeAll( discardedIDs ); - - // call to parent store (should call this after posting instead?) - isInvalidating = true; - parentStore.invalidateObjectsWithGlobalIDs( ids ); - isInvalidating = false; - } - - /** - * Turns the objects with the specified ids into faults, - * so that they will be fetched the next time they are - * accessed, and forwards the call to the parent object store. - */ - public void invalidateObjectsWithGlobalIDs ( - List anArray ) - { - // register change so processRecentChanges is called - willChange(); - - // call to parent to invalidate objects - parentStore.invalidateObjectsWithGlobalIDs( anArray ); - - Object o; - EOGlobalID id; - Iterator it = anArray.iterator(); - while ( it.hasNext() ) - { - id = (EOGlobalID) it.next(); - if ( id != null ) - { - o = objectForGlobalID( id ); - if ( o != null ) - { - Object result = notifyDelegate( - "editingContextShouldInvalidateObject", - new Class[] { EOEditingContext.class, Object.class, EOGlobalID.class }, - new Object[] { this, o, id } ); - if ( ( result == null ) || ( Boolean.TRUE.equals( result ) ) ) - { - // refault the object - refaultObject( o, id, this ); - invalidatedObjectsBuffer.add( o ); - invalidatedIDsBuffer.add( id ); - } - } - } - else - { - throw new WotonomyException( - "Attempted to invalidate a null global id: " + anArray ); - } - } - - } -/* - public boolean invalidatesObjectsWhenFinalized ( ) - { - throw new net.wotonomy.util.WotonomyException("Not implemented yet."); - } - - public boolean invalidatesObjectsWhenFreed ( ) - { - throw new net.wotonomy.util.WotonomyException("Not implemented yet."); - } -*/ - /** - * Returns whether the object referenced by the - * specified id is locked. - * This implementation simply forwards the call to - * the parent object store. - */ - public boolean isObjectLockedWithGlobalID ( - EOGlobalID aGlobalID, - EOEditingContext aContext) - { - return parentStore.isObjectLockedWithGlobalID( - aGlobalID, aContext ); - } - -/* - public void lock () - { - throw new net.wotonomy.util.WotonomyException("Not implemented yet."); - } -*/ - /** - * Locks the specified object in this editing context - * by calling lockObjectWithGlobalID on the parent store. - */ - public void lockObject ( - Object anObject ) - { - parentStore.lockObjectWithGlobalID( - globalIDForObject( anObject ), this ); - } - - /** - * Locks the object referenced by the specified id - * in the specified editing context. - * This implementation simply forwards the call to - * the parent object store. - */ - public void lockObjectWithGlobalID ( - EOGlobalID aGlobalID, - EOEditingContext aContext) - { - parentStore.lockObjectWithGlobalID( - aGlobalID, aContext ); - } - - /** - * Returns whether this editing context attempts to - * lock objects when they are first modified. - */ - public boolean locksObjectsBeforeFirstModification () - { - return lockBeforeModify; - } - - /** - * Returns the message handler for this editing context, - * or null if no message handler has been set. - */ - public Object messageHandler () - { - if ( messageHandler == null ) return null; - return messageHandler.get(); - } - - /** - * Returns the object registered in this editing context - * for the specified id, or null if that id is not - * registered. - */ - public Object objectForGlobalID ( - EOGlobalID aGlobalID ) - { - return registrar.objectForGlobalID( aGlobalID ); - } - - /** - * Returns a read-only List of objects associated with the object - * with the specified id for the specified property - * relationship. This method may not return an array fault - * because array faults call this method to fetch on demand. - * All objects must be registered the specified editing context. - * The specified relationship key must produce a result of - * type Collection for the source object or an exception is thrown. - */ - public NSArray objectsForSourceGlobalID ( - EOGlobalID aGlobalID, - String aRelationshipKey, - EOEditingContext aContext ) - { + // add to buffer + deletedObjectsBuffer.addObject(anObject); + deletedIDsBuffer.addObject(globalIDForObject(anObject)); + } + + /** + * Returns a read-only List of all objects marked as deleted in this editing + * context. + */ + public NSArray deletedObjects() { + return deletedObjectsProxy; + } + + /** + * Called by child editing contexts when they no longer need to track the + * specified id. This implementation forwards the call to the parent store. + */ + public void editingContextDidForgetObjectWithGlobalID(EOEditingContext aContext, EOGlobalID aGlobalID) { + parentStore.editingContextDidForgetObjectWithGlobalID(aContext, aGlobalID); + } + + /** + * Returns a read-only List of registered editors of this editing context. + */ + public NSArray editors() { + NSMutableArray result = new NSMutableArray(); + Object o; + Iterator i = editorSet.iterator(); + while (i.hasNext()) { + o = ((WeakReference) i.next()).get(); + if (o != null) { + result.addObject(o); + } else { + i.remove(); + } + } + return result; + } + + /* + * public static void encodeObjectWithCoder ( Object anObject, NSCoder aCoder ) + * { throw new net.wotonomy.util.WotonomyException("Not implemented yet."); } + */ + + /** + * Returns the object for the specified id. If the object is registered in in + * this context but not in the specified context, this implementation will + * create a copy of the object and register it in the specified context. + * Otherwise it will forward the call to the parent object store. + */ + public /* EOEnterpriseObject */ Object faultForGlobalID(EOGlobalID aGlobalID, EOEditingContext aContext) { + Object result = registrar.objectForGlobalID(aGlobalID); + + // if not registered in our context + if (result == null) { + // get the object registered into our context + result = parentStore.faultForGlobalID(aGlobalID, this); + } + + // if our context is not the specified context + if (aContext != this) { + result = registerClone(aGlobalID, this, result, aContext); + } + + return result; + } + + /** + * Returns a fault representing an object of the specified entity type with + * values from the specified dictionary. This implementation calls + * faultForRawRow on the parent store. + */ + public Object faultForRawRow(Map aDictionary, String anEntityName) { + return parentStore.faultForRawRow(aDictionary, anEntityName, this); + } + + /** + * Returns a fault representing an object of the specified entity type with + * values from the specified dictionary. The fault should belong to the + * specified editing context. This implementation forwards the call to the + * parent store. + */ + public /* EOEnterpriseObject */ Object faultForRawRow(Map aDictionary, String anEntityName, + EOEditingContext aContext) { + return parentStore.faultForRawRow(aDictionary, anEntityName, aContext); + } + + /** + * Returns the fetch timestamp for this editing context. + */ + public double fetchTimestamp() { + return fetchTimestamp; + } + + /** + * Unregisters the specified object from this editing context, removing all + * references to it. Use this method to remove an object from the context + * without marking it for deletion. + */ + public void forgetObject(Object anObject) { + EOGlobalID id = registrar.globalIDForObject(anObject); + if (id == null) { + System.err.println("EOEditingContext.forgetObject: not registered: " + anObject); + return; + } + + // unregister object + registrar.forgetObject(anObject); + + // remove from all, inserted, updated, and deleted lists + int index; + index = updatedObjects.indexOfIdenticalObject(anObject); + if (index != NSArray.NotFound) { + updatedObjects.removeObjectAtIndex(index); + } + index = insertedObjects.indexOfIdenticalObject(anObject); + if (index != NSArray.NotFound) { + insertedObjects.removeObjectAtIndex(index); + return; + } + index = deletedObjects.indexOfIdenticalObject(anObject); + if (index != NSArray.NotFound) { + deletedObjects.removeObjectAtIndex(index); + return; + } + + // notify parent context + parentStore.editingContextDidForgetObjectWithGlobalID(this, id); + } + + /** + * Returns the id for the specified object, or null if the object is not + * registered in this context. + */ + public EOGlobalID globalIDForObject(Object anObject) { + return registrar.globalIDForObject(anObject); + } + + /** + * Returns an array of ids for an array of objects. + */ + private NSArray globalIDsForObjects(List anObjectList) { + NSMutableArray result = new NSMutableArray(); + Iterator it = anObjectList.iterator(); + while (it.hasNext()) { + result.add(globalIDForObject(it.next())); + } + return result; + } + + /** + * Returns whether this editing context has changes that have not yet been + * committed to the parent object store. + */ + public boolean hasChanges() { + if (updatedObjects.count() > 0) + return true; + if (insertedObjects.count() > 0) + return true; + if (deletedObjects.count() > 0) + return true; + return false; + } + + /** + * Given a newly instantiated object, this method initializes its properties to + * values appropriate for the specified id. The object should already belong to + * the specified editing context. This method is called to populate faults. This + * implementation will try to apply the values from an object with a matching id + * in this editing context if possible, calling to the parent object store only + * if such an object is not found. + */ + public void initializeObject(/* EOEnterpriseObject */ Object anObject, EOGlobalID aGlobalID, + EOEditingContext aContext) { + Object existingObject = registrar.objectForGlobalID(aGlobalID); + + // if not registered in our context + if (existingObject == null) { + // get the object registered into our context + existingObject = parentStore.faultForGlobalID(aGlobalID, this); + } + + if (aContext == this) { + // initialize the object + parentStore.initializeObject(/* (EOEnterpriseObject) */existingObject, aGlobalID, this); + } else // ( aContext != this ) + { + // translates child relationships + copy(this, existingObject, aContext, anObject); + } + + aContext.registrar.setCommitSnapshot(anObject, null); + aContext.registrar.setCurrentSnapshot(anObject, null); + } + + /** + * Inserts the specified object into this editing context. This implementation + * calls insertObjectWithGlobalID with an EOTemporaryGlobalID. + */ + public void insertObject(Object anObject) { + insertObjectWithGlobalID(anObject, new EOTemporaryGlobalID()); + } + + /** + * Inserts the specified object into this editing context with the specified id, + * which is expected to be a temporary id. + */ + public void insertObjectWithGlobalID(Object anObject, EOGlobalID aGlobalID) { + willChange(); + + // if this object was marked for deletion + int index = deletedObjects.indexOfIdenticalObject(anObject); + if (index != NSArray.NotFound) { + // don't need to re-register: just update the lists + + // remove from deleted list + deletedObjects.removeObjectAtIndex(index); + + // if in the deleted ids buffer + index = deletedIDsBuffer.indexOfIdenticalObject(anObject); + if (index != NSArray.NotFound) { + // remove from deleted ids buffer + deletedIDsBuffer.removeObjectAtIndex(index); + } + + // if in the deleted objects buffer + index = deletedObjectsBuffer.indexOfIdenticalObject(anObject); + if (index != NSArray.NotFound) { + // remove from deleted objects buffer + deletedObjectsBuffer.removeObjectAtIndex(index); + } else // not in the deleted objects buffer + { + // add to the inserted objects buffer + insertedObjectsBuffer.addObject(anObject); + } + + // we're done + return; + } + + // make sure object is not already in editing context + if (objectForGlobalID(aGlobalID) != null) { + throw new WotonomyException("Tried to insert but object was already registered:" + aGlobalID); + } + + // register object + recordObject(anObject, aGlobalID); + + // add to inserted list + insertedObjects.addObject(anObject); + // add to buffer + insertedObjectsBuffer.addObject(anObject); + } + + /** + * Returns a read-only List of the objects that have been inserted into this + * editing context. + */ + public NSArray insertedObjects() { + return insertedObjectsProxy; + } + + /** + * Turn all objects in this editing context into faults, so that they will be + * fetched the next time they are accessed, and calls + * invalidateObjectsWithGlobalIDs on the parent object store. + */ + public void invalidateAllObjects() { + // register change so processRecentChanges is called + willChange(); + + invalidateAllObjectsQuietly(); + + // post notification + NSNotificationCenter.defaultCenter() + .postNotification(new NSNotification(InvalidatedAllObjectsInStoreNotification, this)); + } + + /** + * Only refaults all objects, does not notify will change nor post notification, + * but does call parent store. Called by invalidateAllObjects() and + * handleNotification(). + */ + private void invalidateAllObjectsQuietly() { + // remember the ids + NSMutableArray ids = new NSMutableArray(registrar.registeredGlobalIDs()); + + // track of discarded IDs (from inserted objects) + NSMutableArray discardedIDs = new NSMutableArray(); + + // refault all objects + EOGlobalID id; + Object o; + Enumeration e = ids.objectEnumerator(); + while (e.hasMoreElements()) { + id = (EOGlobalID) e.nextElement(); + o = objectForGlobalID(id); + + // some objects may have been manually discarded + if (o != null) { + // don't refault newly inserted objects + if (insertedObjects.indexOfIdenticalObject(o) == NSArray.NotFound) { + refaultObject(o, id, this); + } else { + // discard inserted objects + forgetObject(o); + discardedIDs.add(id); + } + invalidatedObjectsBuffer.add(o); + } + invalidatedIDsBuffer.add(id); + } + ids.removeAll(discardedIDs); + + // call to parent store (should call this after posting instead?) + isInvalidating = true; + parentStore.invalidateObjectsWithGlobalIDs(ids); + isInvalidating = false; + } + + /** + * Turns the objects with the specified ids into faults, so that they will be + * fetched the next time they are accessed, and forwards the call to the parent + * object store. + */ + public void invalidateObjectsWithGlobalIDs(List anArray) { + // register change so processRecentChanges is called + willChange(); + + // call to parent to invalidate objects + parentStore.invalidateObjectsWithGlobalIDs(anArray); + + Object o; + EOGlobalID id; + Iterator it = anArray.iterator(); + while (it.hasNext()) { + id = (EOGlobalID) it.next(); + if (id != null) { + o = objectForGlobalID(id); + if (o != null) { + Object result = notifyDelegate("editingContextShouldInvalidateObject", + new Class[] { EOEditingContext.class, Object.class, EOGlobalID.class }, + new Object[] { this, o, id }); + if ((result == null) || (Boolean.TRUE.equals(result))) { + // refault the object + refaultObject(o, id, this); + invalidatedObjectsBuffer.add(o); + invalidatedIDsBuffer.add(id); + } + } + } else { + throw new WotonomyException("Attempted to invalidate a null global id: " + anArray); + } + } + + } + + /* + * public boolean invalidatesObjectsWhenFinalized ( ) { throw new + * net.wotonomy.util.WotonomyException("Not implemented yet."); } + * + * public boolean invalidatesObjectsWhenFreed ( ) { throw new + * net.wotonomy.util.WotonomyException("Not implemented yet."); } + */ + /** + * Returns whether the object referenced by the specified id is locked. This + * implementation simply forwards the call to the parent object store. + */ + public boolean isObjectLockedWithGlobalID(EOGlobalID aGlobalID, EOEditingContext aContext) { + return parentStore.isObjectLockedWithGlobalID(aGlobalID, aContext); + } + + /* + * public void lock () { throw new + * net.wotonomy.util.WotonomyException("Not implemented yet."); } + */ + /** + * Locks the specified object in this editing context by calling + * lockObjectWithGlobalID on the parent store. + */ + public void lockObject(Object anObject) { + parentStore.lockObjectWithGlobalID(globalIDForObject(anObject), this); + } + + /** + * Locks the object referenced by the specified id in the specified editing + * context. This implementation simply forwards the call to the parent object + * store. + */ + public void lockObjectWithGlobalID(EOGlobalID aGlobalID, EOEditingContext aContext) { + parentStore.lockObjectWithGlobalID(aGlobalID, aContext); + } + + /** + * Returns whether this editing context attempts to lock objects when they are + * first modified. + */ + public boolean locksObjectsBeforeFirstModification() { + return lockBeforeModify; + } + + /** + * Returns the message handler for this editing context, or null if no message + * handler has been set. + */ + public Object messageHandler() { + if (messageHandler == null) + return null; + return messageHandler.get(); + } + + /** + * Returns the object registered in this editing context for the specified id, + * or null if that id is not registered. + */ + public Object objectForGlobalID(EOGlobalID aGlobalID) { + return registrar.objectForGlobalID(aGlobalID); + } + + /** + * Returns a read-only List of objects associated with the object with the + * specified id for the specified property relationship. This method may not + * return an array fault because array faults call this method to fetch on + * demand. All objects must be registered the specified editing context. The + * specified relationship key must produce a result of type Collection for the + * source object or an exception is thrown. + */ + public NSArray objectsForSourceGlobalID(EOGlobalID aGlobalID, String aRelationshipKey, EOEditingContext aContext) { //System.out.println( "EOEditingContext.objectsForSourceGlobalID: " //+ aGlobalID + " : " + aRelationshipKey ); - - NSArray result = null; - -if ( aContext == this ) -{ - throw new WotonomyException( "Assert failed: calling objectsForSourceGlobalID on ourself." ); -} - Object source = registrar.objectForGlobalID( aGlobalID ); - - // if not registered in our context - if ( source == null ) - { - // get the object registered into our context - result = parentStore.objectsForSourceGlobalID( - aGlobalID, aRelationshipKey, this ); - } - else // source is registered in our context - { - // get existing value - Object value; - if ( source instanceof EOKeyValueCoding ) - { - value = ((EOKeyValueCoding)source).storedValueForKey( - aRelationshipKey ); - } - else // handle directly - { - value = EOKeyValueCodingSupport.storedValueForKey( - source, aRelationshipKey ); - } - - // if we don't have a valid value on our object - if ( ( value == null ) - || ( ( value instanceof ArrayFault ) - && ( !((ArrayFault)value).isFetched() ) ) ) - { - // do the same as if the source was null - result = parentStore.objectsForSourceGlobalID( - aGlobalID, aRelationshipKey, this ); - - // set our value since we have it - if ( source instanceof EOKeyValueCoding ) - { - ((EOKeyValueCoding)source).takeStoredValueForKey( - result, aRelationshipKey ); - } - else // handle directly - { - EOKeyValueCodingSupport.takeStoredValueForKey( - source, result, aRelationshipKey ); - } - } - else - if ( ( value instanceof ArrayFault ) - && ( !((ArrayFault)value).isFetched() ) ) - { - // do the same as if the source was null - result = parentStore.objectsForSourceGlobalID( - aGlobalID, aRelationshipKey, this ); - } - else - if ( value instanceof NSArray ) - { - result = (NSArray) value; - } - else // not NSArray - if ( value instanceof Collection ) - { - // convert to NSArray - result = new NSArray( (Collection) value ); - } - else - { - throw new WotonomyException( - "Relationship key did not return a collection: " - + aGlobalID + " : " + aRelationshipKey ); - } - } - - // if our context is not the specified context - if ( aContext != this ) - { - result = (NSArray) clone( this, result, aContext ); - } - - return result; - } - - /** - * Returns a read-only List of objects the meet the criteria of - * the supplied specification. This method simply calls - * objectsWithFetchSpecification on this editing context - * with this editing context as the parameter. - */ - public NSArray objectsWithFetchSpecification ( - EOFetchSpecification aFetchSpec ) - { - return objectsWithFetchSpecification( aFetchSpec, this ); - } - - /** - * Returns a read-only List of objects the meet the criteria of - * the supplied specification. Faults are not allowed in the array. - * If any objects are already fetched, they should not be - * refetched. All objects should belong to the specified editing context. - * This implementation forwards the call to the parent object - * store, which will register each object in the specified editing - * context only if it does not already exist. - */ - public NSArray objectsWithFetchSpecification ( - EOFetchSpecification aFetchSpec, - EOEditingContext aContext) - { - if ( aContext == this ) - { - Object result = notifyDelegate( - "editingContextShouldFetchObjects", - new Class[] { EOEditingContext.class, EOFetchSpecification.class }, - new Object[] { aContext, aFetchSpec } ); - if ( result instanceof NSArray ) return (NSArray) result; - } - return parentStore.objectsWithFetchSpecification( aFetchSpec, aContext ); - } - - /** - * Returns the parent object store for this editing context. - * The result will not be null. - */ - public EOObjectStore parentObjectStore () - { - return parentStore; - } - - /** - * Updates the inserted, updated, and deleted objects lists, - * and posts notifications about which objects have been changed. - * This method is called at the end of an event loop in which - * objects were modified. This method is additionally called - * by saveChanges() so that any changes in the same event loop - * will be processed correctly before calling to the parent - * object store. - * This implementation updates those lists immediately, but - * only posts notifications when this method is called. - */ - public void processRecentChanges () - { // System.out.println( "EOEditingContext.processRecentChanges: " + invalidatedObjectsBuffer ); - - /* - * This implementation actually updates those lists immediately, - * but keeps a separate buffer of changes in the current event - * loop for the purposes of posting a notification. - * NOTE: to reenable buffering, uncomment lines from this method - * body and reenable the RecentChangesObserver in the constructor. - */ - - // broadcast ObjectsChangedInStoreNotification - // for the benefit of child editing contexts - - boolean postStoreInfo = - ( insertedObjectsBuffer.size() + - updatedObjectsBuffer.size() + - deletedIDsBuffer.size() + - invalidatedIDsBuffer.size() > 0 ); - - NSMutableDictionary storeInfo = new NSMutableDictionary(); - if ( postStoreInfo ) - { - storeInfo.setObjectForKey( - globalIDsForObjects( insertedObjectsBuffer ), - // globalIDsForObjects( insertedObjects ), - EOObjectStore.InsertedKey ); - storeInfo.setObjectForKey( - globalIDsForObjects( updatedObjectsBuffer ), - // globalIDsForObjects( updatedObjects ), - EOObjectStore.UpdatedKey ); - storeInfo.setObjectForKey( - new NSArray( (Collection) deletedIDsBuffer ), - // globalIDsForObjects( deletedObjects ), - EOObjectStore.DeletedKey ); - storeInfo.setObjectForKey( - new NSArray( (Collection) invalidatedIDsBuffer ), - EOObjectStore.InvalidatedKey ); - } - - // broadcast ObjectsChangedInEditingContextNotification - // for the benefit of attached display groups - - boolean postContextInfo = - ( insertedObjectsBuffer.size() + - updatedObjectsBuffer.size() + - deletedObjectsBuffer.size() + - invalidatedObjectsBuffer.size() > 0 ); - - NSMutableDictionary contextInfo = new NSMutableDictionary(); - - if ( postContextInfo ) - { - - contextInfo.setObjectForKey( - new NSArray( (Collection) insertedObjectsBuffer ), - // new NSArray( (Collection) insertedObjects ), - EOObjectStore.InsertedKey ); - contextInfo.setObjectForKey( - new NSArray( (Collection) updatedObjectsBuffer ), - // new NSArray( (Collection) updatedObjects ), - EOObjectStore.UpdatedKey ); - contextInfo.setObjectForKey( - new NSArray( (Collection) deletedObjectsBuffer ), - // new NSArray( (Collection) deletedObjects ), - EOObjectStore.DeletedKey ); - contextInfo.setObjectForKey( - new NSArray( (Collection) invalidatedObjectsBuffer ), - EOObjectStore.InvalidatedKey ); - } - - // update the current snapshots - - Object o; - Iterator it; - it = insertedObjectsBuffer.iterator(); - while ( it.hasNext() ) - { - o = it.next(); - registrar.setCurrentSnapshot( o, takeSnapshot( o ) ); - } - it = updatedObjectsBuffer.iterator(); - while ( it.hasNext() ) - { - o = it.next(); - registrar.setCurrentSnapshot( o, takeSnapshot( o ) ); - } - - // clear buffers - - insertedObjectsBuffer.removeAllObjects(); - updatedObjectsBuffer.removeAllObjects(); - deletedObjectsBuffer.removeAllObjects(); - deletedIDsBuffer.removeAllObjects(); - invalidatedObjectsBuffer.removeAllObjects(); - invalidatedIDsBuffer.removeAllObjects(); - - // post notifications (does order matter?) - - if ( postStoreInfo ) - { - NSNotificationCenter.defaultCenter().postNotification( - new NSNotification( - ObjectsChangedInStoreNotification, this, storeInfo ) ); - } - - if ( postContextInfo ) - { - NSNotificationCenter.defaultCenter().postNotification( - new NSNotification( - ObjectsChangedInEditingContextNotification, this, contextInfo ) ); - } - - } - - /** - * Returns whether this editing context propagates deletes - * immediately after the event that triggered the delete. - * Otherwise, propagation occurs only before commit. - */ - public boolean propagatesDeletesAtEndOfEvent () - { - return propagateDeletesAfterEvent; - } - - /** - * Registers the specified object in this editing context - * for the specified id. This method is called by an object - * store when fetching objects for a display group, or when - * objects are inserted into a display group. - * This implementation will re-register the object under the - * new id if it is already registered under a different id. - */ - public void recordObject ( - Object anObject, - EOGlobalID aGlobalID ) - { - // find state for re-registration - boolean inserted = false; - boolean updated = false; - boolean deleted = false; - - // is the object already registered? - EOGlobalID existingID = globalIDForObject( anObject ); - if ( existingID != null ) - { - // remember object state - int index; - index = insertedObjects.indexOfIdenticalObject( anObject ); - if ( index != NSArray.NotFound ) inserted = true; - index = updatedObjects.indexOfIdenticalObject( anObject ); - if ( index != NSArray.NotFound ) updated = true; - index = deletedObjects.indexOfIdenticalObject( anObject ); - if ( index != NSArray.NotFound ) deleted = true; - // forget the object - forgetObject( anObject ); - } - - // is the global id already in use? - Object existingObject = objectForGlobalID( aGlobalID ); - if ( existingObject != null ) - { - // forget it (don't worry about state?) - forgetObject( existingObject ); - } - - registrar.registerObject( anObject, aGlobalID ); - - // restore state if necessary - if ( inserted ) insertedObjects.addObject( anObject ); - if ( updated ) updatedObjects.addObject( anObject ); - if ( deleted ) deletedObjects.addObject( anObject ); - } - - /** - * Undoes the last undo operation. - */ - public void redo () - { - //TODO: not supported yet - throw new UnsupportedOperationException("Not implemented yet."); - } - - /** - * Refaults this editing context, turning all unmodified - * objects into faults. This implementation calls - * editingContextWillSaveChanges() on all editors, and - * then calls refaultObjects(). - */ - public void refault () - { - fireWillSaveChanges(); - refaultObjects(); - } - - /** - * Refaults the specified object, turning it into a fault - * for the specified global id in the specified context. - */ - public void refaultObject ( - Object anObject, - EOGlobalID aGlobalID, - EOEditingContext aContext) - { - aContext.registrar.setCurrentSnapshot( anObject, null ); - - ignoreChanges = true; - parentStore.refaultObject( anObject, aGlobalID, aContext ); - ignoreChanges = false; - + + NSArray result = null; + + if (aContext == this) { + throw new WotonomyException("Assert failed: calling objectsForSourceGlobalID on ourself."); + } + Object source = registrar.objectForGlobalID(aGlobalID); + + // if not registered in our context + if (source == null) { + // get the object registered into our context + result = parentStore.objectsForSourceGlobalID(aGlobalID, aRelationshipKey, this); + } else // source is registered in our context + { + // get existing value + Object value; + if (source instanceof EOKeyValueCoding) { + value = ((EOKeyValueCoding) source).storedValueForKey(aRelationshipKey); + } else // handle directly + { + value = EOKeyValueCodingSupport.storedValueForKey(source, aRelationshipKey); + } + + // if we don't have a valid value on our object + if ((value == null) || ((value instanceof ArrayFault) && (!((ArrayFault) value).isFetched()))) { + // do the same as if the source was null + result = parentStore.objectsForSourceGlobalID(aGlobalID, aRelationshipKey, this); + + // set our value since we have it + if (source instanceof EOKeyValueCoding) { + ((EOKeyValueCoding) source).takeStoredValueForKey(result, aRelationshipKey); + } else // handle directly + { + EOKeyValueCodingSupport.takeStoredValueForKey(source, result, aRelationshipKey); + } + } else if ((value instanceof ArrayFault) && (!((ArrayFault) value).isFetched())) { + // do the same as if the source was null + result = parentStore.objectsForSourceGlobalID(aGlobalID, aRelationshipKey, this); + } else if (value instanceof NSArray) { + result = (NSArray) value; + } else // not NSArray + if (value instanceof Collection) { + // convert to NSArray + result = new NSArray((Collection) value); + } else { + throw new WotonomyException( + "Relationship key did not return a collection: " + aGlobalID + " : " + aRelationshipKey); + } + } + + // if our context is not the specified context + if (aContext != this) { + result = (NSArray) clone(this, result, aContext); + } + + return result; + } + + /** + * Returns a read-only List of objects the meet the criteria of the supplied + * specification. This method simply calls objectsWithFetchSpecification on this + * editing context with this editing context as the parameter. + */ + public NSArray objectsWithFetchSpecification(EOFetchSpecification aFetchSpec) { + return objectsWithFetchSpecification(aFetchSpec, this); + } + + /** + * Returns a read-only List of objects the meet the criteria of the supplied + * specification. Faults are not allowed in the array. If any objects are + * already fetched, they should not be refetched. All objects should belong to + * the specified editing context. This implementation forwards the call to the + * parent object store, which will register each object in the specified editing + * context only if it does not already exist. + */ + public NSArray objectsWithFetchSpecification(EOFetchSpecification aFetchSpec, EOEditingContext aContext) { + if (aContext == this) { + Object result = notifyDelegate("editingContextShouldFetchObjects", + new Class[] { EOEditingContext.class, EOFetchSpecification.class }, + new Object[] { aContext, aFetchSpec }); + if (result instanceof NSArray) + return (NSArray) result; + } + return parentStore.objectsWithFetchSpecification(aFetchSpec, aContext); + } + + /** + * Returns the parent object store for this editing context. The result will not + * be null. + */ + public EOObjectStore parentObjectStore() { + return parentStore; + } + + /** + * Updates the inserted, updated, and deleted objects lists, and posts + * notifications about which objects have been changed. This method is called at + * the end of an event loop in which objects were modified. This method is + * additionally called by saveChanges() so that any changes in the same event + * loop will be processed correctly before calling to the parent object store. + * This implementation updates those lists immediately, but only posts + * notifications when this method is called. + */ + public void processRecentChanges() { // System.out.println( "EOEditingContext.processRecentChanges: " + + // invalidatedObjectsBuffer ); + + /* + * This implementation actually updates those lists immediately, but keeps a + * separate buffer of changes in the current event loop for the purposes of + * posting a notification. NOTE: to reenable buffering, uncomment lines from + * this method body and reenable the RecentChangesObserver in the constructor. + */ + + // broadcast ObjectsChangedInStoreNotification + // for the benefit of child editing contexts + + boolean postStoreInfo = (insertedObjectsBuffer.size() + updatedObjectsBuffer.size() + deletedIDsBuffer.size() + + invalidatedIDsBuffer.size() > 0); + + NSMutableDictionary storeInfo = new NSMutableDictionary(); + if (postStoreInfo) { + storeInfo.setObjectForKey(globalIDsForObjects(insertedObjectsBuffer), + // globalIDsForObjects( insertedObjects ), + EOObjectStore.InsertedKey); + storeInfo.setObjectForKey(globalIDsForObjects(updatedObjectsBuffer), + // globalIDsForObjects( updatedObjects ), + EOObjectStore.UpdatedKey); + storeInfo.setObjectForKey(new NSArray((Collection) deletedIDsBuffer), + // globalIDsForObjects( deletedObjects ), + EOObjectStore.DeletedKey); + storeInfo.setObjectForKey(new NSArray((Collection) invalidatedIDsBuffer), EOObjectStore.InvalidatedKey); + } + + // broadcast ObjectsChangedInEditingContextNotification + // for the benefit of attached display groups + + boolean postContextInfo = (insertedObjectsBuffer.size() + updatedObjectsBuffer.size() + + deletedObjectsBuffer.size() + invalidatedObjectsBuffer.size() > 0); + + NSMutableDictionary contextInfo = new NSMutableDictionary(); + + if (postContextInfo) { + + contextInfo.setObjectForKey(new NSArray((Collection) insertedObjectsBuffer), + // new NSArray( (Collection) insertedObjects ), + EOObjectStore.InsertedKey); + contextInfo.setObjectForKey(new NSArray((Collection) updatedObjectsBuffer), + // new NSArray( (Collection) updatedObjects ), + EOObjectStore.UpdatedKey); + contextInfo.setObjectForKey(new NSArray((Collection) deletedObjectsBuffer), + // new NSArray( (Collection) deletedObjects ), + EOObjectStore.DeletedKey); + contextInfo.setObjectForKey(new NSArray((Collection) invalidatedObjectsBuffer), + EOObjectStore.InvalidatedKey); + } + + // update the current snapshots + + Object o; + Iterator it; + it = insertedObjectsBuffer.iterator(); + while (it.hasNext()) { + o = it.next(); + registrar.setCurrentSnapshot(o, takeSnapshot(o)); + } + it = updatedObjectsBuffer.iterator(); + while (it.hasNext()) { + o = it.next(); + registrar.setCurrentSnapshot(o, takeSnapshot(o)); + } + + // clear buffers + + insertedObjectsBuffer.removeAllObjects(); + updatedObjectsBuffer.removeAllObjects(); + deletedObjectsBuffer.removeAllObjects(); + deletedIDsBuffer.removeAllObjects(); + invalidatedObjectsBuffer.removeAllObjects(); + invalidatedIDsBuffer.removeAllObjects(); + + // post notifications (does order matter?) + + if (postStoreInfo) { + NSNotificationCenter.defaultCenter() + .postNotification(new NSNotification(ObjectsChangedInStoreNotification, this, storeInfo)); + } + + if (postContextInfo) { + NSNotificationCenter.defaultCenter().postNotification( + new NSNotification(ObjectsChangedInEditingContextNotification, this, contextInfo)); + } + + } + + /** + * Returns whether this editing context propagates deletes immediately after the + * event that triggered the delete. Otherwise, propagation occurs only before + * commit. + */ + public boolean propagatesDeletesAtEndOfEvent() { + return propagateDeletesAfterEvent; + } + + /** + * Registers the specified object in this editing context for the specified id. + * This method is called by an object store when fetching objects for a display + * group, or when objects are inserted into a display group. This implementation + * will re-register the object under the new id if it is already registered + * under a different id. + */ + public void recordObject(Object anObject, EOGlobalID aGlobalID) { + // find state for re-registration + boolean inserted = false; + boolean updated = false; + boolean deleted = false; + + // is the object already registered? + EOGlobalID existingID = globalIDForObject(anObject); + if (existingID != null) { + // remember object state + int index; + index = insertedObjects.indexOfIdenticalObject(anObject); + if (index != NSArray.NotFound) + inserted = true; + index = updatedObjects.indexOfIdenticalObject(anObject); + if (index != NSArray.NotFound) + updated = true; + index = deletedObjects.indexOfIdenticalObject(anObject); + if (index != NSArray.NotFound) + deleted = true; + // forget the object + forgetObject(anObject); + } + + // is the global id already in use? + Object existingObject = objectForGlobalID(aGlobalID); + if (existingObject != null) { + // forget it (don't worry about state?) + forgetObject(existingObject); + } + + registrar.registerObject(anObject, aGlobalID); + + // restore state if necessary + if (inserted) + insertedObjects.addObject(anObject); + if (updated) + updatedObjects.addObject(anObject); + if (deleted) + deletedObjects.addObject(anObject); + } + + /** + * Undoes the last undo operation. + */ + public void redo() { + // TODO: not supported yet + throw new UnsupportedOperationException("Not implemented yet."); + } + + /** + * Refaults this editing context, turning all unmodified objects into faults. + * This implementation calls editingContextWillSaveChanges() on all editors, and + * then calls refaultObjects(). + */ + public void refault() { + fireWillSaveChanges(); + refaultObjects(); + } + + /** + * Refaults the specified object, turning it into a fault for the specified + * global id in the specified context. + */ + public void refaultObject(Object anObject, EOGlobalID aGlobalID, EOEditingContext aContext) { + aContext.registrar.setCurrentSnapshot(anObject, null); + + ignoreChanges = true; + parentStore.refaultObject(anObject, aGlobalID, aContext); + ignoreChanges = false; + // remove from updated objects if necessary - int i = updatedObjects.indexOfIdenticalObject( anObject ); - if ( i != NSArray.NotFound ) - { - updatedObjects.removeObjectAtIndex( i ); - } - - // add to invalidated notification queue - invalidatedObjectsBuffer.addObject( anObject ); - invalidatedIDsBuffer.addObject( aGlobalID ); - } - - /** - * Turns all unmodified objects into faults, calling - * processRecentChanges() and then refaultObject() for - * each unmodified object. - */ - public void refaultObjects () - { - // is this call really needed? - // processRecentChanges(); - - Object o; - EOGlobalID id; - Iterator it = registeredObjects().iterator(); - while ( it.hasNext() ) - { - o = it.next(); - if ( ( updatedObjects.indexOfIdenticalObject( o ) == NSArray.NotFound ) - && ( insertedObjects.indexOfIdenticalObject( o ) == NSArray.NotFound ) - && ( deletedObjects.indexOfIdenticalObject( o ) == NSArray.NotFound ) ) - { - id = globalIDForObject( o ); - refaultObject( o, id, this ); - } - } - } - - /** - * Calls editingContextWillSaveChanges() on all editors, - * and then calls invalidateAllObjects(). - */ - public void refetch () - { - fireWillSaveChanges(); - invalidateAllObjects(); - } - - /** - * Returns a read-only List of all objects registered in this - * editing context. - */ - public NSArray registeredObjects () - { - return registrar.registeredObjects(); - } - - /** - * Unregisters the specified editor with this editing context. - */ - public void removeEditor ( Object anObject ) - { - if ( anObject == null ) return; - - Object o; - Iterator i = editorSet.iterator(); - while ( i.hasNext() ) - { - o = ((WeakReference)i.next()).get(); - if ( ( o == null ) || ( o == anObject ) ) - { - i.remove(); - } - } - } - - /** - * Unregisters all objects from this editing context, - * and resets the fetch timestamp. - */ - public void reset () - { - Iterator it = registeredObjects().iterator(); - while ( it.hasNext() ) - { - forgetObject( it.next() ); - } - fetchTimestamp = 0; //FIXME: reset timestamp properly - } - - /** - * Reverts the objects in this editing context to - * their original state. - * Calls editingContextWillSaveChanges on all editors, - * discards all inserted objects, restores deleted - * objects, and applies the fetch snapshot to all - * registered objects. - */ - public void revert () - { - willChange(); - fireWillSaveChanges(); - - Iterator it; - - // forget inserted objects - it = new NSArray( insertedObjects ).iterator(); - while ( it.hasNext() ) - { - forgetObject( it.next() ); - } - - EOGlobalID id; - Object o; - byte[] snapshot; - - // re-initialize updated objects - it = new NSArray( updatedObjects ).iterator(); - while ( it.hasNext() ) - { - o = it.next(); - snapshot = (byte[]) registrar.getCommitSnapshot( o ); - if ( snapshot != null ) - { - applySnapshot( snapshot, o ); - } - registrar.setCommitSnapshot( o, null ); - updatedObjectsBuffer.addObject( o ); - } - - // re-initialize deleted objects - it = new NSArray( deletedObjects ).iterator(); - while ( it.hasNext() ) - { - o = it.next(); - snapshot = (byte[]) registrar.getCommitSnapshot( o ); - if ( snapshot != null ) - { - applySnapshot( snapshot, o ); - } - registrar.setCommitSnapshot( o, null ); - updatedObjectsBuffer.addObject( o ); - } - - // reset lists - insertedObjects.removeAllObjects(); // unneccessary? - deletedObjects.removeAllObjects(); - updatedObjects.removeAllObjects(); - - // post notification - processRecentChanges(); - } - - /** - * Returns the root object store, which is the parent - * of all parent object stores of this editing context. - */ - public EOObjectStore rootObjectStore () - { - EOObjectStore parent = parentObjectStore(); - while ( parent instanceof EOEditingContext ) - { - parent = ((EOEditingContext)parent).parentObjectStore(); - } - return parent; - } - - /** - * Calls editingContextWillSaveChanges on all editors, - * and commits all changes in this editing context to - * the parent editing context by calling - * saveChangesInEditingContext to the parent. - * Then posts EditingContextDidSaveChangeNotification. - */ - public void saveChanges () - { + int i = updatedObjects.indexOfIdenticalObject(anObject); + if (i != NSArray.NotFound) { + updatedObjects.removeObjectAtIndex(i); + } + + // add to invalidated notification queue + invalidatedObjectsBuffer.addObject(anObject); + invalidatedIDsBuffer.addObject(aGlobalID); + } + + /** + * Turns all unmodified objects into faults, calling processRecentChanges() and + * then refaultObject() for each unmodified object. + */ + public void refaultObjects() { + // is this call really needed? + // processRecentChanges(); + + Object o; + EOGlobalID id; + Iterator it = registeredObjects().iterator(); + while (it.hasNext()) { + o = it.next(); + if ((updatedObjects.indexOfIdenticalObject(o) == NSArray.NotFound) + && (insertedObjects.indexOfIdenticalObject(o) == NSArray.NotFound) + && (deletedObjects.indexOfIdenticalObject(o) == NSArray.NotFound)) { + id = globalIDForObject(o); + refaultObject(o, id, this); + } + } + } + + /** + * Calls editingContextWillSaveChanges() on all editors, and then calls + * invalidateAllObjects(). + */ + public void refetch() { + fireWillSaveChanges(); + invalidateAllObjects(); + } + + /** + * Returns a read-only List of all objects registered in this editing context. + */ + public NSArray registeredObjects() { + return registrar.registeredObjects(); + } + + /** + * Unregisters the specified editor with this editing context. + */ + public void removeEditor(Object anObject) { + if (anObject == null) + return; + + Object o; + Iterator i = editorSet.iterator(); + while (i.hasNext()) { + o = ((WeakReference) i.next()).get(); + if ((o == null) || (o == anObject)) { + i.remove(); + } + } + } + + /** + * Unregisters all objects from this editing context, and resets the fetch + * timestamp. + */ + public void reset() { + Iterator it = registeredObjects().iterator(); + while (it.hasNext()) { + forgetObject(it.next()); + } + fetchTimestamp = 0; // FIXME: reset timestamp properly + } + + /** + * Reverts the objects in this editing context to their original state. Calls + * editingContextWillSaveChanges on all editors, discards all inserted objects, + * restores deleted objects, and applies the fetch snapshot to all registered + * objects. + */ + public void revert() { + willChange(); + fireWillSaveChanges(); + + Iterator it; + + // forget inserted objects + it = new NSArray(insertedObjects).iterator(); + while (it.hasNext()) { + forgetObject(it.next()); + } + + EOGlobalID id; + Object o; + byte[] snapshot; + + // re-initialize updated objects + it = new NSArray(updatedObjects).iterator(); + while (it.hasNext()) { + o = it.next(); + snapshot = (byte[]) registrar.getCommitSnapshot(o); + if (snapshot != null) { + applySnapshot(snapshot, o); + } + registrar.setCommitSnapshot(o, null); + updatedObjectsBuffer.addObject(o); + } + + // re-initialize deleted objects + it = new NSArray(deletedObjects).iterator(); + while (it.hasNext()) { + o = it.next(); + snapshot = (byte[]) registrar.getCommitSnapshot(o); + if (snapshot != null) { + applySnapshot(snapshot, o); + } + registrar.setCommitSnapshot(o, null); + updatedObjectsBuffer.addObject(o); + } + + // reset lists + insertedObjects.removeAllObjects(); // unneccessary? + deletedObjects.removeAllObjects(); + updatedObjects.removeAllObjects(); + + // post notification + processRecentChanges(); + } + + /** + * Returns the root object store, which is the parent of all parent object + * stores of this editing context. + */ + public EOObjectStore rootObjectStore() { + EOObjectStore parent = parentObjectStore(); + while (parent instanceof EOEditingContext) { + parent = ((EOEditingContext) parent).parentObjectStore(); + } + return parent; + } + + /** + * Calls editingContextWillSaveChanges on all editors, and commits all changes + * in this editing context to the parent editing context by calling + * saveChangesInEditingContext to the parent. Then posts + * EditingContextDidSaveChangeNotification. + */ + public void saveChanges() { //System.out.println( "EOEditingContext.saveChanges: " + this ); - willChange(); - - // process any changes - processRecentChanges(); - - // set up user info for notification to be posted. - NSMutableDictionary userInfo = new NSMutableDictionary(); - userInfo.setObjectForKey( - new NSArray( (Collection) insertedObjects ), - EOObjectStore.InsertedKey ); - userInfo.setObjectForKey( - new NSArray( (Collection) updatedObjects ), - EOObjectStore.UpdatedKey ); - userInfo.setObjectForKey( - new NSArray( (Collection) deletedObjects ), - EOObjectStore.DeletedKey ); - - // notify the editors - fireWillSaveChanges(); - - // notify the delegate - notifyDelegate( - "editingContextWillSaveChanges", - new Class[] { EOEditingContext.class }, - new Object[] { this } ); - - // needed for notification handling - isInvalidating = true; - try - { - // ask parent to save us - parentStore.saveChangesInEditingContext( this ); - } - catch ( RuntimeException e ) - { - // unset save flag and rethrow - isInvalidating = false; - throw e; - } - isInvalidating = false; - - // no exceptions: proceed! - - Object o, key; - Iterator it; - - // update the committed snapshots - it = insertedObjects.iterator(); - while ( it.hasNext() ) - { - o = it.next(); - registrar.setCommitSnapshot( o, null ); - registrar.setCurrentSnapshot( o, null ); - } - it = updatedObjects.iterator(); - while ( it.hasNext() ) - { - o = it.next(); - registrar.setCommitSnapshot( o, null ); - registrar.setCurrentSnapshot( o, null ); - } - - // clear the lists - updatedObjects.removeAllObjects(); - insertedObjects.removeAllObjects(); - it = new NSArray( deletedObjects() ).iterator(); - while ( it.hasNext() ) - { // parent is doing this as well? - forgetObject( it.next() ); - } - - // post notification - NSNotificationCenter.defaultCenter().postNotification( - new NSNotification( - EditingContextDidSaveChangesNotification, this, userInfo ) ); - } - - /** - * Commits all changes in the specified editing context - * to this one. Called by child editing contexts in - * their saveChanges() method. - */ - public void saveChangesInEditingContext ( - EOEditingContext aContext) - { - Object o; - Iterator it; - - // process deletes - List deletes = new NSArray( aContext.deletedObjects() ); - it = deletes.iterator(); - while ( it.hasNext() ) - { - o = it.next(); - EOGlobalID id = aContext.globalIDForObject( o ); - Object localVersion = objectForGlobalID( id ); - if ( localVersion == null ) - { - // make a local copy and register it - localVersion = registerClone( id, aContext, o, this ); - if ( localVersion == null ) - { - throw new WotonomyException( - "Deleted object could not be serialized: " - + id + " : " + o ); - } - } - else // we have a local version, copy changes - { - copy( aContext, o, this, localVersion ); - // copy marks the object as updated: will be on both lists - } - // delete our copy -- marks context as changed - deleteObject( localVersion ); - } - - // process inserts - all inserts are new objects - List inserts = new NSArray( aContext.insertedObjects() ); - it = inserts.iterator(); - while ( it.hasNext() ) - { - o = it.next(); - // make a local copy and register it - EOGlobalID id = aContext.globalIDForObject( o ); - willChange(); // need to mark editing context as changed - Object localVersion = registerClone( id, aContext, o, this ); - if ( localVersion == null ) - { - throw new WotonomyException( - "Inserted object could not be serialized: " - + o ); - } - // insert our copy manually so a new id is not generated - insertedObjects.addObject( localVersion ); - insertedObjectsBuffer.addObject( localVersion ); - } - - // process updates - List updates = new NSArray( aContext.updatedObjects() ); - it = updates.iterator(); - while ( it.hasNext() ) - { - willChange(); // need to mark editing context as changed - o = it.next(); - EOGlobalID id = aContext.globalIDForObject( o ); - Object localVersion = objectForGlobalID( id ); - if ( localVersion == null ) - { - // make a local copy and register it - localVersion = registerClone( id, aContext, o, this ); - if ( localVersion == null ) - { - throw new WotonomyException( - "Updated object could not be serialized: " - + id + " : " + o ); - } - if ( id.isTemporary() ) - { - // mark this object as inserted - insertedObjects.addObject( localVersion ); - insertedObjectsBuffer.addObject( localVersion ); - } - else - { - // mark this object as updated - updatedObjects.addObject( localVersion ); - - // notify of update only if not on deleted list - if ( deletedObjectsBuffer.indexOfIdenticalObject( - localVersion ) == NSArray.NotFound ) - { - updatedObjectsBuffer.addObject( localVersion ); - } - } - } - else // we have a local version, copy changes - { - copy( aContext, o, this, localVersion ); - // copy marks the object as updated - } - } - - } - - /** - * Sets the delegate for this editing context. - * Note: this implementation retains only a - * weak reference to the specified object. - */ - public void setDelegate ( - Object anObject ) - { - if ( anObject == null ) delegate = null; - delegate = new WeakReference( anObject ); - } - - /** - * Sets the fetch timestamp for this editing context. - */ - public void setFetchTimestamp ( - double aDouble ) - { - fetchTimestamp = aDouble; - } -/* - public void setInvalidatesObjectsWhenFinalized ( - boolean invalidatesObjects ) - { - throw new net.wotonomy.util.WotonomyException("Not implemented yet."); - } - - public void setInvalidatesObjectsWhenFreed ( - boolean invalidatesObjects ) - { - throw new net.wotonomy.util.WotonomyException("Not implemented yet."); - } -*/ - /** - * Sets whether this editing context attempts to - * lock objects when they are first modified. - * Default is false. - */ - public void setLocksObjectsBeforeFirstModification ( - boolean locksObjects ) - { - lockBeforeModify = locksObjects; - } - - /** - * Sets the message handler for this editing context. - * Note: this implementation retains only a - * weak reference to the specified object. - */ - public void setMessageHandler ( - Object anObject ) - { - if ( anObject == null ) messageHandler = null; - messageHandler = new WeakReference( anObject ); - } - - /** - * Sets whether this editing context propagates deletes - * immediately after the event that triggered the delete. - * Otherwise, propagation occurs only before commit. - * Default is true. - */ - public void setPropagatesDeletesAtEndOfEvent ( - boolean propagatesDeletes ) - { - propagateDeletesAfterEvent = propagatesDeletes; - } -/* - public void setSharedEditingContext ( - EOSharedEditingContext aSharedEditingContext ) - { - throw new net.wotonomy.util.WotonomyException("Not implemented yet."); - } -*/ - /** - * Sets whether validation is stopped after the - * first error occurs. Otherwise, validation will - * continue for all other objects. - * Default is true. - */ - public void setStopsValidationAfterFirstError ( - boolean stopsValidation ) - { - stopValidationAfterError = stopsValidation; - } - - /** - * Sets the undo manager to be used for this context. - * Note: This is currently javax.swing.undo.UndoManager, - * until we have a implementation of NSUndoManager. - */ -/* - public void setUndoManager ( - UndoManager anUndoManager ) - { - undoManager = anUndoManager; - } -*/ -/* - public EOSharedEditingContext sharedEditingContext () - { - throw new net.wotonomy.util.WotonomyException("Not implemented yet."); - } -*/ - /** - * Returns whether validation is stopped after the - * first error occurs. Otherwise, validation will - * continue for all other objects. - */ - public boolean stopsValidationAfterFirstError () - { - return stopValidationAfterError; - } - - /** - * Reverts the last change on the undo stack. - */ - public void undo () - { - //TODO: not supported yet - throw new UnsupportedOperationException("Not implemented yet."); - } -/* - public NSUndoManager undoManager () - { - throw new net.wotonomy.util.WotonomyException("Not implemented yet."); - } -*/ -/** - public void unlock () - { - throw new net.wotonomy.util.WotonomyException("Not implemented yet."); - } -*/ - /** - * Returns a read-only list of all objects marked as modified, - * but not inserted or deleted, in this editing context. - */ - public NSArray updatedObjects () - { - return updatedObjectsProxy; - } - - /** - * Notify editors of changes. - */ - private void fireWillSaveChanges() - { - Object o = null; - Iterator i = editors().iterator(); - while ( i.hasNext() ) - { - try - { - o = i.next(); - NSSelector.invoke( "editingContextWillSaveChanges", - new Class[] { EOEditingContext.class }, o, this ); - } - catch ( NoSuchMethodException e ) - { - // ignore: not implemented - } - catch ( Exception exc ) - { - // log to standard error - System.err.println( "Error while notifying editor of pending save: " + o ); - exc.printStackTrace(); - } - } - } - - /** - * Handles notifications from parent store, looking for - * InvalidatedAllObjectsInStoreNotification and - * ObjectsChangedInStoreNotification. - * The former causes all objects in this store to be - * invalidated. - * The latter refaults the invalidated ids, merges changes - * from the updated ids, and forgets the deleted ids, then - * posts a ObjectsChangedInStoreNotification. - * Note: This method is not in the public specification. - */ - public void handleNotification( NSNotification aNotification ) - { // System.out.println( "EOEditingContext: " + this + " : " + aNotification ); - - willChange(); - if ( InvalidatedAllObjectsInStoreNotification - .equals( aNotification.name() ) ) - { - refaultObjects(); - - // relay notification - NSNotificationCenter.defaultCenter().postNotification( - new NSNotification( - InvalidatedAllObjectsInStoreNotification, this ) ); - } - else - if ( EOGlobalID.GlobalIDChangedNotification - .equals( aNotification.name() ) ) - { - NSDictionary userInfo = aNotification.userInfo(); - - // if any keys in userInfo are registered ids, - // re-register with new permanent values. - - Object o; - EOGlobalID id; - Enumeration e = userInfo.keyEnumerator(); - while ( e.hasMoreElements() ) - { - id = (EOGlobalID) e.nextElement(); - o = objectForGlobalID( id ); - if ( o != null ) - { - // record object is assumed to handle key updates - recordObject( o, (EOGlobalID) userInfo.objectForKey( id ) ); - } - } - } - else - if ( EOObjectStore.ObjectsChangedInStoreNotification - .equals( aNotification.name() ) ) - { - //System.out.println( "EOEditingContext.handleNotification: " + aNotification + " : " + this ); - // post so child contexts are notified - willChange(); - - Object o; - EOGlobalID id; - Enumeration e; - NSDictionary userInfo = aNotification.userInfo(); - - // inserted objects are ignored - - // existing deleted objects are removed - NSArray deletes = (NSArray) userInfo.objectForKey( - EOObjectStore.DeletedKey ); - e = deletes.objectEnumerator(); - while ( e.hasMoreElements() ) - { - id = (EOGlobalID) e.nextElement(); - o = objectForGlobalID( id ); - if ( o != null ) - { - //System.out.println( "EOEditingContext: deleted: " + id ); - forgetObject( o ); - deletedObjectsBuffer.addObject( o ); - deletedIDsBuffer.addObject( id ); - } - } - - // existing updated objects are merged - NSArray updates = (NSArray) userInfo.objectForKey( - EOObjectStore.UpdatedKey ); - e = updates.objectEnumerator(); - while ( e.hasMoreElements() ) - { - id = (EOGlobalID) e.nextElement(); - o = objectForGlobalID( id ); - if ( o != null ) - { - //System.out.println( "EOEditingContext: updated: " + id ); - if ( updatedObjects // only update if unchanged - .indexOfIdenticalObject( o ) == NSArray.NotFound ) - { - refaultObject( o, id, this ); - updatedObjectsBuffer.addObject( o ); - } - else - { - // notify user and/or merge - handleUpdateConflict( id, o ); - } - } - } - - // existing invalidated objects are refaulted - NSArray invalidates = (NSArray) userInfo.objectForKey( - EOObjectStore.InvalidatedKey ); - e = invalidates.objectEnumerator(); - while ( e.hasMoreElements() ) - { - id = (EOGlobalID) e.nextElement(); - o = objectForGlobalID( id ); - if ( o != null ) - { - if ( updatedObjects // only invalidate if unchanged - .indexOfIdenticalObject( o ) == NSArray.NotFound ) - { - refaultObject( o, id, this ); - } - else - { - // notify user and/or merge - handleUpdateConflict( id, o ); - } - if ( invalidatedObjectsBuffer - .indexOfIdenticalObject( o ) == NSArray.NotFound ) - { - invalidatedObjectsBuffer.addObject( o ); - } - if ( invalidatedIDsBuffer - .indexOfIdenticalObject( id ) == NSArray.NotFound ) - { - invalidatedIDsBuffer.addObject( id ); - } - } - } - - } - } - - /** - * Called by handleNotification to resolve the case where we have - * received notification that another user or context has updated - * an object that is currently marked as edited in this context. - * This implementation first asks the delegate if it should merge. - * If true or no delegate, the changes are merged. True or false, - * the delegate is then sent editingContextDidMergeChanges. - */ - private void handleUpdateConflict( EOGlobalID anID, Object anObject ) - { - // if we're causing the invalidation, ignore - // (this is probably better handled by the caller...) - if ( isInvalidating ) - { - ignoreChanges = true; - parentStore.refaultObject( anObject, anID, this ); - ignoreChanges = false; - return; - } - - Boolean result = (Boolean) notifyDelegate( - "editingContextShouldMergeChangesForObject", - new Class[] { EOEditingContext.class, Object.class }, - new Object[] { this, anObject } ); - - if ( ( result == null ) || ( Boolean.TRUE.equals( result ) ) ) - { - // do merge - mergeExternalChanges( anID, anObject ); - } - else // Boolean.FALSE - { - // do nothing: don't lose the user's changes - } - - // notify merge did happen - notifyDelegate( - "editingContextDidMergeChanges", - new Class[] { EOEditingContext.class }, - new Object[] { this } ); - } - - /** - * For the currently modified object with the specified global id, - * this method merges changes with the updated version in the parent - * object store. This implementation looks at the fetch snapshot - * to determine which changes where made by the user, fetches the - * updated version of the object, and then determine what external - * changes were made. If the changes do not overlap, the original - * changes are applied to the updated version. If there is a conflict, - * notifies the user of the conflict. - */ - private boolean mergeExternalChanges( EOGlobalID anID, Object anObject ) - { - try - { - Iterator i; - Object key; - - // get fetch snapshot - Map fetchSnapshot = committedSnapshotForObject( anObject ); - - // get current snapshot - Map currentSnapshot = currentEventSnapshotForObject( anObject ); - - // diff against fetch snapshot - Map currentDiff = new HashMap(); - i = currentSnapshot.keySet().iterator(); - while ( i.hasNext() ) - { - key = i.next(); - if ( ! currentSnapshot.get( key ).equals( fetchSnapshot.get( key ) ) ) - { - currentDiff.put( key, currentSnapshot.get( key ) ); - } - } - - // refault - ignoreChanges = true; - parentStore.refaultObject( anObject, anID, this ); - ignoreChanges = false; - - // get updated snapshot - Map updatedSnapshot = convertSnapshotToDictionary( takeSnapshot( anObject ) ); - - // diff against fetch snapshot - Map updatedDiff = new HashMap(); - i = updatedSnapshot.keySet().iterator(); - while ( i.hasNext() ) - { - key = i.next(); - if ( ! updatedSnapshot.get( key ).equals( fetchSnapshot.get( key ) ) ) - { - updatedDiff.put( key, updatedSnapshot.get( key ) ); - } - } - - // determine if there's a conflict - boolean proceed = true; - Set updatedKeys = updatedDiff.keySet(); - i = currentDiff.keySet().iterator(); - while ( i.hasNext() ) - { - if ( updatedKeys.contains( i.next() ) ) - { - proceed = false; - break; - } - } - - // if no conflicts, apply original diff to current object and exit - if ( proceed ) - { - KeyValueCodingUtilities.takeStoredValuesFromDictionary( anObject, currentDiff ); - return true; // exit! - } - } - catch ( Exception exc ) - { - // log error to standard out - exc.printStackTrace(); - } - - // notify user we're unable to merge - notifyMessageHandler( MessageChangeConflict + anObject ); - return false; - } - - /** - * Sends the specified message to the message handler. - */ - private void notifyMessageHandler( String aMessage ) - { - Object handler = null; - try - { - handler = messageHandler(); - if ( handler == null ) return; - NSSelector.invoke( "editingContextPresentErrorMessage", - new Class[] { EOEditingContext.class, String.class }, - handler, this, aMessage ); - } - catch ( NoSuchMethodException e ) - { - // ignore: not implemented - } - catch ( Exception exc ) - { - // log to standard error - System.err.println( - "Error while notifying message handler: " + - handler + " : " + aMessage ); - exc.printStackTrace(); - } - } - - /** - * Sends the specified message to the delegate. - * Returns the return value of the method, - * or null if no return value or no delegate - * or no implementation. - */ - private Object notifyDelegate( - String aMethodName, Class[] types, Object[] params ) - { - try - { - Object delegate = delegate(); - if ( delegate == null ) return null; - return NSSelector.invoke( - aMethodName, types, delegate, params ); - } - catch ( NoSuchMethodException e ) - { - // ignore: not implemented - } - catch ( Exception exc ) - { - // log to standard error - System.err.println( - "Error while messaging delegate: " + - delegate + " : " + aMethodName ); - exc.printStackTrace(); - } - - return null; - } - - // interface EOObserving - - /** - * Implementation of the EOObserving interface. - * Called before objects are modified. - */ - public void objectWillChange ( - Object anObject ) - { - if ( ignoreChanges ) return; + willChange(); + + // process any changes + processRecentChanges(); + + // set up user info for notification to be posted. + NSMutableDictionary userInfo = new NSMutableDictionary(); + userInfo.setObjectForKey(new NSArray((Collection) insertedObjects), EOObjectStore.InsertedKey); + userInfo.setObjectForKey(new NSArray((Collection) updatedObjects), EOObjectStore.UpdatedKey); + userInfo.setObjectForKey(new NSArray((Collection) deletedObjects), EOObjectStore.DeletedKey); + + // notify the editors + fireWillSaveChanges(); + + // notify the delegate + notifyDelegate("editingContextWillSaveChanges", new Class[] { EOEditingContext.class }, new Object[] { this }); + + // needed for notification handling + isInvalidating = true; + try { + // ask parent to save us + parentStore.saveChangesInEditingContext(this); + } catch (RuntimeException e) { + // unset save flag and rethrow + isInvalidating = false; + throw e; + } + isInvalidating = false; + + // no exceptions: proceed! + + Object o, key; + Iterator it; + + // update the committed snapshots + it = insertedObjects.iterator(); + while (it.hasNext()) { + o = it.next(); + registrar.setCommitSnapshot(o, null); + registrar.setCurrentSnapshot(o, null); + } + it = updatedObjects.iterator(); + while (it.hasNext()) { + o = it.next(); + registrar.setCommitSnapshot(o, null); + registrar.setCurrentSnapshot(o, null); + } + + // clear the lists + updatedObjects.removeAllObjects(); + insertedObjects.removeAllObjects(); + it = new NSArray(deletedObjects()).iterator(); + while (it.hasNext()) { // parent is doing this as well? + forgetObject(it.next()); + } + + // post notification + NSNotificationCenter.defaultCenter() + .postNotification(new NSNotification(EditingContextDidSaveChangesNotification, this, userInfo)); + } + + /** + * Commits all changes in the specified editing context to this one. Called by + * child editing contexts in their saveChanges() method. + */ + public void saveChangesInEditingContext(EOEditingContext aContext) { + Object o; + Iterator it; + + // process deletes + List deletes = new NSArray(aContext.deletedObjects()); + it = deletes.iterator(); + while (it.hasNext()) { + o = it.next(); + EOGlobalID id = aContext.globalIDForObject(o); + Object localVersion = objectForGlobalID(id); + if (localVersion == null) { + // make a local copy and register it + localVersion = registerClone(id, aContext, o, this); + if (localVersion == null) { + throw new WotonomyException("Deleted object could not be serialized: " + id + " : " + o); + } + } else // we have a local version, copy changes + { + copy(aContext, o, this, localVersion); + // copy marks the object as updated: will be on both lists + } + // delete our copy -- marks context as changed + deleteObject(localVersion); + } + + // process inserts - all inserts are new objects + List inserts = new NSArray(aContext.insertedObjects()); + it = inserts.iterator(); + while (it.hasNext()) { + o = it.next(); + // make a local copy and register it + EOGlobalID id = aContext.globalIDForObject(o); + willChange(); // need to mark editing context as changed + Object localVersion = registerClone(id, aContext, o, this); + if (localVersion == null) { + throw new WotonomyException("Inserted object could not be serialized: " + o); + } + // insert our copy manually so a new id is not generated + insertedObjects.addObject(localVersion); + insertedObjectsBuffer.addObject(localVersion); + } + + // process updates + List updates = new NSArray(aContext.updatedObjects()); + it = updates.iterator(); + while (it.hasNext()) { + willChange(); // need to mark editing context as changed + o = it.next(); + EOGlobalID id = aContext.globalIDForObject(o); + Object localVersion = objectForGlobalID(id); + if (localVersion == null) { + // make a local copy and register it + localVersion = registerClone(id, aContext, o, this); + if (localVersion == null) { + throw new WotonomyException("Updated object could not be serialized: " + id + " : " + o); + } + if (id.isTemporary()) { + // mark this object as inserted + insertedObjects.addObject(localVersion); + insertedObjectsBuffer.addObject(localVersion); + } else { + // mark this object as updated + updatedObjects.addObject(localVersion); + + // notify of update only if not on deleted list + if (deletedObjectsBuffer.indexOfIdenticalObject(localVersion) == NSArray.NotFound) { + updatedObjectsBuffer.addObject(localVersion); + } + } + } else // we have a local version, copy changes + { + copy(aContext, o, this, localVersion); + // copy marks the object as updated + } + } + + } + + /** + * Sets the delegate for this editing context. Note: this implementation retains + * only a weak reference to the specified object. + */ + public void setDelegate(Object anObject) { + if (anObject == null) + delegate = null; + delegate = new WeakReference(anObject); + } + + /** + * Sets the fetch timestamp for this editing context. + */ + public void setFetchTimestamp(double aDouble) { + fetchTimestamp = aDouble; + } + + /* + * public void setInvalidatesObjectsWhenFinalized ( boolean invalidatesObjects ) + * { throw new net.wotonomy.util.WotonomyException("Not implemented yet."); } + * + * public void setInvalidatesObjectsWhenFreed ( boolean invalidatesObjects ) { + * throw new net.wotonomy.util.WotonomyException("Not implemented yet."); } + */ + /** + * Sets whether this editing context attempts to lock objects when they are + * first modified. Default is false. + */ + public void setLocksObjectsBeforeFirstModification(boolean locksObjects) { + lockBeforeModify = locksObjects; + } + + /** + * Sets the message handler for this editing context. Note: this implementation + * retains only a weak reference to the specified object. + */ + public void setMessageHandler(Object anObject) { + if (anObject == null) + messageHandler = null; + messageHandler = new WeakReference(anObject); + } + + /** + * Sets whether this editing context propagates deletes immediately after the + * event that triggered the delete. Otherwise, propagation occurs only before + * commit. Default is true. + */ + public void setPropagatesDeletesAtEndOfEvent(boolean propagatesDeletes) { + propagateDeletesAfterEvent = propagatesDeletes; + } + + /* + * public void setSharedEditingContext ( EOSharedEditingContext + * aSharedEditingContext ) { throw new + * net.wotonomy.util.WotonomyException("Not implemented yet."); } + */ + /** + * Sets whether validation is stopped after the first error occurs. Otherwise, + * validation will continue for all other objects. Default is true. + */ + public void setStopsValidationAfterFirstError(boolean stopsValidation) { + stopValidationAfterError = stopsValidation; + } + + /** + * Sets the undo manager to be used for this context. Note: This is currently + * javax.swing.undo.UndoManager, until we have a implementation of + * NSUndoManager. + */ + /* + * public void setUndoManager ( UndoManager anUndoManager ) { undoManager = + * anUndoManager; } + */ + /* + * public EOSharedEditingContext sharedEditingContext () { throw new + * net.wotonomy.util.WotonomyException("Not implemented yet."); } + */ + /** + * Returns whether validation is stopped after the first error occurs. + * Otherwise, validation will continue for all other objects. + */ + public boolean stopsValidationAfterFirstError() { + return stopValidationAfterError; + } + + /** + * Reverts the last change on the undo stack. + */ + public void undo() { + // TODO: not supported yet + throw new UnsupportedOperationException("Not implemented yet."); + } + + /* + * public NSUndoManager undoManager () { throw new + * net.wotonomy.util.WotonomyException("Not implemented yet."); } + */ + /** + * public void unlock () { throw new net.wotonomy.util.WotonomyException("Not + * implemented yet."); } + */ + /** + * Returns a read-only list of all objects marked as modified, but not inserted + * or deleted, in this editing context. + */ + public NSArray updatedObjects() { + return updatedObjectsProxy; + } + + /** + * Notify editors of changes. + */ + private void fireWillSaveChanges() { + Object o = null; + Iterator i = editors().iterator(); + while (i.hasNext()) { + try { + o = i.next(); + NSSelector.invoke("editingContextWillSaveChanges", new Class[] { EOEditingContext.class }, o, this); + } catch (NoSuchMethodException e) { + // ignore: not implemented + } catch (Exception exc) { + // log to standard error + System.err.println("Error while notifying editor of pending save: " + o); + exc.printStackTrace(); + } + } + } + + /** + * Handles notifications from parent store, looking for + * InvalidatedAllObjectsInStoreNotification and + * ObjectsChangedInStoreNotification. The former causes all objects in this + * store to be invalidated. The latter refaults the invalidated ids, merges + * changes from the updated ids, and forgets the deleted ids, then posts a + * ObjectsChangedInStoreNotification. Note: This method is not in the public + * specification. + */ + public void handleNotification(NSNotification aNotification) { // System.out.println( "EOEditingContext: " + this + + // " : " + aNotification ); + + willChange(); + if (InvalidatedAllObjectsInStoreNotification.equals(aNotification.name())) { + refaultObjects(); + + // relay notification + NSNotificationCenter.defaultCenter() + .postNotification(new NSNotification(InvalidatedAllObjectsInStoreNotification, this)); + } else if (EOGlobalID.GlobalIDChangedNotification.equals(aNotification.name())) { + NSDictionary userInfo = aNotification.userInfo(); + + // if any keys in userInfo are registered ids, + // re-register with new permanent values. + + Object o; + EOGlobalID id; + Enumeration e = userInfo.keyEnumerator(); + while (e.hasMoreElements()) { + id = (EOGlobalID) e.nextElement(); + o = objectForGlobalID(id); + if (o != null) { + // record object is assumed to handle key updates + recordObject(o, (EOGlobalID) userInfo.objectForKey(id)); + } + } + } else if (EOObjectStore.ObjectsChangedInStoreNotification.equals(aNotification.name())) { + // System.out.println( "EOEditingContext.handleNotification: " + aNotification + + // " : " + this ); + // post so child contexts are notified + willChange(); + + Object o; + EOGlobalID id; + Enumeration e; + NSDictionary userInfo = aNotification.userInfo(); + + // inserted objects are ignored + + // existing deleted objects are removed + NSArray deletes = (NSArray) userInfo.objectForKey(EOObjectStore.DeletedKey); + e = deletes.objectEnumerator(); + while (e.hasMoreElements()) { + id = (EOGlobalID) e.nextElement(); + o = objectForGlobalID(id); + if (o != null) { + // System.out.println( "EOEditingContext: deleted: " + id ); + forgetObject(o); + deletedObjectsBuffer.addObject(o); + deletedIDsBuffer.addObject(id); + } + } + + // existing updated objects are merged + NSArray updates = (NSArray) userInfo.objectForKey(EOObjectStore.UpdatedKey); + e = updates.objectEnumerator(); + while (e.hasMoreElements()) { + id = (EOGlobalID) e.nextElement(); + o = objectForGlobalID(id); + if (o != null) { + // System.out.println( "EOEditingContext: updated: " + id ); + if (updatedObjects // only update if unchanged + .indexOfIdenticalObject(o) == NSArray.NotFound) { + refaultObject(o, id, this); + updatedObjectsBuffer.addObject(o); + } else { + // notify user and/or merge + handleUpdateConflict(id, o); + } + } + } + + // existing invalidated objects are refaulted + NSArray invalidates = (NSArray) userInfo.objectForKey(EOObjectStore.InvalidatedKey); + e = invalidates.objectEnumerator(); + while (e.hasMoreElements()) { + id = (EOGlobalID) e.nextElement(); + o = objectForGlobalID(id); + if (o != null) { + if (updatedObjects // only invalidate if unchanged + .indexOfIdenticalObject(o) == NSArray.NotFound) { + refaultObject(o, id, this); + } else { + // notify user and/or merge + handleUpdateConflict(id, o); + } + if (invalidatedObjectsBuffer.indexOfIdenticalObject(o) == NSArray.NotFound) { + invalidatedObjectsBuffer.addObject(o); + } + if (invalidatedIDsBuffer.indexOfIdenticalObject(id) == NSArray.NotFound) { + invalidatedIDsBuffer.addObject(id); + } + } + } + + } + } + + /** + * Called by handleNotification to resolve the case where we have received + * notification that another user or context has updated an object that is + * currently marked as edited in this context. This implementation first asks + * the delegate if it should merge. If true or no delegate, the changes are + * merged. True or false, the delegate is then sent + * editingContextDidMergeChanges. + */ + private void handleUpdateConflict(EOGlobalID anID, Object anObject) { + // if we're causing the invalidation, ignore + // (this is probably better handled by the caller...) + if (isInvalidating) { + ignoreChanges = true; + parentStore.refaultObject(anObject, anID, this); + ignoreChanges = false; + return; + } + + Boolean result = (Boolean) notifyDelegate("editingContextShouldMergeChangesForObject", + new Class[] { EOEditingContext.class, Object.class }, new Object[] { this, anObject }); + + if ((result == null) || (Boolean.TRUE.equals(result))) { + // do merge + mergeExternalChanges(anID, anObject); + } else // Boolean.FALSE + { + // do nothing: don't lose the user's changes + } + + // notify merge did happen + notifyDelegate("editingContextDidMergeChanges", new Class[] { EOEditingContext.class }, new Object[] { this }); + } + + /** + * For the currently modified object with the specified global id, this method + * merges changes with the updated version in the parent object store. This + * implementation looks at the fetch snapshot to determine which changes where + * made by the user, fetches the updated version of the object, and then + * determine what external changes were made. If the changes do not overlap, the + * original changes are applied to the updated version. If there is a conflict, + * notifies the user of the conflict. + */ + private boolean mergeExternalChanges(EOGlobalID anID, Object anObject) { + try { + Iterator i; + Object key; + + // get fetch snapshot + Map fetchSnapshot = committedSnapshotForObject(anObject); + + // get current snapshot + Map currentSnapshot = currentEventSnapshotForObject(anObject); + + // diff against fetch snapshot + Map currentDiff = new HashMap(); + i = currentSnapshot.keySet().iterator(); + while (i.hasNext()) { + key = i.next(); + if (!currentSnapshot.get(key).equals(fetchSnapshot.get(key))) { + currentDiff.put(key, currentSnapshot.get(key)); + } + } + + // refault + ignoreChanges = true; + parentStore.refaultObject(anObject, anID, this); + ignoreChanges = false; + + // get updated snapshot + Map updatedSnapshot = convertSnapshotToDictionary(takeSnapshot(anObject)); + + // diff against fetch snapshot + Map updatedDiff = new HashMap(); + i = updatedSnapshot.keySet().iterator(); + while (i.hasNext()) { + key = i.next(); + if (!updatedSnapshot.get(key).equals(fetchSnapshot.get(key))) { + updatedDiff.put(key, updatedSnapshot.get(key)); + } + } + + // determine if there's a conflict + boolean proceed = true; + Set updatedKeys = updatedDiff.keySet(); + i = currentDiff.keySet().iterator(); + while (i.hasNext()) { + if (updatedKeys.contains(i.next())) { + proceed = false; + break; + } + } + + // if no conflicts, apply original diff to current object and exit + if (proceed) { + KeyValueCodingUtilities.takeStoredValuesFromDictionary(anObject, currentDiff); + return true; // exit! + } + } catch (Exception exc) { + // log error to standard out + exc.printStackTrace(); + } + + // notify user we're unable to merge + notifyMessageHandler(MessageChangeConflict + anObject); + return false; + } + + /** + * Sends the specified message to the message handler. + */ + private void notifyMessageHandler(String aMessage) { + Object handler = null; + try { + handler = messageHandler(); + if (handler == null) + return; + NSSelector.invoke("editingContextPresentErrorMessage", new Class[] { EOEditingContext.class, String.class }, + handler, this, aMessage); + } catch (NoSuchMethodException e) { + // ignore: not implemented + } catch (Exception exc) { + // log to standard error + System.err.println("Error while notifying message handler: " + handler + " : " + aMessage); + exc.printStackTrace(); + } + } + + /** + * Sends the specified message to the delegate. Returns the return value of the + * method, or null if no return value or no delegate or no implementation. + */ + private Object notifyDelegate(String aMethodName, Class[] types, Object[] params) { + try { + Object delegate = delegate(); + if (delegate == null) + return null; + return NSSelector.invoke(aMethodName, types, delegate, params); + } catch (NoSuchMethodException e) { + // ignore: not implemented + } catch (Exception exc) { + // log to standard error + System.err.println("Error while messaging delegate: " + delegate + " : " + aMethodName); + exc.printStackTrace(); + } + + return null; + } + + // interface EOObserving + + /** + * Implementation of the EOObserving interface. Called before objects are + * modified. + */ + public void objectWillChange(Object anObject) { + if (ignoreChanges) + return; //NSNotificationCenter.defaultCenter().postNotification( "objectWillChange", this, new NSDictionary( "object", anObject ) ); //new RuntimeException().printStackTrace(); - willChange(); - - // mark as updated if not marked already - int i = updatedObjects.indexOfIdenticalObject( anObject ); - if ( i == NSArray.NotFound ) - { - // don't mark inserted objects as updated - i = insertedObjects.indexOfIdenticalObject( anObject ); - if ( i == NSArray.NotFound ) - { - i = deletedObjects.indexOfIdenticalObject( anObject ); - if ( i == NSArray.NotFound ) - { - // add object - updatedObjects.addObject( anObject ); - - // record revert snapshot - registrar.setCommitSnapshot( anObject, takeSnapshot( anObject ) ); - } - } - } - - // add to buffer - if ( updatedObjectsBuffer.indexOfIdenticalObject( anObject ) - == NSArray.NotFound ) - { - updatedObjectsBuffer.addObject( anObject ); - } - } - - // static methods - - public static double defaultFetchTimestampLag () - { - return defaultFetchTimestampLag; - } - - /** - * Returns the default parent object store for all - * object stores created with the parameterless - * constructor. - */ - public static EOObjectStore defaultParentObjectStore () - { - return defaultParentObjectStore; - } + willChange(); + + // mark as updated if not marked already + int i = updatedObjects.indexOfIdenticalObject(anObject); + if (i == NSArray.NotFound) { + // don't mark inserted objects as updated + i = insertedObjects.indexOfIdenticalObject(anObject); + if (i == NSArray.NotFound) { + i = deletedObjects.indexOfIdenticalObject(anObject); + if (i == NSArray.NotFound) { + // add object + updatedObjects.addObject(anObject); + + // record revert snapshot + registrar.setCommitSnapshot(anObject, takeSnapshot(anObject)); + } + } + } -/* - public static Object initObjectWithCoder ( - Object anObject, - NSCoder aCoder ) - { - throw new net.wotonomy.util.WotonomyException("Not implemented yet."); - } -*/ + // add to buffer + if (updatedObjectsBuffer.indexOfIdenticalObject(anObject) == NSArray.NotFound) { + updatedObjectsBuffer.addObject(anObject); + } + } - /** - * Returns whether editing contexts are configured to retain strong - * references to their registered objects. If false, editing contexts - * will only retain weak references to their registered objects. - */ - public static boolean instancesRetainRegisteredObjects() - { - return retainsRegisteredObjects; - } - - /** - * Sets the global default fetch timestamp lag. - */ - public static void setDefaultFetchTimestampLag ( - double aDouble ) - { - defaultFetchTimestampLag = aDouble; - } - - /** - * Sets the global default parent object store, - * used for the parameterless constructor. - */ - public static void setDefaultParentObjectStore ( - EOObjectStore anObjectStore ) - { - defaultParentObjectStore = anObjectStore; - } - - public static void setInstancesRetainRegisteredObjects ( - boolean retainsObjects ) - { - retainsRegisteredObjects = retainsObjects; - } + // static methods -/* - public static void setSubstitutionEditingContext ( - EOEditingContext aContext) - { - throw new net.wotonomy.util.WotonomyException("Not implemented yet."); - } - - public static void setUsesContextRelativeEncoding ( - boolean usesRelativeEncoding ) - { - throw new net.wotonomy.util.WotonomyException("Not implemented yet."); - } - - public static EOEditingContext substitutionEditingContext () - { - throw new net.wotonomy.util.WotonomyException("Not implemented yet."); - } - - public static boolean usesContextRelativeEncoding () - { - throw new net.wotonomy.util.WotonomyException("Not implemented yet."); - } -*/ + public static double defaultFetchTimestampLag() { + return defaultFetchTimestampLag; + } + + /** + * Returns the default parent object store for all object stores created with + * the parameterless constructor. + */ + public static EOObjectStore defaultParentObjectStore() { + return defaultParentObjectStore; + } + + /* + * public static Object initObjectWithCoder ( Object anObject, NSCoder aCoder ) + * { throw new net.wotonomy.util.WotonomyException("Not implemented yet."); } + */ + + /** + * Returns whether editing contexts are configured to retain strong references + * to their registered objects. If false, editing contexts will only retain weak + * references to their registered objects. + */ + public static boolean instancesRetainRegisteredObjects() { + return retainsRegisteredObjects; + } + + /** + * Sets the global default fetch timestamp lag. + */ + public static void setDefaultFetchTimestampLag(double aDouble) { + defaultFetchTimestampLag = aDouble; + } + + /** + * Sets the global default parent object store, used for the parameterless + * constructor. + */ + public static void setDefaultParentObjectStore(EOObjectStore anObjectStore) { + defaultParentObjectStore = anObjectStore; + } + + public static void setInstancesRetainRegisteredObjects(boolean retainsObjects) { + retainsRegisteredObjects = retainsObjects; + } + + /* + * public static void setSubstitutionEditingContext ( EOEditingContext aContext) + * { throw new net.wotonomy.util.WotonomyException("Not implemented yet."); } + * + * public static void setUsesContextRelativeEncoding ( boolean + * usesRelativeEncoding ) { throw new + * net.wotonomy.util.WotonomyException("Not implemented yet."); } + * + * public static EOEditingContext substitutionEditingContext () { throw new + * net.wotonomy.util.WotonomyException("Not implemented yet."); } + * + * public static boolean usesContextRelativeEncoding () { throw new + * net.wotonomy.util.WotonomyException("Not implemented yet."); } + */ + + public String toString() { + return "[EOEditingContext@" + Integer.toHexString(System.identityHashCode(this)) + ":" + " inserted=" + + idsForObjects(insertedObjects) + " updated=" + idsForObjects(updatedObjects) + " deleted=" + + idsForObjects(deletedObjects) + " registered=" + registrar.registeredGlobalIDs() + " ]"; + } + + private List idsForObjects(List objects) { + List result = new LinkedList(); + Iterator i = objects.iterator(); + while (i.hasNext()) + result.add(globalIDForObject(i.next())); + return result; + } - public String toString() - { - return "[EOEditingContext@"+Integer.toHexString(System.identityHashCode(this))+":"+ - " inserted="+idsForObjects(insertedObjects)+ - " updated="+idsForObjects(updatedObjects)+ - " deleted="+idsForObjects(deletedObjects)+ - " registered="+registrar.registeredGlobalIDs()+" ]"; - } - private List idsForObjects( List objects ) - { - List result = new LinkedList(); - Iterator i = objects.iterator(); - while ( i.hasNext() ) result.add( globalIDForObject( i.next() ) ); - return result; - } - - // snapshots - - /** - * Returns a NSDictionary containing only the mutable properties - * for the specified object and deep clones of their values. - * Nulls are represented by NSNull.nullValue(). - */ - private byte[] takeSnapshot( Object anObject ) - { // System.out.println( "takeSnapshot: " + anObject ); - return KeyValueCodingUtilities.freeze( anObject, this, anObject, true ); - } - - /** - * Applies the map of properties and values to the - * specified object. Null values for properties must - * be represented by the NSNull.nullValue(). - * Posts a willChange event before applying changes. - */ - private void applySnapshot( byte[] aSnapshot, Object anObject ) - { - // must clone snapshot to avoid changing existing snapshot - NSDictionary values = convertSnapshotToDictionary( aSnapshot ); + // snapshots + + /** + * Returns a NSDictionary containing only the mutable properties for the + * specified object and deep clones of their values. Nulls are represented by + * NSNull.nullValue(). + */ + private byte[] takeSnapshot(Object anObject) { // System.out.println( "takeSnapshot: " + anObject ); + return KeyValueCodingUtilities.freeze(anObject, this, anObject, true); + } + + /** + * Applies the map of properties and values to the specified object. Null values + * for properties must be represented by the NSNull.nullValue(). Posts a + * willChange event before applying changes. + */ + private void applySnapshot(byte[] aSnapshot, Object anObject) { + // must clone snapshot to avoid changing existing snapshot + NSDictionary values = convertSnapshotToDictionary(aSnapshot); //System.out.println( "applySnapshot: " + aSnapshot + " : " + values ); //ignoreChanges = true; - willChange(); - KeyValueCodingUtilities.takeStoredValuesFromDictionary( anObject, values ); + willChange(); + KeyValueCodingUtilities.takeStoredValuesFromDictionary(anObject, values); //ignoreChanges = false; - } - - /** - * Snapshots are stored internally in binary format, - * but exposed to the user as NSDictionaries. - */ - private NSDictionary convertSnapshotToDictionary( byte[] aSnapshot ) - { - // get the object - Object clone = KeyValueCodingUtilities.thaw( aSnapshot, this, true ); - // get all keys for this object - EOClassDescription classDesc = - EOClassDescription.classDescriptionForClass( clone.getClass() ); - List keys = new LinkedList(); - keys.addAll( classDesc.attributeKeys() ); - keys.addAll( classDesc.toOneRelationshipKeys() ); - keys.addAll( classDesc.toManyRelationshipKeys() ); - - return KeyValueCodingUtilities.valuesForKeys( clone, keys ); - } - /** - * Creates a deep clone of the specified object. - * (Object.clone() only creates a shallow clone.) - * Returns null if operation fails. - */ - static private Object clone( - EOEditingContext aSourceContext, - Object aSource, - EOEditingContext aDestinationContext ) - { // System.out.println( "clone: " + aSource ); - return KeyValueCodingUtilities.clone( - aSourceContext, aSource, aDestinationContext ); - } - - /** - * Creates a deep clone of the specified object. - * but does not transpose references. This allows - * us to register an object before transposing - * references so that child objects will be able - * to resolve references to their parent. - * After recording the object, we copy the source - * object into the clone, which does transpose - * and resolve properly. - * Returns null if operation fails. - */ - static private Object registerClone( - EOGlobalID aGlobalID, - EOEditingContext aSourceContext, - Object aSource, - EOEditingContext aDestinationContext ) - { - // while we'd like to just transpose/clone at the same time - // we must record a clone without transposing: this - // avoids a endless loop if the object graph has a cycle - Object clone = KeyValueCodingUtilities.thaw( - KeyValueCodingUtilities.freeze( - aSource, aSourceContext, aSource, false ), - aDestinationContext, false ); - - aDestinationContext.recordObject( clone, aGlobalID ); - - // need to copy to transpose references into this context - // while preserving the same instance of the object - aDestinationContext.ignoreChanges = true; - copy( aSourceContext, aSource, aDestinationContext, clone ); - aDestinationContext.ignoreChanges = false; - - // return our clone - return clone; - } - - /** - * Copies values from one object to another. - * Returns the destination object, or throws exception - * if operation fails. - */ - static private Object copy( - EOEditingContext aSourceContext, - Object aSource, - EOEditingContext aDestinationContext, - Object aDestination ) - { // System.out.println( "copy: " ); - EOObserverCenter.notifyObserversObjectWillChange( aDestination ); - KeyValueCodingUtilities.copy( aSourceContext, aSource, aDestinationContext, aDestination ); - return aDestination; - } - - // process recent changes - - /** - * Called to notify observers of changes. - * Also calls runLater(). - */ - private void willChange() - { - EOObserverCenter.notifyObserversObjectWillChange( this ); - runLater(); - } - - /** - * Called to ensure that processRecentChanges - * will be called on the next event loop. - */ - private void runLater() - { - if ( ! willRunLater ) - { + } + + /** + * Snapshots are stored internally in binary format, but exposed to the user as + * NSDictionaries. + */ + private NSDictionary convertSnapshotToDictionary(byte[] aSnapshot) { + // get the object + Object clone = KeyValueCodingUtilities.thaw(aSnapshot, this, true); + // get all keys for this object + EOClassDescription classDesc = EOClassDescription.classDescriptionForClass(clone.getClass()); + List keys = new LinkedList(); + keys.addAll(classDesc.attributeKeys()); + keys.addAll(classDesc.toOneRelationshipKeys()); + keys.addAll(classDesc.toManyRelationshipKeys()); + + return KeyValueCodingUtilities.valuesForKeys(clone, keys); + } + + /** + * Creates a deep clone of the specified object. (Object.clone() only creates a + * shallow clone.) Returns null if operation fails. + */ + static private Object clone(EOEditingContext aSourceContext, Object aSource, EOEditingContext aDestinationContext) { // System.out.println( + // "clone: + // " + // + + // aSource + // ); + return KeyValueCodingUtilities.clone(aSourceContext, aSource, aDestinationContext); + } + + /** + * Creates a deep clone of the specified object. but does not transpose + * references. This allows us to register an object before transposing + * references so that child objects will be able to resolve references to their + * parent. After recording the object, we copy the source object into the clone, + * which does transpose and resolve properly. Returns null if operation fails. + */ + static private Object registerClone(EOGlobalID aGlobalID, EOEditingContext aSourceContext, Object aSource, + EOEditingContext aDestinationContext) { + // while we'd like to just transpose/clone at the same time + // we must record a clone without transposing: this + // avoids a endless loop if the object graph has a cycle + Object clone = KeyValueCodingUtilities.thaw( + KeyValueCodingUtilities.freeze(aSource, aSourceContext, aSource, false), aDestinationContext, false); + + aDestinationContext.recordObject(clone, aGlobalID); + + // need to copy to transpose references into this context + // while preserving the same instance of the object + aDestinationContext.ignoreChanges = true; + copy(aSourceContext, aSource, aDestinationContext, clone); + aDestinationContext.ignoreChanges = false; + + // return our clone + return clone; + } + + /** + * Copies values from one object to another. Returns the destination object, or + * throws exception if operation fails. + */ + static private Object copy(EOEditingContext aSourceContext, Object aSource, EOEditingContext aDestinationContext, + Object aDestination) { // System.out.println( "copy: " ); + EOObserverCenter.notifyObserversObjectWillChange(aDestination); + KeyValueCodingUtilities.copy(aSourceContext, aSource, aDestinationContext, aDestination); + return aDestination; + } + + // process recent changes + + /** + * Called to notify observers of changes. Also calls runLater(). + */ + private void willChange() { + EOObserverCenter.notifyObserversObjectWillChange(this); + runLater(); + } + + /** + * Called to ensure that processRecentChanges will be called on the next event + * loop. + */ + private void runLater() { + if (!willRunLater) { willRunLater = true; - NSRunLoop.currentRunLoop().performSelectorWithOrder( - runLaterSelector, this, null, EditingContextFlushChangesRunLoopOrdering, null ); + NSRunLoop.currentRunLoop().performSelectorWithOrder(runLaterSelector, this, null, + EditingContextFlushChangesRunLoopOrdering, null); } } - + /** - * This method is called by the event queue run loop - * and calls processRecentChanges. - * NOTE: This method is not part of the specification. - */ - public void flushRecentChanges( Object anObject ) - { + * This method is called by the event queue run loop and calls + * processRecentChanges. NOTE: This method is not part of the specification. + */ + public void flushRecentChanges(Object anObject) { //System.out.println( "EODelayedObserverQueue: running" ); - processRecentChanges(); + processRecentChanges(); willRunLater = false; } - - // inner classes - - /** - * Gatekeeper for all access to registered objects. - */ - static private class Registrar - { - EOEditingContext context; - NSMutableDictionary IDsToObjects; - NSMutableDictionary objectsToIDs; - NSMutableDictionary objectsToCommitSnapshots; - NSMutableDictionary objectsToCurrentSnapshots; - - ReferenceKey comparisonKey; //FIXME not thread safe! - - public Registrar( EOEditingContext aContext ) - { - context = aContext; - IDsToObjects = new NSMutableDictionary(); - objectsToIDs = new NSMutableDictionary(); - objectsToCommitSnapshots = new NSMutableDictionary(); - objectsToCurrentSnapshots = new NSMutableDictionary(); - comparisonKey = new ReferenceKey(); - } - - public NSArray registeredObjects() - { - return IDsToObjects.allValues(); - } - - public NSArray registeredGlobalIDs() - { - return IDsToObjects.allKeys(); - } - - public Object objectForGlobalID( EOGlobalID aGlobalID ) - { - return IDsToObjects.objectForKey( aGlobalID ); - } - - public EOGlobalID globalIDForObject( Object anObject ) - { - comparisonKey.set( anObject ); - return (EOGlobalID) objectsToIDs.objectForKey( comparisonKey ); - } - - public byte[] getCommitSnapshot( Object anObject ) - { - comparisonKey.set( anObject ); - return (byte[]) objectsToCommitSnapshots.objectForKey( comparisonKey ); - } - - public void setCommitSnapshot( Object anObject, byte[] aSnapshot ) - { - if ( aSnapshot == null ) - { - comparisonKey.set( anObject ); - objectsToCommitSnapshots.removeObjectForKey( comparisonKey ); - } - else - { - objectsToCommitSnapshots.setObjectForKey( - aSnapshot, new ReferenceKey( anObject ) ); - } - } - - public byte[] getCurrentSnapshot( Object anObject ) - { - comparisonKey.set( anObject ); - return (byte[]) objectsToCurrentSnapshots.objectForKey( comparisonKey ); - } - - public void setCurrentSnapshot( Object anObject, byte[] aSnapshot ) - { - if ( aSnapshot == null ) - { - comparisonKey.set( anObject ); - objectsToCurrentSnapshots.removeObjectForKey( comparisonKey ); - } - else - { - objectsToCurrentSnapshots.setObjectForKey( - aSnapshot, new ReferenceKey( anObject ) ); - } - } - - public void registerObject( Object anObject, EOGlobalID aGlobalID ) - { - IDsToObjects.setObjectForKey( anObject, aGlobalID ); - objectsToIDs.setObjectForKey( aGlobalID, new ReferenceKey( anObject ) ); - EOObserverCenter.addObserver( context, anObject ); - } - - public void forgetObject( Object anObject ) - { - comparisonKey.set( anObject ); - Object id = objectsToIDs.objectForKey( comparisonKey ); - IDsToObjects.removeObjectForKey( id ); - objectsToIDs.removeObjectForKey( comparisonKey ); - EOObserverCenter.removeObserver( context, anObject ); - } - - public void disposeSnapshots( Object anObject ) - { - setCommitSnapshot( anObject, null ); - setCurrentSnapshot( anObject, null ); - } - - } - - /** - * Registrar that uses only WeakReferences. - * Used if retainsRegisteredObjects is false. - */ - static private class WeakRegistrar extends Registrar - { - private WeakReferenceKey weakComparisonKey; //FIXME not thread safe! - - public WeakRegistrar( EOEditingContext aContext ) - { - super( aContext ); - weakComparisonKey = new WeakReferenceKey(); - } - - public NSArray registeredObjects() - { - Object object; - WeakReferenceKey weakKey; - NSMutableArray result = new NSMutableArray(); - Enumeration e = new NSArray( objectsToIDs.allKeys() ).objectEnumerator(); - while ( e.hasMoreElements() ) - { - weakKey = (WeakReferenceKey) e.nextElement(); - object = weakKey.get(); - if ( object != null ) - { - result.addObject( object ); - } - else - { - // object has been released: perform cleanup - disposeObject( null, weakKey ); - } - } - return result; - } - - public Object objectForGlobalID( EOGlobalID aGlobalID ) - { - WeakReference ref = (WeakReference) super.objectForGlobalID( aGlobalID ); - if ( ref == null ) return null; - Object result = ref.get(); - if ( result == null ) - { - // clean up manually - IDsToObjects.removeObjectForKey( aGlobalID ); - Iterator i = new LinkedList( objectsToIDs.allKeysForObject( ref ) ).iterator(); - while ( i.hasNext() ) - { - objectsToIDs.removeObjectForKey( i.next() ); - } - disposeSnapshots( aGlobalID ); - } - return result; - } - - public byte[] getCommitSnapshot( Object anObject ) - { - weakComparisonKey.set( anObject ); - return (byte[]) objectsToCommitSnapshots.objectForKey( weakComparisonKey ); - } - - public void setCommitSnapshot( Object anObject, byte[] aSnapshot ) - { - if ( aSnapshot == null ) - { - weakComparisonKey.set( anObject ); - objectsToCommitSnapshots.removeObjectForKey( weakComparisonKey ); - } - else - { - objectsToCommitSnapshots.setObjectForKey( - aSnapshot, new WeakReferenceKey( anObject ) ); - } - } - - public byte[] getCurrentSnapshot( Object anObject ) - { - weakComparisonKey.set( anObject ); - return (byte[]) objectsToCurrentSnapshots.objectForKey( weakComparisonKey ); - } - - public void setCurrentSnapshot( Object anObject, byte[] aSnapshot ) - { - if ( aSnapshot == null ) - { - weakComparisonKey.set( anObject ); - objectsToCurrentSnapshots.removeObjectForKey( weakComparisonKey ); - } - else - { - objectsToCurrentSnapshots.setObjectForKey( - aSnapshot, new WeakReferenceKey( anObject ) ); - } - } - - public void registerObject( Object anObject, EOGlobalID aGlobalID ) - { // new net.wotonomy.ui.swing.ReferenceInspector( anObject ); - IDsToObjects.setObjectForKey( new WeakReference( anObject ), aGlobalID ); - objectsToIDs.setObjectForKey( aGlobalID, new WeakReferenceKey( anObject ) ); - EOObserverCenter.addObserver( context, anObject ); - } - - public void forgetObject( Object anObject ) - { - disposeObject( anObject, null ); - } - - // must specify one or the other - private void disposeObject( Object anObject, WeakReferenceKey key ) - { - if ( key == null ) key = new WeakReferenceKey( anObject ); - EOGlobalID id = (EOGlobalID) objectsToIDs.objectForKey( key ); - if ( id != null ) IDsToObjects.removeObjectForKey( id ); - objectsToIDs.removeObjectForKey( key ); - disposeSnapshots( id ); - if ( anObject != null ) - { - EOObserverCenter.removeObserver( context, anObject ); - } - } - } - - /** - * Private class used to force a hashmap to - * perform key comparisons by reference. - */ - static private class ReferenceKey - { - int hashCode; - Object referent; - - public ReferenceKey() - { - referent = null; - hashCode = -1; - } - - public ReferenceKey( Object anObject ) - { - set( anObject ); - } - - public Object get() - { - return referent; - } - - public void set( Object anObject ) - { - referent = anObject; - hashCode = anObject.hashCode(); - } - - /** - * Returns the actual key's hash code. - */ - public int hashCode() - { - return hashCode; - } - - /** - * Compares by reference. - */ - public boolean equals( Object anObject ) - { - if ( anObject == this ) return true; - if ( anObject instanceof ReferenceKey ) - { - return ((ReferenceKey)anObject).get() == referent; - } - return false; - } - } - - /** - * Private class used to force a hashmap to - * perform key comparisons by reference. - */ - static private class WeakReferenceKey extends ReferenceKey - { - public WeakReferenceKey() - { - super(); - } - - public WeakReferenceKey( Object anObject ) - { - super( anObject ); - } - - public Object get() - { - return ((WeakReference)referent).get(); - } - - public void set( Object anObject ) - { - referent = new WeakReference( anObject ); - hashCode = anObject.hashCode(); - } - - /** - * Compares by reference. - */ - public boolean equals( Object anObject ) - { - if ( anObject == this ) return true; - if ( anObject instanceof ReferenceKey ) - { - return ((ReferenceKey)anObject).get() == get(); - } - return false; - } - } - - /** - * Key combining an object with a string. - * Object is compared by reference. - */ - static private class CompoundKey - { - private Object object; - private String string; - private int hashCode; - - /** - * Creates compound key. - * Neither name nor object may be null. - */ - public CompoundKey ( - Object anObject, String aString ) - { - object = anObject; - string = aString; - hashCode = object.hashCode() + string.hashCode(); - } - - public int hashCode() - { - return hashCode; - } - - public boolean equals( Object anObject ) - { - if ( anObject instanceof CompoundKey ) - { - CompoundKey key = (CompoundKey) anObject; - return ( ( key.object == object ) && ( key.string.equals( string ) ) ); - } - return false; - } - - public String toString() - { - return "[CompoundKey:"+object+":"+string+"]"; - } - } - - /** - * Used by EditingContext to delegate behavior to another class. - * Note that EditingContext doesn't require its delegates to implement - * this interface: rather, this interface defines the methods that - * EditingContext will attempt to invoke dynamically on its delegate. - * The delegate may choose to implement only a subset of the methods - * on the interface. - */ - public interface Delegate - { - /** - * Called after the editing context has completed merge operations - * on one or more objects after receiving an ObjectChangedInStore - * notification. - */ - void editingContextDidMergeChanges( - EOEditingContext anEditingContext ); - - /** - * Called by objectsWithFetchSpecification. - * If null, the editing context will pass the fetch specification - * on to its parent store, as normal. Otherwise, the context - * will use the returned array to service the request. - */ - NSArray editingContextShouldFetchObjects( - EOEditingContext anEditingContext, - EOFetchSpecification fetchSpecification ); - - /** - * Called to determine whether an object should be invalidated. - * Return false to prevent the object from being invalidated. - * Default is true. - */ - boolean editingContextShouldInvalidateObject( - EOEditingContext anEditingContext, - Object anObject, - EOGlobalID aGlobalID ); - - /** - * Called to determine whether the editing context should attempt - * to merge changes in the specified object that the parent store - * says has changed via an ObjectChangedInStore notification. - * Default is true. Return false if you wish to handle the merge - * yourself, by extracting the values in the object now and comparing - * them to the values when editingContextDidMergeChanges is called. - */ - boolean editingContextShouldMergeChangesForObject( - EOEditingContext anEditingContext, - Object anObject ); - - /** - * Returns whether the editing context should ask its message handler - * to display a message. Return false if the delegate will display the error. - * Default is true. - */ - boolean editingContextShouldPresentException( - EOEditingContext anEditingContext, - Throwable exception ); - - /** - * Returns whether the editing context should undo the most - * recent set of changes that resulted in a validation failure. - * Default is true. - */ - boolean editingContextShouldUndoUserActionsAfterFailure( - EOEditingContext anEditingContext ); - - /** - * Returns whether the editing context should validate the - * most recent set of changes. Default is true. - */ - boolean editingContextShouldValidateChanges( - EOEditingContext anEditingContext ); - - /** - * Called before the editing context saves its changes - * to the parent object store. - */ - void editingContextWillSaveChanges( - EOEditingContext anEditingContext ); - - } - - /** - * Editors register themselves with the editing context - * so that they may receive notification before the context - * commits changes. This is useful for associations whose - * components do not immediately commit their changes to - * the object they are editing. - */ - public interface Editor - { - /** - * Called before the editing context saves its changes - * to the parent object store. - */ - void editingContextWillSaveChanges( - EOEditingContext anEditingContext ); - - /** - * Called to determine whether this editor has changes - * that have not been committed to the object in the context. - */ - boolean editorHasChangesForEditingContext( - EOEditingContext anEditingContext ); - - } - - /** - * Used by EditingContext to delegate messaging handling to another class, - * typically the display group that has the currently active association. - * Note that EditingContext doesn't require its message handlers to implement - * this interface: rather, this interface defines the methods that - * EditingContext will attempt to invoke dynamically on its delegate. - * The delegate may choose to implement only a subset of the methods - * on the interface. - */ - public interface MessageHandler - { - /** - * Called to display a message for an error that occurred - * in the specified editing context. - */ - void editingContextPresentErrorMessage( - EOEditingContext anEditingContext, - String aMessage ); - - /** - * Called by the specified object store to determine whether - * fetching should continue, where count is the current count - * and limit is the limit as specified by the fetch specification. - * Default is false. - */ - boolean editingContextShouldContinueFetching( - EOEditingContext anEditingContext, - int count, - int limit, - EOObjectStore anObjectStore ); - - } - + + // inner classes + + /** + * Gatekeeper for all access to registered objects. + */ + static private class Registrar { + EOEditingContext context; + NSMutableDictionary IDsToObjects; + NSMutableDictionary objectsToIDs; + NSMutableDictionary objectsToCommitSnapshots; + NSMutableDictionary objectsToCurrentSnapshots; + + ReferenceKey comparisonKey; // FIXME not thread safe! + + public Registrar(EOEditingContext aContext) { + context = aContext; + IDsToObjects = new NSMutableDictionary(); + objectsToIDs = new NSMutableDictionary(); + objectsToCommitSnapshots = new NSMutableDictionary(); + objectsToCurrentSnapshots = new NSMutableDictionary(); + comparisonKey = new ReferenceKey(); + } + + public NSArray registeredObjects() { + return IDsToObjects.allValues(); + } + + public NSArray registeredGlobalIDs() { + return IDsToObjects.allKeys(); + } + + public Object objectForGlobalID(EOGlobalID aGlobalID) { + return IDsToObjects.objectForKey(aGlobalID); + } + + public EOGlobalID globalIDForObject(Object anObject) { + comparisonKey.set(anObject); + return (EOGlobalID) objectsToIDs.objectForKey(comparisonKey); + } + + public byte[] getCommitSnapshot(Object anObject) { + comparisonKey.set(anObject); + return (byte[]) objectsToCommitSnapshots.objectForKey(comparisonKey); + } + + public void setCommitSnapshot(Object anObject, byte[] aSnapshot) { + if (aSnapshot == null) { + comparisonKey.set(anObject); + objectsToCommitSnapshots.removeObjectForKey(comparisonKey); + } else { + objectsToCommitSnapshots.setObjectForKey(aSnapshot, new ReferenceKey(anObject)); + } + } + + public byte[] getCurrentSnapshot(Object anObject) { + comparisonKey.set(anObject); + return (byte[]) objectsToCurrentSnapshots.objectForKey(comparisonKey); + } + + public void setCurrentSnapshot(Object anObject, byte[] aSnapshot) { + if (aSnapshot == null) { + comparisonKey.set(anObject); + objectsToCurrentSnapshots.removeObjectForKey(comparisonKey); + } else { + objectsToCurrentSnapshots.setObjectForKey(aSnapshot, new ReferenceKey(anObject)); + } + } + + public void registerObject(Object anObject, EOGlobalID aGlobalID) { + IDsToObjects.setObjectForKey(anObject, aGlobalID); + objectsToIDs.setObjectForKey(aGlobalID, new ReferenceKey(anObject)); + EOObserverCenter.addObserver(context, anObject); + } + + public void forgetObject(Object anObject) { + comparisonKey.set(anObject); + Object id = objectsToIDs.objectForKey(comparisonKey); + IDsToObjects.removeObjectForKey(id); + objectsToIDs.removeObjectForKey(comparisonKey); + EOObserverCenter.removeObserver(context, anObject); + } + + public void disposeSnapshots(Object anObject) { + setCommitSnapshot(anObject, null); + setCurrentSnapshot(anObject, null); + } + + } + + /** + * Registrar that uses only WeakReferences. Used if retainsRegisteredObjects is + * false. + */ + static private class WeakRegistrar extends Registrar { + private WeakReferenceKey weakComparisonKey; // FIXME not thread safe! + + public WeakRegistrar(EOEditingContext aContext) { + super(aContext); + weakComparisonKey = new WeakReferenceKey(); + } + + public NSArray registeredObjects() { + Object object; + WeakReferenceKey weakKey; + NSMutableArray result = new NSMutableArray(); + Enumeration e = new NSArray(objectsToIDs.allKeys()).objectEnumerator(); + while (e.hasMoreElements()) { + weakKey = (WeakReferenceKey) e.nextElement(); + object = weakKey.get(); + if (object != null) { + result.addObject(object); + } else { + // object has been released: perform cleanup + disposeObject(null, weakKey); + } + } + return result; + } + + public Object objectForGlobalID(EOGlobalID aGlobalID) { + WeakReference ref = (WeakReference) super.objectForGlobalID(aGlobalID); + if (ref == null) + return null; + Object result = ref.get(); + if (result == null) { + // clean up manually + IDsToObjects.removeObjectForKey(aGlobalID); + Iterator i = new LinkedList(objectsToIDs.allKeysForObject(ref)).iterator(); + while (i.hasNext()) { + objectsToIDs.removeObjectForKey(i.next()); + } + disposeSnapshots(aGlobalID); + } + return result; + } + + public byte[] getCommitSnapshot(Object anObject) { + weakComparisonKey.set(anObject); + return (byte[]) objectsToCommitSnapshots.objectForKey(weakComparisonKey); + } + + public void setCommitSnapshot(Object anObject, byte[] aSnapshot) { + if (aSnapshot == null) { + weakComparisonKey.set(anObject); + objectsToCommitSnapshots.removeObjectForKey(weakComparisonKey); + } else { + objectsToCommitSnapshots.setObjectForKey(aSnapshot, new WeakReferenceKey(anObject)); + } + } + + public byte[] getCurrentSnapshot(Object anObject) { + weakComparisonKey.set(anObject); + return (byte[]) objectsToCurrentSnapshots.objectForKey(weakComparisonKey); + } + + public void setCurrentSnapshot(Object anObject, byte[] aSnapshot) { + if (aSnapshot == null) { + weakComparisonKey.set(anObject); + objectsToCurrentSnapshots.removeObjectForKey(weakComparisonKey); + } else { + objectsToCurrentSnapshots.setObjectForKey(aSnapshot, new WeakReferenceKey(anObject)); + } + } + + public void registerObject(Object anObject, EOGlobalID aGlobalID) { // new + // net.wotonomy.ui.swing.ReferenceInspector( + // anObject ); + IDsToObjects.setObjectForKey(new WeakReference(anObject), aGlobalID); + objectsToIDs.setObjectForKey(aGlobalID, new WeakReferenceKey(anObject)); + EOObserverCenter.addObserver(context, anObject); + } + + public void forgetObject(Object anObject) { + disposeObject(anObject, null); + } + + // must specify one or the other + private void disposeObject(Object anObject, WeakReferenceKey key) { + if (key == null) + key = new WeakReferenceKey(anObject); + EOGlobalID id = (EOGlobalID) objectsToIDs.objectForKey(key); + if (id != null) + IDsToObjects.removeObjectForKey(id); + objectsToIDs.removeObjectForKey(key); + disposeSnapshots(id); + if (anObject != null) { + EOObserverCenter.removeObserver(context, anObject); + } + } + } + + /** + * Private class used to force a hashmap to perform key comparisons by + * reference. + */ + static private class ReferenceKey { + int hashCode; + Object referent; + + public ReferenceKey() { + referent = null; + hashCode = -1; + } + + public ReferenceKey(Object anObject) { + set(anObject); + } + + public Object get() { + return referent; + } + + public void set(Object anObject) { + referent = anObject; + hashCode = anObject.hashCode(); + } + + /** + * Returns the actual key's hash code. + */ + public int hashCode() { + return hashCode; + } + + /** + * Compares by reference. + */ + public boolean equals(Object anObject) { + if (anObject == this) + return true; + if (anObject instanceof ReferenceKey) { + return ((ReferenceKey) anObject).get() == referent; + } + return false; + } + } + + /** + * Private class used to force a hashmap to perform key comparisons by + * reference. + */ + static private class WeakReferenceKey extends ReferenceKey { + public WeakReferenceKey() { + super(); + } + + public WeakReferenceKey(Object anObject) { + super(anObject); + } + + public Object get() { + return ((WeakReference) referent).get(); + } + + public void set(Object anObject) { + referent = new WeakReference(anObject); + hashCode = anObject.hashCode(); + } + + /** + * Compares by reference. + */ + public boolean equals(Object anObject) { + if (anObject == this) + return true; + if (anObject instanceof ReferenceKey) { + return ((ReferenceKey) anObject).get() == get(); + } + return false; + } + } + + /** + * Key combining an object with a string. Object is compared by reference. + */ + static private class CompoundKey { + private Object object; + private String string; + private int hashCode; + + /** + * Creates compound key. Neither name nor object may be null. + */ + public CompoundKey(Object anObject, String aString) { + object = anObject; + string = aString; + hashCode = object.hashCode() + string.hashCode(); + } + + public int hashCode() { + return hashCode; + } + + public boolean equals(Object anObject) { + if (anObject instanceof CompoundKey) { + CompoundKey key = (CompoundKey) anObject; + return ((key.object == object) && (key.string.equals(string))); + } + return false; + } + + public String toString() { + return "[CompoundKey:" + object + ":" + string + "]"; + } + } + + /** + * Used by EditingContext to delegate behavior to another class. Note that + * EditingContext doesn't require its delegates to implement this interface: + * rather, this interface defines the methods that EditingContext will attempt + * to invoke dynamically on its delegate. The delegate may choose to implement + * only a subset of the methods on the interface. + */ + public interface Delegate { + /** + * Called after the editing context has completed merge operations on one or + * more objects after receiving an ObjectChangedInStore notification. + */ + void editingContextDidMergeChanges(EOEditingContext anEditingContext); + + /** + * Called by objectsWithFetchSpecification. If null, the editing context will + * pass the fetch specification on to its parent store, as normal. Otherwise, + * the context will use the returned array to service the request. + */ + NSArray editingContextShouldFetchObjects(EOEditingContext anEditingContext, + EOFetchSpecification fetchSpecification); + + /** + * Called to determine whether an object should be invalidated. Return false to + * prevent the object from being invalidated. Default is true. + */ + boolean editingContextShouldInvalidateObject(EOEditingContext anEditingContext, Object anObject, + EOGlobalID aGlobalID); + + /** + * Called to determine whether the editing context should attempt to merge + * changes in the specified object that the parent store says has changed via an + * ObjectChangedInStore notification. Default is true. Return false if you wish + * to handle the merge yourself, by extracting the values in the object now and + * comparing them to the values when editingContextDidMergeChanges is called. + */ + boolean editingContextShouldMergeChangesForObject(EOEditingContext anEditingContext, Object anObject); + + /** + * Returns whether the editing context should ask its message handler to display + * a message. Return false if the delegate will display the error. Default is + * true. + */ + boolean editingContextShouldPresentException(EOEditingContext anEditingContext, Throwable exception); + + /** + * Returns whether the editing context should undo the most recent set of + * changes that resulted in a validation failure. Default is true. + */ + boolean editingContextShouldUndoUserActionsAfterFailure(EOEditingContext anEditingContext); + + /** + * Returns whether the editing context should validate the most recent set of + * changes. Default is true. + */ + boolean editingContextShouldValidateChanges(EOEditingContext anEditingContext); + + /** + * Called before the editing context saves its changes to the parent object + * store. + */ + void editingContextWillSaveChanges(EOEditingContext anEditingContext); + + } + + /** + * Editors register themselves with the editing context so that they may receive + * notification before the context commits changes. This is useful for + * associations whose components do not immediately commit their changes to the + * object they are editing. + */ + public interface Editor { + /** + * Called before the editing context saves its changes to the parent object + * store. + */ + void editingContextWillSaveChanges(EOEditingContext anEditingContext); + + /** + * Called to determine whether this editor has changes that have not been + * committed to the object in the context. + */ + boolean editorHasChangesForEditingContext(EOEditingContext anEditingContext); + + } + + /** + * Used by EditingContext to delegate messaging handling to another class, + * typically the display group that has the currently active association. Note + * that EditingContext doesn't require its message handlers to implement this + * interface: rather, this interface defines the methods that EditingContext + * will attempt to invoke dynamically on its delegate. The delegate may choose + * to implement only a subset of the methods on the interface. + */ + public interface MessageHandler { + /** + * Called to display a message for an error that occurred in the specified + * editing context. + */ + void editingContextPresentErrorMessage(EOEditingContext anEditingContext, String aMessage); + + /** + * Called by the specified object store to determine whether fetching should + * continue, where count is the current count and limit is the limit as + * specified by the fetch specification. Default is false. + */ + boolean editingContextShouldContinueFetching(EOEditingContext anEditingContext, int count, int limit, + EOObjectStore anObjectStore); + + } + } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.86 2003/12/18 15:37:38 mpowers - * Changes to retain ability to work with objects that don't necessarily - * implement EOEnterpriseObject. I would still like to preserve this case - * for general usage, however the access package is free to assume that - * those objects will be EOs and cast appropriately. + * Revision 1.86 2003/12/18 15:37:38 mpowers Changes to retain ability to work + * with objects that don't necessarily implement EOEnterpriseObject. I would + * still like to preserve this case for general usage, however the access + * package is free to assume that those objects will be EOs and cast + * appropriately. * - * Revision 1.85 2003/08/19 01:53:12 chochos - * EOObjectStore had some incompatible return types (Object instead of EOEnterpriseObject, in fault methods mostly). It's internally consistent but I hope it doesn't break anything based on this, even though fault methods mostly throw exceptions for now. + * Revision 1.85 2003/08/19 01:53:12 chochos EOObjectStore had some incompatible + * return types (Object instead of EOEnterpriseObject, in fault methods mostly). + * It's internally consistent but I hope it doesn't break anything based on + * this, even though fault methods mostly throw exceptions for now. * - * Revision 1.84 2003/08/06 23:07:52 chochos - * general code cleanup (mostly, removing unused imports) + * Revision 1.84 2003/08/06 23:07:52 chochos general code cleanup (mostly, + * removing unused imports) * - * Revision 1.83 2003/02/13 15:24:33 mpowers - * hasChanges is now derived, not tracked. - * refaultObject now more consistently removes object from updated list. + * Revision 1.83 2003/02/13 15:24:33 mpowers hasChanges is now derived, not + * tracked. refaultObject now more consistently removes object from updated + * list. * - * Revision 1.82 2002/12/16 15:46:00 mpowers - * Major refactoring to implement setInstancesRetainRegisteredObjects(). + * Revision 1.82 2002/12/16 15:46:00 mpowers Major refactoring to implement + * setInstancesRetainRegisteredObjects(). * - * Revision 1.81 2002/11/18 22:10:58 mpowers - * Now resetting hasChanges flag on reset. + * Revision 1.81 2002/11/18 22:10:58 mpowers Now resetting hasChanges flag on + * reset. * - * Revision 1.80 2002/10/24 21:15:33 mpowers - * New implementations of NSArray and subclasses. + * Revision 1.80 2002/10/24 21:15:33 mpowers New implementations of NSArray and + * subclasses. * - * Revision 1.79 2002/10/24 18:18:12 mpowers - * NSArray's are now considered read-only, so we can return our internal - * representation to reduce unnecessary object allocation. + * Revision 1.79 2002/10/24 18:18:12 mpowers NSArray's are now considered + * read-only, so we can return our internal representation to reduce unnecessary + * object allocation. * - * Revision 1.78 2002/06/21 21:44:33 mpowers - * No longer marking deleted objects as updated (thanks to dwang). + * Revision 1.78 2002/06/21 21:44:33 mpowers No longer marking deleted objects + * as updated (thanks to dwang). * - * Revision 1.77 2002/05/20 15:10:17 mpowers - * No longer refaulting if delegate does not wish to handle the merge. + * Revision 1.77 2002/05/20 15:10:17 mpowers No longer refaulting if delegate + * does not wish to handle the merge. * - * Revision 1.76 2002/03/26 21:46:06 mpowers - * Contributing EditingContext as a java-friendly convenience. + * Revision 1.76 2002/03/26 21:46:06 mpowers Contributing EditingContext as a + * java-friendly convenience. * - * Revision 1.75 2002/03/06 16:14:57 mpowers - * More attempts at ignoring update conflicts that come from ourself. + * Revision 1.75 2002/03/06 16:14:57 mpowers More attempts at ignoring update + * conflicts that come from ourself. * - * Revision 1.74 2002/02/21 21:57:50 mpowers - * Implemented default merge behavior. + * Revision 1.74 2002/02/21 21:57:50 mpowers Implemented default merge behavior. * - * Revision 1.73 2002/02/20 16:46:54 mpowers - * Implemented better support for EOEditingContext.Delegate. + * Revision 1.73 2002/02/20 16:46:54 mpowers Implemented better support for + * EOEditingContext.Delegate. * - * Revision 1.70 2002/02/19 22:26:05 mpowers - * Implemented EOEditingContext.MessageHandler support. + * Revision 1.70 2002/02/19 22:26:05 mpowers Implemented + * EOEditingContext.MessageHandler support. * - * Revision 1.69 2002/02/19 16:33:42 mpowers - * Implemented support for EditingContext.Editor + * Revision 1.69 2002/02/19 16:33:42 mpowers Implemented support for + * EditingContext.Editor * - * Revision 1.68 2002/02/13 22:00:34 mpowers - * Fixed: invalidateAllObjects tries to invalidate inserted objects, - * typically causing class cast exceptions involving EOTemporaryGlobalID. + * Revision 1.68 2002/02/13 22:00:34 mpowers Fixed: invalidateAllObjects tries + * to invalidate inserted objects, typically causing class cast exceptions + * involving EOTemporaryGlobalID. * - * Revision 1.67 2002/02/06 21:15:35 mpowers - * No longer refaulting a dirty object when we receive an invalidation notif. + * Revision 1.67 2002/02/06 21:15:35 mpowers No longer refaulting a dirty object + * when we receive an invalidation notif. * - * Revision 1.66 2002/01/08 19:31:03 mpowers - * refaultObject now correctly refaults the object. + * Revision 1.66 2002/01/08 19:31:03 mpowers refaultObject now correctly + * refaults the object. * - * Revision 1.65 2001/12/20 18:56:15 mpowers - * Refinements to snapshotting and calling processRecentChanges. + * Revision 1.65 2001/12/20 18:56:15 mpowers Refinements to snapshotting and + * calling processRecentChanges. * - * Revision 1.64 2001/12/10 15:11:41 mpowers - * Now only tracking a commit snapshot after an object has been modified. + * Revision 1.64 2001/12/10 15:11:41 mpowers Now only tracking a commit snapshot + * after an object has been modified. * - * Revision 1.63 2001/11/14 00:08:10 mpowers - * Now marking context changed when objects are inserted or deleted - * and when child contexts save their changes into this context. + * Revision 1.63 2001/11/14 00:08:10 mpowers Now marking context changed when + * objects are inserted or deleted and when child contexts save their changes + * into this context. * - * Revision 1.62 2001/11/07 14:49:31 mpowers - * invalidateAllObjects now handles objects manually discarded in the course - * of invalidation. + * Revision 1.62 2001/11/07 14:49:31 mpowers invalidateAllObjects now handles + * objects manually discarded in the course of invalidation. * - * Revision 1.61 2001/10/26 20:02:49 mpowers - * No longer using NSNotificationQueue: all notifications are posted immed. + * Revision 1.61 2001/10/26 20:02:49 mpowers No longer using + * NSNotificationQueue: all notifications are posted immed. * - * Revision 1.60 2001/10/26 18:37:50 mpowers - * Now using NSRunLoop to correctly flush recent changes before delayed - * observers and AWT events. + * Revision 1.60 2001/10/26 18:37:50 mpowers Now using NSRunLoop to correctly + * flush recent changes before delayed observers and AWT events. * - * Revision 1.59 2001/10/23 22:29:59 mpowers - * Now posting notifications immediately. - * Recent changes are flushed at ObserverPrioritySixth, soon to change. + * Revision 1.59 2001/10/23 22:29:59 mpowers Now posting notifications + * immediately. Recent changes are flushed at ObserverPrioritySixth, soon to + * change. * - * Revision 1.58 2001/09/10 14:16:51 mpowers - * EditingContexts now relay InvalidatedAllObjectsInStore notifications. + * Revision 1.58 2001/09/10 14:16:51 mpowers EditingContexts now relay + * InvalidatedAllObjectsInStore notifications. * - * Revision 1.57 2001/06/18 14:11:15 mpowers - * Inserting a deleted object simply cancels the delete operation. + * Revision 1.57 2001/06/18 14:11:15 mpowers Inserting a deleted object simply + * cancels the delete operation. * - * Revision 1.56 2001/06/07 22:07:59 mpowers - * Now handling delete notifications before update notifications. - * Eliminated the case where deleted objects were also being put - * on the updated list when notifying child contexts. + * Revision 1.56 2001/06/07 22:07:59 mpowers Now handling delete notifications + * before update notifications. Eliminated the case where deleted objects were + * also being put on the updated list when notifying child contexts. * - * Revision 1.55 2001/05/18 21:04:33 mpowers - * Reimplemented EditingContext.initializeObject. + * Revision 1.55 2001/05/18 21:04:33 mpowers Reimplemented + * EditingContext.initializeObject. * - * Revision 1.54 2001/05/05 23:05:42 mpowers - * Implemented Array Faults. + * Revision 1.54 2001/05/05 23:05:42 mpowers Implemented Array Faults. * - * Revision 1.53 2001/05/05 15:00:06 mpowers - * Tested load-on-demand: still works. - * Now using registerClone for consistency. - * Editing context is temporarily posting notification on objectWillChange. + * Revision 1.53 2001/05/05 15:00:06 mpowers Tested load-on-demand: still works. + * Now using registerClone for consistency. Editing context is temporarily + * posting notification on objectWillChange. * - * Revision 1.52 2001/05/05 14:11:48 mpowers - * Implemented registerClone. + * Revision 1.52 2001/05/05 14:11:48 mpowers Implemented registerClone. * - * Revision 1.51 2001/05/04 16:57:56 mpowers - * Now correctly transposing references to editing contexts when - * cloning/copying between editing contexts. + * Revision 1.51 2001/05/04 16:57:56 mpowers Now correctly transposing + * references to editing contexts when cloning/copying between editing contexts. * - * Revision 1.50 2001/05/02 17:58:41 mpowers - * Removed debugging code, added comments. + * Revision 1.50 2001/05/02 17:58:41 mpowers Removed debugging code, added + * comments. * - * Revision 1.49 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.49 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.48 2001/05/02 12:39:05 mpowers - * Fixed a nasty problem with transpose-cloning and faultForGlobalID. - * Now we're forced to create a deep clone, registered it, and then - * transpose it after it has been registered. + * Revision 1.48 2001/05/02 12:39:05 mpowers Fixed a nasty problem with + * transpose-cloning and faultForGlobalID. Now we're forced to create a deep + * clone, registered it, and then transpose it after it has been registered. * - * Revision 1.47 2001/04/30 13:15:24 mpowers - * Child contexts re-initializing objects invalidated in parent now - * propery transpose relationships. + * Revision 1.47 2001/04/30 13:15:24 mpowers Child contexts re-initializing + * objects invalidated in parent now propery transpose relationships. * - * Revision 1.46 2001/04/29 22:02:45 mpowers - * Work on id transposing between editing contexts. + * Revision 1.46 2001/04/29 22:02:45 mpowers Work on id transposing between + * editing contexts. * - * Revision 1.45 2001/04/29 02:29:31 mpowers - * Debugging relationship faulting. + * Revision 1.45 2001/04/29 02:29:31 mpowers Debugging relationship faulting. * - * Revision 1.44 2001/04/28 16:18:44 mpowers - * Implementing relationships. + * Revision 1.44 2001/04/28 16:18:44 mpowers Implementing relationships. * - * Revision 1.43 2001/04/28 14:12:23 mpowers - * Refactored cloning/copying into KeyValueCodingUtilities. + * Revision 1.43 2001/04/28 14:12:23 mpowers Refactored cloning/copying into + * KeyValueCodingUtilities. * - * Revision 1.42 2001/04/27 00:27:11 mpowers - * Provided description to not-implemented exceptions. + * Revision 1.42 2001/04/27 00:27:11 mpowers Provided description to + * not-implemented exceptions. * - * Revision 1.41 2001/04/26 01:16:44 mpowers - * Major bug fix so we no longer accumulate objects in the all objects - * list with every InvalidateAllObjectsInStore. + * Revision 1.41 2001/04/26 01:16:44 mpowers Major bug fix so we no longer + * accumulate objects in the all objects list with every + * InvalidateAllObjectsInStore. * - * Revision 1.40 2001/04/21 23:07:49 mpowers - * Now only broadcasts notifications if there's actually a change. + * Revision 1.40 2001/04/21 23:07:49 mpowers Now only broadcasts notifications + * if there's actually a change. * - * Revision 1.39 2001/04/13 16:33:11 mpowers - * Corrected the refaulting behavior. + * Revision 1.39 2001/04/13 16:33:11 mpowers Corrected the refaulting behavior. * - * Revision 1.38 2001/04/09 21:42:10 mpowers - * Debugging and optimizing notifications. + * Revision 1.38 2001/04/09 21:42:10 mpowers Debugging and optimizing + * notifications. * - * Revision 1.37 2001/04/08 20:59:47 mpowers - * objectsForFetchSpecification now relies on faultForGlobalID. + * Revision 1.37 2001/04/08 20:59:47 mpowers objectsForFetchSpecification now + * relies on faultForGlobalID. * - * Revision 1.36 2001/04/03 20:36:01 mpowers - * Fixed refaulting/reverting/invalidating to be self-consistent. + * Revision 1.36 2001/04/03 20:36:01 mpowers Fixed + * refaulting/reverting/invalidating to be self-consistent. * - * Revision 1.35 2001/03/29 03:29:49 mpowers - * Now using KeyValueCoding and Support instead of Introspector. + * Revision 1.35 2001/03/29 03:29:49 mpowers Now using KeyValueCoding and + * Support instead of Introspector. * - * Revision 1.34 2001/03/28 14:06:29 mpowers - * Implemented snapshots. Revert now uses snapshots. + * Revision 1.34 2001/03/28 14:06:29 mpowers Implemented snapshots. Revert now + * uses snapshots. * - * Revision 1.33 2001/03/20 23:20:33 mpowers - * invalidating all objects now sets the dirty flag to false. + * Revision 1.33 2001/03/20 23:20:33 mpowers invalidating all objects now sets + * the dirty flag to false. * - * Revision 1.32 2001/03/19 21:44:36 mpowers - * Reverts reinitialize for now. + * Revision 1.32 2001/03/19 21:44:36 mpowers Reverts reinitialize for now. * Testing for inserted objects instead of temp id when invalidating object. * - * Revision 1.31 2001/03/15 21:10:26 mpowers - * Implemented global id re-registration for newly saved inserts. + * Revision 1.31 2001/03/15 21:10:26 mpowers Implemented global id + * re-registration for newly saved inserts. * - * Revision 1.30 2001/03/13 21:41:34 mpowers - * Broadcasting willChange for any change to hasChanges. - * Fixed major bug with inserted objects treated as updated objects - * in child display groups. + * Revision 1.30 2001/03/13 21:41:34 mpowers Broadcasting willChange for any + * change to hasChanges. Fixed major bug with inserted objects treated as + * updated objects in child display groups. * - * Revision 1.29 2001/03/09 22:10:30 mpowers - * Fine tuned initializeObject. + * Revision 1.29 2001/03/09 22:10:30 mpowers Fine tuned initializeObject. * - * Revision 1.28 2001/03/06 23:23:55 mpowers - * objectForGlobalID now returns null if not found. - * objectsForFetchSpecification again does things the old way, for now. + * Revision 1.28 2001/03/06 23:23:55 mpowers objectForGlobalID now returns null + * if not found. objectsForFetchSpecification again does things the old way, for + * now. * - * Revision 1.27 2001/03/02 16:31:45 mpowers - * Trying to better handle fetches from child contexts. - * No longer trying to invalidate temporary objects. + * Revision 1.27 2001/03/02 16:31:45 mpowers Trying to better handle fetches + * from child contexts. No longer trying to invalidate temporary objects. * - * Revision 1.26 2001/02/28 16:25:19 mpowers - * Now calling globalIDForObject internally. + * Revision 1.26 2001/02/28 16:25:19 mpowers Now calling globalIDForObject + * internally. * - * Revision 1.25 2001/02/27 17:36:55 mpowers - * Objects inserted from child now preserve the existing temporary id. + * Revision 1.25 2001/02/27 17:36:55 mpowers Objects inserted from child now + * preserve the existing temporary id. * - * Revision 1.24 2001/02/27 02:11:17 mpowers - * Now throwing exception when cloning fails. - * Removed debugging printlns. + * Revision 1.24 2001/02/27 02:11:17 mpowers Now throwing exception when cloning + * fails. Removed debugging printlns. * - * Revision 1.23 2001/02/26 22:41:51 mpowers - * Implemented null placeholder classes. - * Duplicator now uses NSNull. - * No longer catching base exception class. + * Revision 1.23 2001/02/26 22:41:51 mpowers Implemented null placeholder + * classes. Duplicator now uses NSNull. No longer catching base exception class. * - * Revision 1.22 2001/02/26 21:18:45 mpowers - * Now marking edited objects from child contexts that were not already - * recorded in parent as changed in saveChangesInEditingContext. + * Revision 1.22 2001/02/26 21:18:45 mpowers Now marking edited objects from + * child contexts that were not already recorded in parent as changed in + * saveChangesInEditingContext. * - * Revision 1.21 2001/02/26 15:53:22 mpowers - * Fine-tuning notification firing. + * Revision 1.21 2001/02/26 15:53:22 mpowers Fine-tuning notification firing. * Child display groups now update properly after parent save or invalidate. * - * Revision 1.20 2001/02/24 17:03:22 mpowers - * Implemented the notification queue, and changed editing context to use it. + * Revision 1.20 2001/02/24 17:03:22 mpowers Implemented the notification queue, + * and changed editing context to use it. * - * Revision 1.19 2001/02/23 23:44:15 mpowers - * Fine-tuning notification handling. + * Revision 1.19 2001/02/23 23:44:15 mpowers Fine-tuning notification handling. * - * Revision 1.18 2001/02/22 22:56:57 mpowers - * Only refaulting edited objects on parent store invalidateAll. + * Revision 1.18 2001/02/22 22:56:57 mpowers Only refaulting edited objects on + * parent store invalidateAll. * - * Revision 1.17 2001/02/22 20:54:39 mpowers - * Implemented notification handling. + * Revision 1.17 2001/02/22 20:54:39 mpowers Implemented notification handling. * - * Revision 1.16 2001/02/21 22:10:55 mpowers - * Editing context is now posting appropriate notifications. + * Revision 1.16 2001/02/21 22:10:55 mpowers Editing context is now posting + * appropriate notifications. * - * Revision 1.15 2001/02/21 21:17:32 mpowers - * Now retaining a reference to the recent changes observer. - * Better documented need to retain reference. - * Started implementing notifications. + * Revision 1.15 2001/02/21 21:17:32 mpowers Now retaining a reference to the + * recent changes observer. Better documented need to retain reference. Started + * implementing notifications. * - * Revision 1.14 2001/02/20 17:24:22 mpowers - * Now using reference keys in objectToID. + * Revision 1.14 2001/02/20 17:24:22 mpowers Now using reference keys in + * objectToID. * - * Revision 1.13 2001/02/20 16:45:36 mpowers - * Child data sources now accept a data source instead of an editing context - * for more flexibility. Child data sources now forward relationship - * methods to parent source. + * Revision 1.13 2001/02/20 16:45:36 mpowers Child data sources now accept a + * data source instead of an editing context for more flexibility. Child data + * sources now forward relationship methods to parent source. * - * Revision 1.12 2001/02/16 22:51:29 mpowers - * Now deep-cloning objects passed between editing contexts. + * Revision 1.12 2001/02/16 22:51:29 mpowers Now deep-cloning objects passed + * between editing contexts. * - * Revision 1.11 2001/02/16 18:34:19 mpowers - * Implementing nested contexts. + * Revision 1.11 2001/02/16 18:34:19 mpowers Implementing nested contexts. * - * Revision 1.9 2001/02/15 21:13:30 mpowers - * First draft implementation is complete. Now on to debugging. + * Revision 1.9 2001/02/15 21:13:30 mpowers First draft implementation is + * complete. Now on to debugging. * - * Revision 1.7 2001/02/13 23:24:29 mpowers - * Implementing more of editing context. + * Revision 1.7 2001/02/13 23:24:29 mpowers Implementing more of editing + * context. * - * Revision 1.4 2001/02/09 22:09:34 mpowers - * Completed implementation of EOObjectStore. + * Revision 1.4 2001/02/09 22:09:34 mpowers Completed implementation of + * EOObjectStore. * - * Revision 1.3 2001/02/06 15:24:11 mpowers - * Widened parameters on abstract method to fix build. + * Revision 1.3 2001/02/06 15:24:11 mpowers Widened parameters on abstract + * method to fix build. * - * Revision 1.2 2001/02/05 03:45:37 mpowers - * Starting work on EOEditingContext. + * Revision 1.2 2001/02/05 03:45:37 mpowers Starting work on EOEditingContext. * - * Revision 1.1.1.1 2000/12/21 15:46:42 mpowers - * Contributing wotonomy. + * Revision 1.1.1.1 2000/12/21 15:46:42 mpowers Contributing wotonomy. * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOEnterpriseObject.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOEnterpriseObject.java index 112531c..db03a22 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOEnterpriseObject.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOEnterpriseObject.java @@ -22,198 +22,180 @@ import net.wotonomy.foundation.NSArray; import net.wotonomy.foundation.NSDictionary; /** -* EOEnterpriseObject defines the required methods a data object -* must implement to take full advantage of the control package. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * EOEnterpriseObject defines the required methods a data object must implement + * to take full advantage of the control package. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public interface EOEnterpriseObject - extends EOKeyValueCodingAdditions, - EORelationshipManipulation, - EODeferredFaulting, - EOValidation -{ - /** - * Returns a List of all property keys defined on this object. - * This includes both attributes and relationships. - */ - NSArray allPropertyKeys(); - - /** - * Returns a list of all attributes defined on this object. - * Attributes are all properties that are not relationships. - */ - NSArray attributeKeys(); - - //void awakeFromClientUpdate(EOEditingContext aContext) - - /** - * Called when the object has first been fetched into the - * specified editing context. - */ - void awakeFromFetch(EOEditingContext anEditingContext); - - /** - * Called when the object has been inserted into the - * specified editing context. - */ - void awakeFromInsertion(EOEditingContext anEditingContext); - - /** - * Returns a Map representing the delta of the current state - * from the state represented in the specified snapshot. - * The result will contain only the keys that have changed - * and their values. Relationship keys will map to an NSArray - * that contains an NSArray of added objects and an NSArray - * of removed objects, in that order. - */ - NSDictionary changesFromSnapshot(NSDictionary snapshot); - - /** - * Returns a class description for this object. - */ - EOClassDescription classDescription(); - - /** - * Returns a class description for the object at the - * other end of the specified relationship key. - */ - EOClassDescription classDescriptionForDestinationKey(String aKey); - - /** - * Clears all property values for this object. - * This method is called to clean-up an object that - * will no longer be used, and implementations should - * ensure that all references are set to null to - * prevent problems with garbage-collection. - */ - void clearProperties(); - - /** - * Returns the delete rule constant defined on EOClassDescription - * for the relationship defined by the specified key. - */ - int deleteRuleForRelationshipKey(String aRelationshipKey); - - /** - * Returns the editing context in which this object is registered. - */ - EOEditingContext editingContext(); - - /** - * Returns the name of the entity that this object represents. - */ - String entityName(); - - /** - * Returns a String containing all property keys and values for - * this object. Relationships should be represented by calling - * eoShallowDescription() on the object. - */ - String eoDescription(); - - /** - * Returns a String containing all attribute keys and values for - * this object. Relationships are not included. - */ - String eoShallowDescription(); - - /** - * Returns the key used to reference this object on the - * object at the other end of the specified relationship. - */ - String inverseForRelationshipKey(String aRelationshipKey); - - //Object invokeRemoteMethod( - // String aMethodName, Class[] aTypeArray Object[] anArgumentArray) - - /** - * Returns whether the specified relationship key represents - * a to-many relationship. - */ - boolean isToManyKey(String aKey); - - /** - * Returns whether the objects at the other end of the specified - * relationship should be deleted when this object is deleted. - */ - boolean ownsDestinationObjectsForRelationshipKey(String aKey); - - //void prepareValuesForClient() - - /** - * Called to perform the delete propagation for this object - * on the specified editing context. All relationships - * should be processed according to their corresponding - * delete rule. - */ - void propagateDeleteWithEditingContext(EOEditingContext aContext); - - /** - * Applies the changes from the specified snapshot to - * this object. - * @see #changesFromSnapshot(NSDictionary) - */ - void reapplyChangesFromDictionary(NSDictionary aDeltaSnapshot); - - /** - * Returns a snapshot of the current state of this object. - * All property keys are mapped to their values; nulls are - * represented by NSNull. - */ - NSDictionary snapshot(); - - /** - * Returns a List of the to-many relationship keys - * for this object. - */ - NSArray toManyRelationshipKeys(); - - /** - * Returns a List of the to-one relationship keys - * for this object. - */ - NSArray toOneRelationshipKeys(); - - /** - * Applies the specified snapshot to this object, - * converting NSNulls to null and calling - * takeStoredValueForKey for each key in the Map. - */ - void updateFromSnapshot(NSDictionary aSnapshot); - - /** - * Returns a short, stateful string representation - * of this object. - */ - String userPresentableDescription(); - - /** - * This method should be implemented to call - * EOObserverCenter.objectWillChange( this ), - * and it should be called by each setter method - * on this object before changes are made to the - * object's internal state. - */ - void willChange(); + extends EOKeyValueCodingAdditions, EORelationshipManipulation, EODeferredFaulting, EOValidation { + /** + * Returns a List of all property keys defined on this object. This includes + * both attributes and relationships. + */ + NSArray allPropertyKeys(); + + /** + * Returns a list of all attributes defined on this object. Attributes are all + * properties that are not relationships. + */ + NSArray attributeKeys(); + + // void awakeFromClientUpdate(EOEditingContext aContext) + + /** + * Called when the object has first been fetched into the specified editing + * context. + */ + void awakeFromFetch(EOEditingContext anEditingContext); + + /** + * Called when the object has been inserted into the specified editing context. + */ + void awakeFromInsertion(EOEditingContext anEditingContext); + + /** + * Returns a Map representing the delta of the current state from the state + * represented in the specified snapshot. The result will contain only the keys + * that have changed and their values. Relationship keys will map to an NSArray + * that contains an NSArray of added objects and an NSArray of removed objects, + * in that order. + */ + NSDictionary changesFromSnapshot(NSDictionary snapshot); + + /** + * Returns a class description for this object. + */ + EOClassDescription classDescription(); + + /** + * Returns a class description for the object at the other end of the specified + * relationship key. + */ + EOClassDescription classDescriptionForDestinationKey(String aKey); + + /** + * Clears all property values for this object. This method is called to clean-up + * an object that will no longer be used, and implementations should ensure that + * all references are set to null to prevent problems with garbage-collection. + */ + void clearProperties(); + + /** + * Returns the delete rule constant defined on EOClassDescription for the + * relationship defined by the specified key. + */ + int deleteRuleForRelationshipKey(String aRelationshipKey); + + /** + * Returns the editing context in which this object is registered. + */ + EOEditingContext editingContext(); + + /** + * Returns the name of the entity that this object represents. + */ + String entityName(); + + /** + * Returns a String containing all property keys and values for this object. + * Relationships should be represented by calling eoShallowDescription() on the + * object. + */ + String eoDescription(); + + /** + * Returns a String containing all attribute keys and values for this object. + * Relationships are not included. + */ + String eoShallowDescription(); + + /** + * Returns the key used to reference this object on the object at the other end + * of the specified relationship. + */ + String inverseForRelationshipKey(String aRelationshipKey); + + // Object invokeRemoteMethod( + // String aMethodName, Class[] aTypeArray Object[] anArgumentArray) + + /** + * Returns whether the specified relationship key represents a to-many + * relationship. + */ + boolean isToManyKey(String aKey); + + /** + * Returns whether the objects at the other end of the specified relationship + * should be deleted when this object is deleted. + */ + boolean ownsDestinationObjectsForRelationshipKey(String aKey); + + // void prepareValuesForClient() + + /** + * Called to perform the delete propagation for this object on the specified + * editing context. All relationships should be processed according to their + * corresponding delete rule. + */ + void propagateDeleteWithEditingContext(EOEditingContext aContext); + + /** + * Applies the changes from the specified snapshot to this object. + * + * @see #changesFromSnapshot(NSDictionary) + */ + void reapplyChangesFromDictionary(NSDictionary aDeltaSnapshot); + + /** + * Returns a snapshot of the current state of this object. All property keys are + * mapped to their values; nulls are represented by NSNull. + */ + NSDictionary snapshot(); + + /** + * Returns a List of the to-many relationship keys for this object. + */ + NSArray toManyRelationshipKeys(); + + /** + * Returns a List of the to-one relationship keys for this object. + */ + NSArray toOneRelationshipKeys(); + + /** + * Applies the specified snapshot to this object, converting NSNulls to null and + * calling takeStoredValueForKey for each key in the Map. + */ + void updateFromSnapshot(NSDictionary aSnapshot); + + /** + * Returns a short, stateful string representation of this object. + */ + String userPresentableDescription(); + + /** + * This method should be implemented to call EOObserverCenter.objectWillChange( + * this ), and it should be called by each setter method on this object before + * changes are made to the object's internal state. + */ + void willChange(); } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.1 2001/11/13 04:13:59 mpowers - * Added interfaces needed to begin work on EOCustomObject. + * Revision 1.1 2001/11/13 04:13:59 mpowers Added interfaces needed to begin + * work on EOCustomObject. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOFaultHandler.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOFaultHandler.java index 19dc2df..e407492 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOFaultHandler.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOFaultHandler.java @@ -19,14 +19,13 @@ License along with this library; if not, see http://www.gnu.org package net.wotonomy.control; /** -* EOFaultHandler defines the contract for objects that can -* create and populate faults. In wotonomy, this interface is -* currently only a marker interface. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 893 $ -*/ + * EOFaultHandler defines the contract for objects that can create and populate + * faults. In wotonomy, this interface is currently only a marker interface. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 893 $ + */ public abstract class EOFaultHandler { protected Class _targetClass; @@ -38,7 +37,7 @@ public abstract class EOFaultHandler { public static EOFaultHandler handlerForFault(Object obj) { if (!(obj instanceof EOFaulting)) throw new IllegalArgumentException("Object must implement EOFaulting"); - return ((EOFaulting)obj).faultHandler(); + return ((EOFaulting) obj).faultHandler(); } public static boolean isFault(Object obj) { @@ -46,20 +45,20 @@ public abstract class EOFaultHandler { return false; boolean isit = (obj instanceof EOFaulting); if (isit) - isit = ((EOFaulting)obj).isFault(); + isit = ((EOFaulting) obj).isFault(); return isit; } public static void makeObjectIntoFault(Object obj, EOFaultHandler handler) { if (!(obj instanceof EOFaulting)) throw new IllegalArgumentException("Object must implement EOFaulting"); - ((EOFaulting)obj).turnIntoFault(handler); + ((EOFaulting) obj).turnIntoFault(handler); } public static void clearFault(Object obj) { if (!(obj instanceof EOFaulting)) throw new IllegalArgumentException("Object must implement EOFaulting"); - ((EOFaulting)obj).clearFault(); + ((EOFaulting) obj).clearFault(); } public Class targetClass() { @@ -87,16 +86,15 @@ public abstract class EOFaultHandler { } /* - * $Log$ - * Revision 1.1 2006/02/16 13:19:57 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. + * $Log$ Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.2 2003/08/19 01:53:12 chochos - * EOObjectStore had some incompatible return types (Object instead of EOEnterpriseObject, in fault methods mostly). It's internally consistent but I hope it doesn't break anything based on this, even though fault methods mostly throw exceptions for now. + * Revision 1.2 2003/08/19 01:53:12 chochos EOObjectStore had some incompatible + * return types (Object instead of EOEnterpriseObject, in fault methods mostly). + * It's internally consistent but I hope it doesn't break anything based on + * this, even though fault methods mostly throw exceptions for now. * - * Revision 1.1 2001/11/13 04:13:59 mpowers - * Added interfaces needed to begin work on EOCustomObject. + * Revision 1.1 2001/11/13 04:13:59 mpowers Added interfaces needed to begin + * work on EOCustomObject. * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOFaulting.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOFaulting.java index 95b3e35..f468949 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOFaulting.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOFaulting.java @@ -19,61 +19,56 @@ License along with this library; if not, see http://www.gnu.org package net.wotonomy.control; /** -* EOFaulting defines the requirements for objects that -* can be faulted by an EOFaultManager. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 893 $ -*/ -public interface EOFaulting -{ - /** - * Called by EOFaultHandler to prepare the object to be turned into a fault. - */ - void clearFault(); - - /** - * Returns this object's EOFaultHandler. - */ - EOFaultHandler faultHandler(); - - /** - * Returns whether this object is currently a fault. - * Returns true if this object has not yet retrieved any values. - */ - boolean isFault(); - - /** - * Turns this object into a fault using the specified fault handler. - */ - void turnIntoFault( EOFaultHandler aFaultHandler ); - - /** - * Called to completely fire the fault, reading all values. - * This method may be implemented to call willRead(null). - */ - void willRead(); - - /** - * Called to fire the fault for the specified key. - * The fault manager is required to populate the specified key - * with a value, and may populate any or all of the other values - * on this object. A null key will populate all values on the object. - * NOTE: This method is not part of the specification. - */ - void willRead( String aKey ); + * EOFaulting defines the requirements for objects that can be faulted by an + * EOFaultManager. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 893 $ + */ +public interface EOFaulting { + /** + * Called by EOFaultHandler to prepare the object to be turned into a fault. + */ + void clearFault(); + + /** + * Returns this object's EOFaultHandler. + */ + EOFaultHandler faultHandler(); + + /** + * Returns whether this object is currently a fault. Returns true if this object + * has not yet retrieved any values. + */ + boolean isFault(); + + /** + * Turns this object into a fault using the specified fault handler. + */ + void turnIntoFault(EOFaultHandler aFaultHandler); + + /** + * Called to completely fire the fault, reading all values. This method may be + * implemented to call willRead(null). + */ + void willRead(); + + /** + * Called to fire the fault for the specified key. The fault manager is required + * to populate the specified key with a value, and may populate any or all of + * the other values on this object. A null key will populate all values on the + * object. NOTE: This method is not part of the specification. + */ + void willRead(String aKey); } /* - * $Log$ - * Revision 1.1 2006/02/16 13:19:57 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. + * $Log$ Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.1 2001/11/13 04:13:59 mpowers - * Added interfaces needed to begin work on EOCustomObject. + * Revision 1.1 2001/11/13 04:13:59 mpowers Added interfaces needed to begin + * work on EOCustomObject. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOFetchSpecification.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOFetchSpecification.java index 71f3b78..9ff353e 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOFetchSpecification.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOFetchSpecification.java @@ -30,439 +30,378 @@ import net.wotonomy.foundation.NSSelector; import net.wotonomy.foundation.internal.WotonomyException; /** -* EOFetchSpecification defines the parameters used to request -* objects from an EOObjectStore. They are commonly created -* and passed to a EODataSource which fetches from its -* EOEditingContext, which passes the call up to its root -* EOObjectStore's objectsWithFetchSpecification method. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * EOFetchSpecification defines the parameters used to request objects from an + * EOObjectStore. They are commonly created and passed to a EODataSource which + * fetches from its EOEditingContext, which passes the call up to its root + * EOObjectStore's objectsWithFetchSpecification method. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public class EOFetchSpecification implements EOKeyValueArchiving { - private boolean fetchesRawRows; - private String entityName; - private NSDictionary hints; - private boolean deep; - private int fetchLimit; - private boolean locksObjects; - private NSArray prefetchingRelationshipKeyPaths; - private boolean promptsAfterFetchLimit; - private EOQualifier qualifier; - private NSArray rawRowKeyPaths; - private boolean refreshesRefetchedObjects; - private boolean requiresAllQualifierBindingVariables; - private NSArray sortOrderings; - private boolean distinct; - - /** - * Default constructor initializes internal state. - */ - public EOFetchSpecification() - { - fetchesRawRows = false; - entityName = null; - hints = null; - deep = true; - fetchLimit = 0; - locksObjects = false; - prefetchingRelationshipKeyPaths = null; - promptsAfterFetchLimit = false; - qualifier = null; - rawRowKeyPaths = null; - refreshesRefetchedObjects = false; - requiresAllQualifierBindingVariables = false; - sortOrderings = null; - distinct = false; - } - - /** - * Constructs a fetch specification for the specified entity type using - * the specified qualifier and sort ordering. - */ - public EOFetchSpecification( String anEntityName, EOQualifier aQualifier, List aSortOrderingList ) - { - this(); - entityName = anEntityName; - qualifier = aQualifier; - sortOrderings = new NSArray( (Collection) aSortOrderingList ); - } - - /** - * Constructs a fetch specification for the specified entity type using - * the specified qualifier and sort ordering, distinct flag, deep flag, - * and hints dictionary. - */ - public EOFetchSpecification( String anEntityName, EOQualifier aQualifier, NSArray aSortOrderingList, - boolean usesDistinct, boolean isDeep, Map aHintMap) - { - this(); - entityName = anEntityName; - qualifier = aQualifier; - sortOrderings = new NSArray( (Collection) aSortOrderingList ); - distinct = usesDistinct; - deep = isDeep; - hints = new NSMutableDictionary( (Map) aHintMap ); - } - - /** - * Convenience to return the named fetch specification from the class description - * corresponding to the specified entity name. Returns null if either entityName - * or spec name cannot be resolved. - */ - public static EOFetchSpecification fetchSpecificationNamed( String name, String entityName) - { - EOClassDescription classDesc = EOClassDescription.classDescriptionForEntityName( entityName ); - if ( classDesc == null ) return null; - return classDesc.fetchSpecificationNamed( name ); - } - - /** - * Implemented to return a new fetch specification that is a deep copy of this one. - */ - public Object clone() - { - EOFetchSpecification clone = new EOFetchSpecification(); - - clone.fetchesRawRows = this.fetchesRawRows; - clone.entityName = this.entityName; - if ( this.hints != null ) - clone.hints = new NSDictionary( (Map) this.hints ); - clone.deep = this.deep; - clone.locksObjects = this.locksObjects; - if ( this.prefetchingRelationshipKeyPaths != null ) - clone.prefetchingRelationshipKeyPaths = - new NSArray( (List) prefetchingRelationshipKeyPaths ); - clone.promptsAfterFetchLimit = this.promptsAfterFetchLimit; - if ( this.qualifier != null ) - clone.qualifier = this.qualifier; //FIXME: probably should clone? - if ( this.rawRowKeyPaths != null ) - clone.rawRowKeyPaths = new NSArray( (List) this.rawRowKeyPaths ); - clone.refreshesRefetchedObjects = this.refreshesRefetchedObjects; - clone.requiresAllQualifierBindingVariables = - this.requiresAllQualifierBindingVariables; - if ( this.sortOrderings != null ) - clone.sortOrderings = new NSArray( (List) this.sortOrderings ); - clone.distinct = this.distinct; - - return clone; - } - - /** - * Returns the name of the entity fetched by this fetch spec. - */ - public String entityName() - { - return entityName; - } - - /** - * Returns the current fetch limit. - * A fetch limit of zero indicates no fetch limit. - * Zero is the default. - */ - public int fetchLimit() - { - return fetchLimit; - } - - /** - * Returns whether this fetch spec will fetch raw rows. - * Default is false. - */ - public boolean fetchesRawRows() - { - return fetchesRawRows; - } - - /** - * Returns a fetch specification that resolves the bindings - * in the specified map. - */ - public EOFetchSpecification - fetchSpecificationWithQualifierBindings(Map aBindingMap) - { - throw new WotonomyException( "Not implemented yet" ); - } - - /** - * Returns a Map containing the hints used by this fetch specification, - * or null if no hints have been specified. - */ - public NSDictionary hints() - { - if ( hints == null ) return null; - return new NSDictionary( (NSDictionary) hints ); - } - - /** - * Returns whether entities related to the primary - * entities are fetched by this fetch spec. If true, all relationships - * whose destinations meet the qualifier criteria will be returned - * in addition to primary results. If false, only the primary entities - * will be returned. Default is true. - */ - public boolean isDeep() - { - return deep; - } - - /** - * Returns whether this data source should lock objects that - * are fetched. Default is false. - */ - public boolean locksObjects() - { - return locksObjects; - } - - /*** - * Returns a List of relationships for the fetched objects that - * should also be fetched, or null if no such list has been specified. - * Use this to avoid additional calls to the server to fetch - * relationships that you know you will use. - * NOTE: wotonomy allows you to specify non-relational keys - * as well. - */ - public NSArray prefetchingRelationshipKeyPaths() - { - return prefetchingRelationshipKeyPaths; - } - - /** - * Returns whether the user should be prompted to continue - * when the fetch limit has been exceeded. - * Default is false. - */ - public boolean promptsAfterFetchLimit() - { - return promptsAfterFetchLimit; - } - - /** - * Returns the qualifier used by this fetch specification, - * or null if none has been specified. - */ - public EOQualifier qualifier() - { - return qualifier; - } - - /** - * Returns a List of keys or key paths for which - * values should be returned when fetching raw rows, - * or null if no raw row key paths have been specified. - */ - public NSArray rawRowKeyPaths() - { - return rawRowKeyPaths; - } - - /** - * Returns whether fetched objects should replace - * modified versions already fetched into an editing context. - * If true, those changes will be lost. - * Default is false. - */ - public boolean refreshesRefetchedObjects() - { - return refreshesRefetchedObjects; - } - - /** - * Returns whether all qualifier bindings must be specified - * in order to fetch. If true, an exception is thrown if - * unspecified bindings exist. If false, unspecified bindings - * will be removed from the qualifier. Default is false. - */ - public boolean requiresAllQualifierBindingVariables() - { - return requiresAllQualifierBindingVariables; - } - - /** - * Sets the name of the entity fetched by this spec. - */ - public void setEntityName(String aName) - { - entityName = aName; - } - - /** - * Sets whether this fetch spec will return raw rows. - */ - public void setFetchesRawRows(boolean shouldFetchRawRows) - { - fetchesRawRows = shouldFetchRawRows; - } - - /** - * Sets the limit on the number of records returned for this fetch spec. - * Zero indicates no limit on fetches. - */ - public void setFetchLimit(int aLimit) - { - fetchLimit = aLimit; - } - - /** - * Sets the hints passed by this fetch spec. - */ - public void setHints(Map aHintMap) - { - if ( aHintMap == null ) - { - hints = null; - } - else - { - hints = new NSDictionary( (Map) aHintMap ); - } - } - - /** - * Sets whether this fetch specification fetches deeply. - */ - public void setIsDeep(boolean isDeep) - { - deep = isDeep; - } - - /** - * Sets whether this fetch spec locks objects that - * are returned by the fetch. - */ - public void setLocksObjects(boolean shouldLockObjects) - { - locksObjects = shouldLockObjects; - } - - /** - * Sets the prefetch key paths that should be used as an optimization - * hint to the server. NOTE: wotonomy allows you to specify non-relationship - * keys as well. - */ - public void setPrefetchingRelationshipKeyPaths(List aKeyPathList) - { - if ( aKeyPathList == null ) - { - prefetchingRelationshipKeyPaths = null; - } - else - { - prefetchingRelationshipKeyPaths = new NSArray( (List) aKeyPathList ); - } - } - - /** - * Sets whether the user should be prompted when the fetch limit has been - * reached. - */ - public void setPromptsAfterFetchLimit(boolean shouldPrompt) - { - promptsAfterFetchLimit = shouldPrompt; - } - - /** - * Sets the qualifier used by this fetch specification. - */ - public void setQualifier(EOQualifier aQualifier) - { - qualifier = aQualifier; - } - - /** - * Sets the key paths to be returned if this fetch spec - * is returning raw rows. - */ - public void setRawRowKeyPaths(List aKeyPathList) - { - if ( aKeyPathList == null ) - { - rawRowKeyPaths = null; - } - else - { - rawRowKeyPaths = new NSArray( (List) aKeyPathList ); - } - } - - /** - * Sets whether modified objects in an editing context should - * be replaced by newer versions returned by this fetch spec. - */ - public void setRefreshesRefetchedObjects(boolean shouldRefresh) - { - refreshesRefetchedObjects = shouldRefresh; - } - - /** - * Sets whether this fetch spec should require all bindings to be - * resolved before executing. - */ - public void setRequiresAllQualifierBindingVariables(boolean shouldRequireAll) - { - requiresAllQualifierBindingVariables = shouldRequireAll; - } - - /** - * Sets the sort orderings used by this fetch spec. - */ - public void setSortOrderings(List aSortList) - { - if ( aSortList == null ) - { - sortOrderings = null; - } - else - { - sortOrderings = new NSArray( (List) aSortList ); - } - } - - /** - * Sets whether this fetch spec should return only distinct - * objects. - */ - public void setUsesDistinct(boolean shouldUseDistinct) - { - distinct = shouldUseDistinct; - } - - /** - * Returns a List of the sort orderings used by this fetch spec, - * or null if none have been specified. - */ - public NSArray sortOrderings() - { - return sortOrderings; - } - - /** - * Returns a string representation of this fetch specification. - */ - public String toString() - { - return "[FetchSpecification:qualifier=("+qualifier+"),sortOrderings="+sortOrderings+"]"; - } - - /** - * Returns whether this fetch specification will return only one - * reference to each distinct object returned by the fetch. - * Default is false. - */ - public boolean usesDistinct() - { - return distinct; - } + private boolean fetchesRawRows; + private String entityName; + private NSDictionary hints; + private boolean deep; + private int fetchLimit; + private boolean locksObjects; + private NSArray prefetchingRelationshipKeyPaths; + private boolean promptsAfterFetchLimit; + private EOQualifier qualifier; + private NSArray rawRowKeyPaths; + private boolean refreshesRefetchedObjects; + private boolean requiresAllQualifierBindingVariables; + private NSArray sortOrderings; + private boolean distinct; + + /** + * Default constructor initializes internal state. + */ + public EOFetchSpecification() { + fetchesRawRows = false; + entityName = null; + hints = null; + deep = true; + fetchLimit = 0; + locksObjects = false; + prefetchingRelationshipKeyPaths = null; + promptsAfterFetchLimit = false; + qualifier = null; + rawRowKeyPaths = null; + refreshesRefetchedObjects = false; + requiresAllQualifierBindingVariables = false; + sortOrderings = null; + distinct = false; + } + + /** + * Constructs a fetch specification for the specified entity type using the + * specified qualifier and sort ordering. + */ + public EOFetchSpecification(String anEntityName, EOQualifier aQualifier, List aSortOrderingList) { + this(); + entityName = anEntityName; + qualifier = aQualifier; + sortOrderings = new NSArray((Collection) aSortOrderingList); + } + + /** + * Constructs a fetch specification for the specified entity type using the + * specified qualifier and sort ordering, distinct flag, deep flag, and hints + * dictionary. + */ + public EOFetchSpecification(String anEntityName, EOQualifier aQualifier, NSArray aSortOrderingList, + boolean usesDistinct, boolean isDeep, Map aHintMap) { + this(); + entityName = anEntityName; + qualifier = aQualifier; + sortOrderings = new NSArray((Collection) aSortOrderingList); + distinct = usesDistinct; + deep = isDeep; + hints = new NSMutableDictionary((Map) aHintMap); + } + + /** + * Convenience to return the named fetch specification from the class + * description corresponding to the specified entity name. Returns null if + * either entityName or spec name cannot be resolved. + */ + public static EOFetchSpecification fetchSpecificationNamed(String name, String entityName) { + EOClassDescription classDesc = EOClassDescription.classDescriptionForEntityName(entityName); + if (classDesc == null) + return null; + return classDesc.fetchSpecificationNamed(name); + } + + /** + * Implemented to return a new fetch specification that is a deep copy of this + * one. + */ + public Object clone() { + EOFetchSpecification clone = new EOFetchSpecification(); + + clone.fetchesRawRows = this.fetchesRawRows; + clone.entityName = this.entityName; + if (this.hints != null) + clone.hints = new NSDictionary((Map) this.hints); + clone.deep = this.deep; + clone.locksObjects = this.locksObjects; + if (this.prefetchingRelationshipKeyPaths != null) + clone.prefetchingRelationshipKeyPaths = new NSArray((List) prefetchingRelationshipKeyPaths); + clone.promptsAfterFetchLimit = this.promptsAfterFetchLimit; + if (this.qualifier != null) + clone.qualifier = this.qualifier; // FIXME: probably should clone? + if (this.rawRowKeyPaths != null) + clone.rawRowKeyPaths = new NSArray((List) this.rawRowKeyPaths); + clone.refreshesRefetchedObjects = this.refreshesRefetchedObjects; + clone.requiresAllQualifierBindingVariables = this.requiresAllQualifierBindingVariables; + if (this.sortOrderings != null) + clone.sortOrderings = new NSArray((List) this.sortOrderings); + clone.distinct = this.distinct; + + return clone; + } + + /** + * Returns the name of the entity fetched by this fetch spec. + */ + public String entityName() { + return entityName; + } + + /** + * Returns the current fetch limit. A fetch limit of zero indicates no fetch + * limit. Zero is the default. + */ + public int fetchLimit() { + return fetchLimit; + } + + /** + * Returns whether this fetch spec will fetch raw rows. Default is false. + */ + public boolean fetchesRawRows() { + return fetchesRawRows; + } + + /** + * Returns a fetch specification that resolves the bindings in the specified + * map. + */ + public EOFetchSpecification fetchSpecificationWithQualifierBindings(Map aBindingMap) { + throw new WotonomyException("Not implemented yet"); + } + + /** + * Returns a Map containing the hints used by this fetch specification, or null + * if no hints have been specified. + */ + public NSDictionary hints() { + if (hints == null) + return null; + return new NSDictionary((NSDictionary) hints); + } + + /** + * Returns whether entities related to the primary entities are fetched by this + * fetch spec. If true, all relationships whose destinations meet the qualifier + * criteria will be returned in addition to primary results. If false, only the + * primary entities will be returned. Default is true. + */ + public boolean isDeep() { + return deep; + } + + /** + * Returns whether this data source should lock objects that are fetched. + * Default is false. + */ + public boolean locksObjects() { + return locksObjects; + } + + /*** + * Returns a List of relationships for the fetched objects that should also be + * fetched, or null if no such list has been specified. Use this to avoid + * additional calls to the server to fetch relationships that you know you will + * use. NOTE: wotonomy allows you to specify non-relational keys as well. + */ + public NSArray prefetchingRelationshipKeyPaths() { + return prefetchingRelationshipKeyPaths; + } + + /** + * Returns whether the user should be prompted to continue when the fetch limit + * has been exceeded. Default is false. + */ + public boolean promptsAfterFetchLimit() { + return promptsAfterFetchLimit; + } + + /** + * Returns the qualifier used by this fetch specification, or null if none has + * been specified. + */ + public EOQualifier qualifier() { + return qualifier; + } + + /** + * Returns a List of keys or key paths for which values should be returned when + * fetching raw rows, or null if no raw row key paths have been specified. + */ + public NSArray rawRowKeyPaths() { + return rawRowKeyPaths; + } + + /** + * Returns whether fetched objects should replace modified versions already + * fetched into an editing context. If true, those changes will be lost. Default + * is false. + */ + public boolean refreshesRefetchedObjects() { + return refreshesRefetchedObjects; + } + + /** + * Returns whether all qualifier bindings must be specified in order to fetch. + * If true, an exception is thrown if unspecified bindings exist. If false, + * unspecified bindings will be removed from the qualifier. Default is false. + */ + public boolean requiresAllQualifierBindingVariables() { + return requiresAllQualifierBindingVariables; + } + + /** + * Sets the name of the entity fetched by this spec. + */ + public void setEntityName(String aName) { + entityName = aName; + } + + /** + * Sets whether this fetch spec will return raw rows. + */ + public void setFetchesRawRows(boolean shouldFetchRawRows) { + fetchesRawRows = shouldFetchRawRows; + } + + /** + * Sets the limit on the number of records returned for this fetch spec. Zero + * indicates no limit on fetches. + */ + public void setFetchLimit(int aLimit) { + fetchLimit = aLimit; + } + + /** + * Sets the hints passed by this fetch spec. + */ + public void setHints(Map aHintMap) { + if (aHintMap == null) { + hints = null; + } else { + hints = new NSDictionary((Map) aHintMap); + } + } + + /** + * Sets whether this fetch specification fetches deeply. + */ + public void setIsDeep(boolean isDeep) { + deep = isDeep; + } + + /** + * Sets whether this fetch spec locks objects that are returned by the fetch. + */ + public void setLocksObjects(boolean shouldLockObjects) { + locksObjects = shouldLockObjects; + } + + /** + * Sets the prefetch key paths that should be used as an optimization hint to + * the server. NOTE: wotonomy allows you to specify non-relationship keys as + * well. + */ + public void setPrefetchingRelationshipKeyPaths(List aKeyPathList) { + if (aKeyPathList == null) { + prefetchingRelationshipKeyPaths = null; + } else { + prefetchingRelationshipKeyPaths = new NSArray((List) aKeyPathList); + } + } + + /** + * Sets whether the user should be prompted when the fetch limit has been + * reached. + */ + public void setPromptsAfterFetchLimit(boolean shouldPrompt) { + promptsAfterFetchLimit = shouldPrompt; + } + + /** + * Sets the qualifier used by this fetch specification. + */ + public void setQualifier(EOQualifier aQualifier) { + qualifier = aQualifier; + } + + /** + * Sets the key paths to be returned if this fetch spec is returning raw rows. + */ + public void setRawRowKeyPaths(List aKeyPathList) { + if (aKeyPathList == null) { + rawRowKeyPaths = null; + } else { + rawRowKeyPaths = new NSArray((List) aKeyPathList); + } + } + + /** + * Sets whether modified objects in an editing context should be replaced by + * newer versions returned by this fetch spec. + */ + public void setRefreshesRefetchedObjects(boolean shouldRefresh) { + refreshesRefetchedObjects = shouldRefresh; + } + + /** + * Sets whether this fetch spec should require all bindings to be resolved + * before executing. + */ + public void setRequiresAllQualifierBindingVariables(boolean shouldRequireAll) { + requiresAllQualifierBindingVariables = shouldRequireAll; + } + + /** + * Sets the sort orderings used by this fetch spec. + */ + public void setSortOrderings(List aSortList) { + if (aSortList == null) { + sortOrderings = null; + } else { + sortOrderings = new NSArray((List) aSortList); + } + } + + /** + * Sets whether this fetch spec should return only distinct objects. + */ + public void setUsesDistinct(boolean shouldUseDistinct) { + distinct = shouldUseDistinct; + } + + /** + * Returns a List of the sort orderings used by this fetch spec, or null if none + * have been specified. + */ + public NSArray sortOrderings() { + return sortOrderings; + } + + /** + * Returns a string representation of this fetch specification. + */ + public String toString() { + return "[FetchSpecification:qualifier=(" + qualifier + "),sortOrderings=" + sortOrderings + "]"; + } + + /** + * Returns whether this fetch specification will return only one reference to + * each distinct object returned by the fetch. Default is false. + */ + public boolean usesDistinct() { + return distinct; + } public void encodeWithKeyValueArchiver(EOKeyValueArchiver arch) { arch.encodeObject("EOFetchSpecification", "class"); arch.encodeObject(entityName(), "entityName"); arch.encodeInt(fetchLimit(), "fetchLimit"); - //flags + // flags if (isDeep()) arch.encodeObject("YES", "isDeep"); arch.encodeObject(qualifier(), "qualifier"); @@ -479,11 +418,11 @@ public class EOFetchSpecification implements EOKeyValueArchiving { if (usesDistinct()) arch.encodeObject("YES", "usesDistinct"); - //encode arrays - if (sortOrderings() != null) { + // encode arrays + if (sortOrderings() != null) { NSMutableArray arr = new NSMutableArray(sortOrderings().count()); for (int i = 0; i < sortOrderings.count(); i++) { - EOSortOrdering so = (EOSortOrdering)sortOrderings().objectAtIndex(i); + EOSortOrdering so = (EOSortOrdering) sortOrderings().objectAtIndex(i); EOKeyValueArchiver ar2 = new EOKeyValueArchiver(); so.encodeWithKeyValueArchiver(ar2); arr.addObject(ar2.dictionary()); @@ -500,18 +439,18 @@ public class EOFetchSpecification implements EOKeyValueArchiving { public static Object decodeWithKeyValueUnarchiver(EOKeyValueUnarchiver unarch) { EOFetchSpecification fs = new EOFetchSpecification(); - fs.setEntityName((String)unarch.decodeObjectForKey("entityName")); + fs.setEntityName((String) unarch.decodeObjectForKey("entityName")); fs.setFetchLimit(unarch.decodeIntForKey("fetchLimit")); fs.setIsDeep(unarch.decodeBoolForKey("isDeep")); fs.setRefreshesRefetchedObjects(unarch.decodeBoolForKey("refreshesRefetchedObjects")); - //Sort orderings - NSArray arr = (NSArray)unarch.decodeObjectForKey("sortOrderings"); - if (arr != null && arr.count() > 0) { + // Sort orderings + NSArray arr = (NSArray) unarch.decodeObjectForKey("sortOrderings"); + if (arr != null && arr.count() > 0) { NSMutableArray orderings = new NSMutableArray(arr.count()); for (int i = 0; i < arr.count(); i++) { - NSDictionary so = (NSDictionary)arr.objectAtIndex(i); - String selname = (String)so.objectForKey("selectorName"); + NSDictionary so = (NSDictionary) arr.objectAtIndex(i); + String selname = (String) so.objectForKey("selectorName"); NSSelector selector = EOSortOrdering.CompareAscending; if (selname.startsWith("compareDescending")) selector = EOSortOrdering.CompareDescending; @@ -519,47 +458,43 @@ public class EOFetchSpecification implements EOKeyValueArchiving { selector = EOSortOrdering.CompareCaseInsensitiveAscending; else if (selname.startsWith("compareCaseInsensitiveDescending")) selector = EOSortOrdering.CompareCaseInsensitiveDescending; - EOSortOrdering eoso = new EOSortOrdering((String)so.objectForKey("key"), selector); + EOSortOrdering eoso = new EOSortOrdering((String) so.objectForKey("key"), selector); orderings.addObject(eoso); } fs.setSortOrderings(orderings); } - //raw rows - arr = (NSArray)unarch.decodeObjectForKey("rawRowKeyPaths"); + // raw rows + arr = (NSArray) unarch.decodeObjectForKey("rawRowKeyPaths"); if (arr != null && arr.count() > 0) { fs.setFetchesRawRows(true); fs.setRawRowKeyPaths(arr); } - //qualifier - fs.setQualifier((EOQualifier)unarch.decodeObjectForKey("qualifier")); + // qualifier + fs.setQualifier((EOQualifier) unarch.decodeObjectForKey("qualifier")); return fs; } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.4 2003/08/11 18:19:01 chochos - * encoding/decoding with EOKeyValueArchiving now works properly + * Revision 1.4 2003/08/11 18:19:01 chochos encoding/decoding with + * EOKeyValueArchiving now works properly * - * Revision 1.3 2003/08/09 01:22:20 chochos - * implements EOKeyValueArchiving (and unarchiving) + * Revision 1.3 2003/08/09 01:22:20 chochos implements EOKeyValueArchiving (and + * unarchiving) * - * Revision 1.2 2001/11/24 17:32:57 mpowers - * We now have a real implementation. + * Revision 1.2 2001/11/24 17:32:57 mpowers We now have a real implementation. * - * Revision 1.1 2001/02/05 03:45:37 mpowers - * Starting work on EOEditingContext. + * Revision 1.1 2001/02/05 03:45:37 mpowers Starting work on EOEditingContext. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOGenericRecord.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOGenericRecord.java index 4358ecf..9d732f9 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOGenericRecord.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOGenericRecord.java @@ -22,130 +22,112 @@ import net.wotonomy.foundation.NSMutableDictionary; import net.wotonomy.foundation.NSNull; /** -* EOGenericRecord extends EOCustomObject to provide a -* general-purpose implementation, relying entirely on the -* class description for entity-specific behavior, and -* storing data in a dictionary. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public class EOGenericRecord extends EOCustomObject -{ - private EOClassDescription classDescription; - private NSMutableDictionary dataDictionary; - - /** - * Default constructor. - */ - protected EOGenericRecord() - { - classDescription = null; - dataDictionary = new NSMutableDictionary(); - } - - /** - * Preferred constructor. - */ - public EOGenericRecord( EOClassDescription aDescription ) - { - this(); - classDescription = aDescription; - } - - /** - * Overridden to return true so that deferred faults are used. - */ - public static boolean usesDeferredFaultCreation() - { - return true; - } - - /** - * Compatibility constructor: aContext and anID are ignored. - */ - public EOGenericRecord( - EOEditingContext aContext, EOClassDescription aDescription, EOGlobalID anID ) - { - this( aDescription ); - } - - /** - * Returns a class description for this object. - * Overridden to return the class description passed - * into the constructor. - */ - public EOClassDescription classDescription() - { - return classDescription; - } - - // interface EOKeyValueCoding - - /** - * Calls storedValueForKey. - */ - public Object valueForKey( String aKey ) - { - return storedValueForKey( aKey ); - } - - /** - * Calls willChange and then calls takeStoredValueForKey. - */ - public void takeValueForKey( Object aValue, String aKey ) - { - willChange(); - takeStoredValueForKey( aValue, aKey ); - } - - /** - * Calls willRead for the specified key, - * and returns the corresponding value from - * the data dictionary. Keys that do not - * exist will return null. - */ - public Object storedValueForKey( String aKey ) - { - willRead( aKey ); - Object result = dataDictionary.objectForKey( aKey ); - if ( NSNull.nullValue().equals( result ) ) result = null; - return result; - } - - /** - * Writes the specified value into the data dictionary - * for the specified key. Nulls are stored as NSNulls - * in the dictionary. - * No checking is performed to determine whether the - * key is a valid attribute key. - */ - public void takeStoredValueForKey( Object aValue, String aKey ) - { - if ( aValue == null ) aValue = NSNull.nullValue(); - dataDictionary.setObjectForKey( aValue, aKey ); - } + * EOGenericRecord extends EOCustomObject to provide a general-purpose + * implementation, relying entirely on the class description for entity-specific + * behavior, and storing data in a dictionary. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public class EOGenericRecord extends EOCustomObject { + private EOClassDescription classDescription; + private NSMutableDictionary dataDictionary; + + /** + * Default constructor. + */ + protected EOGenericRecord() { + classDescription = null; + dataDictionary = new NSMutableDictionary(); + } + + /** + * Preferred constructor. + */ + public EOGenericRecord(EOClassDescription aDescription) { + this(); + classDescription = aDescription; + } + + /** + * Overridden to return true so that deferred faults are used. + */ + public static boolean usesDeferredFaultCreation() { + return true; + } + + /** + * Compatibility constructor: aContext and anID are ignored. + */ + public EOGenericRecord(EOEditingContext aContext, EOClassDescription aDescription, EOGlobalID anID) { + this(aDescription); + } + + /** + * Returns a class description for this object. Overridden to return the class + * description passed into the constructor. + */ + public EOClassDescription classDescription() { + return classDescription; + } + + // interface EOKeyValueCoding + + /** + * Calls storedValueForKey. + */ + public Object valueForKey(String aKey) { + return storedValueForKey(aKey); + } + + /** + * Calls willChange and then calls takeStoredValueForKey. + */ + public void takeValueForKey(Object aValue, String aKey) { + willChange(); + takeStoredValueForKey(aValue, aKey); + } + + /** + * Calls willRead for the specified key, and returns the corresponding value + * from the data dictionary. Keys that do not exist will return null. + */ + public Object storedValueForKey(String aKey) { + willRead(aKey); + Object result = dataDictionary.objectForKey(aKey); + if (NSNull.nullValue().equals(result)) + result = null; + return result; + } + + /** + * Writes the specified value into the data dictionary for the specified key. + * Nulls are stored as NSNulls in the dictionary. No checking is performed to + * determine whether the key is a valid attribute key. + */ + public void takeStoredValueForKey(Object aValue, String aKey) { + if (aValue == null) + aValue = NSNull.nullValue(); + dataDictionary.setObjectForKey(aValue, aKey); + } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.2 2003/08/06 23:07:52 chochos - * general code cleanup (mostly, removing unused imports) + * Revision 1.2 2003/08/06 23:07:52 chochos general code cleanup (mostly, + * removing unused imports) * - * Revision 1.1 2001/11/18 18:57:10 mpowers - * Implemented EOGenericRecord. + * Revision 1.1 2001/11/18 18:57:10 mpowers Implemented EOGenericRecord. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOGlobalID.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOGlobalID.java index 1b4ccbe..346362c 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOGlobalID.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOGlobalID.java @@ -21,63 +21,51 @@ package net.wotonomy.control; import java.io.Serializable; /** -* A pure java implementation of EOGlobalID. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 893 $ -*/ -public abstract class EOGlobalID implements Cloneable, Serializable -{ - /** - * ObjectStores broadcast this notification when they - * replace a temporary global id with a permanent one. - * EditingContexts listen for these notifications to - * update their mapping of global ids to objects. - * The object of the notification is null, and the user - * info contains a mapping of the old temporary ids to - * the new permanent ids. - */ - public static final String GlobalIDChangedNotification - = "GlobalIDChangedNotification"; - - /** - * Returns whether this id is a temporary id. - * Temporary ids are generated for newly created - * objects that have not been persisted. When - * persisted, the temporary id is discarded in favor - * of the one generated by the object store. - */ - public abstract boolean isTemporary(); - - /** - * Returns a copy of this object. - * This implementation calls super.clone(). - */ - public Object clone() throws CloneNotSupportedException - { - return super.clone(); - } + * A pure java implementation of EOGlobalID. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 893 $ + */ +public abstract class EOGlobalID implements Cloneable, Serializable { + /** + * ObjectStores broadcast this notification when they replace a temporary global + * id with a permanent one. EditingContexts listen for these notifications to + * update their mapping of global ids to objects. The object of the notification + * is null, and the user info contains a mapping of the old temporary ids to the + * new permanent ids. + */ + public static final String GlobalIDChangedNotification = "GlobalIDChangedNotification"; + + /** + * Returns whether this id is a temporary id. Temporary ids are generated for + * newly created objects that have not been persisted. When persisted, the + * temporary id is discarded in favor of the one generated by the object store. + */ + public abstract boolean isTemporary(); + + /** + * Returns a copy of this object. This implementation calls super.clone(). + */ + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } } /* - * $Log$ - * Revision 1.1 2006/02/16 13:19:57 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. + * $Log$ Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.4 2001/04/29 22:02:45 mpowers - * Work on id transposing between editing contexts. + * Revision 1.4 2001/04/29 22:02:45 mpowers Work on id transposing between + * editing contexts. * - * Revision 1.3 2001/03/15 21:10:26 mpowers - * Implemented global id re-registration for newly saved inserts. + * Revision 1.3 2001/03/15 21:10:26 mpowers Implemented global id + * re-registration for newly saved inserts. * - * Revision 1.2 2001/02/15 21:13:30 mpowers - * First draft implementation is complete. Now on to debugging. + * Revision 1.2 2001/02/15 21:13:30 mpowers First draft implementation is + * complete. Now on to debugging. * - * Revision 1.1 2001/02/05 03:45:37 mpowers - * Starting work on EOEditingContext. + * Revision 1.1 2001/02/05 03:45:37 mpowers Starting work on EOEditingContext. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOIntegralKeyGlobalID.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOIntegralKeyGlobalID.java index ee7aac1..14f7925 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOIntegralKeyGlobalID.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOIntegralKeyGlobalID.java @@ -18,11 +18,11 @@ package net.wotonomy.control; /** -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 893 $ -*/ + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 893 $ + */ public class EOIntegralKeyGlobalID extends EOKeyGlobalID { protected Number keyValue; @@ -32,28 +32,36 @@ public class EOIntegralKeyGlobalID extends EOKeyGlobalID { keyValue = value; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see net.wotonomy.control.EOKeyGlobalID#keyValues() */ public Object[] keyValues() { - return new Object[]{ keyValue }; + return new Object[] { keyValue }; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see net.wotonomy.control.EOKeyGlobalID#_keyValuesNoCopy() */ public Object[] _keyValuesNoCopy() { - return new Object[]{ keyValue }; + return new Object[] { keyValue }; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see net.wotonomy.control.EOKeyGlobalID#keyCount() */ public int keyCount() { return 1; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see net.wotonomy.control.EOGlobalID#isTemporary() */ public boolean isTemporary() { @@ -62,11 +70,9 @@ public class EOIntegralKeyGlobalID extends EOKeyGlobalID { } /* - * $Log$ - * Revision 1.1 2006/02/16 13:19:57 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. + * $Log$ Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.2 2003/08/19 01:59:01 chochos - * Added the wotonomy headers + * Revision 1.2 2003/08/19 01:59:01 chochos Added the wotonomy headers * */ diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyComparisonQualifier.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyComparisonQualifier.java index 97baaab..ef9c244 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyComparisonQualifier.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyComparisonQualifier.java @@ -22,13 +22,11 @@ import net.wotonomy.foundation.NSSelector; import net.wotonomy.foundation.internal.WotonomyException; /** -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public class EOKeyComparisonQualifier - extends EOQualifier - implements EOKeyValueArchiving, EOQualifierEvaluation { + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public class EOKeyComparisonQualifier extends EOQualifier implements EOKeyValueArchiving, EOQualifierEvaluation { private String _leftKey; private String _rightKey; @@ -54,29 +52,31 @@ public class EOKeyComparisonQualifier } /** - * Evaluates this qualifier for the specified object, - * and returns whether the object is qualified. - * selector() is invoked on the value for key() on the - * specified object, with value() as the parameter. - */ + * Evaluates this qualifier for the specified object, and returns whether the + * object is qualified. selector() is invoked on the value for key() on the + * specified object, with value() as the parameter. + */ public boolean evaluateWithObject(Object eo) { try { Object lvalue, rvalue; - if ( eo instanceof EOKeyValueCoding) { - lvalue = ((EOKeyValueCoding)eo).valueForKey(leftKey()); - rvalue = ((EOKeyValueCoding)eo).valueForKey(rightKey()); + if (eo instanceof EOKeyValueCoding) { + lvalue = ((EOKeyValueCoding) eo).valueForKey(leftKey()); + rvalue = ((EOKeyValueCoding) eo).valueForKey(rightKey()); } else { lvalue = EOKeyValueCodingSupport.valueForKey(eo, leftKey()); rvalue = EOKeyValueCodingSupport.valueForKey(eo, rightKey()); } - return ((Boolean)_selector.invoke( lvalue, rvalue)).booleanValue(); + return ((Boolean) _selector.invoke(lvalue, rvalue)).booleanValue(); } catch (Exception exc) { - throw new WotonomyException( exc ); + throw new WotonomyException(exc); } } - /* (non-Javadoc) - * @see net.wotonomy.control.EOKeyValueArchiving#encodeWithKeyValueArchiver(net.wotonomy.control.EOKeyValueArchiver) + /* + * (non-Javadoc) + * + * @see net.wotonomy.control.EOKeyValueArchiving#encodeWithKeyValueArchiver(net. + * wotonomy.control.EOKeyValueArchiver) */ public void encodeWithKeyValueArchiver(EOKeyValueArchiver arch) { arch.encodeObject("EOKeyComparisonQualifier", "class"); @@ -108,10 +108,10 @@ public class EOKeyComparisonQualifier } public static Object decodeWithKeyValueArchiver(EOKeyValueUnarchiver arch) { - String k = (String)arch.decodeObjectForKey("key"); - String v = (String)arch.decodeObjectForKey("value"); + String k = (String) arch.decodeObjectForKey("key"); + String v = (String) arch.decodeObjectForKey("value"); NSSelector sel = null; - String sname = (String)arch.decodeObjectForKey("selectorName"); + String sname = (String) arch.decodeObjectForKey("selectorName"); if (sname.equals("isEqualTo:")) sel = EOQualifier.QualifierOperatorEqual; else if (sname.equals("isNotEqualTo:")) @@ -136,16 +136,15 @@ public class EOKeyComparisonQualifier } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.1 2003/08/12 01:42:36 chochos - * this qualifier was missing + * Revision 1.1 2003/08/12 01:42:36 chochos this qualifier was missing * */ diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyGlobalID.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyGlobalID.java index 76c4d05..7034f03 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyGlobalID.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyGlobalID.java @@ -28,119 +28,117 @@ import net.wotonomy.foundation.NSCoder; import net.wotonomy.foundation.NSCoding; /** -* The model object which represents the mapping between database -* fields and object properties, lists available entities, lists -* connection dictionaries, and has fetch specifications. -* -* @author cgruber@israfil.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * The model object which represents the mapping between database fields and + * object properties, lists available entities, lists connection dictionaries, + * and has fetch specifications. + * + * @author cgruber@israfil.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ -public abstract class EOKeyGlobalID extends EOGlobalID - implements NSCoding { +public abstract class EOKeyGlobalID extends EOGlobalID implements NSCoding { protected String _entityName; protected int _hash; - protected EOKeyGlobalID(String entityName, int hashCode) { - super(); - _entityName = entityName; - _hash = hashCode; - } + protected EOKeyGlobalID(String entityName, int hashCode) { + super(); + _entityName = entityName; + _hash = hashCode; + } - protected void _prepClone(EOKeyGlobalID gid) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + protected void _prepClone(EOKeyGlobalID gid) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public static EOKeyGlobalID globalIDWithEntityName(String s, Object aobj[]) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public static EOKeyGlobalID globalIDWithEntityName(String s, Object aobj[]) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public static EOKeyGlobalID _defaultGlobalIDWithEntityName(String s, Object aobj[]) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public static EOKeyGlobalID _defaultGlobalIDWithEntityName(String s, Object aobj[]) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public String entityName() { - return _entityName; - } + public String entityName() { + return _entityName; + } - public String _literalEntityName() { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public String _literalEntityName() { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public boolean _isFinal() { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public boolean _isFinal() { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public void _setGuessedEntityName(String s) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public void _setGuessedEntityName(String s) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public String _guessedEntityName() { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public String _guessedEntityName() { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public void _setSubEntityName(String s) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public void _setSubEntityName(String s) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public String _subEntityName() { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public String _subEntityName() { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public int hashCode() { - return _hash; - } + public int hashCode() { + return _hash; + } - public abstract Object[] keyValues(); + public abstract Object[] keyValues(); - public abstract Object[] _keyValuesNoCopy(); + public abstract Object[] _keyValuesNoCopy(); - public abstract int keyCount(); + public abstract int keyCount(); - public NSArray keyValuesArray() { - return new NSArray(keyValues()); - } + public NSArray keyValuesArray() { + return new NSArray(keyValues()); + } - public static Object decodeObject(NSCoder nscoder) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public static Object decodeObject(NSCoder nscoder) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public static EOKeyGlobalID _adjustForInheritance(EOKeyGlobalID eokeyglobalid, String s, String s1) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public static EOKeyGlobalID _adjustForInheritance(EOKeyGlobalID eokeyglobalid, String s, String s1) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public void encodeWithCoder(NSCoder nscoder) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public void encodeWithCoder(NSCoder nscoder) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public Class classForCoder() { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public Class classForCoder() { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - protected Object readResolve() throws ObjectStreamException { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + protected Object readResolve() throws ObjectStreamException { + throw new UnsupportedOperationException("Not Yet Implemented"); + } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.2 2003/08/19 01:50:54 chochos - * added two concrete implementations of EOKeyGlobalID. + * Revision 1.2 2003/08/19 01:50:54 chochos added two concrete implementations + * of EOKeyGlobalID. * - * Revision 1.1 2002/07/14 21:59:06 mpowers - * Contributions from cgruber. + * Revision 1.1 2002/07/14 21:59:06 mpowers Contributions from cgruber. * - * Revision 1.1 2002/06/25 00:11:09 cgruber - * Add EOKeyGlobalID, but it won't work without NSCoder. + * Revision 1.1 2002/06/25 00:11:09 cgruber Add EOKeyGlobalID, but it won't work + * without NSCoder. * */ diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueArchiver.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueArchiver.java index 3e2f808..e759c1a 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueArchiver.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueArchiver.java @@ -23,15 +23,14 @@ import net.wotonomy.foundation.NSMutableDictionary; import net.wotonomy.foundation.NSSelector; /** -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public class EOKeyValueArchiver { - //for the delegate - public static final NSSelector sel = new NSSelector("referenceToEncodeForObject", - new Class[]{ Object.class }); + // for the delegate + public static final NSSelector sel = new NSSelector("referenceToEncodeForObject", new Class[] { Object.class }); NSMutableDictionary dict = new NSMutableDictionary(); private Object _delegate; @@ -57,7 +56,7 @@ public class EOKeyValueArchiver { } if (obj instanceof EOKeyValueArchiving) { EOKeyValueArchiver arch = new EOKeyValueArchiver(); - ((EOKeyValueArchiving)obj).encodeWithKeyValueArchiver(arch); + ((EOKeyValueArchiving) obj).encodeWithKeyValueArchiver(arch); dict.setObjectForKey(arch.dictionary(), key); return; } @@ -85,22 +84,23 @@ public class EOKeyValueArchiver { public void setDelegate(Object delegate) { _delegate = delegate; } + public Object delegate() { return _delegate; } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.1 2003/08/09 01:17:53 chochos - * Part of the EOKeyValueArchiving protocol (archives objects into NSDictionaries and vice-versa) + * Revision 1.1 2003/08/09 01:17:53 chochos Part of the EOKeyValueArchiving + * protocol (archives objects into NSDictionaries and vice-versa) * */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueArchiving.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueArchiving.java index 0d9f78c..97a1338 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueArchiving.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueArchiving.java @@ -18,24 +18,23 @@ License along with this library; if not, see http://www.gnu.org package net.wotonomy.control; /** - * Remember that this method is also part of the interface: - * public static Object decodeWithKeyValueUnarchiver(EOKeyValueUnarchiver unarchiver) + * Remember that this method is also part of the interface: public static Object + * decodeWithKeyValueUnarchiver(EOKeyValueUnarchiver unarchiver) * -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 893 $ -*/ + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 893 $ + */ public interface EOKeyValueArchiving { public abstract void encodeWithKeyValueArchiver(EOKeyValueArchiver archiver); } /* - * $Log$ - * Revision 1.1 2006/02/16 13:19:57 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. + * $Log$ Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.1 2003/08/09 01:17:53 chochos - * Part of the EOKeyValueArchiving protocol (archives objects into NSDictionaries and vice-versa) + * Revision 1.1 2003/08/09 01:17:53 chochos Part of the EOKeyValueArchiving + * protocol (archives objects into NSDictionaries and vice-versa) * */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueCoding.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueCoding.java index b3cf926..490738c 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueCoding.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueCoding.java @@ -21,109 +21,95 @@ package net.wotonomy.control; import net.wotonomy.foundation.NSKeyValueCoding; /** -* EOKeyValueCoding defines an interface for classes that -* need to have more control over the wotonomy's property -* introspection facilities.

-* -* On an object that implements this interface, wotonomy -* will call these methods, and otherwise use the static -* methods on EOKeyValueCodingSupport.

-* -* EOKeyValueCodingSupport implements the default behaviors -* for each of these methods, so classes implementing this -* interface can call those methods to acheive the same -* behavior.

-* -* valueForKey and takeValueForKey are called in response -* to user actions, like viewing an object or updating its -* value in a user interface. These should call the public -* getter and setter methods on the object itself and the -* operations should be subject to validation.

-* -* storedValueForKey and takeStoredValueForKey are called -* in response to wotonomy actions, like snapshotting, -* faulting, commits, and reverts. These operations should -* bypass the public methods and directly modify the internal -* state of the object without validation. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 893 $ -*/ -public interface EOKeyValueCoding extends NSKeyValueCoding -{ - /** - * Returns the value for the specified property. - * If the property does not exist, this method should - * call handleQueryWithUnboundKey. - */ - Object valueForKey( String aKey ); + * EOKeyValueCoding defines an interface for classes that need to have more + * control over the wotonomy's property introspection facilities.
+ *
+ * + * On an object that implements this interface, wotonomy will call these + * methods, and otherwise use the static methods on EOKeyValueCodingSupport. + *
+ *
+ * + * EOKeyValueCodingSupport implements the default behaviors for each of these + * methods, so classes implementing this interface can call those methods to + * acheive the same behavior.
+ *
+ * + * valueForKey and takeValueForKey are called in response to user actions, like + * viewing an object or updating its value in a user interface. These should + * call the public getter and setter methods on the object itself and the + * operations should be subject to validation.
+ *
+ * + * storedValueForKey and takeStoredValueForKey are called in response to + * wotonomy actions, like snapshotting, faulting, commits, and reverts. These + * operations should bypass the public methods and directly modify the internal + * state of the object without validation. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 893 $ + */ +public interface EOKeyValueCoding extends NSKeyValueCoding { + /** + * Returns the value for the specified property. If the property does not exist, + * this method should call handleQueryWithUnboundKey. + */ + Object valueForKey(String aKey); - /** - * Sets the property to the specified value. - * If the property does not exist, this method should - * call handleTakeValueForUnboundKey. - * If the property is of a type that cannot allow - * null (e.g. primitive types) and aValue is null, - * this method should call unableToSetNullForKey. - */ - void takeValueForKey( Object aValue, String aKey ); + /** + * Sets the property to the specified value. If the property does not exist, + * this method should call handleTakeValueForUnboundKey. If the property is of a + * type that cannot allow null (e.g. primitive types) and aValue is null, this + * method should call unableToSetNullForKey. + */ + void takeValueForKey(Object aValue, String aKey); - /** - * Returns the value for the private field that - * corresponds to the specified property. - */ - Object storedValueForKey( String aKey ); + /** + * Returns the value for the private field that corresponds to the specified + * property. + */ + Object storedValueForKey(String aKey); - /** - * Sets the the private field that corresponds to the - * specified property to the specified value. - */ - void takeStoredValueForKey( Object aValue, String aKey ); + /** + * Sets the the private field that corresponds to the specified property to the + * specified value. + */ + void takeStoredValueForKey(Object aValue, String aKey); - /** - * Called by valueForKey when the specified key is - * not found on this object. Implementing classes - * should handle the specified value or otherwise - * throw an exception. - */ - Object handleQueryWithUnboundKey( String aKey ); + /** + * Called by valueForKey when the specified key is not found on this object. + * Implementing classes should handle the specified value or otherwise throw an + * exception. + */ + Object handleQueryWithUnboundKey(String aKey); - /** - * Called by takeValueForKey when the specified key - * is not found on this object. Implementing classes - * should handle the specified value or otherwise - * throw an exception. - */ - void handleTakeValueForUnboundKey( Object aValue, String aKey ); + /** + * Called by takeValueForKey when the specified key is not found on this object. + * Implementing classes should handle the specified value or otherwise throw an + * exception. + */ + void handleTakeValueForUnboundKey(Object aValue, String aKey); - /** - * Called by takeValueForKey when the type of the - * specified key is not allowed to be null, as is - * the case with primitive types. Implementing - * classes should handle this case appropriately - * or otherwise throw an exception. - */ - void unableToSetNullForKey( String aKey ); + /** + * Called by takeValueForKey when the type of the specified key is not allowed + * to be null, as is the case with primitive types. Implementing classes should + * handle this case appropriately or otherwise throw an exception. + */ + void unableToSetNullForKey(String aKey); } /* - * $Log$ - * Revision 1.1 2006/02/16 13:19:57 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. + * $Log$ Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.3 2003/01/16 22:47:30 mpowers - * Compatibility changes to support compiling woextensions source. - * (34 out of 56 classes compile!) + * Revision 1.3 2003/01/16 22:47:30 mpowers Compatibility changes to support + * compiling woextensions source. (34 out of 56 classes compile!) * - * Revision 1.2 2001/03/28 16:12:30 mpowers - * Documented interface. + * Revision 1.2 2001/03/28 16:12:30 mpowers Documented interface. * - * Revision 1.1 2001/03/27 23:25:05 mpowers - * Contributing interface, no docs yet. + * Revision 1.1 2001/03/27 23:25:05 mpowers Contributing interface, no docs yet. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueCodingAdditions.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueCodingAdditions.java index bc48f58..d1bb2c0 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueCodingAdditions.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueCodingAdditions.java @@ -25,152 +25,127 @@ import net.wotonomy.foundation.NSDictionary; import net.wotonomy.foundation.NSKeyValueCodingAdditions; /** -* EOKeyValueCodingAdditions defines an interface for classes -* that need to have more control over the wotonomy's bulk -* property copying and cloning facilities.

-* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public interface EOKeyValueCodingAdditions extends EOKeyValueCoding, NSKeyValueCodingAdditions -{ - - /** - * Static utilities methods that - * call the appropriate method if the object implements - * NSKeyValueCodingAdditions, otherwise calls the method - * on DefaultImplementation. - */ - public class Utility extends NSKeyValueCodingAdditions.Utility - { - /** - * Calls the appropriate method if the object implements - * NSKeyValueCodingAdditions, otherwise calls the method - * on DefaultImplementation. - */ - public static void takeValuesFromDictionary( - Object object, Map dictionary) - { - if (object instanceof NSKeyValueCodingAdditions) { - ((NSKeyValueCodingAdditions)object).takeValuesFromDictionary(dictionary); - } else { - DefaultImplementation.takeValuesFromDictionary(object, dictionary); - } - } - - /** - * Calls the appropriate method if the object implements - * NSKeyValueCodingAdditions, otherwise calls the method - * on DefaultImplementation. - */ -/* - public static void takeValuesFromDictionaryWithMapping( - Object object, NSDictionary dictionary, NSDictionary mapping) - { - if (object instanceof NSKeyValueCodingAdditions) { - ((NSKeyValueCodingAdditions)object).takeValuesFromDictionaryWithMapping(dictionary, mapping); - } else { - DefaultImplementation.takeValuesFromDictionaryWithMapping(object, dictionary, mapping); - } - } -*/ - - /** - * Calls the appropriate method if the object implements - * NSKeyValueCodingAdditions, otherwise calls the method - * on DefaultImplementation. - */ - public static NSDictionary valuesForKeys( - Object object, List keys) - { - if (object instanceof NSKeyValueCodingAdditions) { - return ((NSKeyValueCodingAdditions)object).valuesForKeys(keys); - } else { - return DefaultImplementation.valuesForKeys(object, keys); - } - } - - /** - * Calls the appropriate method if the object implements - * NSKeyValueCodingAdditions, otherwise calls the method - * on DefaultImplementation. - */ -/* - public static NSDictionary valuesForKeysWithMapping( - Object object, NSDictionary mapping) - { - if (object instanceof NSKeyValueCodingAdditions) { - return ((NSKeyValueCodingAdditions)object).valuesForKeysWithMapping(mapping); - } else { - return DefaultImplementation.valuesForKeysWithMapping(object, mapping); - } - } -*/ - } - - /** - * Provides a reflection-based implementation for classes that - * don't implement NSKeyValueCodingAdditions. - */ - public class DefaultImplementation extends NSKeyValueCodingAdditions.DefaultImplementation - { - public static void takeValuesFromDictionary( - Object object, NSDictionary dictionary) - { - throw new RuntimeException( "Not implemented yet." ); - } - - public static void takeValuesFromDictionaryWithMapping( - Object object, NSDictionary dictionary, NSDictionary mapping) - { - throw new RuntimeException( "Not implemented yet." ); - } - - public static NSDictionary valuesForKeys( - Object object, List keys) - { - throw new RuntimeException( "Not implemented yet." ); - } - - public static NSDictionary valuesForKeysWithMapping( - Object object, Map mapping) - { - throw new RuntimeException( "Not implemented yet." ); - } - } + * EOKeyValueCodingAdditions defines an interface for classes that need to have + * more control over the wotonomy's bulk property copying and cloning + * facilities.
+ *
+ * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public interface EOKeyValueCodingAdditions extends EOKeyValueCoding, NSKeyValueCodingAdditions { + + /** + * Static utilities methods that call the appropriate method if the object + * implements NSKeyValueCodingAdditions, otherwise calls the method on + * DefaultImplementation. + */ + public class Utility extends NSKeyValueCodingAdditions.Utility { + /** + * Calls the appropriate method if the object implements + * NSKeyValueCodingAdditions, otherwise calls the method on + * DefaultImplementation. + */ + public static void takeValuesFromDictionary(Object object, Map dictionary) { + if (object instanceof NSKeyValueCodingAdditions) { + ((NSKeyValueCodingAdditions) object).takeValuesFromDictionary(dictionary); + } else { + DefaultImplementation.takeValuesFromDictionary(object, dictionary); + } + } + + /** + * Calls the appropriate method if the object implements + * NSKeyValueCodingAdditions, otherwise calls the method on + * DefaultImplementation. + */ + /* + * public static void takeValuesFromDictionaryWithMapping( Object object, + * NSDictionary dictionary, NSDictionary mapping) { if (object instanceof + * NSKeyValueCodingAdditions) { + * ((NSKeyValueCodingAdditions)object).takeValuesFromDictionaryWithMapping( + * dictionary, mapping); } else { + * DefaultImplementation.takeValuesFromDictionaryWithMapping(object, dictionary, + * mapping); } } + */ + + /** + * Calls the appropriate method if the object implements + * NSKeyValueCodingAdditions, otherwise calls the method on + * DefaultImplementation. + */ + public static NSDictionary valuesForKeys(Object object, List keys) { + if (object instanceof NSKeyValueCodingAdditions) { + return ((NSKeyValueCodingAdditions) object).valuesForKeys(keys); + } else { + return DefaultImplementation.valuesForKeys(object, keys); + } + } + + /** + * Calls the appropriate method if the object implements + * NSKeyValueCodingAdditions, otherwise calls the method on + * DefaultImplementation. + */ + /* + * public static NSDictionary valuesForKeysWithMapping( Object object, + * NSDictionary mapping) { if (object instanceof NSKeyValueCodingAdditions) { + * return ((NSKeyValueCodingAdditions)object).valuesForKeysWithMapping(mapping); + * } else { return DefaultImplementation.valuesForKeysWithMapping(object, + * mapping); } } + */ + } + + /** + * Provides a reflection-based implementation for classes that don't implement + * NSKeyValueCodingAdditions. + */ + public class DefaultImplementation extends NSKeyValueCodingAdditions.DefaultImplementation { + public static void takeValuesFromDictionary(Object object, NSDictionary dictionary) { + throw new RuntimeException("Not implemented yet."); + } + + public static void takeValuesFromDictionaryWithMapping(Object object, NSDictionary dictionary, + NSDictionary mapping) { + throw new RuntimeException("Not implemented yet."); + } + + public static NSDictionary valuesForKeys(Object object, List keys) { + throw new RuntimeException("Not implemented yet."); + } + + public static NSDictionary valuesForKeysWithMapping(Object object, Map mapping) { + throw new RuntimeException("Not implemented yet."); + } + } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.4 2003/01/16 22:47:30 mpowers - * Compatibility changes to support compiling woextensions source. - * (34 out of 56 classes compile!) + * Revision 1.4 2003/01/16 22:47:30 mpowers Compatibility changes to support + * compiling woextensions source. (34 out of 56 classes compile!) * - * Revision 1.3 2001/12/10 15:25:11 mpowers - * Now properly extending EOKeyValueCoding. + * Revision 1.3 2001/12/10 15:25:11 mpowers Now properly extending + * EOKeyValueCoding. * - * 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/03/29 03:29:49 mpowers - * Now using KeyValueCoding and Support instead of Introspector. + * Revision 1.1 2001/03/29 03:29:49 mpowers Now using KeyValueCoding and Support + * instead of Introspector. * - * Revision 1.2 2001/03/28 16:12:30 mpowers - * Documented interface. + * Revision 1.2 2001/03/28 16:12:30 mpowers Documented interface. * - * Revision 1.1 2001/03/27 23:25:05 mpowers - * Contributing interface, no docs yet. + * Revision 1.1 2001/03/27 23:25:05 mpowers Contributing interface, no docs yet. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueCodingSupport.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueCodingSupport.java index 89e3e91..70cf63c 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueCodingSupport.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueCodingSupport.java @@ -25,211 +25,161 @@ import net.wotonomy.foundation.internal.NullPrimitiveException; import net.wotonomy.foundation.internal.WotonomyException; /** -* EOKeyValueCodingSupport defines default behavior for -* classes implementing EOKeyValueSupport.

-* -* On an object that does not implement EOKeyValueCoding, -* wotonomy will call the methods on this class directly. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public class EOKeyValueCodingSupport -{ - /** - * Returns the value for the specified property key - * on the specified object.

- * - * If the property does not exist, this method calls - * handleQueryWithUnboundKey on the object if it - * implements EOKeyValueCoding, otherwise calls - * handleQueryWithUnboundKey on this class.

- */ - static public Object valueForKey( - Object anObject, String aKey ) - { - //TODO: may need to handle "." nesting here so - // that handleQueryWithUnboundKey gets called for - // for the nested object, not the parent object - - //Correction: need to handle key paths in - // KeyValueCodingAdditionsSupport. - - try - { - return Introspector.get( anObject, aKey ); - } - catch ( IntrospectorException exc ) - { - if ( anObject instanceof EOKeyValueCoding ) - { - return ((EOKeyValueCoding)anObject).handleQueryWithUnboundKey( aKey ); - } - return handleQueryWithUnboundKey( anObject, aKey ); - } - } - - /** - * Sets the property to the specified value on - * the specified object. - * - * If the property does not exist, this method calls - * handleTakeValueForUnboundKey on the object if it - * implements EOKeyValueCoding, otherwise calls - * handleTakeValueForUnboundKey on this class. - * - * If the property is of a type that cannot allow - * null (e.g. primitive types) and aValue is null, - * this method should call unableToSetNullForKey - * on the object if it implements EOKeyValueCoding, - * otherwise calls unableToSetNullForKey on this class. - */ - static public void takeValueForKey( - Object anObject, Object aValue, String aKey ) - { - //TODO: may need to handle "." nesting here so - // that handleTakeValueForUnboundKey gets called for - // for the nested object, not the parent object - - try - { - Introspector.set( anObject, aKey, aValue ); - } - catch ( NullPrimitiveException exc ) - { - if ( anObject instanceof EOKeyValueCoding ) - { - ((EOKeyValueCoding)anObject).unableToSetNullForKey( aKey ); - } - else - { - unableToSetNullForKey( anObject, aKey ); - } - } - catch ( MissingPropertyException exc ) - { - if ( anObject instanceof EOKeyValueCoding ) - { - ((EOKeyValueCoding)anObject).handleTakeValueForUnboundKey( - aValue, aKey ); - } - else - { - handleTakeValueForUnboundKey( anObject, aValue, aKey ); - } - } - - } - - /** - * Returns the value for the private field that - * corresponds to the specified property on - * the specified object. - * - * This implementation currently calls valueForKey, - * because java security currently prevents us from - * accessing the fields of another object. - */ - static public Object storedValueForKey( - Object anObject, String aKey ) - { - //TODO: this currently just calls valueForKey - return valueForKey( anObject, aKey ); - } - - /** - * Sets the the private field that corresponds to the - * specified property to the specified value on the - * specified object. - * - * This implementation currently calls takeValueForKey, - * because java security currently prevents us from - * accessing the fields of another object. - */ - static public void takeStoredValueForKey( - Object anObject, Object aValue, String aKey ) - { - //TODO: this currently just calls takeValueForKey - takeValueForKey( anObject, aValue, aKey ); - } - - /** - * Called by valueForKey when the specified key is - * not found on the specified object, if that object - * does not implement EOKeyValueCoding. - * - * This implementation throws a WotonomyException. - */ - static public Object handleQueryWithUnboundKey( - Object anObject, String aKey ) - { - throw new WotonomyException( - "Key not found for object: " - + aKey + " : " + anObject ); - } - - /** - * Called by takeValueForKey when the specified key - * is not found on the specified object, if that object - * does not implement EOKeyValueCoding. - * - * This implementation throws a WotonomyException. - */ - static public void handleTakeValueForUnboundKey( - Object anObject, Object aValue, String aKey ) - { - throw new WotonomyException( - "Key not found for object while setting value: " - + aKey + " : " + anObject + " : " + aValue ); - } - - /** - * Called by takeValueForKey when the type of the - * specified key is not allowed to be null, as is - * the case with primitive types, if the specified - * object does not implement EOKeyValueCoding. - * - * This implementation throws a WotonomyException. - */ - static public void unableToSetNullForKey( - Object anObject, String aKey ) - { - throw new WotonomyException( - "Tried to key on object to null: " - + aKey + " : " + anObject ); - } + * EOKeyValueCodingSupport defines default behavior for classes implementing + * EOKeyValueSupport.
+ *
+ * + * On an object that does not implement EOKeyValueCoding, wotonomy will call the + * methods on this class directly. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public class EOKeyValueCodingSupport { + /** + * Returns the value for the specified property key on the specified object. + *
+ *
+ * + * If the property does not exist, this method calls handleQueryWithUnboundKey + * on the object if it implements EOKeyValueCoding, otherwise calls + * handleQueryWithUnboundKey on this class.
+ *
+ */ + static public Object valueForKey(Object anObject, String aKey) { + // TODO: may need to handle "." nesting here so + // that handleQueryWithUnboundKey gets called for + // for the nested object, not the parent object + + // Correction: need to handle key paths in + // KeyValueCodingAdditionsSupport. + + try { + return Introspector.get(anObject, aKey); + } catch (IntrospectorException exc) { + if (anObject instanceof EOKeyValueCoding) { + return ((EOKeyValueCoding) anObject).handleQueryWithUnboundKey(aKey); + } + return handleQueryWithUnboundKey(anObject, aKey); + } + } + + /** + * Sets the property to the specified value on the specified object. + * + * If the property does not exist, this method calls + * handleTakeValueForUnboundKey on the object if it implements EOKeyValueCoding, + * otherwise calls handleTakeValueForUnboundKey on this class. + * + * If the property is of a type that cannot allow null (e.g. primitive types) + * and aValue is null, this method should call unableToSetNullForKey on the + * object if it implements EOKeyValueCoding, otherwise calls + * unableToSetNullForKey on this class. + */ + static public void takeValueForKey(Object anObject, Object aValue, String aKey) { + // TODO: may need to handle "." nesting here so + // that handleTakeValueForUnboundKey gets called for + // for the nested object, not the parent object + + try { + Introspector.set(anObject, aKey, aValue); + } catch (NullPrimitiveException exc) { + if (anObject instanceof EOKeyValueCoding) { + ((EOKeyValueCoding) anObject).unableToSetNullForKey(aKey); + } else { + unableToSetNullForKey(anObject, aKey); + } + } catch (MissingPropertyException exc) { + if (anObject instanceof EOKeyValueCoding) { + ((EOKeyValueCoding) anObject).handleTakeValueForUnboundKey(aValue, aKey); + } else { + handleTakeValueForUnboundKey(anObject, aValue, aKey); + } + } + + } + + /** + * Returns the value for the private field that corresponds to the specified + * property on the specified object. + * + * This implementation currently calls valueForKey, because java security + * currently prevents us from accessing the fields of another object. + */ + static public Object storedValueForKey(Object anObject, String aKey) { + // TODO: this currently just calls valueForKey + return valueForKey(anObject, aKey); + } + + /** + * Sets the the private field that corresponds to the specified property to the + * specified value on the specified object. + * + * This implementation currently calls takeValueForKey, because java security + * currently prevents us from accessing the fields of another object. + */ + static public void takeStoredValueForKey(Object anObject, Object aValue, String aKey) { + // TODO: this currently just calls takeValueForKey + takeValueForKey(anObject, aValue, aKey); + } + + /** + * Called by valueForKey when the specified key is not found on the specified + * object, if that object does not implement EOKeyValueCoding. + * + * This implementation throws a WotonomyException. + */ + static public Object handleQueryWithUnboundKey(Object anObject, String aKey) { + throw new WotonomyException("Key not found for object: " + aKey + " : " + anObject); + } + + /** + * Called by takeValueForKey when the specified key is not found on the + * specified object, if that object does not implement EOKeyValueCoding. + * + * This implementation throws a WotonomyException. + */ + static public void handleTakeValueForUnboundKey(Object anObject, Object aValue, String aKey) { + throw new WotonomyException( + "Key not found for object while setting value: " + aKey + " : " + anObject + " : " + aValue); + } + + /** + * Called by takeValueForKey when the type of the specified key is not allowed + * to be null, as is the case with primitive types, if the specified object does + * not implement EOKeyValueCoding. + * + * This implementation throws a WotonomyException. + */ + static public void unableToSetNullForKey(Object anObject, String aKey) { + throw new WotonomyException("Tried to key on object to null: " + aKey + " : " + anObject); + } } - /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.5 2003/01/16 22:47:30 mpowers - * Compatibility changes to support compiling woextensions source. - * (34 out of 56 classes compile!) + * Revision 1.5 2003/01/16 22:47:30 mpowers Compatibility changes to support + * compiling woextensions source. (34 out of 56 classes compile!) * - * Revision 1.4 2001/05/18 21:04:33 mpowers - * Reimplemented EditingContext.initializeObject. + * Revision 1.4 2001/05/18 21:04:33 mpowers Reimplemented + * EditingContext.initializeObject. * - * Revision 1.3 2001/04/27 00:28:29 mpowers - * Fixed a return value. + * Revision 1.3 2001/04/27 00:28:29 mpowers Fixed a return value. * - * Revision 1.2 2001/04/03 20:36:01 mpowers - * Fixed refaulting/reverting/invalidating to be self-consistent. + * Revision 1.2 2001/04/03 20:36:01 mpowers Fixed + * refaulting/reverting/invalidating to be self-consistent. * - * Revision 1.1 2001/03/28 17:49:33 mpowers - * Implemented EOKeyValueCodingSupport. + * Revision 1.1 2001/03/28 17:49:33 mpowers Implemented EOKeyValueCodingSupport. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueQualifier.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueQualifier.java index 799955e..4ced471 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueQualifier.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueQualifier.java @@ -24,100 +24,80 @@ import net.wotonomy.foundation.NSSelector; import net.wotonomy.foundation.internal.WotonomyException; /** -* EOKeyValueQualifier performs a property-based -* comparison against a specified value. The comparison -* is specified in the form of a NSSelector. The -* selector is expected to take two arguments, the -* property value on an object and the comparison value, -* and return a Boolean indicating whether the object -* is qualified. EOQualifier defines selectors that -* may be used in creating EOKeyValueQualifiers. -* -* @author michael@mpowers.net -* @author yjcheung@intersectsoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public class EOKeyValueQualifier extends EOQualifier - implements EOKeyValueArchiving, EOQualifierEvaluation -{ - private String key; - private NSSelector selector; - private Object value; - - /** - * Constructor specifying a property key, a selector, - * and a value for comparison. The selector may be - * one of the constant selectors defined on EOQualifier. - */ - public EOKeyValueQualifier( - String aKey, - NSSelector aSelector, - Object aValue ) - { - key = aKey; - selector = aSelector; - value = aValue; - } - - /** - * Returns the key for this qualifier. - */ - public String key() - { - return key; - } - - /** - * Returns the selector for this qualifier. - */ - public NSSelector selector() - { - return selector; - } - - /** - * Returns the value for this qualifier. - */ - public Object value() - { - return value; - } - - /** - * Evaluates this qualifier for the specified object, - * and returns whether the object is qualified. - * selector() is invoked on the value for key() on the - * specified object, with value() as the parameter. - */ - public boolean evaluateWithObject( Object anObject ) - { - try - { - Object value; - if ( anObject instanceof EOKeyValueCoding ) - { - value = ((EOKeyValueCoding)anObject).valueForKey( key() ); - } - else - { - value = EOKeyValueCodingSupport.valueForKey( anObject, key() ); - } - return ((Boolean)selector.invoke( value(), value)).booleanValue(); - } - catch ( Exception exc ) - { - throw new WotonomyException( exc ); - } - } - - /** - * Returns a string representation of this qualifier. - */ - public String toString() - { - return "( " + key + " " + selector + " " + value + " )"; - } + * EOKeyValueQualifier performs a property-based comparison against a specified + * value. The comparison is specified in the form of a NSSelector. The selector + * is expected to take two arguments, the property value on an object and the + * comparison value, and return a Boolean indicating whether the object is + * qualified. EOQualifier defines selectors that may be used in creating + * EOKeyValueQualifiers. + * + * @author michael@mpowers.net + * @author yjcheung@intersectsoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public class EOKeyValueQualifier extends EOQualifier implements EOKeyValueArchiving, EOQualifierEvaluation { + private String key; + private NSSelector selector; + private Object value; + + /** + * Constructor specifying a property key, a selector, and a value for + * comparison. The selector may be one of the constant selectors defined on + * EOQualifier. + */ + public EOKeyValueQualifier(String aKey, NSSelector aSelector, Object aValue) { + key = aKey; + selector = aSelector; + value = aValue; + } + + /** + * Returns the key for this qualifier. + */ + public String key() { + return key; + } + + /** + * Returns the selector for this qualifier. + */ + public NSSelector selector() { + return selector; + } + + /** + * Returns the value for this qualifier. + */ + public Object value() { + return value; + } + + /** + * Evaluates this qualifier for the specified object, and returns whether the + * object is qualified. selector() is invoked on the value for key() on the + * specified object, with value() as the parameter. + */ + public boolean evaluateWithObject(Object anObject) { + try { + Object value; + if (anObject instanceof EOKeyValueCoding) { + value = ((EOKeyValueCoding) anObject).valueForKey(key()); + } else { + value = EOKeyValueCodingSupport.valueForKey(anObject, key()); + } + return ((Boolean) selector.invoke(value(), value)).booleanValue(); + } catch (Exception exc) { + throw new WotonomyException(exc); + } + } + + /** + * Returns a string representation of this qualifier. + */ + public String toString() { + return "( " + key + " " + selector + " " + value + " )"; + } public void encodeWithKeyValueArchiver(EOKeyValueArchiver arch) { arch.encodeObject("EOKeyValueQualifier", "class"); @@ -159,10 +139,10 @@ public class EOKeyValueQualifier extends EOQualifier } public static Object decodeWithKeyValueUnarchiver(EOKeyValueUnarchiver arch) { - String k = (String)arch.decodeObjectForKey("key"); + String k = (String) arch.decodeObjectForKey("key"); Object v = arch.decodeObjectForKey("value"); NSSelector sel = null; - String sname = (String)arch.decodeObjectForKey("selectorName"); + String sname = (String) arch.decodeObjectForKey("selectorName"); if (sname.equals("isEqualTo:")) sel = EOQualifier.QualifierOperatorEqual; else if (sname.equals("isNotEqualTo:")) @@ -188,46 +168,42 @@ public class EOKeyValueQualifier extends EOQualifier } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.10 2003/08/12 01:43:04 chochos - * formally implement EOQualifierEvaluation + * Revision 1.10 2003/08/12 01:43:04 chochos formally implement + * EOQualifierEvaluation * - * Revision 1.9 2003/08/11 19:39:30 chochos - * special conditions for NSKeyValueCoding.NullValue -> EONull + * Revision 1.9 2003/08/11 19:39:30 chochos special conditions for + * NSKeyValueCoding.NullValue -> EONull * - * Revision 1.8 2003/08/09 01:22:51 chochos - * qualifiers implement EOKeyValueArchiving + * Revision 1.8 2003/08/09 01:22:51 chochos qualifiers implement + * EOKeyValueArchiving * - * Revision 1.7 2003/08/06 23:07:52 chochos - * general code cleanup (mostly, removing unused imports) + * Revision 1.7 2003/08/06 23:07:52 chochos general code cleanup (mostly, + * removing unused imports) * - * Revision 1.6 2001/10/31 15:26:06 mpowers - * Fixed typo. + * Revision 1.6 2001/10/31 15:26:06 mpowers Fixed typo. * - * Revision 1.5 2001/10/31 15:25:14 mpowers - * Cleanup of qualifiers. + * Revision 1.5 2001/10/31 15:25:14 mpowers Cleanup of qualifiers. * - * Revision 1.4 2001/10/30 22:57:28 mpowers - * EOQualifier framework is now working. + * Revision 1.4 2001/10/30 22:57:28 mpowers EOQualifier framework is now + * working. * - * Revision 1.3 2001/09/13 15:25:56 mpowers - * Started implementation of the EOQualifier framework. + * Revision 1.3 2001/09/13 15:25:56 mpowers Started implementation of the + * EOQualifier framework. * - * Revision 1.2 2001/03/29 03:29:49 mpowers - * Now using KeyValueCoding and Support instead of Introspector. + * Revision 1.2 2001/03/29 03:29:49 mpowers Now using KeyValueCoding and Support + * instead of Introspector. * - * Revision 1.1 2001/02/27 03:33:04 mpowers - * Initial draft of the key-value qualifier. + * Revision 1.1 2001/02/27 03:33:04 mpowers Initial draft of the key-value + * qualifier. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueUnarchiver.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueUnarchiver.java index caed8a4..5238c70 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueUnarchiver.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOKeyValueUnarchiver.java @@ -22,17 +22,18 @@ import java.lang.reflect.Method; import net.wotonomy.foundation.NSDictionary; import net.wotonomy.foundation.NSKeyValueCoding; -/** Creates objects from dictionaries that were created with - * EOKeyValueArchiver. -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ +/** + * Creates objects from dictionaries that were created with EOKeyValueArchiver. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public class EOKeyValueUnarchiver { NSDictionary dict; Object _delegate; - protected static final Class[] METHOD_ARGS = new Class[]{ EOKeyValueUnarchiver.class }; + protected static final Class[] METHOD_ARGS = new Class[] { EOKeyValueUnarchiver.class }; public EOKeyValueUnarchiver(NSDictionary archive) { super(); @@ -54,7 +55,7 @@ public class EOKeyValueUnarchiver { if (x == null) return 0; if (x instanceof Number) - return ((Number)x).intValue(); + return ((Number) x).intValue(); try { int i = Integer.parseInt(x.toString()); return i; @@ -68,7 +69,7 @@ public class EOKeyValueUnarchiver { if (x == null) return null; if (x instanceof NSDictionary) { - NSDictionary d = (NSDictionary)x; + NSDictionary d = (NSDictionary) x; if (d.objectForKey("class") != null) { String cname = d.objectForKey("class").toString(); Class _class = null; @@ -82,11 +83,11 @@ public class EOKeyValueUnarchiver { if (d.objectForKey("value") != null) return d.objectForKey("value").toString(); } else if (cname.equals("EONull")) { - return NSKeyValueCoding.NullValue; + return NSKeyValueCoding.NullValue; } else if (cname.equals("EOFetchSpecification")) { _class = EOFetchSpecification.class; } else if (cname.equals("EOKeyValueQualifier")) { - _class = EOKeyValueQualifier.class; + _class = EOKeyValueQualifier.class; } else if (cname.equals("EONotQualifier")) { _class = EONotQualifier.class; } else if (cname.equals("EOAndQualifier")) { @@ -95,12 +96,12 @@ public class EOKeyValueUnarchiver { _class = EOOrQualifier.class; } else if (cname.equals("EOSortOrdering")) { _class = EOSortOrdering.class; - } else if (cname.indexOf(".") < 0) { //Load a class without package + } else if (cname.indexOf(".") < 0) { // Load a class without package try { _class = Class.forName("net.wotonomy.control." + cname); } catch (ClassNotFoundException ex) { } - //search for the class in access + // search for the class in access if (_class == null) { try { _class = Class.forName("net.wotonomy.access." + cname); @@ -117,7 +118,7 @@ public class EOKeyValueUnarchiver { return x; try { Method met = _class.getMethod("decodeWithKeyValueUnarchiver", METHOD_ARGS); - return met.invoke(null, new Object[]{ new EOKeyValueUnarchiver(d) }); + return met.invoke(null, new Object[] { new EOKeyValueUnarchiver(d) }); } catch (Exception ex) { ex.printStackTrace(); return x; @@ -144,22 +145,23 @@ public class EOKeyValueUnarchiver { public void setDelegate(Object del) { _delegate = del; } + public Object delegate() { return _delegate; } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.2 2003/08/11 18:17:41 chochos - * decoding of objects now works properly + * Revision 1.2 2003/08/11 18:17:41 chochos decoding of objects now works + * properly * */ \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EONotQualifier.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EONotQualifier.java index d086840..1068fd7 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EONotQualifier.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EONotQualifier.java @@ -21,54 +21,46 @@ package net.wotonomy.control; import net.wotonomy.foundation.internal.WotonomyException; /** -* EONotQualifiier negates a specified qualifier, -* evaluating to the opposite of the specified qualifier. -* -* @author michael@mpowers.net -* @author yjcheung@intersectsoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public class EONotQualifier extends EOQualifier - implements EOKeyValueArchiving, EOQualifierEvaluation -{ - private EOQualifier qualifier; + * EONotQualifiier negates a specified qualifier, evaluating to the opposite of + * the specified qualifier. + * + * @author michael@mpowers.net + * @author yjcheung@intersectsoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public class EONotQualifier extends EOQualifier implements EOKeyValueArchiving, EOQualifierEvaluation { + private EOQualifier qualifier; - public EONotQualifier( - EOQualifier aQualifier ) - { - qualifier = aQualifier; - } + public EONotQualifier(EOQualifier aQualifier) { + qualifier = aQualifier; + } - /** - * Returns the qualifier that this qualifier negates. - */ - public EOQualifier qualifier() - { - return qualifier; - } + /** + * Returns the qualifier that this qualifier negates. + */ + public EOQualifier qualifier() { + return qualifier; + } - /** - * Evaluates this qualifier for the specified object, - * and returns whether the object is qualified. - * evaluateWithObject is invoked on qualifier - * and the result is negated and returned. - */ - public boolean evaluateWithObject( Object anObject ) - { - return !(qualifier.evaluateWithObject(anObject)); - } + /** + * Evaluates this qualifier for the specified object, and returns whether the + * object is qualified. evaluateWithObject is invoked on qualifier and the + * result is negated and returned. + */ + public boolean evaluateWithObject(Object anObject) { + return !(qualifier.evaluateWithObject(anObject)); + } - /** - * Returns a string representation of this qualifier. - */ - public String toString() - { - return (new StringBuffer("Not ").append(qualifier.toString()).toString()); - } + /** + * Returns a string representation of this qualifier. + */ + public String toString() { + return (new StringBuffer("Not ").append(qualifier.toString()).toString()); + } public static Object decodeWithKeyValueUnarchiver(EOKeyValueUnarchiver arch) { - EOQualifier q = (EOQualifier)arch.decodeObjectForKey("qualifier"); + EOQualifier q = (EOQualifier) arch.decodeObjectForKey("qualifier"); if (q == null) return null; return new EONotQualifier(q); @@ -78,7 +70,7 @@ public class EONotQualifier extends EOQualifier arch.encodeObject("EONotQualifier", "class"); if (qualifier instanceof EOKeyValueArchiving) { EOKeyValueArchiver ar2 = new EOKeyValueArchiver(); - ((EOKeyValueArchiving)qualifier).encodeWithKeyValueArchiver(ar2); + ((EOKeyValueArchiving) qualifier).encodeWithKeyValueArchiver(ar2); arch.encodeObject(ar2.dictionary(), "qualifiers"); } else throw new WotonomyException("Cannot archive instance of " + qualifier.getClass().getName()); @@ -87,43 +79,37 @@ public class EONotQualifier extends EOQualifier } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.9 2003/08/12 01:43:04 chochos - * formally implement EOQualifierEvaluation + * Revision 1.9 2003/08/12 01:43:04 chochos formally implement + * EOQualifierEvaluation * - * Revision 1.8 2003/08/11 19:39:30 chochos - * special conditions for NSKeyValueCoding.NullValue -> EONull + * Revision 1.8 2003/08/11 19:39:30 chochos special conditions for + * NSKeyValueCoding.NullValue -> EONull * - * Revision 1.7 2003/08/09 01:24:19 chochos - * implements EOKeyValueArchiving + * Revision 1.7 2003/08/09 01:24:19 chochos implements EOKeyValueArchiving * - * Revision 1.6 2003/08/06 23:07:52 chochos - * general code cleanup (mostly, removing unused imports) + * Revision 1.6 2003/08/06 23:07:52 chochos general code cleanup (mostly, + * removing unused imports) * - * Revision 1.5 2001/10/31 15:25:14 mpowers - * Cleanup of qualifiers. + * Revision 1.5 2001/10/31 15:25:14 mpowers Cleanup of qualifiers. * - * Revision 1.4 2001/10/30 22:57:28 mpowers - * EOQualifier framework is now working. + * Revision 1.4 2001/10/30 22:57:28 mpowers EOQualifier framework is now + * working. * - * Revision 1.3 2001/09/13 15:42:20 mpowers - * Fixed another cut/paste typo. + * Revision 1.3 2001/09/13 15:42:20 mpowers Fixed another cut/paste typo. * - * Revision 1.2 2001/09/13 15:41:34 mpowers - * Fixed typo. + * Revision 1.2 2001/09/13 15:41:34 mpowers Fixed typo. * - * Revision 1.1 2001/09/13 15:38:19 mpowers - * Started implementation of the EOQualifier framework. + * Revision 1.1 2001/09/13 15:38:19 mpowers Started implementation of the + * EOQualifier framework. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EONullValue.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EONullValue.java index 3b4544e..1ecce4d 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EONullValue.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EONullValue.java @@ -23,91 +23,84 @@ import java.io.Serializable; import net.wotonomy.foundation.NSNull; /** -* EONullValue is used to represent null in Collections classes -* because List and Map do not specify whether null values -* are allowed and because NSArray and NSDictionary explicitly -* do not allow null values.

-* -* Use of the static singleton method nullValue() is required -* by this implementation because Java cannot return a singleton -* instance from a constructor.

-* -* This implementation duplicates NSNull, but the singleton instances -* are of course different. Be careful. I have no idea why this -* class was even created, given that NSNull exists. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public class EONullValue implements Serializable -{ - private static final EONullValue instance = new EONullValue(); - - /** - * Create a new instance of EONullValue. - */ - private EONullValue () - { - } + * EONullValue is used to represent null in Collections classes because List and + * Map do not specify whether null values are allowed and because NSArray and + * NSDictionary explicitly do not allow null values.
+ *
+ * + * Use of the static singleton method nullValue() is required by this + * implementation because Java cannot return a singleton instance from a + * constructor.
+ *
+ * + * This implementation duplicates NSNull, but the singleton instances are of + * course different. Be careful. I have no idea why this class was even created, + * given that NSNull exists. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public class EONullValue implements Serializable { + private static final EONullValue instance = new EONullValue(); - /** - * Constructor specifying name and object. - */ - public static EONullValue nullValue () - { - return instance; - } + /** + * Create a new instance of EONullValue. + */ + private EONullValue() { + } - /** - * Returns a human-readable string representation. - */ - public String toString() - { - return "[null]"; - } - - /** - * Hashcode of all instances is zero. - */ - public int hashCode() - { - return 0; - } - - /** - * Implemented to return true for any instance of EONullValue - * and for any instance of NSNull. - */ - public boolean equals( Object anObject ) - { - if ( anObject instanceof EONullValue ) return true; - if ( anObject instanceof NSNull ) return true; - return false; - } + /** + * Constructor specifying name and object. + */ + public static EONullValue nullValue() { + return instance; + } + + /** + * Returns a human-readable string representation. + */ + public String toString() { + return "[null]"; + } + + /** + * Hashcode of all instances is zero. + */ + public int hashCode() { + return 0; + } + + /** + * Implemented to return true for any instance of EONullValue and for any + * instance of NSNull. + */ + public boolean equals(Object anObject) { + if (anObject instanceof EONullValue) + return true; + if (anObject instanceof NSNull) + return true; + return false; + } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.3 2003/08/06 23:07:52 chochos - * general code cleanup (mostly, removing unused imports) + * Revision 1.3 2003/08/06 23:07:52 chochos general code cleanup (mostly, + * removing unused imports) * - * Revision 1.2 2001/03/01 20:35:38 mpowers - * Implemented equals and hashCode. + * Revision 1.2 2001/03/01 20:35:38 mpowers Implemented equals and hashCode. * - * Revision 1.1 2001/02/26 22:41:51 mpowers - * Implemented null placeholder classes. - * Duplicator now uses NSNull. - * No longer catching base exception class. + * Revision 1.1 2001/02/26 22:41:51 mpowers Implemented null placeholder + * classes. Duplicator now uses NSNull. No longer catching base exception class. * * */ - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObjectStore.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObjectStore.java index cd18e36..4f60045 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObjectStore.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObjectStore.java @@ -24,297 +24,234 @@ import java.util.Map; import net.wotonomy.foundation.NSArray; /** -* EOObjectStore defines an object repository that tracks -* object creations, deletions, and updates made by -* EOEditingContexts.

-* -* A concrete implementation would probably write these -* changes to some kind of persistent storage, like a -* database.

-* -* EOEditingContext is itself a subclass of EOObjectStore -* that requires an EOObjectStore parent for committing -* its changes. This means that EOEditingContexts can -* use other EOEditingContexts as their parent, but there -* still must exist an EOObjectStore as the root of the -* editing graph. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public abstract class EOObjectStore -{ - /** - * Key for the user info of ObjectsChangedInStoreNotifications. - * The key should retrieve an array of deleted EOGlobalIDs. - */ - public static final String DeletedKey = "deleted"; + * EOObjectStore defines an object repository that tracks object creations, + * deletions, and updates made by EOEditingContexts.
+ *
+ * + * A concrete implementation would probably write these changes to some kind of + * persistent storage, like a database.
+ *
+ * + * EOEditingContext is itself a subclass of EOObjectStore that requires an + * EOObjectStore parent for committing its changes. This means that + * EOEditingContexts can use other EOEditingContexts as their parent, but there + * still must exist an EOObjectStore as the root of the editing graph. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public abstract class EOObjectStore { + /** + * Key for the user info of ObjectsChangedInStoreNotifications. The key should + * retrieve an array of deleted EOGlobalIDs. + */ + public static final String DeletedKey = "deleted"; + + /** + * Key for the user info of ObjectsChangedInStoreNotifications. The key should + * retrieve an array of inserted EOGlobalIDs. + */ + public static final String InsertedKey = "inserted"; + + /** + * Key for the user info of ObjectsChangedInStoreNotifications. The key should + * retrieve an array of updated EOGlobalIDs. EOEditingContexts should refault + * their copies of these objects. + */ + public static final String UpdatedKey = "updated"; + + /** + * Key for the user info of ObjectsChangedInStoreNotification. The key should + * retrieve an array of EOGlobalIDs. + */ + public static final String InvalidatedKey = "invalidated"; + + /** + * Key for the NSNotification posted when this object store is asked to + * invalidate all objects. Object of the notification will be this object store, + * and user info will contain the InvalidatedKey. + */ + public static final String InvalidatedAllObjectsInStoreNotification = "EOInvalidatedAllObjectsInStoreNotification"; + + /** + * Key for the NSNotification posted when this object store is changed. Object + * of the notification will be this object store, and user info will contain + * InsertedKey, UpdatedKey, DeletedKey, and InvalidatedKey. + */ + public static final String ObjectsChangedInStoreNotification = "EOObjectsChangedInStoreNotification"; - /** - * Key for the user info of ObjectsChangedInStoreNotifications. - * The key should retrieve an array of inserted EOGlobalIDs. - */ - public static final String InsertedKey = "inserted"; + /** + * Default constructor is responsible for initializing internal state. + */ + public EOObjectStore() { + } - /** - * Key for the user info of ObjectsChangedInStoreNotifications. - * The key should retrieve an array of updated EOGlobalIDs. - * EOEditingContexts should refault their copies of these objects. - */ - public static final String UpdatedKey = "updated"; + /** + * Called by editing contexts when they no longer need to track the specified + * id. You will not need to call this method, but you use use it for a hint that + * the specified global id is not in use by that child editing context. + */ + public void editingContextDidForgetObjectWithGlobalID(EOEditingContext aContext, EOGlobalID aGlobalID) { + } - /** - * Key for the user info of ObjectsChangedInStoreNotification. - * The key should retrieve an array of EOGlobalIDs. - */ - public static final String InvalidatedKey = "invalidated"; + /** + * Returns a List of objects associated with the object with the specified id + * for the specified property relationship, or may return a placeholder array + * that will defer the fetch until accessed (an array fault). All objects must + * be registered the specified editing context. The specified relationship key + * must produce a result of type Collection for the source object or an + * exception is thrown. + */ + public abstract NSArray arrayFaultWithSourceGlobalID(EOGlobalID aGlobalID, String aRelationship, + EOEditingContext aContext); - /** - * Key for the NSNotification posted when this object store - * is asked to invalidate all objects. Object of the notification - * will be this object store, and user info will contain the - * InvalidatedKey. - */ - public static final String - InvalidatedAllObjectsInStoreNotification = - "EOInvalidatedAllObjectsInStoreNotification"; + /** + * Returns the object for the specified id. The returned object may be a fault. + * The object will be registered in the specified editing context. + */ + public abstract /* EOEnterpriseObject */ Object faultForGlobalID(EOGlobalID aGlobalID, EOEditingContext aContext); - /** - * Key for the NSNotification posted when this object store - * is changed. Object of the notification will be this object - * store, and user info will contain InsertedKey, UpdatedKey, - * DeletedKey, and InvalidatedKey. - */ - public static final String - ObjectsChangedInStoreNotification = - "EOObjectsChangedInStoreNotification"; - - /** - * Default constructor is responsible for initializing - * internal state. - */ - public EOObjectStore () - { - } + /** + * Returns a fault representing an object of the specified entity type with + * values from the specified dictionary. The fault should belong to the + * specified editing context. + */ + public abstract /* EOEnterpriseObject */ Object faultForRawRow(Map aDictionary, String anEntityName, + EOEditingContext aContext); - /** - * Called by editing contexts when they no longer - * need to track the specified id. You will not need - * to call this method, but you use use it for a hint - * that the specified global id is not in use by that - * child editing context. - */ - public void editingContextDidForgetObjectWithGlobalID ( - EOEditingContext aContext, - EOGlobalID aGlobalID ) - { - } - - /** - * Returns a List of objects associated with the object - * with the specified id for the specified property - * relationship, or may return a placeholder array that - * will defer the fetch until accessed (an array fault). - * All objects must be registered the specified editing context. - * The specified relationship key must produce a result of - * type Collection for the source object or an exception is thrown. - */ - public abstract NSArray arrayFaultWithSourceGlobalID ( - EOGlobalID aGlobalID, - String aRelationship, - EOEditingContext aContext ); - - /** - * Returns the object for the specified id. - * The returned object may be a fault. - * The object will be registered in the - * specified editing context. - */ - public abstract /*EOEnterpriseObject*/ Object faultForGlobalID ( - EOGlobalID aGlobalID, - EOEditingContext aContext ); - - /** - * Returns a fault representing an object of - * the specified entity type with values from - * the specified dictionary. The fault should - * belong to the specified editing context. - */ - public abstract /*EOEnterpriseObject*/ Object faultForRawRow ( - Map aDictionary, - String anEntityName, - EOEditingContext aContext ); - - /** - * Given a newly instantiated object, this method - * initializes its properties to values appropriate - * for the specified id. The object should already - * belong to the specified editing context. - * This method is called to populate faults. - */ - public abstract void initializeObject ( - /*EOEnterpriseObject*/ Object eo, - EOGlobalID aGlobalID, - EOEditingContext aContext ); - - /** - * Remove all values from all objects in memory, - * turning them into faults, and posts an NSNotification - * that all objects have been invalidated. - * The notification should be named with the string - * constant InvalidatedAllObjectsInStoreNotification - * with this object store as the object and no user info. - */ - public abstract void invalidateAllObjects (); - - /** - * Removes values with the specified ids from memory, - * turning them into faults, and posts a notification - * that those objects have been invalidated. - * The notification should be named with the string - * constant ObjectsChangedInStoreNotification - * with this object store as the object and user info - * containing a key named InvalidateKey that returns - * a List of the EOGlobalIDs of the invalidated objects. - */ - public abstract void invalidateObjectsWithGlobalIDs ( - List aList ); - - /** - * Returns whether the object corresponding to the - * specified id is locked. The concept of object - * locking is implementation-specific. - */ - public abstract boolean isObjectLockedWithGlobalID ( - EOGlobalID aGlobalID, - EOEditingContext aContext ); - - /** - * Locks the object corresponding to the - * specified id is locked. The concept of object - * locking is implementation-specific. - * The lock may be released when objects are - * invalidated or commited, but this behavior - * is not required. - */ - public abstract void lockObjectWithGlobalID ( - EOGlobalID aGlobalID, - EOEditingContext aContext ); - - /** - * Returns a List of objects associated with the object - * with the specified id for the specified property - * relationship. This method may not return an array fault - * because array faults call this method to fetch on demand. - * All objects must be registered the specified editing context. - * The specified relationship key must produce a result of - * type Collection for the source object or an exception is thrown. - */ - public abstract NSArray objectsForSourceGlobalID ( - EOGlobalID aGlobalID, - String aRelationship, - EOEditingContext aContext ); - - /** - * Returns a List of objects the meet the criteria of - * the supplied specification. Faults are not allowed in the array. - * Each object is registered with the specified editing context. - * If any object is already fetched in the specified context, - * it is not refetched and that object should be used in the array. - */ - public abstract NSArray objectsWithFetchSpecification ( - EOFetchSpecification aFetchSpec, - EOEditingContext aContext ); - - /** - * Removes all values from the specified object, - * converting it into a fault for the specified id. - * New or deleted objects should not be refaulted. - */ - public abstract void refaultObject ( - Object anObject, - EOGlobalID aGlobalID, - EOEditingContext aContext ); - - /** - * Writes all changes in the specified editing context - * to the respository. The object store is expected to - * post a notification that should be named with the string - * constant ObjectsChangedInStoreNotification - * with this object store as the object and user info - * containing keys named UpdatedKey, InsertedKey, and - * DeletedKey that return Lists of the EOGlobalIDs of the - * corresponding objects. - */ - public abstract void saveChangesInEditingContext ( - EOEditingContext aContext ); + /** + * Given a newly instantiated object, this method initializes its properties to + * values appropriate for the specified id. The object should already belong to + * the specified editing context. This method is called to populate faults. + */ + public abstract void initializeObject(/* EOEnterpriseObject */ Object eo, EOGlobalID aGlobalID, + EOEditingContext aContext); + + /** + * Remove all values from all objects in memory, turning them into faults, and + * posts an NSNotification that all objects have been invalidated. The + * notification should be named with the string constant + * InvalidatedAllObjectsInStoreNotification with this object store as the object + * and no user info. + */ + public abstract void invalidateAllObjects(); + + /** + * Removes values with the specified ids from memory, turning them into faults, + * and posts a notification that those objects have been invalidated. The + * notification should be named with the string constant + * ObjectsChangedInStoreNotification with this object store as the object and + * user info containing a key named InvalidateKey that returns a List of the + * EOGlobalIDs of the invalidated objects. + */ + public abstract void invalidateObjectsWithGlobalIDs(List aList); + + /** + * Returns whether the object corresponding to the specified id is locked. The + * concept of object locking is implementation-specific. + */ + public abstract boolean isObjectLockedWithGlobalID(EOGlobalID aGlobalID, EOEditingContext aContext); + + /** + * Locks the object corresponding to the specified id is locked. The concept of + * object locking is implementation-specific. The lock may be released when + * objects are invalidated or commited, but this behavior is not required. + */ + public abstract void lockObjectWithGlobalID(EOGlobalID aGlobalID, EOEditingContext aContext); + + /** + * Returns a List of objects associated with the object with the specified id + * for the specified property relationship. This method may not return an array + * fault because array faults call this method to fetch on demand. All objects + * must be registered the specified editing context. The specified relationship + * key must produce a result of type Collection for the source object or an + * exception is thrown. + */ + public abstract NSArray objectsForSourceGlobalID(EOGlobalID aGlobalID, String aRelationship, + EOEditingContext aContext); + + /** + * Returns a List of objects the meet the criteria of the supplied + * specification. Faults are not allowed in the array. Each object is registered + * with the specified editing context. If any object is already fetched in the + * specified context, it is not refetched and that object should be used in the + * array. + */ + public abstract NSArray objectsWithFetchSpecification(EOFetchSpecification aFetchSpec, EOEditingContext aContext); + + /** + * Removes all values from the specified object, converting it into a fault for + * the specified id. New or deleted objects should not be refaulted. + */ + public abstract void refaultObject(Object anObject, EOGlobalID aGlobalID, EOEditingContext aContext); + + /** + * Writes all changes in the specified editing context to the respository. The + * object store is expected to post a notification that should be named with the + * string constant ObjectsChangedInStoreNotification with this object store as + * the object and user info containing keys named UpdatedKey, InsertedKey, and + * DeletedKey that return Lists of the EOGlobalIDs of the corresponding objects. + */ + public abstract void saveChangesInEditingContext(EOEditingContext aContext); } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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/12/18 15:37:38 mpowers - * Changes to retain ability to work with objects that don't necessarily - * implement EOEnterpriseObject. I would still like to preserve this case - * for general usage, however the access package is free to assume that - * those objects will be EOs and cast appropriately. + * Revision 1.15 2003/12/18 15:37:38 mpowers Changes to retain ability to work + * with objects that don't necessarily implement EOEnterpriseObject. I would + * still like to preserve this case for general usage, however the access + * package is free to assume that those objects will be EOs and cast + * appropriately. * - * Revision 1.14 2003/08/19 01:53:12 chochos - * EOObjectStore had some incompatible return types (Object instead of EOEnterpriseObject, in fault methods mostly). It's internally consistent but I hope it doesn't break anything based on this, even though fault methods mostly throw exceptions for now. + * Revision 1.14 2003/08/19 01:53:12 chochos EOObjectStore had some incompatible + * return types (Object instead of EOEnterpriseObject, in fault methods mostly). + * It's internally consistent but I hope it doesn't break anything based on + * this, even though fault methods mostly throw exceptions for now. * - * Revision 1.13 2002/02/13 21:20:15 mpowers - * Updated comments. + * Revision 1.13 2002/02/13 21:20:15 mpowers Updated comments. * - * Revision 1.12 2001/05/05 23:05:42 mpowers - * Implemented Array Faults. + * Revision 1.12 2001/05/05 23:05:42 mpowers Implemented Array Faults. * - * Revision 1.11 2001/02/21 21:17:32 mpowers - * Now retaining a reference to the recent changes observer. - * Better documented need to retain reference. - * Started implementing notifications. + * Revision 1.11 2001/02/21 21:17:32 mpowers Now retaining a reference to the + * recent changes observer. Better documented need to retain reference. Started + * implementing notifications. * - * Revision 1.10 2001/02/16 22:51:29 mpowers - * Now deep-cloning objects passed between editing contexts. + * Revision 1.10 2001/02/16 22:51:29 mpowers Now deep-cloning objects passed + * between editing contexts. * - * Revision 1.9 2001/02/16 18:34:19 mpowers - * Implementing nested contexts. + * Revision 1.9 2001/02/16 18:34:19 mpowers Implementing nested contexts. * - * Revision 1.8 2001/02/15 21:13:30 mpowers - * First draft implementation is complete. Now on to debugging. + * Revision 1.8 2001/02/15 21:13:30 mpowers First draft implementation is + * complete. Now on to debugging. * - * Revision 1.7 2001/02/14 23:03:02 mpowers - * A near-complete first draft of EOEditingContext. + * Revision 1.7 2001/02/14 23:03:02 mpowers A near-complete first draft of + * EOEditingContext. * - * Revision 1.6 2001/02/13 23:24:29 mpowers - * Implementing more of editing context. + * Revision 1.6 2001/02/13 23:24:29 mpowers Implementing more of editing + * context. * - * Revision 1.5 2001/02/12 20:36:36 mpowers - * Documented methods. + * Revision 1.5 2001/02/12 20:36:36 mpowers Documented methods. * - * Revision 1.4 2001/02/09 22:09:34 mpowers - * Completed implementation of EOObjectStore. + * Revision 1.4 2001/02/09 22:09:34 mpowers Completed implementation of + * EOObjectStore. * - * Revision 1.3 2001/02/06 15:24:11 mpowers - * Widened parameters on abstract method to fix build. + * Revision 1.3 2001/02/06 15:24:11 mpowers Widened parameters on abstract + * method to fix build. * - * Revision 1.2 2001/02/06 14:57:42 mpowers - * Defined abstract methods. + * Revision 1.2 2001/02/06 14:57:42 mpowers Defined abstract methods. * - * Revision 1.1.1.1 2000/12/21 15:46:42 mpowers - * Contributing wotonomy. + * Revision 1.1.1.1 2000/12/21 15:46:42 mpowers Contributing wotonomy. * - * Revision 1.2 2000/12/20 16:25:35 michael - * Added log to all files. + * Revision 1.2 2000/12/20 16:25:35 michael Added log to all files. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObjectStoreCoordinator.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObjectStoreCoordinator.java index e9a3a6a..c2ad03d 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObjectStoreCoordinator.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObjectStoreCoordinator.java @@ -27,178 +27,172 @@ import java.util.Map; import net.wotonomy.foundation.NSArray; import net.wotonomy.foundation.NSDictionary; import net.wotonomy.foundation.NSNotification; + /** -* A representation of a channel of communication to the database. -* -* @author cgruber@israfil.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ + * A representation of a channel of communication to the database. + * + * @author cgruber@israfil.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ public class EOObjectStoreCoordinator extends EOObjectStore { - public static final String CooperatingObjectStoreWasAddedNotification = "EOCooperatingObjectStoreWasAddedNotification"; - public static final String CooperatingObjectStoreWasRemovedNotification = "EOCooperatingObjectStoreWasRemovedNotification"; - public static final String CooperatingObjectStoreNeededNotification = "EOCooperatingObjectStoreNeededNotification"; - public static final String GlobalIDKey = "globalID"; - public static final String FetchSpecificationKey = "fetchSpecification"; - public static final String ObjectKey = "object"; + public static final String CooperatingObjectStoreWasAddedNotification = "EOCooperatingObjectStoreWasAddedNotification"; + public static final String CooperatingObjectStoreWasRemovedNotification = "EOCooperatingObjectStoreWasRemovedNotification"; + public static final String CooperatingObjectStoreNeededNotification = "EOCooperatingObjectStoreNeededNotification"; + public static final String GlobalIDKey = "globalID"; + public static final String FetchSpecificationKey = "fetchSpecification"; + public static final String ObjectKey = "object"; - public static synchronized EOObjectStoreCoordinator defaultCoordinator() { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public static synchronized EOObjectStoreCoordinator defaultCoordinator() { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public static synchronized void setDefaultCoordinator(EOObjectStoreCoordinator eoobjectstorecoordinator) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public static synchronized void setDefaultCoordinator(EOObjectStoreCoordinator eoobjectstorecoordinator) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public EOObjectStoreCoordinator() { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public EOObjectStoreCoordinator() { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public void dispose() { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public void dispose() { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - private NSArray _sources() { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + private NSArray _sources() { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public NSArray cooperatingObjectStores() { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public NSArray cooperatingObjectStores() { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public void addCooperatingObjectStore(EOCooperatingObjectStore eocooperatingobjectstore) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public void addCooperatingObjectStore(EOCooperatingObjectStore eocooperatingobjectstore) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public void removeCooperatingObjectStore(EOCooperatingObjectStore eocooperatingobjectstore) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public void removeCooperatingObjectStore(EOCooperatingObjectStore eocooperatingobjectstore) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public EOCooperatingObjectStore objectStoreForGlobalID(EOGlobalID eoglobalid) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public EOCooperatingObjectStore objectStoreForGlobalID(EOGlobalID eoglobalid) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public EOCooperatingObjectStore objectStoreForObject(EOEnterpriseObject eoenterpriseobject) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public EOCooperatingObjectStore objectStoreForObject(EOEnterpriseObject eoenterpriseobject) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public EOCooperatingObjectStore objectStoreForFetchSpecification(EOFetchSpecification eofetchspecification) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public EOCooperatingObjectStore objectStoreForFetchSpecification(EOFetchSpecification eofetchspecification) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - EOCooperatingObjectStore objectStoreForEntityNamed(String s) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + EOCooperatingObjectStore objectStoreForEntityNamed(String s) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public void forwardUpdateForObject(EOEnterpriseObject eoenterpriseobject, NSDictionary nsdictionary) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public void forwardUpdateForObject(EOEnterpriseObject eoenterpriseobject, NSDictionary nsdictionary) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public NSDictionary valuesForKeys(NSArray nsarray, EOEnterpriseObject eoenterpriseobject) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public NSDictionary valuesForKeys(NSArray nsarray, EOEnterpriseObject eoenterpriseobject) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public void saveChangesInEditingContext(EOEditingContext eoeditingcontext) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public void saveChangesInEditingContext(EOEditingContext eoeditingcontext) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public NSArray objectsWithFetchSpecification(EOFetchSpecification eofetchspecification, EOEditingContext eoeditingcontext) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public NSArray objectsWithFetchSpecification(EOFetchSpecification eofetchspecification, + EOEditingContext eoeditingcontext) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public boolean isObjectLockedWithGlobalID(EOGlobalID eoglobalid, EOEditingContext eoeditingcontext) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public boolean isObjectLockedWithGlobalID(EOGlobalID eoglobalid, EOEditingContext eoeditingcontext) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public void lockObjectWithGlobalID(EOGlobalID eoglobalid, EOEditingContext eoeditingcontext) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public void lockObjectWithGlobalID(EOGlobalID eoglobalid, EOEditingContext eoeditingcontext) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public /*EOEnterpriseObject*/ Object faultForGlobalID(EOGlobalID eoglobalid, EOEditingContext eoeditingcontext) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public /* EOEnterpriseObject */ Object faultForGlobalID(EOGlobalID eoglobalid, EOEditingContext eoeditingcontext) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public /*EOEnterpriseObject*/ Object faultForRawRow(NSDictionary nsdictionary, String s, EOEditingContext eoeditingcontext) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public /* EOEnterpriseObject */ Object faultForRawRow(NSDictionary nsdictionary, String s, + EOEditingContext eoeditingcontext) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public NSArray arrayFaultWithSourceGlobalID(EOGlobalID eoglobalid, String s, EOEditingContext eoeditingcontext) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public NSArray arrayFaultWithSourceGlobalID(EOGlobalID eoglobalid, String s, EOEditingContext eoeditingcontext) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public void editingContextDidForgetObjectWithGlobalID(EOEditingContext eoeditingcontext, EOGlobalID eoglobalid) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public void editingContextDidForgetObjectWithGlobalID(EOEditingContext eoeditingcontext, EOGlobalID eoglobalid) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public NSArray objectsForSourceGlobalID(EOGlobalID eoglobalid, String s, EOEditingContext eoeditingcontext) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public NSArray objectsForSourceGlobalID(EOGlobalID eoglobalid, String s, EOEditingContext eoeditingcontext) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public void invalidateObjectsWithGlobalIDs(NSArray nsarray) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public void invalidateObjectsWithGlobalIDs(NSArray nsarray) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public void invalidateAllObjects() { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public void invalidateAllObjects() { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public void _objectsChangedInSubStore(NSNotification nsnotification) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public void _objectsChangedInSubStore(NSNotification nsnotification) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public void _invalidatedAllObjectsInSubStore(NSNotification nsnotification) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public void _invalidatedAllObjectsInSubStore(NSNotification nsnotification) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public void setUserInfo(NSDictionary nsdictionary) { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public void setUserInfo(NSDictionary nsdictionary) { + throw new UnsupportedOperationException("Not Yet Implemented"); + } - public NSDictionary userInfo() { - throw new UnsupportedOperationException("Not Yet Implemented"); - } + public NSDictionary userInfo() { + throw new UnsupportedOperationException("Not Yet Implemented"); + } /** - * @see net.wotonomy.control.EOObjectStore#faultForRawRow(Map, String, EOEditingContext) + * @see net.wotonomy.control.EOObjectStore#faultForRawRow(Map, String, + * EOEditingContext) */ - public /*EOEnterpriseObject*/ Object faultForRawRow( - Map aDictionary, - String anEntityName, - EOEditingContext aContext) { - throw new UnsupportedOperationException("Not Yet Implemented"); + public /* EOEnterpriseObject */ Object faultForRawRow(Map aDictionary, String anEntityName, + EOEditingContext aContext) { + throw new UnsupportedOperationException("Not Yet Implemented"); } - /** - * @see net.wotonomy.control.EOObjectStore#initializeObject(Object, EOGlobalID, EOEditingContext) + * @see net.wotonomy.control.EOObjectStore#initializeObject(Object, EOGlobalID, + * EOEditingContext) */ - public void initializeObject( - Object anObject, - EOGlobalID aGlobalID, - EOEditingContext aContext) { - throw new UnsupportedOperationException("Not Yet Implemented"); + public void initializeObject(Object anObject, EOGlobalID aGlobalID, EOEditingContext aContext) { + throw new UnsupportedOperationException("Not Yet Implemented"); } - /** * @see net.wotonomy.control.EOObjectStore#invalidateObjectsWithGlobalIDs(List) */ public void invalidateObjectsWithGlobalIDs(List aList) { - throw new UnsupportedOperationException("Not Yet Implemented"); + throw new UnsupportedOperationException("Not Yet Implemented"); } - /** - * @see net.wotonomy.control.EOObjectStore#refaultObject(Object, EOGlobalID, EOEditingContext) + * @see net.wotonomy.control.EOObjectStore#refaultObject(Object, EOGlobalID, + * EOEditingContext) */ - public void refaultObject( - Object anObject, - EOGlobalID aGlobalID, - EOEditingContext aContext) { - throw new UnsupportedOperationException("Not Yet Implemented"); + public void refaultObject(Object anObject, EOGlobalID aGlobalID, EOEditingContext aContext) { + throw new UnsupportedOperationException("Not Yet Implemented"); } - } diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObserverCenter.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObserverCenter.java index d42130c..a8710ef 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObserverCenter.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObserverCenter.java @@ -34,514 +34,423 @@ import net.wotonomy.foundation.NSArray; import net.wotonomy.foundation.NSMutableArray; /** -* EOObserverCenter is a static singleton-like class -* that manages EOObservings that want to be notified -* of changes to those objects that call -* notifyObserversObjectWillChange() before their -* properties change.

-* -* Implementation note: Because Java implements the -* Observer pattern in java.util.Observable, this -* class knows how to register itself as an Observer -* with Observables as well. However, users should -* note that Observables only notify their Observers -* of changes after their property has changed. -* EODelayedObservers would see no difference because -* they always receive their notification after all -* changes have taken place.

-* -* This implementation uses weak references for observers -* and observables. The advantage to this approach is -* that you do not need to explicitly unregister observers -* or observables; they will be unregistered when they are -* garbage-collected. Note that you will need to retain -* a reference to any objects you register or they may -* become unregistered if no other object references them. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public class EOObserverCenter implements Observer -{ - /** - * Would much rather use a WeakHashMap, but that class - * compares by value, and we need to compare by reference. - * This means we need to recreate a weak hashmap with - * the ReferenceKey class below. Using hashtable for - * thread safety. - */ + * EOObserverCenter is a static singleton-like class that manages EOObservings + * that want to be notified of changes to those objects that call + * notifyObserversObjectWillChange() before their properties change.
+ *
+ * + * Implementation note: Because Java implements the Observer pattern in + * java.util.Observable, this class knows how to register itself as an Observer + * with Observables as well. However, users should note that Observables only + * notify their Observers of changes after their property has changed. + * EODelayedObservers would see no difference because they always receive their + * notification after all changes have taken place.
+ *
+ * + * This implementation uses weak references for observers and observables. The + * advantage to this approach is that you do not need to explicitly unregister + * observers or observables; they will be unregistered when they are + * garbage-collected. Note that you will need to retain a reference to any + * objects you register or they may become unregistered if no other object + * references them. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public class EOObserverCenter implements Observer { + /** + * Would much rather use a WeakHashMap, but that class compares by value, and we + * need to compare by reference. This means we need to recreate a weak hashmap + * with the ReferenceKey class below. Using hashtable for thread safety. + */ private static Map observableToObservers = new Hashtable(); - + private static List omniscients = new LinkedList(); - + // suppression count private static int suppressions = 0; - + // singleton instance - needed for Observer private static EOObserverCenter instance = null; - - // optimization: remember last request and result - private static Object lastRequest; - private static NSArray lastResult; - + + // optimization: remember last request and result + private static Object lastRequest; + private static NSArray lastResult; + /** - * Registers the specified EOObserving for - * notifications from the specified object. - * An EOObserving can only be registered - * once for a given object. - */ - public static void addObserver( - EOObserving anObserver, Object anObject ) - { + * Registers the specified EOObserving for notifications from the specified + * object. An EOObserving can only be registered once for a given object. + */ + public static void addObserver(EOObserving anObserver, Object anObject) { // atomic operation - synchronized ( instance() ) - { + synchronized (instance()) { // find observer list - List observers = (List) - observableToObservers.get( new ReferenceKey( anObject ) ); - + List observers = (List) observableToObservers.get(new ReferenceKey(anObject)); + // if observer list not found, create and add item - if ( observers == null ) - { + if (observers == null) { observers = new ArrayList(); - observers.add( new WeakReference( anObserver ) ); - processQueue(); - observableToObservers.put( new ReferenceKey( anObject, queue ), observers ); + observers.add(new WeakReference(anObserver)); + processQueue(); + observableToObservers.put(new ReferenceKey(anObject, queue), observers); // support for java.util.Observable - if ( anObject instanceof Observable ) - { - ((Observable)anObject).addObserver( instance() ); + if (anObject instanceof Observable) { + ((Observable) anObject).addObserver(instance()); } - } - else // observer list found - scan for observer - if ( indexOf( observers, anObserver ) < 0 ) - { + } else // observer list found - scan for observer + if (indexOf(observers, anObserver) < 0) { // observer not found, register it - observers.add( new WeakReference( anObserver ) ); + observers.add(new WeakReference(anObserver)); } - - lastRequest = null; - lastResult = null; + + lastRequest = null; + lastResult = null; } } /** - * Registers the specified EOObserving for notifications - * on all object changes. An EOObserving can be - * registered as an omniscient observer at most once. - * Use omniscient observers with caution. - */ - public static void addOmniscientObserver( - EOObserving anObserver ) - { - if ( indexOf( omniscients, anObserver ) < 0 ) - { - omniscients.add( anObserver ); + * Registers the specified EOObserving for notifications on all object changes. + * An EOObserving can be registered as an omniscient observer at most once. Use + * omniscient observers with caution. + */ + public static void addOmniscientObserver(EOObserving anObserver) { + if (indexOf(omniscients, anObserver) < 0) { + omniscients.add(anObserver); } } /** - * Notifies all EOObservings registered for - * notifications for the specified object. - * This method is typically called by objects - * that wish to broadcast a notification before - * a property change takes place, passing itself - * as the argument. - */ - public static void notifyObserversObjectWillChange( - Object anObject ) - { - if ( observerNotificationSuppressCount() == 0 ) - { - List observers = observersForObject( anObject ); + * Notifies all EOObservings registered for notifications for the specified + * object. This method is typically called by objects that wish to broadcast a + * notification before a property change takes place, passing itself as the + * argument. + */ + public static void notifyObserversObjectWillChange(Object anObject) { + if (observerNotificationSuppressCount() == 0) { + List observers = observersForObject(anObject); EOObserving o; Iterator it = observers.iterator(); - while ( it.hasNext() ) - { + while (it.hasNext()) { o = (EOObserving) it.next(); - o.objectWillChange( anObject ); + o.objectWillChange(anObject); } } } /** - * Returns an observer that is an instance of - * the specified class and - * that is registered for notifications about - * the specified object. If more than one - * such observer exists, which observer is - * returned is undetermined - use - * observersForObject instead. If no observer - * exists, returns null. - */ - public static EOObserving observerForObject( - Object anObject, Class aClass ) - { - List result = observersForObject( anObject ); - if ( result.size() == 0 ) return null; - + * Returns an observer that is an instance of the specified class and that is + * registered for notifications about the specified object. If more than one + * such observer exists, which observer is returned is undetermined - use + * observersForObject instead. If no observer exists, returns null. + */ + public static EOObserving observerForObject(Object anObject, Class aClass) { + List result = observersForObject(anObject); + if (result.size() == 0) + return null; + Object o; Iterator it = result.iterator(); - while ( it.hasNext() ) - { + while (it.hasNext()) { o = it.next(); - if ( aClass.isAssignableFrom( o.getClass() ) ) - { - return (EOObserving) o; + if (aClass.isAssignableFrom(o.getClass())) { + return (EOObserving) o; } } return null; } /** - * Returns the number of times that notifications - * have been suppressed. This is also the number - * of times that enableObserverNotification must - * be called to allow notifications to take place. - */ - public static int observerNotificationSuppressCount() - { + * Returns the number of times that notifications have been suppressed. This is + * also the number of times that enableObserverNotification must be called to + * allow notifications to take place. + */ + public static int observerNotificationSuppressCount() { return suppressions; } /** - * Returns a List of observers for the - * specified object. Returns an empty List - * if no observer has registered for that - * object. - */ - public static NSArray observersForObject( - Object anObject ) - { - synchronized ( instance() ) - { - // optimization: this is called very frequently - // from the same object calling willChange() a - // number of times in a row as it is updating. - if ( lastRequest == anObject ) - { - return lastResult; - } - - NSArray result; - - List references = observerListForObject( anObject ); - if ( references == null ) - { - result = NSArray.EmptyArray; - } - else - { - result = new NSMutableArray(); - Object observer; - Iterator it = references.iterator(); - while ( it.hasNext() ) - { - observer = ((Reference)it.next()).get(); - if ( observer != null ) - { - result.add( observer ); - } - else // reference has expired - { - processQueue(); - it.remove(); // remove from list - // if last observer, unregister observable - if ( references.size() == 0 ) - { - observableToObservers.remove( new ReferenceKey( anObject ) ); - } - } - } - } - - lastRequest = anObject; - lastResult = result; - - return result; - } - + * Returns a List of observers for the specified object. Returns an empty List + * if no observer has registered for that object. + */ + public static NSArray observersForObject(Object anObject) { + synchronized (instance()) { + // optimization: this is called very frequently + // from the same object calling willChange() a + // number of times in a row as it is updating. + if (lastRequest == anObject) { + return lastResult; + } + + NSArray result; + + List references = observerListForObject(anObject); + if (references == null) { + result = NSArray.EmptyArray; + } else { + result = new NSMutableArray(); + Object observer; + Iterator it = references.iterator(); + while (it.hasNext()) { + observer = ((Reference) it.next()).get(); + if (observer != null) { + result.add(observer); + } else // reference has expired + { + processQueue(); + it.remove(); // remove from list + // if last observer, unregister observable + if (references.size() == 0) { + observableToObservers.remove(new ReferenceKey(anObject)); + } + } + } + } + + lastRequest = anObject; + lastResult = result; + + return result; + } + } - + /** - * Returns a reference to the actual list of - * observers for the given object, or null if it - * doesn't exist. - */ - private static List observerListForObject( Object anObject ) - { - return (List) observableToObservers.get( new ReferenceKey( anObject ) ); + * Returns a reference to the actual list of observers for the given object, or + * null if it doesn't exist. + */ + private static List observerListForObject(Object anObject) { + return (List) observableToObservers.get(new ReferenceKey(anObject)); } /** - * Unregisters the specified observer for - * notifications from the specified object. - */ - public static void removeObserver( - EOObserving anObserver, Object anObject ) - { + * Unregisters the specified observer for notifications from the specified + * object. + */ + public static void removeObserver(EOObserving anObserver, Object anObject) { // atomic operation - synchronized ( instance() ) - { - lastRequest = null; - lastResult = null; - - List result = observerListForObject( anObject ); - if ( result == null ) return; - int index = indexOf( result, anObserver ); - if ( index == -1 ) return; - + synchronized (instance()) { + lastRequest = null; + lastResult = null; + + List result = observerListForObject(anObject); + if (result == null) + return; + int index = indexOf(result, anObserver); + if (index == -1) + return; + // remove observer from list - result.remove( index ); - + result.remove(index); + // if last observer, unregister observable - if ( result.size() == 0 ) - { - processQueue(); - observableToObservers.remove( new ReferenceKey( anObject ) ); + if (result.size() == 0) { + processQueue(); + observableToObservers.remove(new ReferenceKey(anObject)); } } } /** - * Unregisters the specified omniscient observer. - */ - public static void removeOmniscientObserver( - EOObserving anObserver ) - { - int index = indexOf( omniscients, anObserver ); - if ( index != -1 ) - { - omniscients.remove( index ); + * Unregisters the specified omniscient observer. + */ + public static void removeOmniscientObserver(EOObserving anObserver) { + int index = indexOf(omniscients, anObserver); + if (index != -1) { + omniscients.remove(index); } } /** - * Enables notifications after they have been - * suppressed by suppressObserverNotification. - * If notifications have been suppressed - * multiple times, this method must be called - * an equal number of times to resume notifications. - * If notifications are not currently suppressed, - * this method does nothing. - */ - public static void enableObserverNotification() - { - if ( suppressions > 0 ) suppressions--; + * Enables notifications after they have been suppressed by + * suppressObserverNotification. If notifications have been suppressed multiple + * times, this method must be called an equal number of times to resume + * notifications. If notifications are not currently suppressed, this method + * does nothing. + */ + public static void enableObserverNotification() { + if (suppressions > 0) + suppressions--; } /** - * Causes notifications to be suppressed until - * the next matching call to enableObserverNotification. - * If this method is called more than once, - * enableObserverNotification must be called an - * equal number of times for notifications to resume. - * This method always causes notifications to cease - * immediately. - */ - public static void suppressObserverNotification() - { + * Causes notifications to be suppressed until the next matching call to + * enableObserverNotification. If this method is called more than once, + * enableObserverNotification must be called an equal number of times for + * notifications to resume. This method always causes notifications to cease + * immediately. + */ + public static void suppressObserverNotification() { suppressions++; } - + /** - * Because we're comparing by reference, we need to - * test for the existence of the object directly. - * @return the index or -1 if not found. - */ - private static int indexOf( List aList, Object anObject ) - { - if ( anObject == null ) return -1; - - synchronized ( aList ) - { + * Because we're comparing by reference, we need to test for the existence of + * the object directly. + * + * @return the index or -1 if not found. + */ + private static int indexOf(List aList, Object anObject) { + if (anObject == null) + return -1; + + synchronized (aList) { int len = aList.size(); - for ( int i = 0; i < len; i++ ) - { + for (int i = 0; i < len; i++) { // compare by reference - if ( anObject == ((Reference)aList.get(i)).get() ) - { + if (anObject == ((Reference) aList.get(i)).get()) { return i; } } } return -1; } - + /** - * Private singleton instance, so we can be an observer. - */ - private static EOObserverCenter instance() - { - if ( instance == null ) - { + * Private singleton instance, so we can be an observer. + */ + private static EOObserverCenter instance() { + if (instance == null) { instance = new EOObserverCenter(); } return instance; } - + + /** + * Interface Observer + */ + public void update(Observable o, Object arg) { + notifyObserversObjectWillChange(o); + } + + /* Reference queue for cleared WeakKeys */ + private static ReferenceQueue queue = new ReferenceQueue(); + + /* + * Remove all invalidated entries from the map, that is, remove all entries + * whose keys have been discarded. This method should be invoked once by each + * public mutator in this class. We don't invoke this method in public accessors + * because that can lead to surprising ConcurrentModificationExceptions. + */ + private static void processQueue() { + synchronized (instance()) { + ReferenceKey rk; + while ((rk = (ReferenceKey) queue.poll()) != null) { + // System.out.println( "EOObserverCenter.processQueue: removing object" ); + observableToObservers.remove(rk); + } + } + } + /** - * Interface Observer - */ - public void update( Observable o, Object arg ) - { - notifyObserversObjectWillChange( o ); + * Private class used to force a hashmap to perform key comparisons by + * reference. Retains a weak reference just like WeakHashMap. + */ + static private class ReferenceKey extends WeakReference { + private int hashCode; + + /** + * Called to create a disposable reference key, used for retrieving values from + * the hashtable. + */ + public ReferenceKey(Object anObject) { + super(anObject); + hashCode = anObject.hashCode(); + } + + /** + * Called to create a reference key that will be used as a key in the hashtable, + * so we need the reference queue to later remove the key from the table when + * referred object is no longer in use. + */ + public ReferenceKey(Object anObject, ReferenceQueue aQueue) { + super(anObject, aQueue); + hashCode = anObject.hashCode(); + } + + /** + * Passes through to actual key's hash code. + */ + public int hashCode() { + return hashCode; + } + + /** + * Compares by reference. + */ + public boolean equals(Object anObject) { + if (!(anObject instanceof ReferenceKey)) + return false; + Object key = get(); + if (key == null) + return false; + return (key == ((ReferenceKey) anObject).get()); + } } - - /* Reference queue for cleared WeakKeys */ - private static ReferenceQueue queue = new ReferenceQueue(); - - /* Remove all invalidated entries from the map, that is, remove all entries - whose keys have been discarded. This method should be invoked once by - each public mutator in this class. We don't invoke this method in - public accessors because that can lead to surprising - ConcurrentModificationExceptions. */ - private static void processQueue() - { - synchronized ( instance() ) - { - ReferenceKey rk; - while ((rk = (ReferenceKey)queue.poll()) != null) - { - //System.out.println( "EOObserverCenter.processQueue: removing object" ); - observableToObservers.remove(rk); - } - } - } - - /** - * Private class used to force a hashmap to - * perform key comparisons by reference. - * Retains a weak reference just like WeakHashMap. - */ - static private class ReferenceKey extends WeakReference - { - private int hashCode; - - /** - * Called to create a disposable reference key, - * used for retrieving values from the hashtable. - */ - public ReferenceKey( Object anObject ) - { - super( anObject ); - hashCode = anObject.hashCode(); - } - - /** - * Called to create a reference key that will be - * used as a key in the hashtable, so we need the - * reference queue to later remove the key from the - * table when referred object is no longer in use. - */ - public ReferenceKey( Object anObject, ReferenceQueue aQueue ) - { - super( anObject, aQueue ); - hashCode = anObject.hashCode(); - } - - /** - * Passes through to actual key's hash code. - */ - public int hashCode() - { - return hashCode; - } - - /** - * Compares by reference. - */ - public boolean equals( Object anObject ) - { - if ( ! ( anObject instanceof ReferenceKey ) ) return false; - Object key = get(); - if ( key == null ) return false; - return ( key == ((ReferenceKey)anObject).get() ); - } - } - - private static String debugString() - { - String result = ""; - int count = 0; - synchronized ( instance() ) - { - Object anObject; - Iterator it = observableToObservers.keySet().iterator(); - while ( it.hasNext() ) - { - result += ((Reference)it.next()).get() + " : "; - count++; - /* - Iterator values = ((List)it.next()).iterator(); - while ( values.hasNext() ) - { - anObject = ((Reference)values.next()).get(); - if ( anObject != null ) - { -// if ( anObject instanceof net.wotonomy.ui.MasterDetailAssociation ) - result += anObject.getClass().toString() + " : "; - count++; - } - } - */ - } - result += "["+count+"]"; + + private static String debugString() { + String result = ""; + int count = 0; + synchronized (instance()) { + Object anObject; + Iterator it = observableToObservers.keySet().iterator(); + while (it.hasNext()) { + result += ((Reference) it.next()).get() + " : "; + count++; + /* + * Iterator values = ((List)it.next()).iterator(); while ( values.hasNext() ) { + * anObject = ((Reference)values.next()).get(); if ( anObject != null ) { // if + * ( anObject instanceof net.wotonomy.ui.MasterDetailAssociation ) result += + * anObject.getClass().toString() + " : "; count++; } } + */ + } + result += "[" + count + "]"; } - return result; - } - + return result; + } + } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.9 2002/10/24 18:18:12 mpowers - * NSArray's are now considered read-only, so we can return our internal - * representation to reduce unnecessary object allocation. + * Revision 1.9 2002/10/24 18:18:12 mpowers NSArray's are now considered + * read-only, so we can return our internal representation to reduce unnecessary + * object allocation. * - * Revision 1.8 2001/02/21 21:17:32 mpowers - * Now retaining a reference to the recent changes observer. - * Better documented need to retain reference. - * Started implementing notifications. + * Revision 1.8 2001/02/21 21:17:32 mpowers Now retaining a reference to the + * recent changes observer. Better documented need to retain reference. Started + * implementing notifications. * - * Revision 1.7 2001/02/17 16:52:05 mpowers - * Changes in imports to support building with jdk1.1 collections. + * Revision 1.7 2001/02/17 16:52:05 mpowers Changes in imports to support + * building with jdk1.1 collections. * - * Revision 1.6 2001/02/05 18:45:45 mpowers - * Reduced access back to private for utility methods. + * Revision 1.6 2001/02/05 18:45:45 mpowers Reduced access back to private for + * utility methods. * - * Revision 1.5 2001/02/05 18:42:32 mpowers - * Updated documentation throughout project. + * Revision 1.5 2001/02/05 18:42:32 mpowers Updated documentation throughout + * project. * - * Revision 1.4 2001/01/18 16:57:47 mpowers - * Added debug facility. + * Revision 1.4 2001/01/18 16:57:47 mpowers Added debug facility. * - * Revision 1.3 2001/01/10 16:28:53 mpowers - * Implemented a compare-by-reference weak hashtable - * because WeakHashMap compared by value and we can't - * assume that display groups won't contain objects - * whose values are equivalent. + * Revision 1.3 2001/01/10 16:28:53 mpowers Implemented a compare-by-reference + * weak hashtable because WeakHashMap compared by value and we can't assume that + * display groups won't contain objects whose values are equivalent. * - * Revision 1.2 2001/01/09 20:10:19 mpowers - * Now using weak references to track observables and their observers. + * Revision 1.2 2001/01/09 20:10:19 mpowers Now using weak references to track + * observables and their observers. * - * Revision 1.1.1.1 2000/12/21 15:46:44 mpowers - * Contributing wotonomy. + * Revision 1.1.1.1 2000/12/21 15:46:44 mpowers Contributing wotonomy. * - * Revision 1.8 2000/12/20 16:25:35 michael - * Added log to all files. + * Revision 1.8 2000/12/20 16:25:35 michael Added log to all files. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObserverProxy.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObserverProxy.java index e616a33..ce8c9a7 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObserverProxy.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObserverProxy.java @@ -21,84 +21,67 @@ package net.wotonomy.control; import net.wotonomy.foundation.NSSelector; /** -* A convenience observer for objects that do not or cannot -* subclass EODelayedObserver. EOObserverProxy will invoke -* an NSSelector on an object when it receives a subjectChanged -* message. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 893 $ -*/ -public class EOObserverProxy - extends EODelayedObserver -{ - protected Object target; - protected NSSelector selector; - protected int priority; - - /** - * Constructs an EODelayedObserver that will invoke the specified selector - * on the specified object, and will run at the specified priority. - */ - public EOObserverProxy ( - Object anObject, NSSelector aSelector, int aPriority ) - { - target = anObject; - selector = aSelector; - priority = aPriority; - } + * A convenience observer for objects that do not or cannot subclass + * EODelayedObserver. EOObserverProxy will invoke an NSSelector on an object + * when it receives a subjectChanged message. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 893 $ + */ +public class EOObserverProxy extends EODelayedObserver { + protected Object target; + protected NSSelector selector; + protected int priority; - /** - * Constructs an EODelayedObserver that will invoke the specified selector - * on the specified object, and will run at ObserverPriorityThird priority, - * which is the default. - */ - public EOObserverProxy ( - Object anObject, NSSelector aSelector ) - { - this( anObject, aSelector, ObserverPriorityThird ); - } + /** + * Constructs an EODelayedObserver that will invoke the specified selector on + * the specified object, and will run at the specified priority. + */ + public EOObserverProxy(Object anObject, NSSelector aSelector, int aPriority) { + target = anObject; + selector = aSelector; + priority = aPriority; + } - /** - * Returns the priority of this observer in the queue. - * This implementation returns the priority specified - * in the constructor. - */ - public int priority () - { - return priority; - } + /** + * Constructs an EODelayedObserver that will invoke the specified selector on + * the specified object, and will run at ObserverPriorityThird priority, which + * is the default. + */ + public EOObserverProxy(Object anObject, NSSelector aSelector) { + this(anObject, aSelector, ObserverPriorityThird); + } + + /** + * Returns the priority of this observer in the queue. This implementation + * returns the priority specified in the constructor. + */ + public int priority() { + return priority; + } + + /** + * Notifies observer that one or more objects that it is observing have changed. + * The observer should check all objects it is observing for changes. + */ + public void subjectChanged() { + try { + selector.invoke(target); + } catch (Exception exc) { + System.out.println("Error notifying observer: "); + exc.printStackTrace(); + } + } - /** - * Notifies observer that one or more objects that - * it is observing have changed. The observer should - * check all objects it is observing for changes. - */ - public void subjectChanged () - { - try - { - selector.invoke( target ); - } - catch ( Exception exc ) - { - System.out.println( "Error notifying observer: " ); - exc.printStackTrace(); - } - } - } /* - * $Log$ - * Revision 1.1 2006/02/16 13:19:57 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. + * $Log$ Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.1 2001/10/22 21:55:32 mpowers - * This turns out to be a really useful class. + * Revision 1.1 2001/10/22 21:55:32 mpowers This turns out to be a really useful + * class. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObserving.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObserving.java index 8ec6e5c..d6a3101 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObserving.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOObserving.java @@ -19,33 +19,27 @@ License along with this library; if not, see http://www.gnu.org package net.wotonomy.control; /** -* A pure java implementation of EOObserving. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 893 $ -*/ -public interface EOObserving -{ - /** - * Called when the specified object is about to change. - */ - void objectWillChange ( Object anObject ); + * A pure java implementation of EOObserving. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 893 $ + */ +public interface EOObserving { + /** + * Called when the specified object is about to change. + */ + void objectWillChange(Object anObject); } /* - * $Log$ - * Revision 1.1 2006/02/16 13:19:57 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. + * $Log$ Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.1.1.1 2000/12/21 15:46:44 mpowers - * Contributing wotonomy. + * Revision 1.1.1.1 2000/12/21 15:46:44 mpowers Contributing wotonomy. * - * Revision 1.2 2000/12/20 16:25:35 michael - * Added log to all files. + * Revision 1.2 2000/12/20 16:25:35 michael Added log to all files. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOOrQualifier.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOOrQualifier.java index 7f4b1c6..fe31abe 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOOrQualifier.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOOrQualifier.java @@ -28,90 +28,76 @@ import net.wotonomy.foundation.NSMutableArray; import net.wotonomy.foundation.internal.WotonomyException; /** -* EOOrQualifier contains other EOQualifiers, -* evaluating as true if any of the contained -* qualifiers evaluate as true. -* -* @author michael@mpowers.net -* @author yjcheung@intersectsoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public class EOOrQualifier extends EOQualifier - implements EOKeyValueArchiving, EOQualifierEvaluation -{ - private List qualifiers; - - public EOOrQualifier( - List aQualifierList ) - { - qualifiers = new LinkedList( aQualifierList ); - } - - /** - * Returns a List of qualifiers contained by this qualifier. - */ - public NSArray qualifiers() - { - return new NSArray( qualifiers ); - } - - /** - * Add a new qualifier to the list. - */ - public void addQualifier(EOQualifier qualifier) - { - qualifiers.add(qualifier); - } - - /** - * Evaluates this qualifier for the specified object, - * and returns whether the object is qualified. - * selector() is invoked on the value for key() on the - * specified object, with value() as the parameter. - * - * Note: this has a lazy "or" implementation. Ex. Qal1 or Qal2. - * If Qal1 is evaluated to be true, then it returns true without - * further evaluate Qal2. - */ - public boolean evaluateWithObject( Object anObject ) - { - Iterator it = qualifiers.iterator(); - while( it.hasNext() ) - { - if ( ((EOQualifier) it.next()).evaluateWithObject(anObject) ) - { - return true; - } - } - return false; - } - - /** - * Returns a string representation of this qualifier. - */ - public String toString() - { - StringBuffer myBuf = new StringBuffer("("); - Iterator it = qualifiers.iterator(); - while (it.hasNext()) - { - myBuf = myBuf.append(((EOQualifier) it.next()).toString()).append(" or "); - } - String myStr = myBuf.toString(); - myStr = myStr.substring(0, myStr.lastIndexOf(" or ")).concat(")"); - return myStr; - } + * EOOrQualifier contains other EOQualifiers, evaluating as true if any of the + * contained qualifiers evaluate as true. + * + * @author michael@mpowers.net + * @author yjcheung@intersectsoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public class EOOrQualifier extends EOQualifier implements EOKeyValueArchiving, EOQualifierEvaluation { + private List qualifiers; + + public EOOrQualifier(List aQualifierList) { + qualifiers = new LinkedList(aQualifierList); + } + + /** + * Returns a List of qualifiers contained by this qualifier. + */ + public NSArray qualifiers() { + return new NSArray(qualifiers); + } + + /** + * Add a new qualifier to the list. + */ + public void addQualifier(EOQualifier qualifier) { + qualifiers.add(qualifier); + } + + /** + * Evaluates this qualifier for the specified object, and returns whether the + * object is qualified. selector() is invoked on the value for key() on the + * specified object, with value() as the parameter. + * + * Note: this has a lazy "or" implementation. Ex. Qal1 or Qal2. If Qal1 is + * evaluated to be true, then it returns true without further evaluate Qal2. + */ + public boolean evaluateWithObject(Object anObject) { + Iterator it = qualifiers.iterator(); + while (it.hasNext()) { + if (((EOQualifier) it.next()).evaluateWithObject(anObject)) { + return true; + } + } + return false; + } + + /** + * Returns a string representation of this qualifier. + */ + public String toString() { + StringBuffer myBuf = new StringBuffer("("); + Iterator it = qualifiers.iterator(); + while (it.hasNext()) { + myBuf = myBuf.append(((EOQualifier) it.next()).toString()).append(" or "); + } + String myStr = myBuf.toString(); + myStr = myStr.substring(0, myStr.lastIndexOf(" or ")).concat(")"); + return myStr; + } public static Object decodeWithKeyValueUnarchiver(EOKeyValueUnarchiver arch) { - NSArray a = (NSArray)arch.decodeObjectForKey("qualifiers"); + NSArray a = (NSArray) arch.decodeObjectForKey("qualifiers"); if (a == null) return null; NSMutableArray l = new NSMutableArray(); for (int i = 0; i < a.count(); i++) { - NSDictionary d = (NSDictionary)a.objectAtIndex(i); + NSDictionary d = (NSDictionary) a.objectAtIndex(i); EOKeyValueUnarchiver ua = new EOKeyValueUnarchiver(d); - EOQualifier q = (EOQualifier)EOQualifier.decodeWithKeyValueUnarchiver(ua); + EOQualifier q = (EOQualifier) EOQualifier.decodeWithKeyValueUnarchiver(ua); if (q != null) l.addObject(q); } @@ -121,11 +107,11 @@ public class EOOrQualifier extends EOQualifier public void encodeWithKeyValueArchiver(EOKeyValueArchiver arch) { arch.encodeObject("EOOrQualifier", "class"); NSMutableArray arr = new NSMutableArray(qualifiers.size()); - for (int i = 0; i < qualifiers.size(); i++) { - EOQualifier q = (EOQualifier)qualifiers.get(i); + for (int i = 0; i < qualifiers.size(); i++) { + EOQualifier q = (EOQualifier) qualifiers.get(i); if (q instanceof EOKeyValueArchiving) { EOKeyValueArchiver ar2 = new EOKeyValueArchiver(); - ((EOKeyValueArchiving)q).encodeWithKeyValueArchiver(ar2); + ((EOKeyValueArchiving) q).encodeWithKeyValueArchiver(ar2); arr.addObject(ar2.dictionary()); } else throw new WotonomyException("Cannot archive instance of " + q.getClass().getName()); @@ -136,34 +122,31 @@ public class EOOrQualifier extends EOQualifier } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.6 2003/08/12 01:43:04 chochos - * formally implement EOQualifierEvaluation + * Revision 1.6 2003/08/12 01:43:04 chochos formally implement + * EOQualifierEvaluation * - * Revision 1.5 2003/08/09 01:22:51 chochos - * qualifiers implement EOKeyValueArchiving + * Revision 1.5 2003/08/09 01:22:51 chochos qualifiers implement + * EOKeyValueArchiving * - * Revision 1.4 2003/08/06 23:07:52 chochos - * general code cleanup (mostly, removing unused imports) + * Revision 1.4 2003/08/06 23:07:52 chochos general code cleanup (mostly, + * removing unused imports) * - * Revision 1.3 2001/10/31 15:25:14 mpowers - * Cleanup of qualifiers. + * Revision 1.3 2001/10/31 15:25:14 mpowers Cleanup of qualifiers. * - * Revision 1.2 2001/10/30 22:57:28 mpowers - * EOQualifier framework is now working. + * Revision 1.2 2001/10/30 22:57:28 mpowers EOQualifier framework is now + * working. * - * Revision 1.1 2001/09/13 15:25:56 mpowers - * Started implementation of the EOQualifier framework. + * Revision 1.1 2001/09/13 15:25:56 mpowers Started implementation of the + * EOQualifier framework. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOQualifier.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOQualifier.java index 6fffea4..32443fa 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOQualifier.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOQualifier.java @@ -38,643 +38,504 @@ import net.wotonomy.foundation.internal.ValueConverter; import net.wotonomy.foundation.internal.WotonomyException; /** -* EOQualifiers are used to perform property-based -* qualifications on objects: for a set of criteria, -* a qualifier either qualifies or disqualifies an -* given object. EOKeyValueQualifiers can be joined -* by EOAndQualifier and EOOrQualifier, and so can -* form a tree of qualifications.

-* -* Certain qualifiers -* can accept a variable in place of a value; variable -* names are marked by a "$", as in "$name". Variables -* are resolved with the qualifierWithBindings() method. -* -* @author michael@mpowers.net -* @author yjcheung@intersectsoft.com -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public abstract class EOQualifier -{ - public static final NSSelector - QualifierOperatorCaseInsensitiveLike = new OperatorCaseInsensitiveLike(); - public static final NSSelector - QualifierOperatorContains = new OperatorContains(); - public static final NSSelector - QualifierOperatorEqual = new OperatorEqual(); - public static final NSSelector - QualifierOperatorGreaterThan = new OperatorGreaterThan(); - public static final NSSelector - QualifierOperatorGreaterThanOrEqualTo = new OperatorGreaterThanOrEqualTo(); - public static final NSSelector - QualifierOperatorLessThan = new OperatorLessThan(); - public static final NSSelector - QualifierOperatorLessThanOrEqualTo = new OperatorLessThanOrEqualTo(); - public static final NSSelector - QualifierOperatorLike = new OperatorLike(); - public static final NSSelector - QualifierOperatorNotEqual = new OperatorNotEqual(); - - /** - * Default constructor. - */ - public EOQualifier () - { - } - - /** - * Adds all qualifier keys in this qualifier to - * the specified Set, which is expected to be - * mutable. The tree of qualifiers is traversed - * and the left-hand-side of each expression is - * added to the set. - */ - public void addQualifierKeysToSet ( Set aSet ) - { - throw new RuntimeException( "Not implemented yet." ); - } - - /** - * Returns a Set of all property names used for - * comparisons by this qualifier. The tree of - * qualifiers is traversed and the left-hand-side - * of each expression is added to the set. - */ - public NSSet allQualifierKeys () - { - throw new RuntimeException( "Not implemented yet." ); - } - - /** - * Returns a List containing the variables used - * at compare-time by this qualifier. Each variable - * will appear only once in the list. - */ - public NSArray bindingKeys () - { - throw new RuntimeException( "Not implemented yet." ); - } - - /** - * Returns whether the specified object meets the - * criteria defined by this qualifier. - */ - public boolean evaluateWithObject ( Object anObject ) - { - return true; - } - - /** - * Returns the key (which can be a key path) that - * is tested against the specified binding variable. - * The tree is traversed looking for the first instance - * of the specified variable, and the corresponding - * left-hand-side of the expression is returned. - */ - public String keyPathForBindingKey ( String aVariable ) - { - throw new RuntimeException( "Not implemented yet." ); - } - - /** - * Returns a qualifier that is like this qualifier, - * except all variables will be replaced with values - * from the specified Map whose keys match the variable - * names. If requireAll is true, an exception will be - * thrown if there is no key that matches on of the - * variables in the tree; otherwise, the qualifier - * containing the unmatched variable is removed. - */ - public EOQualifier qualifierWithBindings ( - Map aMap, - boolean requireAll ) - { - throw new WotonomyException( "Not implemented yet." ); - } - - - /** - * Tests whether all the keys in this qualifier can - * be applied to an object of the specified class. - * @return A Throwable if the validation fails, - * otherwise returns null if the class can be used - * with this qualifier. - */ - public Throwable validateKeysWithRootClassDescription ( - Class aClass ) - { - throw new WotonomyException( "Not implemented yet." ); - } - - // statics - - /** - * Convenience to retain only those objects from the specified - * List that meet the specified qualifier's requirements. - */ - public static void filterArrayWithQualifier ( - List anObjectList, EOQualifier aQualifier ) - { - ListIterator iterator = anObjectList.listIterator(); - while ( iterator.hasNext() ) - { - if ( ! aQualifier.evaluateWithObject( iterator.next() ) ) - { - iterator.remove(); - } - } - } - - /** - * Convenience to return a List consisting only - * of those objects in the specified List that meet - * the specified qualifier's requirements. - */ - public static NSArray filteredArrayWithQualifier ( - List anObjectList, EOQualifier aQualifier ) - { - Object o; - List result = new LinkedList(); - Iterator iterator = anObjectList.iterator(); - while ( iterator.hasNext() ) - { - o = iterator.next(); - if ( aQualifier.evaluateWithObject( o ) ) - { - result.add( o ); - } - } - return new NSArray( (Collection) result ); - } - - /** - * Convenience to create a set of EOKeyValueQualifiers - * joined by an EOAndQualifier. Each pair of keys and - * values are used to create EOKeyValueQualifiers. - */ - public static EOQualifier - qualifierToMatchAllValues ( Map aMap ) - { - Object key, value; - List qualifierList = new LinkedList(); - Iterator iterator = aMap.keySet().iterator(); - while ( iterator.hasNext() ) - { - key = iterator.next(); - value = aMap.get( key ); - qualifierList.add( new EOKeyValueQualifier( - key.toString(), QualifierOperatorEqual, value ) ); - } - return new EOAndQualifier( qualifierList ); - } - - /** - * Convenience to create a set of EOKeyValueQualifiers - * joined by an EOOrQualifier. Each pair of keys and - * values are used to create EOKeyValueQualifiers. - */ - public static EOQualifier - qualifierToMatchAnyValue ( Map aMap ) - { - Object key, value; - List qualifierList = new LinkedList(); - Iterator iterator = aMap.keySet().iterator(); - while ( iterator.hasNext() ) - { - key = iterator.next(); - value = aMap.get( key ); - qualifierList.add( new EOKeyValueQualifier( - key.toString(), QualifierOperatorEqual, value ) ); - } - return new EOOrQualifier( qualifierList ); - } - - /** - * Returns an EOQualifier that meets the criteria - * represented by the specified string and variable - * length argument list. This method parses the string - * and returns a tree of qualifiers. Each token beginning - * with "%" is replaced with the corresponding object - * from the argument list. The parser recognizes the - * operation tokens returned from the allQualifierOperators() - * method. - */ - public static EOQualifier qualifierWithQualifierFormat ( - String aString, List anArgumentList ) - { - throw new RuntimeException( "Not implemented yet." ); - } - - /** - * Returns a List of operators that are supported for - * relational operations. This excludes string comparison - * operators. - */ - public static NSArray relationalQualifierOperators () - { - NSMutableArray result = new NSMutableArray(); - BaseSelector selector; - Iterator iterator = allQualifierOperators().iterator(); - while ( iterator.hasNext() ) - { - selector = (BaseSelector) iterator.next(); - if ( selector.isRelationalOperator() ) - { - result.addObject( selector ); - } - } - return result; - } - - /** - * Returns a List of valid operators. - */ - public static NSArray allQualifierOperators () - { - return operators.allKeys(); - } - - /** - * Returns a selector the corresponds to the operation - * represented by the specified string. For example, - * ">" represents QualifierOperatorGreaterThan. - */ - public static NSSelector operatorSelectorForString ( - String anOperatorString ) - { - return (NSSelector) - operators.objectForKey( anOperatorString ); - } - - /** - * Returns a string the corresponds to the operation - * represented by the specified selector. For example, - * QualifierOperatorGreaterThan is represented with ">". - */ - public static String stringForOperatorSelector ( - NSSelector aSelector ) - { - return (String) - operators.allKeysForObject( aSelector ).lastObject(); - } - - /** - * Returns a string representation of this qualifier. - */ - public String toString() - { - //TODO: implement this - return super.toString(); - } - - // built-in qualifiers - - private static NSMutableDictionary operators; - static - { - operators = new NSMutableDictionary(); - operators.setObjectForKey( - QualifierOperatorCaseInsensitiveLike, - QualifierOperatorCaseInsensitiveLike.toString() ); - operators.setObjectForKey( - QualifierOperatorContains, - QualifierOperatorContains.toString() ); - operators.setObjectForKey( - QualifierOperatorEqual, - QualifierOperatorEqual.toString() ); - operators.setObjectForKey( - QualifierOperatorGreaterThan, - QualifierOperatorGreaterThan.toString() ); - operators.setObjectForKey( - QualifierOperatorGreaterThanOrEqualTo, - QualifierOperatorGreaterThanOrEqualTo.toString() ); - operators.setObjectForKey( - QualifierOperatorLessThan, - QualifierOperatorLessThan.toString() ); - operators.setObjectForKey( - QualifierOperatorLessThanOrEqualTo, - QualifierOperatorLessThanOrEqualTo.toString() ); - operators.setObjectForKey( - QualifierOperatorLike, - QualifierOperatorLike.toString() ); - operators.setObjectForKey( - QualifierOperatorNotEqual, - QualifierOperatorNotEqual.toString() ); - } - - static private abstract class BaseSelector extends NSSelector - { - public String name () - { - return "BaseSelector"; - } - - public Class[] parameterTypes () - { - return new Class[] { Object.class, Object.class }; - } - - public Method methodOnClass (Class aClass) - throws NoSuchMethodException - { - throw new NoSuchMethodException(); - } - - public Method methodOnObject (Object anObject) - throws NoSuchMethodException - { - throw new NoSuchMethodException(); - } - - public boolean implementedByClass (Class aClass) - { - return true; - } - - public boolean implementedByObject (Object anObject) - { - return true; - } - - public boolean isRelationalOperator() - { - return true; - } - - public Object invoke (Object anObject, Object[] parameters) - throws IllegalAccessException, IllegalArgumentException, - InvocationTargetException, NoSuchMethodException - { - return qualify( anObject, parameters[0] ); - } - - abstract protected Boolean qualify( Object target, Object parameter ); - - protected int doCompare(Object o1, Object o2) - { - Class firstClass = o1.getClass(); - Class secondClass = o2.getClass(); - - if ( ! ( secondClass.equals( firstClass ) ) ) - { - Object converted = null; - if ( o2 instanceof Comparable ) - { - converted = ValueConverter.convertObjectToClass( o1, secondClass ); - if (converted != null) - { - o1 = converted; - } - } - - if (converted == null && (o1 instanceof Comparable)) - { - converted = ValueConverter.convertObjectToClass( o2, firstClass ); - if ( converted != null ) - { - o2 = converted; - } - } - - if (converted == null) - { - throw new WotonomyException("Qualifier: Not Comparable Objects"); - // no way to compare - } - } - - return ((Comparable)o2).compareTo( o1 ); - } - - } - - - static class OperatorCaseInsensitiveLike extends BaseSelector { - - public boolean isRelationalOperator() - { - return false; - } - - protected Boolean qualify( Object o1, Object o2 ) - { - String myString1 = o1.toString(); - String myString2 = o2.toString(); - myString1 = myString1.toLowerCase(); - myString2 = myString2.toLowerCase(); - StringTokenizer st = new StringTokenizer(myString1, "%"); - - while (st.hasMoreTokens()) { - String part = st.nextToken(); - int index = myString2.indexOf(part); - if (index > -1) - { - myString2 = myString2.substring(index + part.length()); - } - else - { - return Boolean.FALSE; - } - } - return Boolean.TRUE; - - } - - public String toString() - { - return "caseInsensitiveLike"; - } - } - - static class OperatorContains extends BaseSelector { - - public boolean isRelationalOperator() - { - return false; - } - - protected Boolean qualify( Object o1, Object o2 ) - { - String myString1 = o1.toString(); - String myString2 = o2.toString(); - return new Boolean( - myString2.indexOf(myString1) > -1 ); - } - - public String toString() - { - return "contains"; - } - } - - static class OperatorEqual extends BaseSelector { - - protected Boolean qualify( Object o1, Object o2 ) - { - return new Boolean( doCompare(o1, o2) == 0 ); - } - - public String toString() - { - return "="; - } - } - - static class OperatorGreaterThan extends BaseSelector { - - protected Boolean qualify( Object o1, Object o2 ) - { - return new Boolean( doCompare(o1, o2) > 0 ); - } - - public String toString() - { - return ">"; - } - } - - static class OperatorGreaterThanOrEqualTo extends BaseSelector { - - protected Boolean qualify( Object o1, Object o2 ) - { - return new Boolean( doCompare(o1, o2) >= 0 ); - } - - public String toString() - { - return new String(" >= "); - } - } - - static class OperatorLessThan extends BaseSelector { - - protected Boolean qualify( Object o1, Object o2 ) - { - return new Boolean( doCompare(o1, o2) < 0 ); - } - - public String toString() - { - return ">"; - } - } - - static class OperatorLessThanOrEqualTo extends BaseSelector { - - protected Boolean qualify( Object o1, Object o2 ) - { - return new Boolean (doCompare(o1, o2) <= 0); - } - - public String toString() - { - return "<="; - } - } - - static class OperatorLike extends BaseSelector { - - public boolean isRelationalOperator() - { - return false; - } - - protected Boolean qualify( Object o1, Object o2 ) - { - String myString1 = o1.toString(); - String myString2 = o2.toString(); - StringTokenizer st = new StringTokenizer(myString1, "%"); - while (st.hasMoreTokens()) { - String part = st.nextToken(); - int index = myString2.indexOf(part); - if (index > -1) - { - myString2 = myString2.substring(index + part.length()); - } - else - { - return Boolean.FALSE; - } - } - return Boolean.TRUE; - } - - public String toString() - { - return "like"; - } - } - - static class OperatorNotEqual extends BaseSelector { - - protected Boolean qualify( Object o1, Object o2 ) - { - return new Boolean(!(o1.equals(o2))); - } - - public String toString() - { - return "!="; - } - } - + * EOQualifiers are used to perform property-based qualifications on objects: + * for a set of criteria, a qualifier either qualifies or disqualifies an given + * object. EOKeyValueQualifiers can be joined by EOAndQualifier and + * EOOrQualifier, and so can form a tree of qualifications.
+ *
+ * + * Certain qualifiers can accept a variable in place of a value; variable names + * are marked by a "$", as in "$name". Variables are resolved with the + * qualifierWithBindings() method. + * + * @author michael@mpowers.net + * @author yjcheung@intersectsoft.com + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public abstract class EOQualifier { + public static final NSSelector QualifierOperatorCaseInsensitiveLike = new OperatorCaseInsensitiveLike(); + public static final NSSelector QualifierOperatorContains = new OperatorContains(); + public static final NSSelector QualifierOperatorEqual = new OperatorEqual(); + public static final NSSelector QualifierOperatorGreaterThan = new OperatorGreaterThan(); + public static final NSSelector QualifierOperatorGreaterThanOrEqualTo = new OperatorGreaterThanOrEqualTo(); + public static final NSSelector QualifierOperatorLessThan = new OperatorLessThan(); + public static final NSSelector QualifierOperatorLessThanOrEqualTo = new OperatorLessThanOrEqualTo(); + public static final NSSelector QualifierOperatorLike = new OperatorLike(); + public static final NSSelector QualifierOperatorNotEqual = new OperatorNotEqual(); + + /** + * Default constructor. + */ + public EOQualifier() { + } + + /** + * Adds all qualifier keys in this qualifier to the specified Set, which is + * expected to be mutable. The tree of qualifiers is traversed and the + * left-hand-side of each expression is added to the set. + */ + public void addQualifierKeysToSet(Set aSet) { + throw new RuntimeException("Not implemented yet."); + } + + /** + * Returns a Set of all property names used for comparisons by this qualifier. + * The tree of qualifiers is traversed and the left-hand-side of each expression + * is added to the set. + */ + public NSSet allQualifierKeys() { + throw new RuntimeException("Not implemented yet."); + } + + /** + * Returns a List containing the variables used at compare-time by this + * qualifier. Each variable will appear only once in the list. + */ + public NSArray bindingKeys() { + throw new RuntimeException("Not implemented yet."); + } + + /** + * Returns whether the specified object meets the criteria defined by this + * qualifier. + */ + public boolean evaluateWithObject(Object anObject) { + return true; + } + + /** + * Returns the key (which can be a key path) that is tested against the + * specified binding variable. The tree is traversed looking for the first + * instance of the specified variable, and the corresponding left-hand-side of + * the expression is returned. + */ + public String keyPathForBindingKey(String aVariable) { + throw new RuntimeException("Not implemented yet."); + } + + /** + * Returns a qualifier that is like this qualifier, except all variables will be + * replaced with values from the specified Map whose keys match the variable + * names. If requireAll is true, an exception will be thrown if there is no key + * that matches on of the variables in the tree; otherwise, the qualifier + * containing the unmatched variable is removed. + */ + public EOQualifier qualifierWithBindings(Map aMap, boolean requireAll) { + throw new WotonomyException("Not implemented yet."); + } + + /** + * Tests whether all the keys in this qualifier can be applied to an object of + * the specified class. + * + * @return A Throwable if the validation fails, otherwise returns null if the + * class can be used with this qualifier. + */ + public Throwable validateKeysWithRootClassDescription(Class aClass) { + throw new WotonomyException("Not implemented yet."); + } + + // statics + + /** + * Convenience to retain only those objects from the specified List that meet + * the specified qualifier's requirements. + */ + public static void filterArrayWithQualifier(List anObjectList, EOQualifier aQualifier) { + ListIterator iterator = anObjectList.listIterator(); + while (iterator.hasNext()) { + if (!aQualifier.evaluateWithObject(iterator.next())) { + iterator.remove(); + } + } + } + + /** + * Convenience to return a List consisting only of those objects in the + * specified List that meet the specified qualifier's requirements. + */ + public static NSArray filteredArrayWithQualifier(List anObjectList, EOQualifier aQualifier) { + Object o; + List result = new LinkedList(); + Iterator iterator = anObjectList.iterator(); + while (iterator.hasNext()) { + o = iterator.next(); + if (aQualifier.evaluateWithObject(o)) { + result.add(o); + } + } + return new NSArray((Collection) result); + } + + /** + * Convenience to create a set of EOKeyValueQualifiers joined by an + * EOAndQualifier. Each pair of keys and values are used to create + * EOKeyValueQualifiers. + */ + public static EOQualifier qualifierToMatchAllValues(Map aMap) { + Object key, value; + List qualifierList = new LinkedList(); + Iterator iterator = aMap.keySet().iterator(); + while (iterator.hasNext()) { + key = iterator.next(); + value = aMap.get(key); + qualifierList.add(new EOKeyValueQualifier(key.toString(), QualifierOperatorEqual, value)); + } + return new EOAndQualifier(qualifierList); + } + + /** + * Convenience to create a set of EOKeyValueQualifiers joined by an + * EOOrQualifier. Each pair of keys and values are used to create + * EOKeyValueQualifiers. + */ + public static EOQualifier qualifierToMatchAnyValue(Map aMap) { + Object key, value; + List qualifierList = new LinkedList(); + Iterator iterator = aMap.keySet().iterator(); + while (iterator.hasNext()) { + key = iterator.next(); + value = aMap.get(key); + qualifierList.add(new EOKeyValueQualifier(key.toString(), QualifierOperatorEqual, value)); + } + return new EOOrQualifier(qualifierList); + } + + /** + * Returns an EOQualifier that meets the criteria represented by the specified + * string and variable length argument list. This method parses the string and + * returns a tree of qualifiers. Each token beginning with "%" is replaced with + * the corresponding object from the argument list. The parser recognizes the + * operation tokens returned from the allQualifierOperators() method. + */ + public static EOQualifier qualifierWithQualifierFormat(String aString, List anArgumentList) { + throw new RuntimeException("Not implemented yet."); + } + + /** + * Returns a List of operators that are supported for relational operations. + * This excludes string comparison operators. + */ + public static NSArray relationalQualifierOperators() { + NSMutableArray result = new NSMutableArray(); + BaseSelector selector; + Iterator iterator = allQualifierOperators().iterator(); + while (iterator.hasNext()) { + selector = (BaseSelector) iterator.next(); + if (selector.isRelationalOperator()) { + result.addObject(selector); + } + } + return result; + } + + /** + * Returns a List of valid operators. + */ + public static NSArray allQualifierOperators() { + return operators.allKeys(); + } + + /** + * Returns a selector the corresponds to the operation represented by the + * specified string. For example, ">" represents QualifierOperatorGreaterThan. + */ + public static NSSelector operatorSelectorForString(String anOperatorString) { + return (NSSelector) operators.objectForKey(anOperatorString); + } + + /** + * Returns a string the corresponds to the operation represented by the + * specified selector. For example, QualifierOperatorGreaterThan is represented + * with ">". + */ + public static String stringForOperatorSelector(NSSelector aSelector) { + return (String) operators.allKeysForObject(aSelector).lastObject(); + } + + /** + * Returns a string representation of this qualifier. + */ + public String toString() { + // TODO: implement this + return super.toString(); + } + + // built-in qualifiers + + private static NSMutableDictionary operators; + static { + operators = new NSMutableDictionary(); + operators.setObjectForKey(QualifierOperatorCaseInsensitiveLike, + QualifierOperatorCaseInsensitiveLike.toString()); + operators.setObjectForKey(QualifierOperatorContains, QualifierOperatorContains.toString()); + operators.setObjectForKey(QualifierOperatorEqual, QualifierOperatorEqual.toString()); + operators.setObjectForKey(QualifierOperatorGreaterThan, QualifierOperatorGreaterThan.toString()); + operators.setObjectForKey(QualifierOperatorGreaterThanOrEqualTo, + QualifierOperatorGreaterThanOrEqualTo.toString()); + operators.setObjectForKey(QualifierOperatorLessThan, QualifierOperatorLessThan.toString()); + operators.setObjectForKey(QualifierOperatorLessThanOrEqualTo, QualifierOperatorLessThanOrEqualTo.toString()); + operators.setObjectForKey(QualifierOperatorLike, QualifierOperatorLike.toString()); + operators.setObjectForKey(QualifierOperatorNotEqual, QualifierOperatorNotEqual.toString()); + } + + static private abstract class BaseSelector extends NSSelector { + public String name() { + return "BaseSelector"; + } + + public Class[] parameterTypes() { + return new Class[] { Object.class, Object.class }; + } + + public Method methodOnClass(Class aClass) throws NoSuchMethodException { + throw new NoSuchMethodException(); + } + + public Method methodOnObject(Object anObject) throws NoSuchMethodException { + throw new NoSuchMethodException(); + } + + public boolean implementedByClass(Class aClass) { + return true; + } + + public boolean implementedByObject(Object anObject) { + return true; + } + + public boolean isRelationalOperator() { + return true; + } + + public Object invoke(Object anObject, Object[] parameters) throws IllegalAccessException, + IllegalArgumentException, InvocationTargetException, NoSuchMethodException { + return qualify(anObject, parameters[0]); + } + + abstract protected Boolean qualify(Object target, Object parameter); + + protected int doCompare(Object o1, Object o2) { + Class firstClass = o1.getClass(); + Class secondClass = o2.getClass(); + + if (!(secondClass.equals(firstClass))) { + Object converted = null; + if (o2 instanceof Comparable) { + converted = ValueConverter.convertObjectToClass(o1, secondClass); + if (converted != null) { + o1 = converted; + } + } + + if (converted == null && (o1 instanceof Comparable)) { + converted = ValueConverter.convertObjectToClass(o2, firstClass); + if (converted != null) { + o2 = converted; + } + } + + if (converted == null) { + throw new WotonomyException("Qualifier: Not Comparable Objects"); + // no way to compare + } + } + + return ((Comparable) o2).compareTo(o1); + } + + } + + static class OperatorCaseInsensitiveLike extends BaseSelector { + + public boolean isRelationalOperator() { + return false; + } + + protected Boolean qualify(Object o1, Object o2) { + String myString1 = o1.toString(); + String myString2 = o2.toString(); + myString1 = myString1.toLowerCase(); + myString2 = myString2.toLowerCase(); + StringTokenizer st = new StringTokenizer(myString1, "%"); + + while (st.hasMoreTokens()) { + String part = st.nextToken(); + int index = myString2.indexOf(part); + if (index > -1) { + myString2 = myString2.substring(index + part.length()); + } else { + return Boolean.FALSE; + } + } + return Boolean.TRUE; + + } + + public String toString() { + return "caseInsensitiveLike"; + } + } + + static class OperatorContains extends BaseSelector { + + public boolean isRelationalOperator() { + return false; + } + + protected Boolean qualify(Object o1, Object o2) { + String myString1 = o1.toString(); + String myString2 = o2.toString(); + return new Boolean(myString2.indexOf(myString1) > -1); + } + + public String toString() { + return "contains"; + } + } + + static class OperatorEqual extends BaseSelector { + + protected Boolean qualify(Object o1, Object o2) { + return new Boolean(doCompare(o1, o2) == 0); + } + + public String toString() { + return "="; + } + } + + static class OperatorGreaterThan extends BaseSelector { + + protected Boolean qualify(Object o1, Object o2) { + return new Boolean(doCompare(o1, o2) > 0); + } + + public String toString() { + return ">"; + } + } + + static class OperatorGreaterThanOrEqualTo extends BaseSelector { + + protected Boolean qualify(Object o1, Object o2) { + return new Boolean(doCompare(o1, o2) >= 0); + } + + public String toString() { + return new String(" >= "); + } + } + + static class OperatorLessThan extends BaseSelector { + + protected Boolean qualify(Object o1, Object o2) { + return new Boolean(doCompare(o1, o2) < 0); + } + + public String toString() { + return ">"; + } + } + + static class OperatorLessThanOrEqualTo extends BaseSelector { + + protected Boolean qualify(Object o1, Object o2) { + return new Boolean(doCompare(o1, o2) <= 0); + } + + public String toString() { + return "<="; + } + } + + static class OperatorLike extends BaseSelector { + + public boolean isRelationalOperator() { + return false; + } + + protected Boolean qualify(Object o1, Object o2) { + String myString1 = o1.toString(); + String myString2 = o2.toString(); + StringTokenizer st = new StringTokenizer(myString1, "%"); + while (st.hasMoreTokens()) { + String part = st.nextToken(); + int index = myString2.indexOf(part); + if (index > -1) { + myString2 = myString2.substring(index + part.length()); + } else { + return Boolean.FALSE; + } + } + return Boolean.TRUE; + } + + public String toString() { + return "like"; + } + } + + static class OperatorNotEqual extends BaseSelector { + + protected Boolean qualify(Object o1, Object o2) { + return new Boolean(!(o1.equals(o2))); + } + + public String toString() { + return "!="; + } + } public static Object decodeWithKeyValueUnarchiver(EOKeyValueUnarchiver ua) { - String cname = (String)ua.decodeObjectForKey("class"); + String cname = (String) ua.decodeObjectForKey("class"); if (cname.equals("EOKeyValueQualifier")) - return (EOQualifier)EOKeyValueQualifier.decodeWithKeyValueUnarchiver(ua); + return (EOQualifier) EOKeyValueQualifier.decodeWithKeyValueUnarchiver(ua); if (cname.equals("EOAndQualifier")) - return (EOQualifier)EOAndQualifier.decodeWithKeyValueUnarchiver(ua); + return (EOQualifier) EOAndQualifier.decodeWithKeyValueUnarchiver(ua); if (cname.equals("EOOrQualifier")) - return (EOQualifier)EOOrQualifier.decodeWithKeyValueUnarchiver(ua); + return (EOQualifier) EOOrQualifier.decodeWithKeyValueUnarchiver(ua); if (cname.equals("EONotQualifier")) - return (EOQualifier)EONotQualifier.decodeWithKeyValueUnarchiver(ua); + return (EOQualifier) EONotQualifier.decodeWithKeyValueUnarchiver(ua); return null; } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.10 2003/08/09 01:22:51 chochos - * qualifiers implement EOKeyValueArchiving + * Revision 1.10 2003/08/09 01:22:51 chochos qualifiers implement + * EOKeyValueArchiving * - * Revision 1.9 2001/11/04 18:29:11 mpowers - * Better handling for non-string types used with non-relational operators. + * Revision 1.9 2001/11/04 18:29:11 mpowers Better handling for non-string types + * used with non-relational operators. * - * Revision 1.8 2001/10/31 15:25:14 mpowers - * Cleanup of qualifiers. + * Revision 1.8 2001/10/31 15:25:14 mpowers Cleanup of qualifiers. * - * Revision 1.7 2001/10/30 22:57:28 mpowers - * EOQualifier framework is now working. + * Revision 1.7 2001/10/30 22:57:28 mpowers EOQualifier framework is now + * working. * - * Revision 1.6 2001/10/30 22:16:37 mpowers - * Implemented operators as selectors. + * Revision 1.6 2001/10/30 22:16:37 mpowers Implemented operators as selectors. * - * Revision 1.5 2001/09/14 14:21:28 mpowers - * Updated javadoc. + * Revision 1.5 2001/09/14 14:21:28 mpowers Updated javadoc. * - * Revision 1.3 2001/09/13 15:25:56 mpowers - * Started implementation of the EOQualifier framework. + * Revision 1.3 2001/09/13 15:25:56 mpowers Started implementation of the + * EOQualifier framework. * - * Revision 1.2 2001/02/27 03:33:04 mpowers - * Initial draft of the key-value qualifier. + * Revision 1.2 2001/02/27 03:33:04 mpowers Initial draft of the key-value + * qualifier. * - * Revision 1.1.1.1 2000/12/21 15:46:47 mpowers - * Contributing wotonomy. + * Revision 1.1.1.1 2000/12/21 15:46:47 mpowers Contributing wotonomy. * - * Revision 1.2 2000/12/20 16:25:35 michael - * Added log to all files. + * Revision 1.2 2000/12/20 16:25:35 michael Added log to all files. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOQualifierEvaluation.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOQualifierEvaluation.java index 87769b8..bbdc190 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOQualifierEvaluation.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOQualifierEvaluation.java @@ -18,25 +18,23 @@ License along with this library; if not, see http://www.gnu.org package net.wotonomy.control; /** -* EOQualifiers that want to perform in-memory -* evaluation should implement this interface.

-* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 893 $ -*/ + * EOQualifiers that want to perform in-memory evaluation should implement this + * interface.
+ *
+ * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 893 $ + */ public interface EOQualifierEvaluation { public boolean evaluateWithObject(Object eo); } /* - * $Log$ - * Revision 1.1 2006/02/16 13:19:57 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. + * $Log$ Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.1 2003/08/12 01:42:17 chochos - * formally declare this interface + * Revision 1.1 2003/08/12 01:42:17 chochos formally declare this interface * */ - \ No newline at end of file diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EORelationshipManipulation.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EORelationshipManipulation.java index 568b555..4b8845b 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EORelationshipManipulation.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EORelationshipManipulation.java @@ -19,58 +19,48 @@ License along with this library; if not, see http://www.gnu.org package net.wotonomy.control; /** -* EORelationshipManipulation provides methods for generically -* adding and removing relationships between objects, handling -* both one-way and reciprocal relationships. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 893 $ -*/ -public interface EORelationshipManipulation -{ - /** - * Adds the specified object to the relationship on this - * object specified by the key. For to-one relationships, - * this operation is the same as valueForKey. - */ - void addObjectToPropertyWithKey( - Object anObject, String aKey ); + * EORelationshipManipulation provides methods for generically adding and + * removing relationships between objects, handling both one-way and reciprocal + * relationships. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 893 $ + */ +public interface EORelationshipManipulation { + /** + * Adds the specified object to the relationship on this object specified by the + * key. For to-one relationships, this operation is the same as valueForKey. + */ + void addObjectToPropertyWithKey(Object anObject, String aKey); - /** - * Removes the specified object from the relationship on - * this object specified by the key. For to-one relationships, - * this operation is the same as takeValueForKey with a null - * value. - */ - void removeObjectFromPropertyWithKey( - Object anObject, String aKey ); + /** + * Removes the specified object from the relationship on this object specified + * by the key. For to-one relationships, this operation is the same as + * takeValueForKey with a null value. + */ + void removeObjectFromPropertyWithKey(Object anObject, String aKey); - /** - * As addObjectToProperty with key, but also performs the - * reciprocal operation on the other side of the relationship. - */ - void addObjectToBothSidesOfRelationshipWithKey( - EORelationshipManipulation anObject, String aKey ); - - /** - * As removeObjectFromPropertyWithKey with key, but also performs the - * reciprocal operation on the other side of the relationship. - */ - void removeObjectFromBothSidesOfRelationshipWithKey( - EORelationshipManipulation anObject, String aKey ); + /** + * As addObjectToProperty with key, but also performs the reciprocal operation + * on the other side of the relationship. + */ + void addObjectToBothSidesOfRelationshipWithKey(EORelationshipManipulation anObject, String aKey); + + /** + * As removeObjectFromPropertyWithKey with key, but also performs the reciprocal + * operation on the other side of the relationship. + */ + void removeObjectFromBothSidesOfRelationshipWithKey(EORelationshipManipulation anObject, String aKey); } /* - * $Log$ - * Revision 1.1 2006/02/16 13:19:57 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. + * $Log$ Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.1 2001/11/13 04:13:59 mpowers - * Added interfaces needed to begin work on EOCustomObject. + * Revision 1.1 2001/11/13 04:13:59 mpowers Added interfaces needed to begin + * work on EOCustomObject. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOSortOrdering.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOSortOrdering.java index 789b6da..e2ce595 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOSortOrdering.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOSortOrdering.java @@ -30,154 +30,128 @@ import net.wotonomy.foundation.NSMutableArray; import net.wotonomy.foundation.NSSelector; /** -* EOSortOrdering defines a sort key and operation. -* DisplayGroups use lists of EOSortOrdering to determine -* how to order their items. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public class EOSortOrdering implements Serializable, EOKeyValueArchiving -{ - /** - * Sorts items in ascending order. - */ - public static final - NSSelector CompareAscending = new CompareAscendingComparator(); - - /** - * Sorts items in descending order. - */ - public static final - NSSelector CompareDescending = new CompareDescendingComparator(); - - /** - * Sorts items' string representations in ascending order - * in a case insensitive manner. - */ - public static final - NSSelector CompareCaseInsensitiveAscending = - new CompareCaseInsensitiveAscendingComparator(); - - /** - * Sorts items' string representations in descending order - * in a case insensitive manner. - */ - public static final - NSSelector CompareCaseInsensitiveDescending = - new CompareCaseInsensitiveDescendingComparator(); - - protected String key; - protected NSSelector selector; - - /** - * Factory-style constructor returns a new EOSortOrdering instance - * with the specified key and selector. Neither may be null. - */ - public static EOSortOrdering sortOrderingWithKey(String key, NSSelector selector) - { - return new EOSortOrdering( key, selector ); - } - - /** - * Constructor creates an EOSortOrdering that uses the - * specified key and selector. Neither may be null. - */ - public EOSortOrdering( String aKey, NSSelector aSelector ) - { - key = aKey; - selector = aSelector; - } - - /** - * Constructor creates an EOSortOrdering that uses the - * specified key and comparator. Neither may be null. - * Not in the spec. - */ - public EOSortOrdering( String aKey, Comparator aComparator ) - { - key = aKey; - selector = new NSSelector( aKey, aComparator ); - } - - /** - * Returns the property key. - */ - public String key() - { - return key; - } - - /** - * Returns the selector. - */ - public NSSelector selector() - { - return selector; - } - - public String toString() - { - return "[EOSortOrdering: key='"+key+"' selector='"+selector+"']"; - } - - public boolean equals( Object anObject ) - { - if ( anObject instanceof EOSortOrdering ) - { - EOSortOrdering x = (EOSortOrdering) anObject; - if ( selector().equals( x.selector() ) ) - { - if ( key().equals( x.key() ) ) - { - return true; - } - } - } - return false; - } - - /** - * Sorts the specified list in place according to the specified - * list of EOSortOrderings. The items will be sorted first by the - * first ordering, and items with equal values for that property - * will be sorted by the next ordering, and so on. - */ - public static void sortArrayUsingKeyOrderArray( - List anObjectList, List aSortOrderingList ) - { - List keys = new ArrayList( aSortOrderingList ); - Collections.reverse( keys ); - Iterator it = keys.iterator(); - EOSortOrdering sortOrdering; - while ( it.hasNext() ) - { - sortOrdering = (EOSortOrdering) it.next(); - Collections.sort( anObjectList, - new DelegatingComparator( - sortOrdering.key(), sortOrdering.selector() ) ); - } - } - - /** - * Sorts the specified list in place according to the specified - * list of EOSortOrderings. The items will be sorted first by the - * first ordering, and items with equal values for that property - * will be sorted by the next ordering, and so on. - */ - public static NSArray sortedArrayUsingKeyOrderArray( - List anObjectList, List aSortOrderingList ) - { - NSArray result = new NSMutableArray(); - result.addAll( anObjectList ); - sortArrayUsingKeyOrderArray( result, aSortOrderingList ); - return result; - } + * EOSortOrdering defines a sort key and operation. DisplayGroups use lists of + * EOSortOrdering to determine how to order their items. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public class EOSortOrdering implements Serializable, EOKeyValueArchiving { + /** + * Sorts items in ascending order. + */ + public static final NSSelector CompareAscending = new CompareAscendingComparator(); + + /** + * Sorts items in descending order. + */ + public static final NSSelector CompareDescending = new CompareDescendingComparator(); + + /** + * Sorts items' string representations in ascending order in a case insensitive + * manner. + */ + public static final NSSelector CompareCaseInsensitiveAscending = new CompareCaseInsensitiveAscendingComparator(); + + /** + * Sorts items' string representations in descending order in a case insensitive + * manner. + */ + public static final NSSelector CompareCaseInsensitiveDescending = new CompareCaseInsensitiveDescendingComparator(); + + protected String key; + protected NSSelector selector; + + /** + * Factory-style constructor returns a new EOSortOrdering instance with the + * specified key and selector. Neither may be null. + */ + public static EOSortOrdering sortOrderingWithKey(String key, NSSelector selector) { + return new EOSortOrdering(key, selector); + } + + /** + * Constructor creates an EOSortOrdering that uses the specified key and + * selector. Neither may be null. + */ + public EOSortOrdering(String aKey, NSSelector aSelector) { + key = aKey; + selector = aSelector; + } + + /** + * Constructor creates an EOSortOrdering that uses the specified key and + * comparator. Neither may be null. Not in the spec. + */ + public EOSortOrdering(String aKey, Comparator aComparator) { + key = aKey; + selector = new NSSelector(aKey, aComparator); + } + + /** + * Returns the property key. + */ + public String key() { + return key; + } + + /** + * Returns the selector. + */ + public NSSelector selector() { + return selector; + } + + public String toString() { + return "[EOSortOrdering: key='" + key + "' selector='" + selector + "']"; + } + + public boolean equals(Object anObject) { + if (anObject instanceof EOSortOrdering) { + EOSortOrdering x = (EOSortOrdering) anObject; + if (selector().equals(x.selector())) { + if (key().equals(x.key())) { + return true; + } + } + } + return false; + } + + /** + * Sorts the specified list in place according to the specified list of + * EOSortOrderings. The items will be sorted first by the first ordering, and + * items with equal values for that property will be sorted by the next + * ordering, and so on. + */ + public static void sortArrayUsingKeyOrderArray(List anObjectList, List aSortOrderingList) { + List keys = new ArrayList(aSortOrderingList); + Collections.reverse(keys); + Iterator it = keys.iterator(); + EOSortOrdering sortOrdering; + while (it.hasNext()) { + sortOrdering = (EOSortOrdering) it.next(); + Collections.sort(anObjectList, new DelegatingComparator(sortOrdering.key(), sortOrdering.selector())); + } + } + + /** + * Sorts the specified list in place according to the specified list of + * EOSortOrderings. The items will be sorted first by the first ordering, and + * items with equal values for that property will be sorted by the next + * ordering, and so on. + */ + public static NSArray sortedArrayUsingKeyOrderArray(List anObjectList, List aSortOrderingList) { + NSArray result = new NSMutableArray(); + result.addAll(anObjectList); + sortArrayUsingKeyOrderArray(result, aSortOrderingList); + return result; + } public static Object decodeWithKeyValueUnarchiver(EOKeyValueUnarchiver arch) { - String k = (String)arch.decodeObjectForKey("key"); - String sname = (String)arch.decodeObjectForKey("selectorName"); + String k = (String) arch.decodeObjectForKey("key"); + String sname = (String) arch.decodeObjectForKey("selectorName"); NSSelector sel = null; if (sname.equals("compareAscending:")) sel = CompareAscending; @@ -189,8 +163,8 @@ public class EOSortOrdering implements Serializable, EOKeyValueArchiving sel = CompareCaseInsensitiveAscending; else { if (sname.endsWith(":")) - sname = sname.substring(0, sname.length()-1); - sel = new NSSelector(sname, new Class[]{ Object.class }); + sname = sname.substring(0, sname.length() - 1); + sel = new NSSelector(sname, new Class[] { Object.class }); } return new EOSortOrdering(k, sel); } @@ -210,197 +184,147 @@ public class EOSortOrdering implements Serializable, EOKeyValueArchiving arch.encodeObject(selector.name() + ":", "selectorName"); } - private static class CompareAscendingComparator - extends NSSelector - { - public int compare(Object o1, Object o2) - { - if ( o1 instanceof Comparable ) - { - if ( o2 instanceof Comparable ) - { - return ((Comparable)o1).compareTo( o2 ); - } - } - - // null handling: null is less than any object - - if ( o1 == null ) - { - if ( o2 == null ) - { - return 0; - } - else - { - return -1; - } - } - else // o1 != null - if ( o2 == null ) - { - return 1; - } - - // fall back on string representation comparison - - return o1.toString().compareTo( o2.toString() ); - } - - public boolean equals(Object obj) - { - return ( this == obj ); - } - } - - private static class CompareDescendingComparator - extends CompareAscendingComparator - { - public int compare(Object o1, Object o2) - { - return -1 * super.compare( o1, o2 ); - } - } - - private static class CompareCaseInsensitiveAscendingComparator - extends NSSelector - { - public int compare(Object o1, Object o2) - { - // null handling: null is less than any object - - if ( o1 == null ) - { - if ( o2 == null ) - { - return 0; - } - else - { - return -1; - } - } - else // o1 != null - if ( o2 == null ) - { - return 1; - } - - return o1.toString().toLowerCase().compareTo( - o2.toString().toLowerCase() ); - } - - public boolean equals(Object obj) - { - return ( this == obj ); - } - } - - private static class CompareCaseInsensitiveDescendingComparator - extends CompareCaseInsensitiveAscendingComparator - { - public int compare(Object o1, Object o2) - { - return -1 * super.compare( o1, o2 ); - } - } - - private static class DelegatingComparator implements Comparator - { - private String key; - private Comparator comparator; - - public DelegatingComparator( String aKey, Comparator aComparator ) - { - key = aKey; - comparator = aComparator; - } - - public int compare(Object o1, Object o2) - { - Object v1, v2; - if ( o1 instanceof EOKeyValueCoding ) - { - v1 = ((EOKeyValueCoding)o1).valueForKey( key ); - } - else - { - v1 = EOKeyValueCodingSupport.valueForKey( o1, key ); - } - if ( o2 instanceof EOKeyValueCoding ) - { - v2 = ((EOKeyValueCoding)o2).valueForKey( key ); - } - else - { - v2 = EOKeyValueCodingSupport.valueForKey( o2, key ); - } - return comparator.compare( v1, v2 ); - } - - public boolean equals(Object obj) - { - return ( this == obj ); - } - } + private static class CompareAscendingComparator extends NSSelector { + public int compare(Object o1, Object o2) { + if (o1 instanceof Comparable) { + if (o2 instanceof Comparable) { + return ((Comparable) o1).compareTo(o2); + } + } + + // null handling: null is less than any object + + if (o1 == null) { + if (o2 == null) { + return 0; + } else { + return -1; + } + } else // o1 != null + if (o2 == null) { + return 1; + } + + // fall back on string representation comparison + + return o1.toString().compareTo(o2.toString()); + } + + public boolean equals(Object obj) { + return (this == obj); + } + } + + private static class CompareDescendingComparator extends CompareAscendingComparator { + public int compare(Object o1, Object o2) { + return -1 * super.compare(o1, o2); + } + } + + private static class CompareCaseInsensitiveAscendingComparator extends NSSelector { + public int compare(Object o1, Object o2) { + // null handling: null is less than any object + + if (o1 == null) { + if (o2 == null) { + return 0; + } else { + return -1; + } + } else // o1 != null + if (o2 == null) { + return 1; + } + + return o1.toString().toLowerCase().compareTo(o2.toString().toLowerCase()); + } + + public boolean equals(Object obj) { + return (this == obj); + } + } + + private static class CompareCaseInsensitiveDescendingComparator extends CompareCaseInsensitiveAscendingComparator { + public int compare(Object o1, Object o2) { + return -1 * super.compare(o1, o2); + } + } + + private static class DelegatingComparator implements Comparator { + private String key; + private Comparator comparator; + + public DelegatingComparator(String aKey, Comparator aComparator) { + key = aKey; + comparator = aComparator; + } + + public int compare(Object o1, Object o2) { + Object v1, v2; + if (o1 instanceof EOKeyValueCoding) { + v1 = ((EOKeyValueCoding) o1).valueForKey(key); + } else { + v1 = EOKeyValueCodingSupport.valueForKey(o1, key); + } + if (o2 instanceof EOKeyValueCoding) { + v2 = ((EOKeyValueCoding) o2).valueForKey(key); + } else { + v2 = EOKeyValueCodingSupport.valueForKey(o2, key); + } + return comparator.compare(v1, v2); + } + + public boolean equals(Object obj) { + return (this == obj); + } + } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.14 2003/08/11 19:39:52 chochos - * now encodes/decodes correctly. + * Revision 1.14 2003/08/11 19:39:52 chochos now encodes/decodes correctly. * - * Revision 1.13 2003/08/09 01:29:56 chochos - * implements EOKeyValueArchiving + * Revision 1.13 2003/08/09 01:29:56 chochos implements EOKeyValueArchiving * - * Revision 1.12 2003/08/06 23:07:52 chochos - * general code cleanup (mostly, removing unused imports) + * Revision 1.12 2003/08/06 23:07:52 chochos general code cleanup (mostly, + * removing unused imports) * - * Revision 1.11 2003/02/07 20:23:23 mpowers - * Provided backwards compatibility for comparators. + * Revision 1.11 2003/02/07 20:23:23 mpowers Provided backwards compatibility + * for comparators. * - * Revision 1.10 2003/01/18 23:46:58 mpowers - * EOSortOrdering is now correctly using NSSelectors. + * Revision 1.10 2003/01/18 23:46:58 mpowers EOSortOrdering is now correctly + * using NSSelectors. * - * Revision 1.9 2003/01/16 22:47:30 mpowers - * Compatibility changes to support compiling woextensions source. - * (34 out of 56 classes compile!) + * Revision 1.9 2003/01/16 22:47:30 mpowers Compatibility changes to support + * compiling woextensions source. (34 out of 56 classes compile!) * - * Revision 1.8 2002/03/01 20:23:27 mpowers - * Implemented equals. + * Revision 1.8 2002/03/01 20:23:27 mpowers Implemented equals. * - * Revision 1.7 2002/02/06 21:15:04 mpowers - * Added null handling to CompareCaseInsensitiveAscendingComparator. + * Revision 1.7 2002/02/06 21:15:04 mpowers Added null handling to + * CompareCaseInsensitiveAscendingComparator. * - * Revision 1.6 2001/12/01 23:51:24 mpowers - * Made serializable. + * Revision 1.6 2001/12/01 23:51:24 mpowers Made serializable. * - * Revision 1.5 2001/03/29 03:29:49 mpowers - * Now using KeyValueCoding and Support instead of Introspector. + * Revision 1.5 2001/03/29 03:29:49 mpowers Now using KeyValueCoding and Support + * instead of Introspector. * - * Revision 1.4 2001/01/24 22:15:52 mpowers - * Fixed npe when comparing nulls. + * Revision 1.4 2001/01/24 22:15:52 mpowers Fixed npe when comparing nulls. * - * Revision 1.3 2001/01/12 19:11:56 mpowers - * Fixed table column click sorting. + * Revision 1.3 2001/01/12 19:11:56 mpowers Fixed table column click sorting. * - * Revision 1.2 2001/01/12 17:23:46 mpowers - * Inner classes are now private. + * Revision 1.2 2001/01/12 17:23:46 mpowers Inner classes are now private. * - * Revision 1.1 2001/01/11 20:34:26 mpowers - * Implemented EOSortOrdering and added support in framework. - * Added header-click to sort table columns. + * Revision 1.1 2001/01/11 20:34:26 mpowers Implemented EOSortOrdering and added + * support in framework. Added header-click to sort table columns. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOTemporaryGlobalID.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOTemporaryGlobalID.java index 44ba855..31351a9 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOTemporaryGlobalID.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOTemporaryGlobalID.java @@ -21,199 +21,181 @@ package net.wotonomy.control; import java.net.InetAddress; /** -* EOTemporaryGlobalID is a network-wide unique key. -* This is used by EOEditingContext to construct temporary -* ids when new objects are created.

-* -* The specified format of the key is a byte array: -* < Sequence [2], ProcessID [2], Time [4], IP Addr [4] >, -* but because java does not allow access to the process id, -* the timestamp of when this class is first loaded is used -* to simulate a process id. -* -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 893 $ -*/ -public class EOTemporaryGlobalID - extends EOGlobalID -{ - /** - * Holds the length in bytes of the key that is generated. - */ - public static final int UniqueBinaryKeyLength = 12; - - private static int sequence; - private static byte[] processid; // 2 bytes - private static byte[] ipaddr; // 4 bytes - - static // static initializer - { - // init sequence - sequence = 0; - - // init processid - processid = new byte[2]; - long time = System.currentTimeMillis(); - processid[1] = (byte) time; - time = time >> 8; - processid[0] = (byte) time; - - // init ipaddr - ipaddr = new byte[4]; - try - { - ipaddr = InetAddress.getLocalHost().getAddress(); - } - catch ( Exception exc ) - { - // could not obtain ip address - use pid twice - ipaddr[0] = processid[0]; - ipaddr[1] = processid[1]; - ipaddr[2] = processid[0]; - ipaddr[3] = processid[1]; - } - } - - private byte[] key; - private int hashCode; - - /** - * Generates a new id with a unique key. - */ - public EOTemporaryGlobalID() - { - key = new byte[UniqueBinaryKeyLength]; - - // init sequence (important byte first) - key[0] = (byte) ( sequence ); - key[1] = (byte) ( sequence >> 8 ); - sequence++; - - // populate pid (important byte first) - key[2] = processid[1]; - key[3] = processid[0]; - - // init time (important byte first) - long time = System.currentTimeMillis(); - key[4] = (byte) time; - time = time >> 8; - key[5] = (byte) time; - time = time >> 8; - key[6] = (byte) time; - time = time >> 8; - key[7] = (byte) time; - - // populate ipaddr - key[8] = ipaddr[0]; - key[9] = ipaddr[1]; - key[10] = ipaddr[2]; - key[11] = ipaddr[3]; - - // use string's hash code - hashCode = new String( key ).hashCode(); - } - - /** - * Private constructor for cloning. - */ - private EOTemporaryGlobalID( byte[] aKey ) - { + * EOTemporaryGlobalID is a network-wide unique key. This is used by + * EOEditingContext to construct temporary ids when new objects are created. + *
+ *
+ * + * The specified format of the key is a byte array: < Sequence [2], ProcessID + * [2], Time [4], IP Addr [4] >, but because java does not allow access to + * the process id, the timestamp of when this class is first loaded is used to + * simulate a process id. + * + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 893 $ + */ +public class EOTemporaryGlobalID extends EOGlobalID { + /** + * Holds the length in bytes of the key that is generated. + */ + public static final int UniqueBinaryKeyLength = 12; + + private static int sequence; + private static byte[] processid; // 2 bytes + private static byte[] ipaddr; // 4 bytes + + static // static initializer + { + // init sequence + sequence = 0; + + // init processid + processid = new byte[2]; + long time = System.currentTimeMillis(); + processid[1] = (byte) time; + time = time >> 8; + processid[0] = (byte) time; + + // init ipaddr + ipaddr = new byte[4]; + try { + ipaddr = InetAddress.getLocalHost().getAddress(); + } catch (Exception exc) { + // could not obtain ip address - use pid twice + ipaddr[0] = processid[0]; + ipaddr[1] = processid[1]; + ipaddr[2] = processid[0]; + ipaddr[3] = processid[1]; + } + } + + private byte[] key; + private int hashCode; + + /** + * Generates a new id with a unique key. + */ + public EOTemporaryGlobalID() { + key = new byte[UniqueBinaryKeyLength]; + + // init sequence (important byte first) + key[0] = (byte) (sequence); + key[1] = (byte) (sequence >> 8); + sequence++; + + // populate pid (important byte first) + key[2] = processid[1]; + key[3] = processid[0]; + + // init time (important byte first) + long time = System.currentTimeMillis(); + key[4] = (byte) time; + time = time >> 8; + key[5] = (byte) time; + time = time >> 8; + key[6] = (byte) time; + time = time >> 8; + key[7] = (byte) time; + + // populate ipaddr + key[8] = ipaddr[0]; + key[9] = ipaddr[1]; + key[10] = ipaddr[2]; + key[11] = ipaddr[3]; + + // use string's hash code + hashCode = new String(key).hashCode(); + } + + /** + * Private constructor for cloning. + */ + private EOTemporaryGlobalID(byte[] aKey) { // key = aKey; // this might be faster - // make copy of key - might be safer - key = new byte[ UniqueBinaryKeyLength ]; - for ( int i = 0; i < UniqueBinaryKeyLength; i++ ) - { - key[i] = aKey[i]; - } - - // use string's hash code - hashCode = new String( aKey ).hashCode(); - } - - /** - * Returns true. - */ - public boolean isTemporary() - { - return true; - } - - /** - * Returns whether the keys are equal. - */ - public boolean equals( Object anObject ) - { - if ( ! ( anObject instanceof EOTemporaryGlobalID ) ) - return false; - - byte[] otherKey = ((EOTemporaryGlobalID)anObject).key; - - for ( int i = 0; i < UniqueBinaryKeyLength; i++ ) - { - if ( key[i] != otherKey[i] ) return false; - } - return true; - } - - /** - * Returns a copy of this object. - */ - public Object clone() - { - // faster than super.clone() - return new EOTemporaryGlobalID( key ); - } - - public int hashCode() - { - return hashCode; - } - - /** - * Returns a string representation of this key. - * This is a 24-character string with each pair - * of characters holding a hexadecimal value that - * is 128 more than the value of the corresponding - * byte (to account for two's complement). - */ - public String toString() - { - String hex; - StringBuffer buffer = new StringBuffer(); - for ( int i = 0; i < key.length; i++ ) - { - // get string: adjust for two's complement - hex = Integer.toHexString( key[i]+128 ); - // pad with zero so we take two characters - if ( hex.length() == 1 ) hex = "0" + hex; - // append hex code - buffer.append( hex ); - } - return buffer.toString(); - } + // make copy of key - might be safer + key = new byte[UniqueBinaryKeyLength]; + for (int i = 0; i < UniqueBinaryKeyLength; i++) { + key[i] = aKey[i]; + } + + // use string's hash code + hashCode = new String(aKey).hashCode(); + } + + /** + * Returns true. + */ + public boolean isTemporary() { + return true; + } + + /** + * Returns whether the keys are equal. + */ + public boolean equals(Object anObject) { + if (!(anObject instanceof EOTemporaryGlobalID)) + return false; + + byte[] otherKey = ((EOTemporaryGlobalID) anObject).key; + + for (int i = 0; i < UniqueBinaryKeyLength; i++) { + if (key[i] != otherKey[i]) + return false; + } + return true; + } + + /** + * Returns a copy of this object. + */ + public Object clone() { + // faster than super.clone() + return new EOTemporaryGlobalID(key); + } + + public int hashCode() { + return hashCode; + } + + /** + * Returns a string representation of this key. This is a 24-character string + * with each pair of characters holding a hexadecimal value that is 128 more + * than the value of the corresponding byte (to account for two's complement). + */ + public String toString() { + String hex; + StringBuffer buffer = new StringBuffer(); + for (int i = 0; i < key.length; i++) { + // get string: adjust for two's complement + hex = Integer.toHexString(key[i] + 128); + // pad with zero so we take two characters + if (hex.length() == 1) + hex = "0" + hex; + // append hex code + buffer.append(hex); + } + return buffer.toString(); + } } /* - * $Log$ - * Revision 1.1 2006/02/16 13:19:57 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. + * $Log$ Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.4 2001/04/29 22:02:45 mpowers - * Work on id transposing between editing contexts. + * Revision 1.4 2001/04/29 22:02:45 mpowers Work on id transposing between + * editing contexts. * - * Revision 1.3 2001/02/15 21:13:30 mpowers - * First draft implementation is complete. Now on to debugging. + * Revision 1.3 2001/02/15 21:13:30 mpowers First draft implementation is + * complete. Now on to debugging. * - * Revision 1.2 2001/02/14 23:03:02 mpowers - * A near-complete first draft of EOEditingContext. + * Revision 1.2 2001/02/14 23:03:02 mpowers A near-complete first draft of + * EOEditingContext. * - * Revision 1.1 2001/02/13 23:24:29 mpowers - * Implementing more of editing context. + * Revision 1.1 2001/02/13 23:24:29 mpowers Implementing more of editing + * context. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOValidation.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOValidation.java index a0aa4db..3054d4c 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOValidation.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOValidation.java @@ -19,54 +19,48 @@ License along with this library; if not, see http://www.gnu.org package net.wotonomy.control; /** -* EOValidation provides methods for validating a operation -* on an object as a whole, rather than on an individual property. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 893 $ -*/ -public interface EOValidation -{ - /** - * Validates this object for delete. - * Throws an exception if this object cannot be deleted. - */ - void validateForDelete(); - - /** - * Validates this object for insertion into the external store. - * Throws an exception if this object cannot be inserted. - * Validations here should be specific to insertion. - * Implementations may call validateForSave(). - */ - void validateForInsert(); - - /** - * Validates this object for a commit to the external store. - * Throws an exception if this object cannot be committed. - * Validations here are not specific to either inserts or updates. - */ - void validateForSave(); - - /** - * Validates this object for update to the external store. - * Throws an exception if this object cannot be updated. - * Validations here should be specific to updates. - * Implementations may call validateForSave(). - */ - void validateForUpdate(); + * EOValidation provides methods for validating a operation on an object as a + * whole, rather than on an individual property. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 893 $ + */ +public interface EOValidation { + /** + * Validates this object for delete. Throws an exception if this object cannot + * be deleted. + */ + void validateForDelete(); + + /** + * Validates this object for insertion into the external store. Throws an + * exception if this object cannot be inserted. Validations here should be + * specific to insertion. Implementations may call validateForSave(). + */ + void validateForInsert(); + + /** + * Validates this object for a commit to the external store. Throws an exception + * if this object cannot be committed. Validations here are not specific to + * either inserts or updates. + */ + void validateForSave(); + + /** + * Validates this object for update to the external store. Throws an exception + * if this object cannot be updated. Validations here should be specific to + * updates. Implementations may call validateForSave(). + */ + void validateForUpdate(); } /* - * $Log$ - * Revision 1.1 2006/02/16 13:19:57 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. + * $Log$ Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.1 2001/11/13 04:13:59 mpowers - * Added interfaces needed to begin work on EOCustomObject. + * Revision 1.1 2001/11/13 04:13:59 mpowers Added interfaces needed to begin + * work on EOCustomObject. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOVectorKeyGlobalID.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOVectorKeyGlobalID.java index cc91fd7..5fc500d 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOVectorKeyGlobalID.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOVectorKeyGlobalID.java @@ -18,11 +18,11 @@ package net.wotonomy.control; /** -* -* @author ezamudio@nasoft.com -* @author $Author: cgruber $ -* @version $Revision: 893 $ -*/ + * + * @author ezamudio@nasoft.com + * @author $Author: cgruber $ + * @version $Revision: 893 $ + */ public class EOVectorKeyGlobalID extends EOKeyGlobalID { protected Object[] _keyValues; @@ -35,14 +35,18 @@ public class EOVectorKeyGlobalID extends EOKeyGlobalID { } } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see net.wotonomy.control.EOKeyGlobalID#keyValuesNoCopy() */ public Object[] _keyValuesNoCopy() { return _keyValues; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see net.wotonomy.control.EOKeyGlobalID#_keyValues() */ public Object[] keyValues() { @@ -53,14 +57,18 @@ public class EOVectorKeyGlobalID extends EOKeyGlobalID { return v; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see net.wotonomy.control.EOKeyGlobalID#keyCount() */ public int keyCount() { return _keyValues.length; } - /* (non-Javadoc) + /* + * (non-Javadoc) + * * @see net.wotonomy.control.EOGlobalID#isTemporary() */ public boolean isTemporary() { @@ -69,11 +77,9 @@ public class EOVectorKeyGlobalID extends EOKeyGlobalID { } /* - * $Log$ - * Revision 1.1 2006/02/16 13:19:57 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. + * $Log$ Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.2 2003/08/19 01:59:01 chochos - * Added the wotonomy headers + * Revision 1.2 2003/08/19 01:59:01 chochos Added the wotonomy headers * */ diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EditingContext.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EditingContext.java index ee40f23..1a120a5 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EditingContext.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EditingContext.java @@ -25,259 +25,210 @@ import java.util.Map; //import javax.swing.undo.UndoManager; /** -* EditingContext provides transactional support for -* fetching, editing, and committing changes made on a -* collection of objects to a parent object store. -* This subclasses EOEditingContext to provide -* java-friendly conveniences. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public class EditingContext extends EOEditingContext -{ - /** - * Default constructor creates a new editing context - * that uses the default object store. If the default - * object store has not been set, an exception is thrown. - */ - public EditingContext() - { - this( defaultParentObjectStore() ); - } - - /** - * Creates a new editing context that uses the specified - * object store as its parent object store. - */ - public EditingContext( EOObjectStore anObjectStore ) - { - super( anObjectStore ); - } - - /** - * Returns a List of objects associated with the object - * with the specified id for the specified property - * relationship, or may return a placeholder array that - * will defer the fetch until needed (aka an array fault). - * All objects must be registered in the specified editing context. - * This implementation calls to its parent object store's - * implementation if the requested source object is not - * registered in this editing context. - * The specified relationship key must produce a result of - * type Collection for the source object or an exception is thrown. - */ - public List getArrayFaultWithSourceGlobalID ( - EOGlobalID aGlobalID, - String aRelationshipKey, - EOEditingContext aContext ) - { - return arrayFaultWithSourceGlobalID( - aGlobalID, aRelationshipKey, aContext ); - } - - /** - * Returns a snapshot of the specified object as it - * existed when it was last read or committed to the - * parent object store. - */ - public Map getCommittedSnapshotForObject ( - Object anObject ) - { - return committedSnapshotForObject( anObject ); - } - - /** - * Returns a snapshot of the specified object as it - * existed before the edits triggered by the current - * event loop were processed. - */ - public Map getCurrentEventSnapshotForObject ( - Object anObject ) - { - return currentEventSnapshotForObject( anObject ); - } - - /** - * Returns the delegate for this editing context, - * or null if no delegate has been set. - */ - public Object getDelegate () - { - return delegate(); - } - - /** - * Returns a List of all objects marked as deleted - * in this editing context. - */ - public List getDeletedObjects () - { - return deletedObjects(); - } - - /** - * Returns a List of registered editors of this - * editing context. - */ - public List getEditors() - { - return editors(); - } - - /** - * Returns the object for the specified id. - * If the object's data has not been fetched, - * it will be fetched when needed. - */ - public Object getFaultForGlobalID ( - EOGlobalID aGlobalID ) - { - return faultForGlobalID( aGlobalID, this ); - } - - /** - * Returns a fault representing an object of - * the specified entity type with values from - * the specified dictionary. - */ - public Object getFaultForRawRow ( - Map aDictionary, - String anEntityName ) - { - return faultForRawRow( aDictionary, anEntityName ); - } - - /** - * Returns the fetch timestamp for this editing context. - */ - public double getFetchTimestamp() - { - return fetchTimestamp(); - } - - /** - * Returns the id for the specified object, or null - * if the object is not registered in this context. - */ - public EOGlobalID getGlobalIDForObject ( - Object anObject ) - { - return globalIDForObject( anObject ); - } - - /** - * Returns a List of the objects that have been - * inserted into this editing context. - */ - public List getInsertedObjects () - { - return insertedObjects(); - } - - /** - * Returns the message handler for this editing context, - * or null if no message handler has been set. - */ - public Object getMessageHandler () - { - return messageHandler(); - } - - /** - * Returns the object registered in this editing context - * for the specified id, or null if that id is not - * registered. - */ - public Object getObjectForGlobalID ( - EOGlobalID aGlobalID ) - { - return objectForGlobalID( aGlobalID ); - } - - /** - * Returns a List of objects the meet the criteria of - * the supplied specification. - */ - public List getObjectsWithFetchSpecification ( - EOFetchSpecification aFetchSpec ) - { - return objectsWithFetchSpecification( aFetchSpec ); - } - - /** - * Returns the parent object store for this editing context. - * The result will not be null. - */ - public EOObjectStore getParentObjectStore () - { - return parentObjectStore(); - } - - /** - * Returns a List of all objects registered in this - * editing context. - */ - public List geRegisteredObjects () - { - return registeredObjects(); - } - - /** - * Returns the root object store, which is the parent - * of all parent object stores of this editing context. - */ - public EOObjectStore getRootObjectStore () - { - return rootObjectStore(); - } - - /** - * Returns a list of all objects marked as modified, - * but not inserted or deleted, in this editing context. - */ - public List getUpdatedObjects () - { - return updatedObjects(); - } - - // static methods - - public static double getDefaultFetchTimestampLag() - { - return defaultFetchTimestampLag(); - } - - /** - * Returns the default parent object store for all - * object stores created with the parameterless - * constructor. - */ - public static EOObjectStore getDefaultParentObjectStore() - { - return defaultParentObjectStore(); - } + * EditingContext provides transactional support for fetching, editing, and + * committing changes made on a collection of objects to a parent object store. + * This subclasses EOEditingContext to provide java-friendly conveniences. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public class EditingContext extends EOEditingContext { + /** + * Default constructor creates a new editing context that uses the default + * object store. If the default object store has not been set, an exception is + * thrown. + */ + public EditingContext() { + this(defaultParentObjectStore()); + } + + /** + * Creates a new editing context that uses the specified object store as its + * parent object store. + */ + public EditingContext(EOObjectStore anObjectStore) { + super(anObjectStore); + } + + /** + * Returns a List of objects associated with the object with the specified id + * for the specified property relationship, or may return a placeholder array + * that will defer the fetch until needed (aka an array fault). All objects must + * be registered in the specified editing context. This implementation calls to + * its parent object store's implementation if the requested source object is + * not registered in this editing context. The specified relationship key must + * produce a result of type Collection for the source object or an exception is + * thrown. + */ + public List getArrayFaultWithSourceGlobalID(EOGlobalID aGlobalID, String aRelationshipKey, + EOEditingContext aContext) { + return arrayFaultWithSourceGlobalID(aGlobalID, aRelationshipKey, aContext); + } + + /** + * Returns a snapshot of the specified object as it existed when it was last + * read or committed to the parent object store. + */ + public Map getCommittedSnapshotForObject(Object anObject) { + return committedSnapshotForObject(anObject); + } + + /** + * Returns a snapshot of the specified object as it existed before the edits + * triggered by the current event loop were processed. + */ + public Map getCurrentEventSnapshotForObject(Object anObject) { + return currentEventSnapshotForObject(anObject); + } + + /** + * Returns the delegate for this editing context, or null if no delegate has + * been set. + */ + public Object getDelegate() { + return delegate(); + } + + /** + * Returns a List of all objects marked as deleted in this editing context. + */ + public List getDeletedObjects() { + return deletedObjects(); + } + + /** + * Returns a List of registered editors of this editing context. + */ + public List getEditors() { + return editors(); + } + + /** + * Returns the object for the specified id. If the object's data has not been + * fetched, it will be fetched when needed. + */ + public Object getFaultForGlobalID(EOGlobalID aGlobalID) { + return faultForGlobalID(aGlobalID, this); + } + + /** + * Returns a fault representing an object of the specified entity type with + * values from the specified dictionary. + */ + public Object getFaultForRawRow(Map aDictionary, String anEntityName) { + return faultForRawRow(aDictionary, anEntityName); + } + + /** + * Returns the fetch timestamp for this editing context. + */ + public double getFetchTimestamp() { + return fetchTimestamp(); + } + + /** + * Returns the id for the specified object, or null if the object is not + * registered in this context. + */ + public EOGlobalID getGlobalIDForObject(Object anObject) { + return globalIDForObject(anObject); + } + + /** + * Returns a List of the objects that have been inserted into this editing + * context. + */ + public List getInsertedObjects() { + return insertedObjects(); + } + + /** + * Returns the message handler for this editing context, or null if no message + * handler has been set. + */ + public Object getMessageHandler() { + return messageHandler(); + } + + /** + * Returns the object registered in this editing context for the specified id, + * or null if that id is not registered. + */ + public Object getObjectForGlobalID(EOGlobalID aGlobalID) { + return objectForGlobalID(aGlobalID); + } + + /** + * Returns a List of objects the meet the criteria of the supplied + * specification. + */ + public List getObjectsWithFetchSpecification(EOFetchSpecification aFetchSpec) { + return objectsWithFetchSpecification(aFetchSpec); + } + + /** + * Returns the parent object store for this editing context. The result will not + * be null. + */ + public EOObjectStore getParentObjectStore() { + return parentObjectStore(); + } + + /** + * Returns a List of all objects registered in this editing context. + */ + public List geRegisteredObjects() { + return registeredObjects(); + } + + /** + * Returns the root object store, which is the parent of all parent object + * stores of this editing context. + */ + public EOObjectStore getRootObjectStore() { + return rootObjectStore(); + } + + /** + * Returns a list of all objects marked as modified, but not inserted or + * deleted, in this editing context. + */ + public List getUpdatedObjects() { + return updatedObjects(); + } + + // static methods + + public static double getDefaultFetchTimestampLag() { + return defaultFetchTimestampLag(); + } + + /** + * Returns the default parent object store for all object stores created with + * the parameterless constructor. + */ + public static EOObjectStore getDefaultParentObjectStore() { + return defaultParentObjectStore(); + } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.2 2003/08/06 23:07:52 chochos - * general code cleanup (mostly, removing unused imports) + * Revision 1.2 2003/08/06 23:07:52 chochos general code cleanup (mostly, + * removing unused imports) * - * Revision 1.1 2002/03/26 21:46:36 mpowers - * Contributing EditingContext as a java-friendly convenience. + * Revision 1.1 2002/03/26 21:46:36 mpowers Contributing EditingContext as a + * java-friendly convenience. * * */ - - 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. * * */ - - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/ObservableArray.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/ObservableArray.java index 19d39ff..ff66578 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/ObservableArray.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/ObservableArray.java @@ -26,321 +26,272 @@ import net.wotonomy.foundation.NSMutableArray; import net.wotonomy.foundation.NSRange; /** -* A package class that extends NSMutableArray but makes use -* of the fact that wotonomy's implementation extends ArrayList -* to intercept insertions and deletion and register and -* unregister objects for change notifications as appropriate. -* Since we can't be sure of ArrayList's implementation, we're -* forced to override each and every add and remove method, -* some of which probably call each other. However, -* EOObserverCenter will only register us once per object. -*/ -class ObservableArray extends NSMutableArray -{ - EOObserving observer; - - ObservableArray( EOObserving anObserver ) - { - observer = anObserver; - } - + * A package class that extends NSMutableArray but makes use of the fact that + * wotonomy's implementation extends ArrayList to intercept insertions and + * deletion and register and unregister objects for change notifications as + * appropriate. Since we can't be sure of ArrayList's implementation, we're + * forced to override each and every add and remove method, some of which + * probably call each other. However, EOObserverCenter will only register us + * once per object. + */ +class ObservableArray extends NSMutableArray { + EOObserving observer; + + ObservableArray(EOObserving anObserver) { + observer = anObserver; + } + /** - * Removes the last object from the array. - */ - public void removeLastObject () - { - remove( count() - 1 ); - } + * Removes the last object from the array. + */ + public void removeLastObject() { + remove(count() - 1); + } /** - * Removes the object at the specified index. - */ - public void removeObjectAtIndex (int index) - { - remove( index ); - } + * Removes the object at the specified index. + */ + public void removeObjectAtIndex(int index) { + remove(index); + } /** - * Adds all objects in the specified collection. - */ - public void addObjectsFromArray (Collection aCollection) - { - addAll( aCollection ); - } + * Adds all objects in the specified collection. + */ + public void addObjectsFromArray(Collection aCollection) { + addAll(aCollection); + } /** - * Removes all objects from the array. - */ - public void removeAllObjects () - { - clear(); - } + * Removes all objects from the array. + */ + public void removeAllObjects() { + clear(); + } /** - * Removes all objects equivalent to the specified object - * within the range of specified indices. - */ - public void removeObject (Object anObject, NSRange aRange) - { - if ( ( anObject == null ) || ( aRange == null ) ) return; - - int loc = aRange.location(); - int max = aRange.maxRange(); - for ( int i = loc; i < max; i++ ) - { - if ( anObject.equals( get( i ) ) ) - { - remove( i ); - i = i - 1; - max = max - 1; - } - } - } + * Removes all objects equivalent to the specified object within the range of + * specified indices. + */ + public void removeObject(Object anObject, NSRange aRange) { + if ((anObject == null) || (aRange == null)) + return; + + int loc = aRange.location(); + int max = aRange.maxRange(); + for (int i = loc; i < max; i++) { + if (anObject.equals(get(i))) { + remove(i); + i = i - 1; + max = max - 1; + } + } + } /** - * Removes all instances of the specified object within the - * range of specified indices, comparing by reference. - */ - public void removeIdenticalObject (Object anObject, NSRange aRange) - { - if ( ( anObject == null ) || ( aRange == null ) ) return; - - int loc = aRange.location(); - int max = aRange.maxRange(); - for ( int i = loc; i < max; i++ ) - { - if ( anObject == get( i ) ) - { - remove( i ); - i = i - 1; - max = max - 1; - } - } - } + * Removes all instances of the specified object within the range of specified + * indices, comparing by reference. + */ + public void removeIdenticalObject(Object anObject, NSRange aRange) { + if ((anObject == null) || (aRange == null)) + return; + + int loc = aRange.location(); + int max = aRange.maxRange(); + for (int i = loc; i < max; i++) { + if (anObject == get(i)) { + remove(i); + i = i - 1; + max = max - 1; + } + } + } /** - * Removes all objects in the specified collection from the array. - */ - public void removeObjectsInArray (Collection aCollection) - { - removeAll( aCollection ); - } + * Removes all objects in the specified collection from the array. + */ + public void removeObjectsInArray(Collection aCollection) { + removeAll(aCollection); + } /** - * Removes all objects in the indices within the specified range - * from the array. - */ - public void removeObjectsInRange (NSRange aRange) - { - if ( aRange == null ) return; - - for ( int i = 0; i < aRange.length(); i++ ) - { - remove( aRange.location() ); - } - } + * Removes all objects in the indices within the specified range from the array. + */ + public void removeObjectsInRange(NSRange aRange) { + if (aRange == null) + return; + + for (int i = 0; i < aRange.length(); i++) { + remove(aRange.location()); + } + } /** - * Replaces objects in the current range with objects from - * the specified range of the specified array. If currentRange - * is larger than otherRange, the extra objects are removed. - * If otherRange is larger than currentRange, the extra objects - * are added. - */ - public void replaceObjectsInRange (NSRange currentRange, - List otherArray, NSRange otherRange) - { - if ( ( currentRange == null ) || ( otherArray == null ) || - ( otherRange == null ) ) return; - + * Replaces objects in the current range with objects from the specified range + * of the specified array. If currentRange is larger than otherRange, the extra + * objects are removed. If otherRange is larger than currentRange, the extra + * objects are added. + */ + public void replaceObjectsInRange(NSRange currentRange, List otherArray, NSRange otherRange) { + if ((currentRange == null) || (otherArray == null) || (otherRange == null)) + return; + // transform otherRange if out of bounds for array - if ( otherRange.maxRange() > otherArray.size() ) - { + if (otherRange.maxRange() > otherArray.size()) { // TODO: Test this logic. - int loc = Math.min( otherRange.location(), otherArray.size() - 1 ); - otherRange = new NSRange( loc, otherArray.size() - loc ); + int loc = Math.min(otherRange.location(), otherArray.size() - 1); + otherRange = new NSRange(loc, otherArray.size() - loc); } - + Object o; - List subList = subList( - currentRange.location(), currentRange.maxRange() ); + List subList = subList(currentRange.location(), currentRange.maxRange()); int otherIndex = otherRange.location(); // TODO: Test this logic. - for ( int i = 0; i < subList.size(); i++ ) - { - if ( otherIndex < otherRange.maxRange() ) - { // set object - subList.set( i, otherArray.get( otherIndex ) ); - } - else - { // remove extra elements from currentRange - subList.remove( i ); - i--; + for (int i = 0; i < subList.size(); i++) { + if (otherIndex < otherRange.maxRange()) { // set object + subList.set(i, otherArray.get(otherIndex)); + } else { // remove extra elements from currentRange + subList.remove(i); + i--; } otherIndex++; } // TODO: Test this logic. - for ( int i = otherIndex; i < otherRange.maxRange(); i++ ) - { - add( otherArray.get( i ) ); + for (int i = otherIndex; i < otherRange.maxRange(); i++) { + add(otherArray.get(i)); } } /** - * Clears the current array and then populates it with the - * contents of the specified collection. - */ - public void setArray (Collection aCollection) - { - clear(); - addAll( aCollection ); - } + * Clears the current array and then populates it with the contents of the + * specified collection. + */ + public void setArray(Collection aCollection) { + clear(); + addAll(aCollection); + } /** - * Removes all objects equivalent to the specified object. - */ - public void removeObject (Object anObject) - { - remove( anObject ); - } + * Removes all objects equivalent to the specified object. + */ + public void removeObject(Object anObject) { + remove(anObject); + } /** - * Removes all occurences of the specified object, - * comparing by reference. - */ - public void removeIdenticalObject (Object anObject) - { - EOObserverCenter.removeObserver( observer, anObject ); - super.removeIdenticalObject( anObject ); - } + * Removes all occurences of the specified object, comparing by reference. + */ + public void removeIdenticalObject(Object anObject) { + EOObserverCenter.removeObserver(observer, anObject); + super.removeIdenticalObject(anObject); + } /** - * Inserts the specified object into this array at the - * specified index. - */ - public void insertObjectAtIndex (Object anObject, int anIndex) - { - add( anIndex, anObject ); - } - + * Inserts the specified object into this array at the specified index. + */ + public void insertObjectAtIndex(Object anObject, int anIndex) { + add(anIndex, anObject); + } + /** - * Replaces the object at the specified index with the - * specified object. - */ - public void replaceObjectAtIndex (int anIndex, Object anObject) - { - set( anIndex, anObject ); - } + * Replaces the object at the specified index with the specified object. + */ + public void replaceObjectAtIndex(int anIndex, Object anObject) { + set(anIndex, anObject); + } /** - * Adds the specified object to the end of this array. - */ - public void addObject (Object anObject) - { - add( anObject ); - } - - // interface List: mutators - - public void add(int index, Object element) - { - EOObserverCenter.addObserver( observer, element ); - super.add( index, element ); - } - - public boolean add(Object o) - { - EOObserverCenter.addObserver( observer, o ); - return super.add(o); - } - - public boolean addAll(Collection coll) - { - Iterator it = coll.iterator(); - while ( it.hasNext() ) - { - EOObserverCenter.addObserver( observer, it.next() ); - } - return super.addAll(coll); - } - - public boolean addAll(int index, Collection c) - { - Iterator it = c.iterator(); - while ( it.hasNext() ) - { - EOObserverCenter.addObserver( observer, it.next() ); - } - return super.addAll( index, c ); - } - - public void clear() - { - Iterator it = iterator(); - while ( it.hasNext() ) - { - EOObserverCenter.removeObserver( observer, it.next() ); - } - super.clear(); - } - - public Object remove(int index) - { - EOObserverCenter.removeObserver( observer, get(index) ); - return super.remove( index ); - } - - public boolean remove(Object o) - { - EOObserverCenter.removeObserver( observer, o ); - return super.remove(o); - } - - public boolean removeAll(Collection coll) - { - Iterator it = coll.iterator(); - while ( it.hasNext() ) - { - EOObserverCenter.removeObserver( observer, it.next() ); - } - return super.removeAll(coll); - } - - public boolean retainAll(Collection coll) - { - throw new UnsupportedOperationException(); - } - - public Object set(int index, Object element) - { - EOObserverCenter.removeObserver( observer, get(index) ); - EOObserverCenter.addObserver( observer, element ); - return super.set( index, element ); - } + * Adds the specified object to the end of this array. + */ + public void addObject(Object anObject) { + add(anObject); + } + + // interface List: mutators + + public void add(int index, Object element) { + EOObserverCenter.addObserver(observer, element); + super.add(index, element); + } + + public boolean add(Object o) { + EOObserverCenter.addObserver(observer, o); + return super.add(o); + } + + public boolean addAll(Collection coll) { + Iterator it = coll.iterator(); + while (it.hasNext()) { + EOObserverCenter.addObserver(observer, it.next()); + } + return super.addAll(coll); + } + + public boolean addAll(int index, Collection c) { + Iterator it = c.iterator(); + while (it.hasNext()) { + EOObserverCenter.addObserver(observer, it.next()); + } + return super.addAll(index, c); + } + + public void clear() { + Iterator it = iterator(); + while (it.hasNext()) { + EOObserverCenter.removeObserver(observer, it.next()); + } + super.clear(); + } + + public Object remove(int index) { + EOObserverCenter.removeObserver(observer, get(index)); + return super.remove(index); + } + + public boolean remove(Object o) { + EOObserverCenter.removeObserver(observer, o); + return super.remove(o); + } + + public boolean removeAll(Collection coll) { + Iterator it = coll.iterator(); + while (it.hasNext()) { + EOObserverCenter.removeObserver(observer, it.next()); + } + return super.removeAll(coll); + } + + public boolean retainAll(Collection coll) { + throw new UnsupportedOperationException(); + } + + public Object set(int index, Object element) { + EOObserverCenter.removeObserver(observer, get(index)); + EOObserverCenter.addObserver(observer, element); + return super.set(index, element); + } } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.1 2002/10/24 21:15:35 mpowers - * New implementations of NSArray and subclasses. + * Revision 1.1 2002/10/24 21:15:35 mpowers New implementations of NSArray and + * subclasses. * - * Revision 1.1 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.1 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.1 2001/01/24 14:37:24 mpowers - * Contributing a delegate useful for debugging. + * Revision 1.1 2001/01/24 14:37:24 mpowers Contributing a delegate useful for + * debugging. * * */ - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/OrderedDataSource.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/OrderedDataSource.java index 8b88615..f91e76d 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/OrderedDataSource.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/OrderedDataSource.java @@ -19,39 +19,31 @@ License along with this library; if not, see http://www.gnu.org package net.wotonomy.control; /** -* A simple extension of EODataSource that -* allows for indexed insertion. The wotonomy -* implementation of EODisplayGroup supports -* this and will use it if possible. This is -* useful for classes like the PropertyDataSource, -* where the ordering of items in an indexed -* property may be important. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 893 $ -*/ -public abstract class OrderedDataSource extends EODataSource -{ - /** - * Inserts the specified object into this data source, - * at the specified index. - */ - public abstract void insertObjectAtIndex ( - Object anObject, int anIndex ); + * A simple extension of EODataSource that allows for indexed insertion. The + * wotonomy implementation of EODisplayGroup supports this and will use it if + * possible. This is useful for classes like the PropertyDataSource, where the + * ordering of items in an indexed property may be important. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 893 $ + */ +public abstract class OrderedDataSource extends EODataSource { + /** + * Inserts the specified object into this data source, at the specified index. + */ + public abstract void insertObjectAtIndex(Object anObject, int anIndex); } /* - * $Log$ - * Revision 1.1 2006/02/16 13:19:57 cgruber - * Check in all sources in eclipse-friendly maven-enabled packages. + * $Log$ Revision 1.1 2006/02/16 13:19:57 cgruber Check in all sources in + * eclipse-friendly maven-enabled packages. * - * Revision 1.2 2003/08/06 23:07:52 chochos - * general code cleanup (mostly, removing unused imports) + * Revision 1.2 2003/08/06 23:07:52 chochos general code cleanup (mostly, + * removing unused imports) * - * Revision 1.1 2001/01/24 14:10:53 mpowers - * Contributing OrderedDataSource, and PropertyDataSource extends it. + * Revision 1.1 2001/01/24 14:10:53 mpowers Contributing OrderedDataSource, and + * PropertyDataSource extends it. * * */ - diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/PropertyDataSource.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/PropertyDataSource.java index 76f7219..c02c3e2 100644 --- a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/PropertyDataSource.java +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/PropertyDataSource.java @@ -34,516 +34,413 @@ import net.wotonomy.foundation.internal.Introspector; import net.wotonomy.foundation.internal.WotonomyException; /** -* A data source that reads and writes to an indexed -* property of a java object. This class is used by -* MasterDetailAssociation to retreive objects from -* the master display group. -* -* @author michael@mpowers.net -* @author $Author: cgruber $ -* @version $Revision: 894 $ -*/ -public class PropertyDataSource extends OrderedDataSource -{ - protected Object source; - protected String key; - protected Class lastKnownType; // for best-guessing - protected EOClassDescription classDesc; - protected EOEditingContext context; - - /** - * Creates a new PropertyDataSource with no editing context - * and will try to guess the appropriate class description - * when trying to create objects. - */ - public PropertyDataSource() - { - this( null, (EOClassDescription) null ); - } - - /** - * Creates a new PropertyDataSource that uses the specified - * editing context, but will try to guess the appropriate - * class description when trying to create objects. - */ - public PropertyDataSource( EOEditingContext aContext ) - { - this( aContext, (EOClassDescription) null ); - } - - /** - * Creates a new PropertyDataSource that uses the specified - * editing context and vends objects of the specified class. - */ - public PropertyDataSource( - EOEditingContext aContext, Class aClass ) - { - this( aContext, EOClassDescription.classDescriptionForClass( aClass ) ); - } - - /** - * Creates a new PropertyDataSource that uses the specified - * editing context and vends objects of the specified - * class description. - */ - public PropertyDataSource( - EOEditingContext aContext, EOClassDescription aClassDesc ) - { - source = null; - key = null; - lastKnownType = null; - classDesc = aClassDesc; - context = aContext; - } - - /** - * Provides the master object for detail display groups. - */ - public Object source() - { - return source; - } - - /** - * Allows a detail display group to set the master object. - */ - public void setSource( Object anObject ) - { - source = anObject; - } - - /** - * Provides the detail key for detail display groups. - */ - public String key() - { - return key; - } - - /** - * Allows a detail display group to set the detail key. - */ - public void setKey( String aKey ) - { - key = aKey; - } - - /** - * Inserts the specified object into this data source. - * Calls insertObjectAtIndex and appends to the end - * of the list. - */ - public void insertObject ( Object anObject ) - { - insertObjectAtIndex( anObject, -1 ); // trick to force to end - } - - /** - * Inserts the specified object into this data source, - * at the specified index. - */ - public void insertObjectAtIndex ( - Object anObject, int anIndex ) - { - if ( source == null ) return; - List list = readAsList(); - if ( anIndex == -1 ) anIndex = list.size(); // force to end - if ( anIndex > list.size() ) anIndex = list.size(); // force to end - list.add( anIndex, anObject ); - writeAsList( list ); - } - - /** - * Deletes the specified object from this data source. - */ - public void deleteObject ( Object anObject ) - { - if ( source == null ) return; - List list = readAsList(); - list.remove( anObject ); - writeAsList( list ); - } - - public EOEditingContext editingContext () - { - return context; - } - - /** - * Returns a List containing the objects in this - * data source. - */ - public NSArray fetchObjects () - { - if ( source == null ) return NSArray.EmptyArray; - return readAsList(); - } - - /** - * Returns a new instance of this class. - */ - public EODataSource - dataSourceQualifiedByKey ( String aKey ) - { - // determine the target class desc if possible - EOClassDescription keyClassDesc = null; - if ( classDesc != null ) - { - keyClassDesc = classDesc.classDescriptionForDestinationKey( aKey ); - } - return new PropertyDataSource( editingContext(), keyClassDesc ); - } - - /** - * Restricts this data source to vend those - * objects that are associated with the specified - * key on the specified object. - */ - public void - qualifyWithRelationshipKey ( - String aKey, Object anObject ) - { - source = anObject; - key = aKey; - } - - /** - * Returns the class description passed to the - * constructor, if any. If no class description and - * if the bound property is an indexed property, - * the type of the array is returned, otherwise - * this method returns null. This method is called - * by createObject(). - */ - public EOClassDescription - classDescriptionForObjects () - { - // just return the class description if we have one - if ( classDesc != null ) return classDesc; - - // otherwise, try to do some guesswork - EOClassDescription result = null; - - // lastKnownType is not updated here - Class type = lastKnownType; - - // if no last known type - if ( type == null ) - { - // if source and key were specified - if ( ( source != null ) && ( key != null ) ) - { - // try to get an array type - Method m = Introspector.getPropertyReadMethod( - source.getClass(), key, new Class[0] ); - if ( m != null ) - { - Class returnType = m.getReturnType(); - if ( returnType.isArray() ) - { - type = returnType.getComponentType(); - } - } - else - { - throw new WotonomyException( "Key does not exist for object: " + key + " : " + source ); - } - } - - // does not update lastKnownType because - // we prefer to get that info from a fetch. - } - - // if type has been determined - if ( type != null ) - { - result = - EOClassDescription.classDescriptionForClass( type ); - } - - return result; - } - - /** - * Calls getValue() and returns the result as a List. - * Sets lastKnownType to the retrieved type. - */ - protected NSMutableArray readAsList() - { - Object value = getValue(); - if ( value == null ) - { - return new NSMutableArray(); - } - - Object o; - NSMutableArray result = new NSMutableArray(); - boolean hasReadType = false; - lastKnownType = null; - - // if instance of array, convert to list - if ( value.getClass().isArray() ) - { - int count = Array.getLength( value ); - for ( int i = 0; i < count; i++ ) - { - o = Array.get( value, i ); - if ( o != null ) - { - // we've already found a type - if ( hasReadType ) - { - // check that this matches the last known type - if ( o.getClass() != lastKnownType ) - { - // not all of the same type: set to null - lastKnownType = null; - } - } - else // this is the first type we've found - { - // remember it - hasReadType = true; - lastKnownType = o.getClass(); - } - } - result.add( o ); + * A data source that reads and writes to an indexed property of a java object. + * This class is used by MasterDetailAssociation to retreive objects from the + * master display group. + * + * @author michael@mpowers.net + * @author $Author: cgruber $ + * @version $Revision: 894 $ + */ +public class PropertyDataSource extends OrderedDataSource { + protected Object source; + protected String key; + protected Class lastKnownType; // for best-guessing + protected EOClassDescription classDesc; + protected EOEditingContext context; + + /** + * Creates a new PropertyDataSource with no editing context and will try to + * guess the appropriate class description when trying to create objects. + */ + public PropertyDataSource() { + this(null, (EOClassDescription) null); + } + + /** + * Creates a new PropertyDataSource that uses the specified editing context, but + * will try to guess the appropriate class description when trying to create + * objects. + */ + public PropertyDataSource(EOEditingContext aContext) { + this(aContext, (EOClassDescription) null); + } + + /** + * Creates a new PropertyDataSource that uses the specified editing context and + * vends objects of the specified class. + */ + public PropertyDataSource(EOEditingContext aContext, Class aClass) { + this(aContext, EOClassDescription.classDescriptionForClass(aClass)); + } + + /** + * Creates a new PropertyDataSource that uses the specified editing context and + * vends objects of the specified class description. + */ + public PropertyDataSource(EOEditingContext aContext, EOClassDescription aClassDesc) { + source = null; + key = null; + lastKnownType = null; + classDesc = aClassDesc; + context = aContext; + } + + /** + * Provides the master object for detail display groups. + */ + public Object source() { + return source; + } + + /** + * Allows a detail display group to set the master object. + */ + public void setSource(Object anObject) { + source = anObject; + } + + /** + * Provides the detail key for detail display groups. + */ + public String key() { + return key; + } + + /** + * Allows a detail display group to set the detail key. + */ + public void setKey(String aKey) { + key = aKey; + } + + /** + * Inserts the specified object into this data source. Calls insertObjectAtIndex + * and appends to the end of the list. + */ + public void insertObject(Object anObject) { + insertObjectAtIndex(anObject, -1); // trick to force to end + } + + /** + * Inserts the specified object into this data source, at the specified index. + */ + public void insertObjectAtIndex(Object anObject, int anIndex) { + if (source == null) + return; + List list = readAsList(); + if (anIndex == -1) + anIndex = list.size(); // force to end + if (anIndex > list.size()) + anIndex = list.size(); // force to end + list.add(anIndex, anObject); + writeAsList(list); + } + + /** + * Deletes the specified object from this data source. + */ + public void deleteObject(Object anObject) { + if (source == null) + return; + List list = readAsList(); + list.remove(anObject); + writeAsList(list); + } + + public EOEditingContext editingContext() { + return context; + } + + /** + * Returns a List containing the objects in this data source. + */ + public NSArray fetchObjects() { + if (source == null) + return NSArray.EmptyArray; + return readAsList(); + } + + /** + * Returns a new instance of this class. + */ + public EODataSource dataSourceQualifiedByKey(String aKey) { + // determine the target class desc if possible + EOClassDescription keyClassDesc = null; + if (classDesc != null) { + keyClassDesc = classDesc.classDescriptionForDestinationKey(aKey); + } + return new PropertyDataSource(editingContext(), keyClassDesc); + } + + /** + * Restricts this data source to vend those objects that are associated with the + * specified key on the specified object. + */ + public void qualifyWithRelationshipKey(String aKey, Object anObject) { + source = anObject; + key = aKey; + } + + /** + * Returns the class description passed to the constructor, if any. If no class + * description and if the bound property is an indexed property, the type of the + * array is returned, otherwise this method returns null. This method is called + * by createObject(). + */ + public EOClassDescription classDescriptionForObjects() { + // just return the class description if we have one + if (classDesc != null) + return classDesc; + + // otherwise, try to do some guesswork + EOClassDescription result = null; + + // lastKnownType is not updated here + Class type = lastKnownType; + + // if no last known type + if (type == null) { + // if source and key were specified + if ((source != null) && (key != null)) { + // try to get an array type + Method m = Introspector.getPropertyReadMethod(source.getClass(), key, new Class[0]); + if (m != null) { + Class returnType = m.getReturnType(); + if (returnType.isArray()) { + type = returnType.getComponentType(); + } + } else { + throw new WotonomyException("Key does not exist for object: " + key + " : " + source); + } } + + // does not update lastKnownType because + // we prefer to get that info from a fetch. } - else - if ( value instanceof Collection ) - { + + // if type has been determined + if (type != null) { + result = EOClassDescription.classDescriptionForClass(type); + } + + return result; + } + + /** + * Calls getValue() and returns the result as a List. Sets lastKnownType to the + * retrieved type. + */ + protected NSMutableArray readAsList() { + Object value = getValue(); + if (value == null) { + return new NSMutableArray(); + } + + Object o; + NSMutableArray result = new NSMutableArray(); + boolean hasReadType = false; + lastKnownType = null; + + // if instance of array, convert to list + if (value.getClass().isArray()) { + int count = Array.getLength(value); + for (int i = 0; i < count; i++) { + o = Array.get(value, i); + if (o != null) { + // we've already found a type + if (hasReadType) { + // check that this matches the last known type + if (o.getClass() != lastKnownType) { + // not all of the same type: set to null + lastKnownType = null; + } + } else // this is the first type we've found + { + // remember it + hasReadType = true; + lastKnownType = o.getClass(); + } + } + result.add(o); + } + } else if (value instanceof Collection) { // convert to list so we handle sets, etc. - Iterator i = ((Collection)value).iterator(); - while ( i.hasNext() ) - { - o = i.next(); - if ( o != null ) - { - // we've already found a type - if ( hasReadType ) - { - // check that this matches the last known type - if ( o.getClass() != lastKnownType ) - { - // not all of the same type: set to null - lastKnownType = null; - } - } - else // this is the first type we've found - { - // remember it - hasReadType = true; - lastKnownType = o.getClass(); - } - } - result.add( o ); - } + Iterator i = ((Collection) value).iterator(); + while (i.hasNext()) { + o = i.next(); + if (o != null) { + // we've already found a type + if (hasReadType) { + // check that this matches the last known type + if (o.getClass() != lastKnownType) { + // not all of the same type: set to null + lastKnownType = null; + } + } else // this is the first type we've found + { + // remember it + hasReadType = true; + lastKnownType = o.getClass(); + } + } + result.add(o); + } + } else { + lastKnownType = null; + throw new WotonomyException("PropertyDataSource: " + "bound property was not an indexed property: " + key); } - else - { - lastKnownType = null; - throw new WotonomyException( "PropertyDataSource: " + - "bound property was not an indexed property: " + key ); + + return result; + } + + /** + * Converts the specified List to lastKnownType and calls setValue(). + */ + protected void writeAsList(List anObjectList) { + if (source == null) { + throw new WotonomyException("PropertyDataSource: " + "no source object: " + key); + } + + Class c = source.getClass(); + Method m = Introspector.getPropertyReadMethod(c, key, new Class[0]); + if (m == null) { + throw new WotonomyException("Could not read property for object: " + key + " : " + source + " (" + c + ")"); } - return result; - } - - /** - * Converts the specified List to lastKnownType - * and calls setValue(). - */ - protected void writeAsList( List anObjectList ) - { - if ( source == null ) - { - throw new WotonomyException( "PropertyDataSource: " + - "no source object: " + key ); - } - - Class c = source.getClass(); - Method m = Introspector.getPropertyReadMethod( c, key, new Class[0] ); - if ( m == null ) - { - throw new WotonomyException( "Could not read property for object: " - + key + " : " + source + " (" + c + ")" ); - } - - Class returnType = m.getReturnType(); - - int count = anObjectList.size(); - Object result = null; - - if ( returnType.isArray() ) - { - Class type = returnType.getComponentType(); - result = Array.newInstance( type, count ); - for ( int i = 0; i < count; i++ ) - { - Array.set( result, i, anObjectList.get( i ) ); - } - } - else - { - Collection collection = null; - - if ( ! returnType.isInterface() ) - { - try - { - collection = (Collection) returnType.newInstance(); - } - catch ( Exception exc ) - { - // no default constructor, leave null - } - } - - // try to find an acceptable collections type - if ( collection == null ) - { - if ( returnType.isAssignableFrom( NSMutableArray.class ) ) - { - collection = new NSMutableArray(); - } - else - if ( returnType.isAssignableFrom( LinkedList.class ) ) - { - collection = new LinkedList(); - } - else - if ( returnType.isAssignableFrom( ArrayList.class ) ) - { - collection = new ArrayList(); - } - else - if ( returnType.isAssignableFrom( HashSet.class ) ) - { - collection = new HashSet(); - } - else - if ( returnType.isAssignableFrom( TreeSet.class ) ) - { - collection = new TreeSet(); - } - } - - if ( collection == null ) - { - throw new WotonomyException( "Could not create a collection of type: " + returnType ); - } - - collection.addAll( anObjectList ); - result = collection; - } - - setValue( result ); - } - - /** - * Returns the value of the indexed property - * specified by qualifyWithRelationshipKey. - */ - protected Object getValue() - { - if ( source instanceof EOKeyValueCoding ) - { - return ((EOKeyValueCoding)source).valueForKey( key ); - } - return EOKeyValueCodingSupport.valueForKey( source, key ); - } - - /** - * Sets the value of the indexed property - * specified by qualifyWithRelationshipKey. - * The argument is assumed to be of appropriate - * type for the property. EOObserverCenter is - * notified that the object will change. - */ - protected void setValue( Object aValue ) - { - EOClassDescription sourceDesc = - EOClassDescription.classDescriptionForClass( source.getClass() ); - - - // if we're not editing a relationship (?) + Class returnType = m.getReturnType(); + + int count = anObjectList.size(); + Object result = null; + + if (returnType.isArray()) { + Class type = returnType.getComponentType(); + result = Array.newInstance(type, count); + for (int i = 0; i < count; i++) { + Array.set(result, i, anObjectList.get(i)); + } + } else { + Collection collection = null; + + if (!returnType.isInterface()) { + try { + collection = (Collection) returnType.newInstance(); + } catch (Exception exc) { + // no default constructor, leave null + } + } + + // try to find an acceptable collections type + if (collection == null) { + if (returnType.isAssignableFrom(NSMutableArray.class)) { + collection = new NSMutableArray(); + } else if (returnType.isAssignableFrom(LinkedList.class)) { + collection = new LinkedList(); + } else if (returnType.isAssignableFrom(ArrayList.class)) { + collection = new ArrayList(); + } else if (returnType.isAssignableFrom(HashSet.class)) { + collection = new HashSet(); + } else if (returnType.isAssignableFrom(TreeSet.class)) { + collection = new TreeSet(); + } + } + + if (collection == null) { + throw new WotonomyException("Could not create a collection of type: " + returnType); + } + + collection.addAll(anObjectList); + result = collection; + } + + setValue(result); + } + + /** + * Returns the value of the indexed property specified by + * qualifyWithRelationshipKey. + */ + protected Object getValue() { + if (source instanceof EOKeyValueCoding) { + return ((EOKeyValueCoding) source).valueForKey(key); + } + return EOKeyValueCodingSupport.valueForKey(source, key); + } + + /** + * Sets the value of the indexed property specified by + * qualifyWithRelationshipKey. The argument is assumed to be of appropriate type + * for the property. EOObserverCenter is notified that the object will change. + */ + protected void setValue(Object aValue) { + EOClassDescription sourceDesc = EOClassDescription.classDescriptionForClass(source.getClass()); + + // if we're not editing a relationship (?) // if ( ! sourceDesc.toManyRelationshipKeys().containsObject( key ) ) - { - // mark the parent as changed - EOObserverCenter.notifyObserversObjectWillChange( source ); - } - - - if ( source instanceof EOKeyValueCoding ) - { - ((EOKeyValueCoding)source).takeValueForKey( aValue, key ); - } - else - { - EOKeyValueCodingSupport.takeValueForKey( source, aValue, key ); - } - } - + { + // mark the parent as changed + EOObserverCenter.notifyObserversObjectWillChange(source); + } + + if (source instanceof EOKeyValueCoding) { + ((EOKeyValueCoding) source).takeValueForKey(aValue, key); + } else { + EOKeyValueCodingSupport.takeValueForKey(source, aValue, key); + } + } + } /* - * $Log$ - * Revision 1.2 2006/02/16 16:47:14 cgruber - * Move some classes in to "internal" packages and re-work imports, etc. + * $Log$ 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.14 2003/01/18 23:30:42 mpowers - * WODisplayGroup now compiles. + * Revision 1.14 2003/01/18 23:30:42 mpowers WODisplayGroup now compiles. * - * Revision 1.13 2002/10/24 21:15:36 mpowers - * New implementations of NSArray and subclasses. + * Revision 1.13 2002/10/24 21:15:36 mpowers New implementations of NSArray and + * subclasses. * - * Revision 1.12 2002/10/24 18:18:12 mpowers - * NSArray's are now considered read-only, so we can return our internal - * representation to reduce unnecessary object allocation. + * Revision 1.12 2002/10/24 18:18:12 mpowers NSArray's are now considered + * read-only, so we can return our internal representation to reduce unnecessary + * object allocation. * - * Revision 1.11 2002/04/15 21:55:33 mpowers - * Catching a condition where the get may not return the value passed to set. + * Revision 1.11 2002/04/15 21:55:33 mpowers Catching a condition where the get + * may not return the value passed to set. * - * Revision 1.10 2002/03/08 23:20:37 mpowers - * insertObject now calls insertObjectAtIndex. + * Revision 1.10 2002/03/08 23:20:37 mpowers insertObject now calls + * insertObjectAtIndex. * - * Revision 1.9 2001/06/05 19:10:41 mpowers - * Better handling of null properties. + * Revision 1.9 2001/06/05 19:10:41 mpowers Better handling of null properties. * - * Revision 1.8 2001/05/21 14:03:35 mpowers - * Added a convenience constructor for java classes. + * Revision 1.8 2001/05/21 14:03:35 mpowers Added a convenience constructor for + * java classes. * - * Revision 1.7 2001/04/30 13:15:24 mpowers - * Child contexts re-initializing objects invalidated in parent now - * propery transpose relationships. + * Revision 1.7 2001/04/30 13:15:24 mpowers Child contexts re-initializing + * objects invalidated in parent now propery transpose relationships. * - * 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.5 2001/04/28 22:17:51 mpowers - * Revised PropertyDataSource to be EOClassDescription-aware. + * Revision 1.5 2001/04/28 22:17:51 mpowers Revised PropertyDataSource to be + * EOClassDescription-aware. * - * Revision 1.4 2001/04/27 23:37:20 mpowers - * Now using EOClassDescription in the EODataSource class, as we should. + * Revision 1.4 2001/04/27 23:37:20 mpowers Now using EOClassDescription in the + * EODataSource class, as we should. * - * Revision 1.3 2001/03/29 03:29:49 mpowers - * Now using KeyValueCoding and Support instead of Introspector. + * Revision 1.3 2001/03/29 03:29:49 mpowers Now using KeyValueCoding and Support + * instead of Introspector. * - * Revision 1.2 2001/01/24 14:10:53 mpowers - * Contributing OrderedDataSource, and PropertyDataSource extends it. + * Revision 1.2 2001/01/24 14:10:53 mpowers Contributing OrderedDataSource, and + * PropertyDataSource extends it. * - * Revision 1.1.1.1 2000/12/21 15:46:50 mpowers - * Contributing wotonomy. + * Revision 1.1.1.1 2000/12/21 15:46:50 mpowers Contributing wotonomy. * - * Revision 1.3 2000/12/20 16:25:35 michael - * Added log to all files. + * Revision 1.3 2000/12/20 16:25:35 michael Added log to all files. * * */ - 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 index e12fda0..e0fe1eb 100644 --- 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 @@ -23,237 +23,202 @@ 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. -* -* -* @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 -{ + * 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. + * + * + * @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() - { + * 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 delegate object. + */ + public Surrogate(Object[] aDelegateArray) { + setDelegates(aDelegateArray); } /** - * Constructor specifying a default value. - */ - public Surrogate( Object aDefault ) - { - setDefaultValue( aDefault ); + * 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 ); + * 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; + * 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 } ); + * 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; + * 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 ) - { + * 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() - { + * 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 ) - { + * 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 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 ); + * 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 ) - { + * 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 (i = 0; i < list.length; i++) { // for each delegate - properties = - Introspector.getReadPropertiesForObject( list[i] ); - for ( j = 0; j < properties.length; j++ ) - { + properties = Introspector.getReadPropertiesForObject(list[i]); + for (j = 0; j < properties.length; j++) { // if delegate has property - if ( properties[j].equals( aKey ) ) - { + if (properties[j].equals(aKey)) { // use this delegate - return Introspector.get( list[i], aKey.toString() ); + return Introspector.get(list[i], aKey.toString()); } } } - + // return from internal map - Object result = directGet( aKey ); - if ( result == null ) - { + Object result = directGet(aKey); + if (result == null) { // if not in map, return default object result = getDefaultValue(); } - return result; + 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 ) - { + + /** + * 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 (i = 0; i < list.length; i++) { // for each delegate - properties = - Introspector.getWritePropertiesForObject( list[i] ); - for ( j = 0; j < properties.length; j++ ) - { + properties = Introspector.getWritePropertiesForObject(list[i]); + for (j = 0; j < properties.length; j++) { // if delegate has property - if ( properties[j].equals( aKey ) ) - { + if (properties[j].equals(aKey)) { // use this delegate - EOObserverCenter.notifyObserversObjectWillChange( list[i] ); - return Introspector.set( list[i], aKey.toString(), aValue ); + EOObserverCenter.notifyObserversObjectWillChange(list[i]); + return Introspector.set(list[i], aKey.toString(), aValue); } } } - + // set on internal map - EOObserverCenter.notifyObserversObjectWillChange( this ); - return directPut( aKey, aValue ); + EOObserverCenter.notifyObserversObjectWillChange(this); + return directPut(aKey, aValue); } /** - * Overridden to compare by reference. - */ - public boolean equals( Object anObject ) - { - return ( this == anObject ); + * 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. + * $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 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.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. + * Revision 1.2 2000/12/20 16:25:48 michael Added log to all files. * * */ - -- cgit v1.2.3