]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/StandardNodeManager.java
Fail safe import fixes made by Antti
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / StandardNodeManager.java
index 631d3a1a39dfbe88110dc0ef52942f536ebe50e1..c48c3f9d11983f333c78acdfb5e29d12b21011f5 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2013 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *     VTT Technical Research Centre of Finland - initial API and implementation\r
- *     Semantum Oy - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.db.layer0;\r
-\r
-import java.util.ArrayList;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Set;\r
-import java.util.concurrent.atomic.AtomicBoolean;\r
-\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.databoard.binding.Binding;\r
-import org.simantics.databoard.binding.VariantBinding;\r
-import org.simantics.databoard.binding.error.BindingConstructionException;\r
-import org.simantics.databoard.binding.error.BindingException;\r
-import org.simantics.databoard.binding.error.RuntimeBindingConstructionException;\r
-import org.simantics.databoard.binding.mutable.Variant;\r
-import org.simantics.databoard.type.Datatype;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.simulator.variable.NodeManager;\r
-import org.simantics.simulator.variable.Realm;\r
-import org.simantics.simulator.variable.exceptions.NoSuchNodeException;\r
-import org.simantics.simulator.variable.exceptions.NodeManagerException;\r
-import org.simantics.simulator.variable.exceptions.NotInRealmException;\r
-\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.procedure.TObjectProcedure;\r
-import gnu.trove.set.hash.THashSet;\r
-\r
-/**\r
- * StandardNodeManager gives default implementations to some methods\r
- * of NodeManager.\r
- * \r
- * @author Antti Villberg\r
- */\r
-public abstract class StandardNodeManager<Node,Engine extends StandardEngine<Node>> implements NodeManager<Node> {\r
-       \r
-       final private Node root;\r
-       final private StandardRealm<Node,Engine> realm;\r
-\r
-    final static Binding NO_BINDING = new VariantBinding() {\r
-\r
-        @Override\r
-        public Object getContent(Object variant, Binding contentBinding) throws BindingException {\r
-            throw new Error();\r
-        }\r
-\r
-        @Override\r
-        public Object getContent(Object variant) throws BindingException {\r
-            throw new Error();\r
-        }\r
-\r
-        @Override\r
-        public Datatype getContentType(Object variant) throws BindingException {\r
-            throw new Error();\r
-        }\r
-\r
-        @Override\r
-        public Binding getContentBinding(Object variant) throws BindingException {\r
-            throw new Error();\r
-        }\r
-\r
-        @Override\r
-        public Object create(Binding contentBinding, Object content) throws BindingException {\r
-            throw new Error();\r
-        }\r
-\r
-        @Override\r
-        public void setContent(Object variant, Binding contentBinding, Object content) throws BindingException {\r
-            throw new Error();\r
-        }\r
-\r
-        @Override\r
-        public boolean isInstance(Object obj) {\r
-            return true;\r
-        }\r
-\r
-        @Override\r
-        public void assertInstaceIsValid(Object obj, Set<Object> validInstances) throws BindingException {\r
-            throw new Error();\r
-        }\r
-        \r
-        @Override\r
-        public int compare(Object o1, Object o2) throws org.simantics.databoard.binding.error.RuntimeBindingException {\r
-               if(o1 == null) {\r
-                       if(o2 == null) {\r
-                               return 0;\r
-                       } else {\r
-                               return  - System.identityHashCode(o2);\r
-                       }\r
-               } else {\r
-                       if(o2 == null) {\r
-                               return  System.identityHashCode(o1);\r
-                       } else {\r
-                               if(o1.equals(o2)) return 0;\r
-                               return System.identityHashCode(o1) - System.identityHashCode(o2);       \r
-                       }\r
-               }\r
-        }\r
-\r
-    };\r
-    \r
-    THashMap<Node, Object> valueCache = new THashMap<Node, Object>(); \r
-    protected THashMap<Node, THashSet<Runnable>> listeners = new THashMap<Node, 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 StandardNodeManager(StandardRealm<Node,Engine> realm, Node root) {\r
-       this.realm = realm;\r
-       this.root = root;\r
-       }\r
-    \r
-       @Override\r
-       public List<String> getChildNames(Node node) throws NodeManagerException {\r
-               List<Node> children = getChildren(node);\r
-               ArrayList<String> names = new ArrayList<String>(children.size());\r
-               for(Node child : children)\r
-                       names.add(getName(child));\r
-               return names;\r
-       }\r
-       \r
-       @Override\r
-       public List<String> getPropertyNames(Node node) throws NodeManagerException {\r
-               List<Node> properties = getProperties(node);\r
-               ArrayList<String> names = new ArrayList<String>(properties.size());\r
-               for(Node property : properties)\r
-                       names.add(getName(property));\r
-               return names;\r
-       }\r
-       \r
-       @Override\r
-       public Object getValue(Node node, String propertyName, Binding binding)\r
-                       throws NodeManagerException, BindingException {\r
-               Node property = getProperty(node, propertyName);\r
-               if(property == null)\r
-                       throw new NoSuchNodeException("Didn't find a property " + propertyName);\r
-               return getValue(property, binding);\r
-       }\r
-       \r
-       @Override\r
-       public void setValue(Node node, String propertyName, Object value,\r
-                       Binding binding) throws NodeManagerException, BindingException {\r
-               Node property = getProperty(node, propertyName);\r
-               if(property == null)\r
-                       throw new NoSuchNodeException("Didn't find a property " + propertyName);\r
-               setValue(property, value, binding);\r
-       }\r
-       \r
-       @Override\r
-       public Variant getValue(Node node) throws NodeManagerException {\r
-               Object value = getEngineValueOrCached(node);\r
-               if (value instanceof Variant)\r
-                   return (Variant) value;\r
-        try {\r
-            Binding binding = Bindings.getBinding(value.getClass());\r
-            return new Variant(binding, value);\r
-        } catch (BindingConstructionException e) {\r
-            e.printStackTrace();\r
-            return null;\r
-        }\r
-       }\r
-       \r
-       @Override\r
-       public Variant getValue(Node node, String propertyName)\r
-                       throws NodeManagerException {\r
-               Node property = getProperty(node, propertyName);\r
-               if(property == null)\r
-                       throw new NoSuchNodeException("Didn't find a property " + propertyName);\r
-               return getValue(property);\r
-       }\r
-       \r
-    @Override\r
-    public String getPropertyURI(Node parent, Node property) {\r
-        return null;\r
-    }\r
-    \r
-    @Override\r
-    public Realm getRealm() {\r
-       return realm;\r
-    }\r
-    \r
-    public StandardRealm<Node, Engine> getStandardRealm() {\r
-       return realm;\r
-    }\r
-    \r
-    protected String getRealmId() {\r
-       return realm.id;\r
-    }\r
-    \r
-    public Node getRoot() {\r
-       return root;\r
-    }\r
-    \r
-    protected boolean isRoot(Node node) {\r
-       return root.equals(node);\r
-    }\r
-\r
-    @Override\r
-    public void addNodeListener(Node 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
-        getRealm().asyncExec(listener);\r
-    }\r
-\r
-    @Override\r
-    public void removeNodeListener(Node 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
-    protected Object getEngineValueOrCached(Node node) throws NodeManagerException {\r
-        Object value = valueCache.get(node);\r
-        if(value == null) {\r
-               value = realm.getEngine().getValue(node);\r
-            valueCache.put(node, value);\r
-        }\r
-        return value;\r
-    }\r
-    \r
-\r
-    @Override\r
-    public Object getValue(Node node, Binding binding) throws NodeManagerException {\r
-        checkThreadAccess();\r
-        return getEngineValueOrCached(node);\r
-    }\r
-\r
-    protected void checkThreadAccess() throws NodeManagerException {\r
-        if(Thread.currentThread() != realm.getThread())\r
-            throw new NotInRealmException();\r
-    }\r
-    \r
-    protected Datatype getDatatypeForValue(Object value) throws DatabaseException {\r
-       Binding binding = Bindings.getBindingUnchecked(value.getClass());\r
-       if(binding == null) return null;\r
-       else return binding.type();\r
-    }\r
-    \r
-    @Override\r
-    public void setValue(Node node, Object value, Binding binding)\r
-            throws NodeManagerException {\r
-       checkThreadAccess();\r
-       valueCache.put(node, value);\r
-       realm.getEngine().setValue(node, value);\r
-       realm.nodeManager.valueCache.put(node, value);\r
-       refreshVariables();\r
-    }\r
-    \r
-    @Override\r
-    public String getName(Node node) {\r
-        if(isRoot(node)) {\r
-               String id = getRealmId();\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 realm.getEngine().getName(node);\r
-        }\r
-    }\r
-    \r
-\r
-    @Override\r
-    public Node getNode(String path) throws NodeManagerException {\r
-        checkThreadAccess();\r
-        throw new UnsupportedOperationException();\r
-    }\r
-    \r
-    @Override\r
-    public Node getChild(Node node, String name) throws NodeManagerException {\r
-        checkThreadAccess();\r
-       Map<String,Node> map = realm.getEngine().getChildren(node);\r
-       return map.get(name);\r
-    }\r
-\r
-    @Override\r
-    public Node getProperty(Node node, String name) throws NodeManagerException {\r
-       checkThreadAccess();\r
-       Map<String,Node> map = realm.getEngine().getProperties(node);\r
-       return map.get(name);\r
-    }\r
-\r
-    @Override\r
-    public List<Node> getChildren(Node node) throws NodeManagerException {\r
-        checkThreadAccess();\r
-        return new ArrayList<Node>(realm.getEngine().getChildren(node).values());\r
-    }\r
-\r
-    @Override\r
-    public List<Node> getProperties(Node node) throws NodeManagerException {\r
-        checkThreadAccess();\r
-        return new ArrayList<Node>(realm.getEngine().getProperties(node).values());\r
-    }\r
-\r
-    @Override\r
-    public Datatype getDatatype(Node node) throws NodeManagerException {\r
-        checkThreadAccess();\r
-        try {\r
-            Datatype type = getDatatypeForValue(getEngineValueOrCached(node));\r
-            return type;\r
-        } catch (DatabaseException e) {\r
-            e.printStackTrace();\r
-        } catch (RuntimeBindingConstructionException e) {\r
-            // There is no datatype for all values\r
-        }\r
-        return null;\r
-    }\r
-    \r
-}\r
+/*******************************************************************************
+ * Copyright (c) 2013 Association for Decentralized Information Management
+ * in Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     VTT Technical Research Centre of Finland - initial API and implementation
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.db.layer0;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.simantics.databoard.Bindings;
+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 gnu.trove.map.hash.THashMap;
+import gnu.trove.procedure.TObjectProcedure;
+import gnu.trove.set.hash.THashSet;
+
+/**
+ * StandardNodeManager gives default implementations to some methods
+ * of NodeManager.
+ * 
+ * @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;
+
+    final static Binding NO_BINDING = new VariantBinding() {
+
+        @Override
+        public Object getContent(Object variant, Binding contentBinding) throws BindingException {
+            throw new Error();
+        }
+
+        @Override
+        public Object getContent(Object variant) throws BindingException {
+            throw new Error();
+        }
+
+        @Override
+        public Datatype getContentType(Object variant) throws BindingException {
+            throw new Error();
+        }
+
+        @Override
+        public Binding getContentBinding(Object variant) throws BindingException {
+            throw new Error();
+        }
+
+        @Override
+        public Object create(Binding contentBinding, Object content) throws BindingException {
+            throw new Error();
+        }
+
+        @Override
+        public void setContent(Object variant, Binding contentBinding, Object content) throws BindingException {
+            throw new Error();
+        }
+
+        @Override
+        public boolean isInstance(Object obj) {
+            return true;
+        }
+
+        @Override
+        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);       
+                       }
+               }
+        }
+
+    };
+    
+    THashMap<Node, Object> valueCache = new THashMap<Node, Object>(); 
+    protected THashMap<Node, THashSet<Runnable>> listeners = new THashMap<Node, 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 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;
+        try {
+            Binding binding = Bindings.getBinding(value.getClass());
+            return new Variant(binding, value);
+        } catch (BindingConstructionException e) {
+            e.printStackTrace();
+            return null;
+        }
+       }
+       
+       @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;
+    }
+    
+    public StandardRealm<Node, Engine> getStandardRealm() {
+       return realm;
+    }
+    
+    protected String getRealmId() {
+       return realm.getId();
+    }
+    
+    public Node getRoot() {
+       return root;
+    }
+    
+    protected boolean isRoot(Node node) {
+       return root.equals(node);
+    }
+
+    @Override
+    public void addNodeListener(Node 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);
+        }
+        getRealm().asyncExec(listener);
+    }
+
+    @Override
+    public void removeNodeListener(Node 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();
+    }
+    
+    protected Object getEngineValueOrCached(Node node) throws NodeManagerException {
+        Object value = valueCache.get(node);
+        if(value == null) {
+               value = realm.getEngine().getValue(node);
+            valueCache.put(node, value);
+        }
+        return value;
+    }
+    
+
+    @Override
+    public Object getValue(Node node, Binding binding) throws NodeManagerException {
+        checkThreadAccess();
+        return getEngineValueOrCached(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();
+    }
+    
+    @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();
+    }
+    
+    @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;
+        } else {
+               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);
+    }
+
+    @Override
+    public Node getProperty(Node node, String name) throws NodeManagerException {
+       checkThreadAccess();
+       Map<String,Node> map = realm.getEngine().getProperties(node);
+       return map.get(name);
+    }
+
+    @Override
+    public List<Node> getChildren(Node node) throws NodeManagerException {
+        checkThreadAccess();
+        return new ArrayList<Node>(realm.getEngine().getChildren(node).values());
+    }
+
+    @Override
+    public List<Node> getProperties(Node node) throws NodeManagerException {
+        checkThreadAccess();
+        return new ArrayList<Node>(realm.getEngine().getProperties(node).values());
+    }
+
+    @Override
+    public Datatype getDatatype(Node node) throws NodeManagerException {
+        checkThreadAccess();
+        try {
+            Datatype type = getDatatypeForValue(getEngineValueOrCached(node));
+            return type;
+        } catch (DatabaseException e) {
+            e.printStackTrace();
+        } catch (RuntimeBindingConstructionException e) {
+            // There is no datatype for all values
+        }
+        return null;
+    }
+
+    public void clear() {
+        valueCache.clear();
+        listeners.clear();
+    }
+}