]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.modeling/src/org/simantics/modeling/scl/SCLNodeManager.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / scl / SCLNodeManager.java
diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/SCLNodeManager.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/scl/SCLNodeManager.java
new file mode 100644 (file)
index 0000000..a062eb7
--- /dev/null
@@ -0,0 +1,277 @@
+package org.simantics.modeling.scl;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collections;\r
+import java.util.List;\r
+import java.util.Set;\r
+import java.util.concurrent.atomic.AtomicBoolean;\r
+\r
+import org.simantics.databoard.Datatypes;\r
+import org.simantics.databoard.binding.Binding;\r
+import org.simantics.databoard.type.Datatype;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.layer0.variable.NodeSupport;\r
+import org.simantics.scl.compiler.types.Type;\r
+import org.simantics.simulator.variable.Realm;\r
+import org.simantics.simulator.variable.exceptions.NodeManagerException;\r
+import org.simantics.simulator.variable.exceptions.NotInRealmException;\r
+import org.simantics.simulator.variable.impl.AbstractNodeManager;\r
+import org.simantics.structural.stubs.StructuralResource2;\r
+\r
+import gnu.trove.map.hash.THashMap;\r
+import gnu.trove.procedure.TObjectProcedure;\r
+import gnu.trove.set.hash.THashSet;\r
+\r
+public class SCLNodeManager extends AbstractNodeManager<String> {\r
+\r
+    public static final String ROOT = "@";\r
+    \r
+    SCLRealm realm;\r
+    THashMap<String, Object> valueCache = new THashMap<String, Object>(); \r
+    THashMap<String, THashSet<Runnable>> listeners = new THashMap<String, THashSet<Runnable>>(); \r
+    \r
+    AtomicBoolean fireNodeListenersScheduled = new AtomicBoolean(false);\r
+    Runnable fireNodeListeners = new Runnable() {\r
+        @Override\r
+        public void run() {\r
+            fireNodeListenersScheduled.set(false);\r
+            final TObjectProcedure<Runnable> procedure = new TObjectProcedure<Runnable>() {\r
+                @Override\r
+                public boolean execute(Runnable object) {\r
+                    object.run();\r
+                    return true;\r
+                }\r
+            };\r
+            synchronized(listeners) {\r
+                listeners.forEachValue(new TObjectProcedure<THashSet<Runnable>>() {\r
+                    @Override\r
+                    public boolean execute(THashSet<Runnable> object) {\r
+                        object.forEach(procedure);\r
+                        return true;\r
+                    }\r
+                });\r
+            }\r
+        }\r
+    };\r
+    \r
+    Runnable clearValueCache = new Runnable() {\r
+        @Override\r
+        public void run() {\r
+            valueCache.clear(); \r
+        }\r
+    };\r
+    \r
+    public SCLNodeManager(SCLRealm realm) {\r
+        super();\r
+        this.realm = realm;\r
+    }\r
+\r
+    @Override\r
+    public Realm getRealm() {\r
+        return realm;\r
+    }\r
+\r
+    public String getRoot() {\r
+       return ROOT;\r
+    }\r
+    \r
+    @Override\r
+    public String getName(String node) {\r
+        if(ROOT.equals(node)) {\r
+               String id = realm.id;\r
+               int lastSlash = id.lastIndexOf("/");\r
+               if(lastSlash == -1) throw new IllegalStateException("Invalid realm id " + id);\r
+               String name = id.substring(lastSlash+1); \r
+               return name;\r
+        } else\r
+            return node;\r
+    }\r
+\r
+    @Override\r
+    public void addNodeListener(String node, Runnable listener) {\r
+        synchronized(listeners) {\r
+            THashSet<Runnable> l = listeners.get(node);\r
+            if(l == null) {\r
+                l = new THashSet<Runnable>();\r
+                listeners.put(node, l);\r
+            }\r
+            l.add(listener);\r
+        }\r
+        realm.asyncExec(listener);\r
+    }\r
+\r
+    @Override\r
+    public void removeNodeListener(String node, Runnable listener) {\r
+        synchronized(listeners) {\r
+            THashSet<Runnable> l = listeners.get(node);\r
+            if(l != null) {\r
+                l.remove(listener);\r
+                if(l.isEmpty())\r
+                    listeners.remove(node);\r
+            }\r
+        }\r
+    }\r
+    \r
+    public void fireNodeListeners() {\r
+        if(!fireNodeListenersScheduled.getAndSet(true))\r
+            realm.asyncExec(fireNodeListeners);\r
+    }\r
+    \r
+    public void fireNodeListenersSync() {\r
+       try {\r
+                       realm.syncExec(fireNodeListeners);\r
+               } catch (InterruptedException e) {\r
+                       e.printStackTrace();\r
+               }\r
+    }\r
+\r
+    public void refreshVariables() {\r
+        realm.asyncExec(clearValueCache);\r
+        fireNodeListeners();\r
+    }\r
+\r
+    public void refreshVariablesSync() {\r
+        try {\r
+                       realm.syncExec(clearValueCache);\r
+               } catch (InterruptedException e) {\r
+                       e.printStackTrace();\r
+               }\r
+        fireNodeListenersSync();\r
+    }\r
+\r
+    @Override\r
+    public String getNode(String path) throws NodeManagerException {\r
+        checkThreadAccess();\r
+        throw new UnsupportedOperationException();\r
+    }\r
+\r
+    @Override\r
+    public String getChild(String node, String name)\r
+            throws NodeManagerException {\r
+        checkThreadAccess();\r
+        return null;\r
+    }\r
+\r
+    @Override\r
+    public String getProperty(String node, String name)\r
+            throws NodeManagerException {\r
+        checkThreadAccess();\r
+        if(node.equals(ROOT))\r
+            return name;\r
+        else\r
+            return null;\r
+    }\r
+\r
+    @Override\r
+    public List<String> getChildren(String node) throws NodeManagerException {\r
+        checkThreadAccess();\r
+        return Collections.emptyList();\r
+    }\r
+\r
+    @Override\r
+    public List<String> getProperties(String node) throws NodeManagerException {\r
+        checkThreadAccess();\r
+        if(!node.equals(ROOT))\r
+            return Collections.emptyList();\r
+               \r
+        Set<String> variables = realm.getConnection().getVariables();\r
+        return new ArrayList<String>(variables);\r
+               \r
+    }\r
+\r
+    @Override\r
+    public Datatype getDatatype(String node) throws NodeManagerException {\r
+        checkThreadAccess();\r
+        try {\r
+            Datatype type = getDatatypeForValue(getSCLValue(node));\r
+            return type;\r
+        } catch (DatabaseException e) {\r
+            e.printStackTrace();\r
+        }\r
+        return null;\r
+    }\r
+\r
+    @Override\r
+    public Object getValue(String node, Binding binding) throws NodeManagerException {\r
+        checkThreadAccess();\r
+        return getSCLValue(node);\r
+    }\r
+\r
+    \r
+    private Type getType(String name) {\r
+        return realm.getConnection().getVariableType(name);\r
+    }\r
+\r
+    private Datatype getDatatypeForValue(Object value) throws DatabaseException {\r
+       if(value instanceof Double) return Datatypes.DOUBLE;\r
+       if(value instanceof Float) return Datatypes.FLOAT;\r
+       if(value instanceof Integer) return Datatypes.INTEGER;\r
+       if(value instanceof Long) return Datatypes.LONG;\r
+       if(value instanceof String) return Datatypes.STRING;\r
+       if(value instanceof Boolean) return Datatypes.BOOLEAN;\r
+       \r
+       if (value instanceof List) return null;\r
+       \r
+       if (value instanceof Object) return null;\r
+       \r
+       if (value == null) return null;\r
+        \r
+       else throw new DatabaseException("No Datatype for value " + value);\r
+    }\r
+\r
+    @Override\r
+    public void setValue(String node, Object value, Binding binding)\r
+            throws NodeManagerException {\r
+       checkThreadAccess();\r
+       valueCache.put(node, value);\r
+       realm.getConnection().setVariable(node, getType(node), value);\r
+       realm.nodeManager.valueCache.put(node, value);\r
+       refreshVariables();\r
+    }\r
+\r
+    public void setValue(String node, Type type, Object value)\r
+            throws NodeManagerException {\r
+       \r
+       checkThreadAccess();\r
+       valueCache.put(node, value);\r
+       realm.getConnection().setVariable(node, type, value);\r
+       \r
+       NodeSupport support = SCLSessionManager.getOrCreateNodeSupport(realm.getId());\r
+       support.structureCache.put(ROOT, null);\r
+       support.valueCache.put(node, null);\r
+       \r
+       realm.nodeManager.valueCache.put(node, value);\r
+       realm.nodeManager.\r
+       refreshVariables();\r
+    }\r
+    \r
+    static final Set<String> COMPONENT_CLASS = Collections.singleton(StructuralResource2.URIs.Component);\r
+            \r
+    @Override\r
+    public Set<String> getClassifications(String node) throws NodeManagerException {\r
+        checkThreadAccess();\r
+        if(node.equals(ROOT))\r
+            return COMPONENT_CLASS;\r
+        else\r
+            return Collections.emptySet();\r
+    }\r
+\r
+    private Object getSCLValue(String node) throws NodeManagerException {\r
+        Object value = valueCache.get(node);\r
+        if(value == null) {\r
+               value = realm.getConnection().getVariableValue(node);\r
+            valueCache.put(node, value);\r
+        }\r
+        return value;\r
+    }\r
+    \r
+    private void checkThreadAccess() throws NodeManagerException {\r
+        if(Thread.currentThread() != realm.getThread())\r
+            throw new NotInRealmException();\r
+    }\r
+    \r
+    @Override\r
+    public String getPropertyURI(String parent, String property) {\r
+        return "http://www.simantics.org/Modeling-1.2/CommandSession/hasValue";\r
+    }\r
+}\r