|
|
@@ -3,6 +3,9 @@ package name.tflucke.ieat2.controllers;
|
|
|
import java.util.List;
|
|
|
import java.util.Arrays;
|
|
|
import java.util.Set;
|
|
|
+import java.util.Map;
|
|
|
+import java.util.TreeMap;
|
|
|
+import java.util.stream.Stream;
|
|
|
import java.util.stream.Collectors;
|
|
|
import java.lang.reflect.Field;
|
|
|
import java.lang.reflect.Modifier;
|
|
|
@@ -39,7 +42,7 @@ public abstract class AbstractController<T extends DBObject> {
|
|
|
@Autowired
|
|
|
protected Datastore db;
|
|
|
private final Class<T> clazz;
|
|
|
- private final Set<Field> fields;
|
|
|
+ private final Map<Class<?>, Set<Field>> fields;
|
|
|
|
|
|
/**
|
|
|
* Sets up class information about how/what to store.
|
|
|
@@ -47,9 +50,30 @@ public abstract class AbstractController<T extends DBObject> {
|
|
|
protected AbstractController(final Class<T> clazz)
|
|
|
{
|
|
|
this.clazz = clazz;
|
|
|
- fields = Arrays.stream(clazz.getDeclaredFields())
|
|
|
- .filter((Field field) -> Modifier.isPublic(field.getModifiers()))
|
|
|
- .collect(Collectors.toSet());
|
|
|
+ fields = new TreeMap<>((Class<?> a, Class<?> b) -> {
|
|
|
+ return a.hashCode() - b.hashCode();
|
|
|
+ });
|
|
|
+ }
|
|
|
+
|
|
|
+ private Stream<Field> getFieldStream(Class<?> clazz) {
|
|
|
+ if (DBObject.class.equals(clazz)) {
|
|
|
+ return Stream.empty();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return Stream.concat(Arrays.stream(clazz.getDeclaredFields()),
|
|
|
+ getFieldStream(clazz.getSuperclass()));
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ protected Set<Field> getFields(Class<? extends DBObject> clazz) {
|
|
|
+ Set<Field> res = fields.get(clazz);
|
|
|
+ if (res == null) {
|
|
|
+ res = getFieldStream(clazz)
|
|
|
+ .filter((Field field) -> Modifier.isPublic(field.getModifiers()))
|
|
|
+ .collect(Collectors.toSet());
|
|
|
+ fields.put(clazz, res);
|
|
|
+ }
|
|
|
+ return res;
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -80,14 +104,12 @@ public abstract class AbstractController<T extends DBObject> {
|
|
|
*/
|
|
|
protected T get(final String id) {
|
|
|
final T result = db.getByKey(clazz, toKey(id));
|
|
|
- if (result == null)
|
|
|
- {
|
|
|
- throw new ResourceNotFoundException();
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
- return result;
|
|
|
- }
|
|
|
+ if (result == null) {
|
|
|
+ throw new ResourceNotFoundException();
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ return result;
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -127,16 +149,17 @@ public abstract class AbstractController<T extends DBObject> {
|
|
|
* @return The newly updated element
|
|
|
*/
|
|
|
protected T update(final String id, final T element) {
|
|
|
- // Update is more complex to allow partial updates.
|
|
|
+ Set<Field> fields = getFields(element.getClass());
|
|
|
final UpdateOperations<T> updateOps = db.createUpdateOperations(clazz);
|
|
|
updateOps.inc("version");
|
|
|
fields.forEach((Field field) -> {
|
|
|
try {
|
|
|
final Object value = field.get(element);
|
|
|
- if (value != null)
|
|
|
- {
|
|
|
- updateOps.set(field.getName(), value);
|
|
|
- }
|
|
|
+ if (value != null) {
|
|
|
+ updateOps.set(field.getName(), value);
|
|
|
+ }
|
|
|
+ log.debug(field.getName());
|
|
|
+ log.debug(value);
|
|
|
}
|
|
|
catch (IllegalAccessException ise) {
|
|
|
// Filter at beginning should leave only public fields.
|
|
|
@@ -147,6 +170,7 @@ public abstract class AbstractController<T extends DBObject> {
|
|
|
}
|
|
|
});
|
|
|
db.update(toKey(id), updateOps);
|
|
|
+ log.debug(updateOps);
|
|
|
return get(id);
|
|
|
}
|
|
|
|