Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.googlecode.objectify.impl.AsyncObjectifyImpl Maven / Gradle / Ivy
Go to download
*** THIS VERSION UPLOADED FOR USE WITH CEDAR-COMMON, TO AVOID DEPENDENCIES ON GOOGLE CODE-BASED MAVEN REPOSITORIES. *** The simplest convenient interface to the Google App Engine datastore
package com.googlecode.objectify.impl;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Future;
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.AsyncObjectify;
import com.googlecode.objectify.Key;
import com.googlecode.objectify.NotFoundException;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.ObjectifyFactory;
import com.googlecode.objectify.Query;
import com.googlecode.objectify.Result;
import com.googlecode.objectify.util.SimpleFutureWrapper;
/**
* Implementation of the Objectify interface. Note we *always* use the AsyncDatastoreService
* methods that use transactions to avoid the confusion of implicit transactions.
*
* @author Jeff Schnitzer
*/
public class AsyncObjectifyImpl implements AsyncObjectify
{
/** The factory that produced us */
protected ObjectifyFactory factory;
/** The google object that does the actual heavy lifting */
protected AsyncDatastoreService ads;
/** The transaction to use. If null, do not use transactions. */
protected Transaction txn;
/** The synchronous version of this API; gets initialized by ObjectifyImpl's constructor */
protected Objectify sync;
/**
* Protected constructor creates a wrapper on the datastore with
* the specified txn.
*
* @param txn can be null to not use transactions.
*/
public AsyncObjectifyImpl(ObjectifyFactory fact, AsyncDatastoreService ds, Transaction txn)
{
this.factory = fact;
this.ads = ds;
this.txn = txn;
}
/* (non-Javadoc)
* @see com.google.code.objectify.Objectify#get(java.lang.Iterable)
*/
@Override
public Result, T>> get(Iterable> keys)
{
// First we need to turn the keys into raw keys
final List rawKeys = new ArrayList();
for (Key obKey: keys)
rawKeys.add(obKey.getRaw());
Future> futureEntities = this.ads.get(this.txn, rawKeys);
Future, T>> wrapped = new SimpleFutureWrapper, Map, T>>(futureEntities) {
@Override
protected Map, T> wrap(Map orig) throws Exception
{
Map, T> result = new LinkedHashMap, T>(orig.size() * 2);
// We preserve the order of the original keys
for (com.google.appengine.api.datastore.Key rawKey: rawKeys)
{
Entity entity = orig.get(rawKey);
if (entity != null)
{
EntityMetadata metadata = factory.getMetadata(rawKey);
result.put(new Key(rawKey), (T)metadata.toObject(entity, sync()));
}
}
return result;
}
};
return new ResultAdapter, T>>(wrapped);
}
/* (non-Javadoc)
* @see com.googlecode.objectify.AsyncObjectify#get(com.googlecode.objectify.Key[])
*/
@Override
public Result, T>> get(Key... keys)
{
return this.get(Arrays.asList(keys));
}
/* (non-Javadoc)
* @see com.googlecode.objectify.AsyncObjectify#get(com.googlecode.objectify.Key)
*/
@Override
public Result get(final Key key)
{
// The actual implementation is find().
Result found = this.find(key);
Future wrapped = new SimpleFutureWrapper(found.getFuture()) {
@Override
protected T wrap(T t) throws Exception
{
if (t != null)
return t;
else
throw new NotFoundException(key);
}
};
return new ResultAdapter(wrapped);
}
/* (non-Javadoc)
* @see com.googlecode.objectify.AsyncObjectify#get(java.lang.Class, long)
*/
@Override
public Result get(Class clazz, long id)
{
// The cast gets rid of "no unique maximal instance exists" compiler error
return (Result)this.get(new Key(clazz, id));
}
/* (non-Javadoc)
* @see com.googlecode.objectify.AsyncObjectify#get(java.lang.Class, java.lang.String)
*/
@Override
public Result get(Class clazz, String name)
{
// The cast gets rid of "no unique maximal instance exists" compiler error
return (Result)this.get(new Key(clazz, name));
}
/* (non-Javadoc)
* @see com.googlecode.objectify.AsyncObjectify#get(java.lang.Class, java.lang.Iterable)
*/
@Override
@SuppressWarnings("unchecked")
public Result> get(Class clazz, Iterable ids)
{
List> keys = new ArrayList>();
for (Object id: ids)
{
if (id instanceof Long)
keys.add(new Key(clazz, (Long)id));
else if (id instanceof String)
keys.add(new Key(clazz, (String)id));
else
throw new IllegalArgumentException("Only Long or String is allowed, not " + id.getClass().getName() + " (" + id + ")");
}
Result, T>> fetched = this.get(keys);
Future> wrapped = new SimpleFutureWrapper, T>, Map>(fetched.getFuture()) {
@Override
protected Map wrap(Map, T> base) throws Exception
{
Map result = new LinkedHashMap(base.size() * 2);
for (Map.Entry, T> entry: base.entrySet())
{
Object mapKey = entry.getKey().getName() != null ? entry.getKey().getName() : entry.getKey().getId();
result.put((S)mapKey, entry.getValue());
}
return result;
}
};
return new ResultAdapter>(wrapped);
}
/* (non-Javadoc)
* @see com.googlecode.objectify.AsyncObjectify#get(java.lang.Class, S[])
*/
@Override
public Result> get(Class clazz, S... idsOrNames)
{
return this.get(clazz, Arrays.asList(idsOrNames));
}
/* (non-Javadoc)
* @see com.googlecode.objectify.AsyncObjectify#find(com.google.appengine.api.datastore.Key)
*/
@Override
public Result find(final Key key)
{
Result, T>> multi = this.get(Collections.singleton(key));
Future wrapped = new SimpleFutureWrapper, T>, T>(multi.getFuture()) {
@Override
protected T wrap(Map, T> base) throws Exception
{
return base.get(key);
}
};
return new ResultAdapter(wrapped);
}
/* (non-Javadoc)
* @see com.googlecode.objectify.AsyncObjectify#find(java.lang.Class, long)
*/
@Override
public Result find(Class clazz, long id)
{
return this.find(new Key(clazz, id));
}
/* (non-Javadoc)
* @see com.googlecode.objectify.AsyncObjectify#find(java.lang.Class, java.lang.String)
*/
@Override
public Result find(Class clazz, String name)
{
return this.find(new Key(clazz, name));
}
/* (non-Javadoc)
* @see com.google.code.objectify.AsyncObjectify#put(java.lang.Object)
*/
@Override
public Result> put(final T obj)
{
// let's just translate this to a put(iterable) call
Result, T>> result = this.put(Collections.singleton(obj));
Future> future = new SimpleFutureWrapper, T>, Key>(result.getFuture()) {
@Override
protected Key wrap(Map, T> putted) throws Exception
{
return putted.keySet().iterator().next();
}
};
return new ResultAdapter>(future);
}
/* (non-Javadoc)
* @see com.google.code.objectify.AsyncObjectify#put(java.lang.Iterable)
*/
@Override
public Result, T>> put(final Iterable objs)
{
List entityList = new ArrayList();
for (T obj: objs)
{
EntityMetadata metadata = this.factory.getMetadataForEntity(obj);
entityList.add(metadata.toEntity(obj, this.sync()));
}
Future> raw = this.ads.put(this.txn, entityList);
Future, T>> wrapped = new SimpleFutureWrapper, Map, T>>(raw) {
@Override
protected Map, T> wrap(List rawKeys) throws Exception
{
Map, T> result = new LinkedHashMap, T>(rawKeys.size() * 2);
// Patch up any generated keys in the original objects while building new key list
Iterator keysIt = rawKeys.iterator();
for (T obj: objs)
{
com.google.appengine.api.datastore.Key k = keysIt.next();
EntityMetadata metadata = factory.getMetadataForEntity(obj);
metadata.setKey(obj, k);
result.put(new Key(k), obj);
}
return result;
}
};
return new ResultAdapter, T>>(wrapped);
}
/* (non-Javadoc)
* @see com.googlecode.objectify.AsyncObjectify#put(T[])
*/
@Override
public Result, T>> put(T... objs)
{
return this.put(Arrays.asList(objs));
}
/* (non-Javadoc)
* @see com.googlecode.objectify.Objectify#delete(java.lang.Object[])
*/
@Override
public Result delete(Object... keysOrEntities)
{
return this.delete(Arrays.asList(keysOrEntities));
}
/* (non-Javadoc)
* @see com.googlecode.objectify.Objectify#delete(java.lang.Class, long)
*/
@Override
public Result delete(Class clazz, long id)
{
return this.delete(new Key(clazz, id));
}
/* (non-Javadoc)
* @see com.googlecode.objectify.Objectify#delete(Class, String)
*/
@Override
public Result delete(Class clazz, String name)
{
return this.delete(new Key(clazz, name));
}
/* (non-Javadoc)
* @see com.google.code.objectify.Objectify#delete(java.lang.Iterable)
*/
@Override
public Result delete(Iterable keysOrEntities)
{
// We have to be careful here, objs could contain raw Keys or Keys or entity objects or both!
List keys = new ArrayList();
for (Object obj: keysOrEntities)
keys.add(this.factory.getRawKey(obj));
return new ResultAdapter(this.ads.delete(this.txn, keys));
}
/**
* Not currently part of the AsyncObjectify api, but the actual logic lives here.
*/
public Query query()
{
return new QueryImpl(this.factory, this.sync());
}
/**
* Not currently part of the AsyncObjectify api, but the actual logic lives here.
*/
public Query query(Class clazz)
{
return new QueryImpl(this.factory, this.sync(), clazz);
}
/**
* Not currently part of the AsyncObjectify api, but the actual logic lives here.
*/
public Transaction getTxn()
{
return this.txn;
}
/* (non-Javadoc)
* @see com.google.code.objectify.AsyncObjectify#getAsyncDatastore()
*/
@Override
public AsyncDatastoreService getAsyncDatastore()
{
return this.ads;
}
/**
* Not currently part of the AsyncObjectify api, but the actual logic lives here.
*/
public ObjectifyFactory getFactory()
{
return this.factory;
}
/* (non-Javadoc)
* @see com.googlecode.objectify.AsyncObjectify#sync()
*/
@Override
public Objectify sync()
{
return this.sync;
}
}