X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.scenegraph.loader%2Fsrc%2Forg%2Fsimantics%2Fscenegraph%2Floader%2FScenegraphLoaderUtils.java;h=e40773002ebfb68fb5bab610b5896c1e0f699001;hb=7a7ad0a2319ce70a184e099adad8a69c23562bd9;hp=eddc08347f37caf11f2e112645e0482fe91f3a5c;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.scenegraph.loader/src/org/simantics/scenegraph/loader/ScenegraphLoaderUtils.java b/bundles/org.simantics.scenegraph.loader/src/org/simantics/scenegraph/loader/ScenegraphLoaderUtils.java index eddc08347..e40773002 100644 --- a/bundles/org.simantics.scenegraph.loader/src/org/simantics/scenegraph/loader/ScenegraphLoaderUtils.java +++ b/bundles/org.simantics.scenegraph.loader/src/org/simantics/scenegraph/loader/ScenegraphLoaderUtils.java @@ -1,557 +1,558 @@ -package org.simantics.scenegraph.loader; - -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.Map; - -import org.simantics.Simantics; -import org.simantics.databoard.Bindings; -import org.simantics.databoard.binding.Binding; -import org.simantics.db.ReadGraph; -import org.simantics.db.RequestProcessor; -import org.simantics.db.Resource; -import org.simantics.db.common.NamedResource; -import org.simantics.db.common.procedure.adapter.ListenerAdapter; -import org.simantics.db.common.request.BinaryRead; -import org.simantics.db.common.request.ParametrizedPrimitiveRead; -import org.simantics.db.common.request.ResourceRead; -import org.simantics.db.common.request.UnaryRead; -import org.simantics.db.exception.AssumptionException; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.exception.VariableException; -import org.simantics.db.layer0.request.VariableName; -import org.simantics.db.layer0.request.VariableURI; -import org.simantics.db.layer0.variable.Variable; -import org.simantics.db.layer0.variable.VariableBuilder; -import org.simantics.db.layer0.variable.Variables; -import org.simantics.db.procedure.Listener; -import org.simantics.layer0.Layer0; -import org.simantics.scenegraph.INode; -import org.simantics.scenegraph.LoaderNode; -import org.simantics.scenegraph.ParentNode; -import org.simantics.scenegraph.ontology.ScenegraphResources; -import org.simantics.scenegraph.utils.NodeUtil; -import org.simantics.scl.runtime.function.Function1; -import org.simantics.scl.runtime.function.FunctionImpl2; -import org.simantics.utils.DataContainer; -import org.simantics.utils.datastructures.Pair; -import org.simantics.utils.threads.IThreadWorkQueue; -import org.simantics.utils.threads.ThreadUtils; - -public class ScenegraphLoaderUtils { - - static Map, Collection>> externalMap = new HashMap, Collection>>(); - static Map, Object> externalValueMap = new HashMap, Object>(); - - final public static class ScenegraphPropertyReference { - - static class ExternalRead extends ParametrizedPrimitiveRead, T> { - - public ExternalRead(Variable base, String path) { - super(Pair.make(base, path)); - } - - @Override - public void register(ReadGraph graph, final Listener procedure) { - Object value = externalValueMap.get(parameter); - procedure.execute((T)value); - Collection> listeners = externalMap.get(parameter); - if(listeners == null) { - listeners = new ArrayList>(); - externalMap.put(parameter, listeners); - } - listeners.add(new ListenerAdapter() { - - @Override - public void execute(Object result) { - procedure.execute((T)result); - } - - }); - } - - @Override - public void unregistered() { - externalMap.remove(parameter); - } - - } - - Variable baseVariable; - IThreadWorkQueue thread; - INode root; - String reference; - T value = null; - - public ScenegraphPropertyReference(IThreadWorkQueue thread, INode root, String reference, Variable baseVariable) { - assert(root != null); - this.thread = thread; - this.root = root; - this.reference = reference; - this.baseVariable = baseVariable; - } - - public T getExternalValue(RequestProcessor processor) throws DatabaseException { - return processor.sync(new ExternalRead(baseVariable, reference)); - } - - public T getValue() { - - final Pair ref = NodeUtil.browsePossibleReference(root, reference); - - final DataContainer result = new DataContainer(); - - ThreadUtils.syncExec(thread, new Runnable() { - - @Override - public void run() { - T value = ScenegraphLoaderUtils.getNodeProperty((LoaderNode)ref.first, ref.second); - result.set(value); - } - - }); - - return result.get(); - - } - - public void setValue(final T value) { - - final Pair ref = NodeUtil.browsePossibleReference(root, reference); - if(ref != null) { - ThreadUtils.asyncExec(thread, new Runnable() { - - @Override - public void run() { - Function1 function = ScenegraphLoaderUtils.getPropertyFunction((LoaderNode)ref.first, ref.second); - if(function != null) { - function.apply(value); - } else { - new Exception("no function for ref " + ref).printStackTrace(); - } - } - - }); - } else { - //new Exception("no reference for " + root + " " + reference).printStackTrace(); - } - - - } - - } - public static Collection computeChildren(ReadGraph graph, Variable configuration) throws DatabaseException { - ScenegraphResources SG = ScenegraphResources.getInstance(graph); - Resource represents = configuration.getRepresents(graph); - Collection children = graph.getPossibleRelatedValue2(represents, SG.Node_children, configuration); - if(children == null) return Collections.emptyList(); - ArrayList result = new ArrayList(); - for(Resource item : children) { - VariableBuilder variableBuilder = graph.adapt(item, VariableBuilder.class); - Variable child = variableBuilder.buildChild(graph, configuration, null, item); - if(child != null) result.add(child); - } - return result; - } - - public static Collection getChildren(RequestProcessor processor, Variable configuration) throws DatabaseException { - - return processor.sync(new UnaryRead>(configuration) { - - @Override - public Collection perform(ReadGraph graph) throws DatabaseException { - return parameter.browseChildren(graph); - } - - }); - - } - - public static Collection getChildren(Resource configuration) throws DatabaseException { - - return Simantics.getSession().sync(new ResourceRead>(configuration) { - - @Override - public Collection perform(ReadGraph graph) throws DatabaseException { - return computeChildren(graph, Variables.getVariable(graph, resource)); - } - - }); - - } - - public static Collection getProperties(RequestProcessor processor, Resource configuration) throws DatabaseException { - - return processor.sync(new ResourceRead>(configuration) { - - @Override - public Collection perform(ReadGraph graph) throws DatabaseException { - Layer0 L0 = Layer0.getInstance(graph); - ScenegraphResources SG = ScenegraphResources.getInstance(graph); - ArrayList result = new ArrayList(); - for(Resource predicate : graph.getPredicates(resource)) { - if(graph.isSubrelationOf(predicate, SG.Node_HasProperty)) { - String name = graph.getRelatedValue(predicate, L0.HasName, Bindings.STRING); - result.add(new NamedResource(name, predicate)); - } - } - return result; - } - - }); - - } - - /** - * A custom exception for indicating that the a (runtime) resource has been - * disposed of (i.e. its statements have been removed). Optimized by - * nullifying {@link #fillInStackTrace()} since this is only used customly - * by - * {@link ScenegraphLoaderUtils#listen(RequestProcessor, Variable, String, Function1)} - * to dispose of the DB listeners it creates. - * - * @author Tuukka Lehtonen - */ - static class DisposedRuntimeException extends AssumptionException { - - private static final long serialVersionUID = 5213099691410928157L; - - public DisposedRuntimeException(String message) { - super(message); - } - - @Override - public synchronized Throwable fillInStackTrace() { - return this; - } - - } - - public static void listen(RequestProcessor processor, final ScenegraphLoaderProcess process, final Variable context, final String property, final Function1 function) throws DatabaseException { - - try { - - processor.syncRequest(new BinaryRead (context, property) { - - @SuppressWarnings("unchecked") - @Override - public T perform(ReadGraph graph) throws DatabaseException { - // FIXME: this must throw a dedicated exception in the case where the runtime variable has been deleted which implies this listener should be disposed of - SceneGraphContext vc = getContext(graph, context); - if (vc == null) - throw new DisposedRuntimeException("No scene graph context"); - Resource runtime = vc.getRuntime(); - if (runtime == null || !graph.hasStatement(runtime)) - throw new DisposedRuntimeException("Scene graph runtime disposed"); - - return (T)parameter.getPropertyValue(graph, parameter2); - } - - }, new Listener() { - - private boolean disposed = false; - - @Override - public void exception(Throwable t) { - if (t instanceof DisposedRuntimeException) { - //System.out.println("ScenegraphLoaderUtils(" + this + ").listen: runtime disposed"); - disposed = true; - } else { - //t.printStackTrace(); - } - } - - @Override - public void execute(T result) { - if (!disposed) - disposed = function.apply(result); - } - - @Override - public boolean isDisposed() { - return process.isDisposed() | disposed; - } - - @Override - public String toString() { - return "Scenegraph Property Listener for " + process; - } - - }); - - } catch (DatabaseException e) { - - } - - } - - public static Resource getRuntime(ReadGraph graph, Variable context) throws DatabaseException { - SceneGraphContext vc = getContext(graph, context); - if(vc != null) return vc.getRuntime(); - Variable parent = context.getParent(graph); - if(parent == null) throw new DatabaseException("Runtime resource was not found from context Variable."); - return getRuntime(graph, parent); - } - - public static SceneGraphContext getContext(ReadGraph graph, Variable context) throws DatabaseException { - SceneGraphContext vc = context.adaptPossible(graph, SceneGraphContext.class); - if(vc != null) return vc; - else { - Variable parent = context.getParent(graph); - if(parent != null) return getContext(graph, parent); - else return null; - } - } - - public static Variable getRuntimeVariable(ReadGraph graph, Variable context) throws DatabaseException { - SceneGraphContext vc = getContext(graph, context); - if(vc == null) return null; - else return vc.getRuntimeVariable(); - } - - public static Variable getBaseVariable(ReadGraph graph, Variable context) throws DatabaseException { - - Variable parent = context.getParent(graph); - if(parent == null) return null; - if(context instanceof ScenegraphVariable && !(parent instanceof ScenegraphVariable)) return context; - else return getBaseVariable(graph, parent); - - } - - static class ScenegraphReference extends UnaryRead> { - - public ScenegraphReference(Variable var) { - super(var); - assert(var != null); - } - - @Override - public Pair perform(ReadGraph graph) throws DatabaseException { - Variable base = getBaseVariable(graph, parameter); - return Pair.make(base, Variables.getRVI(graph, base, parameter)); - } - - } - - public static INode create(RequestProcessor processor, ScenegraphLoaderProcess process, ParentNode parent, Resource configuration, final Variable context, Class clazz) throws DatabaseException { - - final String name = processor.sync(new VariableName(context)); - - final String uri = processor.sync(new VariableURI(context)); - - LoaderNode node = (LoaderNode)parent.addNode(name, clazz); - - final Pair reference = processor.sync(new ScenegraphReference(context)); - - node.setPropertyCallback(new FunctionImpl2() { - - @Override - public Boolean apply(String property, Object value) { - Pair key = Pair.make(reference.first, reference.second + "#" + property); - externalValueMap.put(key, value); - Collection> listeners = externalMap.get(key); - if(listeners != null) { - for(Listener listener : listeners) listener.execute(value); - } - return true; - } - - }); - - for(NamedResource property : ScenegraphLoaderUtils.getProperties(processor, configuration)) { - try { - Function1 func = node.getPropertyFunction(property.getName()); - if (func != null) - ScenegraphLoaderUtils.listen(processor, process, context, property.getName(), func); - //else - // System.out.println("NO FUNCTION FOR PROPERTY: " + property.getName() + " (" + node + ")"); - } catch (Exception e) { - e.printStackTrace(); - } - } - - return node; - - } - - public static Variable getVariableSelection(ReadGraph graph, Variable context) throws DatabaseException { - - Variable runtimeVariable = getRuntimeVariable(graph, context); - if (runtimeVariable == null) - throw new VariableException("no runtime variable for context " + context.getURI(graph)); - return runtimeVariable.getPropertyValue(graph, "variable"); - - } - - public static Variable getPossibleVariableSelection(ReadGraph graph, Variable context) throws DatabaseException { - Variable runtimeVariable = getRuntimeVariable(graph, context); - return runtimeVariable == null ? null : (Variable) runtimeVariable.getPossiblePropertyValue(graph, "variable"); - } - - public static Resource getResourceSelection(ReadGraph graph, Variable context) throws DatabaseException { - - Variable runtimeVariable = getRuntimeVariable(graph, context); - if (runtimeVariable == null) - throw new VariableException("no runtime variable for context " + context.getURI(graph)); - Resource sel = runtimeVariable.getPropertyValue(graph, "resource"); - return sel; - - } - - public static Resource getPossibleResourceSelection(ReadGraph graph, Variable context) throws DatabaseException { - - Variable runtimeVariable = getRuntimeVariable(graph, context); - return runtimeVariable == null ? null : (Resource) runtimeVariable.getPossiblePropertyValue(graph, "resource"); - - } - - public static INode getNode(ReadGraph graph, Variable location) throws DatabaseException { - Variable runtime = getRuntimeVariable(graph, location); - INode root = runtime.adapt(graph, INode.class); - Variable base = getBaseVariable(graph, location); - String rvi = Variables.getRVI(graph, base, location); - return NodeUtil.browsePossible(root, rvi); - } - -// public static ScenegraphPropertyReference getPropertyReference(final IThreadWorkQueue thread, final Variable context, final String path) throws DatabaseException { -// return Simantics.getSession().sync(new UniqueRead>() { -// -// @Override -// public ScenegraphPropertyReference perform(ReadGraph graph) throws DatabaseException { -// return getRelativePropertyReference(thread, graph, context, path); -// } -// -// }); -// } - -// public static T getRelativeProperty(final IThreadWorkQueue thread, ReadGraph graph, Variable context, String path) throws DatabaseException { -// ScenegraphPropertyReference ref = getRelativePropertyReference(thread, graph, context, path); -// return ref.getExternalValue(graph); -// } - - public static T getProperty(final IThreadWorkQueue thread, INode _root, String reference) { - - INode root = ((ParentNode)_root).getNodes().iterator().next(); - - final Pair ref = NodeUtil.browsePossibleReference(root, reference); - - final DataContainer result = new DataContainer(); - - ThreadUtils.syncExec(thread, new Runnable() { - - @Override - public void run() { - T value = ScenegraphLoaderUtils.getNodeProperty((LoaderNode)ref.first, ref.second); - result.set(value); - } - - }); - - return result.get(); - - } - - public static ScenegraphPropertyReference getRelativePropertyReference(final IThreadWorkQueue thread, ReadGraph graph, Variable context, String path) throws DatabaseException { - - Variable runtime = getRuntimeVariable(graph, context); - INode root = runtime.adapt(graph, INode.class); - Variable base = getBaseVariable(graph, context); - INode baseNode = NodeUtil.findChildById((ParentNode)root, base.getName(graph)); - String contextRVI = Variables.getRVI(graph, base, context); - String rvi = Variables.getRVI(contextRVI, path); - return new ScenegraphPropertyReference(thread, baseNode, rvi, base); - - } - - public static ScenegraphPropertyReference getPropertyReference(final IThreadWorkQueue thread, ReadGraph graph, Variable context, String path) throws DatabaseException { - - Variable runtime = getRuntimeVariable(graph, context); - INode root = runtime.adapt(graph, INode.class); - Variable base = getBaseVariable(graph, context); - return new ScenegraphPropertyReference(thread, root, path, base); - - } - - public static Method getSynchronizeMethod(INode node, String propertyName) { - try { - String methodName = "synchronize" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1); - for(Method m : node.getClass().getMethods()) { - if(m.getName().equals(methodName)) return m; - } - return null; - } catch (SecurityException e) { - e.printStackTrace(); - } - return null; - } - - public static Method getReadMethod(INode node, String propertyName) { - try { - String methodName = "read" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1); - return node.getClass().getMethod(methodName); - } catch (SecurityException e) { - e.printStackTrace(); - } catch (NoSuchMethodException e) { - e.printStackTrace(); - } - return null; - } - - public static Field getPropertyField(INode node, String propertyName) { - try { - return node.getClass().getField(propertyName); - } catch (SecurityException e) { - e.printStackTrace(); - } catch (NoSuchFieldException e) { - System.err.println("node:" + node); - e.printStackTrace(); - } - return null; - } - - public static Class getPropertyType(Field field) { - return field.getType(); - } - - public static Class getArgumentType(Method method) { - return (Class)method.getGenericParameterTypes()[0]; - } - - public static Class getReturnType(Method method) { - return method.getReturnType(); - } - - public static Binding getPropertyBinding(Class clazz) { - try { - return Bindings.getBindingUnchecked(clazz); - } catch (Throwable t) { - return null; - } - } - - public static Binding getGenericPropertyBinding(Binding binding) { - try { - return Bindings.getBinding(binding.type()); - } catch (Throwable t) { - return null; - } - } - - public static Function1 getPropertyFunction(final LoaderNode node, final String propertyName) { - return node.getPropertyFunction(propertyName); - } - - public static T getNodeProperty(final LoaderNode node, final String propertyName) { - return node.getProperty(propertyName); - } - - public static String getPath(ReadGraph graph, Variable context) throws DatabaseException { - Variable base = getBaseVariable(graph, context); - return Variables.getRVI(graph, base, context); - } - -} +package org.simantics.scenegraph.loader; + +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +import org.simantics.Simantics; +import org.simantics.databoard.Bindings; +import org.simantics.databoard.binding.Binding; +import org.simantics.db.ReadGraph; +import org.simantics.db.RequestProcessor; +import org.simantics.db.Resource; +import org.simantics.db.common.NamedResource; +import org.simantics.db.common.procedure.adapter.ProcedureAdapter; +import org.simantics.db.common.request.BinaryRead; +import org.simantics.db.common.request.ParametrizedPrimitiveRead; +import org.simantics.db.common.request.ResourceRead; +import org.simantics.db.common.request.UnaryRead; +import org.simantics.db.exception.AssumptionException; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.exception.VariableException; +import org.simantics.db.layer0.request.VariableName; +import org.simantics.db.layer0.request.VariableURI; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.layer0.variable.VariableBuilder; +import org.simantics.db.layer0.variable.Variables; +import org.simantics.db.procedure.Listener; +import org.simantics.db.procedure.Procedure; +import org.simantics.layer0.Layer0; +import org.simantics.scenegraph.INode; +import org.simantics.scenegraph.LoaderNode; +import org.simantics.scenegraph.ParentNode; +import org.simantics.scenegraph.ontology.ScenegraphResources; +import org.simantics.scenegraph.utils.NodeUtil; +import org.simantics.scl.runtime.function.Function1; +import org.simantics.scl.runtime.function.FunctionImpl2; +import org.simantics.utils.DataContainer; +import org.simantics.utils.datastructures.Pair; +import org.simantics.utils.threads.IThreadWorkQueue; +import org.simantics.utils.threads.ThreadUtils; + +public class ScenegraphLoaderUtils { + + static Map, Collection>> externalMap = new HashMap, Collection>>(); + static Map, Object> externalValueMap = new HashMap, Object>(); + + final public static class ScenegraphPropertyReference { + + static class ExternalRead extends ParametrizedPrimitiveRead, T> { + + public ExternalRead(Variable base, String path) { + super(Pair.make(base, path)); + } + + @Override + public void register(ReadGraph graph, final Listener procedure) { + Object value = externalValueMap.get(parameter); + procedure.execute((T)value); + Collection> listeners = externalMap.get(parameter); + if(listeners == null) { + listeners = new ArrayList>(); + externalMap.put(parameter, listeners); + } + listeners.add(new ProcedureAdapter() { + + @Override + public void execute(Object result) { + procedure.execute((T)result); + } + + }); + } + + @Override + public void unregistered() { + externalMap.remove(parameter); + } + + } + + Variable baseVariable; + IThreadWorkQueue thread; + INode root; + String reference; + T value = null; + + public ScenegraphPropertyReference(IThreadWorkQueue thread, INode root, String reference, Variable baseVariable) { + assert(root != null); + this.thread = thread; + this.root = root; + this.reference = reference; + this.baseVariable = baseVariable; + } + + public T getExternalValue(RequestProcessor processor) throws DatabaseException { + return processor.sync(new ExternalRead(baseVariable, reference)); + } + + public T getValue() { + + final Pair ref = NodeUtil.browsePossibleReference(root, reference); + + final DataContainer result = new DataContainer(); + + ThreadUtils.syncExec(thread, new Runnable() { + + @Override + public void run() { + T value = ScenegraphLoaderUtils.getNodeProperty((LoaderNode)ref.first, ref.second); + result.set(value); + } + + }); + + return result.get(); + + } + + public void setValue(final T value) { + + final Pair ref = NodeUtil.browsePossibleReference(root, reference); + if(ref != null) { + ThreadUtils.asyncExec(thread, new Runnable() { + + @Override + public void run() { + Function1 function = ScenegraphLoaderUtils.getPropertyFunction((LoaderNode)ref.first, ref.second); + if(function != null) { + function.apply(value); + } else { + new Exception("no function for ref " + ref).printStackTrace(); + } + } + + }); + } else { + //new Exception("no reference for " + root + " " + reference).printStackTrace(); + } + + + } + + } + public static Collection computeChildren(ReadGraph graph, Variable configuration) throws DatabaseException { + ScenegraphResources SG = ScenegraphResources.getInstance(graph); + Resource represents = configuration.getRepresents(graph); + Collection children = graph.getPossibleRelatedValue2(represents, SG.Node_children, configuration); + if(children == null) return Collections.emptyList(); + ArrayList result = new ArrayList(); + for(Resource item : children) { + VariableBuilder variableBuilder = graph.adapt(item, VariableBuilder.class); + Variable child = variableBuilder.buildChild(graph, configuration, null, item); + if(child != null) result.add(child); + } + return result; + } + + public static Collection getChildren(RequestProcessor processor, Variable configuration) throws DatabaseException { + + return processor.sync(new UnaryRead>(configuration) { + + @Override + public Collection perform(ReadGraph graph) throws DatabaseException { + return parameter.browseChildren(graph); + } + + }); + + } + + public static Collection getChildren(Resource configuration) throws DatabaseException { + + return Simantics.getSession().sync(new ResourceRead>(configuration) { + + @Override + public Collection perform(ReadGraph graph) throws DatabaseException { + return computeChildren(graph, Variables.getVariable(graph, resource)); + } + + }); + + } + + public static Collection getProperties(RequestProcessor processor, Resource configuration) throws DatabaseException { + + return processor.sync(new ResourceRead>(configuration) { + + @Override + public Collection perform(ReadGraph graph) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + ScenegraphResources SG = ScenegraphResources.getInstance(graph); + ArrayList result = new ArrayList(); + for(Resource predicate : graph.getPredicates(resource)) { + if(graph.isSubrelationOf(predicate, SG.Node_HasProperty)) { + String name = graph.getRelatedValue(predicate, L0.HasName, Bindings.STRING); + result.add(new NamedResource(name, predicate)); + } + } + return result; + } + + }); + + } + + /** + * A custom exception for indicating that the a (runtime) resource has been + * disposed of (i.e. its statements have been removed). Optimized by + * nullifying {@link #fillInStackTrace()} since this is only used customly + * by + * {@link ScenegraphLoaderUtils#listen(RequestProcessor, Variable, String, Function1)} + * to dispose of the DB listeners it creates. + * + * @author Tuukka Lehtonen + */ + static class DisposedRuntimeException extends AssumptionException { + + private static final long serialVersionUID = 5213099691410928157L; + + public DisposedRuntimeException(String message) { + super(message); + } + + @Override + public synchronized Throwable fillInStackTrace() { + return this; + } + + } + + public static void listen(RequestProcessor processor, final ScenegraphLoaderProcess process, final Variable context, final String property, final Function1 function) throws DatabaseException { + + try { + + processor.syncRequest(new BinaryRead (context, property) { + + @SuppressWarnings("unchecked") + @Override + public T perform(ReadGraph graph) throws DatabaseException { + // FIXME: this must throw a dedicated exception in the case where the runtime variable has been deleted which implies this listener should be disposed of + SceneGraphContext vc = getContext(graph, context); + if (vc == null) + throw new DisposedRuntimeException("No scene graph context"); + Resource runtime = vc.getRuntime(); + if (runtime == null || !graph.hasStatement(runtime)) + throw new DisposedRuntimeException("Scene graph runtime disposed"); + + return (T)parameter.getPropertyValue(graph, parameter2); + } + + }, new Listener() { + + private boolean disposed = false; + + @Override + public void exception(Throwable t) { + if (t instanceof DisposedRuntimeException) { + //System.out.println("ScenegraphLoaderUtils(" + this + ").listen: runtime disposed"); + disposed = true; + } else { + //t.printStackTrace(); + } + } + + @Override + public void execute(T result) { + if (!disposed) + disposed = function.apply(result); + } + + @Override + public boolean isDisposed() { + return process.isDisposed() | disposed; + } + + @Override + public String toString() { + return "Scenegraph Property Listener for " + process; + } + + }); + + } catch (DatabaseException e) { + + } + + } + + public static Resource getRuntime(ReadGraph graph, Variable context) throws DatabaseException { + SceneGraphContext vc = getContext(graph, context); + if(vc != null) return vc.getRuntime(); + Variable parent = context.getParent(graph); + if(parent == null) throw new DatabaseException("Runtime resource was not found from context Variable."); + return getRuntime(graph, parent); + } + + public static SceneGraphContext getContext(ReadGraph graph, Variable context) throws DatabaseException { + SceneGraphContext vc = context.adaptPossible(graph, SceneGraphContext.class); + if(vc != null) return vc; + else { + Variable parent = context.getParent(graph); + if(parent != null) return getContext(graph, parent); + else return null; + } + } + + public static Variable getRuntimeVariable(ReadGraph graph, Variable context) throws DatabaseException { + SceneGraphContext vc = getContext(graph, context); + if(vc == null) return null; + else return vc.getRuntimeVariable(); + } + + public static Variable getBaseVariable(ReadGraph graph, Variable context) throws DatabaseException { + + Variable parent = context.getParent(graph); + if(parent == null) return null; + if(context instanceof ScenegraphVariable && !(parent instanceof ScenegraphVariable)) return context; + else return getBaseVariable(graph, parent); + + } + + static class ScenegraphReference extends UnaryRead> { + + public ScenegraphReference(Variable var) { + super(var); + assert(var != null); + } + + @Override + public Pair perform(ReadGraph graph) throws DatabaseException { + Variable base = getBaseVariable(graph, parameter); + return Pair.make(base, Variables.getRVI(graph, base, parameter)); + } + + } + + public static INode create(RequestProcessor processor, ScenegraphLoaderProcess process, ParentNode parent, Resource configuration, final Variable context, Class clazz) throws DatabaseException { + + final String name = processor.sync(new VariableName(context)); + + final String uri = processor.sync(new VariableURI(context)); + + LoaderNode node = (LoaderNode)parent.addNode(name, clazz); + + final Pair reference = processor.sync(new ScenegraphReference(context)); + + node.setPropertyCallback(new FunctionImpl2() { + + @Override + public Boolean apply(String property, Object value) { + Pair key = Pair.make(reference.first, reference.second + "#" + property); + externalValueMap.put(key, value); + Collection> listeners = externalMap.get(key); + if(listeners != null) { + for(Procedure listener : listeners) listener.execute(value); + } + return true; + } + + }); + + for(NamedResource property : ScenegraphLoaderUtils.getProperties(processor, configuration)) { + try { + Function1 func = node.getPropertyFunction(property.getName()); + if (func != null) + ScenegraphLoaderUtils.listen(processor, process, context, property.getName(), func); + //else + // System.out.println("NO FUNCTION FOR PROPERTY: " + property.getName() + " (" + node + ")"); + } catch (Exception e) { + e.printStackTrace(); + } + } + + return node; + + } + + public static Variable getVariableSelection(ReadGraph graph, Variable context) throws DatabaseException { + + Variable runtimeVariable = getRuntimeVariable(graph, context); + if (runtimeVariable == null) + throw new VariableException("no runtime variable for context " + context.getURI(graph)); + return runtimeVariable.getPropertyValue(graph, "variable"); + + } + + public static Variable getPossibleVariableSelection(ReadGraph graph, Variable context) throws DatabaseException { + Variable runtimeVariable = getRuntimeVariable(graph, context); + return runtimeVariable == null ? null : (Variable) runtimeVariable.getPossiblePropertyValue(graph, "variable"); + } + + public static Resource getResourceSelection(ReadGraph graph, Variable context) throws DatabaseException { + + Variable runtimeVariable = getRuntimeVariable(graph, context); + if (runtimeVariable == null) + throw new VariableException("no runtime variable for context " + context.getURI(graph)); + Resource sel = runtimeVariable.getPropertyValue(graph, "resource"); + return sel; + + } + + public static Resource getPossibleResourceSelection(ReadGraph graph, Variable context) throws DatabaseException { + + Variable runtimeVariable = getRuntimeVariable(graph, context); + return runtimeVariable == null ? null : (Resource) runtimeVariable.getPossiblePropertyValue(graph, "resource"); + + } + + public static INode getNode(ReadGraph graph, Variable location) throws DatabaseException { + Variable runtime = getRuntimeVariable(graph, location); + INode root = runtime.adapt(graph, INode.class); + Variable base = getBaseVariable(graph, location); + String rvi = Variables.getRVI(graph, base, location); + return NodeUtil.browsePossible(root, rvi); + } + +// public static ScenegraphPropertyReference getPropertyReference(final IThreadWorkQueue thread, final Variable context, final String path) throws DatabaseException { +// return Simantics.getSession().sync(new UniqueRead>() { +// +// @Override +// public ScenegraphPropertyReference perform(ReadGraph graph) throws DatabaseException { +// return getRelativePropertyReference(thread, graph, context, path); +// } +// +// }); +// } + +// public static T getRelativeProperty(final IThreadWorkQueue thread, ReadGraph graph, Variable context, String path) throws DatabaseException { +// ScenegraphPropertyReference ref = getRelativePropertyReference(thread, graph, context, path); +// return ref.getExternalValue(graph); +// } + + public static T getProperty(final IThreadWorkQueue thread, INode _root, String reference) { + + INode root = ((ParentNode)_root).getNodes().iterator().next(); + + final Pair ref = NodeUtil.browsePossibleReference(root, reference); + + final DataContainer result = new DataContainer(); + + ThreadUtils.syncExec(thread, new Runnable() { + + @Override + public void run() { + T value = ScenegraphLoaderUtils.getNodeProperty((LoaderNode)ref.first, ref.second); + result.set(value); + } + + }); + + return result.get(); + + } + + public static ScenegraphPropertyReference getRelativePropertyReference(final IThreadWorkQueue thread, ReadGraph graph, Variable context, String path) throws DatabaseException { + + Variable runtime = getRuntimeVariable(graph, context); + INode root = runtime.adapt(graph, INode.class); + Variable base = getBaseVariable(graph, context); + INode baseNode = NodeUtil.findChildById((ParentNode)root, base.getName(graph)); + String contextRVI = Variables.getRVI(graph, base, context); + String rvi = Variables.getRVI(contextRVI, path); + return new ScenegraphPropertyReference(thread, baseNode, rvi, base); + + } + + public static ScenegraphPropertyReference getPropertyReference(final IThreadWorkQueue thread, ReadGraph graph, Variable context, String path) throws DatabaseException { + + Variable runtime = getRuntimeVariable(graph, context); + INode root = runtime.adapt(graph, INode.class); + Variable base = getBaseVariable(graph, context); + return new ScenegraphPropertyReference(thread, root, path, base); + + } + + public static Method getSynchronizeMethod(INode node, String propertyName) { + try { + String methodName = "synchronize" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1); + for(Method m : node.getClass().getMethods()) { + if(m.getName().equals(methodName)) return m; + } + return null; + } catch (SecurityException e) { + e.printStackTrace(); + } + return null; + } + + public static Method getReadMethod(INode node, String propertyName) { + try { + String methodName = "read" + propertyName.substring(0,1).toUpperCase() + propertyName.substring(1); + return node.getClass().getMethod(methodName); + } catch (SecurityException e) { + e.printStackTrace(); + } catch (NoSuchMethodException e) { + e.printStackTrace(); + } + return null; + } + + public static Field getPropertyField(INode node, String propertyName) { + try { + return node.getClass().getField(propertyName); + } catch (SecurityException e) { + e.printStackTrace(); + } catch (NoSuchFieldException e) { + System.err.println("node:" + node); + e.printStackTrace(); + } + return null; + } + + public static Class getPropertyType(Field field) { + return field.getType(); + } + + public static Class getArgumentType(Method method) { + return (Class)method.getGenericParameterTypes()[0]; + } + + public static Class getReturnType(Method method) { + return method.getReturnType(); + } + + public static Binding getPropertyBinding(Class clazz) { + try { + return Bindings.getBindingUnchecked(clazz); + } catch (Throwable t) { + return null; + } + } + + public static Binding getGenericPropertyBinding(Binding binding) { + try { + return Bindings.getBinding(binding.type()); + } catch (Throwable t) { + return null; + } + } + + public static Function1 getPropertyFunction(final LoaderNode node, final String propertyName) { + return node.getPropertyFunction(propertyName); + } + + public static T getNodeProperty(final LoaderNode node, final String propertyName) { + return node.getProperty(propertyName); + } + + public static String getPath(ReadGraph graph, Variable context) throws DatabaseException { + Variable base = getBaseVariable(graph, context); + return Variables.getRVI(graph, base, context); + } + +}