Created
July 24, 2011 08:45
-
-
Save kdmukai/1102416 to your computer and use it in GitHub Desktop.
Final versions of ObjectifyGenericDAO with interfaces
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.essaytagger.server.impl; | |
import com.essaytagger.model.Comment; | |
import com.essaytagger.model.Essay; | |
import com.essaytagger.server.IEssayManagerExtensions; | |
import com.google.appengine.api.datastore.EntityNotFoundException; | |
import com.googlecode.objectify.Key; | |
/** | |
* Implementation class for any Essay-specific methods that aren't already handled by ObjectifyGenericDAO<T>. | |
*/ | |
public class EssayManagerExtensionsImpl extends ObjectifyGenericDAO<Essay> implements IEssayManagerExtensions { | |
public EssayManagerExtensionsImpl() { | |
// Generic type needs to be explicitly passed to the ObjectifyGenericDAO<T> constructor | |
super(Essay.class); | |
} | |
/************************************************************** | |
* Overrides of the GenericDAO implementations | |
*************************************************************/ | |
@Override | |
public void delete(Essay entity) { | |
// First do something special and specific for Essay entities | |
// ... | |
// Now we can delete the entity from the datastore | |
super.delete(entity); | |
} | |
// Also have to override this version to control all delete() behavior | |
@Override | |
public void deleteKey(Key<Essay> entityKey) { | |
try { | |
Essay essay = this.get(entityKey); | |
delete(essay); | |
} catch (EntityNotFoundException e) { | |
// TODO Auto-generated catch block | |
e.printStackTrace(); | |
} | |
} | |
/************************************************************************************************* | |
* Implementation of new methods from the Extension interface | |
************************************************************************************************/ | |
public void addCommentToEssay(Essay essay, Comment comment) { | |
// Implement the business logic specific to this unique method | |
// ... | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.essaytagger.server; | |
import com.essaytagger.model.BasicUser; | |
import com.essaytagger.model.Essay; | |
import com.essaytagger.server.impl.EssayManagerExtensionsImpl; | |
import com.essaytagger.server.impl.ObjectifyGenericDAO; | |
import com.googlecode.objectify.ObjectifyService; | |
public class EssayTaggerManagerFactory { | |
// Declare entity-specific versions of each Generic interface | |
public interface IBasicUserManager extends IGenericDAO<BasicUser> {} | |
public interface IEssayManager extends IEssayManagerExtensions {} | |
// The use those interfaces as we declare entity-specific DAOs | |
private static class BasicUserManager extends ObjectifyGenericDAO<BasicUser> implements IBasicUserManager {} | |
private static class EssayManager extends EssayManagerExtensionsImpl implements IEssayManager {} | |
static { | |
ObjectifyService.register(BasicUser.class); | |
ObjectifyService.register(Essay.class); | |
} | |
// Static-only usage pattern | |
protected EssayTaggerManagerFactory() {} | |
public static IEssayManager getEssayManager() { | |
return new EssayManager(); | |
} | |
public static IBasicUserManager getBasicUserManager() { | |
return new BasicUserManager(); | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.essaytagger.server; | |
import com.essaytagger.model.Comment; | |
import com.essaytagger.model.Essay; | |
/** | |
* Declare additional Essay-specific methods that aren't covered in the IGenericDAO<T> interface. | |
*/ | |
public interface IEssayManagerExtensions extends IGenericDAO<Essay> { | |
public void addCommentToEssay(Essay essay, Comment comment); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.essaytagger.server; | |
import java.util.List; | |
import java.util.Map; | |
import com.google.appengine.api.datastore.EntityNotFoundException; | |
import com.googlecode.objectify.Key; | |
public interface IGenericDAO<T> { | |
public Key<T> put(T entity); | |
public Map<Key<T>, T> putAll(Iterable<T> entities); | |
public void delete(T entity); | |
public void deleteKey(Key<T> entityKey); | |
public void deleteAll(Iterable<T> entities); | |
public void deleteKeys(Iterable<Key<T>> keys); | |
public T get(Long id) throws EntityNotFoundException; | |
public T get(Key<T> key) throws EntityNotFoundException; | |
/* | |
* Convenience method to generate a typed Key<T> for a given id | |
*/ | |
public Key<T> getKey(Long id); | |
/* | |
* Get ALL entities of type <T> in the datastore. Potentially very inefficient!! | |
* Make sure you have a good reason to use this!! | |
*/ | |
public List<T> listAll(); | |
/** | |
* Convenience method to get all objects matching a single property | |
* | |
* @param propName | |
* @param propValue | |
* @return T matching Object | |
*/ | |
public T getByProperty(String propName, Object propValue); | |
public List<T> listByProperty(String propName, Object propValue); | |
public List<Key<T>> listKeysByProperty(String propName, Object propValue); | |
public T getByExample(T exampleObj); | |
public List<T> listByExample(T exampleObj); | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.essaytagger.server.impl; | |
import java.lang.reflect.Field; | |
import java.lang.reflect.Modifier; | |
import java.lang.reflect.ParameterizedType; | |
import java.util.ArrayList; | |
import java.util.Collection; | |
import java.util.Iterator; | |
import java.util.List; | |
import java.util.Map; | |
import javax.persistence.Embedded; | |
import javax.persistence.Transient; | |
import com.essaytagger.server.IGenericDAO; | |
import com.google.appengine.api.datastore.EntityNotFoundException; | |
import com.googlecode.objectify.Key; | |
import com.googlecode.objectify.Query; | |
import com.googlecode.objectify.util.DAOBase; | |
public abstract class ObjectifyGenericDAO<T> extends DAOBase implements IGenericDAO<T> { | |
static final int BAD_MODIFIERS = Modifier.FINAL | Modifier.STATIC | Modifier.TRANSIENT; | |
protected Class<T> clazz; | |
@SuppressWarnings("unchecked") | |
public ObjectifyGenericDAO() { | |
clazz = ((Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0]); | |
} | |
/** | |
* We've got to get the associated domain class somehow | |
* | |
* @param clazz | |
*/ | |
protected ObjectifyGenericDAO(Class<T> clazz) | |
{ | |
this.clazz = clazz; | |
} | |
public Key<T> put(T entity) | |
{ | |
return ofy().put(entity); | |
} | |
public Map<Key<T>, T> putAll(Iterable<T> entities) | |
{ | |
return ofy().put(entities); | |
} | |
public void delete(T entity) | |
{ | |
ofy().delete(entity); | |
} | |
public void deleteKey(Key<T> entityKey) | |
{ | |
ofy().delete(entityKey); | |
} | |
public void deleteAll(Iterable<T> entities) | |
{ | |
ofy().delete(entities); | |
} | |
public void deleteKeys(Iterable<Key<T>> keys) | |
{ | |
ofy().delete(keys); | |
} | |
public T get(Long id) throws EntityNotFoundException | |
{ | |
return ofy().get(this.clazz, id); | |
} | |
public T get(Key<T> key) throws EntityNotFoundException | |
{ | |
return ofy().get(key); | |
} | |
/* | |
* Convenience method to generate a typed Key<T> for a given id | |
*/ | |
public Key<T> getKey(Long id) { | |
return new Key<T>(clazz, id); | |
} | |
/* | |
* Get ALL entities of type <T> in the datastore. DANGEROUS!! INEFFICIENT!! | |
* Only doing this for dev/debugging purposes. | |
*/ | |
public List<T> listAll() | |
{ | |
Query<T> q = ofy().query(clazz); | |
return asList(q.fetch()); | |
} | |
/** | |
* Convenience method to get all objects matching a single property | |
* | |
* @param propName | |
* @param propValue | |
* @return T matching Object | |
*/ | |
public T getByProperty(String propName, Object propValue) | |
{ | |
Query<T> q = ofy().query(clazz); | |
q.filter(propName, propValue); | |
return q.get(); | |
} | |
public List<T> listByProperty(String propName, Object propValue) | |
{ | |
Query<T> q = ofy().query(clazz); | |
q.filter(propName, propValue); | |
return asList(q.fetch()); | |
} | |
public List<Key<T>> listKeysByProperty(String propName, Object propValue) | |
{ | |
Query<T> q = ofy().query(clazz); | |
q.filter(propName, propValue); | |
return asKeyList(q.fetchKeys()); | |
} | |
public T getByExample(T exampleObj) | |
{ | |
Query<T> queryByExample = buildQueryByExample(exampleObj); | |
Iterable<T> iterableResults = queryByExample.fetch(); | |
Iterator<T> i = iterableResults.iterator(); | |
T obj = i.next(); | |
if (i.hasNext()) | |
throw new RuntimeException("Too many results"); | |
return obj; | |
} | |
public List<T> listByExample(T exampleObj) | |
{ | |
Query<T> queryByExample = buildQueryByExample(exampleObj); | |
return asList(queryByExample.fetch()); | |
} | |
private List<T> asList(Iterable<T> iterable) | |
{ | |
ArrayList<T> list = new ArrayList<T>(); | |
for (T t : iterable) | |
{ | |
list.add(t); | |
} | |
return list; | |
} | |
private List<Key<T>> asKeyList(Iterable<Key<T>> iterableKeys) | |
{ | |
ArrayList<Key<T>> keys = new ArrayList<Key<T>>(); | |
for (Key<T> key : iterableKeys) | |
{ | |
keys.add(key); | |
} | |
return keys; | |
} | |
private Query<T> buildQueryByExample(T exampleObj) | |
{ | |
Query<T> q = ofy().query(clazz); | |
// Add all non-null properties to query filter | |
for (Field field : clazz.getDeclaredFields()) | |
{ | |
// Ignore transient, embedded, array, and collection properties | |
if (field.isAnnotationPresent(Transient.class) | |
|| (field.isAnnotationPresent(Embedded.class)) | |
|| (field.getType().isArray()) | |
|| (Collection.class.isAssignableFrom(field.getType())) | |
|| ((field.getModifiers() & BAD_MODIFIERS) != 0)) | |
continue; | |
field.setAccessible(true); | |
Object value; | |
try | |
{ | |
value = field.get(exampleObj); | |
} | |
catch (IllegalArgumentException e) | |
{ | |
throw new RuntimeException(e); | |
} | |
catch (IllegalAccessException e) | |
{ | |
throw new RuntimeException(e); | |
} | |
if (value != null) | |
{ | |
q.filter(field.getName(), value); | |
} | |
} | |
return q; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment