X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.diagram%2Fsrc%2Forg%2Fsimantics%2Fdiagram%2Fruntime%2FRuntimeDiagramManager.java;h=10c2d89040b1fe2a800091cda84767be54982f09;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hp=ef117ee8a8359f0cba338f6f4b69b9bd2c50c449;hpb=969bd23cab98a79ca9101af33334000879fb60c5;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.diagram/src/org/simantics/diagram/runtime/RuntimeDiagramManager.java b/bundles/org.simantics.diagram/src/org/simantics/diagram/runtime/RuntimeDiagramManager.java index ef117ee8a..10c2d8904 100644 --- a/bundles/org.simantics.diagram/src/org/simantics/diagram/runtime/RuntimeDiagramManager.java +++ b/bundles/org.simantics.diagram/src/org/simantics/diagram/runtime/RuntimeDiagramManager.java @@ -1,373 +1,373 @@ -/******************************************************************************* - * Copyright (c) 2010, 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 - issue #4384 - *******************************************************************************/ -package org.simantics.diagram.runtime; - -import java.util.concurrent.atomic.AtomicReference; - -import org.eclipse.ui.IEditorInput; -import org.simantics.databoard.Bindings; -import org.simantics.db.AsyncReadGraph; -import org.simantics.db.RequestProcessor; -import org.simantics.db.Resource; -import org.simantics.db.Session; -import org.simantics.db.VirtualGraph; -import org.simantics.db.WriteGraph; -import org.simantics.db.common.procedure.adapter.ListenerSupport; -import org.simantics.db.common.request.WriteRequest; -import org.simantics.db.common.request.WriteResultRequest; -import org.simantics.db.exception.DatabaseException; -import org.simantics.db.layer0.util.RemoverUtil; -import org.simantics.db.layer0.variable.RVI; -import org.simantics.db.procedure.AsyncListener; -import org.simantics.diagram.stubs.DiagramResource; -import org.simantics.layer0.Layer0; -import org.simantics.operation.Layer0X; -import org.simantics.ui.workbench.IResourceEditorInput2; -import org.simantics.utils.datastructures.Callback; -import org.simantics.utils.ui.ErrorLogger; - -/** - * A helper class for managing the life-cycle of a diagram runtime realization. - * - *

- * The diagram runtime resource is a virtual (transient) graph database resource - * that specifies the active runtime properties of the diagram as follows: - * - *

- *    RUNTIME RESOURCE
- *    |---[DIAGRAM.RuntimeDiagram.HasConfiguration]---> :DIAGRAM.Diagram (directed link, no inverse relation)
- *    |---[DIAGRAM.RuntimeDiagram.HasRuntimeProfile]---> :DIAGRAM.Profile (directed link, no inverse relation)
- *    |---[DIAGRAM.HasModelURI]------------ "Model URI" : L0.String
- *    |---[DIAGRAM.HasVariable]------------ "Variable URI" : L0.String
- *    `---[DIAGRAM.HasRVI]----------------- "RVI" : L0.String
- * 
- * - * The runtime resource itself is not attached anywhere in the graph, it only - * contains a directed link back to its diagram. - * - *

- * For example diagram profiles require the runtime diagram to have the - * DIAGRAM.HasVariable property. This in turn requires that the model has a - * proper {@link Layer0X#HasBaseRealization} relation in order to be resolved - * (see {@link RuntimeVariable}). - * - *

- * To get started using this class, see - * {@link #track(Session, Resource, IEditorInput, ListenerSupport)} and - * {@link #create(Session, Resource, String, String)}. - * - *

- * Instances of this class are not thread-safe. - * - * @author Tuukka Lehtonen - */ -public class RuntimeDiagramManager { - - private boolean disposed; - - private Session session; - private IEditorInput editorInput; - private ListenerSupport support; - - private AtomicReference runtimeDiagram = new AtomicReference(); - - /** - * Constructs a new RuntimeDiagramManager, creates a new runtime diagram - * based on the specified editor input if it is an - * {@link IResourceEditorInput2} and starts tracking (listening) to changes - * in editor input which specifies the ModelURI and RVI needed for the - * runtime diagram. The tracking aspect comes to play in that editor inputs - * are basically allowed to change and therefore this manager tries to - * listen to changes in both the Model URI and RVI. If the input changes, - * the manager will automatically update the properties of the runtime - * diagram to match the input. - * - *

- * Invoking this method is equal to calling: - * - *

-     * RuntimeDiagramManager manager = new RuntimeDiagramManager(session);
-     * manager.track(diagram, editorInput, listenerSupport);
-     * 
- * - * @param session - * @param diagram - * @param editorInput - * @param listenerSupport - * @return - * @throws DatabaseException - */ - public static RuntimeDiagramManager track( - Session session, - final Resource diagram, - IEditorInput editorInput, - ListenerSupport listenerSupport) - throws DatabaseException - { - RuntimeDiagramManager manager = new RuntimeDiagramManager(session); - manager.track(diagram, editorInput, listenerSupport); - return manager; - } - - /** - * Just as {@link #track(Session, Resource, IEditorInput, ListenerSupport)} - * this method will construct a RuntimeDiagramManager and create a runtime - * diagram resource, but contrary to - * {@link #track(Session, Resource, IEditorInput, ListenerSupport)} it will - * not listen to changes nor update the runtime diagram properties. - * - *

- * Invoking this method is equal to calling: - *

-     * RuntimeDiagramManager manager = new RuntimeDiagramManager(session);
-     * manager.createRuntimeDiagram(diagram, modelURI, RVI);
-     * 
- * - * @param session - * @param diagram - * @param modelURI - * @param RVI - * @return - * @throws DatabaseException - * - * @see {@link #track(Session, Resource, IEditorInput, ListenerSupport)} - */ - public static RuntimeDiagramManager create( - Session session, - Resource diagram, - String modelURI, - String RVI) - throws DatabaseException - { - RuntimeDiagramManager manager = new RuntimeDiagramManager(session); - manager.createRuntimeDiagram(diagram, modelURI, RVI); - return manager; - } - - public RuntimeDiagramManager(Session session) { - this.session = session; - } - - public Resource getRuntimeDiagram() { - return runtimeDiagram.get(); - } - - public void dispose() { - synchronized (this) { - assertNotDisposed(); - disposed = true; - } - - destroy(); - - this.session = null; - this.editorInput = null; - this.support = null; - } - - private void assertNotDisposed() { - if (disposed) - throw new IllegalStateException(this + " is disposed"); - } - - private static IResourceEditorInput2 getResourceInput(Object input) { - if (input instanceof IResourceEditorInput2) - return (IResourceEditorInput2) input; - return null; - } - - private IResourceEditorInput2 getResourceInput() { - return getResourceInput(editorInput); - } - - /** - * Does nothing if already tracking a diagram runtime resource. - * - * @param diagram - * @param editorInput - * @param listenerSupport - * @return the current tracked diagram runtime resource - * @throws DatabaseException - * - * @see {@link #track(Session, Resource, IEditorInput, ListenerSupport)} - */ - public Resource track(final Resource diagram, IEditorInput editorInput, ListenerSupport listenerSupport) throws DatabaseException { - Resource runtime = runtimeDiagram.get(); - if (runtime != null) - return runtime; - - if (editorInput == null) - throw new NullPointerException("null editorInput"); - if (listenerSupport == null) - throw new NullPointerException("null listenerSupport"); - - final IResourceEditorInput2 input = getResourceInput(editorInput); - if (input == null) - return null; - - this.editorInput = editorInput; - this.support = listenerSupport; - - runtime = session.syncRequest(new WriteResultRequest(session.getService(VirtualGraph.class)) { - @Override - public Resource perform(WriteGraph graph) throws DatabaseException { - RuntimeDiagramDesc variable = graph.syncRequest(new RuntimeVariableForInput(input)); - if (variable == null) - return null; - - final Resource runtime = createRuntimeDiagram(graph, diagram, variable); - listenRequest(graph, diagram); - return runtime; - } - }); - - runtimeDiagram.set(runtime); - return runtime; - } - - /** - * @param diagram - * @param modelURI - * @param RVI - * @return - * @throws DatabaseException - * - * @see {@link #create(Session, Resource, String, String) - */ - public Resource createRuntimeDiagram(final Resource diagram, final String modelURI, final String RVI) throws DatabaseException { - Resource runtime = runtimeDiagram.get(); - if (runtime != null) - return runtime; - - runtime = session.syncRequest(new WriteResultRequest(session.getService(VirtualGraph.class)) { - @Override - public Resource perform(WriteGraph graph) throws DatabaseException { - Resource model = graph.getPossibleResource(modelURI); - return createRuntimeDiagram(graph, diagram, model, RVI); - } - }); - - runtimeDiagram.set(runtime); - return runtime; - } - - /** - * @param graph - * @param diagram - * @param modelURI - * @param RVI - * @return - * @throws DatabaseException - */ - public Resource createRuntimeDiagram(WriteGraph graph, final Resource diagram, final Resource model, final String rvis) throws DatabaseException { - RVI rvi = rvis != null ? RVI.fromResourceFormat(graph, rvis) : null; - RuntimeDiagramDesc desc = graph.syncRequest(new RuntimeVariable(model, rvi, diagram)); - if (desc == null) - return null; - return createRuntimeDiagram(graph, diagram, desc); - } - - private void listenRequest(RequestProcessor processor, final Resource diagram) { - processor.asyncRequest(new RuntimeVariableForInput(getResourceInput()), new AsyncListener() { - - @Override - public void exception(AsyncReadGraph graph, Throwable throwable) { - ListenerSupport s = support; - if (s != null) - s.exception(throwable); - } - - @Override - public void execute(AsyncReadGraph graph, final RuntimeDiagramDesc desc) { - if (desc == null) - return; - - Session session = graph.getSession(); - session.asyncRequest(new WriteRequest(session.getService(VirtualGraph.class)) { - @Override - public void perform(WriteGraph graph) throws DatabaseException { - Resource runtime = getRuntimeDiagram(); - if (runtime != null) - writeConfig(graph, runtime, diagram, desc); - } - }, new Callback() { - @Override - public void run(DatabaseException e) { - ListenerSupport s = support; - if (e != null && s != null) - s.exception(e); - } - }); - } - - @Override - public boolean isDisposed() { - if(disposed) return true; - else return support != null && support.isDisposed(); - } - }); - } - - private Resource createRuntimeDiagram(WriteGraph graph, Resource diagram, RuntimeDiagramDesc desc) throws DatabaseException { - - Layer0 L0 = Layer0.getInstance(graph); - final DiagramResource DIA = DiagramResource.getInstance(graph); - - // Create the new runtime diagram instance! - final Resource runtime = graph.newResource(); - graph.claim(runtime, L0.InstanceOf, null, DIA.RuntimeDiagram); - graph.claim(runtime, DIA.RuntimeDiagram_HasConfiguration, null, diagram); - - writeConfig(graph, runtime, diagram, desc); - - return runtime; - } - - private void writeConfig(WriteGraph graph, final Resource runtime, final Resource diagram, RuntimeDiagramDesc desc) throws DatabaseException { - final DiagramResource DIA = DiagramResource.getInstance(graph); - if (desc.getVariableURI() != null) - graph.claimLiteral(runtime, DIA.RuntimeDiagram_HasVariable, desc.getVariableURI(), Bindings.STRING); - if (desc.getRVI() != null) - graph.claimLiteral(runtime, DIA.RuntimeDiagram_HasRVI, desc.getRVI(), Bindings.STRING); - if (desc.getModelURI() != null) - graph.claimLiteral(runtime, DIA.RuntimeDiagram_HasModelURI, desc.getModelURI(), Bindings.STRING); - if (desc.getActiveProfileURI() != null) { - Resource activeProfile = graph.getPossibleResource(desc.getActiveProfileURI()); - if (activeProfile != null) { - graph.deny(runtime, DIA.RuntimeDiagram_HasRuntimeProfile); - graph.claim(runtime, DIA.RuntimeDiagram_HasRuntimeProfile, null, activeProfile); - } - } - } - - private void destroy() { - final Resource rd = runtimeDiagram.getAndSet(null); - if (rd != null) { - try { - session.syncRequest(new WriteRequest(session.getService(VirtualGraph.class)) { - @Override - public void perform(WriteGraph graph) throws DatabaseException { - RemoverUtil.remove(graph, rd); - } - }); - } catch (DatabaseException e) { - ListenerSupport s = support; - if (s != null) - s.exception(e); - else - ErrorLogger.defaultLogError(e); - } - } - } - -} +/******************************************************************************* + * Copyright (c) 2010, 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 - issue #4384 + *******************************************************************************/ +package org.simantics.diagram.runtime; + +import java.util.concurrent.atomic.AtomicReference; + +import org.eclipse.ui.IEditorInput; +import org.simantics.databoard.Bindings; +import org.simantics.db.AsyncReadGraph; +import org.simantics.db.RequestProcessor; +import org.simantics.db.Resource; +import org.simantics.db.Session; +import org.simantics.db.VirtualGraph; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.procedure.adapter.ListenerSupport; +import org.simantics.db.common.request.WriteRequest; +import org.simantics.db.common.request.WriteResultRequest; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.util.RemoverUtil; +import org.simantics.db.layer0.variable.RVI; +import org.simantics.db.procedure.AsyncListener; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.layer0.Layer0; +import org.simantics.operation.Layer0X; +import org.simantics.ui.workbench.IResourceEditorInput2; +import org.simantics.utils.datastructures.Callback; +import org.simantics.utils.ui.ErrorLogger; + +/** + * A helper class for managing the life-cycle of a diagram runtime realization. + * + *

+ * The diagram runtime resource is a virtual (transient) graph database resource + * that specifies the active runtime properties of the diagram as follows: + * + *

+ *    RUNTIME RESOURCE
+ *    |---[DIAGRAM.RuntimeDiagram.HasConfiguration]---> :DIAGRAM.Diagram (directed link, no inverse relation)
+ *    |---[DIAGRAM.RuntimeDiagram.HasRuntimeProfile]---> :DIAGRAM.Profile (directed link, no inverse relation)
+ *    |---[DIAGRAM.HasModelURI]------------ "Model URI" : L0.String
+ *    |---[DIAGRAM.HasVariable]------------ "Variable URI" : L0.String
+ *    `---[DIAGRAM.HasRVI]----------------- "RVI" : L0.String
+ * 
+ * + * The runtime resource itself is not attached anywhere in the graph, it only + * contains a directed link back to its diagram. + * + *

+ * For example diagram profiles require the runtime diagram to have the + * DIAGRAM.HasVariable property. This in turn requires that the model has a + * proper {@link Layer0X#HasBaseRealization} relation in order to be resolved + * (see {@link RuntimeVariable}). + * + *

+ * To get started using this class, see + * {@link #track(Session, Resource, IEditorInput, ListenerSupport)} and + * {@link #create(Session, Resource, String, String)}. + * + *

+ * Instances of this class are not thread-safe. + * + * @author Tuukka Lehtonen + */ +public class RuntimeDiagramManager { + + private boolean disposed; + + private Session session; + private IEditorInput editorInput; + private ListenerSupport support; + + private AtomicReference runtimeDiagram = new AtomicReference(); + + /** + * Constructs a new RuntimeDiagramManager, creates a new runtime diagram + * based on the specified editor input if it is an + * {@link IResourceEditorInput2} and starts tracking (listening) to changes + * in editor input which specifies the ModelURI and RVI needed for the + * runtime diagram. The tracking aspect comes to play in that editor inputs + * are basically allowed to change and therefore this manager tries to + * listen to changes in both the Model URI and RVI. If the input changes, + * the manager will automatically update the properties of the runtime + * diagram to match the input. + * + *

+ * Invoking this method is equal to calling: + * + *

+     * RuntimeDiagramManager manager = new RuntimeDiagramManager(session);
+     * manager.track(diagram, editorInput, listenerSupport);
+     * 
+ * + * @param session + * @param diagram + * @param editorInput + * @param listenerSupport + * @return + * @throws DatabaseException + */ + public static RuntimeDiagramManager track( + Session session, + final Resource diagram, + IEditorInput editorInput, + ListenerSupport listenerSupport) + throws DatabaseException + { + RuntimeDiagramManager manager = new RuntimeDiagramManager(session); + manager.track(diagram, editorInput, listenerSupport); + return manager; + } + + /** + * Just as {@link #track(Session, Resource, IEditorInput, ListenerSupport)} + * this method will construct a RuntimeDiagramManager and create a runtime + * diagram resource, but contrary to + * {@link #track(Session, Resource, IEditorInput, ListenerSupport)} it will + * not listen to changes nor update the runtime diagram properties. + * + *

+ * Invoking this method is equal to calling: + *

+     * RuntimeDiagramManager manager = new RuntimeDiagramManager(session);
+     * manager.createRuntimeDiagram(diagram, modelURI, RVI);
+     * 
+ * + * @param session + * @param diagram + * @param modelURI + * @param RVI + * @return + * @throws DatabaseException + * + * @see {@link #track(Session, Resource, IEditorInput, ListenerSupport)} + */ + public static RuntimeDiagramManager create( + Session session, + Resource diagram, + String modelURI, + String RVI) + throws DatabaseException + { + RuntimeDiagramManager manager = new RuntimeDiagramManager(session); + manager.createRuntimeDiagram(diagram, modelURI, RVI); + return manager; + } + + public RuntimeDiagramManager(Session session) { + this.session = session; + } + + public Resource getRuntimeDiagram() { + return runtimeDiagram.get(); + } + + public void dispose() { + synchronized (this) { + assertNotDisposed(); + disposed = true; + } + + destroy(); + + this.session = null; + this.editorInput = null; + this.support = null; + } + + private void assertNotDisposed() { + if (disposed) + throw new IllegalStateException(this + " is disposed"); + } + + private static IResourceEditorInput2 getResourceInput(Object input) { + if (input instanceof IResourceEditorInput2) + return (IResourceEditorInput2) input; + return null; + } + + private IResourceEditorInput2 getResourceInput() { + return getResourceInput(editorInput); + } + + /** + * Does nothing if already tracking a diagram runtime resource. + * + * @param diagram + * @param editorInput + * @param listenerSupport + * @return the current tracked diagram runtime resource + * @throws DatabaseException + * + * @see {@link #track(Session, Resource, IEditorInput, ListenerSupport)} + */ + public Resource track(final Resource diagram, IEditorInput editorInput, ListenerSupport listenerSupport) throws DatabaseException { + Resource runtime = runtimeDiagram.get(); + if (runtime != null) + return runtime; + + if (editorInput == null) + throw new NullPointerException("null editorInput"); + if (listenerSupport == null) + throw new NullPointerException("null listenerSupport"); + + final IResourceEditorInput2 input = getResourceInput(editorInput); + if (input == null) + return null; + + this.editorInput = editorInput; + this.support = listenerSupport; + + runtime = session.syncRequest(new WriteResultRequest(session.getService(VirtualGraph.class)) { + @Override + public Resource perform(WriteGraph graph) throws DatabaseException { + RuntimeDiagramDesc variable = graph.syncRequest(new RuntimeVariableForInput(input)); + if (variable == null) + return null; + + final Resource runtime = createRuntimeDiagram(graph, diagram, variable); + listenRequest(graph, diagram); + return runtime; + } + }); + + runtimeDiagram.set(runtime); + return runtime; + } + + /** + * @param diagram + * @param modelURI + * @param RVI + * @return + * @throws DatabaseException + * + * @see {@link #create(Session, Resource, String, String) + */ + public Resource createRuntimeDiagram(final Resource diagram, final String modelURI, final String RVI) throws DatabaseException { + Resource runtime = runtimeDiagram.get(); + if (runtime != null) + return runtime; + + runtime = session.syncRequest(new WriteResultRequest(session.getService(VirtualGraph.class)) { + @Override + public Resource perform(WriteGraph graph) throws DatabaseException { + Resource model = graph.getPossibleResource(modelURI); + return createRuntimeDiagram(graph, diagram, model, RVI); + } + }); + + runtimeDiagram.set(runtime); + return runtime; + } + + /** + * @param graph + * @param diagram + * @param modelURI + * @param RVI + * @return + * @throws DatabaseException + */ + public Resource createRuntimeDiagram(WriteGraph graph, final Resource diagram, final Resource model, final String rvis) throws DatabaseException { + RVI rvi = rvis != null ? RVI.fromResourceFormat(graph, rvis) : null; + RuntimeDiagramDesc desc = graph.syncRequest(new RuntimeVariable(model, rvi, diagram)); + if (desc == null) + return null; + return createRuntimeDiagram(graph, diagram, desc); + } + + private void listenRequest(RequestProcessor processor, final Resource diagram) { + processor.asyncRequest(new RuntimeVariableForInput(getResourceInput()), new AsyncListener() { + + @Override + public void exception(AsyncReadGraph graph, Throwable throwable) { + ListenerSupport s = support; + if (s != null) + s.exception(throwable); + } + + @Override + public void execute(AsyncReadGraph graph, final RuntimeDiagramDesc desc) { + if (desc == null) + return; + + Session session = graph.getSession(); + session.asyncRequest(new WriteRequest(session.getService(VirtualGraph.class)) { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + Resource runtime = getRuntimeDiagram(); + if (runtime != null) + writeConfig(graph, runtime, diagram, desc); + } + }, new Callback() { + @Override + public void run(DatabaseException e) { + ListenerSupport s = support; + if (e != null && s != null) + s.exception(e); + } + }); + } + + @Override + public boolean isDisposed() { + if(disposed) return true; + else return support != null && support.isDisposed(); + } + }); + } + + private Resource createRuntimeDiagram(WriteGraph graph, Resource diagram, RuntimeDiagramDesc desc) throws DatabaseException { + + Layer0 L0 = Layer0.getInstance(graph); + final DiagramResource DIA = DiagramResource.getInstance(graph); + + // Create the new runtime diagram instance! + final Resource runtime = graph.newResource(); + graph.claim(runtime, L0.InstanceOf, null, DIA.RuntimeDiagram); + graph.claim(runtime, DIA.RuntimeDiagram_HasConfiguration, null, diagram); + + writeConfig(graph, runtime, diagram, desc); + + return runtime; + } + + private void writeConfig(WriteGraph graph, final Resource runtime, final Resource diagram, RuntimeDiagramDesc desc) throws DatabaseException { + final DiagramResource DIA = DiagramResource.getInstance(graph); + if (desc.getVariableURI() != null) + graph.claimLiteral(runtime, DIA.RuntimeDiagram_HasVariable, desc.getVariableURI(), Bindings.STRING); + if (desc.getRVI() != null) + graph.claimLiteral(runtime, DIA.RuntimeDiagram_HasRVI, desc.getRVI(), Bindings.STRING); + if (desc.getModelURI() != null) + graph.claimLiteral(runtime, DIA.RuntimeDiagram_HasModelURI, desc.getModelURI(), Bindings.STRING); + if (desc.getActiveProfileURI() != null) { + Resource activeProfile = graph.getPossibleResource(desc.getActiveProfileURI()); + if (activeProfile != null) { + graph.deny(runtime, DIA.RuntimeDiagram_HasRuntimeProfile); + graph.claim(runtime, DIA.RuntimeDiagram_HasRuntimeProfile, null, activeProfile); + } + } + } + + private void destroy() { + final Resource rd = runtimeDiagram.getAndSet(null); + if (rd != null) { + try { + session.syncRequest(new WriteRequest(session.getService(VirtualGraph.class)) { + @Override + public void perform(WriteGraph graph) throws DatabaseException { + RemoverUtil.remove(graph, rd); + } + }); + } catch (DatabaseException e) { + ListenerSupport s = support; + if (s != null) + s.exception(e); + else + ErrorLogger.defaultLogError(e); + } + } + } + +}