Explorar o código

Fixed bug with subclass fields not updating.

Thomas Flucke %!s(int64=7) %!d(string=hai) anos
pai
achega
082019f990
Modificáronse 1 ficheiros con 41 adicións e 17 borrados
  1. 41 17
      src/name/tflucke/ieat2/controllers/AbstractController.java

+ 41 - 17
src/name/tflucke/ieat2/controllers/AbstractController.java

@@ -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);
     }