You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by aa...@apache.org on 2026/08/30 16:04:40 UTC
(cayenne) branch master updated (e90c3c503 -> debcdc94d)
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git
from e90c3c503 Getting rid of useless ParameterizedQuery interface
new 4eb038c8a refactoring Select - make all trivially implemented common methods "default" methods of the interface
new debcdc94d removing dead code - EOQuery
The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
Summary of changes:
.../wocompat/EOFetchSpecificationParser.java | 302 +++++++++++++
.../apache/cayenne/wocompat/EOModelProcessor.java | 2 +-
.../org/apache/cayenne/wocompat/EOObjEntity.java | 4 +-
.../java/org/apache/cayenne/wocompat/EOQuery.java | 495 ---------------------
...st.java => EOFetchSpecificationParserTest.java} | 45 +-
.../org/apache/cayenne/query/FluentSelect.java | 24 -
.../org/apache/cayenne/query/MappedSelect.java | 22 -
.../java/org/apache/cayenne/query/SQLSelect.java | 23 -
.../main/java/org/apache/cayenne/query/Select.java | 22 +-
.../java/org/apache/cayenne/query/SelectById.java | 23 -
10 files changed, 348 insertions(+), 614 deletions(-)
create mode 100644 cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOFetchSpecificationParser.java
delete mode 100644 cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOQuery.java
rename cayenne-wocompat/src/test/java/org/apache/cayenne/wocompat/{EOQueryTest.java => EOFetchSpecificationParserTest.java} (55%)
(cayenne) 02/02: removing dead code - EOQuery
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit debcdc94dab0812372b6fbb04d7be9b1db17d079
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun Aug 30 12:03:35 2026 -0400
removing dead code - EOQuery
---
.../wocompat/EOFetchSpecificationParser.java | 302 +++++++++++++
.../apache/cayenne/wocompat/EOModelProcessor.java | 2 +-
.../org/apache/cayenne/wocompat/EOObjEntity.java | 4 +-
.../java/org/apache/cayenne/wocompat/EOQuery.java | 495 ---------------------
...st.java => EOFetchSpecificationParserTest.java} | 45 +-
5 files changed, 331 insertions(+), 517 deletions(-)
diff --git a/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOFetchSpecificationParser.java b/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOFetchSpecificationParser.java
new file mode 100644
index 000000000..a52d0866f
--- /dev/null
+++ b/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOFetchSpecificationParser.java
@@ -0,0 +1,302 @@
+/*****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * https://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ ****************************************************************/
+
+package org.apache.cayenne.wocompat;
+
+import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionException;
+import org.apache.cayenne.exp.ExpressionFactory;
+import org.apache.cayenne.exp.ExpressionParameter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * EOFetchSpecificationParser parses EOFetchSpecifications from a
+ * WebObjects-style EOModel. It recursively builds Cayenne Expression
+ * objects and assembles them into the final aggregate Expression.
+ */
+@SuppressWarnings("unchecked")
+class EOFetchSpecificationParser {
+
+ // Xcode/EOModeler expressions have a colon at the end of the selector
+ // name
+ // (just like standard Objective-C syntax). WOLips does not. Add both
+ // sets to the hash map to handle both types of models.
+
+ // Selector strings (Java-base).
+ static final String IS_EQUAL_TO = "isEqualTo";
+ static final String IS_NOT_EQUAL_TO = "isNotEqualTo";
+ static final String IS_LIKE = "isLike";
+ static final String CASE_INSENSITIVE_LIKE = "isCaseInsensitiveLike";
+ static final String IS_LESS_THAN = "isLessThan";
+ static final String IS_LESS_THAN_OR_EQUAL_TO = "isLessThanOrEqualTo";
+ static final String IS_GREATER_THAN = "isGreaterThan";
+ static final String IS_GREATER_THAN_OR_EQUAL_TO = "isGreaterThanOrEqualTo";
+
+ private static final String OBJ_C = ":"; // Objective-C syntax addition.
+
+ private static Map<String, Integer> selectorToExpressionBridge;
+ private static final Logger LOGGER = LoggerFactory.getLogger(EOFetchSpecificationParser.class);
+
+ /**
+ * selectorToExpressionBridge is just a mapping of EOModeler's selector
+ * types to Cayenne Expression types.
+ *
+ * @return HashMap of Expression types, keyed by the corresponding
+ * selector name
+ */
+ static synchronized Map<String, Integer> selectorToExpressionBridge() {
+ // Initialize selectorToExpressionBridge if needed.
+ if (null == selectorToExpressionBridge) {
+ selectorToExpressionBridge = new HashMap<>();
+
+ selectorToExpressionBridge.put(IS_EQUAL_TO, Expression.EQUAL_TO);
+ selectorToExpressionBridge.put(IS_EQUAL_TO + OBJ_C, Expression.EQUAL_TO);
+
+ selectorToExpressionBridge.put(IS_NOT_EQUAL_TO, Expression.NOT_EQUAL_TO);
+ selectorToExpressionBridge.put(IS_NOT_EQUAL_TO + OBJ_C, Expression.NOT_EQUAL_TO);
+
+ selectorToExpressionBridge.put(IS_LIKE, Expression.LIKE);
+ selectorToExpressionBridge.put(IS_LIKE + OBJ_C, Expression.LIKE);
+
+ selectorToExpressionBridge.put(CASE_INSENSITIVE_LIKE, Expression.LIKE_IGNORE_CASE);
+ selectorToExpressionBridge.put(CASE_INSENSITIVE_LIKE + OBJ_C, Expression.LIKE_IGNORE_CASE);
+
+ selectorToExpressionBridge.put(IS_LESS_THAN, Expression.LESS_THAN);
+ selectorToExpressionBridge.put(IS_LESS_THAN + OBJ_C, Expression.LESS_THAN);
+
+ selectorToExpressionBridge.put(IS_LESS_THAN_OR_EQUAL_TO, Expression.LESS_THAN_EQUAL_TO);
+ selectorToExpressionBridge.put(IS_LESS_THAN_OR_EQUAL_TO + OBJ_C, Expression.LESS_THAN_EQUAL_TO);
+
+ selectorToExpressionBridge.put(IS_GREATER_THAN, Expression.GREATER_THAN);
+ selectorToExpressionBridge.put(IS_GREATER_THAN + OBJ_C, Expression.GREATER_THAN);
+
+ selectorToExpressionBridge.put(IS_GREATER_THAN_OR_EQUAL_TO, Expression.GREATER_THAN_EQUAL_TO);
+ selectorToExpressionBridge.put(IS_GREATER_THAN_OR_EQUAL_TO + OBJ_C, Expression.GREATER_THAN_EQUAL_TO);
+ }
+
+ return selectorToExpressionBridge;
+ }
+
+ /**
+ * isAggregate determines whether a qualifier is "aggregate" -- has
+ * children -- or "simple".
+ *
+ * @param qualifier
+ * - a Map containing the qualifier settings
+ * @return boolean indicating whether the qualifier is "aggregate"
+ * qualifier
+ */
+ static boolean isAggregate(Map<String, ?> qualifier) {
+ boolean result = true;
+
+ String theClass = (String) qualifier.get("class");
+ if (theClass == null) {
+ return false; // should maybe throw an exception?
+ }
+ if (theClass.equalsIgnoreCase("EOKeyValueQualifier")
+ || theClass.equalsIgnoreCase("EOKeyComparisonQualifier")) {
+ result = false;
+ }
+
+ return result;
+ }
+
+ /**
+ * expressionTypeForQualifier looks at a qualifier containing the
+ * EOModeler FetchSpecification and returns the equivalent Cayenne
+ * Expression type for its selector.
+ *
+ * @param qualifierMap
+ * - a Map containing the qualifier settings to examine.
+ * @return int Expression type
+ */
+ static int expressionTypeForQualifier(Map<String, ?> qualifierMap) {
+ // get selector
+ String selector = (String) qualifierMap.get("selectorName");
+ return expressionTypeForSelector(selector);
+ }
+
+ /**
+ * expressionTypeForSelector looks at a selector from an EOModeler
+ * FetchSpecification and returns the equivalent Cayenne Expression
+ * type.
+ *
+ * @param selector
+ * - a String containing the selector name.
+ * @return int Expression type
+ */
+ static int expressionTypeForSelector(String selector) {
+ Integer expType = selectorToExpressionBridge().get(selector);
+ return (expType != null ? expType : -1);
+ }
+
+ /**
+ * aggregateExpressionClassForQualifier looks at a qualifer and returns
+ * the aggregate type: one of Expression.AND, Expression.OR, or
+ * Expression.NOT
+ *
+ * @param qualifierMap
+ * - containing the qualifier to examine
+ * @return int aggregate Expression type
+ */
+ static int aggregateExpressionClassForQualifier(Map<String, ?> qualifierMap) {
+ String qualifierClass = (String) qualifierMap.get("class");
+ if (qualifierClass != null) {
+ if (qualifierClass.equalsIgnoreCase("EOAndQualifier")) {
+ return Expression.AND;
+ } else if (qualifierClass.equalsIgnoreCase("EOOrQualifier")) {
+ return Expression.OR;
+ } else if (qualifierClass.equalsIgnoreCase("EONotQualifier")) {
+ return Expression.NOT;
+ }
+ }
+
+ return -1; // error
+ }
+
+ /**
+ * makeQualifier recursively builds an Expression for each condition in
+ * the qualifierMap and assembles from them the complex Expression to
+ * represent the entire EOFetchSpecification.
+ *
+ * @param qualifierMap
+ * - Map representation of EOFetchSpecification
+ * @return Expression translation of the EOFetchSpecification
+ */
+ static Expression makeQualifier(EOObjEntity entity, Map<String, ?> qualifierMap) {
+ if (isAggregate(qualifierMap)) {
+ // the fetch specification has more than one qualifier
+ int aggregateClass = aggregateExpressionClassForQualifier(qualifierMap); // AND,
+ // OR,
+ // NOT
+
+ if (aggregateClass == Expression.NOT) {
+ // NOT qualifiers only have one child, keyed with
+ // "qualifier"
+ Map<String, ?> child = (Map<String, ?>) qualifierMap.get("qualifier");
+ // build the child expression
+ Expression childExp = makeQualifier(entity, child);
+
+ return childExp.notExp(); // add the "not" clause and return
+ // the
+ // result
+ } else {
+ // AND, OR qualifiers can have multiple children, keyed with
+ // "qualifiers"
+ // get the list of children
+ List<Map<String, ?>> children = (List<Map<String, ?>>) qualifierMap.get("qualifiers");
+ if (children != null) {
+ ArrayList<Expression> childExpressions = new ArrayList<>();
+ // build an Expression for each child
+ for (Map<String, ?> child : children) {
+ Expression childExp = makeQualifier(entity, child);
+ childExpressions.add(childExp);
+ }
+ // join the child expressions and return the result
+ return ExpressionFactory.joinExp(aggregateClass, childExpressions);
+ }
+ }
+
+ } // end if isAggregate(qualifierMap)...
+
+ // the query has a single qualifier
+ // get expression selector type
+ String qualifierClass = (String) qualifierMap.get("class");
+
+ // the key or key path we're comparing
+ String key = null;
+ // the key, keyPath, value, or parameterized value against which
+ // we're
+ // comparing the key
+ Object comparisonValue = null;
+
+ if ("EOKeyComparisonQualifier".equals(qualifierClass)) {
+ // Comparing two keys or key paths
+ key = (String) qualifierMap.get("leftValue");
+ comparisonValue = qualifierMap.get("rightValue");
+ // FIXME: I think EOKeyComparisonQualifier style Expressions are not supported...
+ return null;
+ } else if ("EOKeyValueQualifier".equals(qualifierClass)) {
+ // Comparing key with a value or parameterized value
+ key = (String) qualifierMap.get("key");
+ Object value = qualifierMap.get("value");
+
+ if (value instanceof Map) {
+ Map<String, String> valueMap = (Map<String, String>) value;
+ String objClass = valueMap.get("class"); // can be a
+ // qualifier class or java type
+ if ("EOQualifierVariable".equals(objClass) && valueMap.containsKey("_key")) {
+ // make a parameterized expression
+ String paramName = valueMap.get("_key");
+ comparisonValue = new ExpressionParameter(paramName);
+ } else {
+ Object queryVal = valueMap.get("value");
+ if ("NSNumber".equals(objClass)) {
+ // comparison to NSNumber -- cast
+ comparisonValue = queryVal;
+ } else if ("EONull".equals(objClass)) {
+ // comparison to null
+ comparisonValue = null;
+ } else { // Could there be other types? boolean, date,
+ // etc.???
+ // no cast
+ comparisonValue = queryVal;
+ }
+ }
+
+ } else if (value instanceof String) {
+ // value expression
+ comparisonValue = value;
+ } // end if (value instanceof Map) else...
+ }
+
+ // check whether the key is an object path; if at least one
+ // component is not,
+ // switch to db path..
+
+ Expression keyExp = ExpressionFactory.exp(key);
+ try {
+ entity.lastPathComponent(keyExp, Collections.emptyMap());
+ } catch (ExpressionException e) {
+ try {
+ keyExp = entity.translateToDbPath(keyExp);
+ } catch (Exception dbpathEx) {
+ LOGGER.warn("Couldn't find {} in {} in EOModel", keyExp, entity.getName());
+ }
+ }
+
+ try {
+ Expression exp = ExpressionFactory.expressionOfType(expressionTypeForQualifier(qualifierMap));
+
+ exp.setOperand(0, keyExp);
+ exp.setOperand(1, comparisonValue);
+ return exp;
+ } catch (ExpressionException e) {
+ LOGGER.warn(e.getUnlabeledMessage());
+ return null;
+ }
+ }
+}
diff --git a/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOModelProcessor.java b/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOModelProcessor.java
index eb1eb79e1..079ccf07b 100644
--- a/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOModelProcessor.java
+++ b/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOModelProcessor.java
@@ -263,7 +263,7 @@ public class EOModelProcessor {
// qualifiers
Map<String, ?> qualifierMap = (Map<String, ?>) plistMap.get("qualifier");
if (qualifierMap != null && !qualifierMap.isEmpty()) {
- descriptor.setQualifier(EOQuery.EOFetchSpecificationParser.makeQualifier((EOObjEntity) root, qualifierMap));
+ descriptor.setQualifier(EOFetchSpecificationParser.makeQualifier((EOObjEntity) root, qualifierMap));
}
// prefetches
diff --git a/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOObjEntity.java b/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOObjEntity.java
index 53cba8228..515e47bdf 100644
--- a/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOObjEntity.java
+++ b/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOObjEntity.java
@@ -83,7 +83,7 @@ public class EOObjEntity extends ObjEntity {
* @since 1.2
*/
// TODO: andrus, 5/27/2006 - make public after 1.2. Also maybe move entity
- // initialization code from EOModelProcessor to this class, kind of like EOQuery does.
+ // initialization code from EOModelProcessor to this class.
Map getEoMap() {
return eoMap;
}
@@ -92,7 +92,7 @@ public class EOObjEntity extends ObjEntity {
* @since 1.2
*/
// TODO: andrus, 5/27/2006 - make public after 1.2. Also maybe move entity
- // initialization code from EOModelProcessor to this class, kind of like EOQuery does.
+ // initialization code from EOModelProcessor to this class.
void setEoMap(Map eoMap) {
this.eoMap = eoMap;
}
diff --git a/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOQuery.java b/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOQuery.java
deleted file mode 100644
index 5fecd4bc6..000000000
--- a/cayenne-wocompat/src/main/java/org/apache/cayenne/wocompat/EOQuery.java
+++ /dev/null
@@ -1,495 +0,0 @@
-/*****************************************************************
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * https://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- ****************************************************************/
-
-package org.apache.cayenne.wocompat;
-
-import org.apache.cayenne.exp.Expression;
-import org.apache.cayenne.exp.ExpressionException;
-import org.apache.cayenne.exp.ExpressionFactory;
-import org.apache.cayenne.exp.ExpressionParameter;
-import org.apache.cayenne.exp.parser.ASTObjPath;
-import org.apache.cayenne.map.Entity;
-import org.apache.cayenne.map.ObjAttribute;
-import org.apache.cayenne.map.ObjEntity;
-import org.apache.cayenne.map.ObjRelationship;
-import org.apache.cayenne.query.ObjectSelect;
-import org.apache.cayenne.query.PrefetchTreeNode;
-import org.apache.cayenne.query.SortOrder;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * A descriptor of SelectQuery loaded from EOModel. It is an informal
- * "decorator" of Cayenne SelectQuery to provide access to the extra information
- * of WebObjects EOFetchSpecification.
- *
- * @since 1.1
- * @since 5.0 this query extends {@link ObjectSelect}
- */
-@SuppressWarnings("unchecked")
-public class EOQuery<T> extends ObjectSelect<T> {
-
- protected Map<String, ?> plistMap;
- protected Map<String, String> bindings;
-
- public EOQuery(ObjEntity root, Map<String, ?> plistMap) {
- super();
- entityName(root.getName());
- setRoot(root);
- this.plistMap = plistMap;
- initFromPlist(plistMap);
- }
-
- protected void initFromPlist(Map<String, ?> plistMap) {
-
- if("YES".equalsIgnoreCase((String) plistMap.get("usesDistinct"))) {
- distinct();
- }
-
- Object fetchLimit = plistMap.get("fetchLimit");
- if (fetchLimit != null) {
- try {
- if (fetchLimit instanceof Number) {
- limit(((Number) fetchLimit).intValue());
- } else {
- limit(Integer.parseInt(fetchLimit.toString()));
- }
- } catch (NumberFormatException nfex) {
- // ignoring...
- }
- }
-
- // sort orderings
- List<Map<String, String>> orderings = (List<Map<String, String>>) plistMap.get("sortOrderings");
- if (orderings != null && !orderings.isEmpty()) {
- for (Map<String, String> ordering : orderings) {
- boolean asc = !"compareDescending:".equals(ordering.get("selectorName"));
- String key = ordering.get("key");
- if (key != null) {
- orderBy(key, asc ? SortOrder.ASCENDING : SortOrder.DESCENDING);
- }
- }
- }
-
- // qualifiers
- Map<String, ?> qualifierMap = (Map<String, ?>) plistMap.get("qualifier");
- if (qualifierMap != null && !qualifierMap.isEmpty()) {
- where(makeQualifier(qualifierMap));
- }
-
- // prefetches
- List<?> prefetches = (List<?>) plistMap.get("prefetchingRelationshipKeyPaths");
- if (prefetches != null && !prefetches.isEmpty()) {
- for (Object prefetch : prefetches) {
- prefetch((String) prefetch, PrefetchTreeNode.UNDEFINED_SEMANTICS);
- }
- }
-
- // data rows - note that we do not support fetching individual columns
- // in the
- // modeler...
- if (plistMap.containsKey("rawRowKeyPaths")) {
- fetchDataRows();
- }
- }
-
- public Collection<String> getBindingNames() {
- if (bindings == null) {
- initBindings();
- }
-
- return bindings.keySet();
- }
-
- public String bindingClass(String name) {
- if (bindings == null) {
- initBindings();
- }
-
- return bindings.get(name);
- }
-
- private synchronized void initBindings() {
- if (bindings != null) {
- return;
- }
-
- bindings = new HashMap<>();
-
- if (!(root instanceof Entity)) {
- return;
- }
-
- Map<String, ?> qualifier = (Map<String, ?>) plistMap.get("qualifier");
- initBindings(bindings, (Entity<?,?,?>) root, qualifier);
- }
-
- private void initBindings(Map<String,String> bindings, Entity<?,?,?> entity, Map<String, ?> qualifier) {
- if (qualifier == null) {
- return;
- }
-
- if ("EOKeyValueQualifier".equals(qualifier.get("class"))) {
- String key = (String) qualifier.get("key");
- if (key == null) {
- return;
- }
-
- Object value = qualifier.get("value");
- if (!(value instanceof Map)) {
- return;
- }
-
- Map<String, ?> valueMap = (Map<String, ?>) value;
- if (!"EOQualifierVariable".equals(valueMap.get("class")) || !valueMap.containsKey("_key")) {
- return;
- }
-
- String name = (String) valueMap.get("_key");
- String className = null;
-
- // we don't know whether its obj path or db path, so the expression
- // can blow
- // ... in fact we can't support DB Path as the key is different from
- // external
- // name,
- // so we will use Object type for all DB path...
- try {
- Object lastObject = new ASTObjPath(key).evaluate(entity);
-
- if (lastObject instanceof ObjAttribute) {
- className = ((ObjAttribute) lastObject).getType();
- } else if (lastObject instanceof ObjRelationship) {
- ObjEntity target = ((ObjRelationship) lastObject).getTargetEntity();
- if (target != null) {
- className = target.getClassName();
- }
- }
- } catch (ExpressionException ex) {
- className = "java.lang.Object";
- }
-
- if (className == null) {
- className = "java.lang.Object";
- }
-
- bindings.put(name, className);
-
- return;
- }
-
- List<Map<String, ?>> children = (List<Map<String, ?>>) qualifier.get("qualifiers");
- if (children != null) {
- for (Map<String, ?> child : children) {
- initBindings(bindings, entity, child);
- }
- }
- }
-
- /**
- * Creates the Expression equivalent of the EOFetchSpecification represented
- * by the Map.
- *
- * @param qualifierMap
- * - FetchSpecification to translate
- * @return Expression equivalent to FetchSpecification
- */
- public synchronized Expression makeQualifier(Map<String, ?> qualifierMap) {
- if (qualifierMap == null) {
- return null;
- }
-
- return EOFetchSpecificationParser.makeQualifier((EOObjEntity) getRoot(), qualifierMap);
- }
-
- /**
- * EOFetchSpecificationParser parses EOFetchSpecifications from a
- * WebObjects-style EOModel. It recursively builds Cayenne Expression
- * objects and assembles them into the final aggregate Expression.
- */
- static class EOFetchSpecificationParser {
-
- // Xcode/EOModeler expressions have a colon at the end of the selector
- // name
- // (just like standard Objective-C syntax). WOLips does not. Add both
- // sets to the hash map to handle both types of models.
-
- // Selector strings (Java-base).
- static final String IS_EQUAL_TO = "isEqualTo";
- static final String IS_NOT_EQUAL_TO = "isNotEqualTo";
- static final String IS_LIKE = "isLike";
- static final String CASE_INSENSITIVE_LIKE = "isCaseInsensitiveLike";
- static final String IS_LESS_THAN = "isLessThan";
- static final String IS_LESS_THAN_OR_EQUAL_TO = "isLessThanOrEqualTo";
- static final String IS_GREATER_THAN = "isGreaterThan";
- static final String IS_GREATER_THAN_OR_EQUAL_TO = "isGreaterThanOrEqualTo";
-
- private static final String OBJ_C = ":"; // Objective-C syntax addition.
-
- private static Map<String, Integer> selectorToExpressionBridge;
- private static final Logger LOGGER = LoggerFactory.getLogger(EOFetchSpecificationParser.class);
-
- /**
- * selectorToExpressionBridge is just a mapping of EOModeler's selector
- * types to Cayenne Expression types.
- *
- * @return HashMap of Expression types, keyed by the corresponding
- * selector name
- */
- static synchronized Map<String, Integer> selectorToExpressionBridge() {
- // Initialize selectorToExpressionBridge if needed.
- if (null == selectorToExpressionBridge) {
- selectorToExpressionBridge = new HashMap<>();
-
- selectorToExpressionBridge.put(IS_EQUAL_TO, Expression.EQUAL_TO);
- selectorToExpressionBridge.put(IS_EQUAL_TO + OBJ_C, Expression.EQUAL_TO);
-
- selectorToExpressionBridge.put(IS_NOT_EQUAL_TO, Expression.NOT_EQUAL_TO);
- selectorToExpressionBridge.put(IS_NOT_EQUAL_TO + OBJ_C, Expression.NOT_EQUAL_TO);
-
- selectorToExpressionBridge.put(IS_LIKE, Expression.LIKE);
- selectorToExpressionBridge.put(IS_LIKE + OBJ_C, Expression.LIKE);
-
- selectorToExpressionBridge.put(CASE_INSENSITIVE_LIKE, Expression.LIKE_IGNORE_CASE);
- selectorToExpressionBridge.put(CASE_INSENSITIVE_LIKE + OBJ_C, Expression.LIKE_IGNORE_CASE);
-
- selectorToExpressionBridge.put(IS_LESS_THAN, Expression.LESS_THAN);
- selectorToExpressionBridge.put(IS_LESS_THAN + OBJ_C, Expression.LESS_THAN);
-
- selectorToExpressionBridge.put(IS_LESS_THAN_OR_EQUAL_TO, Expression.LESS_THAN_EQUAL_TO);
- selectorToExpressionBridge.put(IS_LESS_THAN_OR_EQUAL_TO + OBJ_C, Expression.LESS_THAN_EQUAL_TO);
-
- selectorToExpressionBridge.put(IS_GREATER_THAN, Expression.GREATER_THAN);
- selectorToExpressionBridge.put(IS_GREATER_THAN + OBJ_C, Expression.GREATER_THAN);
-
- selectorToExpressionBridge.put(IS_GREATER_THAN_OR_EQUAL_TO, Expression.GREATER_THAN_EQUAL_TO);
- selectorToExpressionBridge.put(IS_GREATER_THAN_OR_EQUAL_TO + OBJ_C, Expression.GREATER_THAN_EQUAL_TO);
- }
-
- return selectorToExpressionBridge;
- }
-
- /**
- * isAggregate determines whether a qualifier is "aggregate" -- has
- * children -- or "simple".
- *
- * @param qualifier
- * - a Map containing the qualifier settings
- * @return boolean indicating whether the qualifier is "aggregate"
- * qualifier
- */
- static boolean isAggregate(Map<String, ?> qualifier) {
- boolean result = true;
-
- String theClass = (String) qualifier.get("class");
- if (theClass == null) {
- return false; // should maybe throw an exception?
- }
- if (theClass.equalsIgnoreCase("EOKeyValueQualifier")
- || theClass.equalsIgnoreCase("EOKeyComparisonQualifier")) {
- result = false;
- }
-
- return result;
- }
-
- /**
- * expressionTypeForQualifier looks at a qualifier containing the
- * EOModeler FetchSpecification and returns the equivalent Cayenne
- * Expression type for its selector.
- *
- * @param qualifierMap
- * - a Map containing the qualifier settings to examine.
- * @return int Expression type
- */
- static int expressionTypeForQualifier(Map<String, ?> qualifierMap) {
- // get selector
- String selector = (String) qualifierMap.get("selectorName");
- return expressionTypeForSelector(selector);
- }
-
- /**
- * expressionTypeForSelector looks at a selector from an EOModeler
- * FetchSpecification and returns the equivalent Cayenne Expression
- * type.
- *
- * @param selector
- * - a String containing the selector name.
- * @return int Expression type
- */
- static int expressionTypeForSelector(String selector) {
- Integer expType = selectorToExpressionBridge().get(selector);
- return (expType != null ? expType : -1);
- }
-
- /**
- * aggregateExpressionClassForQualifier looks at a qualifer and returns
- * the aggregate type: one of Expression.AND, Expression.OR, or
- * Expression.NOT
- *
- * @param qualifierMap
- * - containing the qualifier to examine
- * @return int aggregate Expression type
- */
- static int aggregateExpressionClassForQualifier(Map<String, ?> qualifierMap) {
- String qualifierClass = (String) qualifierMap.get("class");
- if (qualifierClass != null) {
- if (qualifierClass.equalsIgnoreCase("EOAndQualifier")) {
- return Expression.AND;
- } else if (qualifierClass.equalsIgnoreCase("EOOrQualifier")) {
- return Expression.OR;
- } else if (qualifierClass.equalsIgnoreCase("EONotQualifier")) {
- return Expression.NOT;
- }
- }
-
- return -1; // error
- }
-
- /**
- * makeQualifier recursively builds an Expression for each condition in
- * the qualifierMap and assembles from them the complex Expression to
- * represent the entire EOFetchSpecification.
- *
- * @param qualifierMap
- * - Map representation of EOFetchSpecification
- * @return Expression translation of the EOFetchSpecification
- */
- static Expression makeQualifier(EOObjEntity entity, Map<String, ?> qualifierMap) {
- if (isAggregate(qualifierMap)) {
- // the fetch specification has more than one qualifier
- int aggregateClass = aggregateExpressionClassForQualifier(qualifierMap); // AND,
- // OR,
- // NOT
-
- if (aggregateClass == Expression.NOT) {
- // NOT qualifiers only have one child, keyed with
- // "qualifier"
- Map<String, ?> child = (Map<String, ?>) qualifierMap.get("qualifier");
- // build the child expression
- Expression childExp = makeQualifier(entity, child);
-
- return childExp.notExp(); // add the "not" clause and return
- // the
- // result
- } else {
- // AND, OR qualifiers can have multiple children, keyed with
- // "qualifiers"
- // get the list of children
- List<Map<String, ?>> children = (List<Map<String, ?>>) qualifierMap.get("qualifiers");
- if (children != null) {
- ArrayList<Expression> childExpressions = new ArrayList<>();
- // build an Expression for each child
- for (Map<String, ?> child : children) {
- Expression childExp = makeQualifier(entity, child);
- childExpressions.add(childExp);
- }
- // join the child expressions and return the result
- return ExpressionFactory.joinExp(aggregateClass, childExpressions);
- }
- }
-
- } // end if isAggregate(qualifierMap)...
-
- // the query has a single qualifier
- // get expression selector type
- String qualifierClass = (String) qualifierMap.get("class");
-
- // the key or key path we're comparing
- String key = null;
- // the key, keyPath, value, or parameterized value against which
- // we're
- // comparing the key
- Object comparisonValue = null;
-
- if ("EOKeyComparisonQualifier".equals(qualifierClass)) {
- // Comparing two keys or key paths
- key = (String) qualifierMap.get("leftValue");
- comparisonValue = qualifierMap.get("rightValue");
- // FIXME: I think EOKeyComparisonQualifier style Expressions are not supported...
- return null;
- } else if ("EOKeyValueQualifier".equals(qualifierClass)) {
- // Comparing key with a value or parameterized value
- key = (String) qualifierMap.get("key");
- Object value = qualifierMap.get("value");
-
- if (value instanceof Map) {
- Map<String, String> valueMap = (Map<String, String>) value;
- String objClass = valueMap.get("class"); // can be a
- // qualifier class or java type
- if ("EOQualifierVariable".equals(objClass) && valueMap.containsKey("_key")) {
- // make a parameterized expression
- String paramName = valueMap.get("_key");
- comparisonValue = new ExpressionParameter(paramName);
- } else {
- Object queryVal = valueMap.get("value");
- if ("NSNumber".equals(objClass)) {
- // comparison to NSNumber -- cast
- comparisonValue = queryVal;
- } else if ("EONull".equals(objClass)) {
- // comparison to null
- comparisonValue = null;
- } else { // Could there be other types? boolean, date,
- // etc.???
- // no cast
- comparisonValue = queryVal;
- }
- }
-
- } else if (value instanceof String) {
- // value expression
- comparisonValue = value;
- } // end if (value instanceof Map) else...
- }
-
- // check whether the key is an object path; if at least one
- // component is not,
- // switch to db path..
-
- Expression keyExp = ExpressionFactory.exp(key);
- try {
- entity.lastPathComponent(keyExp, Collections.emptyMap());
- } catch (ExpressionException e) {
- try {
- keyExp = entity.translateToDbPath(keyExp);
- } catch (Exception dbpathEx) {
- LOGGER.warn("Couldn't find {} in {} in EOModel", keyExp, entity.getName());
- }
- }
-
- try {
- Expression exp = ExpressionFactory.expressionOfType(expressionTypeForQualifier(qualifierMap));
-
- exp.setOperand(0, keyExp);
- exp.setOperand(1, comparisonValue);
- return exp;
- } catch (ExpressionException e) {
- LOGGER.warn(e.getUnlabeledMessage());
- return null;
- }
- }
- }
-}
diff --git a/cayenne-wocompat/src/test/java/org/apache/cayenne/wocompat/EOQueryTest.java b/cayenne-wocompat/src/test/java/org/apache/cayenne/wocompat/EOFetchSpecificationParserTest.java
similarity index 55%
rename from cayenne-wocompat/src/test/java/org/apache/cayenne/wocompat/EOQueryTest.java
rename to cayenne-wocompat/src/test/java/org/apache/cayenne/wocompat/EOFetchSpecificationParserTest.java
index ab423976c..8761dd4cc 100644
--- a/cayenne-wocompat/src/test/java/org/apache/cayenne/wocompat/EOQueryTest.java
+++ b/cayenne-wocompat/src/test/java/org/apache/cayenne/wocompat/EOFetchSpecificationParserTest.java
@@ -20,48 +20,55 @@
package org.apache.cayenne.wocompat;
import org.apache.cayenne.map.DataMap;
+import org.apache.cayenne.map.QueryDescriptor;
+import org.apache.cayenne.map.SelectQueryDescriptor;
+import org.apache.cayenne.query.ObjectSelect;
+import org.apache.cayenne.query.Ordering;
import org.apache.cayenne.query.PrefetchTreeNode;
import org.junit.jupiter.api.Test;
import java.net.URL;
import java.util.Collection;
-import java.util.Map;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertTrue;
-public class EOQueryTest {
+public class EOFetchSpecificationParserTest {
@Test
- public void constructor() throws Exception {
+ public void loadedFetchSpecification() throws Exception {
URL url = getClass().getClassLoader().getResource("wotests/fetchspec.eomodeld/");
assertNotNull(url);
- EOModelProcessor processor = new EOModelProcessor();
- DataMap map = processor.loadEOModel(url);
+ DataMap map = new EOModelProcessor().loadEOModel(url);
- @SuppressWarnings("unchecked")
- Map<String, ?> fspecMap = (Map<String, ?>) PropertyListSerialization.propertyListFromStream(getClass()
- .getClassLoader()
- .getResourceAsStream("wotests/fetchspec.eomodeld/Entity1.fspec"));
- assertNotNull(fspecMap);
- assertNotNull(fspecMap.get("E1FS1"));
+ QueryDescriptor descriptor = map.getQueryDescriptor("Entity1_E1FS1");
+ assertNotNull(descriptor);
+ SelectQueryDescriptor selectDescriptor = assertInstanceOf(SelectQueryDescriptor.class, descriptor);
+ assertSame(map.getObjEntity("Entity1"), selectDescriptor.getRoot());
- @SuppressWarnings("unchecked")
- EOQuery query = new EOQuery(map.getObjEntity("Entity1"), (Map<String, ?>) fspecMap.get("E1FS1"));
-
- assertNotNull(query.getWhere());
+ assertNotNull(selectDescriptor.getQualifier());
assertEquals(
"(name = \"aa\") and (db:ID >= 7) and ((e2.name = \"bb\") or (db:e2.ID != 5))",
- query.getWhere().toString());
+ selectDescriptor.getQualifier().toString());
+
+ ObjectSelect<?> query = selectDescriptor.buildQuery();
assertNotNull(query.getPrefetches());
+ Collection<PrefetchTreeNode> prefetches = query.getPrefetches().getChildren();
+ assertEquals(1, prefetches.size());
+ assertEquals("e2", prefetches.iterator().next().getName());
- Collection children = query.getPrefetches().getChildren();
- assertEquals(1, children.size());
- assertEquals("e2", ((PrefetchTreeNode) children.iterator().next()).getName());
+ Collection<Ordering> orderings = query.getOrderings();
+ assertEquals(1, orderings.size());
+ Ordering ordering = orderings.iterator().next();
+ assertEquals("name", ordering.getSortSpecString());
+ assertFalse(ordering.isAscending());
assertTrue(query.isFetchingDataRows());
assertEquals(500, query.getLimit());
(cayenne) 01/02: refactoring Select - make all trivially implemented common methods "default" methods of the interface
Posted by aa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
asf-gitbox-commits pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/cayenne.git
commit 4eb038c8ad767c22990ca212d4d055c6ee0e6a22
Author: Andrus Adamchik <an...@objectstyle.com>
AuthorDate: Sun Aug 30 11:43:35 2026 -0400
refactoring Select - make all trivially implemented common methods "default" methods of the interface
---
.../org/apache/cayenne/query/FluentSelect.java | 24 ----------------------
.../org/apache/cayenne/query/MappedSelect.java | 22 --------------------
.../java/org/apache/cayenne/query/SQLSelect.java | 23 ---------------------
.../main/java/org/apache/cayenne/query/Select.java | 22 +++++++++++++++-----
.../java/org/apache/cayenne/query/SelectById.java | 23 ---------------------
5 files changed, 17 insertions(+), 97 deletions(-)
diff --git a/cayenne/src/main/java/org/apache/cayenne/query/FluentSelect.java b/cayenne/src/main/java/org/apache/cayenne/query/FluentSelect.java
index 5491c2047..093fc2731 100644
--- a/cayenne/src/main/java/org/apache/cayenne/query/FluentSelect.java
+++ b/cayenne/src/main/java/org/apache/cayenne/query/FluentSelect.java
@@ -29,10 +29,6 @@ import java.util.Map;
import java.util.function.Function;
import org.apache.cayenne.CayenneRuntimeException;
-import org.apache.cayenne.ObjectContext;
-import org.apache.cayenne.ResultBatchIterator;
-import org.apache.cayenne.ResultIterator;
-import org.apache.cayenne.ResultIteratorCallback;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.exp.ExpressionFactory;
import org.apache.cayenne.exp.property.Property;
@@ -485,30 +481,10 @@ public abstract class FluentSelect<T, S extends FluentSelect<T, S>> extends Abst
}
}
- @Override
- public List<T> select(ObjectContext context) {
- return context.select(this);
- }
- @Override
- public T selectOne(ObjectContext context) {
- return context.selectOne(this);
- }
- @Override
- public void iterate(ObjectContext context, ResultIteratorCallback<T> callback) {
- context.iterate(this, callback);
- }
- @Override
- public ResultIterator<T> iterator(ObjectContext context) {
- return context.iterator(this);
- }
- @Override
- public ResultBatchIterator<T> batchIterator(ObjectContext context, int size) {
- return context.batchIterator(this, size);
- }
@Override
public SQLAction createSQLAction(SQLActionVisitor visitor) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/query/MappedSelect.java b/cayenne/src/main/java/org/apache/cayenne/query/MappedSelect.java
index c6322221f..f87518113 100644
--- a/cayenne/src/main/java/org/apache/cayenne/query/MappedSelect.java
+++ b/cayenne/src/main/java/org/apache/cayenne/query/MappedSelect.java
@@ -24,9 +24,6 @@ import java.util.Map;
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.ObjectContext;
-import org.apache.cayenne.ResultBatchIterator;
-import org.apache.cayenne.ResultIterator;
-import org.apache.cayenne.ResultIteratorCallback;
import org.apache.cayenne.map.EntityResolver;
import org.apache.cayenne.map.QueryDescriptor;
@@ -151,34 +148,15 @@ public class MappedSelect<T> extends AbstractMappedQuery implements Select<T> {
return (MappedSelect<T>) super.param(name, value);
}
- public List<T> select(ObjectContext context) {
- return context.select(this);
- }
- @Override
- public T selectOne(ObjectContext context) {
- return context.selectOne(this);
- }
@Override
public T selectFirst(ObjectContext context) {
return context.selectFirst(limit(1));
}
- @Override
- public void iterate(ObjectContext context, ResultIteratorCallback<T> callback) {
- context.iterate(this, callback);
- }
- @Override
- public ResultIterator<T> iterator(ObjectContext context) {
- return context.iterator(this);
- }
- @Override
- public ResultBatchIterator<T> batchIterator(ObjectContext context, int size) {
- return context.batchIterator(this, size);
- }
@Override
protected Query createReplacementQuery(EntityResolver resolver) {
diff --git a/cayenne/src/main/java/org/apache/cayenne/query/SQLSelect.java b/cayenne/src/main/java/org/apache/cayenne/query/SQLSelect.java
index 4c7b93d6d..8b122a5e4 100644
--- a/cayenne/src/main/java/org/apache/cayenne/query/SQLSelect.java
+++ b/cayenne/src/main/java/org/apache/cayenne/query/SQLSelect.java
@@ -29,9 +29,6 @@ import java.util.function.Function;
import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.DataRow;
import org.apache.cayenne.ObjectContext;
-import org.apache.cayenne.ResultBatchIterator;
-import org.apache.cayenne.ResultIterator;
-import org.apache.cayenne.ResultIteratorCallback;
import org.apache.cayenne.map.DataMap;
import org.apache.cayenne.map.EntityResolver;
@@ -199,35 +196,15 @@ public class SQLSelect<T> extends IndirectQuery implements Select<T> {
this.pageSize = QueryMetadata.PAGE_SIZE_DEFAULT;
}
- @Override
- public List<T> select(ObjectContext context) {
- return context.select(this);
- }
- @Override
- public T selectOne(ObjectContext context) {
- return context.selectOne(this);
- }
@Override
public T selectFirst(ObjectContext context) {
return context.selectFirst(limit(1));
}
- @Override
- public void iterate(ObjectContext context, ResultIteratorCallback<T> callback) {
- context.iterate(this, callback);
- }
- @Override
- public ResultIterator<T> iterator(ObjectContext context) {
- return context.iterator(this);
- }
- @Override
- public ResultBatchIterator<T> batchIterator(ObjectContext context, int size) {
- return context.batchIterator(this, size);
- }
public boolean isFetchingDataRows() {
return isFetchingDataRows;
diff --git a/cayenne/src/main/java/org/apache/cayenne/query/Select.java b/cayenne/src/main/java/org/apache/cayenne/query/Select.java
index eddc7d669..bbcc3bb6a 100644
--- a/cayenne/src/main/java/org/apache/cayenne/query/Select.java
+++ b/cayenne/src/main/java/org/apache/cayenne/query/Select.java
@@ -39,7 +39,9 @@ public interface Select<T> extends Query {
*
* @since 4.0
*/
- List<T> select(ObjectContext context);
+ default List<T> select(ObjectContext context) {
+ return context.select(this);
+ }
/**
* Selects a single object using provided context. The query is expected to
@@ -51,7 +53,9 @@ public interface Select<T> extends Query {
*
* @since 4.0
*/
- T selectOne(ObjectContext context);
+ default T selectOne(ObjectContext context) {
+ return context.selectOne(this);
+ }
/**
* Selects a single object using provided context. The query itself can
@@ -71,6 +75,8 @@ public interface Select<T> extends Query {
*
* @since 4.0
*/
+ // TODO: downstream implementors call context.selectFirst(limit(1)), so it has side effect
+ // on "this" query. Limit optimizes generated SQL, so it is needed, but this is dirty
T selectFirst(ObjectContext context);
/**
@@ -83,7 +89,9 @@ public interface Select<T> extends Query {
*
* @since 4.0
*/
- void iterate(ObjectContext context, ResultIteratorCallback<T> callback);
+ default void iterate(ObjectContext context, ResultIteratorCallback<T> callback) {
+ context.iterate(this, callback);
+ }
/**
* Creates a ResultIterator based on the provided context. It is usually
@@ -98,7 +106,9 @@ public interface Select<T> extends Query {
*
* @since 4.0
*/
- ResultIterator<T> iterator(ObjectContext context);
+ default ResultIterator<T> iterator(ObjectContext context) {
+ return context.iterator(this);
+ }
/**
* Creates a ResultBatchIterator based on the provided context and batch
@@ -109,5 +119,7 @@ public interface Select<T> extends Query {
*
* @since 4.0
*/
- ResultBatchIterator<T> batchIterator(ObjectContext context, int size);
+ default ResultBatchIterator<T> batchIterator(ObjectContext context, int size) {
+ return context.batchIterator(this, size);
+ }
}
diff --git a/cayenne/src/main/java/org/apache/cayenne/query/SelectById.java b/cayenne/src/main/java/org/apache/cayenne/query/SelectById.java
index 4796a56fc..d5e11659e 100644
--- a/cayenne/src/main/java/org/apache/cayenne/query/SelectById.java
+++ b/cayenne/src/main/java/org/apache/cayenne/query/SelectById.java
@@ -22,9 +22,6 @@ import org.apache.cayenne.CayenneRuntimeException;
import org.apache.cayenne.DataRow;
import org.apache.cayenne.ObjectContext;
import org.apache.cayenne.ObjectId;
-import org.apache.cayenne.ResultBatchIterator;
-import org.apache.cayenne.ResultIterator;
-import org.apache.cayenne.ResultIteratorCallback;
import org.apache.cayenne.exp.Expression;
import org.apache.cayenne.map.EntityResolver;
import org.apache.cayenne.map.ObjEntity;
@@ -452,35 +449,15 @@ public class SelectById<T> extends IndirectQuery implements Select<T> {
this(root, idSpec, false);
}
- @Override
- public List<T> select(ObjectContext context) {
- return context.select(this);
- }
- @Override
- public T selectOne(ObjectContext context) {
- return context.selectOne(this);
- }
@Override
public T selectFirst(ObjectContext context) {
return context.selectFirst(this);
}
- @Override
- public void iterate(ObjectContext context, ResultIteratorCallback<T> callback) {
- context.iterate(this, callback);
- }
- @Override
- public ResultIterator<T> iterator(ObjectContext context) {
- return context.iterator(this);
- }
- @Override
- public ResultBatchIterator<T> batchIterator(ObjectContext context, int size) {
- return context.batchIterator(this, size);
- }
/**
* Instructs Cayenne to look for query results in the "local" cache when