/*******************************************************************************
* 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:
* Semantum Oy - initial API and implementation
*******************************************************************************/
package org.simantics.simulator.variable;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import org.simantics.databoard.binding.Binding;
import org.simantics.databoard.binding.error.BindingException;
import org.simantics.databoard.binding.mutable.Variant;
import org.simantics.databoard.type.Datatype;
import org.simantics.simulator.variable.exceptions.InvalidPathException;
import org.simantics.simulator.variable.exceptions.NoSuchNodeException;
import org.simantics.simulator.variable.exceptions.NoValueException;
import org.simantics.simulator.variable.exceptions.NodeManagerException;
import org.simantics.simulator.variable.exceptions.NotInRealmException;
/**
* A proxy implementation of NodeManager for debugging purposes.
*
* It prints time-stamped enter + exit/return strings when methods are entered
* and exited.
*
* TODO: Implement optional extra delays for different methods.
*
* @author Tuukka Lehtonen
*/
public class DebugNodeManager implements NodeManager {
protected NodeManager delegate;
public DebugNodeManager(NodeManager delegate) {
this.delegate = delegate;
}
// --- Do not require a realm access ---
protected long println(String msg) {
long ts = System.nanoTime();
double time = (double) ts * 1e-6;
System.out.format("[%s @%f] %s\n", delegate.getClass().getSimpleName(), time, msg);
return ts;
}
protected long println(long previousTime, String msg) {
long ts = System.nanoTime();
long dt = ts - previousTime;
double time = (double) ts * 1e-6;
double dtime = (double) dt * 1e-6;
System.out.format("[%s @%f, took %f ms] %s\n", delegate.getClass().getSimpleName(), time, dtime, msg);
return ts;
}
protected void format(String msg, Object... args) {
println(String.format(msg, args));
}
/**
* The realm of the node manager. Almost all other methods
* of this class must be called inside this realm.
*/
@Override
public Realm getRealm() {
println("getRealm");
return delegate.getRealm();
}
@Override
public String getName(Node node) {
long ts = println("enter getName(" + node + ")");
String name = delegate.getName(node);
println(ts, "return getName(" + node + ") = " + name);
return name;
}
/**
* Adds a listener to a certain node. The new listener is called as
* soon as possible (for example before simulator takes the next simulation
* step). After the first call, it is called always the node value
* or structure may have changed. This can be called outside of the realm.
*/
@Override
public void addNodeListener(Node node, Runnable listener) {
long ts = println("enter addNodeListener(" + node + ", " + listener + ")");
delegate.addNodeListener(node, listener);
println(ts, "exit addNodeListener(" + node + ", " + listener + ")");
}
/**
* Removes previously added listener. This can be called outside of
* the realm.
*/
@Override
public void removeNodeListener(Node node, Runnable listener) {
long ts = println("enter removeNodeListener(" + node + ", " + listener + ")");
delegate.removeNodeListener(node, listener);
println(ts, "exit removeNodeListener(" + node + ", " + listener + ")");
}
// --- Require a realm access ---
/**
* @return {@code null} if node cannot be found, otherwise a node with the given path
* @throws InvalidPathException if the path is not in a valid path format
* @throws NotInRealmException if not synchronized to the realm
*/
@Override
public Node getNode(String path) throws NodeManagerException {
long ts = println("enter getNode(" + path + ")");
Node node = getNode(path);
println(ts, "return getNode(" + path + ") = " + node);
return node;
}
/**
* @return {@code null} if node cannot be found, otherwise a child node with the given name
* @throws NotInRealmException if not synchronized to the realm
*/
@Override
public Node getChild(Node node, String name) throws NodeManagerException {
long ts = println("enter getChild(" + node + ", " + name + ")");
Node child = getChild(node, name);
println(ts, "return getChild(" + node + ", " + name + ") = " + child);
return child;
}
@Override
public Node getProperty(Node node, String name) throws NodeManagerException {
long ts = println("enter getProperty(" + node + ", " + name + ")");
Node property = delegate.getProperty(node, name);
println(ts, "return getProperty(" + node + ", " + name + ") = " + property);
return property;
}
@Override
public List getChildNames(Node node) throws NodeManagerException {
long ts = println("enter getChildNames(" + node + ")");
List childNames = delegate.getChildNames(node);
println(ts, "return getChildNames(" + node + ") = " + childNames);
return childNames;
}
@Override
public List getPropertyNames(Node node) throws NodeManagerException {
long ts = println("enter getPropertyNames(" + node + ")");
List propertyNames = delegate.getPropertyNames(node);
println(ts, "return getPropertyNames(" + node + ") = " + propertyNames);
return propertyNames;
}
@Override
public List getChildren(Node node) throws NodeManagerException {
long ts = println("enter getChildren(" + node + ")");
List children = delegate.getChildren(node);
println(ts, "return getChildren(" + node + ") = " + children);
return children;
}
@Override
public List getProperties(Node node) throws NodeManagerException {
long ts = println("enter getProperties(" + node + ")");
List properties = delegate.getProperties(node);
println(ts, "return getProperties(" + node + ") = " + properties);
return properties;
}
/**
* @throws NoValueException if the node has no value (and therefore no datatype)
* @throws NotInRealmException if not synchronized to the realm
*/
@Override
public Datatype getDatatype(Node node) throws NodeManagerException {
long ts = println("enter getValue(" + node + ")");
Datatype datatype = delegate.getDatatype(node);
println(ts, "return getValue(" + node + ") = " + datatype);
return datatype;
}
/**
* @throws NoValueException if the node has no value
* @throws NotInRealmException if not synchronized to the realm
*/
@Override
public Object getValue(Node node, Binding binding) throws NodeManagerException, BindingException {
long ts = println("enter getValue(" + node + ", " + binding + ")");
Object value = delegate.getValue(node, binding);
println(ts, "return getValue(" + node + ", " + binding + ") = " + value);
return value;
}
/**
* A variant of {@link #getValue(Object, Binding)} that uses
* a binding chosen by the node manager.
*/
@Override
public Variant getValue(Node node) throws NodeManagerException {
long ts = println("enter getValue(" + node + ")");
Variant value = delegate.getValue(node);
println(ts, "return getValue(" + node + ") = " + value);
return value;
}
/**
* @throws NoSuchNodeException if the property does not exist
* @throws NoValueException if the property has no value
* @throws NotInRealmException if not synchronized to the realm
* @throws BindingException if the value can not be bound to the given binding
*/
@Override
public Object getValue(Node node, String property, Binding binding) throws NodeManagerException, BindingException {
long ts = println("enter getValue(" + node + ", " + property + ", " + binding + ")");
Object value = delegate.getValue(node, property, binding);
println(ts, "return getValue(" + node + ", " + property + ", " + binding + ") = " + value);
return value;
}
/**
* A variant of {@link #getValue(Object, String, Binding)} that uses
* a binding chosen by the node manager.
*/
@Override
public Variant getValue(Node node, String property) throws NodeManagerException {
long ts = println("enter getValue(" + node + ", " + property + ")");
Variant value = delegate.getValue(node, property);
println(ts, "return getValue(" + node + ", " + property + ") = " + value);
return value;
}
/**
* @throws BindingException if the value can not be bound to the given binding
* @throws NoValueException if the property has no value that could be assigned
* @throws NotInRealmException if not synchronized to the realm
*/
@Override
public void setValue(Node node, Object value, Binding binding) throws NodeManagerException, BindingException {
long ts = println("enter setValue(" + node + ", " + value + ", " + binding + ")");
delegate.setValue(node, value, binding);
println(ts, "exit setValue(" + node + ", " + value + ", " + binding + ")");
}
/**
* @throws BindingException if the value can not be bound to the given binding
* @throws NoSuchNodeException if the property does not exist
* @throws NoValueException if the property has no value that could be assigned
* @throws NotInRealmException if not synchronized to the realm
*/
@Override
public void setValue(Node node, String property, Object value, Binding binding) throws NodeManagerException, BindingException {
long ts = println("enter setValue(" + node + ", " + property + ", " + value + ", " + binding + ")");
delegate.setValue(node, property, value, binding);
println(ts, "exit setValue(" + node + ", " + property + ", " + value + ", " + binding + ")");
}
/**
* Asks the full URI of a property node. The parent of the property is also given as a parameter.
* This is an optional method, NodeManager does not have to implement it for all nodes.
*/
@Override
public String getPropertyURI(Node parent, Node property) {
long ts = println("enter getPropertyURI(" + parent + ", " + property + ")");
String result = delegate.getPropertyURI(parent, property);
println(ts, "return getPropertyURI(" + parent + ", " + property + ") = " + result);
return result;
}
/**
* Asks for the classifications of a property node.
* This is an optional method, NodeManager does not have to implement it for all nodes.
* A default implementation should just return {@link Collections#emptySet()}.
* Classifications can be any strings, however a recommended interpretation is to return
* the URIs of the primary ontological types that this node corresponds to.
*
* @param node the node to classify
* @return classifications of the node, empty set if the node has no classifications
* @throws NodeManagerException
*/
@Override
public Set getClassifications(Node node) throws NodeManagerException {
long ts = println("enter getClassifications(" + node + ")");
Set result = delegate.getClassifications(node);
println(ts, "return getClassifications(" + node + ") = " + result);
return result;
}
}