diff options
| author | Benjamin Culkin <scorpress@gmail.com> | 2024-05-19 17:56:33 -0400 |
|---|---|---|
| committer | Benjamin Culkin <scorpress@gmail.com> | 2024-05-19 17:56:33 -0400 |
| commit | aedc34d55462a75e329bbf342251ff6504cd117e (patch) | |
| tree | bcc8f1f2352582717b484df302aeea6696b8f000 /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')
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 |
