package com.googlecode.objectify;
import java.util.List;
import java.util.Map;
import java.util.Set;
import com.google.appengine.api.datastore.Cursor;
import com.google.appengine.api.datastore.QueryResultIterable;
/**
* <p>This is similar to the datastore Query object, but better understands
* real class objects - it allows you to filter and sort by the key field
* normally.</p>
*
* <p>The methods of this class follow the GAE/Python Query class rather than
* the GAE/Java Query class because the Python version is much more convenient
* to use. The Java version seems to have been designed for machines, not
* humans. You will appreciate the improvement.</p>
*
* <p>Construct this class by calling {@code Objectify.query()}</p>
*
* <p>Note that this class is Iterable itself; you do not need to call the
* fetch() method, but it is available if you like it.</p>
*
* <p>To obtain a {@code Cursor} call {@code Query.iterator().getCursor()}.
* This cursor can be resumed with {@code Query.cursor()}.</p>
*
* @author Jeff Schnitzer <jeff@infohazard.org>
*/
public interface Query<T> extends QueryResultIterable<T>
{
/**
* <p>Create a filter based on the specified condition and value, using
* the same syntax as the GAE/Python query class. Examples:</p>
*
* <ul>
* <li>{@code filter("age >=", age)}</li>
* <li>{@code filter("age =", age)}</li>
* <li>{@code filter("age", age)} (if no operator, = is assumed)</li>
* <li>{@code filter("age !=", age)}</li>
* <li>{@code filter("age in", ageList)}</li>
* </ul>
*
* <p>You can filter on id properties <strong>if</strong> this query is
* restricted to a Class<T> and the entity has no @Parent. If you are
* having trouble working around this limitation, please consult the
* objectify-appengine google group.</p>
* <p>You can <strong>not</strong> filter on @Parent properties. Use
* the {@code ancestor()} method instead.</p>
*/
public Query<T> filter(String condition, Object value);
/**
* <p>Sorts based on a property. Examples:</p>
*
* <ul>
* <li>{@code sort("age")}</li>
* <li>{@code sort("-age")} (descending sort)</li>
* </ul>
*
* <p>You can sort on id properties <strong>if</strong> this query is
* restricted to a Class<T>. Note that this is only important for
* descending sorting; default iteration is key-ascending.</p>
* <p>You can <strong>not</strong> sort on @Parent properties.</p>
*/
public Query<T> order(String condition);
/**
* Restricts result set only to objects which have the given ancestor
* somewhere in the chain. Doesn't need to be the immediate parent.
*
* @param keyOrEntity can be a Key, a Key<T>, or an Objectify entity object.
*/
public Query<T> ancestor(Object keyOrEntity);
/**
* Limit the fetched result set to a certain number of values.
*
* @param value must be >= 0. A value of 0 indicates no limit.
*/
public Query<T> limit(int value);
/**
* Starts the query results at a particular zero-based offset.
*
* @param value must be >= 0
*/
public Query<T> offset(int value);
/**
* Starts query results at the specified Cursor. You can obtain a Cursor from
* a QueryResultIterator by calling the getCursor() method.
*/
public Query<T> cursor(Cursor value);
/**
* <p>Generates a string that consistently and uniquely specifies this query. There
* is no way to convert this string back into a query and there is no guarantee that
* the string will be consistent across versions of Objectify.</p>
*
* <p>In particular, this value is useful as a key for a simple memcache query cache.</p>
*/
public String toString();
/**
* Gets the first entity in the result set. Obeys the offset value.
*
* @return the only instance in the result, or null if the result set is empty.
*/
public T get();
/**
* Get the key of the first entity in the result set. Obeys the offset value.
*
* @return the key of the first instance in the result, or null if the result set is empty.
*/
public Key<T> getKey();
/**
* Implemented as "return this;". No point, really.
*/
@Deprecated
public QueryResultIterable<T> fetch();
/**
* Prepares an Iterable that will obtain the keys of the results. This is more efficient than
* fetching the actual results. Note that every time iterator() is called on the Iterable,
* a fresh query is executed; calling this method does not cause a datastore operation.
*/
public QueryResultIterable<Key<T>> fetchKeys();
/**
* Execute a keys-only query and then extract parent keys, returning them as a Set.
*
* @throws IllegalStateException if any member of the query result does not have a parent.
*/
public <V> Set<Key<V>> fetchParentKeys();
/**
* Gets the parent keys and then fetches the actual entities. This is the same
* as calling {@code ofy.get(query.fetchParentKeys())}.
*
* @throws IllegalStateException if any member of the query result does not have a parent.
*/
public <V> Map<Key<V>, V> fetchParents();
/**
* <p>Count the total number of values in the result, <strong>ignoring <em>limit</em> and <em>offset</em>.</p>
* <p>This is somewhat faster than fetching, but the time still grows with the number of results.</p>
*/
public int countAll();
/**
* <p>Execute the query and get the results as a List. The list will be equivalent to a simple ArrayList;
* you can iterate through it multiple times without incurring additional datastore cost.</p>
*
* <p>Note that you must be careful about limit()ing the size of the list returned; you can
* easily exceed the practical memory limits of Appengine by querying for a very large dataset.</p>
*/
public List<T> list();
/**
* <p>Execute a keys-only query and get the results as a List. This is more efficient than
* fetching the actual results.</p>
*
* <p>The size and scope considerations of list() apply; don't fetch more data than you
* can fit in a simple ArrayList.</p>
*/
public List<Key<T>> listKeys();
}