cayenne-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ntimof...@apache.org
Subject cayenne git commit: Remove "recursive" generic from FluentSelect and split back ObjectSelect and ColumnSelect methods. This is a workaround for static compiling in Groovy that can't handle such generics.
Date Thu, 20 Apr 2017 12:00:33 GMT
Repository: cayenne
Updated Branches:
  refs/heads/master 4e268e756 -> 0e6f0df17


Remove "recursive" generic from FluentSelect and split back ObjectSelect and ColumnSelect
methods.
This is a workaround for static compiling in Groovy that can't handle such generics.


Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/0e6f0df1
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/0e6f0df1
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/0e6f0df1

Branch: refs/heads/master
Commit: 0e6f0df1714216e3b615e7ed6718693439175a10
Parents: 4e268e7
Author: Nikita Timofeev <stariy95@gmail.com>
Authored: Thu Apr 20 15:00:27 2017 +0300
Committer: Nikita Timofeev <stariy95@gmail.com>
Committed: Thu Apr 20 15:00:27 2017 +0300

----------------------------------------------------------------------
 .../org/apache/cayenne/query/ColumnSelect.java  | 331 +++++++++++++++-
 .../org/apache/cayenne/query/FluentSelect.java  | 391 +------------------
 .../org/apache/cayenne/query/ObjectSelect.java  | 378 +++++++++++++++++-
 3 files changed, 706 insertions(+), 394 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/cayenne/blob/0e6f0df1/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelect.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelect.java b/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelect.java
index b0f708c..ca9db48 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelect.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/ColumnSelect.java
@@ -19,14 +19,19 @@
 
 package org.apache.cayenne.query;
 
+import java.sql.Statement;
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 
+import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.exp.Expression;
 import org.apache.cayenne.exp.ExpressionFactory;
 import org.apache.cayenne.exp.Property;
+import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.EntityResolver;
+import org.apache.cayenne.map.ObjEntity;
 
 /**
  * <p>A helper builder for queries selecting individual properties based on the root
object.</p>
@@ -55,7 +60,7 @@ import org.apache.cayenne.map.EntityResolver;
  *
  * @since 4.0
  */
-public class ColumnSelect<T> extends FluentSelect<T, ColumnSelect<T>> {
+public class ColumnSelect<T> extends FluentSelect<T> {
 
     private Collection<Property<?>> columns;
     private boolean havingExpressionIsActive = false;
@@ -101,6 +106,323 @@ public class ColumnSelect<T> extends FluentSelect<T, ColumnSelect<T>>
{
     }
 
     /**
+     * Sets the type of the entity to fetch without changing the return type of
+     * the query.
+     *
+     * @return this object
+     */
+    public ColumnSelect<T> entityType(Class<?> entityType) {
+        return resetEntity(entityType, null, null);
+    }
+
+    /**
+     * Sets the {@link ObjEntity} name to fetch without changing the return type
+     * of the query. This form is most often used for generic entities that
+     * don't map to a distinct class.
+     *
+     * @return this object
+     */
+    public ColumnSelect<T> entityName(String entityName) {
+        return resetEntity(null, entityName, null);
+    }
+
+    /**
+     * Sets the {@link DbEntity} name to fetch without changing the return type
+     * of the query. This form is most often used for generic entities that
+     * don't map to a distinct class.
+     *
+     * @return this object
+     */
+    public ColumnSelect<T> dbEntityName(String dbEntityName) {
+        return resetEntity(null, null, dbEntityName);
+    }
+
+    @SuppressWarnings("unchecked")
+    private ColumnSelect<T> resetEntity(Class<?> entityType, String entityName,
String dbEntityName) {
+        this.entityType = entityType;
+        this.entityName = entityName;
+        this.dbEntityName = dbEntityName;
+        return (ColumnSelect<T>)this;
+    }
+
+    /**
+     * Appends a qualifier expression of this query. An equivalent to
+     * {@link #and(Expression...)} that can be used a syntactic sugar.
+     *
+     * @return this object
+     */
+    public ColumnSelect<T> where(Expression expression) {
+        return and(expression);
+    }
+
+    /**
+     * Appends a qualifier expression of this query, using provided expression
+     * String and an array of position parameters. This is an equivalent to
+     * calling "and".
+     *
+     * @return this object
+     */
+    public ColumnSelect<T> where(String expressionString, Object... parameters) {
+        return and(ExpressionFactory.exp(expressionString, parameters));
+    }
+
+    /**
+     * AND's provided expressions to the existing WHERE clause expression.
+     *
+     * @return this object
+     */
+    public ColumnSelect<T> and(Expression... expressions) {
+        if (expressions == null || expressions.length == 0) {
+            return this;
+        }
+
+        return and(Arrays.asList(expressions));
+    }
+
+    /**
+     * OR's provided expressions to the existing WHERE clause expression.
+     *
+     * @return this object
+     */
+    @SuppressWarnings("unchecked")
+    public ColumnSelect<T> or(Expression... expressions) {
+        if (expressions == null || expressions.length == 0) {
+            return this;
+        }
+
+        return or(Arrays.asList(expressions));
+    }
+
+    /**
+     * Add an ascending ordering on the given property. If there is already an ordering
+     * on this query then add this ordering with a lower priority.
+     *
+     * @param property the property to sort on
+     * @return this object
+     */
+    public ColumnSelect<T> orderBy(String property) {
+        return orderBy(new Ordering(property));
+    }
+
+    /**
+     * Add an ordering on the given property. If there is already an ordering
+     * on this query then add this ordering with a lower priority.
+     *
+     * @param property  the property to sort on
+     * @param sortOrder the direction of the ordering
+     * @return this object
+     */
+    public ColumnSelect<T> orderBy(String property, SortOrder sortOrder) {
+        return orderBy(new Ordering(property, sortOrder));
+    }
+
+    /**
+     * Add one or more orderings to this query.
+     *
+     * @return this object
+     */
+    public ColumnSelect<T> orderBy(Ordering... orderings) {
+
+        if (orderings == null) {
+            return this;
+        }
+
+        if (this.orderings == null) {
+            this.orderings = new ArrayList<>(orderings.length);
+        }
+
+        Collections.addAll(this.orderings, orderings);
+
+        return this;
+    }
+
+    /**
+     * Adds a list of orderings to this query.
+     *
+     * @return this object
+     */
+    public ColumnSelect<T> orderBy(Collection<Ordering> orderings) {
+
+        if (orderings == null) {
+            return this;
+        }
+
+        if (this.orderings == null) {
+            this.orderings = new ArrayList<>(orderings.size());
+        }
+
+        this.orderings.addAll(orderings);
+
+        return this;
+    }
+
+    /**
+     * Merges prefetch into the query prefetch tree.
+     *
+     * @return this object
+     */
+    public ColumnSelect<T> prefetch(PrefetchTreeNode prefetch) {
+
+        if (prefetch == null) {
+            return this;
+        }
+
+        if (prefetches == null) {
+            prefetches = new PrefetchTreeNode();
+        }
+
+        prefetches.merge(prefetch);
+        return this;
+    }
+
+    /**
+     * Merges a prefetch path with specified semantics into the query prefetch
+     * tree.
+     *
+     * @return this object
+     */
+    public ColumnSelect<T> prefetch(String path, int semantics) {
+
+        if (path == null) {
+            return this;
+        }
+
+        if (prefetches == null) {
+            prefetches = new PrefetchTreeNode();
+        }
+
+        prefetches.addPath(path).setSemantics(semantics);
+        return this;
+    }
+
+    /**
+     * Resets query fetch limit - a parameter that defines max number of objects
+     * that should be ever be fetched from the database.
+     */
+    public ColumnSelect<T> limit(int fetchLimit) {
+        if (this.limit != fetchLimit) {
+            this.limit = fetchLimit;
+            this.replacementQuery = null;
+        }
+
+        return this;
+    }
+
+    /**
+     * Resets query fetch offset - a parameter that defines how many objects
+     * should be skipped when reading data from the database.
+     */
+    public ColumnSelect<T> offset(int fetchOffset) {
+        if (this.offset != fetchOffset) {
+            this.offset = fetchOffset;
+            this.replacementQuery = null;
+        }
+
+        return this;
+    }
+
+    /**
+     * Resets query page size. A non-negative page size enables query result
+     * pagination that saves memory and processing time for large lists if only
+     * parts of the result are ever going to be accessed.
+     */
+    public ColumnSelect<T> pageSize(int pageSize) {
+        if (this.pageSize != pageSize) {
+            this.pageSize = pageSize;
+            this.replacementQuery = null;
+        }
+
+        return this;
+    }
+
+    /**
+     * Sets fetch size of the PreparedStatement generated for this query. Only
+     * non-negative values would change the default size.
+     *
+     * @see Statement#setFetchSize(int)
+     */
+    public ColumnSelect<T> statementFetchSize(int size) {
+        if (this.statementFetchSize != size) {
+            this.statementFetchSize = size;
+            this.replacementQuery = null;
+        }
+
+        return this;
+    }
+
+    public ColumnSelect<T> cacheStrategy(QueryCacheStrategy strategy) {
+        if (this.cacheStrategy != strategy) {
+            this.cacheStrategy = strategy;
+            this.replacementQuery = null;
+        }
+
+        if(this.cacheGroup != null) {
+            this.cacheGroup = null;
+            this.replacementQuery = null;
+        }
+
+        return this;
+    }
+
+    public ColumnSelect<T> cacheStrategy(QueryCacheStrategy strategy, String cacheGroup)
{
+        return cacheStrategy(strategy).cacheGroup(cacheGroup);
+    }
+
+    public ColumnSelect<T> cacheGroup(String cacheGroup) {
+        this.cacheGroup = cacheGroup;
+        this.replacementQuery = null;
+        return this;
+    }
+
+    /**
+     * Instructs Cayenne to look for query results in the "local" cache when
+     * running the query. This is a short-hand notation for:
+     * <p>
+     * <pre>
+     * query.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE, cacheGroup);
+     * </pre>
+     */
+    public ColumnSelect<T> localCache(String cacheGroup) {
+        return cacheStrategy(QueryCacheStrategy.LOCAL_CACHE, cacheGroup);
+    }
+
+    /**
+     * Instructs Cayenne to look for query results in the "local" cache when
+     * running the query. This is a short-hand notation for:
+     * <p>
+     * <pre>
+     * query.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+     * </pre>
+     */
+    public ColumnSelect<T> localCache() {
+        return cacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+    }
+
+    /**
+     * Instructs Cayenne to look for query results in the "shared" cache when
+     * running the query. This is a short-hand notation for:
+     * <p>
+     * <pre>
+     * query.cacheStrategy(QueryCacheStrategy.SHARED_CACHE, cacheGroup);
+     * </pre>
+     */
+    public ColumnSelect<T> sharedCache(String cacheGroup) {
+        return cacheStrategy(QueryCacheStrategy.SHARED_CACHE, cacheGroup);
+    }
+
+    /**
+     * Instructs Cayenne to look for query results in the "shared" cache when
+     * running the query. This is a short-hand notation for:
+     * <p>
+     * <pre>
+     * query.cacheStrategy(QueryCacheStrategy.SHARED_CACHE);
+     * </pre>
+     */
+    public ColumnSelect<T> sharedCache() {
+        return cacheStrategy(QueryCacheStrategy.SHARED_CACHE);
+    }
+
+    /**
      * <p>Add properties to select.</p>
      * <p>Can be any properties that can be resolved against root entity type
      * (root entity properties, function call expressions, properties of relationships, etc).</p>
@@ -242,7 +564,6 @@ public class ColumnSelect<T> extends FluentSelect<T, ColumnSelect<T>>
{
      *
      * @return this object
      */
-    @SuppressWarnings("unchecked")
     public ColumnSelect<T> and(Collection<Expression> expressions) {
 
         if (expressions == null || expressions.isEmpty()) {
@@ -269,7 +590,6 @@ public class ColumnSelect<T> extends FluentSelect<T, ColumnSelect<T>>
{
      *
      * @return this object
      */
-    @SuppressWarnings("unchecked")
     public ColumnSelect<T> or(Collection<Expression> expressions) {
         if (expressions == null || expressions.isEmpty()) {
             return this;
@@ -334,4 +654,9 @@ public class ColumnSelect<T> extends FluentSelect<T, ColumnSelect<T>>
{
     public Expression getHaving() {
         return having;
     }
+
+    @Override
+    public T selectFirst(ObjectContext context) {
+        return context.selectFirst(limit(1));
+    }
 }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/0e6f0df1/cayenne-server/src/main/java/org/apache/cayenne/query/FluentSelect.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/FluentSelect.java b/cayenne-server/src/main/java/org/apache/cayenne/query/FluentSelect.java
index 91204af..8f2360c 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/FluentSelect.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/FluentSelect.java
@@ -19,11 +19,7 @@
 
 package org.apache.cayenne.query;
 
-import java.sql.Statement;
-import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collection;
-import java.util.Collections;
 import java.util.List;
 
 import org.apache.cayenne.CayenneRuntimeException;
@@ -32,7 +28,6 @@ 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.map.DbEntity;
 import org.apache.cayenne.map.EntityResolver;
 import org.apache.cayenne.map.ObjEntity;
@@ -42,7 +37,7 @@ import org.apache.cayenne.map.ObjEntity;
  *
  * @since 4.0
  */
-public abstract class FluentSelect<T, S extends FluentSelect<T, S>> extends IndirectQuery
implements Select<T> {
+public abstract class FluentSelect<T> extends IndirectQuery implements Select<T>
{
 
     protected Class<?> entityType;
     protected String entityName;
@@ -106,385 +101,6 @@ public abstract class FluentSelect<T, S extends FluentSelect<T,
S>> extends Indi
         return replacement;
     }
 
-    /**
-     * Sets the type of the entity to fetch without changing the return type of
-     * the query.
-     *
-     * @return this object
-     */
-    public S entityType(Class<?> entityType) {
-        return resetEntity(entityType, null, null);
-    }
-
-    /**
-     * Sets the {@link ObjEntity} name to fetch without changing the return type
-     * of the query. This form is most often used for generic entities that
-     * don't map to a distinct class.
-     *
-     * @return this object
-     */
-    public S entityName(String entityName) {
-        return resetEntity(null, entityName, null);
-    }
-
-    /**
-     * Sets the {@link DbEntity} name to fetch without changing the return type
-     * of the query. This form is most often used for generic entities that
-     * don't map to a distinct class.
-     *
-     * @return this object
-     */
-    public S dbEntityName(String dbEntityName) {
-        return resetEntity(null, null, dbEntityName);
-    }
-
-    @SuppressWarnings("unchecked")
-    private S resetEntity(Class<?> entityType, String entityName, String dbEntityName)
{
-        this.entityType = entityType;
-        this.entityName = entityName;
-        this.dbEntityName = dbEntityName;
-        return (S)this;
-    }
-
-    /**
-     * Appends a qualifier expression of this query. An equivalent to
-     * {@link #and(Expression...)} that can be used a syntactic sugar.
-     *
-     * @return this object
-     */
-    public S where(Expression expression) {
-        return and(expression);
-    }
-
-    /**
-     * Appends a qualifier expression of this query, using provided expression
-     * String and an array of position parameters. This is an equivalent to
-     * calling "and".
-     *
-     * @return this object
-     */
-    public S where(String expressionString, Object... parameters) {
-        return and(ExpressionFactory.exp(expressionString, parameters));
-    }
-
-    /**
-     * AND's provided expressions to the existing WHERE clause expression.
-     *
-     * @return this object
-     */
-    @SuppressWarnings("unchecked")
-    public S and(Expression... expressions) {
-        if (expressions == null || expressions.length == 0) {
-            return (S)this;
-        }
-
-        return and(Arrays.asList(expressions));
-    }
-
-    /**
-     * AND's provided expressions to the existing WHERE clause expression.
-     *
-     * @return this object
-     */
-    @SuppressWarnings("unchecked")
-    public S and(Collection<Expression> expressions) {
-
-        if (expressions == null || expressions.isEmpty()) {
-            return (S)this;
-        }
-
-        Collection<Expression> all;
-
-        if (where != null) {
-            all = new ArrayList<>(expressions.size() + 1);
-            all.add(where);
-            all.addAll(expressions);
-        } else {
-            all = expressions;
-        }
-
-        where = ExpressionFactory.and(all);
-        return (S)this;
-    }
-
-    /**
-     * OR's provided expressions to the existing WHERE clause expression.
-     *
-     * @return this object
-     */
-    @SuppressWarnings("unchecked")
-    public S or(Expression... expressions) {
-        if (expressions == null || expressions.length == 0) {
-            return (S)this;
-        }
-
-        return or(Arrays.asList(expressions));
-    }
-
-    /**
-     * OR's provided expressions to the existing WHERE clause expression.
-     *
-     * @return this object
-     */
-    @SuppressWarnings("unchecked")
-    public S or(Collection<Expression> expressions) {
-        if (expressions == null || expressions.isEmpty()) {
-            return (S)this;
-        }
-
-        Collection<Expression> all;
-
-        if (where != null) {
-            all = new ArrayList<>(expressions.size() + 1);
-            all.add(where);
-            all.addAll(expressions);
-        } else {
-            all = expressions;
-        }
-
-        where = ExpressionFactory.or(all);
-        return (S)this;
-    }
-
-    /**
-     * Add an ascending ordering on the given property. If there is already an ordering
-     * on this query then add this ordering with a lower priority.
-     *
-     * @param property the property to sort on
-     * @return this object
-     */
-    public S orderBy(String property) {
-        return orderBy(new Ordering(property));
-    }
-
-    /**
-     * Add an ordering on the given property. If there is already an ordering
-     * on this query then add this ordering with a lower priority.
-     *
-     * @param property  the property to sort on
-     * @param sortOrder the direction of the ordering
-     * @return this object
-     */
-    public S orderBy(String property, SortOrder sortOrder) {
-        return orderBy(new Ordering(property, sortOrder));
-    }
-
-    /**
-     * Add one or more orderings to this query.
-     *
-     * @return this object
-     */
-    @SuppressWarnings("unchecked")
-    public S orderBy(Ordering... orderings) {
-
-        if (orderings == null) {
-            return (S)this;
-        }
-
-        if (this.orderings == null) {
-            this.orderings = new ArrayList<>(orderings.length);
-        }
-
-        Collections.addAll(this.orderings, orderings);
-
-        return (S)this;
-    }
-
-    /**
-     * Adds a list of orderings to this query.
-     *
-     * @return this object
-     */
-    @SuppressWarnings("unchecked")
-    public S orderBy(Collection<Ordering> orderings) {
-
-        if (orderings == null) {
-            return (S)this;
-        }
-
-        if (this.orderings == null) {
-            this.orderings = new ArrayList<>(orderings.size());
-        }
-
-        this.orderings.addAll(orderings);
-
-        return (S)this;
-    }
-
-    /**
-     * Merges prefetch into the query prefetch tree.
-     *
-     * @return this object
-     */
-    @SuppressWarnings("unchecked")
-    public S prefetch(PrefetchTreeNode prefetch) {
-
-        if (prefetch == null) {
-            return (S)this;
-        }
-
-        if (prefetches == null) {
-            prefetches = new PrefetchTreeNode();
-        }
-
-        prefetches.merge(prefetch);
-        return (S)this;
-    }
-
-    /**
-     * Merges a prefetch path with specified semantics into the query prefetch
-     * tree.
-     *
-     * @return this object
-     */
-    @SuppressWarnings("unchecked")
-    public S prefetch(String path, int semantics) {
-
-        if (path == null) {
-            return (S)this;
-        }
-
-        if (prefetches == null) {
-            prefetches = new PrefetchTreeNode();
-        }
-
-        prefetches.addPath(path).setSemantics(semantics);
-        return (S)this;
-    }
-
-    /**
-     * Resets query fetch limit - a parameter that defines max number of objects
-     * that should be ever be fetched from the database.
-     */
-    @SuppressWarnings("unchecked")
-    public S limit(int fetchLimit) {
-        if (this.limit != fetchLimit) {
-            this.limit = fetchLimit;
-            this.replacementQuery = null;
-        }
-
-        return (S)this;
-    }
-
-    /**
-     * Resets query fetch offset - a parameter that defines how many objects
-     * should be skipped when reading data from the database.
-     */
-    @SuppressWarnings("unchecked")
-    public S offset(int fetchOffset) {
-        if (this.offset != fetchOffset) {
-            this.offset = fetchOffset;
-            this.replacementQuery = null;
-        }
-
-        return (S)this;
-    }
-
-    /**
-     * Resets query page size. A non-negative page size enables query result
-     * pagination that saves memory and processing time for large lists if only
-     * parts of the result are ever going to be accessed.
-     */
-    @SuppressWarnings("unchecked")
-    public S pageSize(int pageSize) {
-        if (this.pageSize != pageSize) {
-            this.pageSize = pageSize;
-            this.replacementQuery = null;
-        }
-
-        return (S)this;
-    }
-
-    /**
-     * Sets fetch size of the PreparedStatement generated for this query. Only
-     * non-negative values would change the default size.
-     *
-     * @see Statement#setFetchSize(int)
-     */
-    @SuppressWarnings("unchecked")
-    public S statementFetchSize(int size) {
-        if (this.statementFetchSize != size) {
-            this.statementFetchSize = size;
-            this.replacementQuery = null;
-        }
-
-        return (S)this;
-    }
-
-    @SuppressWarnings("unchecked")
-    public S cacheStrategy(QueryCacheStrategy strategy) {
-        if (this.cacheStrategy != strategy) {
-            this.cacheStrategy = strategy;
-            this.replacementQuery = null;
-        }
-
-        if(this.cacheGroup != null) {
-            this.cacheGroup = null;
-            this.replacementQuery = null;
-        }
-
-        return (S)this;
-    }
-
-    public S cacheStrategy(QueryCacheStrategy strategy, String cacheGroup) {
-        return cacheStrategy(strategy).cacheGroup(cacheGroup);
-    }
-
-    @SuppressWarnings("unchecked")
-    public S cacheGroup(String cacheGroup) {
-        this.cacheGroup = cacheGroup;
-        this.replacementQuery = null;
-        return (S)this;
-    }
-
-    /**
-     * Instructs Cayenne to look for query results in the "local" cache when
-     * running the query. This is a short-hand notation for:
-     * <p>
-     * <pre>
-     * query.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE, cacheGroup);
-     * </pre>
-     */
-    public S localCache(String cacheGroup) {
-        return cacheStrategy(QueryCacheStrategy.LOCAL_CACHE, cacheGroup);
-    }
-
-    /**
-     * Instructs Cayenne to look for query results in the "local" cache when
-     * running the query. This is a short-hand notation for:
-     * <p>
-     * <pre>
-     * query.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
-     * </pre>
-     */
-    public S localCache() {
-        return cacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
-    }
-
-    /**
-     * Instructs Cayenne to look for query results in the "shared" cache when
-     * running the query. This is a short-hand notation for:
-     * <p>
-     * <pre>
-     * query.cacheStrategy(QueryCacheStrategy.SHARED_CACHE, cacheGroup);
-     * </pre>
-     */
-    public S sharedCache(String cacheGroup) {
-        return cacheStrategy(QueryCacheStrategy.SHARED_CACHE, cacheGroup);
-    }
-
-    /**
-     * Instructs Cayenne to look for query results in the "shared" cache when
-     * running the query. This is a short-hand notation for:
-     * <p>
-     * <pre>
-     * query.cacheStrategy(QueryCacheStrategy.SHARED_CACHE);
-     * </pre>
-     */
-    public S sharedCache() {
-        return cacheStrategy(QueryCacheStrategy.SHARED_CACHE);
-    }
-
     public String getCacheGroup() {
         return cacheGroup;
     }
@@ -547,11 +163,6 @@ public abstract class FluentSelect<T, S extends FluentSelect<T,
S>> extends Indi
     }
 
     @Override
-    public T selectFirst(ObjectContext context) {
-        return context.selectFirst(limit(1));
-    }
-
-    @Override
     public void iterate(ObjectContext context, ResultIteratorCallback<T> callback)
{
         context.iterate(this, callback);
     }

http://git-wip-us.apache.org/repos/asf/cayenne/blob/0e6f0df1/cayenne-server/src/main/java/org/apache/cayenne/query/ObjectSelect.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/query/ObjectSelect.java b/cayenne-server/src/main/java/org/apache/cayenne/query/ObjectSelect.java
index da03ccb..a37cf37 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/query/ObjectSelect.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/query/ObjectSelect.java
@@ -21,11 +21,17 @@ package org.apache.cayenne.query;
 import org.apache.cayenne.DataRow;
 import org.apache.cayenne.ObjectContext;
 import org.apache.cayenne.exp.Expression;
+import org.apache.cayenne.exp.ExpressionFactory;
 import org.apache.cayenne.exp.Property;
 import org.apache.cayenne.map.DbEntity;
 import org.apache.cayenne.map.EntityResolver;
 import org.apache.cayenne.map.ObjEntity;
 
+import java.sql.Statement;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
 import java.util.List;
 
 /**
@@ -43,7 +49,7 @@ import java.util.List;
  *
  * @since 4.0
  */
-public class ObjectSelect<T> extends FluentSelect<T, ObjectSelect<T>> {
+public class ObjectSelect<T> extends FluentSelect<T> {
 
     private static final long serialVersionUID = -156124021150949227L;
 
@@ -155,6 +161,371 @@ public class ObjectSelect<T> extends FluentSelect<T, ObjectSelect<T>>
{
     }
 
     /**
+     * Sets the type of the entity to fetch without changing the return type of
+     * the query.
+     *
+     * @return this object
+     */
+    public ObjectSelect<T> entityType(Class<?> entityType) {
+        return resetEntity(entityType, null, null);
+    }
+
+    /**
+     * Sets the {@link ObjEntity} name to fetch without changing the return type
+     * of the query. This form is most often used for generic entities that
+     * don't map to a distinct class.
+     *
+     * @return this object
+     */
+    public ObjectSelect<T> entityName(String entityName) {
+        return resetEntity(null, entityName, null);
+    }
+
+    /**
+     * Sets the {@link DbEntity} name to fetch without changing the return type
+     * of the query. This form is most often used for generic entities that
+     * don't map to a distinct class.
+     *
+     * @return this object
+     */
+    public ObjectSelect<T> dbEntityName(String dbEntityName) {
+        return resetEntity(null, null, dbEntityName);
+    }
+
+    private ObjectSelect<T> resetEntity(Class<?> entityType, String entityName,
String dbEntityName) {
+        this.entityType = entityType;
+        this.entityName = entityName;
+        this.dbEntityName = dbEntityName;
+        return this;
+    }
+
+    /**
+     * Appends a qualifier expression of this query. An equivalent to
+     * {@link #and(Expression...)} that can be used a syntactic sugar.
+     *
+     * @return this object
+     */
+    public ObjectSelect<T> where(Expression expression) {
+        return and(expression);
+    }
+
+    /**
+     * Appends a qualifier expression of this query, using provided expression
+     * String and an array of position parameters. This is an equivalent to
+     * calling "and".
+     *
+     * @return this object
+     */
+    public ObjectSelect<T> where(String expressionString, Object... parameters) {
+        return and(ExpressionFactory.exp(expressionString, parameters));
+    }
+
+    /**
+     * AND's provided expressions to the existing WHERE clause expression.
+     *
+     * @return this object
+     */
+    public ObjectSelect<T> and(Expression... expressions) {
+        if (expressions == null || expressions.length == 0) {
+            return this;
+        }
+
+        return and(Arrays.asList(expressions));
+    }
+
+    /**
+     * AND's provided expressions to the existing WHERE clause expression.
+     *
+     * @return this object
+     */
+    public ObjectSelect<T> and(Collection<Expression> expressions) {
+
+        if (expressions == null || expressions.isEmpty()) {
+            return this;
+        }
+
+        Collection<Expression> all;
+
+        if (where != null) {
+            all = new ArrayList<>(expressions.size() + 1);
+            all.add(where);
+            all.addAll(expressions);
+        } else {
+            all = expressions;
+        }
+
+        where = ExpressionFactory.and(all);
+        return this;
+    }
+
+    /**
+     * OR's provided expressions to the existing WHERE clause expression.
+     *
+     * @return this object
+     */
+    public ObjectSelect<T> or(Expression... expressions) {
+        if (expressions == null || expressions.length == 0) {
+            return this;
+        }
+
+        return or(Arrays.asList(expressions));
+    }
+
+    /**
+     * OR's provided expressions to the existing WHERE clause expression.
+     *
+     * @return this object
+     */
+    public ObjectSelect<T> or(Collection<Expression> expressions) {
+        if (expressions == null || expressions.isEmpty()) {
+            return this;
+        }
+
+        Collection<Expression> all;
+
+        if (where != null) {
+            all = new ArrayList<>(expressions.size() + 1);
+            all.add(where);
+            all.addAll(expressions);
+        } else {
+            all = expressions;
+        }
+
+        where = ExpressionFactory.or(all);
+        return this;
+    }
+
+    /**
+     * Add an ascending ordering on the given property. If there is already an ordering
+     * on this query then add this ordering with a lower priority.
+     *
+     * @param property the property to sort on
+     * @return this object
+     */
+    public ObjectSelect<T> orderBy(String property) {
+        return orderBy(new Ordering(property));
+    }
+
+    /**
+     * Add an ordering on the given property. If there is already an ordering
+     * on this query then add this ordering with a lower priority.
+     *
+     * @param property  the property to sort on
+     * @param sortOrder the direction of the ordering
+     * @return this object
+     */
+    public ObjectSelect<T> orderBy(String property, SortOrder sortOrder) {
+        return orderBy(new Ordering(property, sortOrder));
+    }
+
+    /**
+     * Add one or more orderings to this query.
+     *
+     * @return this object
+     */
+    public ObjectSelect<T> orderBy(Ordering... orderings) {
+
+        if (orderings == null) {
+            return this;
+        }
+
+        if (this.orderings == null) {
+            this.orderings = new ArrayList<>(orderings.length);
+        }
+
+        Collections.addAll(this.orderings, orderings);
+
+        return this;
+    }
+
+    /**
+     * Adds a list of orderings to this query.
+     *
+     * @return this object
+     */
+    public ObjectSelect<T> orderBy(Collection<Ordering> orderings) {
+
+        if (orderings == null) {
+            return this;
+        }
+
+        if (this.orderings == null) {
+            this.orderings = new ArrayList<>(orderings.size());
+        }
+
+        this.orderings.addAll(orderings);
+
+        return this;
+    }
+
+    /**
+     * Merges prefetch into the query prefetch tree.
+     *
+     * @return this object
+     */
+    public ObjectSelect<T> prefetch(PrefetchTreeNode prefetch) {
+
+        if (prefetch == null) {
+            return this;
+        }
+
+        if (prefetches == null) {
+            prefetches = new PrefetchTreeNode();
+        }
+
+        prefetches.merge(prefetch);
+        return this;
+    }
+
+    /**
+     * Merges a prefetch path with specified semantics into the query prefetch
+     * tree.
+     *
+     * @return this object
+     */
+    public ObjectSelect<T> prefetch(String path, int semantics) {
+
+        if (path == null) {
+            return this;
+        }
+
+        if (prefetches == null) {
+            prefetches = new PrefetchTreeNode();
+        }
+
+        prefetches.addPath(path).setSemantics(semantics);
+        return this;
+    }
+
+    /**
+     * Resets query fetch limit - a parameter that defines max number of objects
+     * that should be ever be fetched from the database.
+     */
+    @SuppressWarnings("unchecked")
+    public ObjectSelect<T> limit(int fetchLimit) {
+        if (this.limit != fetchLimit) {
+            this.limit = fetchLimit;
+            this.replacementQuery = null;
+        }
+
+        return this;
+    }
+
+    /**
+     * Resets query fetch offset - a parameter that defines how many objects
+     * should be skipped when reading data from the database.
+     */
+    public ObjectSelect<T> offset(int fetchOffset) {
+        if (this.offset != fetchOffset) {
+            this.offset = fetchOffset;
+            this.replacementQuery = null;
+        }
+
+        return this;
+    }
+
+    /**
+     * Resets query page size. A non-negative page size enables query result
+     * pagination that saves memory and processing time for large lists if only
+     * parts of the result are ever going to be accessed.
+     */
+    public ObjectSelect<T> pageSize(int pageSize) {
+        if (this.pageSize != pageSize) {
+            this.pageSize = pageSize;
+            this.replacementQuery = null;
+        }
+
+        return this;
+    }
+
+    /**
+     * Sets fetch size of the PreparedStatement generated for this query. Only
+     * non-negative values would change the default size.
+     *
+     * @see Statement#setFetchSize(int)
+     */
+    public ObjectSelect<T> statementFetchSize(int size) {
+        if (this.statementFetchSize != size) {
+            this.statementFetchSize = size;
+            this.replacementQuery = null;
+        }
+
+        return this;
+    }
+
+    public ObjectSelect<T> cacheStrategy(QueryCacheStrategy strategy) {
+        if (this.cacheStrategy != strategy) {
+            this.cacheStrategy = strategy;
+            this.replacementQuery = null;
+        }
+
+        if(this.cacheGroup != null) {
+            this.cacheGroup = null;
+            this.replacementQuery = null;
+        }
+
+        return this;
+    }
+
+    public ObjectSelect<T> cacheStrategy(QueryCacheStrategy strategy, String cacheGroup)
{
+        return cacheStrategy(strategy).cacheGroup(cacheGroup);
+    }
+
+    public ObjectSelect<T> cacheGroup(String cacheGroup) {
+        this.cacheGroup = cacheGroup;
+        this.replacementQuery = null;
+        return this;
+    }
+
+    /**
+     * Instructs Cayenne to look for query results in the "local" cache when
+     * running the query. This is a short-hand notation for:
+     * <p>
+     * <pre>
+     * query.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE, cacheGroup);
+     * </pre>
+     */
+    public ObjectSelect<T> localCache(String cacheGroup) {
+        return cacheStrategy(QueryCacheStrategy.LOCAL_CACHE, cacheGroup);
+    }
+
+    /**
+     * Instructs Cayenne to look for query results in the "local" cache when
+     * running the query. This is a short-hand notation for:
+     * <p>
+     * <pre>
+     * query.cacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+     * </pre>
+     */
+    public ObjectSelect<T> localCache() {
+        return cacheStrategy(QueryCacheStrategy.LOCAL_CACHE);
+    }
+
+    /**
+     * Instructs Cayenne to look for query results in the "shared" cache when
+     * running the query. This is a short-hand notation for:
+     * <p>
+     * <pre>
+     * query.cacheStrategy(QueryCacheStrategy.SHARED_CACHE, cacheGroup);
+     * </pre>
+     */
+    public ObjectSelect<T> sharedCache(String cacheGroup) {
+        return cacheStrategy(QueryCacheStrategy.SHARED_CACHE, cacheGroup);
+    }
+
+    /**
+     * Instructs Cayenne to look for query results in the "shared" cache when
+     * running the query. This is a short-hand notation for:
+     * <p>
+     * <pre>
+     * query.cacheStrategy(QueryCacheStrategy.SHARED_CACHE);
+     * </pre>
+     */
+    public ObjectSelect<T> sharedCache() {
+        return cacheStrategy(QueryCacheStrategy.SHARED_CACHE);
+    }
+
+    /**
      * Forces query to fetch DataRows. This automatically changes whatever
      * result type was set previously to "DataRow".
      *
@@ -275,6 +646,11 @@ public class ObjectSelect<T> extends FluentSelect<T, ObjectSelect<T>>
{
         return count().selectOne(context);
     }
 
+    @Override
+    public T selectFirst(ObjectContext context) {
+        return context.selectFirst(limit(1));
+    }
+
     public boolean isFetchingDataRows() {
         return fetchingDataRows;
     }


Mime
View raw message