]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.document.server/src/org/simantics/document/server/state/StateNodeManager.java
New implementation of server state based on StandardNodeManager
[simantics/platform.git] / bundles / org.simantics.document.server / src / org / simantics / document / server / state / StateNodeManager.java
diff --git a/bundles/org.simantics.document.server/src/org/simantics/document/server/state/StateNodeManager.java b/bundles/org.simantics.document.server/src/org/simantics/document/server/state/StateNodeManager.java
new file mode 100644 (file)
index 0000000..0b48e27
--- /dev/null
@@ -0,0 +1,149 @@
+package org.simantics.document.server.state;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.Map;
+import java.util.Set;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.binding.Binding;
+import org.simantics.databoard.binding.error.BindingConstructionException;
+import org.simantics.databoard.binding.mutable.Variant;
+import org.simantics.databoard.serialization.RuntimeSerializerConstructionException;
+import org.simantics.databoard.serialization.SerializerConstructionException;
+import org.simantics.db.layer0.variable.NodeSupport;
+import org.simantics.simulator.toolkit.StandardNodeManager;
+import org.simantics.simulator.toolkit.StandardRealm;
+import org.simantics.simulator.variable.exceptions.NodeManagerException;
+import org.slf4j.LoggerFactory;
+
+public class StateNodeManager extends StandardNodeManager<StateNode, StateNodeManagerSupport> {
+
+       private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(StateNodeManager.class);
+
+       private NodeSupport<StateNode> support;
+
+       public StateNodeManager(StandardRealm<StateNode, StateNodeManagerSupport> realm, StateNode root) {
+               super(realm, root);
+       }
+
+       public void registerSupport(NodeSupport<StateNode> support) {
+               this.support = support;
+       }
+
+       @Override
+       public Set<String> getClassifications(StateNode node) throws NodeManagerException {
+               return Collections.emptySet();
+       }
+
+       @Override
+       public void refreshVariable(StateNode node) {
+               super.refreshVariable(node);
+               support.valueCache.clearExpired();
+               support.structureCache.clearExpired();
+       }
+
+       public void setState(String key, Object value) {
+               try {
+                       getRealm().syncExec(() -> {
+                               try {
+                                       StateRootNode rootNode = (StateRootNode) getRoot();
+                                       StatePropertyNode propertyNode = rootNode.getProperty(key);
+                                       if (propertyNode == null) {
+                                               setValue(rootNode.createProperty(key), value, Bindings.OBJECT);
+                                               refreshVariable(rootNode);
+                                       } else {
+                                               setValue(propertyNode, value, Bindings.OBJECT);
+                                       }
+                               } catch (NodeManagerException e) {
+                                       LOGGER.error("Failed to set state.", e);
+                               }
+                       });
+               } catch (InterruptedException e) {
+                       LOGGER.error("Setting state was interrupted.", e);
+               }
+       }
+
+       public byte[] serialize() {
+               final byte [][] result = new byte[1][];
+               try {
+                       getRealm().syncExec(() -> {
+                               State state = new State();
+                               StateRootNode root = (StateRootNode) getRoot();
+                               for (StateNode node : root.getProperties().values()) {
+                                       StatePropertyNode property = (StatePropertyNode)node;
+                                       try {
+                                               Binding binding = Bindings.getInstanceBinding(property.getValue());
+                                               if (binding != null) {
+                                                       state.properties.put(property.getName(), new Variant(binding, property.getValue()));
+                                               }
+                                       } catch (BindingConstructionException e) {
+                                               // skip
+                                       }
+                               }
+
+                               try {
+                                       result[0] = Bindings.getSerializerUnchecked(State.BINDING).serialize(state);
+                               } catch (RuntimeSerializerConstructionException | IOException e) {
+                               }
+                       });
+               } catch (InterruptedException e) {
+                       LOGGER.error("Serializing state was interrupted.", e);
+               }
+               return result[0];
+       }
+
+       public void deserialize(byte[] bytes) {
+               try {
+                       getRealm().syncExec(() -> {
+                               StateRootNode rootNode = (StateRootNode) getRoot();
+                               rootNode.clear();
+                               try {
+                                       State state = (State) Bindings.getSerializer(State.BINDING).deserialize(bytes);
+                                       for (Map.Entry<String, Variant> entry : state.properties.entrySet()) {
+                                               String key = entry.getKey();
+                                               Object value = entry.getValue().getValue();
+                                               try {
+                                                       setValue(rootNode.createProperty(key), value, Bindings.OBJECT);
+                                               } catch (NodeManagerException e) {
+                                                       LOGGER.error("Failed to deserialize state.", e);
+                                               }
+                                       }
+                                       refreshVariable(rootNode);
+                               } catch (IOException e1) {
+                                       LOGGER.error("Failed to deserialize state.", e1);
+                               } catch (SerializerConstructionException e1) {
+                                       LOGGER.error("Failed to deserialize state.", e1);
+                               }
+                       });
+               } catch (InterruptedException e) {
+                       LOGGER.error("Deserializing state was interrupted.", e);
+               }
+       }
+
+       public void clearState() {
+               try {
+                       getRealm().syncExec(() -> {
+                               StateRootNode rootNode = (StateRootNode) getRoot();
+                               rootNode.clear();
+                               refreshVariable(rootNode);
+                       });
+               } catch (InterruptedException e) {
+                       LOGGER.error("Clearing state was interrupted.", e);
+               }
+       }
+
+       public void removeState(String key) {
+               try {
+                       getRealm().syncExec(() -> {
+                               StateRootNode rootNode = (StateRootNode) getRoot();
+                               if (rootNode.removeProperty(key)) {
+                                       refreshVariable(rootNode);
+                               }
+                       });
+               } catch (InterruptedException e) {
+                       LOGGER.error("Removing state was interrupted.", e);
+               }
+       }
+
+}