+++ /dev/null
-/*******************************************************************************
- * 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();
- }
-}