1 package org.simantics.modeling.scl;
3 import java.util.ArrayList;
4 import java.util.Collections;
7 import java.util.concurrent.atomic.AtomicBoolean;
9 import org.simantics.databoard.Datatypes;
10 import org.simantics.databoard.binding.Binding;
11 import org.simantics.databoard.type.Datatype;
12 import org.simantics.db.exception.DatabaseException;
13 import org.simantics.db.layer0.variable.NodeSupport;
14 import org.simantics.modeling.ModelingResources;
15 import org.simantics.scl.compiler.types.Type;
16 import org.simantics.simulator.variable.Realm;
17 import org.simantics.simulator.variable.exceptions.NodeManagerException;
18 import org.simantics.simulator.variable.exceptions.NotInRealmException;
19 import org.simantics.simulator.variable.impl.AbstractNodeManager;
20 import org.simantics.structural.stubs.StructuralResource2;
22 import gnu.trove.map.hash.THashMap;
23 import gnu.trove.procedure.TObjectProcedure;
24 import gnu.trove.set.hash.THashSet;
26 public class SCLNodeManager extends AbstractNodeManager<String> {
28 public static final String ROOT = "@";
31 THashMap<String, Object> valueCache = new THashMap<String, Object>();
32 THashMap<String, THashSet<Runnable>> listeners = new THashMap<String, THashSet<Runnable>>();
34 AtomicBoolean fireNodeListenersScheduled = new AtomicBoolean(false);
35 Runnable fireNodeListeners = new Runnable() {
38 fireNodeListenersScheduled.set(false);
39 final TObjectProcedure<Runnable> procedure = new TObjectProcedure<Runnable>() {
41 public boolean execute(Runnable object) {
46 synchronized(listeners) {
47 listeners.forEachValue(new TObjectProcedure<THashSet<Runnable>>() {
49 public boolean execute(THashSet<Runnable> object) {
50 object.forEach(procedure);
58 Runnable clearValueCache = new Runnable() {
65 public SCLNodeManager(SCLRealm realm) {
71 public Realm getRealm() {
75 public String getRoot() {
80 public String getName(String node) {
81 if(ROOT.equals(node)) {
82 String id = realm.getId();
83 int lastSlash = id.lastIndexOf("/");
84 if(lastSlash == -1) throw new IllegalStateException("Invalid realm id " + id);
85 String name = id.substring(lastSlash+1);
92 public void addNodeListener(String node, Runnable listener) {
93 synchronized(listeners) {
94 THashSet<Runnable> l = listeners.get(node);
96 l = new THashSet<Runnable>();
97 listeners.put(node, l);
101 realm.asyncExec(listener);
105 public void removeNodeListener(String node, Runnable listener) {
106 synchronized(listeners) {
107 THashSet<Runnable> l = listeners.get(node);
111 listeners.remove(node);
116 public void fireNodeListeners() {
117 if(!fireNodeListenersScheduled.getAndSet(true))
118 realm.asyncExec(fireNodeListeners);
121 public void fireNodeListenersSync() {
123 realm.syncExec(fireNodeListeners);
124 } catch (InterruptedException e) {
129 public void refreshVariables() {
130 realm.asyncExec(clearValueCache);
134 public void refreshVariablesSync() {
136 realm.syncExec(clearValueCache);
137 } catch (InterruptedException e) {
140 fireNodeListenersSync();
144 public String getNode(String path) throws NodeManagerException {
146 throw new UnsupportedOperationException();
150 public String getChild(String node, String name)
151 throws NodeManagerException {
157 public String getProperty(String node, String name)
158 throws NodeManagerException {
160 if(node.equals(ROOT))
167 public List<String> getChildren(String node) throws NodeManagerException {
169 return Collections.emptyList();
173 public List<String> getProperties(String node) throws NodeManagerException {
175 if(!node.equals(ROOT))
176 return Collections.emptyList();
178 Set<String> variables = realm.getConnection().getVariables();
179 return new ArrayList<String>(variables);
184 public Datatype getDatatype(String node) throws NodeManagerException {
187 Datatype type = getDatatypeForValue(getSCLValue(node));
189 } catch (DatabaseException e) {
196 public Object getValue(String node, Binding binding) throws NodeManagerException {
198 return getSCLValue(node);
202 private Type getType(String name) {
203 return realm.getConnection().getVariableType(name);
206 private Datatype getDatatypeForValue(Object value) throws DatabaseException {
207 if(value instanceof Double) return Datatypes.DOUBLE;
208 if(value instanceof Float) return Datatypes.FLOAT;
209 if(value instanceof Integer) return Datatypes.INTEGER;
210 if(value instanceof Long) return Datatypes.LONG;
211 if(value instanceof String) return Datatypes.STRING;
212 if(value instanceof Boolean) return Datatypes.BOOLEAN;
214 if (value instanceof List) return null;
216 if (value instanceof Object) return null;
218 if (value == null) return null;
220 else throw new DatabaseException("No Datatype for value " + value);
224 public void setValue(String node, Object value, Binding binding)
225 throws NodeManagerException {
227 valueCache.put(node, value);
228 realm.getConnection().setVariable(node, getType(node), value);
229 realm.getNodeManager().valueCache.put(node, value);
233 public void setValue(String node, Type type, Object value)
234 throws NodeManagerException {
237 valueCache.put(node, value);
238 realm.getConnection().setVariable(node, type, value);
240 NodeSupport support = SCLSessionManager.getOrCreateNodeSupport(realm.getId());
241 support.structureCache.put(ROOT, null);
242 support.valueCache.put(node, null);
244 realm.getNodeManager().valueCache.put(node, value);
245 realm.getNodeManager().
249 static final Set<String> COMPONENT_CLASS = Collections.singleton(StructuralResource2.URIs.Component);
252 public Set<String> getClassifications(String node) throws NodeManagerException {
254 if(node.equals(ROOT))
255 return COMPONENT_CLASS;
257 return Collections.emptySet();
260 private Object getSCLValue(String node) throws NodeManagerException {
261 Object value = valueCache.get(node);
263 value = realm.getConnection().getVariableValue(node);
264 valueCache.put(node, value);
269 private void checkThreadAccess() throws NodeManagerException {
270 if(Thread.currentThread() != realm.getThread())
271 throw new NotInRealmException();
275 public String getPropertyURI(String parent, String property) {
276 return ModelingResources.URIs.SCLCommandSession_hasValue;
279 public void clear() {