]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardNodeManager.java
Simulator toolkit enhancements
[simantics/platform.git] / bundles / org.simantics.simulator.toolkit / src / org / simantics / simulator / toolkit / StandardNodeManager.java
similarity index 52%
rename from bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/StandardNodeManager.java
rename to bundles/org.simantics.simulator.toolkit/src/org/simantics/simulator/toolkit/StandardNodeManager.java
index c48c3f9d11983f333c78acdfb5e29d12b21011f5..87ae4f32f3b7394d1e8168c705c2584ba0ae3f8c 100644 (file)
@@ -10,7 +10,7 @@
  *     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;
@@ -19,19 +19,22 @@ import java.util.Set;
 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;
@@ -43,12 +46,14 @@ import gnu.trove.set.hash.THashSet;
  * 
  * @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 {
@@ -89,149 +94,135 @@ public abstract class StandardNodeManager<Node,Engine extends StandardEngine<Nod
         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
@@ -239,7 +230,7 @@ public abstract class StandardNodeManager<Node,Engine extends StandardEngine<Nod
         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);
@@ -258,18 +249,18 @@ public abstract class StandardNodeManager<Node,Engine extends StandardEngine<Nod
             }
         }
     }
-    
+
     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() {
@@ -279,82 +270,97 @@ public abstract class StandardNodeManager<Node,Engine extends StandardEngine<Nod
 
     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
@@ -373,10 +379,10 @@ public abstract class StandardNodeManager<Node,Engine extends StandardEngine<Nod
     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
         }
@@ -387,4 +393,5 @@ public abstract class StandardNodeManager<Node,Engine extends StandardEngine<Nod
         valueCache.clear();
         listeners.clear();
     }
-}
+
+}
\ No newline at end of file