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