X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.modeling%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2Ftypicals%2FTypicalUtil.java;fp=bundles%2Forg.simantics.modeling%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2Ftypicals%2FTypicalUtil.java;h=9c29290a50e03e2e1da3e01c6afc591aa6b4d9ea;hp=0000000000000000000000000000000000000000;hb=969bd23cab98a79ca9101af33334000879fb60c5;hpb=866dba5cd5a3929bbeae85991796acb212338a08 diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/typicals/TypicalUtil.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/typicals/TypicalUtil.java new file mode 100644 index 000000000..9c29290a5 --- /dev/null +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/typicals/TypicalUtil.java @@ -0,0 +1,642 @@ +/******************************************************************************* + * Copyright (c) 2012 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 + *******************************************************************************/ +package org.simantics.modeling.typicals; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.Semaphore; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Consumer; + +import org.simantics.NameLabelMode; +import org.simantics.NameLabelUtil; +import org.simantics.Simantics; +import org.simantics.databoard.Bindings; +import org.simantics.db.ReadGraph; +import org.simantics.db.RequestProcessor; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.WriteOnlyGraph; +import org.simantics.db.common.CommentMetadata; +import org.simantics.db.common.NamedResource; +import org.simantics.db.common.request.FreshName; +import org.simantics.db.common.request.ObjectsWithType; +import org.simantics.db.common.request.PossibleIndexRoot; +import org.simantics.db.common.request.UniqueRead; +import org.simantics.db.common.request.WriteResultRequest; +import org.simantics.db.common.uri.UnescapedChildMapOfResource; +import org.simantics.db.common.utils.CommonDBUtils; +import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.exception.RuntimeDatabaseException; +import org.simantics.db.layer0.adapter.CopyHandler; +import org.simantics.db.layer0.adapter.Instances; +import org.simantics.db.layer0.request.Configuration; +import org.simantics.db.layer0.request.PossibleModel; +import org.simantics.db.layer0.util.ClipboardUtils; +import org.simantics.db.layer0.util.SimanticsClipboard.Representation; +import org.simantics.db.layer0.util.SimanticsClipboardImpl; +import org.simantics.db.layer0.util.SimanticsKeys; +import org.simantics.db.layer0.variable.Variable; +import org.simantics.db.layer0.variable.Variables; +import org.simantics.db.procedure.Procedure; +import org.simantics.db.request.WriteResult; +import org.simantics.diagram.stubs.DiagramResource; +import org.simantics.graph.db.IImportAdvisor; +import org.simantics.graph.db.TransferableGraphs; +import org.simantics.graph.representation.Root; +import org.simantics.graph.representation.TransferableGraph1; +import org.simantics.layer0.Layer0; +import org.simantics.modeling.ModelingResources; +import org.simantics.modeling.ModelingUtils.CompositeInfo; +import org.simantics.modeling.ModelingUtils.DiagramComponentInfo; +import org.simantics.modeling.services.ComponentNamingUtil; +import org.simantics.modeling.services.NamingException; +import org.simantics.operation.Layer0X; +import org.simantics.scl.runtime.function.Function2; +import org.simantics.scl.runtime.function.Function4; +import org.simantics.structural.stubs.StructuralResource2; +import org.simantics.structural2.utils.StructuralUtils; +import org.simantics.ui.SimanticsUI; +import org.simantics.utils.datastructures.Pair; +import org.simantics.utils.ui.dialogs.ShowMessage; + +/** + * @author Tuukka Lehtonen + */ +public class TypicalUtil { + + private static final boolean DEBUG = false; + + private static class TypicalNamingFunction implements Function2 { + private NameLabelMode mode; + + @Override + public String apply(ReadGraph graph, Resource r) { + try { + if (mode == null) + mode = NameLabelUtil.getNameLabelMode(graph); + Variable v = Variables.getPossibleVariable(graph, r); + if (v != null) { + Resource root = Variables.getPossibleIndexRoot(graph, v); + if (root != null) { + Variable rootV = Variables.getVariable(graph, root); + List path = Variables.getPath(graph, rootV, v); + path.add(0, rootV); + return typicalLabel(graph, v, path); + } + } + return TypicalUtil.getName(graph, r); + } catch (DatabaseException e) { + throw new RuntimeDatabaseException(e); + } + } + + protected String typicalLabel(ReadGraph graph, Variable v, List path) throws DatabaseException { + StringBuilder sb = new StringBuilder(); + labelVariable(graph, v, sb); + if (path.size() > 0) { + sb.append(" ("); + for (Variable vv : path) { + sb.append("/"); + labelVariable(graph, vv, sb); + } + sb.append(")"); + } + return sb.toString(); + } + + protected StringBuilder labelVariable(ReadGraph graph, Variable v, StringBuilder result) throws DatabaseException { + Resource r = v.getPossibleRepresents(graph); + if (r != null) { + result.append(NameLabelUtil.modalName(graph, r, mode)); + } else { + result.append(NameLabelUtil.modalName(graph, v, mode)); + } + return result; + } + }; + + public static Collection toNamedResources(RequestProcessor processor, final Collection rs) throws DatabaseException { + return toNamedResources(processor, rs, new TypicalNamingFunction()); + } + + public static Collection toNamedResources(RequestProcessor processor, final Collection rs, final Function2 namingFunction) throws DatabaseException { + return processor.syncRequest(new UniqueRead>() { + @Override + public Collection perform(ReadGraph graph) throws DatabaseException { + return toNamedResources(graph, rs, namingFunction); + } + }); + } + + public static Collection toNamedResources(ReadGraph graph, Collection rs, final Function2 namingFunction) throws DatabaseException { + Collection result = new ArrayList(rs.size()); + for (Resource r : rs) + result.add(new NamedResource(namingFunction.apply(graph, r), r)); + return result; + } + + public static String getName(ReadGraph graph, Resource r) throws DatabaseException { + String s = graph.getPossibleAdapter(r, String.class); + if (s == null) + s = NameUtils.getSafeLabel(graph, r); + return s; + } + + public static WriteResult instantiateTemplate(final Resource target, final NamedResource template, + final Consumer> successContinuation) { + return new WriteResultRequest() { + @Override + public Resource perform(WriteGraph graph) throws DatabaseException { + // Custom instantiation by copying the original and mapping the original to the copy + CommonDBUtils.selectClusterSet(graph, target); + SimanticsClipboardImpl clipboard = new SimanticsClipboardImpl(); + CopyHandler ch = new TypicalCompositeCopyHandler(template.getResource()); + ch.copyToClipboard(graph, clipboard); + + Map hints = Collections.singletonMap(ClipboardUtils.HINT_TARGET_RESOURCE, target); + + for (Set object : clipboard.getContents()) { + TransferableGraph1 tg = ClipboardUtils.accept(graph, object, SimanticsKeys.KEY_TRANSFERABLE_GRAPH, hints); + if (tg != null) { + DiagramPasteImportAdvisor advisor = new DiagramPasteImportAdvisor(graph, target, template.getName()); + TransferableGraphs.importGraph1(graph, tg, advisor); + Resource copy = advisor.getRoot(); + + configureCopyType(graph, copy, template.getResource()); + associateCopyToTemplate(graph, copy, template.getResource()); + + if (successContinuation!= null) + successContinuation.accept(Pair.make(graph, copy)); + + return copy; + } + } + throw new DatabaseException("Failed to instantiate typical template through clipboard"); + } + }; + } + + public static void configureCopyType(WriteGraph graph, Resource copy, Resource template) throws DatabaseException { + // Remove master template instance tag type(s) + Layer0 L0 = Layer0.getInstance(graph); + DiagramResource DIA = DiagramResource.getInstance(graph); + ModelingResources MOD = ModelingResources.getInstance(graph); + for (Resource type : graph.getObjects(template, L0.InstanceOf)) { + if (graph.isInheritedFrom(type, MOD.MasterTypicalCompositeType)) + graph.deny(copy, L0.InstanceOf, type); + else + graph.claim(copy, L0.InstanceOf, null, type); + } + for (Resource templateDiagram : graph.getObjects(template, MOD.CompositeToDiagram)) { + Resource templateDiagramType = graph.getPossibleType(templateDiagram, DIA.Diagram); + if (templateDiagramType != null) { + for (Resource copiedDiagram : graph.getObjects(copy, MOD.CompositeToDiagram)) { + graph.claim(copiedDiagram, L0.InstanceOf, null, templateDiagramType); + } + } + } + } + + public static void associateCopyToTemplate(WriteGraph graph, Resource copy, Resource template) throws DatabaseException { + DiagramResource DIA = DiagramResource.getInstance(graph); + ModelingResources MOD = ModelingResources.getInstance(graph); + Resource templateDiagram = graph.getSingleObject(template, MOD.CompositeToDiagram); + Resource copyDiagram = graph.getSingleObject(copy, MOD.CompositeToDiagram); + Map templateDiagramElements = graph.syncRequest(new UnescapedChildMapOfResource(templateDiagram)); + Map copyDiagramElements = graph.syncRequest(new UnescapedChildMapOfResource(copyDiagram)); + + // Associations are intentionally bi-directional + graph.claim(copyDiagram, MOD.HasDiagramSource, MOD.DiagramHasInstance, templateDiagram); + for (String element : templateDiagramElements.keySet()) { + Resource templateElement = templateDiagramElements.get(element); + if (!graph.isInstanceOf(templateElement, DIA.Element)) + continue; + Resource copyElement = copyDiagramElements.get(element); + graph.claim(copyElement, MOD.HasElementSource, MOD.ElementHasInstance, templateElement); + graph.claim(copyElement, MOD.IsTemplatized, MOD.IsTemplatized, copyElement); + } + + Long modCount = graph.getPossibleRelatedValue(copyDiagram, DIA.HasModCount); + if (modCount == null) + modCount = 0L; + modCount += 1L << 32; + graph.claimLiteral(copyDiagram, DiagramResource.getInstance(graph).HasModCount, modCount, Bindings.LONG); + } + + /** + * @param graph + * @param typicalCompositeInstance + * @param excludedComponents the set of components in the specified + * composite that are not freshly renamed or null to + * freshly name all components + * @throws DatabaseException + */ + public static void generateFreshModuleNames(WriteGraph graph, Resource typicalCompositeInstance, Set excludedComponents) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + StructuralResource2 STR = StructuralResource2.getInstance(graph); + Resource configurationRoot = graph.sync(new Configuration(typicalCompositeInstance)); + for(Map.Entry entry : graph.syncRequest(new UnescapedChildMapOfResource(typicalCompositeInstance)).entrySet()) { + Resource component = entry.getValue(); + if (!graph.isInstanceOf(component, STR.Component)) + continue; + if (excludedComponents != null && excludedComponents.contains(component)) + continue; + try { + String renamed = ComponentNamingUtil.findFreshInstanceName(graph, SimanticsUI.getProject(), configurationRoot, typicalCompositeInstance, component); + if (DEBUG) + System.out.println("Typicals: renamed " + entry.getKey() + " -> " + renamed); + graph.claimLiteral(entry.getValue(), L0.HasName, L0.NameOf, renamed, Bindings.STRING); + } catch (NamingException e) { + throw new DatabaseException(e); + } + } + } + + public static class DiagramPasteImportAdvisor implements IImportAdvisor { + + protected final Resource library; + protected final Resource model; + protected Resource diagram; + protected final String diagramName; + + public DiagramPasteImportAdvisor(ReadGraph graph, Resource library, String originalName) throws DatabaseException { + this.library = library; + this.diagram = null; + this.diagramName = graph.syncRequest(new FreshName(library, originalName)); + this.model = graph.syncRequest(new PossibleModel(library)); + } + + public void analyzeType(ReadGraph graph, Root root) throws DatabaseException { + } + + @Override + public Resource analyzeRoot(ReadGraph graph, Root root) throws DatabaseException { + if("%model".equals(root.name)) return model; + return null; + } + @Override + public Resource createRoot(WriteOnlyGraph graph, Root root) throws DatabaseException { + + Layer0 l0 = graph.getService(Layer0.class); + if(CompositeInfo.isComposite(root.name)) { + // Use existing if available + if(diagram == null) diagram = graph.newResource(); + graph.claim(library, l0.ConsistsOf, l0.PartOf, diagram); + graph.newClusterSet(diagram); + graph.setClusterSet4NewResource(diagram); + graph.addLiteral(diagram, l0.HasName, l0.NameOf, l0.String, diagramName, Bindings.STRING); + return diagram; + } else if (DiagramComponentInfo.isDiagramComponent(root.name)) { + DiagramComponentInfo info = DiagramComponentInfo.parse(root.name); + Resource child = graph.newResource(); + graph.addLiteral(child, l0.HasName, l0.NameOf, l0.String, info.getUnescapedComponentName(), Bindings.STRING); + return child; + } else { + throw new DatabaseException("Unclassified root " + root.name); + } + + } + + public Resource getRoot() { + return diagram; + } + + } + + /** + * @param graph + * @param typicalInstanceComposite + * @param renamedComponentsOutput a set that can be provided to get the set + * of components that was renamed as output from this method or + * null to not collect renamed components + * @throws DatabaseException + */ + public static void applyTypicalModuleNames(WriteGraph graph, Resource typicalInstanceComposite, Set renamedComponentsOutput) throws DatabaseException { + + Layer0 L0 = Layer0.getInstance(graph); + StructuralResource2 STR = StructuralResource2.getInstance(graph); + + Function4 nameEvaluator = getTypicalNamingFunction(graph, typicalInstanceComposite); + if (nameEvaluator == null) + return; + + Collection components = graph.syncRequest(new ObjectsWithType(typicalInstanceComposite, L0.ConsistsOf, STR.Component)); + for (Resource component : components) { + applyTypicalModuleName(graph, component, nameEvaluator, renamedComponentsOutput); + } + + } + + public static boolean applyTypicalModuleName(WriteGraph graph, Resource instanceComponent, Function4 nameEvaluator, Set renamedComponentsOutput) throws DatabaseException { + + Layer0 L0 = Layer0.getInstance(graph); + StructuralResource2 STR = StructuralResource2.getInstance(graph); + ModelingResources MOD = ModelingResources.getInstance(graph); + + Resource componentType = graph.getPossibleType(instanceComponent, STR.Component); + if (componentType == null) + return false; + + Resource instanceElement = graph.getPossibleObject(instanceComponent, MOD.ComponentToElement); + if (instanceElement == null) + return false; + + Resource templateElement = graph.getPossibleObject(instanceElement, MOD.HasElementSource); + if (templateElement == null) + return false; + + Resource templateComponent = graph.getPossibleObject(templateElement, MOD.ElementToComponent); + if (templateComponent == null) + return false; + + // TODO: Use variables and EXPRESSION property instead ? + String nameExpression = graph.getPossibleRelatedValue(templateComponent, L0.HasName, Bindings.STRING); + if (nameExpression == null) + return false; + + Resource instanceComposite = graph.getPossibleObject(instanceComponent, L0.PartOf); + if (instanceComposite == null) + return false; + + // This evaluator replaces % with assigned primary position name + String evaluatedInstanceName = (String) nameEvaluator.apply(graph, instanceComposite, instanceComponent, nameExpression); + if(evaluatedInstanceName == null) + return false; + + String instanceName = graph.getPossibleRelatedValue(instanceComponent, L0.HasName, Bindings.STRING); + if(instanceName == null) + return false; + + if(!evaluatedInstanceName.equals(instanceName)) { + + graph.claimLiteral(instanceComponent, L0.HasName, evaluatedInstanceName, Bindings.STRING); + if (renamedComponentsOutput != null) + renamedComponentsOutput.add(instanceComponent); + + if (DEBUG) + System.out.println("TypicalUtil.applyTypicalModuleName: applied name expression " + nameExpression + " -> " + instanceName + " -> " + evaluatedInstanceName); + + return true; + + } + + return false; + + } + + /** + * @param graph + * @param typicalComposite + * @param componentsToCheck the set of components to check for required + * naming + * @throws DatabaseException + */ + public static void applySelectedModuleNames(WriteGraph graph, Resource typicalComposite, List componentsToCheck) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + StructuralResource2 STR = StructuralResource2.getInstance(graph); + ModelingResources MOD = ModelingResources.getInstance(graph); + + Function4 nameEvaluator = getTypicalNamingFunction(graph, typicalComposite); + if (nameEvaluator == null) + return; + + for (Resource component : componentsToCheck) { + Resource componentType = graph.getPossibleType(component, STR.Component); + if (componentType == null) + continue; + + Resource element = graph.getPossibleObject(component, MOD.ComponentToElement); + if (element == null) + continue; + + Resource templateElement = graph.getPossibleObject(element, MOD.HasElementSource); + if (templateElement == null) + continue; + + Resource templateComponent = graph.getPossibleObject(templateElement, MOD.ElementToComponent); + if (templateComponent == null) + continue; + + String nameExpression = graph.getPossibleRelatedValue(templateComponent, L0.HasName, Bindings.STRING); + if (nameExpression == null) + continue; + + // NOTE: This assumes that nameEvaluator also makes sure that the + // evaluated names do not collide with any existing names in the + // model. + String evaluatedInstanceName = (String) nameEvaluator.apply(graph, typicalComposite, component, nameExpression); + if (evaluatedInstanceName != null && !evaluatedInstanceName.equals(nameExpression)) { + if (DEBUG) + System.out.println("TypicalUtil.applySelectionModuleNames: applied name expression " + nameExpression + " -> " + evaluatedInstanceName); + graph.claimLiteral(component, L0.HasName, evaluatedInstanceName, Bindings.STRING); + } + } + } + + /** + * @param graph + * @param typicalComposite + * @return f :: ReadGraph -> Resource composite -> Resource component -> String expression -> String name + * @throws DatabaseException + */ + public static Function4 getTypicalNamingFunction(ReadGraph graph, Resource typicalComposite) throws DatabaseException { + ModelingResources MOD = ModelingResources.getInstance(graph); + Function4 nameEvaluator = graph.getPossibleRelatedValue2(typicalComposite, MOD.TypicalComposite_typicalNamingFunction); + return nameEvaluator; + } + + /** + * @param processor + * @param model + * @return + * @throws DatabaseException + */ + public static Collection findModelTypicals(RequestProcessor processor, final Resource model) throws DatabaseException { + return processor.syncRequest(new UniqueRead>() { + @Override + public Collection perform(ReadGraph graph) throws DatabaseException { + ModelingResources MOD = ModelingResources.getInstance(graph); + Resource typicalMasterType = graph.getSingleObject(model, MOD.StructuralModel_HasMasterTypicalCompositeType); + Instances query = graph.adapt(typicalMasterType, Instances.class); + return query.find(graph, model); + } + }); + } + + /** + * A utility for synchronous execution of asynchronous procedures. + * @param runnable the callback that contains asynchronous execution + * @return the result received from the specified callback + * @throws DatabaseException + */ + public static T syncExec(Consumer> runnable) throws DatabaseException { + final AtomicReference ref = new AtomicReference(); + final AtomicReference exc = new AtomicReference(); + final Semaphore sem = new Semaphore(0); + runnable.accept(new Procedure() { + @Override + public void execute(T result) { + if (ref.compareAndSet(null, result)) + sem.release(); + } + @Override + public void exception(Throwable t) { + if (exc.compareAndSet(null, t)) + sem.release(); + } + }); + try { + sem.acquire(); + Throwable t = exc.get(); + if (t != null) { + if (t instanceof DatabaseException) + throw (DatabaseException) t; + throw new DatabaseException(t); + } + return (T) ref.get(); + } catch (InterruptedException ex) { + throw new DatabaseException(ex); + } + } + + /* + * SCL API + */ + public static void syncTypicalInstance(WriteGraph graph, Resource instance) throws DatabaseException { + SyncTypicalTemplatesToInstances sync = SyncTypicalTemplatesToInstances.syncSingleInstance(null, instance); + sync.perform(graph); + } + + /** + * Creates a new master typical diagram and its corresponding composites. + * + *

+ * The created typical composite and diagram type are specified by the model + * using {@link ModelingResources#StructuralModel_HasTypicalCompositeBaseType} + * and {@link ModelingResources#StructuralModel_HasTypicalDiagramBaseType}. + * + *

+ * Marks the created master composite with the model-specified master composite + * type to support searching. The master type is specified by the model using + * {@link ModelingResources#StructuralModel_HasMasterTypicalCompositeType}. + * + *

+ * Clones symbol contributions from the sources specified by the model through + * {@link ModelingResources#StructuralModel_CloneTypicalDiagramSymbolContributionsFrom} + * . + * + * @author Tuukka Lehtonen + */ + + public static Resource newMasterTypical(final Resource target) throws DatabaseException { + + return Simantics.getSession().syncRequest(new WriteResultRequest() { + + @Override + public Resource perform(WriteGraph graph) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + Layer0X L0X = Layer0X.getInstance(graph); + DiagramResource DIA = DiagramResource.getInstance(graph); + ModelingResources MOD = ModelingResources.getInstance(graph); + + Resource indexRoot = graph.sync(new PossibleIndexRoot(target)); + if (indexRoot == null) { + ShowMessage.showInformation("No Model or Shared Library", "Cannot find a containing model or shared library from the input selection. Typical master diagram creation not possible."); + return null; + } + + Resource compositeBaseType = graph.getPossibleObject(indexRoot, MOD.StructuralModel_HasTypicalCompositeBaseType); + Resource diagramBaseType = graph.getPossibleObject(indexRoot, MOD.StructuralModel_HasTypicalDiagramBaseType); + Resource masterCompositeType = graph.getPossibleObject(indexRoot, MOD.StructuralModel_HasMasterTypicalCompositeType); + Collection cloneSymbolContributionsFrom = graph.getObjects(indexRoot, MOD.StructuralModel_CloneTypicalDiagramSymbolContributionsFrom); + if (compositeBaseType == null || diagramBaseType == null || masterCompositeType == null) { + ShowMessage.showInformation("No Typical Support", "Creation of typical diagrams is not supported for this container."); + return null; + } + + Resource compositeType = graph.newResource(); + graph.claim(compositeType, L0.Inherits, compositeBaseType); + String compositeTypeName = NameUtils.findFreshName(graph, "TypicalCompositeType", target); + graph.claimLiteral(compositeType, L0.HasName, compositeTypeName); + + Resource diagramType = graph.newResource(); + graph.claim(diagramType, L0.Inherits, diagramBaseType); + graph.claimLiteral(diagramType, L0.HasName, "Type"); + + String name = NameUtils.findFreshName(graph, "Typical", target, L0.ConsistsOf, "%s%d"); + + Resource composite = StructuralUtils.newComponent(graph, target, name + "@1", compositeType); + graph.claim(composite, L0.InstanceOf, null, masterCompositeType); + + Resource diagram = graph.newResource(); + graph.claim(diagram, L0.InstanceOf, null, diagramType); + graph.claimLiteral(diagram, L0.HasName, "__DIAGRAM__", Bindings.STRING); + graph.claim(diagram, L0.SubrelationOf, null, L0.HasNext); + graph.claim(diagram, MOD.DiagramToComposite, composite); + Resource diagramInv = graph.newResource(); + graph.claim(diagramInv, L0.InverseOf, diagram); + graph.claim(diagramInv, L0.SubrelationOf, null, L0.HasPrevious); + graph.claimLiteral(diagramInv, L0.HasName, "Inverse", Bindings.STRING); + graph.claim(diagram, L0.ConsistsOf, diagramInv); + graph.claim(diagram, diagram, diagramInv, diagram); + + Resource mapping = graph.newResource(); + graph.claim(diagram, L0X.HasTrigger, mapping); + graph.claim(mapping, L0.InstanceOf, null, MOD.DiagramToCompositeMapping); + + // Make diagram part of a dummy container entity attached to the parent + // composite if it's not already part of something. + Resource container = graph.newResource(); + graph.claim(container, L0.InstanceOf, null, DIA.DiagramContainer); + graph.addLiteral(container, L0.HasName, L0.NameOf, L0.String, "__CONTAINER__", Bindings.STRING); + + // Compose all created resources into the following hierarchy: + // Typical Composite : TypicalCompositeType + // Typical Composite Type : STR.CompositeType + // __CONTAINER__ : DIA.DiagramContainer + // "__DIAGRAM__" : "Type" + // "Type"