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/control/EOFetchSpecification.java | |
Initial import from SVN
Diffstat (limited to 'projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOFetchSpecification.java')
| -rw-r--r-- | projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOFetchSpecification.java | 565 |
1 files changed, 565 insertions, 0 deletions
diff --git a/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOFetchSpecification.java b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOFetchSpecification.java new file mode 100644 index 0000000..71f3b78 --- /dev/null +++ b/projects/net.wotonomy.persistence/src/main/java/net/wotonomy/control/EOFetchSpecification.java @@ -0,0 +1,565 @@ +/* +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.control; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import net.wotonomy.foundation.NSArray; +import net.wotonomy.foundation.NSDictionary; +import net.wotonomy.foundation.NSMutableArray; +import net.wotonomy.foundation.NSMutableDictionary; +import net.wotonomy.foundation.NSSelector; +import net.wotonomy.foundation.internal.WotonomyException; + +/** +* EOFetchSpecification defines the parameters used to request +* objects from an EOObjectStore. They are commonly created +* and passed to a EODataSource which fetches from its +* EOEditingContext, which passes the call up to its root +* EOObjectStore's objectsWithFetchSpecification method. +* +* @author michael@mpowers.net +* @author $Author: cgruber $ +* @version $Revision: 894 $ +*/ +public class EOFetchSpecification implements EOKeyValueArchiving { + private boolean fetchesRawRows; + private String entityName; + private NSDictionary hints; + private boolean deep; + private int fetchLimit; + private boolean locksObjects; + private NSArray prefetchingRelationshipKeyPaths; + private boolean promptsAfterFetchLimit; + private EOQualifier qualifier; + private NSArray rawRowKeyPaths; + private boolean refreshesRefetchedObjects; + private boolean requiresAllQualifierBindingVariables; + private NSArray sortOrderings; + private boolean distinct; + + /** + * Default constructor initializes internal state. + */ + public EOFetchSpecification() + { + fetchesRawRows = false; + entityName = null; + hints = null; + deep = true; + fetchLimit = 0; + locksObjects = false; + prefetchingRelationshipKeyPaths = null; + promptsAfterFetchLimit = false; + qualifier = null; + rawRowKeyPaths = null; + refreshesRefetchedObjects = false; + requiresAllQualifierBindingVariables = false; + sortOrderings = null; + distinct = false; + } + + /** + * Constructs a fetch specification for the specified entity type using + * the specified qualifier and sort ordering. + */ + public EOFetchSpecification( String anEntityName, EOQualifier aQualifier, List aSortOrderingList ) + { + this(); + entityName = anEntityName; + qualifier = aQualifier; + sortOrderings = new NSArray( (Collection) aSortOrderingList ); + } + + /** + * Constructs a fetch specification for the specified entity type using + * the specified qualifier and sort ordering, distinct flag, deep flag, + * and hints dictionary. + */ + public EOFetchSpecification( String anEntityName, EOQualifier aQualifier, NSArray aSortOrderingList, + boolean usesDistinct, boolean isDeep, Map aHintMap) + { + this(); + entityName = anEntityName; + qualifier = aQualifier; + sortOrderings = new NSArray( (Collection) aSortOrderingList ); + distinct = usesDistinct; + deep = isDeep; + hints = new NSMutableDictionary( (Map) aHintMap ); + } + + /** + * Convenience to return the named fetch specification from the class description + * corresponding to the specified entity name. Returns null if either entityName + * or spec name cannot be resolved. + */ + public static EOFetchSpecification fetchSpecificationNamed( String name, String entityName) + { + EOClassDescription classDesc = EOClassDescription.classDescriptionForEntityName( entityName ); + if ( classDesc == null ) return null; + return classDesc.fetchSpecificationNamed( name ); + } + + /** + * Implemented to return a new fetch specification that is a deep copy of this one. + */ + public Object clone() + { + EOFetchSpecification clone = new EOFetchSpecification(); + + clone.fetchesRawRows = this.fetchesRawRows; + clone.entityName = this.entityName; + if ( this.hints != null ) + clone.hints = new NSDictionary( (Map) this.hints ); + clone.deep = this.deep; + clone.locksObjects = this.locksObjects; + if ( this.prefetchingRelationshipKeyPaths != null ) + clone.prefetchingRelationshipKeyPaths = + new NSArray( (List) prefetchingRelationshipKeyPaths ); + clone.promptsAfterFetchLimit = this.promptsAfterFetchLimit; + if ( this.qualifier != null ) + clone.qualifier = this.qualifier; //FIXME: probably should clone? + if ( this.rawRowKeyPaths != null ) + clone.rawRowKeyPaths = new NSArray( (List) this.rawRowKeyPaths ); + clone.refreshesRefetchedObjects = this.refreshesRefetchedObjects; + clone.requiresAllQualifierBindingVariables = + this.requiresAllQualifierBindingVariables; + if ( this.sortOrderings != null ) + clone.sortOrderings = new NSArray( (List) this.sortOrderings ); + clone.distinct = this.distinct; + + return clone; + } + + /** + * Returns the name of the entity fetched by this fetch spec. + */ + public String entityName() + { + return entityName; + } + + /** + * Returns the current fetch limit. + * A fetch limit of zero indicates no fetch limit. + * Zero is the default. + */ + public int fetchLimit() + { + return fetchLimit; + } + + /** + * Returns whether this fetch spec will fetch raw rows. + * Default is false. + */ + public boolean fetchesRawRows() + { + return fetchesRawRows; + } + + /** + * Returns a fetch specification that resolves the bindings + * in the specified map. + */ + public EOFetchSpecification + fetchSpecificationWithQualifierBindings(Map aBindingMap) + { + throw new WotonomyException( "Not implemented yet" ); + } + + /** + * Returns a Map containing the hints used by this fetch specification, + * or null if no hints have been specified. + */ + public NSDictionary hints() + { + if ( hints == null ) return null; + return new NSDictionary( (NSDictionary) hints ); + } + + /** + * Returns whether entities related to the primary + * entities are fetched by this fetch spec. If true, all relationships + * whose destinations meet the qualifier criteria will be returned + * in addition to primary results. If false, only the primary entities + * will be returned. Default is true. + */ + public boolean isDeep() + { + return deep; + } + + /** + * Returns whether this data source should lock objects that + * are fetched. Default is false. + */ + public boolean locksObjects() + { + return locksObjects; + } + + /*** + * Returns a List of relationships for the fetched objects that + * should also be fetched, or null if no such list has been specified. + * Use this to avoid additional calls to the server to fetch + * relationships that you know you will use. + * NOTE: wotonomy allows you to specify non-relational keys + * as well. + */ + public NSArray prefetchingRelationshipKeyPaths() + { + return prefetchingRelationshipKeyPaths; + } + + /** + * Returns whether the user should be prompted to continue + * when the fetch limit has been exceeded. + * Default is false. + */ + public boolean promptsAfterFetchLimit() + { + return promptsAfterFetchLimit; + } + + /** + * Returns the qualifier used by this fetch specification, + * or null if none has been specified. + */ + public EOQualifier qualifier() + { + return qualifier; + } + + /** + * Returns a List of keys or key paths for which + * values should be returned when fetching raw rows, + * or null if no raw row key paths have been specified. + */ + public NSArray rawRowKeyPaths() + { + return rawRowKeyPaths; + } + + /** + * Returns whether fetched objects should replace + * modified versions already fetched into an editing context. + * If true, those changes will be lost. + * Default is false. + */ + public boolean refreshesRefetchedObjects() + { + return refreshesRefetchedObjects; + } + + /** + * Returns whether all qualifier bindings must be specified + * in order to fetch. If true, an exception is thrown if + * unspecified bindings exist. If false, unspecified bindings + * will be removed from the qualifier. Default is false. + */ + public boolean requiresAllQualifierBindingVariables() + { + return requiresAllQualifierBindingVariables; + } + + /** + * Sets the name of the entity fetched by this spec. + */ + public void setEntityName(String aName) + { + entityName = aName; + } + + /** + * Sets whether this fetch spec will return raw rows. + */ + public void setFetchesRawRows(boolean shouldFetchRawRows) + { + fetchesRawRows = shouldFetchRawRows; + } + + /** + * Sets the limit on the number of records returned for this fetch spec. + * Zero indicates no limit on fetches. + */ + public void setFetchLimit(int aLimit) + { + fetchLimit = aLimit; + } + + /** + * Sets the hints passed by this fetch spec. + */ + public void setHints(Map aHintMap) + { + if ( aHintMap == null ) + { + hints = null; + } + else + { + hints = new NSDictionary( (Map) aHintMap ); + } + } + + /** + * Sets whether this fetch specification fetches deeply. + */ + public void setIsDeep(boolean isDeep) + { + deep = isDeep; + } + + /** + * Sets whether this fetch spec locks objects that + * are returned by the fetch. + */ + public void setLocksObjects(boolean shouldLockObjects) + { + locksObjects = shouldLockObjects; + } + + /** + * Sets the prefetch key paths that should be used as an optimization + * hint to the server. NOTE: wotonomy allows you to specify non-relationship + * keys as well. + */ + public void setPrefetchingRelationshipKeyPaths(List aKeyPathList) + { + if ( aKeyPathList == null ) + { + prefetchingRelationshipKeyPaths = null; + } + else + { + prefetchingRelationshipKeyPaths = new NSArray( (List) aKeyPathList ); + } + } + + /** + * Sets whether the user should be prompted when the fetch limit has been + * reached. + */ + public void setPromptsAfterFetchLimit(boolean shouldPrompt) + { + promptsAfterFetchLimit = shouldPrompt; + } + + /** + * Sets the qualifier used by this fetch specification. + */ + public void setQualifier(EOQualifier aQualifier) + { + qualifier = aQualifier; + } + + /** + * Sets the key paths to be returned if this fetch spec + * is returning raw rows. + */ + public void setRawRowKeyPaths(List aKeyPathList) + { + if ( aKeyPathList == null ) + { + rawRowKeyPaths = null; + } + else + { + rawRowKeyPaths = new NSArray( (List) aKeyPathList ); + } + } + + /** + * Sets whether modified objects in an editing context should + * be replaced by newer versions returned by this fetch spec. + */ + public void setRefreshesRefetchedObjects(boolean shouldRefresh) + { + refreshesRefetchedObjects = shouldRefresh; + } + + /** + * Sets whether this fetch spec should require all bindings to be + * resolved before executing. + */ + public void setRequiresAllQualifierBindingVariables(boolean shouldRequireAll) + { + requiresAllQualifierBindingVariables = shouldRequireAll; + } + + /** + * Sets the sort orderings used by this fetch spec. + */ + public void setSortOrderings(List aSortList) + { + if ( aSortList == null ) + { + sortOrderings = null; + } + else + { + sortOrderings = new NSArray( (List) aSortList ); + } + } + + /** + * Sets whether this fetch spec should return only distinct + * objects. + */ + public void setUsesDistinct(boolean shouldUseDistinct) + { + distinct = shouldUseDistinct; + } + + /** + * Returns a List of the sort orderings used by this fetch spec, + * or null if none have been specified. + */ + public NSArray sortOrderings() + { + return sortOrderings; + } + + /** + * Returns a string representation of this fetch specification. + */ + public String toString() + { + return "[FetchSpecification:qualifier=("+qualifier+"),sortOrderings="+sortOrderings+"]"; + } + + /** + * Returns whether this fetch specification will return only one + * reference to each distinct object returned by the fetch. + * Default is false. + */ + public boolean usesDistinct() + { + return distinct; + } + + public void encodeWithKeyValueArchiver(EOKeyValueArchiver arch) { + arch.encodeObject("EOFetchSpecification", "class"); + arch.encodeObject(entityName(), "entityName"); + arch.encodeInt(fetchLimit(), "fetchLimit"); + + //flags + if (isDeep()) + arch.encodeObject("YES", "isDeep"); + arch.encodeObject(qualifier(), "qualifier"); + if (refreshesRefetchedObjects()) + arch.encodeObject("YES", "refreshesRefetchedObjects"); + if (locksObjects()) + arch.encodeObject("YES", "locksObjects"); + if (fetchesRawRows()) + arch.encodeObject("YES", "fetchesRawRows"); + if (promptsAfterFetchLimit()) + arch.encodeObject("YES", "promptsAfterFetchLimit"); + if (requiresAllQualifierBindingVariables()) + arch.encodeObject("YES", "requiresAllQualifierBindingVariables"); + if (usesDistinct()) + arch.encodeObject("YES", "usesDistinct"); + + //encode arrays + if (sortOrderings() != null) { + NSMutableArray arr = new NSMutableArray(sortOrderings().count()); + for (int i = 0; i < sortOrderings.count(); i++) { + EOSortOrdering so = (EOSortOrdering)sortOrderings().objectAtIndex(i); + EOKeyValueArchiver ar2 = new EOKeyValueArchiver(); + so.encodeWithKeyValueArchiver(ar2); + arr.addObject(ar2.dictionary()); + } + arch.encodeObject(arr, "sortOrderings"); + } + if (rawRowKeyPaths != null && rawRowKeyPaths.count() > 0) + arch.encodeObject(rawRowKeyPaths, "rawRowKeyPaths"); + if (prefetchingRelationshipKeyPaths != null && prefetchingRelationshipKeyPaths.count() > 0) + arch.encodeObject(rawRowKeyPaths, "prefetchingRelationshipKeyPaths"); + if (hints != null && hints.count() > 0) + arch.encodeObject(hints, "hints"); + } + + public static Object decodeWithKeyValueUnarchiver(EOKeyValueUnarchiver unarch) { + EOFetchSpecification fs = new EOFetchSpecification(); + fs.setEntityName((String)unarch.decodeObjectForKey("entityName")); + fs.setFetchLimit(unarch.decodeIntForKey("fetchLimit")); + fs.setIsDeep(unarch.decodeBoolForKey("isDeep")); + fs.setRefreshesRefetchedObjects(unarch.decodeBoolForKey("refreshesRefetchedObjects")); + + //Sort orderings + NSArray arr = (NSArray)unarch.decodeObjectForKey("sortOrderings"); + if (arr != null && arr.count() > 0) { + NSMutableArray orderings = new NSMutableArray(arr.count()); + for (int i = 0; i < arr.count(); i++) { + NSDictionary so = (NSDictionary)arr.objectAtIndex(i); + String selname = (String)so.objectForKey("selectorName"); + NSSelector selector = EOSortOrdering.CompareAscending; + if (selname.startsWith("compareDescending")) + selector = EOSortOrdering.CompareDescending; + else if (selname.startsWith("compareCaseInsensitiveAscending")) + selector = EOSortOrdering.CompareCaseInsensitiveAscending; + else if (selname.startsWith("compareCaseInsensitiveDescending")) + selector = EOSortOrdering.CompareCaseInsensitiveDescending; + EOSortOrdering eoso = new EOSortOrdering((String)so.objectForKey("key"), selector); + orderings.addObject(eoso); + } + fs.setSortOrderings(orderings); + } + //raw rows + arr = (NSArray)unarch.decodeObjectForKey("rawRowKeyPaths"); + if (arr != null && arr.count() > 0) { + fs.setFetchesRawRows(true); + fs.setRawRowKeyPaths(arr); + } + //qualifier + fs.setQualifier((EOQualifier)unarch.decodeObjectForKey("qualifier")); + return fs; + } + +} + +/* + * $Log$ + * Revision 1.2 2006/02/16 16:47:14 cgruber + * Move some classes in to "internal" packages and re-work imports, etc. + * + * 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 18:19:01 chochos + * encoding/decoding with EOKeyValueArchiving now works properly + * + * Revision 1.3 2003/08/09 01:22:20 chochos + * implements EOKeyValueArchiving (and unarchiving) + * + * Revision 1.2 2001/11/24 17:32:57 mpowers + * We now have a real implementation. + * + * Revision 1.1 2001/02/05 03:45:37 mpowers + * Starting work on EOEditingContext. + * + * + */ + + |
