* VTT Technical Research Centre of Finland - initial API and implementation
* Semantum Oy - initial API and implementation
*******************************************************************************/
-package org.simantics.db.layer0;
+package org.simantics.simulator.toolkit;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import org.simantics.databoard.Bindings;
+import org.simantics.databoard.adapter.AdaptException;
+import org.simantics.databoard.adapter.Adapter;
+import org.simantics.databoard.adapter.AdapterConstructionException;
import org.simantics.databoard.binding.Binding;
import org.simantics.databoard.binding.VariantBinding;
-import org.simantics.databoard.binding.error.BindingConstructionException;
import org.simantics.databoard.binding.error.BindingException;
import org.simantics.databoard.binding.error.RuntimeBindingConstructionException;
import org.simantics.databoard.binding.mutable.Variant;
import org.simantics.databoard.type.Datatype;
-import org.simantics.db.exception.DatabaseException;
import org.simantics.simulator.variable.NodeManager;
import org.simantics.simulator.variable.Realm;
import org.simantics.simulator.variable.exceptions.NoSuchNodeException;
import org.simantics.simulator.variable.exceptions.NodeManagerException;
import org.simantics.simulator.variable.exceptions.NotInRealmException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
import gnu.trove.map.hash.THashMap;
import gnu.trove.procedure.TObjectProcedure;
*
* @author Antti Villberg
*/
-public abstract class StandardNodeManager<Node,Engine extends StandardEngine<Node>> implements NodeManager<Node> {
-
- final private Node root;
- final private StandardRealm<Node,Engine> realm;
+public abstract class StandardNodeManager<Node, Engine extends StandardNodeManagerSupport<Node>> implements NodeManager<Node> {
- final static Binding NO_BINDING = new VariantBinding() {
+ private static final Logger LOGGER = LoggerFactory.getLogger(StandardNodeManager.class);
+
+ private final Node root;
+ private final StandardRealm<Node,Engine> realm;
+
+ static final Binding NO_BINDING = new VariantBinding() {
@Override
public Object getContent(Object variant, Binding contentBinding) throws BindingException {
public void assertInstaceIsValid(Object obj, Set<Object> validInstances) throws BindingException {
throw new Error();
}
-
+
@Override
public int compare(Object o1, Object o2) throws org.simantics.databoard.binding.error.RuntimeBindingException {
- if(o1 == null) {
- if(o2 == null) {
- return 0;
- } else {
- return - System.identityHashCode(o2);
- }
- } else {
- if(o2 == null) {
- return System.identityHashCode(o1);
- } else {
- if(o1.equals(o2)) return 0;
- return System.identityHashCode(o1) - System.identityHashCode(o2);
- }
- }
+ if(o1 == null) {
+ if(o2 == null) {
+ return 0;
+ } else {
+ return - System.identityHashCode(o2);
+ }
+ } else {
+ if(o2 == null) {
+ return System.identityHashCode(o1);
+ } else {
+ if(o1.equals(o2)) return 0;
+ return System.identityHashCode(o1) - System.identityHashCode(o2);
+ }
+ }
}
};
-
- THashMap<Node, Object> valueCache = new THashMap<Node, Object>();
- protected THashMap<Node, THashSet<Runnable>> listeners = new THashMap<Node, THashSet<Runnable>>();
-
+
+ THashMap<Node, Variant> valueCache = new THashMap<>();
+ protected THashMap<Node, THashSet<Runnable>> listeners = new THashMap<>();
+
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;
- }
+ TObjectProcedure<Runnable> procedure = r -> {
+ r.run();
+ return true;
};
synchronized(listeners) {
- listeners.forEachValue(new TObjectProcedure<THashSet<Runnable>>() {
- @Override
- public boolean execute(THashSet<Runnable> object) {
- object.forEach(procedure);
- return true;
- }
+ listeners.forEachValue(set -> {
+ set.forEach(procedure);
+ return true;
});
}
}
};
-
- Runnable clearValueCache = new Runnable() {
- @Override
- public void run() {
- valueCache.clear();
- }
- };
-
+
+ Runnable clearValueCache = () -> valueCache.clear();
+
public StandardNodeManager(StandardRealm<Node,Engine> realm, Node root) {
- this.realm = realm;
- this.root = root;
- }
-
- @Override
- public List<String> getChildNames(Node node) throws NodeManagerException {
- List<Node> children = getChildren(node);
- ArrayList<String> names = new ArrayList<String>(children.size());
- for(Node child : children)
- names.add(getName(child));
- return names;
- }
-
- @Override
- public List<String> getPropertyNames(Node node) throws NodeManagerException {
- List<Node> properties = getProperties(node);
- ArrayList<String> names = new ArrayList<String>(properties.size());
- for(Node property : properties)
- names.add(getName(property));
- return names;
- }
-
- @Override
- public Object getValue(Node node, String propertyName, Binding binding)
- throws NodeManagerException, BindingException {
- Node property = getProperty(node, propertyName);
- if(property == null)
- throw new NoSuchNodeException("Didn't find a property " + propertyName);
- return getValue(property, binding);
- }
-
- @Override
- public void setValue(Node node, String propertyName, Object value,
- Binding binding) throws NodeManagerException, BindingException {
- Node property = getProperty(node, propertyName);
- if(property == null)
- throw new NoSuchNodeException("Didn't find a property " + propertyName);
- setValue(property, value, binding);
- }
-
- @Override
- public Variant getValue(Node node) throws NodeManagerException {
- Object value = getEngineValueOrCached(node);
- if (value instanceof Variant)
- return (Variant) value;
+ assert(realm != null);
+ assert(root != null);
+ this.realm = realm;
+ this.root = root;
+ }
+
+ @Override
+ public List<String> getChildNames(Node node) throws NodeManagerException {
+ List<Node> children = getChildren(node);
+ ArrayList<String> names = new ArrayList<>(children.size());
+ for(Node child : children)
+ names.add(getName(child));
+ return names;
+ }
+
+ @Override
+ public List<String> getPropertyNames(Node node) throws NodeManagerException {
+ List<Node> properties = getProperties(node);
+ ArrayList<String> names = new ArrayList<>(properties.size());
+ for(Node property : properties)
+ names.add(getName(property));
+ return names;
+ }
+
+ @Override
+ public Object getValue(Node node, String propertyName, Binding binding)
+ throws NodeManagerException, BindingException {
+ Node property = getProperty(node, propertyName);
+ if(property == null)
+ throw new NoSuchNodeException("Didn't find a property " + propertyName);
+ return getValue(property, binding);
+ }
+
+ @Override
+ public void setValue(Node node, String propertyName, Object value,
+ Binding binding) throws NodeManagerException, BindingException {
+ Node property = getProperty(node, propertyName);
+ if(property == null)
+ throw new NoSuchNodeException("Didn't find a property " + propertyName);
+ setValue(property, value, binding);
+ }
+
+ @Override
+ public Variant getValue(Node node, String propertyName)
+ throws NodeManagerException {
+ Node property = getProperty(node, propertyName);
+ if(property == null)
+ throw new NoSuchNodeException("Didn't find a property " + propertyName);
+ return getValue(property);
+ }
+
+ @Override
+ public Object getValue(Node node, Binding binding) throws NodeManagerException, BindingException {
try {
- Binding binding = Bindings.getBinding(value.getClass());
- return new Variant(binding, value);
- } catch (BindingConstructionException e) {
- e.printStackTrace();
- return null;
+ return getValue(node).getValue(binding);
+ } catch (AdaptException e) {
+ throw new BindingException(e);
}
- }
-
- @Override
- public Variant getValue(Node node, String propertyName)
- throws NodeManagerException {
- Node property = getProperty(node, propertyName);
- if(property == null)
- throw new NoSuchNodeException("Didn't find a property " + propertyName);
- return getValue(property);
- }
-
+ }
+
@Override
public String getPropertyURI(Node parent, Node property) {
return null;
}
-
+
@Override
public Realm getRealm() {
- return realm;
+ return realm;
}
-
+
public StandardRealm<Node, Engine> getStandardRealm() {
- return realm;
+ return realm;
}
-
+
protected String getRealmId() {
- return realm.getId();
+ return realm.getId();
}
-
+
public Node getRoot() {
- return root;
+ return root;
}
-
+
protected boolean isRoot(Node node) {
- return root.equals(node);
+ return root.equals(node);
}
@Override
synchronized(listeners) {
THashSet<Runnable> l = listeners.get(node);
if(l == null) {
- l = new THashSet<Runnable>();
+ l = new THashSet<>();
listeners.put(node, l);
}
l.add(listener);
}
}
}
-
+
public void fireNodeListeners() {
if(!fireNodeListenersScheduled.getAndSet(true))
realm.asyncExec(fireNodeListeners);
}
-
+
public void fireNodeListenersSync() {
- try {
- realm.syncExec(fireNodeListeners);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
+ try {
+ realm.syncExec(fireNodeListeners);
+ } catch (InterruptedException e) {
+ LOGGER.error("Synchronous node listener firing was interrupted.", e);
+ }
}
public void refreshVariables() {
public void refreshVariablesSync() {
try {
- realm.syncExec(clearValueCache);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
+ realm.syncExec(clearValueCache);
+ } catch (InterruptedException e) {
+ LOGGER.error("Synchronous value cache refresh was interrupted.", e);
+ }
fireNodeListenersSync();
}
-
- protected Object getEngineValueOrCached(Node node) throws NodeManagerException {
- Object value = valueCache.get(node);
- if(value == null) {
- value = realm.getEngine().getValue(node);
- valueCache.put(node, value);
+
+ protected Variant getEngineVariantOrCached(Node node) throws NodeManagerException {
+ Variant variant = valueCache.get(node);
+ if(variant == null) {
+ Object value = realm.getEngine().getEngineValue(node);
+ Binding binding = realm.getEngine().getEngineBinding(node);
+ variant = new Variant(binding, value);
+ valueCache.put(node, variant);
}
- return value;
+ return variant;
}
-
@Override
- public Object getValue(Node node, Binding binding) throws NodeManagerException {
+ public Variant getValue(Node node) throws NodeManagerException {
checkThreadAccess();
- return getEngineValueOrCached(node);
+ return getEngineVariantOrCached(node);
}
protected void checkThreadAccess() throws NodeManagerException {
if(Thread.currentThread() != realm.getThread())
throw new NotInRealmException();
}
-
- protected Datatype getDatatypeForValue(Object value) throws DatabaseException {
- Binding binding = Bindings.getBindingUnchecked(value.getClass());
- if(binding == null) return null;
- else return binding.type();
+
+ protected Datatype getDatatypeForValue(Object value) {
+ Binding binding = Bindings.getBindingUnchecked(value.getClass());
+ if(binding == null) return null;
+ else return binding.type();
}
-
+
@Override
public void setValue(Node node, Object value, Binding binding)
throws NodeManagerException {
- checkThreadAccess();
- valueCache.put(node, value);
- realm.getEngine().setValue(node, value);
- realm.getNodeManager().valueCache.put(node, value);
- refreshVariables();
+ checkThreadAccess();
+ Binding targetBinding = realm.getEngine().getEngineBinding(node);
+ if(binding.equals(targetBinding)) {
+ Variant variant = new Variant(binding, value);
+ valueCache.put(node, variant);
+ realm.getEngine().setEngineValue(node, value);
+ } else {
+ try {
+ Adapter adapter = Bindings.getAdapter(binding, targetBinding);
+ Object targetValue = adapter.adapt(value);
+ Variant variant = new Variant(targetBinding, targetValue);
+ valueCache.put(node, variant);
+ realm.getEngine().setEngineValue(node, targetValue);
+ } catch (AdapterConstructionException e) {
+ throw new NodeManagerException(e);
+ } catch (AdaptException e) {
+ throw new NodeManagerException(e);
+ }
+ }
+ refreshVariables();
}
-
+
@Override
public String getName(Node node) {
if(isRoot(node)) {
- String id = getRealmId();
- int lastSlash = id.lastIndexOf("/");
- if(lastSlash == -1) throw new IllegalStateException("Invalid realm id " + id);
- String name = id.substring(lastSlash+1);
- return name;
+ String id = getRealmId();
+ int lastSlash = id.lastIndexOf("/");
+ if(lastSlash == -1) throw new IllegalStateException("Invalid realm id " + id);
+ String name = id.substring(lastSlash+1);
+ return name;
} else {
- return realm.getEngine().getName(node);
+ return realm.getEngine().getName(node);
}
}
-
@Override
public Node getNode(String path) throws NodeManagerException {
checkThreadAccess();
throw new UnsupportedOperationException();
}
-
+
@Override
public Node getChild(Node node, String name) throws NodeManagerException {
checkThreadAccess();
- Map<String,Node> map = realm.getEngine().getChildren(node);
- return map.get(name);
+ Map<String,Node> map = realm.getEngine().getChildren(node);
+ return map.get(name);
}
@Override
public Node getProperty(Node node, String name) throws NodeManagerException {
- checkThreadAccess();
- Map<String,Node> map = realm.getEngine().getProperties(node);
- return map.get(name);
+ checkThreadAccess();
+ Map<String,Node> map = realm.getEngine().getProperties(node);
+ return map.get(name);
}
@Override
public Datatype getDatatype(Node node) throws NodeManagerException {
checkThreadAccess();
try {
- Datatype type = getDatatypeForValue(getEngineValueOrCached(node));
- return type;
- } catch (DatabaseException e) {
- e.printStackTrace();
+ Variant v = getEngineVariantOrCached(node);
+ Binding b = v.getBinding();
+ if(b == null) return null;
+ return b.type();
} catch (RuntimeBindingConstructionException e) {
// There is no datatype for all values
}
valueCache.clear();
listeners.clear();
}
-}
+
+}
\ No newline at end of file