From 875b74f5843072408ae8ed85d4605a72105c121c Mon Sep 17 00:00:00 2001
From: Timm Fitschen <t.fitschen@indiscale.com>
Date: Thu, 19 Nov 2020 22:37:02 +0100
Subject: [PATCH] WIP: automatic record state

---
 .../jobs/core/CheckStateTransition.java       |  2 +-
 .../server/jobs/core/InheritInitialState.java | 34 +++++++++++++++
 .../server/jobs/core/InitEntityStateJobs.java |  9 ++++
 .../server/jobs/core/MakeStateMessage.java    | 43 ++++++++++++-------
 4 files changed, 72 insertions(+), 16 deletions(-)
 create mode 100644 src/main/java/org/caosdb/server/jobs/core/InheritInitialState.java

diff --git a/src/main/java/org/caosdb/server/jobs/core/CheckStateTransition.java b/src/main/java/org/caosdb/server/jobs/core/CheckStateTransition.java
index 91843299..af3ba15a 100644
--- a/src/main/java/org/caosdb/server/jobs/core/CheckStateTransition.java
+++ b/src/main/java/org/caosdb/server/jobs/core/CheckStateTransition.java
@@ -15,7 +15,7 @@ import org.caosdb.server.utils.ServerMessages;
  *
  * @author Timm Fitschen (t.fitschen@indiscale.com)
  */
-@JobAnnotation(time = JobExecutionTime.CHECK, transaction = WriteTransaction.class)
+@JobAnnotation(time = JobExecutionTime.POST_CHECK, transaction = WriteTransaction.class)
 public class CheckStateTransition extends EntityStateJob {
 
   private static final Message TRANSITION_NOT_ALLOWED =
diff --git a/src/main/java/org/caosdb/server/jobs/core/InheritInitialState.java b/src/main/java/org/caosdb/server/jobs/core/InheritInitialState.java
new file mode 100644
index 00000000..e21d76c9
--- /dev/null
+++ b/src/main/java/org/caosdb/server/jobs/core/InheritInitialState.java
@@ -0,0 +1,34 @@
+package org.caosdb.server.jobs.core;
+
+import java.util.List;
+import org.caosdb.server.entity.Message;
+import org.caosdb.server.entity.wrapper.Parent;
+import org.caosdb.server.entity.wrapper.Property;
+import org.caosdb.server.jobs.JobAnnotation;
+import org.caosdb.server.jobs.JobExecutionTime;
+
+@JobAnnotation(time = JobExecutionTime.CHECK)
+public class InheritInitialState extends EntityStateJob {
+
+  @Override
+  protected void run() {
+    try {
+      State parentState = getFirstParentState();
+      if (parentState != null) {
+        getEntity().addMessage(parentState);
+      }
+    } catch (Message e) {
+      getEntity().addError(e);
+    }
+  }
+
+  private State getFirstParentState() throws Message {
+    for (Parent par : getEntity().getParents()) {
+      List<Property> stateProperties = getStateProperties(par, false);
+      if (stateProperties.size() > 0) {
+        return createState(stateProperties.get(0));
+      }
+    }
+    return null;
+  }
+}
diff --git a/src/main/java/org/caosdb/server/jobs/core/InitEntityStateJobs.java b/src/main/java/org/caosdb/server/jobs/core/InitEntityStateJobs.java
index e4a32bc5..5dec5d49 100644
--- a/src/main/java/org/caosdb/server/jobs/core/InitEntityStateJobs.java
+++ b/src/main/java/org/caosdb/server/jobs/core/InitEntityStateJobs.java
@@ -7,8 +7,10 @@ import org.caosdb.server.CaosDBServer;
 import org.caosdb.server.entity.ClientMessage;
 import org.caosdb.server.entity.Entity;
 import org.caosdb.server.entity.EntityInterface;
+import org.caosdb.server.entity.InsertEntity;
 import org.caosdb.server.entity.Message;
 import org.caosdb.server.entity.Message.MessageType;
+import org.caosdb.server.entity.Role;
 import org.caosdb.server.entity.UpdateEntity;
 import org.caosdb.server.entity.wrapper.Property;
 import org.caosdb.server.jobs.JobAnnotation;
@@ -43,6 +45,13 @@ public class InitEntityStateJobs extends EntityStateJob implements Observer {
         appendJob(CheckStateTransition.class);
         appendJob(MakeStateProperty.class);
         appendJob(MakeStateMessage.class);
+      } else if (newState == null
+          && getEntity().getRole() == Role.Record
+          && getEntity() instanceof InsertEntity) {
+        appendJob(InheritInitialState.class);
+        appendJob(CheckStateTransition.class);
+        appendJob(MakeStateProperty.class);
+        appendJob(MakeStateMessage.class);
       }
     }
   }
diff --git a/src/main/java/org/caosdb/server/jobs/core/MakeStateMessage.java b/src/main/java/org/caosdb/server/jobs/core/MakeStateMessage.java
index f2090d82..f47c1157 100644
--- a/src/main/java/org/caosdb/server/jobs/core/MakeStateMessage.java
+++ b/src/main/java/org/caosdb/server/jobs/core/MakeStateMessage.java
@@ -1,6 +1,7 @@
 package org.caosdb.server.jobs.core;
 
 import java.util.List;
+import java.util.Map;
 import org.caosdb.server.CaosDBServer;
 import org.caosdb.server.entity.Message;
 import org.caosdb.server.entity.wrapper.Property;
@@ -36,26 +37,19 @@ public class MakeStateMessage extends EntityStateJob {
         List<Property> stateProperties = getStateProperties(true);
 
         // only add the State during Retrieve. In all other cases, the State is already present.
-        if (stateProperties != null && getTransaction() instanceof Retrieve) {
-          String sparse =
-              getTransaction().getContainer().getFlags().getOrDefault(SPARSE_FLAG, "false");
-          if ("true".equals(sparse)) {
+        if (stateProperties != null
+            && stateProperties.size() > 0
+            && getTransaction() instanceof Retrieve) {
+          if (isSparse()) {
             for (Property s : stateProperties) {
-              getEntity()
-                  .addMessage(
-                      new ToElementable() {
-                        @Override
-                        public void addToElement(Element ret) {
-                          Element state = new Element(STATE_XML_TAG);
-                          state.setAttribute(STATE_ATTRIBUTE_ID, s.getValue().toString());
-                          ret.addContent(state);
-                        }
-                      });
+              getEntity().addMessage(getSparseStateMessage(s));
             }
           } else {
             for (Property s : stateProperties) {
               State stateMessage = createState(s);
-              stateMessage.getStateModel();
+              stateMessage
+                  .getStateModel(); // trigger retrieval of state model because when the XML Writer
+              // calls the addToElement method, it is to late.
               getEntity().addMessage(stateMessage);
             }
           }
@@ -65,4 +59,23 @@ public class MakeStateMessage extends EntityStateJob {
       }
     }
   }
+
+  private ToElementable getSparseStateMessage(Property s) {
+    return new ToElementable() {
+      @Override
+      public void addToElement(Element ret) {
+        Element state = new Element(STATE_XML_TAG);
+        state.setAttribute(STATE_ATTRIBUTE_ID, s.getValue().toString());
+        ret.addContent(state);
+      }
+    };
+  }
+
+  private boolean isSparse() {
+    Map<String, String> flags = getTransaction().getContainer().getFlags();
+    if (flags != null) {
+      return "true".equals(flags.getOrDefault(SPARSE_FLAG, "false"));
+    }
+    return false;
+  }
 }
-- 
GitLab