@SuppressWarnings("deprecation")
public static <T extends JPABase> T edit(ParamNode rootParamNode, String name, Object o, Annotation[] annotations) {
// #1601 - If name is empty, we're dealing with "root" request parameters (without prefixes).
// Must not call rootParamNode.getChild in that case, as it returns null. Use rootParamNode itself instead.
ParamNode paramNode = StringUtils.isEmpty(name) ? rootParamNode : rootParamNode.getChild(name, true);
// #1195 - Needs to keep track of whick keys we remove so that we can restore it before
// returning from this method.
List<ParamNode.RemovedNode> removedNodesList = new ArrayList<ParamNode.RemovedNode>();
try {
BeanWrapper bw = new BeanWrapper(o.getClass());
// Start with relations
Set<Field> fields = new HashSet<Field>();
Class clazz = o.getClass();
while (!clazz.equals(Object.class)) {
Collections.addAll(fields, clazz.getDeclaredFields());
clazz = clazz.getSuperclass();
}
for (Field field : fields) {
boolean isEntity = false;
String relation = null;
boolean multiple = false;
//
if (field.isAnnotationPresent(OneToOne.class) || field.isAnnotationPresent(ManyToOne.class)) {
isEntity = true;
relation = field.getType().getName();
}
if (field.isAnnotationPresent(OneToMany.class) || field.isAnnotationPresent(ManyToMany.class)) {
Class fieldType = (Class) ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0];
isEntity = true;
relation = fieldType.getName();
multiple = true;
}
if (isEntity) {
ParamNode fieldParamNode = paramNode.getChild(field.getName(), true);
Class<Model> c = (Class<Model>) Yalp.classloader.loadClass(relation);
if (JPABase.class.isAssignableFrom(c)) {
String keyName = Model.Manager.factoryFor(c).keyName();
if (multiple && Collection.class.isAssignableFrom(field.getType())) {
Collection l = new ArrayList();
if (SortedSet.class.isAssignableFrom(field.getType())) {
l = new TreeSet();
} else if (Set.class.isAssignableFrom(field.getType())) {
l = new HashSet();
}
String[] ids = fieldParamNode.getChild(keyName, true).getValues();
if (ids != null) {
// Remove it to prevent us from finding it again later
fieldParamNode.removeChild(keyName, removedNodesList);
for (String _id : ids) {
if (_id.equals("")) {
continue;
}
Query q = JPA.em().createQuery("from " + relation + " where " + keyName + " = ?1");
q.setParameter(1, Binder.directBind(rootParamNode.getOriginalKey(), annotations, _id, Model.Manager.factoryFor((Class<Model>) Yalp.classloader.loadClass(relation)).keyType(), null));
try {
l.add(q.getSingleResult());
} catch (NoResultException e) {
Validation.addError(name + "." + field.getName(), "validation.notFound", _id);
}
}
bw.set(field.getName(), o, l);
}
} else {
String[] ids = fieldParamNode.getChild(keyName, true).getValues();
if (ids != null && ids.length > 0 && !ids[0].equals("")) {
Query q = JPA.em().createQuery("from " + relation + " where " + keyName + " = ?1");
q.setParameter(1, Binder.directBind(rootParamNode.getOriginalKey(), annotations, ids[0], Model.Manager.factoryFor((Class<Model>) Yalp.classloader.loadClass(relation)).keyType(), null));
try {
Object to = q.getSingleResult();
edit(paramNode, field.getName(), to, field.getAnnotations());
// Remove it to prevent us from finding it again later
paramNode.removeChild(field.getName(), removedNodesList);
bw.set(field.getName(), o, to);
} catch (NoResultException e) {
Validation.addError(fieldParamNode.getOriginalKey(), "validation.notFound", ids[0]);
// Remove only the key to prevent us from finding it again later
// This how the old impl does it..
fieldParamNode.removeChild(keyName, removedNodesList);
if (fieldParamNode.getAllChildren().size() == 0) {
// remove the whole node..
paramNode.removeChild(field.getName(), removedNodesList);
}
}
} else if (ids != null && ids.length > 0 && ids[0].equals("")) {
bw.set(field.getName(), o, null);
// Remove the key to prevent us from finding it again later
fieldParamNode.removeChild(keyName, removedNodesList);
}
}
}
}
}
// #1601 - If name is empty, we're dealing with "root" request parameters (without prefixes).
// Must not call rootParamNode.getChild in that case, as it returns null. Use rootParamNode itself instead.
ParamNode beanNode = StringUtils.isEmpty(name) ? rootParamNode : rootParamNode.getChild(name, true);
Binder.bindBean(beanNode, o, annotations);
return (T) o;
} catch (Exception e) {
throw new UnexpectedException(e);
} finally {