/******************************************************************************* * 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.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
* Invoking this method is equal to calling:
*
*
* 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.
*
*
* 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