com.googlecode.objectify.impl.LoadEngine Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of objectify Show documentation
Show all versions of objectify Show documentation
The simplest convenient interface to the Google App Engine datastore
package com.googlecode.objectify.impl;
import com.google.appengine.api.datastore.AsyncDatastoreService;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.Transaction;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.Ref;
import com.googlecode.objectify.Result;
import com.googlecode.objectify.impl.ref.LiveRef;
import com.googlecode.objectify.impl.translate.LoadContext;
import com.googlecode.objectify.util.ResultCache;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.Future;
import java.util.logging.Level;
import java.util.logging.Logger;
/**
* Represents one "batch" of loading. Get a number of Result objects, then execute(). Some work is done
* right away, some work is done on the first get(). There might be multiple rounds of execution to process
* all the @Load groups, but that is invisible outside this class.
*
* @author Jeff Schnitzer
*/
public class LoadEngine
{
/** */
private static final Logger log = Logger.getLogger(LoadEngine.class.getName());
/** */
ObjectifyImpl ofy;
AsyncDatastoreService ads;
Session session;
LoadArrangement loadArrangement;
/** The current round, replaced whenever the round executes */
Round round;
/**
*/
public LoadEngine(ObjectifyImpl ofy, Session session, AsyncDatastoreService ads, LoadArrangement loadArrangement) {
this.ofy = ofy;
this.session = session;
this.ads = ads;
this.loadArrangement = loadArrangement;
this.round = new Round(this, 0);
if (log.isLoggable(Level.FINEST))
log.finest("Starting load engine with groups " + loadArrangement);
}
/**
* Gets the result, possibly from the session, putting it in the session if necessary.
* Also will recursively prepare the session with @Load parents as appropriate.
* @throws NullPointerException if key is null
*/
public Result load(Key key) {
if (key == null)
throw new NullPointerException("You tried to load a null key!");
Result result = round.get(key);
// If we are running a transaction, enlist the result so that it gets processed on commit even
// if the client never materializes the result.
if (ofy.getTransaction() != null)
ofy.getTransaction().enlist(result);
// Now check to see if we need to recurse and add our parent(s) to the round
if (key.getParent() != null) {
KeyMetadata meta = ofy.factory().keys().getMetadata(key);
// Is it really possible for this to be null?
if (meta != null) {
if (meta.shouldLoadParent(loadArrangement)) {
load(key.getParent());
}
}
}
return result;
}
/**
* Starts asychronous fetching of the batch.
*/
public void execute() {
if (round.needsExecution()) {
Round old = round;
round = old.next();
old.execute();
}
}
/**
* Create a Ref for the key, and maybe start a load operation depending on current load groups.
*
* @param rootEntity is the entity key which holds this property (possibly through some level of embedded objects)
*/
public Ref makeRef(Key rootEntity, LoadConditions loadConditions, Key key) {
Ref ref = new LiveRef<>(key, ofy);
if (shouldLoad(loadConditions)) {
load(key);
}
return ref;
}
/**
* @return true if the specified property should be loaded in this batch
*/
public boolean shouldLoad(LoadConditions loadConditions) {
return loadConditions.shouldLoad(loadArrangement);
}
/**
* Stuffs an Entity into a place where values in the round can be obtained instead of going to the datastore.
* Called by non-hybrid queries to add results and eliminate batch fetching.
*/
public void stuff(Entity ent) {
round.stuff(ent);
}
/**
* Asynchronously translate raw to processed; might produce successive load operations as refs are filled in
*/
public Result