summaryrefslogtreecommitdiff
path: root/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access
diff options
context:
space:
mode:
authorBenjamin Culkin <scorpress@gmail.com>2024-05-19 17:56:33 -0400
committerBenjamin Culkin <scorpress@gmail.com>2024-05-19 17:56:33 -0400
commitaedc34d55462a75e329bbf342251ff6504cd117e (patch)
treebcc8f1f2352582717b484df302aeea6696b8f000 /projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access
Initial import from SVN
Diffstat (limited to 'projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access')
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessArrayFaultHandler.java71
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessFaultHandler.java66
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessGenericFaultHandler.java75
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessLock.java60
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptor.java269
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptorChannel.java244
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptorContext.java118
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptorOperation.java120
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAttribute.java381
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabase.java267
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabaseChannel.java138
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabaseContext.java568
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabaseOperation.java48
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOEntity.java637
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOEntityClassDescription.java185
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOGeneralAdaptorException.java62
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOJoin.java56
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOModel.java396
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOModelGroup.java198
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOProperty.java46
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOPropertyListEncoding.java53
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOQualifierSQLGeneration.java241
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EORelationship.java319
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOSQLExpression.java697
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOSQLExpressionFactory.java131
-rw-r--r--projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOStoredProcedure.java141
26 files changed, 5587 insertions, 0 deletions
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
new file mode 100644
index 0000000..1aafa13
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessArrayFaultHandler.java
@@ -0,0 +1,71 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+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 {
+
+ protected EOKeyGlobalID _sourceID;
+ protected String _relation;
+
+ 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)
+ */
+ public void completeInitializationOfObject(Object obj) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public String relationshipName() {
+ return _relation;
+ }
+
+ public EOKeyGlobalID sourceGlobalID() {
+ return _sourceID;
+ }
+
+}
+/*
+ * $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.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
new file mode 100644
index 0000000..d4cabe9
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessFaultHandler.java
@@ -0,0 +1,66 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+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 {
+
+ protected EOKeyGlobalID _gid;
+
+ public EOAccessFaultHandler(EOKeyGlobalID gid, EODatabaseContext dbc, EOEditingContext ec) {
+ super();
+ _gid = gid;
+ setContext(dbc, ec);
+ }
+
+ /* (non-Javadoc)
+ * @see net.wotonomy.control.EOFaultHandler#completeInitializationOfObject(java.lang.Object)
+ */
+ public void completeInitializationOfObject(Object obj) {
+ // TODO Auto-generated method stub
+
+ }
+
+ public EOKeyGlobalID globalID() {
+ return _gid;
+ }
+
+}
+/*
+ * $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.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
new file mode 100644
index 0000000..6876151
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessGenericFaultHandler.java
@@ -0,0 +1,75 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+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 $
+*/
+public abstract class EOAccessGenericFaultHandler extends EOFaultHandler {
+
+ protected EODatabaseContext _dbContext;
+ protected EOEditingContext _ec;
+
+ public EOAccessGenericFaultHandler() {
+ super();
+ }
+
+ /* (non-Javadoc)
+ * @see net.wotonomy.control.EOFaultHandler#faultWillFire(java.lang.Object)
+ */
+ public void faultWillFire(Object obj) {
+ // TODO Auto-generated method stub
+
+ }
+
+ protected void setContext(EODatabaseContext dbc, EOEditingContext ec) {
+ _dbContext = dbc;
+ _ec = ec;
+ }
+
+ public EODatabaseContext databaseContext() {
+ return _dbContext;
+ }
+
+ public EOEditingContext editingContext() {
+ return _ec;
+ }
+
+}
+/*
+ * $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.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
new file mode 100644
index 0000000..28199c5
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAccessLock.java
@@ -0,0 +1,60 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.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.
+ *
+ * @author ezamudio@nasoft.com
+ * @author $Author: cgruber $
+ * @version $Revision: 894 $
+ */
+public class EOAccessLock {
+
+ private static NSRecursiveLock _lock = new NSRecursiveLock();
+
+ private EOAccessLock() {
+ super();
+ }
+
+ public static void lock() {
+ _lock.lock();
+ }
+
+ public static void unlock() {
+ _lock.unlock();
+ }
+
+}
+/*
+ * $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.
+ *
+ * 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
+ *
+ */
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
new file mode 100644
index 0000000..28295d1
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptor.java
@@ -0,0 +1,269 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+import net.wotonomy.foundation.NSArray;
+import net.wotonomy.foundation.NSData;
+import net.wotonomy.foundation.NSDictionary;
+import net.wotonomy.foundation.NSKeyValueCoding;
+import net.wotonomy.foundation.NSMutableArray;
+import net.wotonomy.foundation.NSMutableDictionary;
+import net.wotonomy.foundation.NSTimestamp;
+
+/**
+*
+* @author ezamudio@nasoft.com
+* @author $Author: cgruber $
+* @version $Revision: 894 $
+*/
+
+public abstract class EOAdaptor {
+
+ protected String _name;
+ protected NSDictionary _connectionDictionary = NSDictionary.EmptyDictionary;
+ protected NSMutableArray _contexts = new NSMutableArray();
+ protected Class _expressionClass;
+ private static NSMutableDictionary _expressionClassesByName = new NSMutableDictionary();
+
+ public EOAdaptor(String name) {
+ super();
+ _name = name;
+ }
+
+ /**
+ * 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.
+ */
+ public static EOAdaptor adaptorWithModel(EOModel model) {
+ if (model == null)
+ throw new IllegalArgumentException("Model must not be null.");
+ if (model.adaptorName() == null || model.adaptorName().length() == 0)
+ throw new IllegalArgumentException("Cannot create an adaptor with an empty name.");
+ EOAdaptor adaptor = adaptorWithName(model.adaptorName());
+ if (adaptor == null)
+ throw new IllegalArgumentException("Cannot create adaptor with name " + model.adaptorName());
+ adaptor.setConnectionDictionary(model.connectionDictionary());
+ return adaptor;
+ }
+
+ /**
+ * 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
+ */
+ public static EOAdaptor adaptorWithName(String name) {
+ Class adaptorClass = null;
+ String cname = null;
+ if (name.endsWith("Adaptor") && name.indexOf('.') > 0) {
+ cname = name;
+ int lastdot = name.lastIndexOf('.');
+ //take off the package and the 'Adaptor' suffix
+ name = cname.substring(lastdot, cname.length() - 7);
+ } else {
+ //construct the fully qualified class name
+ cname = "net.wotonomy." + name.toLowerCase() + "adaptor." + name + "Adaptor";
+ }
+ try {
+ adaptorClass = Class.forName(cname);
+ } catch (ClassNotFoundException ex) {
+ throw new IllegalArgumentException("Cannot find class named " + name);
+ }
+ 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 });
+ } 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());
+ }
+ return adaptor;
+ }
+
+ public static void setExpressionClassName(String expClassName, String adaptorClassName) {
+ _expressionClassesByName.setObjectForKey(expClassName, adaptorClassName);
+ }
+ public static String expressionClassName(String adaptorClassName) {
+ return (String)_expressionClassesByName.objectForKey(adaptorClassName);
+ }
+
+ public void assignExternalInfoForAttribute(EOAttribute attribute) {
+ if (!attribute.isDerived()) {
+ attribute.setColumnName(attribute.name().toUpperCase());
+ }
+ assignExternalTypeForAttribute(attribute);
+ }
+
+ public void assignExternalTypeForAttribute(EOAttribute attribute) {
+ }
+
+ public void assignExternalInfoForEntity(EOEntity entity) {
+ entity.setExternalName(entity.name().toUpperCase());
+ }
+
+ 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
+ NSArray atts = e.attributes();
+ for (int j = 0; j < atts.count(); j++) {
+ EOAttribute a = (EOAttribute)atts.objectAtIndex(i);
+ assignExternalInfoForAttribute(a);
+ }
+ assignExternalInfoForEntity(e);
+ }
+ }
+
+ public boolean canServiceModel(EOModel model) {
+ NSDictionary mcd = model.connectionDictionary();
+ if (mcd == null && _connectionDictionary == null)
+ return true;
+ if (mcd == null || _connectionDictionary == null)
+ return false;
+ return mcd.equals(_connectionDictionary);
+ }
+
+ public void setConnectionDictionary(NSDictionary connection) {
+ _connectionDictionary = connection;
+ }
+ public NSDictionary connectionDictionary() {
+ return _connectionDictionary;
+ }
+
+ public NSArray contexts() {
+ return new NSArray(_contexts);
+ }
+
+ public abstract void assertConnectionDictionaryIsValid();
+
+ public abstract EOAdaptorContext createAdaptorContext();
+
+ public abstract Class defaultExpressionClass();
+
+ public abstract EOSQLExpressionFactory expressionFactory();
+
+ public abstract boolean isValidQualifierType(String typeName, EOModel model);
+
+ public Class expressionClass() {
+ if (_expressionClass != null)
+ return _expressionClass;
+ String cname = expressionClassName(name());
+ if (cname != null) {
+ try {
+ _expressionClass = Class.forName(cname);
+ } catch (ClassNotFoundException ex) {
+ throw new IllegalStateException("Cannot find expression class named " + cname);
+ }
+ }
+ return defaultExpressionClass();
+ }
+
+ public NSArray externalTypesWithModel(EOModel model) {
+ return NSArray.EmptyArray;
+ }
+
+ public NSData fetchedValueForDataValue(NSData value, EOAttribute attr) {
+ return value;
+ }
+
+ public NSTimestamp fetchedValueForDateValue(NSTimestamp value, EOAttribute attr) {
+ return value;
+ }
+
+ public Number fetchedValueForNumberValue(Number value, EOAttribute attr) {
+ return value;
+ }
+
+ public String fetchedValueForStringValue(String value, EOAttribute attr) {
+ return value;
+ }
+
+ public Object fetchedValueForValue(Object value, EOAttribute attr) {
+ if (value == NSKeyValueCoding.NullValue)
+ return value;
+ if (value instanceof String)
+ return fetchedValueForStringValue((String)value, attr);
+ if (value instanceof NSData)
+ return fetchedValueForDataValue((NSData)value, attr);
+ if (value instanceof Number)
+ return fetchedValueForNumberValue((Number)value, attr);
+ if (value instanceof NSTimestamp)
+ return fetchedValueForDateValue((NSTimestamp)value, attr);
+ return value;
+ }
+
+ public void handleDroppedConnection() {
+ for (int i = 0; i < _contexts.count(); i++) {
+ EOAdaptorContext c = (EOAdaptorContext)_contexts.objectAtIndex(i);
+ c.transactionDidRollback();
+ c.handleDroppedConnection();
+ }
+ _contexts.removeAllObjects();
+ }
+
+ public boolean hasOpenChannels() {
+ for (int i = 0; i < _contexts.count(); i++) {
+ EOAdaptorContext c = (EOAdaptorContext)_contexts.objectAtIndex(i);
+ if (c.hasOpenChannels())
+ return true;
+ }
+ return false;
+ }
+
+ public String internalTypeForExternalType(String extType, EOModel model) {
+ return null;
+ }
+
+ public boolean isDroppedConnectionException(Exception ex) {
+ return false;
+ }
+
+ public String name() {
+ return _name;
+ }
+
+ public NSArray prototypeAttributes() {
+ return NSArray.EmptyArray;
+ }
+
+}
+/*
+ * $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.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
+ *
+ */ \ 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
new file mode 100644
index 0000000..09b8a6d
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptorChannel.java
@@ -0,0 +1,244 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+import net.wotonomy.control.EOFetchSpecification;
+import net.wotonomy.control.EOQualifier;
+import net.wotonomy.foundation.NSArray;
+import net.wotonomy.foundation.NSDictionary;
+import net.wotonomy.foundation.NSMutableDictionary;
+
+/**
+*
+* @author ezamudio@nasoft.com
+* @author $Author: cgruber $
+* @version $Revision: 894 $
+*/
+public abstract class EOAdaptorChannel {
+
+ protected EOAdaptorContext _context;
+
+ public EOAdaptorChannel(EOAdaptorContext context) {
+ super();
+ _context = context;
+ }
+
+ public EOAdaptorContext adaptorContext() {
+ return _context;
+ }
+
+ public void addStoredProceduresNamed(NSArray names, EOModel model) {
+ }
+
+ public abstract NSArray attributesToFetch();
+
+ public abstract void cancelFetch();
+
+ public abstract void closeChannel();
+
+ public abstract NSArray describeResults();
+
+ public abstract int deleteRowsDescribedByQualifier(EOQualifier q, EOEntity entity);
+
+ public abstract void evaluateExpression(EOSQLExpression sql);
+
+ public abstract void executeStoredProcedure(EOStoredProcedure proc, NSDictionary values);
+
+ public abstract NSMutableDictionary fetchRow();
+
+ public abstract void insertRow(NSDictionary row, EOEntity entity);
+
+ public abstract boolean isFetchInProgress();
+
+ public abstract boolean isOpen();
+
+ public abstract void openChannel();
+
+ public abstract NSDictionary returnValuesForLastStoredProcedureInvocation();
+
+ public abstract void selectAttributes(NSArray atts, EOFetchSpecification fspec, boolean lock, EOEntity entity);
+
+ public abstract void setAttributesToFetch(NSArray atts);
+
+ public abstract int updateValuesInRowsDescribedByQualifier(NSDictionary row, EOQualifier q, EOEntity entity);
+
+ public void deleteRowDescribedByQualifier(EOQualifier q, EOEntity entity) {
+ adaptorContext().beginTransaction();
+ int count = deleteRowsDescribedByQualifier(q, entity);
+ if (count != 1) {
+ adaptorContext().rollbackTransaction();
+ throw new EOGeneralAdaptorException("Qualifier deleted " + count + " rows instead of exactly one.");
+ }
+ adaptorContext().commitTransaction();
+ }
+
+ public EOModel describeModelWithTableNames(NSArray names) {
+ return null;
+ }
+
+ public NSArray describeStoredProcedureNames() {
+ return NSArray.EmptyArray;
+ }
+
+ public NSArray describeTableNames() {
+ return NSArray.EmptyArray;
+ }
+
+ 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();
+ return new NSMutableDictionary(values, keys);
+ }
+
+ public void lockRowComparingAttributes(NSArray atts, EOEntity entity, EOQualifier q, NSDictionary snapshot) {
+ EOFetchSpecification fspec = new EOFetchSpecification(entity.name(), q, null);
+ adaptorContext().beginTransaction();
+ selectAttributes(atts, fspec, true, entity);
+ if (isFetchInProgress()) {
+ NSDictionary row = fetchRow();
+ if (row == null) {
+ cancelFetch();
+ adaptorContext().rollbackTransaction();
+ throw new EOGeneralAdaptorException("Cannot obtain row to lock. Probably modified from the outside.");
+ }
+ if (isFetchInProgress()) {
+ if (fetchRow() != null) {
+ cancelFetch();
+ adaptorContext().rollbackTransaction();
+ throw new EOGeneralAdaptorException("Qualifier returns more than one row.");
+ }
+ }
+ java.util.Enumeration enumeration = snapshot.keyEnumerator();
+ while (enumeration.hasMoreElements()) {
+ Object key = enumeration.nextElement();
+ Object svalue = snapshot.objectForKey(key);
+ Object rvalue = row.objectForKey(key);
+ if (rvalue == null) {
+ cancelFetch();
+ adaptorContext().rollbackTransaction();
+ throw new EOGeneralAdaptorException("Value for key " + key + " not found in locked row.");
+ }
+ if (!rvalue.equals(svalue)) {
+ cancelFetch();
+ adaptorContext().rollbackTransaction();
+ throw new EOGeneralAdaptorException("Value for key " + key + " differes from snapshot.");
+ }
+ }
+ adaptorContext().commitTransaction();
+ return;
+ }
+ adaptorContext().rollbackTransaction();
+ throw new EOGeneralAdaptorException("A fetch was never generated.");
+ }
+
+ 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.",
+ new NSDictionary(operation, "operation"));
+ 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.",
+ 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.",
+ new NSDictionary(operation, "operation"));
+ 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.",
+ new NSDictionary(operation, "operation"));
+ 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.",
+ 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.",
+ 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,
+ new NSDictionary(operation, "operation"));
+ }
+ }
+
+ public void performAdaptorOperations(NSArray ops) {
+ for (int i = 0; i < ops.count(); i++) {
+ EOAdaptorOperation adop = (EOAdaptorOperation)ops.objectAtIndex(i);
+ performAdaptorOperation(adop);
+ }
+ }
+
+ public NSArray primaryKeysForNewRowsWithEntity(int count, EOEntity entity) {
+ NSDictionary[] keys = new NSDictionary[count];
+ for (int i = 0; i < count; i++)
+ keys[i] = NSDictionary.EmptyDictionary;
+ return new NSArray(keys);
+ }
+
+ public void updateValuesInRowDescribedByQualifier(NSDictionary row, EOQualifier q, EOEntity entity) {
+ adaptorContext().beginTransaction();
+ int count = updateValuesInRowsDescribedByQualifier(row, q, entity);
+ if (count != 1) {
+ adaptorContext().rollbackTransaction();
+ 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.
+ *
+ * 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.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
+ *
+ */ \ 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
new file mode 100644
index 0000000..aff0ddd
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptorContext.java
@@ -0,0 +1,118 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+import net.wotonomy.foundation.NSArray;
+import net.wotonomy.foundation.NSMutableArray;
+import net.wotonomy.foundation.NSNotificationCenter;
+
+/**
+*
+* @author ezamudio@nasoft.com
+* @author $Author: cgruber $
+* @version $Revision: 894 $
+*/
+
+public abstract class EOAdaptorContext {
+
+ public static final String AdaptorContextBeginTransactionNotification = "AdaptorContextBeginTransaction";
+ public static final String AdaptorContextCommitTransactionNotification = "AdaptorContextCommitTransaction";
+ public static final String AdaptorContextRollbackTransactionNotification = "AdaptorContextRollbackTransaction";
+
+ protected EOAdaptor _adaptor;
+ protected NSMutableArray _channels = new NSMutableArray();
+ protected boolean _hasOpenTransaction;
+
+ public EOAdaptorContext(EOAdaptor adaptor) {
+ super();
+ _adaptor = adaptor;
+ }
+
+ public EOAdaptor adaptor() {
+ return _adaptor;
+ }
+
+ public abstract void beginTransaction();
+
+ public abstract void commitTransaction();
+
+ public abstract void rollbackTransaction();
+
+ public abstract EOAdaptorChannel createAdaptorChannel();
+
+ public abstract void handleDroppedConnection();
+
+ public NSArray channels() {
+ return new NSArray(_channels);
+ }
+
+ public boolean hasBusyChannels() {
+ for (int i = 0; i < _channels.count(); i++) {
+ EOAdaptorChannel chan = (EOAdaptorChannel)_channels.objectAtIndex(i);
+ if (chan.isFetchInProgress())
+ return true;
+ }
+ return false;
+ }
+
+ public boolean hasOpenChannels() {
+ for (int i = 0; i < _channels.count(); i++) {
+ EOAdaptorChannel chan = (EOAdaptorChannel)_channels.objectAtIndex(i);
+ if (chan.isOpen())
+ return true;
+ }
+ return false;
+ }
+
+ public boolean hasOpenTransaction() {
+ return _hasOpenTransaction;
+ }
+
+ public void transactionDidBegin() {
+ _hasOpenTransaction = true;
+ NSNotificationCenter.defaultCenter().postNotification(
+ AdaptorContextBeginTransactionNotification, this);
+ }
+
+ public void transactionDidCommit() {
+ _hasOpenTransaction = false;
+ NSNotificationCenter.defaultCenter().postNotification(
+ AdaptorContextCommitTransactionNotification, this);
+ }
+
+ public void transactionDidRollback() {
+ _hasOpenTransaction = false;
+ 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.
+ *
+ * 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 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
new file mode 100644
index 0000000..818985d
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAdaptorOperation.java
@@ -0,0 +1,120 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+import net.wotonomy.control.EOQualifier;
+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 $
+*/
+public class EOAdaptorOperation {
+
+ protected EOEntity _entity;
+ protected NSArray _attributes;
+ protected NSDictionary _changedValues;
+ protected Throwable _exception;
+ protected EOQualifier _qualifier;
+ protected EOStoredProcedure _proc;
+ protected int _adaptorOp;
+
+ public EOAdaptorOperation(EOEntity entity) {
+ super();
+ _entity = entity;
+ }
+
+ public void setAdaptorOperator(int adOp) {
+ _adaptorOp = adOp;
+ }
+ public int adaptorOperator() {
+ return _adaptorOp;
+ }
+
+ public void setAttributes(NSArray atts) {
+ _attributes = atts;
+ }
+ public NSArray attributes() {
+ return _attributes;
+ }
+
+ public void setChangedValues(NSDictionary values) {
+ _changedValues = values;
+ }
+ public NSDictionary changedValues() {
+ return _changedValues;
+ }
+
+ public int compareAdaptorOperation(EOAdaptorOperation op) {
+ if (op.entity() != null && entity() != null) {
+ if (!op.entity().name().equals(entity().name()))
+ op.entity().name().compareTo(entity().name());
+ }
+ if (adaptorOperator() < op.adaptorOperator())
+ return -1;
+ if (adaptorOperator() > op.adaptorOperator())
+ return 1;
+ return 0;
+ }
+
+ public EOEntity entity() {
+ return _entity;
+ }
+
+ public void setException(Throwable t) {
+ _exception = t;
+ }
+ public Throwable exception() {
+ return _exception;
+ }
+
+ public void setQualifier(EOQualifier q) {
+ _qualifier = q;
+ }
+ public EOQualifier qualifier() {
+ return _qualifier;
+ }
+
+ 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.
+ *
+ * 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 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
new file mode 100644
index 0000000..8b651ec
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOAttribute.java
@@ -0,0 +1,381 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+import net.wotonomy.foundation.NSDictionary;
+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 $
+*/
+public class EOAttribute extends EOProperty implements EOPropertyListEncoding {
+
+ //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;
+ public static final int InOutParameter = 3;
+
+ protected EOEntity _entity;
+ protected String _name;
+ protected String _columnName;
+ protected String _definition;
+ protected String _className;
+ protected String _externalType;
+ protected Class _valueClass;
+ protected String _valueClassName;
+ protected String _valueType;
+ protected String _valueFactoryMethodName;
+ protected String _readFormat;
+ protected String _writeFormat;
+ protected String _prototypeName;
+ protected EOAttribute _prototype;
+ protected NSSelector _valueFactoryMethod;
+ protected boolean _allowsNull;
+ protected boolean _readOnly;
+ protected boolean _isFlattened;
+ protected boolean _knowsIfFlattened;
+ protected int _precision;
+ protected int _scale;
+ protected int _width;
+ protected int _parameterDirection;
+ protected NSDictionary _internalInfo;
+ protected NSDictionary _userInfo;
+
+ protected boolean _has_allowsNull;
+
+ public EOAttribute() {
+ super();
+ _allowsNull = true;
+ }
+
+ public EOAttribute(NSDictionary dict, Object obj) {
+ super();
+ if (obj instanceof EOEntity)
+ _entity = (EOEntity)obj;
+ setName((String)dict.objectForKey("name"));
+ if (dict.objectForKey("columnName") != null)
+ 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");
+ if (dict.objectForKey("precision") != null)
+ setPrecision(Integer.parseInt((String)dict.objectForKey("precision")));
+ if (dict.objectForKey("scale") != null)
+ setScale(Integer.parseInt((String)dict.objectForKey("scale")));
+ if (dict.objectForKey("width") != null)
+ setWidth(Integer.parseInt((String)dict.objectForKey("width")));
+ if (dict.objectForKey("parameterDirection") != null)
+ setParameterDirection(Integer.parseInt((String)dict.objectForKey("parameterDirection")));
+ setAllowsNull("Y".equals(dict.objectForKey("allowsNull")));
+ }
+
+ void setEntity(EOEntity value) {
+ _entity = value;
+ }
+
+ public void setName(String name) {
+ _name = name;
+ }
+ public String name() {
+ return _name;
+ }
+
+ public void setColumnName(String name) {
+ _columnName = name;
+ }
+ public String columnName() {
+ if (_columnName != null)
+ return _columnName;
+ if (prototype() != null)
+ if (_prototype.columnName() != null)
+ return _prototype.columnName();
+ return null;
+ }
+
+ public void setClassName(String name) {
+ _className = name;
+ }
+ public String className() {
+ if (_className != null)
+ return _className;
+ if (prototype() != null)
+ if (_prototype.className() != null)
+ return _prototype.className();
+ return null;
+ }
+
+ public void setDefinition(String def) {
+ _definition = def;
+ _columnName = null;
+ }
+ public String definition() {
+ if (_definition != null)
+ return _definition;
+ if (prototype() != null)
+ if (_prototype.definition() != null)
+ return _prototype.definition();
+ return null;
+ }
+
+ public void setExternalType(String type) {
+ _externalType = type;
+ }
+ public String externalType() {
+ if (_externalType != null)
+ return _externalType;
+ if (prototype() != null)
+ if (_prototype.externalType() != null)
+ return _prototype.externalType();
+ return null;
+ }
+
+ public void setAllowsNull(boolean flag) {
+ _allowsNull = flag;
+ _has_allowsNull = true;
+ }
+ public boolean allowsNull() {
+ if (_has_allowsNull)
+ return _allowsNull;
+ if (prototype() != null)
+ return _prototype.allowsNull();
+ return _allowsNull;
+ }
+
+ public void setReadOnly(boolean flag) {
+ _readOnly = flag;
+ }
+ public boolean readOnly() {
+ return _readOnly;
+ }
+
+ public void setPrototype(EOAttribute proto) {
+ _prototype = proto;
+ if (proto != null)
+ _prototypeName = proto.name();
+ else
+ _prototypeName = null;
+ }
+ public EOAttribute prototype() {
+ if (_prototypeName != null && _prototype == null) {
+ try {
+ EOModel m = _entity.model();
+ EOModelGroup g = m.modelGroup();
+ EOEntity protos = g.entityNamed("EO" + m.adaptorName() + "Prototypes");
+ if (protos == null)
+ protos = g.entityNamed("EOPrototypes");
+ _prototype = protos.attributeNamed(_prototypeName);
+ } catch (NullPointerException e) {
+ }
+ }
+ return _prototype;
+ }
+
+ public void setPrecision(int value) {
+ _precision = value;
+ }
+ public int precision() {
+ if (_precision > 0)
+ return _precision;
+ if (prototype() != null)
+ return _prototype.precision();
+ return _precision;
+ }
+
+ public void setScale(int value) {
+ _scale = value;
+ }
+ public int scale() {
+ if (_scale > 0)
+ return _scale;
+ if (prototype() != null)
+ return _prototype.scale();
+ return _scale;
+ }
+
+ public void setWidth(int value) {
+ _width = value;
+ }
+ public int width() {
+ if (_width > 0)
+ return _width;
+ if (prototype() != null)
+ return _prototype.width();
+ return _width;
+ }
+
+ /** @deprecated Use setClassName instead. */
+ public void setValueClassName(String name) {
+ setClassName(name);
+ }
+ /** @deprecated Use className() instead. */
+ public String valueClassName() {
+ return className();
+ }
+
+ public void setValueType(String type) {
+ _valueType = type;
+ }
+ public String valueType() {
+ if (_valueType != null)
+ return _valueType;
+ if (prototype() != null)
+ return _prototype.valueType();
+ return null;
+ }
+
+ public void setReadFormat(String value) {
+ _readFormat = value;
+ }
+ public String readFormat() {
+ return _readFormat;
+ }
+
+ public void setWriteFormat(String value) {
+ _writeFormat = value;
+ }
+ public String writeFormat() {
+ return _writeFormat;
+ }
+
+ public boolean isDerived() {
+ 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.
+ * @return true if the receiver is flattened.
+ */
+ public boolean isFlattened() {
+ if (_knowsIfFlattened)
+ return _isFlattened;
+ _knowsIfFlattened = true;
+ if (definition() == null)
+ return false;
+ _isFlattened = (entity()._attributeForPath(definition()) != null);
+ return _isFlattened;
+ }
+
+ public EOEntity entity() {
+ return _entity;
+ }
+
+ public void setParameterDirection(int dir) {
+ _parameterDirection = dir;
+ }
+ public int parameterDirection() {
+ return _parameterDirection;
+ }
+
+ public String relationshipPath() {
+ if (isFlattened())
+ return definition();
+ return null;
+ }
+
+ public void setUserInfo(NSDictionary value) {
+ _userInfo = value;
+ }
+ public NSDictionary userInfo() {
+ return _userInfo;
+ }
+
+ public void awakeWithPropertyList(NSDictionary plist) {
+ }
+
+ public void encodeIntoPropertyList(NSMutableDictionary dict) {
+ dict.setObjectForKey(name(), "name");
+ if (_prototypeName != null)
+ dict.setObjectForKey(_prototypeName, "prototypeName");
+ if (_columnName != null)
+ dict.setObjectForKey(_columnName, "columnName");
+ if (_definition != null)
+ dict.setObjectForKey(_definition, "definition");
+ if (_className != null)
+ dict.setObjectForKey(_className, "valueClassName");
+ if (_valueType != null)
+ dict.setObjectForKey(_valueType, "valueType");
+ if (_precision > 0)
+ dict.setObjectForKey(new Integer(_precision), "precision");
+ if (_scale > 0)
+ dict.setObjectForKey(new Integer(_scale), "scale");
+ if (_width > 0)
+ dict.setObjectForKey(new Integer(_width), "width");
+ if (_externalType != null)
+ dict.setObjectForKey(_externalType, "externalType");
+ if (_readFormat != null)
+ dict.setObjectForKey(_readFormat, "readFormat");
+ if (_writeFormat != null)
+ dict.setObjectForKey(_writeFormat, "writeFormat");
+ if (_allowsNull)
+ dict.setObjectForKey("Y", "allowsNull");
+ if (_entity == null)
+ dict.setObjectForKey(new Integer(parameterDirection()), "parameterDirection");
+ if (userInfo() != null && userInfo().count() > 0)
+ dict.setObjectForKey(userInfo(), "userInfo");
+ if (_internalInfo != null && _internalInfo.count() > 0)
+ dict.setObjectForKey(_internalInfo, "internalInfo");
+ }
+
+}
+/*
+ * $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.
+ *
+ * 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.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.4 2003/08/09 01:35:35 chochos
+ * implement EOPropertyListEncoding
+ *
+ * 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.1 2003/08/07 02:39:45 chochos
+ * EOAttribute. Can be initialized from a property list.
+ *
+*/ \ 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
new file mode 100644
index 0000000..a9177c5
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabase.java
@@ -0,0 +1,267 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+import java.util.Enumeration;
+
+import net.wotonomy.control.EOEnterpriseObject;
+import net.wotonomy.control.EOGlobalID;
+import net.wotonomy.foundation.NSArray;
+import net.wotonomy.foundation.NSDictionary;
+import net.wotonomy.foundation.NSMutableArray;
+import net.wotonomy.foundation.NSMutableDictionary;
+import net.wotonomy.foundation.NSTimestamp;
+
+/**
+*
+* @author ezamudio@nasoft.com
+* @author $Author: cgruber $
+* @version $Revision: 894 $
+*/
+public class EODatabase {
+
+ protected EOAdaptor _adaptor;
+ protected NSMutableArray _models = new NSMutableArray();
+ protected NSMutableArray _contexts = new NSMutableArray();
+ protected NSMutableDictionary _resultCache = new NSMutableDictionary();
+ protected NSMutableDictionary _snapshots = new NSMutableDictionary();
+ protected NSTimestamp _timestamp;
+ protected static boolean _releaseUnrefSnapshots = true;
+
+ public EODatabase(EOAdaptor adaptor) {
+ super();
+ if (adaptor == null)
+ throw new IllegalArgumentException("Adaptor cannot be null.");
+ _adaptor = adaptor;
+ }
+
+ public EODatabase(EOModel model) {
+ super();
+ _adaptor = EOAdaptor.adaptorWithModel(model);
+ addModel(model);
+ }
+
+ public EOAdaptor adaptor() {
+ return _adaptor;
+ }
+
+ public void addModel(EOModel model) {
+ if (!addModelIfCompatible(model))
+ throw new IllegalArgumentException("Model is not compatible with this database.");
+ }
+
+ public void removeMode(EOModel model) {
+ _models.removeObject(model);
+ }
+
+ public boolean addModelIfCompatible(EOModel model) {
+ if (_models.containsObject(model))
+ return false;
+ if (model.adaptorName().equals(adaptor().name())) {
+ if (adaptor().canServiceModel(model)) {
+ _models.addObject(model);
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public void decrementSnapshotCountForGlobalID(EOGlobalID gid) {
+ if (_releaseUnrefSnapshots) {
+ }
+ }
+
+ public void incrementSnapshotCountForGlobalID(EOGlobalID gid) {
+ if (_releaseUnrefSnapshots) {
+ }
+ }
+
+ public static void disableSnapshotRefCounting() {
+ _releaseUnrefSnapshots = false;
+ }
+
+ public EOEntity entityForObject(EOEnterpriseObject eo) {
+ String cname = eo.getClass().getName();
+ for (int i = 0; i < _models.count(); 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);
+ if (e.className().equals(cname))
+ return e;
+ }
+ }
+ return null;
+ }
+
+ public EOEntity entityNamed(String name) {
+ for (int i = 0; i < _models.count(); 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);
+ if (e.name().equals(name))
+ return e;
+ }
+ }
+ return null;
+ }
+
+ public void forgetAllSnapshots() {
+ _snapshots.removeAllObjects();
+ }
+
+ public void forgetSnapshotForGlobalID(EOGlobalID gid) {
+ _snapshots.removeObjectForKey(gid);
+ }
+
+ public void forgetSnapshotsForGlobalIDs(NSArray gids) {
+ for (int i = 0; i < gids.count(); 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);
+ c.handleDroppedConnection();
+ }
+ }
+
+ public void invalidateResultCache() {
+ _resultCache.removeAllObjects();
+ }
+
+ public void invalidateResultCacheForEntityNamed(String name) {
+ _resultCache.removeObjectForKey(name);
+ }
+
+ public NSArray models() {
+ return new NSArray(_models);
+ }
+
+ public void recordSnapshotForGlobalID(NSDictionary snap, EOGlobalID gid) {
+ _snapshots.setObjectForKey(snap, gid);
+ }
+
+ public void recordSnapshotForSourceGlobalID(NSArray gids, EOGlobalID gid, String name) {
+ NSMutableDictionary d = (NSMutableDictionary)_snapshots.objectForKey(gid);
+ if (d == null) {
+ d = new NSMutableDictionary();
+ _snapshots.setObjectForKey(d, gid);
+ }
+ d.setObjectForKey(gids, name);
+ }
+
+ public void recordSnapshots(NSDictionary snaps) {
+ _snapshots.addEntriesFromDictionary(snaps);
+ }
+
+ public void recordToManySnapshots(NSDictionary snaps) {
+ Enumeration enumeration = snaps.keyEnumerator();
+ while (enumeration.hasMoreElements()) {
+ 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);
+ recordSnapshotForSourceGlobalID(gids, gid, relName);
+ }
+ }
+ }
+
+ public void registerContext(EODatabaseContext context) {
+ if (!_contexts.contains(context)) {
+ if (context.database() != this)
+ throw new IllegalStateException("Cannot register context assigned to a different database.");
+ _contexts.addObject(context);
+ }
+ }
+
+ public void unregisterContext(EODatabaseContext context) {
+ _contexts.removeObject(context);
+ }
+
+ public NSArray registeredContexts() {
+ return new NSArray(_contexts);
+ }
+
+ public NSArray resultCacheForEntityNamed(String name) {
+ return (NSArray)_resultCache.objectForKey(name);
+ }
+
+ public void setResultCache(NSArray cache, String entityName) {
+ _resultCache.setObjectForKey(cache, entityName);
+ }
+
+ public void setTimestampToNow() {
+ _timestamp = new NSTimestamp();
+ }
+
+ public NSDictionary snapshotForGlobalID(EOGlobalID gid) {
+ return (NSDictionary)_snapshots.objectForKey(gid);
+ }
+
+ public NSDictionary snapshotForGlobalID(EOGlobalID gid, long l) {
+ return null;
+ }
+
+ public NSArray snapshotForSourceGlobalID(EOGlobalID gid, String name) {
+ NSDictionary d = (NSDictionary)_snapshots.objectForKey(gid);
+ if (d == null)
+ return null;
+ return (NSArray)d.objectForKey(name);
+ }
+
+ public NSDictionary snapshotForSourceGlobalID(EOGlobalID gid, String s, long l) {
+ return null;
+ }
+
+ public NSDictionary snapshots() {
+ return _snapshots;
+ }
+
+ public long timestampForGlobalID(EOGlobalID gid) {
+ return NSTimestamp.DistantPast.timeIntervalSinceReferenceDate();
+ }
+
+ public long timestampForSourceGlobalID(EOGlobalID gid, String s) {
+ return 0;
+ }
+
+}
+/*
+ * $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.
+ *
+ * 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
+ *
+ * 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...
+ *
+ */ \ 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
new file mode 100644
index 0000000..10424e9
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabaseChannel.java
@@ -0,0 +1,138 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+import net.wotonomy.control.EOClassDescription;
+import net.wotonomy.control.EOEditingContext;
+import net.wotonomy.control.EOFetchSpecification;
+import net.wotonomy.control.EOGlobalID;
+import net.wotonomy.control.EOKeyValueCodingAdditions;
+import net.wotonomy.foundation.NSArray;
+import net.wotonomy.foundation.NSDictionary;
+import net.wotonomy.foundation.NSMutableArray;
+
+/**
+*
+* @author ezamudio@nasoft.com
+* @author $Author: cgruber $
+* @version $Revision: 894 $
+*/
+public class EODatabaseChannel {
+
+ protected EODatabaseContext _context;
+ protected EOAdaptorChannel _channel;
+ protected EOEntity _currEntity;
+ protected EOEditingContext _currEC;
+ protected NSArray _attributes;
+ protected boolean _locking;
+ protected boolean _refreshing;
+
+ public EODatabaseChannel(EODatabaseContext context) {
+ super();
+ _context = context;
+ _channel = _context.adaptorContext().createAdaptorChannel();
+ }
+
+ public EOAdaptorChannel adaptorChannel() {
+ return _channel;
+ }
+
+ public EODatabaseContext databaseContext() {
+ return _context;
+ }
+
+ public void cancelFetch() {
+ _channel.cancelFetch();
+ }
+
+ public Object fetchObject() {
+ NSDictionary r = _channel.fetchRow();
+ EOGlobalID gid = _currEntity.globalIDForRow(r);
+ Object eo = _currEC.objectForGlobalID(gid);
+ if (eo == null) {
+ eo = EOClassDescription.classDescriptionForEntityName(_currEntity.name()).createInstanceWithEditingContext(_currEC, gid);
+ if (eo instanceof EOKeyValueCodingAdditions)
+ ((EOKeyValueCodingAdditions)eo).takeValuesFromDictionary(r);
+ else
+ EOKeyValueCodingAdditions.DefaultImplementation.takeValuesFromDictionary(eo, r);
+ } else {
+ if (isRefreshingObjects()) {
+ //TODO: refresh object (how?)
+ }
+ }
+ return eo;
+ }
+
+ public boolean isFetchInProgress() {
+ return _channel.isFetchInProgress();
+ }
+
+ public void setIsLocking(boolean flag) {
+ _locking = flag;
+ }
+
+ public boolean isLocking() {
+ return _locking;
+ }
+
+ public void setIsRefreshingObjects(boolean flag) {
+ _refreshing = flag;
+ }
+
+ public boolean isRefreshingObjects() {
+ return _refreshing;
+ }
+
+ public void selectObjectsWithFetchSpecification(EOFetchSpecification fspec, EOEditingContext ec) {
+ setIsLocking(fspec.locksObjects());
+ setIsRefreshingObjects(fspec.refreshesRefetchedObjects());
+ setCurrentEditingContext(ec);
+ setCurrentEntity(databaseContext().database().entityNamed(fspec.entityName()));
+ NSMutableArray atts = new NSMutableArray();
+ atts.addObjectsFromArray(_currEntity.attributes());
+ adaptorChannel().selectAttributes(atts, fspec, isLocking(), _currEntity);
+ adaptorChannel().setAttributesToFetch(atts);
+ _attributes = atts;
+ }
+
+ public void setCurrentEditingContext(EOEditingContext ec) {
+ _currEC = ec;
+ }
+
+ public void setCurrentEntity(EOEntity entity) {
+ _currEntity = entity;
+ }
+
+}
+/*
+ * $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.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...
+ *
+ */ \ 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
new file mode 100644
index 0000000..af696fe
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabaseContext.java
@@ -0,0 +1,568 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+import java.util.Enumeration;
+import java.util.List;
+import java.util.Map;
+
+import net.wotonomy.control.EOAndQualifier;
+import net.wotonomy.control.EOCooperatingObjectStore;
+import net.wotonomy.control.EOEditingContext;
+import net.wotonomy.control.EOEnterpriseObject;
+import net.wotonomy.control.EOFaultHandler;
+import net.wotonomy.control.EOFaulting;
+import net.wotonomy.control.EOFetchSpecification;
+import net.wotonomy.control.EOGlobalID;
+import net.wotonomy.control.EOKeyGlobalID;
+import net.wotonomy.control.EOKeyValueCoding;
+import net.wotonomy.control.EOKeyValueCodingSupport;
+import net.wotonomy.control.EOKeyValueQualifier;
+import net.wotonomy.control.EOObjectStoreCoordinator;
+import net.wotonomy.control.EOQualifier;
+import net.wotonomy.foundation.NSArray;
+import net.wotonomy.foundation.NSDictionary;
+import net.wotonomy.foundation.NSLocking;
+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 {
+
+ private static Class _contextClass;
+ protected EODatabase _database;
+ protected EOAdaptorContext _context;
+ protected NSMutableArray _channels = new NSMutableArray();
+ protected NSMutableArray _lockedObjects = new NSMutableArray();
+
+ protected NSMutableDictionary _simpleSnaps;
+ protected NSMutableDictionary _manySnaps;
+
+ protected EOObjectStoreCoordinator _coordinator;
+ protected EOEditingContext _currEC;
+ protected int _updateStrategy;
+
+ public EODatabaseContext(EODatabase database) {
+ super();
+ _database = database;
+ _context = _database.adaptor().createAdaptorContext();
+ }
+
+ public EOAdaptorContext adaptorContext() {
+ return _context;
+ }
+
+ public EODatabase database() {
+ return _database;
+ }
+
+ public EODatabaseChannel availableChannel() {
+ for (int i = 0; i < _channels.count(); i++) {
+ EODatabaseChannel c = (EODatabaseChannel)_channels.objectAtIndex(i);
+ if (!c.isFetchInProgress())
+ return c;
+ }
+ EODatabaseChannel c = new EODatabaseChannel(this);
+ registerChannel(c);
+ return c;
+ }
+
+ public void batchFetchRelationship(EORelationship rel, NSArray arr, EOEditingContext ec) {
+ }
+
+ public static void setContextClassToRegister(Class contextClass) {
+ _contextClass = contextClass;
+ }
+ public static Class contextClassToRegister() {
+ if (_contextClass == null)
+ _contextClass = EODatabaseContext.class;
+ return _contextClass;
+ }
+
+ public EOObjectStoreCoordinator coordinator() {
+ return _coordinator;
+ }
+
+ public void editingContextDidForgetObjectWithGlobalID(EOEditingContext ec, EOGlobalID gid) {
+ database().decrementSnapshotCountForGlobalID(gid);
+ }
+
+ public void handleDroppedConnection() {
+ //TODO: unregister channels
+ adaptorContext().handleDroppedConnection();
+ }
+
+ /* (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);
+ }
+
+ /* (non-Javadoc)
+ * @see net.wotonomy.control.EOCooperatingObjectStore#ownsObject(net.wotonomy.control.EOEnterpriseObject)
+ */
+ public boolean ownsObject(EOEnterpriseObject eo) {
+ if (eo.entityName() == null)
+ return false;
+ return (database().entityNamed(eo.entityName()) != null);
+ }
+
+ /* (non-Javadoc)
+ * @see net.wotonomy.control.EOCooperatingObjectStore#handlesFetchSpecification(net.wotonomy.control.EOFetchSpecification)
+ */
+ public boolean handlesFetchSpecification(EOFetchSpecification fspec) {
+ String ename = fspec.entityName();
+ return (database().entityNamed(ename) != null);
+ }
+
+ public boolean hasBusyChannels() {
+ return adaptorContext().hasBusyChannels();
+ }
+
+ /* (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
+ _coordinator = coord;
+ _currEC = ec;
+ }
+
+ /* (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)
+ */
+ public void recordUpdateForObject(EOEnterpriseObject eo, NSDictionary changes) {
+ // TODO Auto-generated method stub
+ }
+
+ public void recordSnapshotForGlobalID(NSDictionary snap, EOGlobalID gid) {
+ if (_simpleSnaps == null)
+ throw new IllegalArgumentException("Attempt to record a snapshot without a transaction in progress");
+ _simpleSnaps.setObjectForKey(snap, gid);
+ }
+
+ 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);
+ if (d == null) {
+ d = new NSMutableDictionary();
+ _manySnaps.setObjectForKey(d, gid);
+ }
+ d.setObjectForKey(gids, relationName);
+ }
+
+ public void recordSnapshots(NSDictionary snaps) {
+ 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);
+ }*/
+ }
+
+ public void recordToManySnapshots(NSDictionary snaps) {
+ if (_manySnaps == null)
+ throw new IllegalArgumentException("Attempt to record snapshots without a transaction in progress.");
+ Enumeration enumeration = snaps.keyEnumerator();
+ while (enumeration.hasMoreElements()) {
+ Object key = enumeration.nextElement();
+ 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
+ d2.addEntriesFromDictionary(d);
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see net.wotonomy.control.EOCooperatingObjectStore#performChanges()
+ */
+ public void performChanges() {
+ // TODO Auto-generated method stub
+
+ }
+
+ /* (non-Javadoc)
+ * @see net.wotonomy.control.EOCooperatingObjectStore#commitChanges()
+ */
+ public void commitChanges() {
+ adaptorContext().commitTransaction();
+ }
+
+ /* (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)
+ */
+ public NSDictionary valuesForKeys(NSArray keys, EOEnterpriseObject eo) {
+ // TODO check snapshots; eo could be a fault
+ return eo.valuesForKeys(keys);
+ }
+
+ /* (non-Javadoc)
+ * @see net.wotonomy.foundation.NSLocking#lock()
+ */
+ public void lock() {
+ EOAccessLock.lock();
+ }
+
+ /* (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)
+ */
+ 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);
+ return new NSArray(handler);
+ }
+
+ /* (non-Javadoc)
+ * @see net.wotonomy.control.EOObjectStore#faultForGlobalID(net.wotonomy.control.EOGlobalID, net.wotonomy.control.EOEditingContext)
+ */
+ 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());
+ 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)
+ */
+ public /*EOEnterpriseObject*/ Object faultForRawRow(Map row, String entityName, EOEditingContext ec) {
+ EOEntity e = database().entityNamed(entityName);
+ EOGlobalID gid = e.globalIDForRow(row);
+ return faultForGlobalID(gid, ec);
+ }
+
+ public void forgetSnapshotForGlobalID(EOGlobalID gid) {
+ if (_simpleSnaps == null)
+ throw new IllegalArgumentException("Attempt to forget snapshot with no transaction in progress.");
+ _simpleSnaps.removeObjectForKey(gid);
+ _manySnaps.removeObjectForKey(gid);
+ }
+
+ public void forgetSnapshotsForGlobalIDs(List gids) {
+ for (int i = 0; i < gids.size(); 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)
+ */
+ 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());
+ NSArray props = e.classProperties();
+ for (int i = 0; i < props.count(); 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() );
+ }
+ } else if (p instanceof EORelationship) {
+ if (((EORelationship)p).isToMany()) {
+ val = arrayFaultWithSourceGlobalID(gid, p.name(), ec);
+ } else {
+ 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() );
+ }
+ }
+ }
+ }
+
+ /* (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)
+ */
+ public void invalidateObjectsWithGlobalIDs(List aList) {
+ forgetSnapshotsForGlobalIDs(aList);
+ }
+
+ /* (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);
+ }
+
+ public boolean isObjectLockedWithGlobalID(EOGlobalID gid) {
+ return _lockedObjects.containsObject(gid);
+ }
+
+ /* (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);
+ if (snap == null)
+ return;
+ if (!(gid instanceof EOKeyGlobalID))
+ return;
+ EOEntity e = database().entityNamed(((EOKeyGlobalID)gid).entityName());
+ EOQualifier q = e.qualifierForPrimaryKey(snap);
+ EOFetchSpecification fspec = new EOFetchSpecification(e.name(), q, null);
+ fspec.setLocksObjects(true);
+ NSArray arr = ec.objectsWithFetchSpecification(fspec);
+ if (arr.count() != 1)
+ 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)
+ */
+ 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
+ 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);
+ 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
+ } else
+ return value;
+ }
+
+ //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());
+
+ //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);
+ 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);
+ } else {
+ q = new EOAndQualifier(subq);
+ }
+ EOFetchSpecification fspec = new EOFetchSpecification(rel.destinationEntity().name(), q, null);
+ NSArray res = ec.objectsWithFetchSpecification(fspec, ec);
+ NSMutableArray gids = new NSMutableArray(res.count());
+ for (int i = 0; i < res.count(); i++)
+ gids.addObject(ec.globalIDForObject(res.objectAtIndex(i)));
+ recordSnapshotForSourceGlobalID(gids, gid, relationName);
+ return res;
+ }
+
+ /* (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();
+ channel.selectObjectsWithFetchSpecification(fspec, ec);
+ NSMutableArray arr = new NSMutableArray();
+ while (channel.isFetchInProgress()) {
+ Object o = channel.fetchObject();
+ if (o != null) {
+ arr.addObject(o);
+ }
+ }
+ return arr;
+ }
+
+ /* (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));
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see net.wotonomy.control.EOObjectStore#saveChangesInEditingContext(net.wotonomy.control.EOEditingContext)
+ */
+ public void saveChangesInEditingContext(EOEditingContext ec) {
+ prepareForSaveWithCoordinator(null, ec);
+ recordChangesInEditingContext();
+ performChanges();
+ commitChanges();
+ }
+
+ public void registerChannel(EODatabaseChannel channel) {
+ if (channel.databaseContext() != this)
+ throw new IllegalArgumentException("Cannot register a channel on a context other than its own.");
+ if (_channels.containsObject(channel))
+ throw new IllegalArgumentException("Attempt to register a channel more than once.");
+ _channels.addObject(channel);
+ }
+
+ public void unregisterChannel(EODatabaseChannel channel) {
+ if (channel.databaseContext() != this)
+ throw new IllegalArgumentException("Attempt to unregister a channel from a context other than its own.");
+ _channels.removeObject(channel);
+ }
+
+ public NSArray registeredChannels() {
+ return new NSArray(_channels);
+ }
+
+ public NSDictionary snapshotForGlobalID(EOGlobalID gid) {
+ NSDictionary d = null;
+ if (_simpleSnaps != null) {
+ d = (NSDictionary)_simpleSnaps.objectForKey(gid);
+ }
+ if (d == null)
+ d = database().snapshotForGlobalID(gid);
+ return d;
+ }
+
+ public NSArray snapshotForSourceGlobalID(EOGlobalID gid, String name) {
+ NSArray a = null;
+ if (_manySnaps != null) {
+ NSDictionary d = (NSDictionary)_manySnaps.objectForKey(gid);
+ a = (NSArray)d.objectForKey(name);
+ }
+ if (a == null)
+ a = database().snapshotForSourceGlobalID(gid, name);
+ return a;
+ }
+
+ public void setUpdateStrategy(int strategy) {
+ _updateStrategy = strategy;
+ }
+
+ public int updateStrategy() {
+ return _updateStrategy;
+ }
+
+}
+/*
+ * $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.
+ *
+ * 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
+ *
+ * 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.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.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
new file mode 100644
index 0000000..596180e
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EODatabaseOperation.java
@@ -0,0 +1,48 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+/**
+*
+* @author ezamudio@nasoft.com
+* @author $Author: cgruber $
+* @version $Revision: 893 $
+*/
+public class EODatabaseOperation {
+
+ public static final int AdaptorLockOperator = 0;
+ public static final int AdaptorInsertOperator = 1;
+ public static final int AdaptorUpdateOperator = 2;
+ public static final int AdaptorDeleteOperator = 3;
+ public static final int AdaptorStoredProcedureOperator = 4;
+
+ public static final int DatabaseNothingOperator = 0;
+ public static final int DatabaseInsertOperator = 1;
+ public static final int DatabaseUpdateOperator = 2;
+ public static final int DatabaseDeleteOperator = 3;
+
+}
+/*
+ * $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.
+ *
+ */ \ 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
new file mode 100644
index 0000000..4adc4a1
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOEntity.java
@@ -0,0 +1,637 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.util.Map;
+
+import net.wotonomy.control.EOAndQualifier;
+import net.wotonomy.control.EOClassDescription;
+import net.wotonomy.control.EOFetchSpecification;
+import net.wotonomy.control.EOGenericRecord;
+import net.wotonomy.control.EOGlobalID;
+import net.wotonomy.control.EOIntegralKeyGlobalID;
+import net.wotonomy.control.EOKeyGlobalID;
+import net.wotonomy.control.EOKeyValueArchiver;
+import net.wotonomy.control.EOKeyValueQualifier;
+import net.wotonomy.control.EOKeyValueUnarchiver;
+import net.wotonomy.control.EOQualifier;
+import net.wotonomy.control.EOVectorKeyGlobalID;
+import net.wotonomy.foundation.NSArray;
+import net.wotonomy.foundation.NSDictionary;
+import net.wotonomy.foundation.NSKeyValueCoding;
+import net.wotonomy.foundation.NSMutableArray;
+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 $
+*/
+public class EOEntity implements EOPropertyListEncoding {
+
+ protected NSMutableDictionary _attributes = new NSMutableDictionary();
+ protected NSMutableDictionary _relations = new NSMutableDictionary();
+ private NSMutableArray _classPropertyNames = new NSMutableArray();
+ private NSMutableArray _classProperties = new NSMutableArray();
+ private NSMutableArray _classPropertyAttributes = new NSMutableArray();
+ private NSMutableArray _classPropertyManyRelationships = new NSMutableArray();
+ private NSMutableArray _classPropertyOneRelationships = new NSMutableArray();
+ protected NSArray _pkAttributes = NSArray.EmptyArray;
+ protected NSArray _pkAttributeNames = NSArray.EmptyArray;
+ protected NSMutableDictionary _fetchSpecs = new NSMutableDictionary();
+ protected NSMutableArray _lockingAttributes = new NSMutableArray();
+
+ protected String _className;
+ protected String _name;
+ protected String _externalName;
+ protected boolean _isAbstract;
+ protected boolean _isReadOnly;
+ protected EOModel _model;
+ protected NSDictionary _userInfo;
+ protected NSDictionary _internalInfo;
+ private boolean _loadedFetchSpecs;
+
+ public EOEntity() {
+ super();
+ }
+
+ 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"));
+ if (dict.objectForKey("internalInfo") != null)
+ _internalInfo = (NSDictionary)dict.objectForKey("internalInfo");
+ if (dict.objectForKey("userInfo") != null)
+ _userInfo = (NSDictionary)dict.objectForKey("userInfo");
+
+ //Read the attributes
+ NSArray atr = (NSArray)dict.objectForKey("attributes");
+ for (int i = 0; i < atr.count(); i++) {
+ NSDictionary d = (NSDictionary)atr.objectAtIndex(i);
+ EOAttribute atrib = new EOAttribute(d, this);
+ addAttribute(atrib);
+ }
+
+ //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));
+ pka.addObject(a);
+ }
+ _pkAttributes = new NSArray(pka);
+ _pkAttributeNames = atr;
+
+ //attributes used for locking
+ _lockingAttributes.removeAllObjects();
+ atr = (NSArray)dict.objectForKey("attributesUsedForLocking");
+ for (int i = 0; i < atr.count(); i++) {
+ String x = (String)atr.objectAtIndex(i);
+ EOAttribute a = attributeNamed(x);
+ _lockingAttributes.addObject(a);
+ }
+
+ //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");
+ if (atr != null) {
+ for (int i = 0; i < atr.count(); i++) {
+ NSDictionary d = (NSDictionary)atr.objectAtIndex(i);
+ EORelationship rel = new EORelationship(d, this);
+ addRelationship(rel);
+ }
+ }
+ }
+
+ public void addAttribute(EOAttribute atr) {
+ if (atr.name() == null)
+ throw new IllegalArgumentException("Cannot add an unnamed attribute to an entity.");
+ if (_attributes.objectForKey(atr.name()) != null)
+ throw new IllegalArgumentException("Entity " + name() + " already has an attribute named " + atr.name());
+ _attributes.setObjectForKey(atr, atr.name());
+ atr.setEntity(this);
+ _lockingAttributes.addObject(atr);
+ _classProperties.addObject(atr);
+ _classPropertyNames.addObject(atr.name());
+ _classPropertyAttributes.addObject(atr);
+ }
+
+ public void removeAttribute(EOAttribute atr) {
+ _attributes.removeObjectForKey(atr.name());
+ atr.setEntity(null);
+ _classProperties.removeObject(atr);
+ _classPropertyNames.removeObject(atr.name());
+ _classPropertyAttributes.removeObject(atr);
+ }
+
+ public void addFetchSpecification(EOFetchSpecification fspec, String name) {
+ loadFetchSpecifications();
+ if (_fetchSpecs.objectForKey(name) != null)
+ throw new IllegalArgumentException("Entity " + name() + " already has a fetch specification named " + name);
+ _fetchSpecs.setObjectForKey(fspec, name);
+ }
+
+ public void removeFetchSpecificationNamed(String name) {
+ _fetchSpecs.removeObjectForKey(name);
+ }
+
+ public EOFetchSpecification fetchSpecificationNamed(String name) {
+ loadFetchSpecifications();
+ return (EOFetchSpecification)_fetchSpecs.objectForKey(name);
+ }
+
+ public NSArray fetchSpecificationNames() {
+ loadFetchSpecifications();
+ return _fetchSpecs.allKeys();
+ }
+
+ /** Loads fetch specifications from the .fspec file,
+ * if one exists.
+ */
+ private void loadFetchSpecifications() {
+ if (_loadedFetchSpecs)
+ return;
+ _loadedFetchSpecs = true;
+ if (model().path() == null)
+ return;
+ File f = new File(model().path());
+ //Read the fetch specification file, if it exists
+ f = new File(f, name() + ".fspec");
+ if (!f.exists())
+ return;
+ NSDictionary fdict = null;
+ String x = null;
+ try {
+ FileInputStream fin = new FileInputStream(f);
+ byte[] b = new byte[fin.available()];
+ fin.read(b);
+ fin.close();
+ x = new String(b);
+ } catch (IOException ex) {
+ throw new IllegalArgumentException("Cannot read file " + f);
+ }
+ fdict = NSPropertyListSerialization.dictionaryForString(x);
+ if (fdict == null)
+ throw new IllegalArgumentException("Cannot read dictionary from " + f);
+ NSArray keys = fdict.allKeys();
+
+ //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);
+ if (fs != null)
+ _fetchSpecs.setObjectForKey(fs, k);
+ }
+ }
+
+ public NSArray attributes() {
+ return _attributes.allValues();
+ }
+
+ public EOAttribute attributeNamed(String name) {
+ return (EOAttribute)_attributes.objectForKey(name);
+ }
+
+ public NSArray flattenedAttributes() {
+ return null;
+ }
+
+ public void setClassName(String name) {
+ _className = name;
+ }
+ public String className() {
+ return _className;
+ }
+
+ public void setName(String name) {
+ _name = name;
+ }
+ public String name() {
+ return _name;
+ }
+
+ public void setExternalName(String name) {
+ _externalName = name;
+ }
+ public String externalName() {
+ return _externalName;
+ }
+
+ public void addRelationship(EORelationship rel) {
+ if (rel.name() == null)
+ throw new IllegalArgumentException("Cannot add an unnamed relationship to an entity.");
+ if (_relations.objectForKey(rel.name()) != null)
+ throw new IllegalArgumentException("Entity " + name() + " already has a relationship named " + rel.name());
+ if (_attributes.objectForKey(rel.name()) != null)
+ throw new IllegalArgumentException("Entity " + name() + " has an attribute named " + rel.name());
+ _relations.setObjectForKey(rel, rel.name());
+ _classProperties.addObject(rel);
+ _classPropertyNames.addObject(rel.name());
+ if (rel.isToMany())
+ _classPropertyManyRelationships.addObject(rel);
+ else
+ _classPropertyOneRelationships.addObject(rel);
+ }
+
+ public void removeRelationship(EORelationship rel) {
+ _relations.removeObjectForKey(rel.name());
+ _classProperties.removeObject(rel);
+ _classPropertyNames.removeObject(rel.name());
+ _classPropertyManyRelationships.removeObject(rel);
+ _classPropertyOneRelationships.removeObject(rel);
+ }
+
+ /** Returns the relationships from this entity to other entities.
+ * @return An array of the relationships of this entity.
+ */
+ public NSArray relationships() {
+ return _relations.allValues();
+ }
+
+ public EORelationship relationshipNamed(String name) {
+ return (EORelationship)_relations.objectForKey(name);
+ }
+ public EOModel model() {
+ return _model;
+ }
+
+ public void setPrimaryKeyAtributes(NSArray pk) {
+ _pkAttributes = pk;
+ }
+ public NSArray primaryKeyAttributes() {
+ return _pkAttributes;
+ }
+
+ public NSArray primaryKeyAttributeNames() {
+ if (_pkAttributeNames.count() != _pkAttributes.count()) {
+ NSMutableArray arr = new NSMutableArray();
+ for (int i = 0; i < _pkAttributes.count(); i++) {
+ EOAttribute a = (EOAttribute)_pkAttributes.objectAtIndex(i);
+ arr.addObject(a.name());
+ }
+ _pkAttributeNames = new NSArray(arr);
+ }
+ return _pkAttributeNames;
+ }
+
+ public boolean hasSimplePrimaryKey() {
+ return _pkAttributes.count() == 1;
+ }
+
+ public boolean isValidPrimaryKeyAttribute(EOAttribute attr) {
+ return !attr.allowsNull();
+ }
+
+ public void setAttributesUsedForLocking(NSArray value) {
+ _lockingAttributes.removeAllObjects();
+ _lockingAttributes.addObjectsFromArray(value);
+ }
+ public NSArray attributesUsedForLocking() {
+ return new NSArray(_lockingAttributes);
+ }
+
+ public void setClassProperties(NSArray value) {
+ _classProperties.removeAllObjects();
+ _classProperties.addObjectsFromArray(value);
+ _classPropertyNames.removeAllObjects();
+ _classPropertyAttributes.removeAllObjects();
+ _classPropertyOneRelationships.removeAllObjects();
+ _classPropertyManyRelationships.removeAllObjects();
+ for (int i = 0; i < value.count(); 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())
+ _classPropertyManyRelationships.addObject(o);
+ else
+ _classPropertyOneRelationships.addObject(o);
+ }
+ }
+ }
+ public NSArray classProperties() {
+ if (_classProperties == null) {
+ if (_classPropertyNames == null)
+ return NSArray.EmptyArray;
+ else {
+ NSMutableArray props = new NSMutableArray();
+ NSMutableArray atribs = new NSMutableArray();
+ NSMutableArray ones = new NSMutableArray();
+ NSMutableArray manies = new NSMutableArray();
+ for (int i = 0; i < _classPropertyNames.count(); i++) {
+ String name = (String)_classPropertyNames.objectAtIndex(i);
+ EOAttribute a = attributeNamed(name);
+ EORelationship r = relationshipNamed(name);
+ if (a != null) {
+ props.addObject(a);
+ atribs.addObject(a);
+ } else if (r != null) {
+ props.addObject(r);
+ if (r.isToMany())
+ manies.addObject(r);
+ else
+ ones.addObject(r);
+ } else
+ throw new IllegalArgumentException("Cannot find attribute or relationship named " + name);
+ }
+ _classProperties = props;
+ _classPropertyAttributes = atribs;
+ _classPropertyOneRelationships = ones;
+ _classPropertyManyRelationships = manies;
+ }
+ }
+ return _classProperties;
+ }
+
+ public NSArray classPropertyNames() {
+ return _classPropertyNames;
+ }
+
+ public NSArray classPropertyAttributeNames() {
+ 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);
+ arr.addObject(a.name());
+ }
+ return arr;
+ }
+
+ public NSArray classPropertyToManyRelationshipNames() {
+ 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);
+ arr.addObject(a.name());
+ }
+ return arr;
+ }
+
+ public NSArray classPropertyToOneRelationshipNames() {
+ 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);
+ arr.addObject(a.name());
+ }
+ return arr;
+ }
+
+ public void setIsAbstractEntity(boolean flag) {
+ _isAbstract = flag;
+ }
+ public boolean isAbstractEntity() {
+ return _isAbstract;
+ }
+
+ 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;
+ }
+
+ public NSArray subEntities() {
+ return null;
+ }
+
+ public NSArray attributesToFetch() {
+ return attributes();
+ }
+
+ public NSArray externalModelsReferenced() {
+ return null;
+ }
+
+ public EOClassDescription classDescriptionForInstances() {
+ EOClassDescription cd = EOClassDescription.classDescriptionForEntityName(name());
+ if (cd == null) {
+ cd = new EOEntityClassDescription(this);
+ Class cl = null;
+ try {
+ cl = Class.forName(className());
+ } catch (ClassNotFoundException ex) {
+ cl = EOGenericRecord.class;
+ }
+ EOClassDescription.registerClassDescription(cd, cl);
+ }
+ return cd;
+ }
+
+ /**
+ * 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.
+ */
+ public EOGlobalID globalIDForRow(Map row) {
+ 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));
+ gid = new EOIntegralKeyGlobalID(name(), n);
+ } else {
+ Object[] vals = new Object[pknames.count()];
+ for (int i = 0; i < pknames.count(); i++) {
+ Object v = row.get(pknames.objectAtIndex(i));
+ vals[i] = v;
+ }
+ gid = new EOVectorKeyGlobalID(name(), vals);
+ }
+ return gid;
+ }
+
+ /**
+ * 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();
+ NSArray pknames = primaryKeyAttributeNames();
+ return new NSDictionary(vals, pknames.toArray());
+ }
+
+ public EOQualifier qualifierForPrimaryKey(Map pkey) {
+ NSArray pknames = primaryKeyAttributeNames();
+ EOQualifier q = null;
+ NSMutableArray subq = new NSMutableArray(pknames.count());
+ for (int i = 0; i < pknames.count(); 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);
+ else
+ q = new EOAndQualifier(subq);
+ return q;
+ }
+
+ public void setUserInfo(NSDictionary value) {
+ _userInfo = value;
+ }
+ public NSDictionary userInfo() {
+ return _userInfo;
+ }
+
+ public void awakeWithPropertyList(NSDictionary plist) {
+ }
+
+ public void encodeIntoPropertyList(NSMutableDictionary dict) {
+ dict.setObjectForKey(name(), "name");
+ dict.setObjectForKey(externalName(), "externalName");
+ dict.setObjectForKey(className(), "className");
+
+ //Encode attributes
+ NSMutableArray arr = new NSMutableArray(_attributes.allValues());
+ for (int i = 0; i < _attributes.count(); i++) {
+ EOAttribute a = (EOAttribute)arr.objectAtIndex(i);
+ NSMutableDictionary d = new NSMutableDictionary();
+ a.encodeIntoPropertyList(d);
+ arr.replaceObjectAtIndex(i, d);
+ }
+ dict.setObjectForKey(arr, "attributes");
+ //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);
+ NSMutableDictionary d = new NSMutableDictionary();
+ r.encodeIntoPropertyList(d);
+ arr.replaceObjectAtIndex(i, d);
+ }
+ dict.setObjectForKey(arr, "relationships");
+ }
+
+ //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);
+ EOKeyValueArchiver arch = new EOKeyValueArchiver();
+ f.encodeWithKeyValueArchiver(arch);
+ d.setObjectForKey(arch.dictionary(), k);
+ }
+ dict.setObjectForKey(d, "fetchSpecificationDictionary");
+
+ //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());
+ dict.setObjectForKey(arr, "attributesUsedForLocking");
+ if (_userInfo != null && _userInfo.count() > 0 )
+ dict.setObjectForKey(_userInfo, "userInfo");
+ if (_internalInfo != null && _internalInfo.count() > 0 )
+ dict.setObjectForKey(_internalInfo, "internalInfo");
+ }
+
+ public EOAttribute _attributeForPath(String path) {
+ NSArray comps = NSArray.componentsSeparatedByString(path, ".");
+ if (comps.count() < 2)
+ return null;
+ EORelationship r = null;
+ EOEntity e = this;
+ 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());
+ }
+
+}
+/*
+ * $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.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.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.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.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.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
new file mode 100644
index 0000000..a235c99
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOEntityClassDescription.java
@@ -0,0 +1,185 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2001 Intersect Software Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+package net.wotonomy.access;
+
+import net.wotonomy.control.EOClassDescription;
+import net.wotonomy.control.EOEditingContext;
+import net.wotonomy.control.EOFetchSpecification;
+import net.wotonomy.control.EOGenericRecord;
+import net.wotonomy.control.EOGlobalID;
+import net.wotonomy.foundation.NSArray;
+import net.wotonomy.foundation.NSMutableArray;
+
+/**
+* @author ezamudio@nasoft.com
+* @author $Author: cgruber $
+* @version $Revision: 894 $
+*/
+public class EOEntityClassDescription extends EOClassDescription {
+
+ protected EOEntity _entity;
+
+ public EOEntityClassDescription() {
+ super();
+ }
+
+ public EOEntityClassDescription(EOEntity entity) {
+ this();
+ _entity = entity;
+ }
+
+ public NSArray allAttributeKeys() {
+ NSArray arr = entity().attributes();
+ NSMutableArray a = new NSMutableArray(arr.count());
+ for (int i = 0; i < arr.count(); i++) {
+ EOAttribute atrib = (EOAttribute)arr.objectAtIndex(i);
+ a.addObject(atrib);
+ }
+ return a;
+ }
+
+ public NSArray allPropertyKeys() {
+ return entity().classPropertyNames();
+ }
+
+ public NSArray allToManyRelationshipKeys() {
+ NSArray arr = entity().relationships();
+ NSMutableArray a = new NSMutableArray(arr.count());
+ for (int i = 0; i < arr.count(); i++) {
+ EORelationship r = (EORelationship)arr.objectAtIndex(i);
+ if (r.isToMany())
+ a.addObject(r);
+ }
+ return a;
+ }
+
+ public NSArray allToOneRelationshipKeys() {
+ NSArray arr = entity().relationships();
+ NSMutableArray a = new NSMutableArray(arr.count());
+ for (int i = 0; i < arr.count(); 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.
+ */
+ 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);
+ if (!atrib.isDerived())
+ a.addObject(atrib);
+ }
+ return a;
+ }
+
+ public EOClassDescription classDescriptionForDestinationKey(String key) {
+ EORelationship r = entity().relationshipNamed(key);
+ if (r == null)
+ return null;
+ return r.destinationEntity().classDescriptionForInstances();
+ }
+
+ public NSArray clientAttributeKeys() {
+ return null;
+ }
+
+ public NSArray clientToManyRelationshipKeys() {
+ return null;
+ }
+
+ public NSArray clientToOneRelationshipKeys() {
+ return null;
+ }
+
+ public EOEntity entity() {
+ return _entity;
+ }
+
+ public String entityName() {
+ return _entity.name();
+ }
+
+ public EOFetchSpecification fetchSpecificationNamed(String name) {
+ return entity().fetchSpecificationNamed(name);
+ }
+
+ public NSArray toManyRelationshipKeys() {
+ NSArray arr = entity().relationships();
+ NSMutableArray a = new NSMutableArray(arr.count());
+ for (int i = 0; i < arr.count(); i++) {
+ EORelationship r = (EORelationship)arr.objectAtIndex(i);
+ if (r.isToMany() && !r.isFlattened())
+ a.addObject(r);
+ }
+ return a;
+ }
+
+ public NSArray toOneRelationshipKeys() {
+ NSArray arr = entity().relationships();
+ NSMutableArray a = new NSMutableArray(arr.count());
+ for (int i = 0; i < arr.count(); i++) {
+ EORelationship r = (EORelationship)arr.objectAtIndex(i);
+ if (!r.isToMany() && !r.isFlattened())
+ a.addObject(r);
+ }
+ return a;
+ }
+
+ public Object createInstanceWithEditingContext(EOEditingContext ec, EOGlobalID gid) {
+ if (theClass == null) {
+ try {
+ theClass = Class.forName(entity().className());
+ } catch (ClassNotFoundException ex) {
+ if (entity().className().equals("net.wotonomy.control.EOGenericRecord"))
+ throw new IllegalArgumentException("Cannot find class " + entity().className());
+ theClass = EOGenericRecord.class;
+ }
+ }
+ return super.createInstanceWithEditingContext(ec, gid);
+ }
+
+}
+/*
+ * $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.
+ *
+ * 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.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.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
new file mode 100644
index 0000000..6c48a3f
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOGeneralAdaptorException.java
@@ -0,0 +1,62 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+import net.wotonomy.foundation.NSDictionary;
+
+/**
+* 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;
+
+ public EOGeneralAdaptorException(String msg) {
+ super(msg);
+ }
+
+ public EOGeneralAdaptorException(String name, NSDictionary userInfo) {
+ super(name);
+ _userInfo = userInfo;
+ }
+
+ public EOGeneralAdaptorException(String selectorName, String className, String msg) {
+ super(msg);
+ _userInfo = new NSDictionary(
+ new Object[]{ selectorName, className },
+ new Object[]{ "selectorName", "className" });
+ }
+
+ public NSDictionary userInfo() {
+ return _userInfo;
+ }
+
+}
+/*
+ * $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
+ *
+ */ \ 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
new file mode 100644
index 0000000..693a7d0
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOJoin.java
@@ -0,0 +1,56 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+/**
+* 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;
+ protected EOAttribute _destination;
+
+ public EOJoin(EOAttribute src, EOAttribute dst) {
+ super();
+ _source = src;
+ _destination = dst;
+ }
+
+ public EOAttribute sourceAttribute() {
+ return _source;
+ }
+
+ public EOAttribute destinationAttribute() {
+ return _destination;
+ }
+
+ /*
+ * $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.
+ *
+ */
+}
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
new file mode 100644
index 0000000..46fc8d0
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOModel.java
@@ -0,0 +1,396 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.util.Enumeration;
+
+import net.wotonomy.foundation.NSArray;
+import net.wotonomy.foundation.NSDictionary;
+import net.wotonomy.foundation.NSMutableArray;
+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 $
+*/
+public class EOModel {
+
+ protected static final String IDX_NAME = "index.eomodeld";
+
+ //This array contains dictionaries with "className" and "name"
+ protected NSMutableArray _entities = new NSMutableArray();
+ protected NSMutableDictionary _entitiesByName = new NSMutableDictionary();
+ protected NSMutableDictionary _entitiesByClass = new NSMutableDictionary();
+ protected NSDictionary _connectionDictionary = NSDictionary.EmptyDictionary;
+ protected String _adaptorName = "JDBC";
+ protected NSMutableDictionary _prototypesByName = new NSMutableDictionary();
+ protected NSMutableDictionary _storedProcedures = new NSMutableDictionary();
+ protected NSMutableArray _storedProcedureNames = new NSMutableArray();
+ protected NSDictionary _userInfo = NSDictionary.EmptyDictionary;
+ protected String _name;
+ protected String _path;
+ protected NSDictionary _internalInfo = NSDictionary.EmptyDictionary;
+ protected EOModelGroup _group;
+
+ public EOModel() {
+ super();
+ }
+
+ public EOModel(NSDictionary dict, Object o) {
+ this();
+ }
+
+ public EOModel(String path) {
+ this();
+ File f = new File(path);
+ _path = f.getAbsolutePath();
+ if (!(f.exists() && f.isDirectory()))
+ throw new IllegalArgumentException("The path is invalid (" + f + ")");
+ _name = f.getName();
+ f = new File(f, "index.eomodeld");
+ if (!(f.exists() && f.isFile()))
+ throw new IllegalArgumentException("Cannot find " + f);
+ String x = null;
+ try {
+ FileInputStream in = new FileInputStream(f);
+ byte[] b = new byte[in.available()];
+ in.read(b);
+ in.close();
+ x = new String(b);
+ } catch (IOException e) {
+ throw new IllegalArgumentException("Cannot read index.eomodeld");
+ }
+ NSDictionary d = NSPropertyListSerialization.dictionaryForString(x);
+ 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();
+ if (d.objectForKey("storedProcedures") != null)
+ _storedProcedureNames.addObjectsFromArray((NSArray)d.objectForKey("storedProcedures"));
+ if (d.objectForKey("internalInfo") != null)
+ _internalInfo = (NSDictionary)d.objectForKey("internalInfo");
+ if (d.objectForKey("userInfo") != null)
+ _userInfo = (NSDictionary)d.objectForKey("userInfo");
+ entityNamed("EOPrototypes");
+ }
+
+ public void setConnectionDictionary(NSDictionary dict) {
+ _connectionDictionary = dict;
+ }
+ public NSDictionary connectionDictionary() {
+ return _connectionDictionary;
+ }
+
+ public void addEntity(EOEntity ent) {
+ _entitiesByName.setObjectForKey(ent, ent.name());
+ _entitiesByClass.setObjectForKey(ent, ent.className());
+ }
+
+ public void removeEntity(EOEntity ent) {
+ _entitiesByName.removeObjectForKey(ent.name());
+ _entitiesByClass.removeObjectForKey(ent.className());
+ }
+
+ public void addStoredProcedure(EOStoredProcedure proc) {
+ if (!_storedProcedureNames.containsObject(proc))
+ _storedProcedureNames.addObject(proc);
+ _storedProcedures.setObjectForKey(proc, proc.name());
+ }
+
+ public void removeStoredProcedure(EOStoredProcedure proc) {
+ _storedProcedureNames.removeObject(proc.name());
+ _storedProcedures.removeObjectForKey(proc.name());
+ }
+
+ public EOStoredProcedure storedProcedureNamed(String name) {
+ 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
+ File f = new File(new File(_path), name + ".storedProcedure");
+ if (!f.exists())
+ return null;
+ String sdict = null;
+ try {
+ FileInputStream fin = new FileInputStream(f);
+ byte[] b = new byte[fin.available()];
+ fin.read(b);
+ fin.close();
+ sdict = new String(b);
+ } catch (IOException ex) {
+ return null;
+ }
+ NSDictionary plist = NSPropertyListSerialization.dictionaryForString(sdict);
+ if (plist == null)
+ throw new IllegalArgumentException("File " + f + " does not contain a valid stored procedure property list.");
+ proc = new EOStoredProcedure(plist, this);
+ //add it to our collection
+ _storedProcedures.setObjectForKey(proc, proc.name());
+ }
+ return proc;
+ }
+
+ public NSArray storedProcedures() {
+ if (_storedProcedures.count() < _storedProcedureNames.count()) {
+ for (int i=0; i<_storedProcedureNames.count(); i++)
+ storedProcedureNamed((String)_storedProcedureNames.objectAtIndex(i));
+ }
+ return _storedProcedures.allValues();
+ }
+
+ public NSArray storedProcedureNames() {
+ return _storedProcedures.allKeys();
+ }
+
+ public void setAdaptorName(String value) {
+ _adaptorName = value;
+ }
+ public String adaptorName() {
+ return _adaptorName;
+ }
+
+ public NSArray entities() {
+ if (_entitiesByName.count() >= _entities.count())
+ 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")));
+ }
+ return es;
+ }
+
+ public NSArray entityNames() {
+ if (_entitiesByName.count() >= _entities.count())
+ return _entitiesByName.allKeys();
+ NSMutableArray names = new NSMutableArray();
+ for (int i = 0; i < _entities.count(); 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);
+ if (e == null && path() != null) {
+ boolean exists = false;
+ for (int i = 0; i < _entities.count(); i++) {
+ NSDictionary d = (NSDictionary)_entities.objectAtIndex(i);
+ if (d.objectForKey("name").equals(name))
+ exists = true;
+ }
+ if (!exists)
+ return null;
+ File f = new File(new File(path()), name + ".plist");
+ if (!(f.exists() && f.isFile()))
+ throw new IllegalArgumentException("Cannot find " + name + ".plist");
+ String s = null;
+ try {
+ FileInputStream fin = new FileInputStream(f);
+ byte[] b = new byte[fin.available()];
+ fin.read(b);
+ fin.close();
+ s = new String(b);
+ } catch (IOException ex) {
+ throw new IllegalArgumentException("Cannot read " + f);
+ }
+ NSDictionary d = NSPropertyListSerialization.dictionaryForString(s);
+ if (d == null)
+ throw new IllegalArgumentException("Cannot parse dictionary for " + f);
+ e = new EOEntity(d, this);
+ _entitiesByName.setObjectForKey(e, e.name());
+ }
+ return e;
+ }
+
+ public String name() {
+ return _name;
+ }
+
+ public String path() {
+ return _path;
+ }
+
+ public void setModelGroup(EOModelGroup group) {
+ _group = group;
+ }
+ public EOModelGroup modelGroup() {
+ return _group;
+ }
+
+ public void setUserInfo(NSDictionary dict) {
+ _userInfo = dict;
+ }
+
+ public NSDictionary userInfo() {
+ return _userInfo;
+ }
+
+ public void write() {
+ }
+
+ public void writeToFile(String path) {
+ if (!path.endsWith(".eomodeld"))
+ path += ".eomodeld";
+ File f = new File(path);
+ if (f.exists()) {
+ if (f.isDirectory()) {
+ 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")))
+ kids[i].delete();
+ }
+ } else
+ f.delete();
+ } else
+ f.mkdirs();
+ File kid = new File(f, "index.eomodeld");
+
+ //encode the index file
+ NSMutableDictionary d = new NSMutableDictionary();
+ d.setObjectForKey(_adaptorName, "adaptorName");
+ d.setObjectForKey("2.1", "EOModelVersion");
+ d.setObjectForKey(_connectionDictionary, "connectionDictionary");
+ if (_internalInfo != null && _internalInfo.count() > 0)
+ d.setObjectForKey(_internalInfo, "internalInfo");
+ if (_userInfo != null && _userInfo.count() > 0)
+ d.setObjectForKey(_userInfo, "userInfo");
+ if (_storedProcedureNames.count() > 0)
+ d.setObjectForKey(_storedProcedureNames, "storedProcedures");
+
+ //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);
+ md.removeAllObjects();
+ ent.encodeIntoPropertyList(md);
+ File plist;
+ 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"));
+ try {
+ PrintStream stream = new PrintStream(new FileOutputStream(plist));
+ stream.println(ps);
+ stream.close();
+ } catch (IOException ex) {
+ }
+ }
+ md.removeObjectForKey("fetchSpecificationDictionary");
+ }
+ plist = new File(f, key + ".plist");
+ String ps = NSPropertyListSerialization.stringForPropertyList(md);
+ try {
+ PrintStream stream = new PrintStream(new FileOutputStream(plist));
+ stream.println(ps);
+ 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" }));
+ }
+ d.setObjectForKey(arr, "entities");
+
+ //write the index file
+ String s = NSPropertyListSerialization.stringForPropertyList(d);
+ try {
+ PrintStream stream = new PrintStream(new FileOutputStream(kid));
+ stream.println(s);
+ stream.close();
+ } catch (IOException ex) {
+ throw new RuntimeException("Cannot write index.eomodeld");
+ }
+
+ //write the stored procedures
+ for (int i = 0; i < _storedProcedureNames.count(); i++) {
+ EOStoredProcedure proc = (EOStoredProcedure)_storedProcedures.objectForKey(_storedProcedureNames.objectAtIndex(i));
+ kid = new File(f, proc.name() + ".storedProcedure");
+ d.removeAllObjects();
+ proc.encodeIntoPropertyList(d);
+ s = NSPropertyListSerialization.stringForPropertyList(d);
+ try {
+ PrintStream stream = new PrintStream(new FileOutputStream(kid));
+ stream.println(s);
+ stream.close();
+ } catch (IOException ex) {
+ throw new RuntimeException("Cannot write " + f);
+ }
+ }
+ _path = f.getAbsolutePath();
+ }
+
+}
+/*
+ * $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.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.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.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.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.
+ *
+*/ \ 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
new file mode 100644
index 0000000..dbab09d
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOModelGroup.java
@@ -0,0 +1,198 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+import net.wotonomy.control.EOFetchSpecification;
+import net.wotonomy.control.EOObjectStoreCoordinator;
+import net.wotonomy.foundation.NSArray;
+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 $
+*/
+public class EOModelGroup {
+
+ private static EOModelGroup _defaultGroup;
+ private static EOModelGroup _globalGroup;
+ protected NSMutableDictionary _models;
+
+ public EOModelGroup() {
+ super();
+ }
+
+ public void addModel(EOModel model) {
+ 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.");
+ NSArray ents = model.entityNames();
+ for (int i = 0; i < ents.count(); 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);
+ }
+ _models.setObjectForKey(model, model.name());
+ }
+
+ public void removeModel(EOModel model) {
+ _models.removeObjectForKey(model.name());
+ }
+
+ public void addModelWithPath(String path) {
+ EOModel model = new EOModel(path);
+ addModel(model);
+ }
+
+ public void addModelsFromDirectory(String dir) {
+ }
+
+ public static void setDefaultGroup(EOModelGroup group) {
+ _defaultGroup = group;
+ }
+ public static EOModelGroup defaultGroup() {
+ if (_defaultGroup == null) {
+ _defaultGroup = globalModelGroup();
+ }
+ return _defaultGroup;
+ }
+
+ public static EOModelGroup globalModelGroup() {
+ if (_globalGroup == null) {
+ _globalGroup = new EOModelGroup();
+ //TODO: read all frameworks and get models from them
+ }
+ return _globalGroup;
+ }
+
+ public EOEntity entityForObject(net.wotonomy.control.EOEnterpriseObject eo) {
+ return null;
+ }
+
+ public EOEntity entityNamed(String name) {
+ java.util.Enumeration enumeration = _models.objectEnumerator();
+ while (enumeration.hasMoreElements()) {
+ EOModel m = (EOModel)enumeration.nextElement();
+ if (m.entityNamed(name) != null)
+ return m.entityNamed(name);
+ }
+ return null;
+ }
+
+ public EOModel modelNamed(String name) {
+ return (EOModel)_models.objectForKey(name);
+ }
+
+ public NSArray modelNames() {
+ return _models.allKeys();
+ }
+
+ public NSArray models() {
+ return _models.allValues();
+ }
+
+ public EOModel modelWithPath(String path) {
+ java.util.Enumeration enumeration = _models.objectEnumerator();
+ while (enumeration.hasMoreElements()) {
+ EOModel m = (EOModel)enumeration.nextElement();
+ if (m.path() != null && m.path().equals(path))
+ return m;
+ }
+ return null;
+ }
+
+ public EOStoredProcedure storedProcedureNamed(String name) {
+ java.util.Enumeration enumeration = _models.objectEnumerator();
+ while (enumeration.hasMoreElements()) {
+ EOModel m = (EOModel)enumeration.nextElement();
+ if (m.storedProcedureNamed(name) != null)
+ return m.storedProcedureNamed(name);
+ }
+ return null;
+ }
+
+ public EOFetchSpecification fetchSpecificationNamed(String fetchSpecName, String entityName) {
+ EOEntity e = entityNamed(entityName);
+ if (e == null)
+ return null;
+ return e.fetchSpecificationNamed(fetchSpecName);
+ }
+
+ public void loadAllModelObjects() {
+ java.util.Enumeration enumeration = _models.objectEnumerator();
+ while (enumeration.hasMoreElements()) {
+ EOModel m = (EOModel)enumeration.nextElement();
+ //this causes all entities to be loaded
+ NSArray ents = m.entities();
+ for (int i=0; i<ents.count(); i++) {
+ EOEntity e = (EOEntity)ents.objectAtIndex(i);
+ //this loads all the fetch specifications
+ e.fetchSpecificationNamed("whatever");
+ }
+ }
+ }
+
+ public static void setModelGroupForObjectStoreCoordinator(EOObjectStoreCoordinator coord, EOModelGroup group) {
+ NSMutableDictionary d = new NSMutableDictionary(coord.userInfo());
+ d.setObjectForKey(group, "ModelGroup");
+ coord.setUserInfo(d);
+ }
+ public static EOModelGroup modelGroupForObjectStoreCoordinator(EOObjectStoreCoordinator coord) {
+ NSDictionary d = coord.userInfo();
+ if (d == null)
+ return defaultGroup();
+ Object g = d.objectForKey("ModelGroup");
+ if (g != null && g instanceof EOModelGroup)
+ return (EOModelGroup)g;
+ return defaultGroup();
+ }
+
+}
+/*
+ * $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.4 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.3 2003/08/08 00:44:04 chochos
+ * manage model groups for object store coordinators.
+ *
+ * Revision 1.2 2003/08/08 00:36:41 chochos
+ * add a little more functionality
+ *
+ * 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
diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOProperty.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOProperty.java
new file mode 100644
index 0000000..89f1fea
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOProperty.java
@@ -0,0 +1,46 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2001 Intersect Software Corporation
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+package net.wotonomy.access;
+
+/**
+* Abstract superclass of EOAttribute and EORelationship.
+*
+* @author ezamudio@nasoft.com
+* @author $Author: cgruber $
+* @version $Revision: 893 $
+*/
+public abstract class EOProperty {
+
+ public EOProperty() {
+ super();
+ }
+
+ public abstract String name();
+
+ public abstract String relationshipPath();
+
+}
+/*
+ * $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/08 06:51:37 chochos
+ * abstract superclass for relationships and attributes
+ *
+ */
diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOPropertyListEncoding.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOPropertyListEncoding.java
new file mode 100644
index 0000000..af456d2
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOPropertyListEncoding.java
@@ -0,0 +1,53 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+import net.wotonomy.foundation.NSDictionary;
+import net.wotonomy.foundation.NSMutableDictionary;
+
+/**
+* Implemented by classes that are read from property lists and that
+* can be written back to property lists.
+*
+* @author ezamudio@nasoft.com
+* @author $Author: cgruber $
+* @version $Revision: 894 $
+*/
+public interface EOPropertyListEncoding {
+
+ public abstract void awakeWithPropertyList(NSDictionary plist);
+
+ public abstract void encodeIntoPropertyList(NSMutableDictionary plist);
+
+}
+
+/* $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.1 2003/08/09 01:34:43 chochos
+/* an interface to provide property list encoding capabilities
+/*
+ *
+ */
+ \ No newline at end of file
diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOQualifierSQLGeneration.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOQualifierSQLGeneration.java
new file mode 100644
index 0000000..4627f76
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOQualifierSQLGeneration.java
@@ -0,0 +1,241 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2000 Michael Powers
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+package net.wotonomy.access;
+
+import net.wotonomy.control.EOAndQualifier;
+import net.wotonomy.control.EOKeyComparisonQualifier;
+import net.wotonomy.control.EOKeyValueQualifier;
+import net.wotonomy.control.EONotQualifier;
+import net.wotonomy.control.EOOrQualifier;
+import net.wotonomy.control.EOQualifier;
+import net.wotonomy.foundation.NSArray;
+import net.wotonomy.foundation.NSMutableDictionary;
+
+/**
+* @author ezamudio@nasoft.com
+* @author $Author: cgruber $
+* @version $Revision: 894 $
+*/
+
+public interface EOQualifierSQLGeneration {
+
+ public EOQualifier qualifierMigratedFromEntityRelationshipPath(
+ EOEntity entity, String path);
+
+ public EOQualifier schemaBasedQualifierWithRootEntity(EOEntity entity);
+
+ public String sqlStringForSQLExpression(EOSQLExpression expression);
+
+ public abstract class Support {
+
+ private static NSMutableDictionary _classes = new NSMutableDictionary();
+
+ static {
+ setSupportForClass(new KeyValueQualifierSupport(), EOKeyValueQualifier.class);
+ setSupportForClass(new KeyComparisonQualifierSupport(), EOKeyComparisonQualifier.class);
+ setSupportForClass(new AndQualifierSupport(), EOAndQualifier.class);
+ setSupportForClass(new OrQualifierSupport(), EOOrQualifier.class);
+ setSupportForClass(new NotQualifierSupport(), EONotQualifier.class);
+ }
+
+ public Support() {
+ super();
+ }
+
+ public static void setSupportForClass(Support sup, Class aClass) {
+ _classes.setObjectForKey(sup, aClass.getName());
+ }
+ public static Support supportForClass(Class aClass) {
+ return (Support)_classes.objectForKey(aClass.getName());
+ }
+
+ public abstract String sqlStringForSQLExpression(EOQualifier q, EOSQLExpression exp);
+
+ public abstract EOQualifier schemaBasedQualifierWithRootEntity(EOQualifier q, EOEntity e);
+
+ public abstract EOQualifier qualifierMigratedFromEntityRelationshipPath(EOQualifier q, EOEntity e, String path);
+
+ }
+
+ public class KeyValueQualifierSupport extends Support {
+
+ public KeyValueQualifierSupport() {
+ super();
+ }
+
+ public String sqlStringForSQLExpression(EOQualifier qualifier, EOSQLExpression exp) {
+ EOKeyValueQualifier q = (EOKeyValueQualifier)qualifier;
+ String sql1 = exp.sqlStringForAttributeNamed(q.key());
+ String sql2 = exp.sqlStringForSelector(q.selector(), q.value());
+ String sql3 = exp.sqlStringForValue(q.value(), q.key());
+ if (q.selector() == EOQualifier.QualifierOperatorCaseInsensitiveLike)
+ return exp.sqlStringForCaseInsensitiveLike(sql1, sql3);
+ else if (q.selector() == EOQualifier.QualifierOperatorLike)
+ sql3 = exp.sqlPatternFromShellPattern(sql3);
+ return sql1 + sql2 + sql3;
+ }
+
+ public EOQualifier schemaBasedQualifierWithRootEntity(EOQualifier q, EOEntity e) {
+ return q;
+ }
+
+ public EOQualifier qualifierMigratedFromEntityRelationshipPath(EOQualifier q, EOEntity e, String path) {
+ return q;
+ }
+
+ }
+
+ public class KeyComparisonQualifierSupport extends Support {
+
+ public KeyComparisonQualifierSupport() {
+ super();
+ }
+
+ public String sqlStringForSQLExpression(EOQualifier qualifier, EOSQLExpression exp) {
+ EOKeyComparisonQualifier q = (EOKeyComparisonQualifier)qualifier;
+ return exp.sqlStringForAttributeNamed(q.leftKey()) +
+ exp.sqlStringForSelector(q.selector(), null) +
+ exp.sqlStringForAttributeNamed(q.rightKey());
+ }
+
+ public EOQualifier schemaBasedQualifierWithRootEntity(EOQualifier q, EOEntity e) {
+ return q;
+ }
+
+ public EOQualifier qualifierMigratedFromEntityRelationshipPath(EOQualifier q, EOEntity e, String path) {
+ return q;
+ }
+
+ }
+
+ public class NotQualifierSupport extends Support {
+
+ public NotQualifierSupport() {
+ super();
+ }
+
+ public String sqlStringForSQLExpression(EOQualifier qualifier, EOSQLExpression exp) {
+ EONotQualifier q = (EONotQualifier)qualifier;
+ return "NOT (" + EOQualifierSQLGeneration.Support.supportForClass(q.qualifier().getClass()).sqlStringForSQLExpression(q.qualifier(), exp) + ")";
+ }
+
+ public EOQualifier schemaBasedQualifierWithRootEntity(EOQualifier qualifier, EOEntity e) {
+ EONotQualifier q = (EONotQualifier)qualifier;
+ return new EONotQualifier(EOQualifierSQLGeneration.Support.supportForClass(q.qualifier().getClass()).schemaBasedQualifierWithRootEntity(q.qualifier(), e));
+ }
+
+ public EOQualifier qualifierMigratedFromEntityRelationshipPath(EOQualifier qualifier, EOEntity e, String path) {
+ EONotQualifier q = (EONotQualifier)qualifier;
+ return new EONotQualifier(EOQualifierSQLGeneration.Support.supportForClass(q.qualifier().getClass()).qualifierMigratedFromEntityRelationshipPath(q.qualifier(), e, path));
+ }
+
+ }
+
+ public class AndQualifierSupport extends Support {
+
+ public AndQualifierSupport() {
+ super();
+ }
+
+ public String sqlStringForSQLExpression(EOQualifier qualifier, EOSQLExpression exp) {
+ EOAndQualifier q = (EOAndQualifier)qualifier;
+ NSArray qus = q.qualifiers();
+ StringBuffer buf = new StringBuffer();
+ for (int i = 0; i < qus.count(); 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)
+ buf.append(" AND ");
+ }
+ if (qus.count() > 1) {
+ buf.insert(0, '(');
+ buf.append(')');
+ }
+ return buf.toString();
+ }
+
+ public EOQualifier schemaBasedQualifierWithRootEntity(EOQualifier q, EOEntity e) {
+ return q;
+ }
+
+ public EOQualifier qualifierMigratedFromEntityRelationshipPath(EOQualifier q, EOEntity e, String path) {
+ return q;
+ }
+
+ }
+
+ public class OrQualifierSupport extends Support {
+
+ public OrQualifierSupport() {
+ super();
+ }
+
+ public String sqlStringForSQLExpression(EOQualifier qualifier, EOSQLExpression exp) {
+ 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);
+ 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)
+ buf.append(" OR ");
+ }
+ if (qus.count() > 1) {
+ buf.insert(0, '(');
+ buf.append(')');
+ }
+ return buf.toString();
+ }
+
+ public EOQualifier schemaBasedQualifierWithRootEntity(EOQualifier q, EOEntity e) {
+ return q;
+ }
+
+ public EOQualifier qualifierMigratedFromEntityRelationshipPath(EOQualifier q, EOEntity e, String path) {
+ return q;
+ }
+
+ }
+
+}
+/*
+ * $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.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.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
new file mode 100644
index 0000000..a5a207f
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EORelationship.java
@@ -0,0 +1,319 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+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 $
+*/
+public class EORelationship extends EOProperty implements EOPropertyListEncoding {
+
+ public static final int InnerJoin = 0;
+ public static final int FullOuterJoin = 1;
+ public static final int LeftOuterJoin = 2;
+ public static final int RightOuterJoin = 3;
+
+ protected String _name;
+ protected int _batchCount;
+ protected int _deleteRule;
+ protected int _joinSemantic;
+ protected EOEntity _destination;
+ protected EOEntity _entity;
+ protected NSMutableArray _joins = new NSMutableArray();
+ protected boolean _isMandatory;
+ protected boolean _isToMany;
+ protected boolean _isFlattened;
+ protected boolean _knowsIfFlattened;
+ protected boolean _ownsDestination;
+ protected boolean _propagatesPrimaryKey;
+ protected boolean _useBatchFaulting;
+ protected NSDictionary _userInfo = NSDictionary.EmptyDictionary;
+ protected NSDictionary _internalInfo = NSDictionary.EmptyDictionary;
+ protected NSDictionary plist;
+ protected String _definition;
+
+ public EORelationship() {
+ super();
+ }
+
+ public EORelationship(NSDictionary dict, Object obj) {
+ super();
+ _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");
+ if (delrule != null) {
+ if (delrule.equals("EODeleteRuleCascade"))
+ setDeleteRule(0);
+ else if (delrule.equals("EODeleteRuleDeny"))
+ setDeleteRule(0);
+ else if (delrule.equals("EODeleteRuleNoAction"))
+ setDeleteRule(0);
+ else if (delrule.equals("EODeleteRuleNullify"))
+ setDeleteRule(0);
+ }
+ delrule = (String)dict.objectForKey("joinSemantic");
+ if (delrule != null) {
+ if (delrule.equals("EOInnerJoin"))
+ setJoinSemantic(InnerJoin);
+ else if (delrule.equals("EOFullOuterJoin"))
+ setJoinSemantic(FullOuterJoin);
+ else if (delrule.equals("EOLeftOuterJoin"))
+ setJoinSemantic(LeftOuterJoin);
+ else if (delrule.equals("EORightOuterJoin"))
+ setJoinSemantic(RightOuterJoin);
+ }
+ delrule = (String)dict.objectForKey("batchCount");
+ if (delrule != null)
+ setNumberOfToManyFaultsToBatchFetch(Integer.parseInt(delrule));
+ NSDictionary d = (NSDictionary)dict.objectForKey("userInfo");
+ if (d != null)
+ _userInfo = d;
+ d = (NSDictionary)dict.objectForKey("internalInfo");
+ if (d != null)
+ _internalInfo = d;
+ plist = dict;
+ }
+
+ public void setName(String name) {
+ _name = name;
+ }
+ public String name() {
+ return _name;
+ }
+
+ public void addJoin(EOJoin join) {
+ _joins.addObject(join);
+ }
+
+ public void removeJoin(EOJoin join) {
+ _joins.removeObject(join);
+ }
+
+ public EOEntity entity() {
+ return _entity;
+ }
+
+ public EOEntity destinationEntity() {
+ isFlattened();
+ if (_destination == null && plist != null) {
+ EOModel model = _entity.model();
+ EOModelGroup group = model.modelGroup();
+ String destEntity = (String)plist.objectForKey("destination");
+ if (group != null)
+ _destination = group.entityNamed(destEntity);
+ else
+ _destination = model.entityNamed(destEntity);
+ }
+ return _destination;
+ }
+
+ public void setOwnsDestination(boolean flag) {
+ _ownsDestination = flag;
+ }
+ public boolean ownsDestination() {
+ return _ownsDestination;
+ }
+
+ public void setToMany(boolean flag) {
+ _isToMany = flag;
+ }
+ public boolean isToMany() {
+ return _isToMany;
+ }
+
+ public void setIsMandatory(boolean flag) {
+ _isMandatory = flag;
+ }
+ public boolean isMandatory() {
+ return _isMandatory;
+ }
+
+ public void setPropagatesPrimaryKey(boolean flag) {
+ _propagatesPrimaryKey = flag;
+ }
+ public boolean propagatesPrimaryKey() {
+ return _propagatesPrimaryKey;
+ }
+
+ public void setDeleteRule(int value) {
+ _deleteRule = value;
+ }
+ public int deleteRule() {
+ return _deleteRule;
+ }
+
+ public void setJoinSemantic(int value) {
+ _joinSemantic = value;
+ }
+ public int joinSemantic() {
+ return _joinSemantic;
+ }
+
+ 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");
+ 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");
+ EOAttribute a1 = _entity.attributeNamed(srcName);
+ EOAttribute a2 = destinationEntity().attributeNamed(dstName);
+ EOJoin j = new EOJoin(a1, a2);
+ addJoin(j);
+ }
+ }
+ return new NSArray(_joins);
+ }
+
+ public void setDefinition(String def) {
+ _definition = def;
+ }
+ public String definition() {
+ return _definition;
+ }
+
+ public boolean isFlattened() {
+ if (_knowsIfFlattened)
+ return _isFlattened;
+ _knowsIfFlattened = true;
+ if (definition() == null)
+ return false;
+ NSArray comps = NSArray.componentsSeparatedByString(definition(), ".");
+ if (comps.count() < 2)
+ return false;
+ EORelationship r = null;
+ EOEntity e = entity();
+ for (int i = 0; i < comps.count(); i++) {
+ String name = (String)comps.objectAtIndex(i);
+ r = e.relationshipNamed(name);
+ if (r == null)
+ return false;
+ e = r.destinationEntity();
+ }
+ _destination = e;
+ _isFlattened = true;
+ return _isFlattened;
+ }
+
+ public boolean isMultiHop() {
+ return false;
+ }
+
+ public String relationshipPath() {
+ if (isFlattened())
+ return _definition;
+ return null;
+ }
+
+ public void setUserInfo(NSDictionary value) {
+ _userInfo = value;
+ }
+ public NSDictionary userInfo() {
+ return _userInfo;
+ }
+
+ public void awakeWithPropertyList(NSDictionary plist) {
+ }
+
+ public void encodeIntoPropertyList(NSMutableDictionary dict) {
+ dict.setObjectForKey(name(), "name");
+ if (destinationEntity() != null && definition() == null)
+ dict.setObjectForKey(_destination.name(), "destination");
+ if (_internalInfo != null && _internalInfo.count() > 0)
+ dict.setObjectForKey(_internalInfo, "internalInfo");
+ if (_userInfo != null && _userInfo.count() > 0)
+ dict.setObjectForKey(_userInfo, "userInfo");
+ 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;
+ }
+ if (_batchCount > 0)
+ dict.setObjectForKey(new Integer(_batchCount), "batchCount");
+ if (definition() != null)
+ dict.setObjectForKey(definition(), "definition");
+ else {
+ NSMutableArray jarr = new NSMutableArray(joins().count());
+ for (int i = 0; i < _joins.count(); i++) {
+ EOJoin j = (EOJoin)_joins.objectAtIndex(i);
+ NSDictionary d = new NSDictionary(
+ new Object[]{ j.sourceAttribute().name(), j.destinationAttribute().name() },
+ new Object[]{ "sourceAttribute", "destinationAttribute" });
+ jarr.addObject(d);
+ }
+ dict.setObjectForKey(jarr, "joins");
+ }
+ }
+
+}
+/*
+ * $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.
+ *
+ * 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.4 2003/08/09 01:35:35 chochos
+ * implement EOPropertyListEncoding
+ *
+ * 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.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
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
new file mode 100644
index 0000000..4cb15e5
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOSQLExpression.java
@@ -0,0 +1,697 @@
+/*
+Wotonomy: OpenStep design patterns for pure Java applications.
+Copyright (C) 2000 Michael Powers
+
+This library is free software; you can redistribute it and/or
+modify it under the terms of the GNU Lesser General Public
+License as published by the Free Software Foundation; either
+version 2.1 of the License, or (at your option) any later version.
+
+This library is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+Lesser General Public License for more details.
+
+You should have received a copy of the GNU Lesser General Public
+License along with this library; if not, see http://www.gnu.org
+*/
+package net.wotonomy.access;
+
+import java.util.Enumeration;
+
+import net.wotonomy.control.EOAndQualifier;
+import net.wotonomy.control.EOFetchSpecification;
+import net.wotonomy.control.EOKeyComparisonQualifier;
+import net.wotonomy.control.EOKeyValueQualifier;
+import net.wotonomy.control.EOOrQualifier;
+import net.wotonomy.control.EOQualifier;
+import net.wotonomy.control.EOSortOrdering;
+import net.wotonomy.foundation.NSArray;
+import net.wotonomy.foundation.NSData;
+import net.wotonomy.foundation.NSDictionary;
+import net.wotonomy.foundation.NSKeyValueCoding;
+import net.wotonomy.foundation.NSMutableArray;
+import net.wotonomy.foundation.NSMutableDictionary;
+import net.wotonomy.foundation.NSSelector;
+import net.wotonomy.foundation.NSTimestamp;
+import net.wotonomy.foundation.NSTimestampFormatter;
+
+/**
+* @author ezamudio@nasoft.com
+* @author $Author: cgruber $
+* @version $Revision: 894 $
+*/
+public abstract class EOSQLExpression {
+
+ public static final String BindVariableAttributeKey = "BindVariableAttribute";
+ public static final String BindVariableColumnKey = "BindVariableColumn";
+ public static final String BindVariableNameKey = "BindVariableName";
+ public static final String BindVariablePlaceHolderKey = "BindVariablePlaceholder";
+ public static final String BindVariableValueKey = "BindVariableValue";
+ private static int UseBindings;
+ private static final int _DefaultFormatSQLStringLength = 64;
+ private static final int _DefaultListStringLength = 256;
+ 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'
+ };
+ private static final int _ValueLengthLimit = 40;
+ protected NSMutableDictionary _aliasesByRelationshipPath;
+ protected NSMutableDictionary _aliasesByEntityName;
+ protected NSMutableArray _bindings;
+ protected NSMutableArray _contextStack;
+ protected static NSTimestampFormatter _defaultDateFormatter;
+ protected EOEntity _entity;
+ protected StringBuffer _joinClauseString;
+ protected StringBuffer _listString;
+ protected StringBuffer _orderByString;
+ protected String _statement;
+ protected String _upperFunctionName;
+ protected boolean _useAliases = true;
+ protected static boolean _quoteExternalNames;
+ protected StringBuffer _valueListString;
+ protected String _whereClauseString;
+
+ private EOSQLExpression() {
+ super();
+ }
+
+ public EOSQLExpression(EOEntity entity) {
+ super();
+ _entity = entity;
+ }
+
+ public String _aliasForRelatedAttributeRelationshipPath(EOAttribute a, String path) {
+ return null;
+ }
+
+ public String _aliasForRelationshipPath(String path) {
+ return (String)_aliasesByRelationshipPath.objectForKey(path);
+ }
+
+ protected NSTimestampFormatter _defaultDateFormatter() {
+ return _defaultDateFormatter;
+ }
+
+ protected StringBuffer _listString() {
+ if (_listString == null)
+ _listString = new StringBuffer();
+ return _listString;
+ }
+
+ protected StringBuffer _orderByString() {
+ if (_orderByString == null)
+ _orderByString = new StringBuffer();
+ return _orderByString;
+ }
+
+ public EOEntity _rootEntityForExpression() {
+ return _entity;
+ }
+
+ public void _setEntity(EOEntity value) {
+ _entity = value;
+ }
+
+ public String _sqlStringForJoinSemanticMatchSemantic(int semantic,int match) {
+ return null;
+ }
+
+ protected String _stringForDate(NSTimestamp timestamp) {
+ return null;
+ }
+
+ protected StringBuffer _valueList() {
+ if (_valueListString == null)
+ _valueListString = new StringBuffer();
+ return _valueListString;
+ }
+
+ 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
+ * @param attr The attribute to create the SQL for.
+ */
+ public void addCreateClauseForAttribute(EOAttribute attr) {
+ StringBuffer buf = new StringBuffer(attr.columnName());
+ buf.append(' ');
+ buf.append(columnTypeStringForAttribute(attr));
+ buf.append(allowsNullClauseForConstraint(attr.allowsNull()));
+ appendItemToListString(buf.toString(), _listString());
+ }
+
+ public void addInsertListAttribute(EOAttribute attr, Object o) {
+ }
+
+ public void addJoinClause(String left, String right, int semantic) {
+ String s = assembleJoinClause(left, right, semantic);
+ if (_joinClauseString == null)
+ _joinClauseString = new StringBuffer();
+ if (_joinClauseString.length() > 0)
+ _joinClauseString.append(" AND ");
+ _joinClauseString.append(s);
+ }
+
+ public void addOrderByAttributeOrdering(EOSortOrdering order) {
+ String sql = sqlStringForAttributeNamed(order.key());
+ 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))
+ sql += " ASC";
+ else
+ sql += " DESC";
+ appendItemToListString(sql, _orderByString());
+ }
+
+ public void addSelectListAttribute(EOAttribute attr) {
+ appendItemToListString(formatSQLString(sqlStringForAttribute(attr), attr.readFormat()), _listString());
+ }
+
+ public void addUpdateListAttribute(EOAttribute attr, Object o) {
+ StringBuffer buf = new StringBuffer(attr.columnName());
+ buf.append('=');
+ buf.append(formatSQLString(formatValueForAttribute(o, attr), attr.writeFormat()));
+ appendItemToListString(buf.toString(), _listString());
+ }
+
+ public NSMutableDictionary aliasesByRelationshipPath() {
+ if (_aliasesByRelationshipPath == null) {
+ _aliasesByRelationshipPath = new NSMutableDictionary();
+ if (!_useAliases)
+ return _aliasesByRelationshipPath;
+ _aliasesByRelationshipPath.setObjectForKey("t0", "");
+ }
+ return _aliasesByRelationshipPath;
+ }
+
+ public String allowsNullClauseForConstraint(boolean flag) {
+ return flag ? "" : " NOT NULL";
+ }
+
+ public void appendItemToListString(String item, StringBuffer list) {
+ if (list.length() > 0)
+ list.append(", ");
+ list.append(item);
+ }
+
+ public String assembleDeleteStatementWithQualifier(EOQualifier q, String tableList, String whereClause) {
+ String s = "DELETE FROM " + tableList;
+ if (whereClause != null && whereClause.length() > 0)
+ s += " WHERE " + whereClause;
+ return s;
+ }
+
+ public String assembleInsertStatementWithRow(NSDictionary row,
+ String tableList, String columnList, String valueList) {
+ String sql = "INSERT INTO " + tableList;
+ if (columnList != null)
+ sql += " (" + columnList + ")";
+ sql += " VALUES " + valueList;
+ return sql;
+ }
+
+ public String assembleJoinClause(String leftName, String rightName, int semantic) {
+ String op = "=";
+ if (semantic == EORelationship.LeftOuterJoin)
+ op = "*=";
+ else if (semantic == EORelationship.RightOuterJoin)
+ op = "=*";
+ 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) {
+ String sql = selectString + " " + columnList + " FROM " + tableList;
+ if (lockClause != null)
+ sql += " " + lockClause;
+ if (whereClause != null || joinClause != null)
+ sql += " WHERE ";
+ if (whereClause != null)
+ sql += whereClause;
+ if (whereClause != null && joinClause != null)
+ sql += " AND ";
+ if (joinClause != null)
+ sql += joinClause;
+ if (orderByClause != null)
+ sql += " ORDER BY " + orderByClause;
+ return sql;
+ }
+
+ 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;
+ return s;
+ }
+
+ public NSArray bindVariableDictionaries() {
+ return null;
+ }
+
+ public abstract NSMutableDictionary bindVariableDictionaryForAttribute(EOAttribute attr, Object o);
+
+ public String columnTypeStringForAttribute(EOAttribute attr) {
+ String x = attr.externalType();
+ if (attr.precision() > 0) {
+ x += " (" + attr.precision() + "," + attr.scale() + ")";
+ } else if (attr.width() > 0) {
+ x += " (" + attr.width() + ")";
+ }
+ return x;
+ }
+
+ public EOEntity entity() {
+ return _entity;
+ }
+
+ public String externalNameQuoteCharacter() {
+ return "\"";
+ }
+
+ public String formatSQLString(String value, String format) {
+ if (format == null)
+ return value;
+ return value;
+ }
+
+ /**
+ * 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--) {
+ if (buf.charAt(i) == sqlEscapeChar()) {
+ buf.insert(i, sqlEscapeChar());
+ i++;
+ }
+ if (buf.charAt(i) == '\'') {
+ buf.insert(i, sqlEscapeChar());
+ i++;
+ }
+ }
+ buf.append('\'');
+ buf.insert(0, '\'');
+ return buf.toString();
+ }
+
+ public String formatValueForAttribute(Object value, EOAttribute attr) {
+ if (value == null || value == NSKeyValueCoding.NullValue)
+ return "NULL";
+ if (value instanceof String)
+ return formatStringValue((String)value);
+ if (value instanceof Number)
+ return sqlStringForNumber((Number)value);
+ //TODO: format timestamps
+ return value.toString();
+ }
+
+ public String joinClauseString() {
+ if (_joinClauseString == null)
+ return null;
+ return _joinClauseString.toString();
+ }
+
+ public void joinExpression() {
+ _joinClauseString = null;
+ if (_aliasesByEntityName.count() > 1) {
+ }
+ }
+
+ public String listString() {
+ return _listString().toString();
+ }
+
+ public String lockClause() {
+ return "";
+ }
+
+ public boolean mustUseBindVariableForAttribute(EOAttribute attr) {
+ return false;
+ }
+
+ public String orderByString() {
+ if (_orderByString == null)
+ return null;
+ return _orderByString.toString();
+ }
+
+ public void prepareConstraintStatementForRelationship(EORelationship rel, NSArray arr1, NSArray arr2) {
+ }
+
+ public void prepareDeleteExpressionForQualifier(EOQualifier q) {
+ String where = null;
+ setStatement(assembleDeleteStatementWithQualifier(q, _entity.externalName(), where));
+ }
+
+ public void prepareInsertExpressionWithRow(NSDictionary row) {
+ StringBuffer cols = new StringBuffer("(");
+ StringBuffer values = new StringBuffer("(");
+ Enumeration enumeration = row.keyEnumerator();
+ while (enumeration.hasMoreElements()) {
+ String key = (String)enumeration.nextElement();
+ EOAttribute a = _entity.attributeNamed(key);
+ cols.append(a.columnName());
+ values.append(formatValueForAttribute(row.objectForKey(key), a));
+ if (enumeration.hasMoreElements()) {
+ cols.append(", ");
+ values.append(", ");
+ }
+ }
+ cols.append(")");
+ cols.append(")");
+ setStatement(assembleInsertStatementWithRow(row, _entity.externalName(), cols.toString(), values.toString()));
+ }
+
+ public void prepareSelectExpressionWithAttributes(NSArray atts, boolean lock, EOFetchSpecification fspec) {
+ _aliasesByRelationshipPath = new NSMutableDictionary();
+ _aliasesByEntityName = new NSMutableDictionary();
+ EOQualifier q = null;
+ NSArray order = null;
+ if (fspec != null) {
+ q = fspec.qualifier();
+ order = fspec.sortOrderings();
+ }
+ //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
+ if (q != null) {
+ if (q instanceof EOQualifierSQLGeneration)
+ setWhereClauseString(sqlStringForQualifier((EOQualifierSQLGeneration)q));
+ else {
+ EOQualifierSQLGeneration.Support sup = EOQualifierSQLGeneration.Support.supportForClass(q.getClass());
+ setWhereClauseString(sup.sqlStringForSQLExpression(q, this));
+ }
+ }
+ //assemble the join string
+ joinExpression();
+ //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);
+ addOrderByAttributeOrdering(so);
+ }
+ }
+ //create the statement
+ setStatement(assembleSelectStatementWithAttributes(atts, lock, q, order, "SELECT", listString(),
+ tableListWithRootEntity(_entity), whereClauseString(), joinClauseString(), orderByString(), lockClause()));
+ }
+
+ /** Build an UPDATE statement with the given information. */
+ public void prepareUpdateExpressionWithRow(NSDictionary row, EOQualifier q) {
+ StringBuffer buf = new StringBuffer();
+ Enumeration enumeration = row.keyEnumerator();
+ while (enumeration.hasMoreElements()) {
+ 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());
+ buf.append(a.columnName());
+ buf.append('=');
+ buf.append(formatValueForAttribute(row.objectForKey(key), a));
+ if (enumeration.hasMoreElements())
+ buf.append(", ");
+ }
+ if (q != null) {
+ setWhereClauseString(sqlStringForQualifier(null));
+ }
+ setStatement(assembleUpdateStatementWithRow(row, q, _entity.externalName(), buf.toString(), whereClauseString()));
+ }
+
+ public void setStatement(String statement) {
+ _statement = statement;
+ }
+
+ public String statement() {
+ return _statement;
+ }
+
+ public void setUseAliases(boolean flag) {
+ _useAliases = flag;
+ }
+
+ public boolean useAliases() {
+ return _useAliases;
+ }
+
+ public void setUseBindVariables(boolean flag) {
+ }
+
+ public boolean useBindVariables() {
+ return System.getProperty("EOAdaptorUseBindVariables", "false").equals("true");
+ }
+
+ /** @deprecated Check externalNameQuoteCharacter instead. */
+ public static void setUseQuotedExternalNames(boolean flag) {
+ _quoteExternalNames = flag;
+ }
+ /** @deprecated Use the instance method externalNameQuoteCharacter instead. */
+ public static boolean useQuotedExternalNames() {
+ return _quoteExternalNames;
+ }
+
+ public void setWhereClauseString(String clause) {
+ _whereClauseString = clause;
+ }
+
+ public String whereClauseString() {
+ return _whereClauseString;
+ }
+
+ public boolean shouldUseBindVariableForAttribute(EOAttribute attr) {
+ return false;
+ }
+
+ public char sqlEscapeChar() {
+ return '\\';
+ }
+
+ public String sqlPatternFromShellPattern(String pattern) {
+ return sqlPatternFromShellPatternWithEscapeCharacter(pattern, sqlEscapeChar());
+ }
+
+ public String sqlPatternFromShellPatternWithEscapeCharacter(String pattern, char escape) {
+ StringBuffer buf = new StringBuffer(pattern);
+ int idx = 0;
+ //escape all '%'
+ do {
+ idx = buf.indexOf("%");
+ if (idx == 0)
+ buf.insert(escape, 0);
+ else if (idx > 0 && buf.charAt(idx-1) != escape)
+ buf.insert(escape, idx);
+ } while (idx >= 0);
+ //escape all '_'
+ do {
+ idx = buf.indexOf("_");
+ if (idx == 0)
+ buf.insert(escape, 0);
+ else if (idx > 0 && buf.charAt(idx-1) != escape)
+ buf.insert(escape, idx);
+ } while (idx >= 0);
+ //substitute all '*'
+ do {
+ idx = buf.indexOf("*");
+ if (idx >= 0)
+ buf.replace(idx, idx+1, "%");
+ } while (idx >= 0);
+ //substitute all '?'
+ do {
+ idx = buf.indexOf("?");
+ if (idx >= 0)
+ buf.replace(idx, idx+1, "_");
+ } while (idx >= 0);
+ return buf.toString();
+ }
+
+ public String sqlStringForAttribute(EOAttribute attr) {
+ if (_aliasesByEntityName == null)
+ _aliasesByEntityName = new NSMutableDictionary();
+ String alias = (String)_aliasesByEntityName.objectForKey(attr.entity().name());
+ if (alias == null) {
+ alias = "t" + (_aliasesByEntityName.count() + 1);
+ _aliasesByEntityName.setObjectForKey(alias, attr.entity().name());
+ }
+ if (useAliases())
+ return alias + "." + attr.columnName();
+ else
+ return attr.entity().externalName() + "." + attr.columnName();
+ }
+
+ public String sqlStringForAttributeNamed(String name) {
+ if (name.indexOf('.') > 0) {
+ 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.
+ * @param path An array of EORelationship objects.
+ * @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);
+ if (i > 0)
+ buf.append('.');
+ buf.append(rel.name());
+ }
+ return buf.toString();
+ }
+
+ public String sqlStringForCaseInsensitiveLike(String key, String value) {
+ return "LOWER(" + key + ") LIKE LOWER(" + sqlPatternFromShellPattern(value) + ")";
+ }
+
+ public String sqlStringForConjoinedQualifiers(NSArray qualifiers) {
+ EOAndQualifier q = new EOAndQualifier(qualifiers);
+ return EOQualifierSQLGeneration.Support.supportForClass(EOAndQualifier.class).sqlStringForSQLExpression(q, this);
+ }
+
+ public String sqlStringForData(NSData data) {
+ byte[] b = data.bytes();
+ char[] c = new char[b.length * 2];
+ int pos = 0;
+ for (int i = 0; i < b.length; i++) {
+ int x = (b[i] & 0xf0) >> 4;
+ c[pos++] = _hexChars[x];
+ x = (b[i] & 0x0f);
+ c[pos++] = _hexChars[x];
+ }
+ return new String(c);
+ }
+
+ public String sqlStringForDisjoinedQualifiers(NSArray qualifiers) {
+ EOOrQualifier q = new EOOrQualifier(qualifiers);
+ return EOQualifierSQLGeneration.Support.supportForClass(EOOrQualifier.class).sqlStringForSQLExpression(q, this);
+ }
+
+ public String sqlStringForKeyComparisonQualifier(EOKeyComparisonQualifier q) {
+ return EOQualifierSQLGeneration.Support.supportForClass(EOKeyComparisonQualifier.class).sqlStringForSQLExpression(q, this);
+ }
+
+ public String sqlStringForKeyValueQualifier(EOKeyValueQualifier q) {
+ return EOQualifierSQLGeneration.Support.supportForClass(EOKeyValueQualifier.class).sqlStringForSQLExpression(q, this);
+ }
+
+ public String sqlStringForNegatedQualifier(EOQualifier q) {
+ EOQualifierSQLGeneration.Support sup = EOQualifierSQLGeneration.Support.supportForClass(q.getClass());
+ String sql = sup.sqlStringForSQLExpression(q, this);
+ return "NOT (" + sql + ")";
+ }
+
+ public static String sqlStringForNumber(Number number) {
+ return number.toString();
+ }
+
+ public String sqlStringForQualifier(EOQualifierSQLGeneration sql) {
+ return sql.sqlStringForSQLExpression(this);
+ }
+
+ public String sqlStringForSchemaObjectName(String name) {
+ return name;
+ }
+
+ public String sqlStringForSelector(NSSelector sel, Object value) {
+ if (sel == EOQualifier.QualifierOperatorEqual) {
+ if (value == NSKeyValueCoding.NullValue)
+ return " is ";
+ return "=";
+ } else if (sel == EOQualifier.QualifierOperatorNotEqual) {
+ if (value == NSKeyValueCoding.NullValue)
+ return " is not ";
+ return "<>";
+ } else if (sel == EOQualifier.QualifierOperatorLessThan) {
+ return "<";
+ } else if (sel == EOQualifier.QualifierOperatorGreaterThan) {
+ return ">";
+ } else if (sel == EOQualifier.QualifierOperatorLessThanOrEqualTo) {
+ return "<=";
+ } else if (sel == EOQualifier.QualifierOperatorGreaterThanOrEqualTo) {
+ return ">=";
+ } else if (sel == EOQualifier.QualifierOperatorLike || sel == EOQualifier.QualifierOperatorCaseInsensitiveLike) {
+ return " like ";
+ }
+ return sel.name();
+ }
+
+ public static String sqlStringForString(String s) {
+ return s;
+ }
+
+ public String sqlStringForValue(Object value, String keyPath) {
+ EOAttribute a = _entity._attributeForPath(keyPath);
+ return formatValueForAttribute(value, a);
+ }
+
+ public String tableListWithRootEntity(EOEntity root) {
+ StringBuffer buf = new StringBuffer(root.externalName());
+ if (useAliases()) {
+ buf.append(" ");
+ buf.append(_aliasesByEntityName.objectForKey(root.name()));
+ }
+ if (_aliasesByEntityName.count() > 0) {
+ Enumeration enumeration = _aliasesByEntityName.keyEnumerator();
+ while (enumeration.hasMoreElements()) {
+ String key = (String)enumeration.nextElement();
+ if (!key.equals(root.name())) {
+ buf.append(", ");
+ buf.append(key);
+ if (useAliases())
+ buf.append(_aliasesByEntityName.objectForKey(key));
+ }
+ }
+ }
+ return buf.toString();
+ }
+
+ public String toString() {
+ return "<" + getClass().getName() + "> " + statement();
+ }
+
+ public String valueList() {
+ return _valueList().toString();
+ }
+
+}
+/*
+ * $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 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.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.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
new file mode 100644
index 0000000..6bdbffe
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOSQLExpressionFactory.java
@@ -0,0 +1,131 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+package net.wotonomy.access;
+
+import java.lang.reflect.Constructor;
+
+import net.wotonomy.control.EOFetchSpecification;
+import net.wotonomy.control.EOQualifier;
+import net.wotonomy.foundation.NSArray;
+import net.wotonomy.foundation.NSDictionary;
+
+/**
+*
+* @author ezamudio@nasoft.com
+* @author $Author: cgruber $
+* @version $Revision: 894 $
+*/
+public class EOSQLExpressionFactory {
+
+ protected EOAdaptor _adaptor;
+ protected Class _expressionClass;
+ private Constructor _instantiator;
+
+ public EOSQLExpressionFactory(EOAdaptor adaptor) {
+ super();
+ _adaptor = adaptor;
+ _expressionClass = _adaptor.expressionClass();
+ if (_expressionClass == null)
+ throw new IllegalStateException("EOAdaptor " + _adaptor.name() + " returned null for expressionClass()");
+ }
+
+ public EOAdaptor adaptor() {
+ return _adaptor;
+ }
+
+ /**
+ * 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.
+ */
+ public EOSQLExpression createExpression(EOEntity entity) {
+ EOSQLExpression expr = null;
+ if (_instantiator == null) {
+ try {
+ _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.");
+ }
+ }
+ try {
+ expr = (EOSQLExpression)_instantiator.newInstance(new Object[]{ entity });
+ } catch (Exception ex) {
+ throw new IllegalArgumentException("Cannot create new expression of class " + _expressionClass.getName());
+ }
+ return expr;
+ }
+
+ public EOSQLExpression expressionForEntity(EOEntity entity) {
+ return createExpression(entity);
+ }
+
+ public EOSQLExpression deleteStatementWithQualifier(EOQualifier qualifier, EOEntity entity) {
+ EOSQLExpression expr = createExpression(entity);
+ expr.prepareDeleteExpressionForQualifier(qualifier);
+ return expr;
+ }
+
+ public EOSQLExpression insertStatementForRow(NSDictionary row, EOEntity entity) {
+ EOSQLExpression expr = createExpression(entity);
+ expr.prepareInsertExpressionWithRow(row);
+ return expr;
+ }
+
+ public EOSQLExpression selectStatementForAttributes(NSArray atts, boolean lock, EOFetchSpecification fspec, EOEntity entity) {
+ EOSQLExpression expr = createExpression(entity);
+ expr.prepareSelectExpressionWithAttributes(atts, lock, fspec);
+ return expr;
+ }
+
+ public EOSQLExpression updateStatementForRow(NSDictionary row, EOQualifier qualifier, EOEntity entity) {
+ EOSQLExpression expr = createExpression(entity);
+ expr.prepareUpdateExpressionWithRow(row, qualifier);
+ return expr;
+ }
+
+ public EOSQLExpression expressionForString(String sql) {
+ EOSQLExpression expr = null;
+ try {
+ expr = (EOSQLExpression)_expressionClass.newInstance();
+ } catch (Exception e) {
+ return null;
+ }
+ expr.setStatement(sql);
+ return expr;
+ }
+
+ public Class expressionClass() {
+ return _expressionClass;
+ }
+
+}
+/*
+ * $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.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
new file mode 100644
index 0000000..f38ec2a
--- /dev/null
+++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/access/EOStoredProcedure.java
@@ -0,0 +1,141 @@
+/*
+ Wotonomy: OpenStep design patterns for pure Java applications.
+ Copyright (C) 2001 Michael Powers
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, see http://www.gnu.org
+ */
+
+package net.wotonomy.access;
+
+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 $
+*/
+public class EOStoredProcedure implements EOPropertyListEncoding {
+
+ protected String _name;
+ protected String _externalName;
+ protected EOModel _model;
+ protected NSArray _arguments = NSArray.EmptyArray;
+ protected NSDictionary _userInfo = NSDictionary.EmptyDictionary;
+ protected NSDictionary _internalInfo = NSDictionary.EmptyDictionary;
+
+ /** Creates a stored procedure from a property list. */
+ public EOStoredProcedure(NSDictionary dict, Object obj) {
+ super();
+ if (obj instanceof EOModel)
+ _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);
+ EOAttribute arg = new EOAttribute(ad, this);
+ args.addObject(arg);
+ }
+ _arguments = args;
+ }
+ setName((String)dict.objectForKey("name"));
+ setExternalName((String)dict.objectForKey("externalName"));
+ if (dict.objectForKey("userInfo") != null)
+ setUserInfo((NSDictionary)dict.objectForKey("userInfo"));
+ if (dict.objectForKey("internalInfo") != null)
+ _internalInfo = (NSDictionary)dict.objectForKey("internalInfo");
+ }
+
+ public EOStoredProcedure(String withName) {
+ super();
+ setName(withName);
+ }
+
+ public void setName(String value) {
+ _name = value;
+ }
+ public String name() {
+ return _name;
+ }
+
+ public void setExternalName(String value) {
+ _externalName = value;
+ }
+ public String externalName() {
+ return _externalName;
+ }
+
+ public void setArguments(NSArray value) {
+ _arguments = value;
+ }
+ public NSArray arguments() {
+ return _arguments;
+ }
+
+ public EOModel model() {
+ return _model;
+ }
+
+ public void setUserInfo(NSDictionary info) {
+ _userInfo = info;
+ }
+ public NSDictionary userInfo() {
+ return _userInfo;
+ }
+
+ public void awakeWithPropertyList(NSDictionary plist) {
+ }
+
+ public void encodeIntoPropertyList(NSMutableDictionary plist) {
+ plist.setObjectForKey(name(), "name");
+ plist.setObjectForKey(externalName(), "externalName");
+ NSMutableArray arr = new NSMutableArray(_arguments.count());
+ NSMutableDictionary d = null;
+ for (int i = 0; i < _arguments.count(); i++) {
+ EOAttribute a = (EOAttribute)_arguments.objectAtIndex(i);
+ d = new NSMutableDictionary();
+ a.encodeIntoPropertyList(d);
+ arr.addObject(d);
+ }
+ plist.setObjectForKey(arr, "arguments");
+ }
+
+}
+/*
+ * $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.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.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.
+ *
+*/ \ No newline at end of file