]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.modeling/src/org/simantics/modeling/typicals/TypicalUtil.java
Remove usage of deprecated SimanticsUI-methods
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / typicals / TypicalUtil.java
index e15f5036d9be684d25fe5f2e7d8b315b229f8b36..a92d7b62643d713ac3095f1d7df58966e8cb80f2 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2012 Association for Decentralized Information Management\r
- * in Industry THTH ry.\r
- * All rights reserved. This program and the accompanying materials\r
- * are made available under the terms of the Eclipse Public License v1.0\r
- * which accompanies this distribution, and is available at\r
- * http://www.eclipse.org/legal/epl-v10.html\r
- *\r
- * Contributors:\r
- *     VTT Technical Research Centre of Finland - initial API and implementation\r
- *******************************************************************************/\r
-package org.simantics.modeling.typicals;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.List;\r
-import java.util.Map;\r
-import java.util.Set;\r
-import java.util.concurrent.Semaphore;\r
-import java.util.concurrent.atomic.AtomicReference;\r
-import java.util.function.Consumer;\r
-\r
-import org.simantics.NameLabelMode;\r
-import org.simantics.NameLabelUtil;\r
-import org.simantics.Simantics;\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.RequestProcessor;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.WriteGraph;\r
-import org.simantics.db.WriteOnlyGraph;\r
-import org.simantics.db.common.CommentMetadata;\r
-import org.simantics.db.common.NamedResource;\r
-import org.simantics.db.common.request.FreshName;\r
-import org.simantics.db.common.request.ObjectsWithType;\r
-import org.simantics.db.common.request.PossibleIndexRoot;\r
-import org.simantics.db.common.request.UniqueRead;\r
-import org.simantics.db.common.request.WriteResultRequest;\r
-import org.simantics.db.common.uri.UnescapedChildMapOfResource;\r
-import org.simantics.db.common.utils.CommonDBUtils;\r
-import org.simantics.db.common.utils.NameUtils;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.exception.RuntimeDatabaseException;\r
-import org.simantics.db.layer0.adapter.CopyHandler;\r
-import org.simantics.db.layer0.adapter.Instances;\r
-import org.simantics.db.layer0.request.Configuration;\r
-import org.simantics.db.layer0.request.PossibleModel;\r
-import org.simantics.db.layer0.util.ClipboardUtils;\r
-import org.simantics.db.layer0.util.SimanticsClipboard.Representation;\r
-import org.simantics.db.layer0.util.SimanticsClipboardImpl;\r
-import org.simantics.db.layer0.util.SimanticsKeys;\r
-import org.simantics.db.layer0.variable.Variable;\r
-import org.simantics.db.layer0.variable.Variables;\r
-import org.simantics.db.procedure.Procedure;\r
-import org.simantics.db.request.WriteResult;\r
-import org.simantics.diagram.stubs.DiagramResource;\r
-import org.simantics.graph.db.IImportAdvisor;\r
-import org.simantics.graph.db.TransferableGraphs;\r
-import org.simantics.graph.representation.Root;\r
-import org.simantics.graph.representation.TransferableGraph1;\r
-import org.simantics.layer0.Layer0;\r
-import org.simantics.modeling.ModelingResources;\r
-import org.simantics.modeling.ModelingUtils.CompositeInfo;\r
-import org.simantics.modeling.ModelingUtils.DiagramComponentInfo;\r
-import org.simantics.modeling.services.ComponentNamingUtil;\r
-import org.simantics.modeling.services.NamingException;\r
-import org.simantics.operation.Layer0X;\r
-import org.simantics.scl.runtime.function.Function2;\r
-import org.simantics.scl.runtime.function.Function4;\r
-import org.simantics.structural.stubs.StructuralResource2;\r
-import org.simantics.structural2.utils.StructuralUtils;\r
-import org.simantics.ui.SimanticsUI;\r
-import org.simantics.utils.datastructures.Pair;\r
-import org.simantics.utils.ui.dialogs.ShowMessage;\r
-\r
-/**\r
- * @author Tuukka Lehtonen\r
- */\r
-public class TypicalUtil {\r
-\r
-    private static final boolean DEBUG = false;\r
-\r
-    private static class TypicalNamingFunction implements Function2<ReadGraph, Resource, String> {\r
-        private NameLabelMode mode;\r
-\r
-        @Override\r
-        public String apply(ReadGraph graph, Resource r) {\r
-            try {\r
-                if (mode == null)\r
-                    mode = NameLabelUtil.getNameLabelMode(graph);\r
-                Variable v = Variables.getPossibleVariable(graph, r);\r
-                if (v != null) {\r
-                    Resource root = Variables.getPossibleIndexRoot(graph, v);\r
-                    if (root != null) {\r
-                        Variable rootV = Variables.getVariable(graph, root);\r
-                        List<Variable> path = Variables.getPath(graph, rootV, v);\r
-                        path.add(0, rootV);\r
-                        return typicalLabel(graph, v, path);\r
-                    }\r
-                }\r
-                return TypicalUtil.getName(graph, r);\r
-            } catch (DatabaseException e) {\r
-                throw new RuntimeDatabaseException(e);\r
-            }\r
-        }\r
-\r
-        protected String typicalLabel(ReadGraph graph, Variable v, List<Variable> path) throws DatabaseException {\r
-            StringBuilder sb = new StringBuilder();\r
-            labelVariable(graph, v, sb);\r
-            if (path.size() > 0) {\r
-                sb.append(" (");\r
-                for (Variable vv : path) {\r
-                    sb.append("/");\r
-                    labelVariable(graph, vv, sb);\r
-                }\r
-                sb.append(")");\r
-            }\r
-            return sb.toString();\r
-        }\r
-\r
-        protected StringBuilder labelVariable(ReadGraph graph, Variable v, StringBuilder result) throws DatabaseException {\r
-            Resource r = v.getPossibleRepresents(graph);\r
-            if (r != null) {\r
-                result.append(NameLabelUtil.modalName(graph, r, mode));\r
-            } else {\r
-                result.append(NameLabelUtil.modalName(graph, v, mode));\r
-            }\r
-            return result;\r
-        }\r
-    };\r
-\r
-    public static Collection<NamedResource> toNamedResources(RequestProcessor processor, final Collection<Resource> rs) throws DatabaseException {\r
-        return toNamedResources(processor, rs, new TypicalNamingFunction());\r
-    }\r
-\r
-    public static Collection<NamedResource> toNamedResources(RequestProcessor processor, final Collection<Resource> rs, final Function2<ReadGraph, Resource, String> namingFunction) throws DatabaseException {\r
-        return processor.syncRequest(new UniqueRead<Collection<NamedResource>>() {\r
-            @Override\r
-            public Collection<NamedResource> perform(ReadGraph graph) throws DatabaseException {\r
-                return toNamedResources(graph, rs, namingFunction);\r
-            }\r
-        });\r
-    }\r
-\r
-    public static Collection<NamedResource> toNamedResources(ReadGraph graph, Collection<Resource> rs, final Function2<ReadGraph, Resource, String> namingFunction) throws DatabaseException {\r
-        Collection<NamedResource> result = new ArrayList<NamedResource>(rs.size());\r
-        for (Resource r : rs)\r
-            result.add(new NamedResource(namingFunction.apply(graph, r), r));\r
-        return result;\r
-    }\r
-\r
-    public static String getName(ReadGraph graph, Resource r) throws DatabaseException {\r
-        String s = graph.getPossibleAdapter(r, String.class);\r
-        if (s == null)\r
-            s = NameUtils.getSafeLabel(graph, r);\r
-        return s;\r
-    }\r
-\r
-    public static WriteResult<Resource> instantiateTemplate(final Resource target, final NamedResource template,\r
-            final Consumer<Pair<WriteGraph, Resource>> successContinuation) {\r
-        return new WriteResultRequest<Resource>() {\r
-            @Override\r
-            public Resource perform(WriteGraph graph) throws DatabaseException {\r
-                // Custom instantiation by copying the original and mapping the original to the copy\r
-               CommonDBUtils.selectClusterSet(graph, target);\r
-                SimanticsClipboardImpl clipboard = new SimanticsClipboardImpl();\r
-                CopyHandler ch = new TypicalCompositeCopyHandler(template.getResource());\r
-                ch.copyToClipboard(graph, clipboard);\r
-\r
-                Map<String,Object> hints = Collections.singletonMap(ClipboardUtils.HINT_TARGET_RESOURCE, target);\r
-\r
-                for (Set<Representation> object : clipboard.getContents()) {\r
-                    TransferableGraph1 tg = ClipboardUtils.accept(graph, object, SimanticsKeys.KEY_TRANSFERABLE_GRAPH, hints);\r
-                    if (tg != null) {\r
-                        DiagramPasteImportAdvisor advisor = new DiagramPasteImportAdvisor(graph, target, template.getName());\r
-                        TransferableGraphs.importGraph1(graph, tg, advisor);\r
-                        Resource copy = advisor.getRoot();\r
-\r
-                        configureCopyType(graph, copy, template.getResource());\r
-                        associateCopyToTemplate(graph, copy, template.getResource());\r
-\r
-                        if (successContinuation!= null)\r
-                            successContinuation.accept(Pair.make(graph, copy));\r
-\r
-                        return copy;\r
-                    }\r
-                }\r
-                throw new DatabaseException("Failed to instantiate typical template through clipboard");\r
-            }\r
-        };\r
-    }\r
-\r
-    public static void configureCopyType(WriteGraph graph, Resource copy, Resource template) throws DatabaseException {\r
-        // Remove master template instance tag type(s)\r
-        Layer0 L0 = Layer0.getInstance(graph);\r
-        DiagramResource DIA = DiagramResource.getInstance(graph);\r
-        ModelingResources MOD = ModelingResources.getInstance(graph);\r
-        for (Resource type : graph.getObjects(template, L0.InstanceOf)) {\r
-            if (graph.isInheritedFrom(type, MOD.MasterTypicalCompositeType))\r
-                graph.deny(copy, L0.InstanceOf, type);\r
-            else\r
-                graph.claim(copy, L0.InstanceOf, null, type);\r
-        }\r
-        for (Resource templateDiagram : graph.getObjects(template, MOD.CompositeToDiagram)) {\r
-            Resource templateDiagramType = graph.getPossibleType(templateDiagram, DIA.Diagram);\r
-            if (templateDiagramType != null) {\r
-                for (Resource copiedDiagram : graph.getObjects(copy, MOD.CompositeToDiagram)) {\r
-                    graph.claim(copiedDiagram, L0.InstanceOf, null, templateDiagramType);\r
-                }\r
-            }\r
-        }\r
-    }\r
-\r
-    public static void associateCopyToTemplate(WriteGraph graph, Resource copy, Resource template) throws DatabaseException {\r
-        DiagramResource DIA = DiagramResource.getInstance(graph);\r
-        ModelingResources MOD = ModelingResources.getInstance(graph);\r
-        Resource templateDiagram = graph.getSingleObject(template, MOD.CompositeToDiagram);\r
-        Resource copyDiagram = graph.getSingleObject(copy, MOD.CompositeToDiagram);\r
-        Map<String, Resource> templateDiagramElements = graph.syncRequest(new UnescapedChildMapOfResource(templateDiagram));\r
-        Map<String, Resource> copyDiagramElements = graph.syncRequest(new UnescapedChildMapOfResource(copyDiagram));\r
-\r
-        // Associations are intentionally bi-directional\r
-        graph.claim(copyDiagram, MOD.HasDiagramSource, MOD.DiagramHasInstance, templateDiagram);\r
-        for (String element : templateDiagramElements.keySet()) {\r
-            Resource templateElement = templateDiagramElements.get(element);\r
-            if (!graph.isInstanceOf(templateElement, DIA.Element))\r
-                continue;\r
-            Resource copyElement = copyDiagramElements.get(element);\r
-            graph.claim(copyElement, MOD.HasElementSource, MOD.ElementHasInstance, templateElement);\r
-            graph.claim(copyElement, MOD.IsTemplatized, MOD.IsTemplatized, copyElement);\r
-        }\r
-\r
-        Long modCount = graph.getPossibleRelatedValue(copyDiagram, DIA.HasModCount);\r
-        if (modCount == null)\r
-            modCount = 0L;\r
-        modCount += 1L << 32;\r
-        graph.claimLiteral(copyDiagram, DiagramResource.getInstance(graph).HasModCount, modCount, Bindings.LONG);\r
-    }\r
-\r
-    /**\r
-     * @param graph\r
-     * @param typicalCompositeInstance\r
-     * @param excludedComponents the set of components in the specified\r
-     *        composite that are not freshly renamed or <code>null</code> to\r
-     *        freshly name all components\r
-     * @throws DatabaseException\r
-     */\r
-    public static void generateFreshModuleNames(WriteGraph graph, Resource typicalCompositeInstance, Set<Resource> excludedComponents) throws DatabaseException {\r
-        Layer0 L0 = Layer0.getInstance(graph);\r
-        StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
-        Resource configurationRoot = graph.sync(new Configuration(typicalCompositeInstance));\r
-        for(Map.Entry<String, Resource> entry : graph.syncRequest(new UnescapedChildMapOfResource(typicalCompositeInstance)).entrySet()) {\r
-            Resource component = entry.getValue();\r
-            if (!graph.isInstanceOf(component, STR.Component))\r
-                continue;\r
-            if (excludedComponents != null && excludedComponents.contains(component))\r
-                continue;\r
-            try {\r
-                String renamed = ComponentNamingUtil.findFreshInstanceName(graph, SimanticsUI.getProject(), configurationRoot, typicalCompositeInstance, component);\r
-                if (DEBUG)\r
-                    System.out.println("Typicals: renamed " + entry.getKey() + " -> " + renamed);\r
-                graph.claimLiteral(entry.getValue(), L0.HasName, L0.NameOf, renamed, Bindings.STRING);\r
-            } catch (NamingException e) {\r
-                throw new DatabaseException(e);\r
-            }\r
-        }\r
-    }\r
-\r
-    public static class DiagramPasteImportAdvisor implements IImportAdvisor {\r
-\r
-        protected final Resource library;\r
-        protected final Resource model;\r
-        protected Resource diagram;\r
-        protected final String diagramName;\r
-\r
-        public DiagramPasteImportAdvisor(ReadGraph graph, Resource library, String originalName) throws DatabaseException {\r
-            this.library = library;\r
-            this.diagram = null;\r
-            this.diagramName = graph.syncRequest(new FreshName(library, originalName));\r
-            this.model = graph.syncRequest(new PossibleModel(library));\r
-        }\r
-\r
-        public void analyzeType(ReadGraph graph, Root root) throws DatabaseException {\r
-        }\r
-\r
-       @Override\r
-       public Resource analyzeRoot(ReadGraph graph, Root root) throws DatabaseException {\r
-               if("%model".equals(root.name)) return model;\r
-               return null;\r
-       }\r
-        @Override\r
-        public Resource createRoot(WriteOnlyGraph graph, Root root) throws DatabaseException {\r
-\r
-               Layer0 l0 = graph.getService(Layer0.class);\r
-            if(CompositeInfo.isComposite(root.name)) {\r
-                // Use existing if available\r
-                if(diagram == null) diagram = graph.newResource();\r
-                graph.claim(library, l0.ConsistsOf, l0.PartOf, diagram);\r
-                graph.newClusterSet(diagram);\r
-                graph.setClusterSet4NewResource(diagram);\r
-                graph.addLiteral(diagram, l0.HasName, l0.NameOf, l0.String, diagramName, Bindings.STRING);\r
-                return diagram;\r
-            } else if (DiagramComponentInfo.isDiagramComponent(root.name)) {\r
-               DiagramComponentInfo info = DiagramComponentInfo.parse(root.name);\r
-                Resource child = graph.newResource();\r
-                graph.addLiteral(child, l0.HasName, l0.NameOf, l0.String, info.getUnescapedComponentName(), Bindings.STRING);\r
-                return child;\r
-            } else {\r
-                throw new DatabaseException("Unclassified root " + root.name);\r
-            }\r
-\r
-        }\r
-\r
-        public Resource getRoot() {\r
-            return diagram;\r
-        }\r
-\r
-    }\r
-\r
-    /**\r
-     * @param graph\r
-     * @param typicalInstanceComposite\r
-     * @param renamedComponentsOutput a set that can be provided to get the set\r
-     *        of components that was renamed as output from this method or\r
-     *        <code>null</code> to not collect renamed components\r
-     * @throws DatabaseException\r
-     */\r
-    public static void applyTypicalModuleNames(WriteGraph graph, Resource typicalInstanceComposite, Set<Resource> renamedComponentsOutput) throws DatabaseException {\r
-       \r
-        Layer0 L0 = Layer0.getInstance(graph);\r
-        StructuralResource2 STR = StructuralResource2.getInstance(graph); \r
-\r
-        Function4<ReadGraph, Resource, Resource, String, String> nameEvaluator = getTypicalNamingFunction(graph, typicalInstanceComposite);\r
-        if (nameEvaluator == null)\r
-            return;\r
-\r
-        Collection<Resource> components = graph.syncRequest(new ObjectsWithType(typicalInstanceComposite, L0.ConsistsOf, STR.Component));\r
-        for (Resource component : components) {\r
-               applyTypicalModuleName(graph, component, nameEvaluator, renamedComponentsOutput);  \r
-        }\r
-        \r
-    }\r
-\r
-    public static boolean applyTypicalModuleName(WriteGraph graph, Resource instanceComponent, Function4<ReadGraph, Resource, Resource, String, String> nameEvaluator, Set<Resource> renamedComponentsOutput) throws DatabaseException {\r
-\r
-        Layer0 L0 = Layer0.getInstance(graph);\r
-        StructuralResource2 STR = StructuralResource2.getInstance(graph); \r
-        ModelingResources MOD = ModelingResources.getInstance(graph);\r
-\r
-        Resource componentType = graph.getPossibleType(instanceComponent, STR.Component);\r
-        if (componentType == null)\r
-            return false;\r
-\r
-        Resource instanceElement = graph.getPossibleObject(instanceComponent, MOD.ComponentToElement);\r
-        if (instanceElement == null)\r
-            return false;\r
-\r
-        Resource templateElement = graph.getPossibleObject(instanceElement, MOD.HasElementSource);\r
-        if (templateElement == null)\r
-            return false;\r
-\r
-        Resource templateComponent = graph.getPossibleObject(templateElement, MOD.ElementToComponent);\r
-        if (templateComponent == null)\r
-            return false;\r
-\r
-        // TODO: Use variables and EXPRESSION property instead ?\r
-        String nameExpression = graph.getPossibleRelatedValue(templateComponent, L0.HasName, Bindings.STRING);\r
-        if (nameExpression == null)\r
-            return false;\r
-\r
-        Resource instanceComposite = graph.getPossibleObject(instanceComponent, L0.PartOf);\r
-        if (instanceComposite == null)\r
-            return false;\r
-        \r
-        // This evaluator replaces % with assigned primary position name\r
-        String evaluatedInstanceName = (String) nameEvaluator.apply(graph, instanceComposite, instanceComponent, nameExpression);\r
-        if(evaluatedInstanceName == null)\r
-               return false;\r
-\r
-       String instanceName = graph.getPossibleRelatedValue(instanceComponent, L0.HasName, Bindings.STRING);\r
-       if(instanceName == null)\r
-               return false;\r
-\r
-       if(!evaluatedInstanceName.equals(instanceName)) {\r
-               \r
-            graph.claimLiteral(instanceComponent, L0.HasName, evaluatedInstanceName, Bindings.STRING);\r
-            if (renamedComponentsOutput != null)\r
-                renamedComponentsOutput.add(instanceComponent);\r
-            \r
-            if (DEBUG)\r
-               System.out.println("TypicalUtil.applyTypicalModuleName: applied name expression " + nameExpression + " -> " + instanceName + " -> " + evaluatedInstanceName);\r
-            \r
-            return true;\r
-               \r
-       }\r
-        \r
-        return false;\r
-       \r
-    }\r
-    \r
-    /**\r
-     * @param graph\r
-     * @param typicalComposite\r
-     * @param componentsToCheck the set of components to check for required\r
-     *        naming\r
-     * @throws DatabaseException\r
-     */\r
-    public static void applySelectedModuleNames(WriteGraph graph, Resource typicalComposite, List<Resource> componentsToCheck) throws DatabaseException {\r
-        Layer0 L0 = Layer0.getInstance(graph);\r
-        StructuralResource2 STR = StructuralResource2.getInstance(graph); \r
-        ModelingResources MOD = ModelingResources.getInstance(graph);\r
-\r
-        Function4<ReadGraph, Resource, Resource, String, String> nameEvaluator = getTypicalNamingFunction(graph, typicalComposite);\r
-        if (nameEvaluator == null)\r
-            return;\r
-\r
-        for (Resource component : componentsToCheck) {\r
-            Resource componentType = graph.getPossibleType(component, STR.Component);\r
-            if (componentType == null)\r
-                continue;\r
-\r
-            Resource element = graph.getPossibleObject(component, MOD.ComponentToElement);\r
-            if (element == null)\r
-                continue;\r
-\r
-            Resource templateElement = graph.getPossibleObject(element, MOD.HasElementSource);\r
-            if (templateElement == null)\r
-                continue;\r
-\r
-            Resource templateComponent = graph.getPossibleObject(templateElement, MOD.ElementToComponent);\r
-            if (templateComponent == null)\r
-                continue;\r
-\r
-            String nameExpression = graph.getPossibleRelatedValue(templateComponent, L0.HasName, Bindings.STRING);\r
-            if (nameExpression == null)\r
-                continue;\r
-\r
-            // NOTE: This assumes that nameEvaluator also makes sure that the\r
-            // evaluated names do not collide with any existing names in the\r
-            // model.\r
-            String evaluatedInstanceName = (String) nameEvaluator.apply(graph, typicalComposite, component, nameExpression);\r
-            if (evaluatedInstanceName != null && !evaluatedInstanceName.equals(nameExpression)) {\r
-                if (DEBUG)\r
-                    System.out.println("TypicalUtil.applySelectionModuleNames: applied name expression " + nameExpression + " -> " + evaluatedInstanceName);\r
-                graph.claimLiteral(component, L0.HasName, evaluatedInstanceName, Bindings.STRING);\r
-            }\r
-        }\r
-    }\r
-\r
-    /**\r
-     * @param graph\r
-     * @param typicalComposite\r
-     * @return f :: ReadGraph -> Resource composite -> Resource component -> String expression -> String name\r
-     * @throws DatabaseException\r
-     */\r
-    public static Function4<ReadGraph, Resource, Resource, String, String> getTypicalNamingFunction(ReadGraph graph, Resource typicalComposite) throws DatabaseException {\r
-        ModelingResources MOD = ModelingResources.getInstance(graph);\r
-        Function4<ReadGraph, Resource, Resource, String, String> nameEvaluator = graph.getPossibleRelatedValue2(typicalComposite, MOD.TypicalComposite_typicalNamingFunction);\r
-        return nameEvaluator;\r
-    }\r
-\r
-    /**\r
-     * @param processor\r
-     * @param model\r
-     * @return\r
-     * @throws DatabaseException\r
-     */\r
-    public static Collection<Resource> findModelTypicals(RequestProcessor processor, final Resource model) throws DatabaseException {\r
-        return processor.syncRequest(new UniqueRead<Collection<Resource>>() {\r
-            @Override\r
-            public Collection<Resource> perform(ReadGraph graph) throws DatabaseException {\r
-                ModelingResources MOD = ModelingResources.getInstance(graph);\r
-                Resource typicalMasterType = graph.getSingleObject(model, MOD.StructuralModel_HasMasterTypicalCompositeType);\r
-                Instances query = graph.adapt(typicalMasterType, Instances.class);\r
-                return query.find(graph, model);\r
-            }\r
-        });\r
-    }\r
-\r
-    /**\r
-     * A utility for synchronous execution of asynchronous procedures.\r
-     * @param runnable the callback that contains asynchronous execution\r
-     * @return the result received from the specified callback\r
-     * @throws DatabaseException\r
-     */\r
-    public static <T> T syncExec(Consumer<Procedure<T>> runnable) throws DatabaseException {\r
-        final AtomicReference<T> ref = new AtomicReference<T>();\r
-        final AtomicReference<Throwable> exc = new AtomicReference<Throwable>();\r
-        final Semaphore sem = new Semaphore(0);\r
-        runnable.accept(new Procedure<T>() {\r
-            @Override\r
-            public void execute(T result) {\r
-                if (ref.compareAndSet(null, result))\r
-                    sem.release();\r
-            }\r
-            @Override\r
-            public void exception(Throwable t) {\r
-                if (exc.compareAndSet(null, t))\r
-                    sem.release();\r
-            }\r
-        });\r
-        try {\r
-            sem.acquire();\r
-            Throwable t = exc.get();\r
-            if (t != null) {\r
-                if (t instanceof DatabaseException)\r
-                    throw (DatabaseException) t;\r
-                throw new DatabaseException(t);\r
-            } \r
-            return (T) ref.get();\r
-        } catch (InterruptedException ex) {\r
-            throw new DatabaseException(ex);\r
-        }\r
-    }\r
-    \r
-    /*\r
-     * SCL API\r
-     */\r
-    public static void syncTypicalInstance(WriteGraph graph, Resource instance) throws DatabaseException {\r
-       SyncTypicalTemplatesToInstances sync = SyncTypicalTemplatesToInstances.syncSingleInstance(null, instance);\r
-       sync.perform(graph);\r
-    }\r
-    \r
-    /**\r
-     * Creates a new master typical diagram and its corresponding composites.\r
-     * \r
-     * <p>\r
-     * The created typical composite and diagram type are specified by the model\r
-     * using {@link ModelingResources#StructuralModel_HasTypicalCompositeBaseType}\r
-     * and {@link ModelingResources#StructuralModel_HasTypicalDiagramBaseType}.\r
-     * \r
-     * <p>\r
-     * Marks the created master composite with the model-specified master composite\r
-     * type to support searching. The master type is specified by the model using\r
-     * {@link ModelingResources#StructuralModel_HasMasterTypicalCompositeType}.\r
-     * \r
-     * <p>\r
-     * Clones symbol contributions from the sources specified by the model through\r
-     * {@link ModelingResources#StructuralModel_CloneTypicalDiagramSymbolContributionsFrom}\r
-     * .\r
-     * \r
-     * @author Tuukka Lehtonen\r
-     */\r
-\r
-    public static Resource newMasterTypical(final Resource target) throws DatabaseException {\r
-       \r
-       return Simantics.getSession().syncRequest(new WriteResultRequest<Resource>() {\r
-       \r
-            @Override\r
-            public Resource perform(WriteGraph graph) throws DatabaseException {\r
-                Layer0 L0 = Layer0.getInstance(graph);\r
-                Layer0X L0X = Layer0X.getInstance(graph);\r
-                DiagramResource DIA = DiagramResource.getInstance(graph);\r
-                ModelingResources MOD = ModelingResources.getInstance(graph);\r
-\r
-                Resource indexRoot = graph.sync(new PossibleIndexRoot(target));\r
-                if (indexRoot == null) {\r
-                    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.");\r
-                    return null;\r
-                }\r
-\r
-                Resource compositeBaseType = graph.getPossibleObject(indexRoot, MOD.StructuralModel_HasTypicalCompositeBaseType);\r
-                Resource diagramBaseType = graph.getPossibleObject(indexRoot, MOD.StructuralModel_HasTypicalDiagramBaseType);\r
-                Resource masterCompositeType = graph.getPossibleObject(indexRoot, MOD.StructuralModel_HasMasterTypicalCompositeType);\r
-                Collection<Resource> cloneSymbolContributionsFrom = graph.getObjects(indexRoot, MOD.StructuralModel_CloneTypicalDiagramSymbolContributionsFrom);\r
-                if (compositeBaseType == null || diagramBaseType == null || masterCompositeType == null) {\r
-                    ShowMessage.showInformation("No Typical Support", "Creation of typical diagrams is not supported for this container.");\r
-                    return null;\r
-                }\r
-\r
-                Resource compositeType = graph.newResource();\r
-                graph.claim(compositeType, L0.Inherits, compositeBaseType);\r
-                String compositeTypeName = NameUtils.findFreshName(graph, "TypicalCompositeType", target);\r
-                graph.claimLiteral(compositeType, L0.HasName, compositeTypeName);\r
-\r
-                Resource diagramType = graph.newResource();\r
-                graph.claim(diagramType, L0.Inherits, diagramBaseType);\r
-                graph.claimLiteral(diagramType, L0.HasName, "Type");\r
-\r
-                String name = NameUtils.findFreshName(graph, "Typical", target, L0.ConsistsOf, "%s%d");\r
-\r
-                Resource composite = StructuralUtils.newComponent(graph, target, name + "@1", compositeType);\r
-                graph.claim(composite, L0.InstanceOf, null, masterCompositeType);\r
-\r
-                Resource diagram = graph.newResource();\r
-                graph.claim(diagram, L0.InstanceOf, null, diagramType);\r
-                graph.claimLiteral(diagram, L0.HasName, "__DIAGRAM__", Bindings.STRING);\r
-                graph.claim(diagram, L0.SubrelationOf, null, L0.HasNext);\r
-                graph.claim(diagram, MOD.DiagramToComposite, composite);\r
-                Resource diagramInv = graph.newResource();\r
-                graph.claim(diagramInv, L0.InverseOf, diagram);\r
-                graph.claim(diagramInv, L0.SubrelationOf, null, L0.HasPrevious);\r
-                graph.claimLiteral(diagramInv, L0.HasName, "Inverse", Bindings.STRING);\r
-                graph.claim(diagram, L0.ConsistsOf, diagramInv);\r
-                graph.claim(diagram, diagram, diagramInv, diagram);\r
-\r
-                Resource mapping = graph.newResource();\r
-                graph.claim(diagram, L0X.HasTrigger, mapping);\r
-                graph.claim(mapping, L0.InstanceOf, null, MOD.DiagramToCompositeMapping);\r
-\r
-                // Make diagram part of a dummy container entity attached to the parent\r
-                // composite if it's not already part of something.\r
-                Resource container = graph.newResource();\r
-                graph.claim(container, L0.InstanceOf, null, DIA.DiagramContainer);\r
-                graph.addLiteral(container, L0.HasName, L0.NameOf, L0.String, "__CONTAINER__", Bindings.STRING);\r
-\r
-                // Compose all created resources into the following hierarchy:\r
-                // Typical Composite : TypicalCompositeType\r
-                //     Typical Composite Type : STR.CompositeType\r
-                //     __CONTAINER__ : DIA.DiagramContainer\r
-                //         "__DIAGRAM__" : "Type"\r
-                //             "Type" <T DIA.Diagram\r
-                graph.claim(diagram, L0.ConsistsOf, diagramType);\r
-                graph.claim(container, L0.ConsistsOf, diagram);\r
-                graph.claim(composite, L0.ConsistsOf, container);\r
-                graph.claim(composite, L0.ConsistsOf, compositeType);\r
-\r
-                // Attach the same symbol contributions to the created typical\r
-                // diagram type as are attached to the model-designated\r
-                // contribution source diagram type.\r
-                boolean clonedIndexRootContribution = false;\r
-                for (Resource symbolContributionSource : cloneSymbolContributionsFrom) {\r
-                    for (Resource contribution : graph.getObjects(symbolContributionSource, DIA.HasSymbolContribution)) {\r
-                        graph.claim(diagramType, DIA.HasSymbolContribution, contribution);\r
-                        clonedIndexRootContribution |= graph.isInstanceOf(contribution, DIA.IndexRootSymbolContribution);\r
-                    }\r
-                }\r
-\r
-                if (!clonedIndexRootContribution) {\r
-                    Resource indexContribution = graph.newResource();\r
-                    graph.claim(indexContribution, L0.InstanceOf, DIA.IndexRootSymbolContribution);\r
-                    graph.claim(diagramType, DIA.HasSymbolContribution, indexContribution);\r
-                }\r
-\r
-                // Add comment to change set.\r
-                CommentMetadata cm = graph.getMetadata(CommentMetadata.class);\r
-                graph.addMetadata(cm.add("Created typical master diagram " + composite));\r
-\r
-                return composite;\r
-            }\r
-        });\r
-    \r
-    }\r
-}\r
-\r
+/*******************************************************************************
+ * 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<ReadGraph, Resource, String> {
+        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<Variable> 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<Variable> 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 List<NamedResource> toNamedResources(RequestProcessor processor, final Collection<Resource> rs) throws DatabaseException {
+        return toNamedResources(processor, rs, new TypicalNamingFunction());
+    }
+
+    public static List<NamedResource> toNamedResources(RequestProcessor processor, final Collection<Resource> rs, final Function2<ReadGraph, Resource, String> namingFunction) throws DatabaseException {
+        return processor.syncRequest(new UniqueRead<List<NamedResource>>() {
+            @Override
+            public List<NamedResource> perform(ReadGraph graph) throws DatabaseException {
+                return toNamedResources(graph, rs, namingFunction);
+            }
+        });
+    }
+
+    public static List<NamedResource> toNamedResources(ReadGraph graph, Collection<Resource> rs, final Function2<ReadGraph, Resource, String> namingFunction) throws DatabaseException {
+        List<NamedResource> 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<Resource> instantiateTemplate(
+            Resource target,
+            NamedResource template,
+            Consumer<Pair<WriteGraph, Resource>> successContinuation)
+    {
+        return new WriteResultRequest<Resource>() {
+            @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<String,Object> hints = Collections.singletonMap(ClipboardUtils.HINT_TARGET_RESOURCE, target);
+
+                for (Set<Representation> 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<String, Resource> templateDiagramElements = graph.syncRequest(new UnescapedChildMapOfResource(templateDiagram));
+        Map<String, Resource> 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 <code>null</code> to
+     *        freshly name all components
+     * @throws DatabaseException
+     */
+    public static void generateFreshModuleNames(WriteGraph graph, Resource typicalCompositeInstance, Set<Resource> excludedComponents) throws DatabaseException {
+        Layer0 L0 = Layer0.getInstance(graph);
+        StructuralResource2 STR = StructuralResource2.getInstance(graph);
+        Resource configurationRoot = graph.sync(new Configuration(typicalCompositeInstance));
+        for(Map.Entry<String, Resource> 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, Simantics.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
+     *        <code>null</code> to not collect renamed components
+     * @throws DatabaseException
+     */
+    public static void applyTypicalModuleNames(WriteGraph graph, Resource typicalInstanceComposite, Set<Resource> renamedComponentsOutput) throws DatabaseException {
+       
+        Layer0 L0 = Layer0.getInstance(graph);
+        StructuralResource2 STR = StructuralResource2.getInstance(graph); 
+
+        Function4<ReadGraph, Resource, Resource, String, String> nameEvaluator = getTypicalNamingFunction(graph, typicalInstanceComposite);
+        if (nameEvaluator == null)
+            return;
+
+        Collection<Resource> 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<ReadGraph, Resource, Resource, String, String> nameEvaluator, Set<Resource> 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<Resource> componentsToCheck) throws DatabaseException {
+        Layer0 L0 = Layer0.getInstance(graph);
+        StructuralResource2 STR = StructuralResource2.getInstance(graph); 
+        ModelingResources MOD = ModelingResources.getInstance(graph);
+
+        Function4<ReadGraph, Resource, Resource, String, String> 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<ReadGraph, Resource, Resource, String, String> getTypicalNamingFunction(ReadGraph graph, Resource typicalComposite) throws DatabaseException {
+        ModelingResources MOD = ModelingResources.getInstance(graph);
+        Function4<ReadGraph, Resource, Resource, String, String> nameEvaluator = graph.getPossibleRelatedValue2(typicalComposite, MOD.TypicalComposite_typicalNamingFunction);
+        return nameEvaluator;
+    }
+
+    /**
+     * @param processor
+     * @param model
+     * @return
+     * @throws DatabaseException
+     */
+    public static Collection<Resource> findModelTypicals(RequestProcessor processor, final Resource model) throws DatabaseException {
+        return processor.syncRequest(new UniqueRead<Collection<Resource>>() {
+            @Override
+            public Collection<Resource> 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> T syncExec(Consumer<Procedure<T>> runnable) throws DatabaseException {
+        final AtomicReference<T> ref = new AtomicReference<T>();
+        final AtomicReference<Throwable> exc = new AtomicReference<Throwable>();
+        final Semaphore sem = new Semaphore(0);
+        runnable.accept(new Procedure<T>() {
+            @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.
+     * 
+     * <p>
+     * The created typical composite and diagram type are specified by the model
+     * using {@link ModelingResources#StructuralModel_HasTypicalCompositeBaseType}
+     * and {@link ModelingResources#StructuralModel_HasTypicalDiagramBaseType}.
+     * 
+     * <p>
+     * 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}.
+     * 
+     * <p>
+     * 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<Resource>() {
+       
+            @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<Resource> 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" <T DIA.Diagram
+                graph.claim(diagram, L0.ConsistsOf, diagramType);
+                graph.claim(container, L0.ConsistsOf, diagram);
+                graph.claim(composite, L0.ConsistsOf, container);
+                graph.claim(composite, L0.ConsistsOf, compositeType);
+
+                // Attach the same symbol contributions to the created typical
+                // diagram type as are attached to the model-designated
+                // contribution source diagram type.
+                boolean clonedIndexRootContribution = false;
+                for (Resource symbolContributionSource : cloneSymbolContributionsFrom) {
+                    for (Resource contribution : graph.getObjects(symbolContributionSource, DIA.HasSymbolContribution)) {
+                        graph.claim(diagramType, DIA.HasSymbolContribution, contribution);
+                        clonedIndexRootContribution |= graph.isInstanceOf(contribution, DIA.IndexRootSymbolContribution);
+                    }
+                }
+
+                if (!clonedIndexRootContribution) {
+                    Resource indexContribution = graph.newResource();
+                    graph.claim(indexContribution, L0.InstanceOf, DIA.IndexRootSymbolContribution);
+                    graph.claim(diagramType, DIA.HasSymbolContribution, indexContribution);
+                }
+
+                // Add comment to change set.
+                CommentMetadata cm = graph.getMetadata(CommentMetadata.class);
+                graph.addMetadata(cm.add("Created typical master diagram " + composite));
+
+                return composite;
+            }
+        });
+    
+    }
+}
+