package net.carchrae.smartgwt.server;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
import javax.persistence.Id;
import net.carchrae.smartgwt.shared.data.UserAccount;
import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.beanutils.ConvertUtils;
import org.apache.commons.beanutils.converters.BooleanConverter;
import org.apache.commons.beanutils.converters.DateConverter;
import org.apache.commons.beanutils.converters.IntegerConverter;
import org.apache.commons.beanutils.converters.LongConverter;
import com.googlecode.objectify.Objectify;
import com.googlecode.objectify.Query;
import com.googlecode.objectify.impl.TypeUtils;
/**
* This does the CRUD
*
* @author tom
*
*/
public class ObjectService {
public enum OperationType {
FETCH, ADD, UPDATE, DELETE
}
public ObjectService(Objectify ofy, Class clazz) {
this.ofy = ofy;
this.clazz = clazz;
findIdFieldName();
// FIXME: add other converters so that null values are stored instead of
// defaults. if you don't do this, you'll get a default value stored
// instead of a null
ConvertUtils.register(new IntegerConverter(null), Integer.class);
ConvertUtils.register(new LongConverter(null), Long.class);
ConvertUtils.register(new BooleanConverter(null), Boolean.class);
// FIXME: todo, add support for time. could just make all date fields
// datetime instead
DateConverter dateConverter = new DateConverter(null);
dateConverter.setPattern("yyyy-MM-dd");
ConvertUtils.register(dateConverter, Date.class);
}
// public static interface Function {
// void apply(DSRequest request);
// }
private Objectify ofy;
private Class clazz;
private Field idField;
// private List<Function> criteriaFunctions = new ArrayList<Function>();
private boolean global;
private void findIdFieldName() {
// Check all the fields
for (Field field : clazz.getDeclaredFields()) {
if (!TypeUtils.isSaveable(field))
continue;
boolean original = field.isAccessible();
field.setAccessible(true);
if (field.isAnnotationPresent(Id.class)) {
idField = field;
}
field.setAccessible(original);
if (idField != null)
break;
}
if (idField == null)
throw new RuntimeException("Could not find ID field in class "
+ clazz.getSimpleName());
}
public ResponseList fetch(Map criteria) {
try {
Query query = ofy.query(clazz);
for (Object key : criteria.keySet()) {
Object value = criteria.get(key);
System.out
.println("Filtering on criteria " + key + "=" + value);
if (value != null
&& List.class.isAssignableFrom(value.getClass())) {
if (((List) value).size() > 0)
query.filter(key + " IN", value);
else
System.out.println("Ignoring criteria : " + key
+ " because it was an empty list");
} else
query.filter((String) key, value);
}
List list = query.list();
return new ResponseList(list);
} catch (Exception e) {
e.printStackTrace();
List list = new ArrayList();
return new ResponseList(list);
}
}
public Response add(Map properties) {
Response response = new Response();
try {
Object object = clazz.newInstance();
BeanUtils.populate(object, properties);
// DataTools.setProperties(request.getValues(), object);
ofy.put(object);
response.setData(object);
} catch (InstantiationException e) {
e.printStackTrace();
response.setFailure();
} catch (IllegalAccessException e) {
e.printStackTrace();
response.setFailure();
} catch (Exception e) {
e.printStackTrace();
response.setFailure();
}
return response;
}
public Response update(Map properties) {
Response response = new Response();
Object object = findObject(properties);
try {
BeanUtils.populate(object, properties);
ofy.put(object);
response.setData(object);
} catch (Exception e) {
e.printStackTrace();
response.setFailure();
}
return response;
}
Object findObject(Map properties) {
Object object = null;
Class<?> class1 = idField.getType();
if (class1.equals(Long.class)) {
String value = (String) properties.get(idField.getName());
Long id = (Long) ConvertUtils.convert(value, Long.class);
object = ofy.find(clazz, id);
}
if (class1.equals(String.class)) {
String id = (String) properties.get(idField.getName());
object = ofy.find(clazz, id);
}
return object;
}
public Response remove(Map properties) {
Object object = findObject(properties);
Response response = new Response();
if (object == null) {
response.setData(object);
response.setFailure();
} else
ofy.delete(object);
return response;
}
// public void addFetchCriteriaFunction(Function f) {
// criteriaFunctions.add(f);
// }
private boolean isAllowed(OperationType type, UserAccount account) {
if (true || account != null)
return true;
else
return false;
}
public void setGlobal(boolean global) {
this.global = global;
}
public boolean isGlobal() {
return global;
}
}