diff --git a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/EntityQuery.java b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/EntityQuery.java
new file mode 100644
index 000000000000..902168f20f48
--- /dev/null
+++ b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/EntityQuery.java
@@ -0,0 +1,67 @@
+/*
+ * Copyright 2015 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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
+ *
+ * http://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 com.google.gcloud.datastore;
+
+import com.google.api.services.datastore.DatastoreV1;
+
+/**
+ * An implementation of a Google Cloud Datastore entity query that can be constructed by providing
+ * all the specific query elements.
+ *
+ * @see Datastore
+ * queries
+ */
+public final class EntityQuery extends StructuredQuery {
+
+ private static final long serialVersionUID = 2990565454831019471L;
+
+ /**
+ * A {@code EntityQuery} builder for queries that return {@link Entity} results.
+ */
+ public static final class Builder extends StructuredQuery.BuilderImpl {
+
+ Builder(EntityQuery query) {
+ super(query);
+ }
+
+ Builder() {
+ super(ResultType.ENTITY);
+ }
+
+ @Override
+ Builder mergeFrom(DatastoreV1.Query queryPb) {
+ super.mergeFrom(queryPb);
+ clearProjection();
+ clearGroupBy();
+ return this;
+ }
+
+ @Override
+ public EntityQuery build() {
+ return new EntityQuery(this);
+ }
+ }
+
+ EntityQuery(Builder builder) {
+ super(builder);
+ }
+
+ @Override
+ public Builder toBuilder() {
+ return new Builder(this);
+ }
+}
diff --git a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/KeyQuery.java b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/KeyQuery.java
new file mode 100644
index 000000000000..7afa0f5099d6
--- /dev/null
+++ b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/KeyQuery.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright 2015 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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
+ *
+ * http://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 com.google.gcloud.datastore;
+
+import com.google.api.services.datastore.DatastoreV1;
+
+/**
+ * An implementation of a Google Cloud Datastore key-only query that can be constructed by providing
+ * all the specific query elements.
+ *
+ * @see Datastore
+ * queries
+ */
+public final class KeyQuery extends StructuredQuery {
+
+ private static final long serialVersionUID = -746768461459070045L;
+
+ /**
+ * A {@code KeyQuery} builder for queries that return {@link Key} results.
+ */
+ public static final class Builder extends StructuredQuery.BuilderImpl {
+
+ Builder(KeyQuery query) {
+ super(query);
+ }
+
+ Builder() {
+ super(ResultType.KEY);
+ projection(Projection.property(KEY_PROPERTY_NAME));
+ }
+
+ @Override
+ Builder mergeFrom(DatastoreV1.Query queryPb) {
+ super.mergeFrom(queryPb);
+ projection(Projection.property(KEY_PROPERTY_NAME));
+ clearGroupBy();
+ return this;
+ }
+
+ @Override
+ public KeyQuery build() {
+ return new KeyQuery(this);
+ }
+ }
+
+ KeyQuery(Builder builder) {
+ super(builder);
+ }
+
+ @Override
+ public Builder toBuilder() {
+ return new Builder(this);
+ }
+}
diff --git a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/ProjectionEntityQuery.java b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/ProjectionEntityQuery.java
new file mode 100644
index 000000000000..bad9fc5af2d0
--- /dev/null
+++ b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/ProjectionEntityQuery.java
@@ -0,0 +1,112 @@
+/*
+ * Copyright 2015 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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
+ *
+ * http://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 com.google.gcloud.datastore;
+
+/**
+ * An implementation of a Google Cloud Datastore projection entity query that can be constructed by
+ * providing all the specific query elements.
+ *
+ * @see Datastore
+ * queries
+ */
+public final class ProjectionEntityQuery extends StructuredQuery {
+
+ private static final long serialVersionUID = 5488451194542425391L;
+
+ /**
+ * A {@code ProjectionEntityQuery} builder for queries that return {@link ProjectionEntity}
+ * results.
+ */
+ public static final class Builder extends StructuredQuery.BuilderImpl {
+
+ Builder(ProjectionEntityQuery query) {
+ super(query);
+ }
+
+ Builder() {
+ super(ResultType.PROJECTION_ENTITY);
+ }
+
+ /**
+ * Clears the projection clause.
+ */
+ @Override
+ public Builder clearProjection() {
+ super.clearProjection();
+ return this;
+ }
+
+ /**
+ * Sets the query's projection clause (clearing any previously specified Projection settings).
+ */
+ @Override
+ public Builder projection(Projection projection, Projection... others) {
+ super.projection(projection, others);
+ return this;
+ }
+
+ /**
+ * Adds one or more projections to the existing projection clause.
+ */
+ @Override
+ public Builder addProjection(Projection projection, Projection... others) {
+ super.addProjection(projection, others);
+ return this;
+ }
+
+ /**
+ * Clears the group by clause.
+ */
+ @Override
+ public Builder clearGroupBy() {
+ super.clearGroupBy();
+ return this;
+ }
+
+ /**
+ * Sets the query's group by clause (clearing any previously specified GroupBy settings).
+ */
+ @Override
+ public Builder groupBy(String property, String... others) {
+ super.groupBy(property, others);
+ return this;
+ }
+
+ /**
+ * Adds one or more properties to the existing group by clause.
+ */
+ @Override
+ public Builder addGroupBy(String property, String... others) {
+ super.addGroupBy(property, others);
+ return this;
+ }
+
+ @Override
+ public ProjectionEntityQuery build() {
+ return new ProjectionEntityQuery(this);
+ }
+ }
+
+ ProjectionEntityQuery(Builder builder) {
+ super(builder);
+ }
+
+ @Override
+ public Builder toBuilder() {
+ return new Builder(this);
+ }
+}
diff --git a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/Query.java b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/Query.java
index 0dbd1633928e..50591a87a6a4 100644
--- a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/Query.java
+++ b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/Query.java
@@ -22,9 +22,6 @@
import com.google.common.base.MoreObjects;
import com.google.common.base.MoreObjects.ToStringHelper;
import com.google.common.collect.Maps;
-import com.google.gcloud.datastore.StructuredQuery.EntityQueryBuilder;
-import com.google.gcloud.datastore.StructuredQuery.KeyQueryBuilder;
-import com.google.gcloud.datastore.StructuredQuery.ProjectionEntityQueryBuilder;
import com.google.protobuf.GeneratedMessage;
import com.google.protobuf.InvalidProtocolBufferException;
@@ -217,21 +214,21 @@ public static GqlQuery.Builder gqlQueryBuilder(ResultType resultType,
/**
* Returns a new {@link StructuredQuery} builder for full (complete entities) queries.
*/
- public static EntityQueryBuilder entityQueryBuilder() {
- return new EntityQueryBuilder();
+ public static EntityQuery.Builder entityQueryBuilder() {
+ return new EntityQuery.Builder();
}
/**
* Returns a new {@link StructuredQuery} builder for key only queries.
*/
- public static KeyQueryBuilder keyQueryBuilder() {
- return new KeyQueryBuilder();
+ public static KeyQuery.Builder keyQueryBuilder() {
+ return new KeyQuery.Builder();
}
/**
* Returns a new {@link StructuredQuery} builder for projection queries.
*/
- public static ProjectionEntityQueryBuilder projectionEntityQueryBuilder() {
- return new ProjectionEntityQueryBuilder();
+ public static ProjectionEntityQuery.Builder projectionEntityQueryBuilder() {
+ return new ProjectionEntityQuery.Builder();
}
}
diff --git a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/StructuredQuery.java b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/StructuredQuery.java
index b8d9dfe87902..15cca241e250 100644
--- a/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/StructuredQuery.java
+++ b/gcloud-java-datastore/src/main/java/com/google/gcloud/datastore/StructuredQuery.java
@@ -81,10 +81,10 @@
* @see Datastore
* queries
*/
-public class StructuredQuery extends Query {
+public abstract class StructuredQuery extends Query {
private static final long serialVersionUID = 546838955624019594L;
- private static final String KEY_PROPERTY_NAME = "__key__";
+ static final String KEY_PROPERTY_NAME = "__key__";
private final transient String kind;
private final ImmutableList projection;
@@ -609,13 +609,48 @@ public static Projection first(String property) {
}
}
+ /**
+ * Interface for StructuredQuery builders.
+ *
+ * @param the type of result the query returns.
+ */
+ public interface Builder {
+ Builder namespace(String namespace);
+
+ Builder kind(String kind);
+
+ Builder startCursor(Cursor startCursor);
+
+ Builder endCursor(Cursor endCursor);
+
+ Builder offset(int offset);
+
+ Builder limit(Integer limit);
+
+ Builder filter(Filter filter);
+
+ Builder clearOrderBy();
+
+ /**
+ * Sets the query's order by clause (clearing any previously specified OrderBy settings).
+ */
+ Builder orderBy(OrderBy orderBy, OrderBy... others);
+
+ /**
+ * Adds settings to the existing order by clause.
+ */
+ Builder addOrderBy(OrderBy orderBy, OrderBy... others);
+
+ StructuredQuery build();
+ }
+
/**
* Base class for StructuredQuery builders.
*
* @param the type of result the query returns.
* @param the query builder.
*/
- protected static class BaseBuilder> {
+ abstract static class BuilderImpl> implements Builder {
private final ResultType resultType;
private String namespace;
@@ -629,12 +664,12 @@ protected static class BaseBuilder> {
private int offset;
private Integer limit;
- BaseBuilder(ResultType resultType) {
+ BuilderImpl(ResultType resultType) {
this.resultType = resultType;
}
- BaseBuilder(StructuredQuery query) {
- resultType = query.type();
+ BuilderImpl(StructuredQuery query) {
+ this(query.type());
namespace = query.namespace();
kind = query.kind;
projection.addAll(query.projection);
@@ -652,60 +687,64 @@ B self() {
return (B) this;
}
+ @Override
public B namespace(String namespace) {
this.namespace = namespace;
return self();
}
+ @Override
public B kind(String kind) {
this.kind = kind;
return self();
}
+ @Override
public B startCursor(Cursor startCursor) {
this.startCursor = startCursor;
return self();
}
+ @Override
public B endCursor(Cursor endCursor) {
this.endCursor = endCursor;
return self();
}
+ @Override
public B offset(int offset) {
Preconditions.checkArgument(offset >= 0, "offset must not be negative");
this.offset = offset;
return self();
}
+ @Override
public B limit(Integer limit) {
Preconditions.checkArgument(limit == null || limit > 0, "limit must be positive");
this.limit = limit;
return self();
}
+ @Override
public B filter(Filter filter) {
this.filter = filter;
return self();
}
+ @Override
public B clearOrderBy() {
orderBy.clear();
return self();
}
- /**
- * Sets the query's order by clause (clearing any previously specified OrderBy settings).
- */
+ @Override
public B orderBy(OrderBy orderBy, OrderBy... others) {
clearOrderBy();
addOrderBy(orderBy, others);
return self();
}
- /**
- * Adds settings to the existing order by clause.
- */
+ @Override
public B addOrderBy(OrderBy orderBy, OrderBy... others) {
this.orderBy.add(orderBy);
Collections.addAll(this.orderBy, others);
@@ -776,121 +815,9 @@ B mergeFrom(DatastoreV1.Query queryPb) {
}
return self();
}
-
- public StructuredQuery build() {
- return new StructuredQuery<>(this);
- }
- }
-
- public static final class Builder extends BaseBuilder> {
-
- Builder(ResultType resultType) {
- super(resultType);
- }
-
- Builder(StructuredQuery query) {
- super(query);
- }
- }
-
- /**
- * A StructuredQuery builder for queries that return Entity results.
- */
- public static final class EntityQueryBuilder extends BaseBuilder {
-
- EntityQueryBuilder() {
- super(ResultType.ENTITY);
- }
-
- @Override
- public StructuredQuery build() {
- return new StructuredQuery<>(this);
- }
- }
-
- /**
- * A StructuredQuery builder for queries that return Key results.
- */
- public static final class KeyQueryBuilder extends BaseBuilder {
-
- KeyQueryBuilder() {
- super(ResultType.KEY);
- projection(Projection.property(KEY_PROPERTY_NAME));
- }
-
- @Override
- KeyQueryBuilder mergeFrom(DatastoreV1.Query queryPb) {
- super.mergeFrom(queryPb);
- projection(Projection.property(KEY_PROPERTY_NAME));
- clearGroupBy();
- return this;
- }
-
- @Override
- public StructuredQuery build() {
- return new StructuredQuery<>(this);
- }
- }
-
- /**
- * A StructuredQuery builder for projection queries.
- */
- public static final class ProjectionEntityQueryBuilder
- extends BaseBuilder {
-
- ProjectionEntityQueryBuilder() {
- super(ResultType.PROJECTION_ENTITY);
- }
-
- @Override
- public StructuredQuery build() {
- return new StructuredQuery<>(this);
- }
-
- @Override
- public ProjectionEntityQueryBuilder clearProjection() {
- return super.clearProjection();
- }
-
- /**
- * Sets the query's projection clause (clearing any previously specified Projection settings).
- */
- @Override
- public ProjectionEntityQueryBuilder projection(Projection projection, Projection... others) {
- return super.projection(projection, others);
- }
-
- /**
- * Adds one or more projections to the existing projection clause.
- */
- @Override
- public ProjectionEntityQueryBuilder addProjection(Projection projection, Projection... others) {
- return super.addProjection(projection, others);
- }
-
- @Override
- public ProjectionEntityQueryBuilder clearGroupBy() {
- return super.clearGroupBy();
- }
-
- /**
- * Sets the query's group by clause (clearing any previously specified GroupBy settings).
- */
- @Override
- public ProjectionEntityQueryBuilder groupBy(String property, String... others) {
- return super.groupBy(property, others);
- }
-
- /**
- * Adds one or more properties to the existing group by clause.
- */
- @Override
- public ProjectionEntityQueryBuilder addGroupBy(String property, String... others) {
- return super.addGroupBy(property, others);
- }
}
- StructuredQuery(BaseBuilder builder) {
+ StructuredQuery(BuilderImpl builder) {
super(builder.resultType, builder.namespace);
kind = builder.kind;
projection = ImmutableList.copyOf(builder.projection);
@@ -971,9 +898,7 @@ public Integer limit() {
return limit;
}
- public Builder toBuilder() {
- return new Builder<>(this);
- }
+ public abstract Builder toBuilder();
@Override
void populatePb(DatastoreV1.RunQueryRequest.Builder requestPb) {
@@ -982,8 +907,7 @@ void populatePb(DatastoreV1.RunQueryRequest.Builder requestPb) {
@Override
StructuredQuery nextQuery(DatastoreV1.QueryResultBatch responsePb) {
- Builder builder = new Builder<>(type());
- builder.mergeFrom(toPb());
+ Builder builder = toBuilder();
builder.startCursor(new Cursor(responsePb.getEndCursor()));
if (offset > 0 && responsePb.getSkippedResults() < offset) {
builder.offset(offset - responsePb.getSkippedResults());
@@ -1035,15 +959,15 @@ Object fromPb(ResultType resultType, String namespace, byte[] bytesPb)
return fromPb(resultType, namespace, DatastoreV1.Query.parseFrom(bytesPb));
}
- private static StructuredQuery> fromPb(ResultType> resultType, String namespace,
+ static StructuredQuery> fromPb(ResultType> resultType, String namespace,
DatastoreV1.Query queryPb) {
- BaseBuilder, ?> builder;
+ BuilderImpl, ?> builder;
if (resultType.equals(ResultType.ENTITY)) {
- builder = new EntityQueryBuilder();
+ builder = new EntityQuery.Builder();
} else if (resultType.equals(ResultType.KEY)) {
- builder = new KeyQueryBuilder();
+ builder = new KeyQuery.Builder();
} else {
- builder = new ProjectionEntityQueryBuilder();
+ builder = new ProjectionEntityQuery.Builder();
}
return builder.namespace(namespace).mergeFrom(queryPb).build();
}
diff --git a/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/StructuredQueryTest.java b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/StructuredQueryTest.java
new file mode 100644
index 000000000000..b0d188cae16e
--- /dev/null
+++ b/gcloud-java-datastore/src/test/java/com/google/gcloud/datastore/StructuredQueryTest.java
@@ -0,0 +1,171 @@
+/*
+ * Copyright 2015 Google Inc. All Rights Reserved.
+ *
+ * Licensed 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
+ *
+ * http://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 com.google.gcloud.datastore;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import com.google.common.collect.ImmutableList;
+import com.google.gcloud.datastore.Query.ResultType;
+import com.google.gcloud.datastore.StructuredQuery.CompositeFilter;
+import com.google.gcloud.datastore.StructuredQuery.Filter;
+import com.google.gcloud.datastore.StructuredQuery.OrderBy;
+import com.google.gcloud.datastore.StructuredQuery.Projection;
+import com.google.gcloud.datastore.StructuredQuery.PropertyFilter;
+
+import org.junit.Test;
+
+import java.util.List;
+
+public class StructuredQueryTest {
+
+ private static final String NAMESPACE = "ns";
+ private static final String KIND = "k";
+ private static final Cursor START_CURSOR = Cursor.copyFrom(new byte[] {1, 2});
+ private static final Cursor END_CURSOR = Cursor.copyFrom(new byte[] {10});
+ private static final int OFFSET = 42;
+ private static final Integer LIMIT = 43;
+ private static final Filter FILTER = CompositeFilter.and(PropertyFilter.gt("p1", 10), PropertyFilter.eq("a", "v"));
+ private static final OrderBy ORDER_BY_1 = OrderBy.asc("p2");
+ private static final OrderBy ORDER_BY_2 = OrderBy.desc("p3");
+ private static final List ORDER_BY = ImmutableList.of(ORDER_BY_1, ORDER_BY_2);
+ private static final Projection PROJECTION1 = Projection.property("p4");
+ private static final Projection PROJECTION2 = Projection.property("p5");
+ private static final List PROJECTION = ImmutableList.of(PROJECTION1, PROJECTION2);
+ private static final String GROUP_BY1 = "p6";
+ private static final String GROUP_BY2 = "p7";
+ private static final List GROUP_BY = ImmutableList.of(GROUP_BY1, GROUP_BY2);
+ private static final EntityQuery ENTITY_QUERY = Query.entityQueryBuilder()
+ .namespace(NAMESPACE)
+ .kind(KIND)
+ .startCursor(START_CURSOR)
+ .endCursor(END_CURSOR)
+ .offset(OFFSET)
+ .limit(LIMIT)
+ .filter(FILTER)
+ .orderBy(ORDER_BY_1, ORDER_BY_2)
+ .build();
+ private static final KeyQuery KEY_QUERY = Query.keyQueryBuilder()
+ .namespace(NAMESPACE)
+ .kind(KIND)
+ .startCursor(START_CURSOR)
+ .endCursor(END_CURSOR)
+ .offset(OFFSET)
+ .limit(LIMIT)
+ .filter(FILTER)
+ .orderBy(ORDER_BY_1, ORDER_BY_2)
+ .build();
+ private static final ProjectionEntityQuery PROJECTION_QUERY =
+ Query.projectionEntityQueryBuilder()
+ .namespace(NAMESPACE)
+ .kind(KIND)
+ .startCursor(START_CURSOR)
+ .endCursor(END_CURSOR)
+ .offset(OFFSET)
+ .limit(LIMIT)
+ .filter(FILTER)
+ .orderBy(ORDER_BY_1, ORDER_BY_2)
+ .projection(PROJECTION1, PROJECTION2)
+ .groupBy(GROUP_BY1, GROUP_BY2)
+ .build();
+
+ @Test
+ public void testEntityQueryBuilder() {
+ compareBaseBuilderFields(ENTITY_QUERY);
+ assertTrue(ENTITY_QUERY.projection().isEmpty());
+ assertTrue(ENTITY_QUERY.groupBy().isEmpty());
+ }
+
+ @Test
+ public void testKeyQueryBuilder() {
+ compareBaseBuilderFields(KEY_QUERY);
+ assertEquals(
+ ImmutableList.of(Projection.property(StructuredQuery.KEY_PROPERTY_NAME)),
+ KEY_QUERY.projection());
+ assertTrue(KEY_QUERY.groupBy().isEmpty());
+ }
+
+ @Test
+ public void testProjectionEntityQueryBuilder() {
+ compareBaseBuilderFields(PROJECTION_QUERY);
+ assertEquals(PROJECTION, PROJECTION_QUERY.projection());
+ assertEquals(GROUP_BY, PROJECTION_QUERY.groupBy());
+ }
+
+ private void compareBaseBuilderFields(StructuredQuery> query) {
+ assertEquals(NAMESPACE, query.namespace());
+ assertEquals(KIND, query.kind());
+ assertEquals(START_CURSOR, query.startCursor());
+ assertEquals(END_CURSOR, query.endCursor());
+ assertEquals(OFFSET, query.offset());
+ assertEquals(LIMIT, query.limit());
+ assertEquals(FILTER, query.filter());
+ assertEquals(ORDER_BY, query.orderBy());
+ }
+
+ @Test
+ public void mergeFrom() {
+ compareMergedQuery(
+ ENTITY_QUERY, new EntityQuery.Builder().mergeFrom(ENTITY_QUERY.toPb()).build());
+ compareMergedQuery(KEY_QUERY, new KeyQuery.Builder().mergeFrom(KEY_QUERY.toPb()).build());
+ compareMergedQuery(
+ PROJECTION_QUERY,
+ new ProjectionEntityQuery.Builder().mergeFrom(PROJECTION_QUERY.toPb()).build());
+ }
+
+ private void compareMergedQuery(StructuredQuery> expected, StructuredQuery> actual) {
+ assertEquals(expected.kind(), actual.kind());
+ assertEquals(expected.startCursor(), actual.startCursor());
+ assertEquals(expected.endCursor(), actual.endCursor());
+ assertEquals(expected.offset(), actual.offset());
+ assertEquals(expected.limit(), actual.limit());
+ assertEquals(expected.filter(), actual.filter());
+ assertEquals(expected.orderBy(), actual.orderBy());
+ assertEquals(expected.projection(), actual.projection());
+ assertEquals(expected.groupBy(), actual.groupBy());
+ }
+
+ @Test
+ public void testToAndFromPb() {
+ assertEquals(
+ ENTITY_QUERY,
+ StructuredQuery.fromPb(ResultType.ENTITY, ENTITY_QUERY.namespace(), ENTITY_QUERY.toPb()));
+ assertEquals(
+ KEY_QUERY, StructuredQuery.fromPb(ResultType.KEY, KEY_QUERY.namespace(), KEY_QUERY.toPb()));
+ assertEquals(
+ PROJECTION_QUERY,
+ StructuredQuery.fromPb(
+ ResultType.PROJECTION_ENTITY, PROJECTION_QUERY.namespace(), PROJECTION_QUERY.toPb()));
+ }
+
+ @Test
+ public void testToBuilder() {
+ List> queries =
+ ImmutableList.>of(ENTITY_QUERY, KEY_QUERY, PROJECTION_QUERY);
+ for (StructuredQuery> query : queries) {
+ assertEquals(query, query.toBuilder().build());
+ }
+ }
+
+ @Test
+ public void testKeyOnly() {
+ assertTrue(KEY_QUERY.keyOnly());
+ assertFalse(ENTITY_QUERY.keyOnly());
+ assertFalse(PROJECTION_QUERY.keyOnly());
+ }
+}