package play.utils.crud;
import static play.libs.Json.toJson;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import javax.persistence.OptimisticLockException;
import com.fasterxml.jackson.databind.JsonNode;
import play.Logger;
import play.Logger.ALogger;
import play.mvc.Controller;
import play.mvc.Result;
import play.utils.dao.DAO;
import play.utils.dao.EntityNotFoundException;
import com.google.common.collect.ImmutableMap;
public abstract class APIController<K, M> extends Controller implements CRUD<K, M> {
protected final ALogger log = Logger.of(getClass());
protected final DAO<K, M> dao;
protected final Class<K> keyClass;
protected final Class<M> modelClass;
public APIController(DAO<K, M> dao, Class<K> keyClass, Class<M> modelClass) {
super();
this.dao = dao;
this.keyClass = keyClass;
this.modelClass = modelClass;
}
public abstract Result create();
public DAO<K, M> getDao() {
return dao;
}
public Class<K> getKeyClass() {
return keyClass;
}
public Class<M> getModelClass() {
return modelClass;
}
public Result update(K key) {
if (log.isDebugEnabled())
log.debug("update <- " + key);
Result check = checkRequired("name", "value");
if (check != null) {
return check;
}
// field name & value
String name = jsonText("name");
String value = jsonText("value");
if (log.isDebugEnabled())
log.debug("name : " + name);
if (log.isDebugEnabled())
log.debug("value : " + value);
M m = dao.get(key);
if (log.isDebugEnabled())
log.debug("m : " + m);
if (m == null) {
return notFound(toJson(ImmutableMap.of("status", "NOT_FOUND", "key", key, "message",
"entity with the given key not found")));
}
String fieldName = Character.toUpperCase(name.charAt(0)) + name.substring(1);
try {
setField(m, fieldName, value);
} catch (NoSuchMethodException e) {
return notFound(toJson(ImmutableMap.of("status", "OK", "key", key, "message", "field[" + name
+ "] on entity not found")));
} catch (SecurityException e) {
return internalServerError(toJson(ImmutableMap.of("status", "OK", "key", key, "message", "error occured : "
+ e)));
} catch (IllegalAccessException e) {
return internalServerError(toJson(ImmutableMap.of("status", "OK", "key", key, "message", "error occured : "
+ e)));
} catch (IllegalArgumentException e) {
return internalServerError(toJson(ImmutableMap.of("status", "OK", "key", key, "message", "error occured : "
+ e)));
} catch (InvocationTargetException e) {
return internalServerError(toJson(ImmutableMap.of("status", "OK", "key", key, "message", "error occured : "
+ e)));
}
dao.update(m);
if (log.isDebugEnabled())
log.debug("updated.");
if (log.isDebugEnabled())
log.debug("m : " + m);
return ok(toJson(ImmutableMap.of("status", "OK", "key", key, "message", "field[" + name + "] updated")));
}
protected <S> void setField(S s, String fieldName, String value) throws NoSuchMethodException, SecurityException,
IllegalAccessException, IllegalArgumentException, InvocationTargetException {
Class<?> cls = s.getClass();
Method method = cls.getMethod("set" + fieldName, String.class);
method.invoke(s, value);
}
public Result list() {
List<M> list = dao.all();
return ok(toJson(ImmutableMap.of("status", "OK", "list", list)));
}
public Result read(K key) {
M model = dao.get(key);
if (model == null) {
return notFound(toJson(ImmutableMap.of("status", "NOT_FOUND", "key", key)));
}
return ok(toJson(ImmutableMap.of("status", "OK", "key", key, "data", model)));
}
public Result delete(K key) {
try {
dao.remove(key);
} catch (EntityNotFoundException e) {
return notFound(toJson(ImmutableMap.of("status", "NOT_FOUND", "key", key)));
} catch (OptimisticLockException e) {
return notFound(toJson(ImmutableMap.of("status", "CANNOT_DELETE", "key", key)));
}
return ok(toJson(ImmutableMap.of("status", "OK", "key", key, "message", "deleted :" + key)));
}
protected String jsonText(String name) {
JsonNode json = request().body().asJson();
JsonNode node = json.get(name);
if (node == null)
return null;
String value = node.asText();
return value;
}
protected List<String> jsonTextList(String name) {
JsonNode json = request().body().asJson();
JsonNode node = json.get(name);
if (node == null)
return null;
List<String> list = new ArrayList<String>();
for (Iterator<JsonNode> elems = node.elements(); elems.hasNext();) {
JsonNode elem = elems.next();
list.add(elem.asText());
}
return list;
}
protected Result checkRequired(String... params) {
List<String> missing = new ArrayList<String>();
for (String param : params) {
String val = jsonText(param);
if (val == null) {
missing.add(param);
}
}
if (!missing.isEmpty()) {
return badRequest(toJson(ImmutableMap.of("status", "MISSING", "message",
"Missing parameters :" + missing.toString())));
}
return null;
}
public static Result invalid(String res) {
String method = request().method();
String resource = request().path();
return notFound(toJson(ImmutableMap.of("status", "NOT_FOUND", "message", "resource not found:" + method + " "
+ resource)));
}
}