package com.googlecode.objectify.cmd;
import com.google.appengine.api.datastore.Entity;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.LoadResult;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.Ref;
import java.util.Map;
import java.util.Set;
/**
* <p>The top element in the command chain for retrieving entities from the datastore.</p>
*
* <p>At this point you can enable load groups with {@code group()}, start all-kinds
* queries by calling query-related methods (see SimpleQuery), load entities by key or ref,
* or narrow your interest to a specific kind by calling {@code type()}.</p>
*
* <p>All command objects are immutable.</p>
*
* @author Jeff Schnitzer <jeff@infohazard.org>
*/
public interface Loader extends SimpleQuery<Object>
{
/**
* <p>Enables one or more fetch groups. This will cause any entity fields (or Ref fields) which
* are annotated with @Load(XYZGroup.class) to be fetched along with your entities. The class
* definition can be any arbitrary class, but inheritance is respected - if you have a
* {@code class Foo extends Bar}, then {@code group(Foo.class)} will cause loading of all {@code @Load(Bar.class)}
* properties.</p>
*
* <p>Calling this method multiple times is the same as passing all the groups into one call.</p>
*
* <p><b>All command objects are immutable; this method returns a new object instead of modifying the
* current command object.</b></p>
*
* @param groups are one or more load groups to enable. They can be any arbitrary class.
* @return a continuation of the immutable command pattern, enabled for fetching this group.
*/
Loader group(Class<?>... groups);
/**
* <p>Restricts the find operation to entities of a particular type. The type may be the
* base of a polymorphic class hierarchy. This is optional.</p>
*
* <p><b>All command objects are immutable; this method returns a new object instead of modifying the
* current command object.</b></p>
*
* @param type is the type of entity (or entities) to retrieve, possibly a base class for a polymorphic hierarchy
* @return the next step in the immutable command chain, which allows you to start a query or define
* keys for a batch get.
*/
<E> LoadType<E> type(Class<E> type);
/**
* <p>Restricts the find operation to entities of a particular kind. This is similar to type()
* but lets you specify any arbitrary kind string. You'll typically only use this if you are
* also working with the low level api directly.</p>
*
* <p><b>All command objects are immutable; this method returns a new object instead of modifying the
* current command object.</b></p>
*
* @param kind is the kind of entity (or entities) to retrieve
* @return the next step in the immutable command chain, which allows you to start a query or define
* keys for a batch get.
*/
<E> LoadType<E> kind(String kind);
/**
* <p>Load a single entity ref. This starts an asynchronous fetch operation.</p>
*
* <p>Since fetching is asynchronous,
* <a href="http://code.google.com/appengine/articles/handling_datastore_errors.html">datastore exceptions</a>
* ({@code DatastoreTimeoutException}, {@code ConcurrentModificationException}, {@code DatastoreFailureException})
* can be thrown from {@code Result} operations.</p>
*
* @param ref holds the key to fetch and will receive the asynchronous result.
* @return a result which can materialize the entity.
*/
<E> LoadResult<E> ref(Ref<E> ref);
/**
* <p>Load multiple refs in a batch operation. This starts an asynchronous fetch.</p>
*
* <p>Since fetching is asynchronous,
* <a href="http://code.google.com/appengine/articles/handling_datastore_errors.html">datastore exceptions</a>
* ({@code DatastoreTimeoutException}, {@code ConcurrentModificationException}, {@code DatastoreFailureException})
* can be thrown from the map operations.</p>
*
* @param refs provide the keys to fetch and will receive the asynchronous result.
* @return as an alternative to accessing the Refs directly, a Map of the asynchronous result.
*/
<E> Map<Key<E>, E> refs(Iterable<Ref<E>> refs);
/**
* <p>A convenient substitute for refs(Iterable)</p>
*/
<E> Map<Key<E>, E> refs(Ref<? extends E>... refs);
/**
* <p>Load a single entity by key. This starts an asynchronous fetch.</p>
*
* <p>Since fetching is asynchronous,
* <a href="http://code.google.com/appengine/articles/handling_datastore_errors.html">datastore exceptions</a>
* ({@code DatastoreTimeoutException}, {@code ConcurrentModificationException}, {@code DatastoreFailureException})
* can be thrown from {@code Result} operations.</p>
*
* @param key defines the entity to fetch
* @return a result which can materialize the entity
*/
<E> LoadResult<E> key(Key<E> key);
/**
* <p>Load multiple entities by key from the datastore in a batch. This starts an asynchronous fetch.</p>
*
* <p>Since fetching is asynchronous,
* <a href="http://code.google.com/appengine/articles/handling_datastore_errors.html">datastore exceptions</a>
* ({@code DatastoreTimeoutException}, {@code ConcurrentModificationException}, {@code DatastoreFailureException})
* will be thrown when the Map is accessed.</p>
*
* @param keys are the keys to fetch
* @return a Map of the asynchronous result. The fetch will be completed when the Map is first accessed.
*/
<E> Map<Key<E>, E> keys(Iterable<Key<E>> keys);
/**
* <p>A convenient substitute for keys(Iterable)</p>
*/
<E> Map<Key<E>, E> keys(Key<? extends E>... keys);
/**
* <p>Load a single entity which has the same id/parent as the specified entity. This starts an asynchronous fetch.</p>
*
* <p>This is a shortcut for {@code key(Key.create(entity))}.</p>
*
* <p>Since fetching is asynchronous,
* <a href="http://code.google.com/appengine/articles/handling_datastore_errors.html">datastore exceptions</a>
* ({@code DatastoreTimeoutException}, {@code ConcurrentModificationException}, {@code DatastoreFailureException})
* may be thrown from {@code Result} operations.</p>
*
* @param entity defines the entity to fetch; it must be of a registered entity type and have valid id/parent fields.
* @return a result which can materialize the entity
*/
<E> LoadResult<E> entity(E entity);
/**
* <p>Load multiple entities from the datastore in a batch. This starts an asynchronous fetch.</p>
*
* <p>Since fetching is asynchronous,
* <a href="http://code.google.com/appengine/articles/handling_datastore_errors.html">datastore exceptions</a>
* ({@code DatastoreTimeoutException}, {@code ConcurrentModificationException}, {@code DatastoreFailureException})
* may be thrown when the Map is accessed.</p>
*
* @param entities must be a list of objects which belong to registered entity types, and must have id & parent fields
* properly set.
* @return a Map of the asynchronous result. The fetch will be completed when the Map is first accessed.
*/
<E> Map<Key<E>, E> entities(Iterable<E> entities);
/**
* <p>A convenient substitute for entities(Iterable)</p>
*/
<E> Map<Key<E>, E> entities(E... entities);
/**
* <p>Load a single entity given any of a variety of acceptable key-like structures. This starts an asynchronous fetch.</p>
*
* <p>The parameter can be any key-like structure, including:</p>
*
* <ul>
* <li>Standard Objectify Key<?> objects.</li>
* <li>Native datastore Key objects.</li>
* <li>Ref<?> objects.</li>
* <li>Registered entity instances which have id and parent fields populated.</li>
* </ul>
*
* <p>Since fetching is asynchronous,
* <a href="http://code.google.com/appengine/articles/handling_datastore_errors.html">datastore exceptions</a>
* ({@code DatastoreTimeoutException}, {@code ConcurrentModificationException}, {@code DatastoreFailureException})
* may be thrown from {@code Result} operations.</p>
*
* @param key defines the entity to fetch; can be anything that represents a key structure
* @return a Ref<?> which holds the asynchronous result
*/
<E> LoadResult<E> value(Object key);
/**
* <p>Fetch multiple entities from the datastore in a batch. This starts an asynchronous fetch.</p>
*
* <p>The parameters can be any mix of key-like structures, including:</p>
*
* <ul>
* <li>Standard Objectify Key<?> objects.</li>
* <li>Native datastore Key objects.</li>
* <li>Ref<?> objects.</li>
* <li>Registered entity instances which have id and parent fields populated.</li>
* </ul>
*
* <p>Since fetching is asynchronous,
* <a href="http://code.google.com/appengine/articles/handling_datastore_errors.html">datastore exceptions</a>
* ({@code DatastoreTimeoutException}, {@code ConcurrentModificationException}, {@code DatastoreFailureException})
* may be thrown when the Map is accessed.</p>
*
* @param keysOrEntities defines a possibly heterogeneous mixture of Key<?>, Ref<?>, native datastore Key, or registered
* entity instances with valid id/parent fields.
* @return a Map of the asynchronous result. The fetch will be completed when the Map is first accessed.
*/
<E> Map<Key<E>, E> values(Iterable<?> keysOrEntities);
/**
* <p>A convenient substitute for values(Iterable)</p>
*/
<E> Map<Key<E>, E> values(Object... keysOrEntities);
/**
* @return the parent Objectify instance
*/
Objectify getObjectify();
/**
* @return the currently enabled load groups in an unmodifiable list
*/
Set<Class<?>> getLoadGroups();
/**
* Convert a native datastore Entity into a typed POJO. This is like a load() operation except that you start with
* the native datastore type instead of fetching it from the datastore. However, note that because of @Load annotations,
* it is possible that datastore operations will be executed during the translation.
*
* @param entity is a native datastore entity which has an appropriate kind registered in the ObjectifyFactory.
* @return the POJO equivalent, just as if you had loaded the entity directly from Objectify.
*/
<T> T fromEntity(Entity entity);
/**
* Get the entity for a key immediately. You rarely, if ever, should want to use this; it exists to support
* Ref<?> behavior. Value will be loaded from the session if available, but will go to the datastore if necessary.
* It is synchronous.
*/
<E> E now(Key<E> key);
}