package crmdna.common; import com.google.appengine.api.datastore.*; import com.google.appengine.api.datastore.Query.FilterOperator; import com.googlecode.objectify.Key; import java.util.ArrayList; import java.util.List; import static crmdna.common.AssertUtils.ensureNotNull; public class ProjectionQuery<T1, T2> { private Class<T1> type; private Class<T2> resultType; private Iterable<Key<T1>> keys; private String property; public static <T3, T4> ProjectionQuery<T3, T4> pq(Class<T3> type, Class<T4> resultType) { ProjectionQuery<T3, T4> projectionQuery = new ProjectionQuery<>(); projectionQuery.type = type; projectionQuery.resultType = resultType; return projectionQuery; } public ProjectionQuery<T1, T2> keys(Iterable<Key<T1>> keys) { this.keys = keys; return this; } public ProjectionQuery<T1, T2> property(String property) { this.property = property; return this; } @SuppressWarnings("unchecked") public List<T2> execute() { ensureNotNull(type, "kind cannot be null"); ensureNotNull(resultType, "result type cannot be null"); ensureNotNull(property, "result type cannot be null"); ensureNotNull(keys, "keys cannot be null"); List<com.google.appengine.api.datastore.Key> rawKeys = new ArrayList<>(); for (Key<?> key : keys) { rawKeys.add(key.getRaw()); } AsyncDatastoreService datastore = DatastoreServiceFactory .getAsyncDatastoreService(); com.google.appengine.api.datastore.Query.Filter filter = new com.google.appengine.api.datastore.Query.FilterPredicate( Entity.KEY_RESERVED_PROPERTY, FilterOperator.IN, rawKeys); com.google.appengine.api.datastore.Query q = new com.google.appengine.api.datastore.Query( type.getSimpleName()); q.setFilter(filter).addProjection( new PropertyProjection(property, resultType)); List<Entity> entities = datastore.prepare(q).asList( FetchOptions.Builder.withLimit(20000)); List<T2> list = new ArrayList<>(); for (Entity entity : entities) { list.add((T2) entity.getProperty(property)); } return list; } }