return null != k ? siena.Util.readField(obj, k) : null;
}
public static <T> T edit(T o, String name, Map<String, String[]> params, Annotation[] annotations) {
try {
BeanWrapper bw = new BeanWrapper(o.getClass());
// Start with relations
Class<?> spClazz = o.getClass();
/*Set<Field> fields = new HashSet<Field>();
while (spClazz!=null) {
Collections.addAll(fields, spClazz.getDeclaredFields());
spClazz = spClazz.getSuperclass();
}*/
for (Field field : ClassInfo.getClassInfo(spClazz).allExtendedFields) {
boolean isEntity = false;
boolean isJson = false;
String relation = null;
boolean multiple = false;
String owner = null;
Class<?> clazz = field.getType();
// ONE TO MANY or ONE TO ONE association
if(ClassInfo.isModel(clazz)) {
isEntity = true;
relation = clazz.getName();
}
// MANY TO ONE association
// type QUERY<T> + annotation @Filter
else if(siena.Query.class.isAssignableFrom(clazz)){
isEntity = true;
multiple = true;
Class<?> fieldType =
(Class<?>) ((ParameterizedType)
field.getGenericType()).getActualTypeArguments()[0];
relation = fieldType.getName();
owner = field.getAnnotation(Filter.class).value();
// by default, takes the type of the parent entity in lower case
if(owner == null || "".equals(owner)){
owner = o.getClass().getName().toLowerCase();
}
}
else if(Json.class.isAssignableFrom(clazz)){
isJson = true;
}
else if(field.isAnnotationPresent(Embedded.class)){
if(List.class.isAssignableFrom(clazz)){
multiple = true;
}
else if(Map.class.isAssignableFrom(clazz)){
multiple = true;
}
else {
multiple = false;
}
}
else if(byte[].class.isAssignableFrom(clazz)
/*|| Blob.class.isAssignableFrom(field.getType())*/)
{
// if params is present but empty, resets the older value
@SuppressWarnings("unused")
String[] posted = params.get(name + "." + field.getName());
// TODO
@SuppressWarnings("unused")
Object val = field.get(o);
//params.put(name + "." + field.getName(), val);
}
if (isEntity) {
// builds entity list for many to one
if (multiple) {
// retrieves list to synchronize new and removed objects
Query<?> q = (Query<?>)siena.Util.readField(o, field);
// no limitation for the time being
List<?> relObjs = q.fetch();
@SuppressWarnings("unchecked")
Class<? extends siena.Model> relClass = (Class<? extends siena.Model>)Play.classloader.loadClass(relation);
String idName = keyName(relClass);
String[] ids = params.get(name + "." + field.getName() + "@"+idName);
if(ids == null) {
ids = params.get(name + "." + field.getName() + "."+idName);
}
if (ids != null) {
params.remove(name + "." + field.getName() + "."+idName);
params.remove(name + "." + field.getName() + "@"+idName);
Field ownerField = siena.Util.getField(relClass, owner);
for (String _id : ids) {
if (_id.equals("")) {
continue;
}
Object idVal = Binder.directBind(_id, keyType(relClass));
// verifies the field is not already owned by the object
// if yes, no need to resave it with this owner
boolean b = false;
for(Object relObj:relObjs){
Object keyRelObj = keyValue(relObj);
if(keyRelObj != null && keyRelObj.equals(idVal)){
relObjs.remove(relObj);
b = true;
break;
}
}
if(!b){
siena.Model res =
siena.Model.all(relClass)
.filter(idName, idVal)
.get();
if(res!=null){
// sets the object to the owner field into the relation entity
if(ownerField == null) {
throw new UnexpectedException("In related Model "+relClass.getName()+" owner field '"+owner+"' not found");
}
siena.Util.setField(res, ownerField, o);
res.save();
}
else Validation.addError(name+"."+field.getName(), "validation.notFound", _id);
}
}
// now remaining objects have to be unowned
for(Object relObj:relObjs){
siena.Util.setField(relObj, ownerField, null);
SienaPlugin.pm().save(relObj);
}
// can't set arraylist to Query<T>
// bw.set(field.getName(), o, l);
}
}
// builds simple entity for simple association
else {
@SuppressWarnings("unchecked")
Class<? extends siena.Model> relClass = (Class<? extends siena.Model>)Play.classloader.loadClass(relation);
String idName = keyName(relClass);
String[] ids = params.get(name + "." + field.getName() + "@"+idName);
if(ids == null) {
ids = params.get(name + "." + field.getName() + "."+idName);
}
if (ids != null && ids.length > 0 && !ids[0].equals("")) {
params.remove(name + "." + field.getName() + "."+idName);
params.remove(name + "." + field.getName() + "@"+idName);
siena.Model res =
siena.Model.all(relClass)
.filter(idName, Binder.directBind(ids[0], keyType(relClass)))
.get();
if(res!=null)
bw.set(field.getName(), o, res);
else Validation.addError(name+"."+field.getName(), "validation.notFound", ids[0]);
} else if(ids != null && ids.length > 0 && ids[0].equals("")) {
bw.set(field.getName(), o , null);
params.remove(name + "." + field.getName() + "."+idName);
params.remove(name + "." + field.getName() + "@"+idName);
}
}
}
else if(isJson){
String[] jsonStr = params.get(name + "." + field.getName());
if (jsonStr != null && jsonStr.length > 0 && !jsonStr[0].equals("")) {
try {
//com.google.gson.JsonParser parser = new com.google.gson.JsonParser();
//parser.parse(jsonStr[0]);
Json json = Json.loads(jsonStr[0]);
if(json!=null){
bw.set(field.getName(), o, json);
params.remove(name + "." + field.getName());
}
else Validation.addError(name+"."+field.getName(), "validation.notParsable");
}catch(JsonParseException ex){
ex.printStackTrace();
Logger.error("json parserdelete exception:%s",
ex.getCause()!=null?ex.getCause().getMessage(): ex.getMessage());
Validation.addError(
name+"."+field.getName(),
"validation.notParsable",
ex.getCause()!=null?ex.getCause().getMessage(): ex.getMessage());
}catch(SienaException ex){
ex.printStackTrace();
Logger.error("json parserdelete exception:%s",
ex.getCause()!=null?ex.getCause().getMessage(): ex.getMessage());
Validation.addError(
name+"."+field.getName(),
"validation.notParsable",
ex.getCause()!=null?ex.getCause().getMessage(): ex.getMessage());
}
catch(IllegalArgumentException ex){
ex.printStackTrace();
Logger.error("json parser exception:%s",
ex.getCause()!=null?ex.getCause().getMessage(): ex.getMessage());
Validation.addError(
name+"."+field.getName(),
"validation.notParsable",
ex.getCause()!=null?ex.getCause().getMessage(): ex.getMessage());
}
}
}
}
// Then bind
// all composites objects (simple entity, list and maps) are managed
// by this function
// v1.0.x code
// bw.bind(name, o.getClass(), params, "", o);
RootParamNode paramNode = RootParamNode.convert(params);
// no http params to bind this object ? so we won't try to bind this object
if(paramNode.getChild(name) == null) {
return null;
}
// v1.1 compliant
bw.bind(name, (Type)o.getClass(), params, "", o, o.getClass().getAnnotations());
return (T) o;
} catch (Exception e) {
throw new UnexpectedException(e);
}