X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.document.server%2Fsrc%2Forg%2Fsimantics%2Fdocument%2Fserver%2Fstate%2FStateNodeManager.java;fp=bundles%2Forg.simantics.document.server%2Fsrc%2Forg%2Fsimantics%2Fdocument%2Fserver%2Fstate%2FStateNodeManager.java;h=0b48e27220bbdf2fa130400b30857f2ad5ef2214;hp=0000000000000000000000000000000000000000;hb=8c8283a01e63980527d605936286747006bea601;hpb=0b65b9e03c2fe0eae91af7a8b87b63df749dc5f9 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 index 000000000..0b48e2722 --- /dev/null +++ b/bundles/org.simantics.document.server/src/org/simantics/document/server/state/StateNodeManager.java @@ -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 { + + private static final org.slf4j.Logger LOGGER = LoggerFactory.getLogger(StateNodeManager.class); + + private NodeSupport support; + + public StateNodeManager(StandardRealm realm, StateNode root) { + super(realm, root); + } + + public void registerSupport(NodeSupport support) { + this.support = support; + } + + @Override + public Set 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 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); + } + } + +}