All Downloads are FREE. Search and download functionalities are using the official Maven repository.

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

The newest version!
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;
	}
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy