]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.modeling/src/org/simantics/modeling/flags/LiftFlag.java
Fixed all line endings of the repository
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / flags / LiftFlag.java
index dd668eb074b6c26ba0d1a525a710cc4a6fc7a60b..0ff83117868fec5ecb1fb05b2261a30925e9adc8 100644 (file)
-/*******************************************************************************\r
- * Copyright (c) 2012 Association for Decentralized Information Management in\r
- * 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.flags;\r
-\r
-import gnu.trove.set.hash.THashSet;\r
-\r
-import java.util.Collections;\r
-import java.util.Set;\r
-\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.databoard.annotations.Optional;\r
-import org.simantics.databoard.util.Bean;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.Statement;\r
-import org.simantics.db.WriteGraph;\r
-import org.simantics.db.common.utils.NameUtils;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.diagram.content.ConnectionUtil;\r
-import org.simantics.diagram.stubs.DiagramResource;\r
-import org.simantics.layer0.Layer0;\r
-import org.simantics.modeling.ModelingResources;\r
-import org.simantics.structural.stubs.StructuralResource2;\r
-import org.simantics.structural2.utils.StructuralUtils;\r
-import org.simantics.utils.ObjectUtils;\r
-\r
-/**\r
- * @author Hannu Niemistö\r
- * @author Tuukka Lehtonen\r
- */\r
-public class LiftFlag {\r
-\r
-    private static final boolean DEBUG = false;\r
-\r
-    public static class LiftedConnectionPoint extends Bean {\r
-        @Optional\r
-        public Resource component;\r
-        @Optional\r
-        public Resource componentType;\r
-        @Optional\r
-        public Resource connectionPoint;\r
-        /**\r
-         * Read through STR.HasAttachmentRelation from configuration connection\r
-         * point.\r
-         */\r
-        @Optional\r
-        public Resource attachmentRelation;\r
-    }\r
-\r
-    /**\r
-     * Creates a connection point for the flag. Returns null\r
-     * if the operation succeeded, otherwise returns an error message.\r
-     */\r
-    public static String liftFlag(WriteGraph g, Resource flag) throws DatabaseException {\r
-        Layer0 L0 = Layer0.getInstance(g);\r
-        StructuralResource2 STR = StructuralResource2.getInstance(g);\r
-        DiagramResource DIA = DiagramResource.getInstance(g);\r
-        ModelingResources MOD = ModelingResources.getInstance(g);\r
-\r
-        // Check preconditions\r
-        if (g.hasStatement(flag, STR.IsJoinedBy))\r
-            return "Flag is already connected to other flag.";\r
-        if (g.hasStatement(flag, DIA.IsLiftedAs))\r
-            return "Flag is already lifted.";\r
-\r
-        // Find configuration connection\r
-        Resource connection = findConfigurationConnection(g, flag);\r
-        if (connection == null)\r
-            return "Couldn't find configuration connection.";\r
-\r
-        // Find component and connection point\r
-        LiftedConnectionPoint lcp = calculateLiftedConnectionPointForConnection(g, connection);\r
-\r
-        // Validate calculated result\r
-        if (lcp.component == null)\r
-            return "Didn't find a component where the flag is connected to.";\r
-        if (lcp.componentType == null)\r
-            return "Didn't find an enclosing user component.";\r
-\r
-        // Generate default name\r
-        if (DEBUG)\r
-            System.out.println("found user component : " + NameUtils.getSafeName(g, lcp.componentType, true));\r
-        String newName = generateTerminalName(g, lcp);\r
-        newName = NameUtils.findFreshName(g, newName, lcp.componentType);\r
-\r
-        // Create the connection point\r
-        Resource connectionPoint = g.newResource();\r
-        Resource connectionPointInv = g.newResource();\r
-\r
-        for (Resource superrelation : g.getObjects(lcp.connectionPoint, L0.SubrelationOf)) {\r
-            g.claim(connectionPoint, L0.SubrelationOf, null, superrelation);\r
-            g.claim(connectionPointInv, L0.SubrelationOf, null, g.getInverse(superrelation));\r
-        }\r
-        for (Resource type : g.getObjects(lcp.connectionPoint, L0.InstanceOf)) {\r
-            g.claim(connectionPoint, L0.InstanceOf, null, type);\r
-        }\r
-        g.claim(connectionPoint, L0.InverseOf, connectionPointInv);\r
-        g.claimLiteral(connectionPoint, L0.HasName, newName, Bindings.STRING);\r
-        g.claim(connectionPoint, L0.ConsistsOf, connectionPointInv);\r
-        g.claimLiteral(connectionPointInv, L0.HasName, "Inverse", Bindings.STRING);\r
-        g.claim(connectionPoint, L0.HasDomain, lcp.componentType);\r
-\r
-        // Copy custom connection point terminal definitions from referenced\r
-        // lifted connection point. Assertions from types may also bring some\r
-        // definitions in already.\r
-        for (Statement terminalStm : g.getStatements(lcp.connectionPoint, MOD.ConnectionRelationToTerminal)) {\r
-            if (!terminalStm.isAsserted(lcp.connectionPoint)) {\r
-                g.claim(connectionPoint, MOD.ConnectionRelationToTerminal, terminalStm.getObject());\r
-            }\r
-        }\r
-\r
-        StructuralUtils.addConnectionPoint(g, lcp.componentType, connectionPoint);\r
-\r
-        g.claim(flag, DIA.IsLiftedAs, connectionPoint);\r
-        // This is now somewhat redundant, because statement is also added\r
-        // in mapping. But maybe flag is lifted when mapping is not active?\r
-        g.claim(connection, STR.Binds, connectionPoint);\r
-\r
-        // See platform issue https://www.simantics.org/redmine/issues/3482\r
-        if (lcp.attachmentRelation != null)\r
-            g.claim(connectionPoint, STR.HasAttachmentRelation, lcp.attachmentRelation);\r
-\r
-        g.claim(lcp.componentType, L0.ConsistsOf, connectionPoint);\r
-\r
-        return null;\r
-    }\r
-\r
-    /**\r
-     * @param g\r
-     * @param element\r
-     * @return\r
-     * @throws DatabaseException\r
-     */\r
-    public static Resource findConfigurationConnection(ReadGraph g, Resource element) throws DatabaseException {\r
-        StructuralResource2 STR = StructuralResource2.getInstance(g);\r
-        ModelingResources MOD = ModelingResources.getInstance(g);\r
-\r
-        for (Resource connector : g.getObjects(element, STR.IsConnectedTo)) {\r
-            Resource diagramConnection = ConnectionUtil.tryGetConnection(g, connector);\r
-            if (diagramConnection != null) {\r
-                Resource connection = g.getPossibleObject(diagramConnection, MOD.DiagramConnectionToConnection);\r
-                if (connection != null)\r
-                    return connection;\r
-            }\r
-            Resource mappedConnection = ConnectionUtil.tryGetMappedConnection(g, connector);\r
-            if(mappedConnection != null) return mappedConnection;\r
-        }\r
-        return null;\r
-    }\r
-\r
-    /**\r
-     * @param g\r
-     * @param lcp\r
-     * @return\r
-     * @throws DatabaseException \r
-     */\r
-    public static String generateTerminalName(ReadGraph g, LiftedConnectionPoint lcp) throws DatabaseException {\r
-        String componentName = NameUtils.getSafeName(g, lcp.component);\r
-        String cpName = NameUtils.getSafeName(g, lcp.connectionPoint);\r
-\r
-        StringBuilder sb = new StringBuilder();\r
-\r
-        // NOTE: NameUtils.getSafeName never returns null so part of this logic below is a bit useless.\r
-        if (componentName == null) {\r
-            if (cpName == null)\r
-                sb.append("ConnectionPoint");\r
-            else\r
-                sb.append("Lifted").append(cpName);\r
-        }\r
-        else {\r
-            if (cpName == null)\r
-                sb.append(componentName).append("Lifted");\r
-            else\r
-                sb.append(componentName).append("_").append(cpName);\r
-        }\r
-\r
-        return sb.toString();\r
-    }\r
-\r
-    /**\r
-     * @param graph\r
-     * @param flag\r
-     * @return\r
-     * @throws DatabaseException\r
-     */\r
-    public static LiftedConnectionPoint calculateLiftedConnectionPointForFlag(ReadGraph graph, Resource flag)\r
-            throws DatabaseException {\r
-        Resource connection = findConfigurationConnection(graph, flag);\r
-        return connection == null\r
-                ? new LiftedConnectionPoint()\r
-                : calculateLiftedConnectionPointForConnection(graph, connection);\r
-    }\r
-\r
-    /**\r
-     * @param graph\r
-     * @param connection\r
-     * @return\r
-     * @throws DatabaseException\r
-     */\r
-    public static LiftedConnectionPoint calculateLiftedConnectionPointForConnection(ReadGraph graph, Resource connection)\r
-            throws DatabaseException {\r
-        Layer0 L0 = Layer0.getInstance(graph);\r
-        DiagramResource DIA = DiagramResource.getInstance(graph);\r
-        ModelingResources MOD = ModelingResources.getInstance(graph);\r
-        StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
-\r
-        if (DEBUG)\r
-            System.out.println("calculateLiftedConnectionPoint from connection: " + NameUtils.getSafeName(graph, connection, true));\r
-\r
-        LiftedConnectionPoint result = new LiftedConnectionPoint();\r
-\r
-        findOutputTerminal: for (Statement stat : graph.getStatements(connection, STR.Connects)) {\r
-            result.component = stat.getObject();\r
-            result.connectionPoint = graph.getInverse(stat.getPredicate());\r
-            result.attachmentRelation = graph.getPossibleObject(result.connectionPoint, STR.HasAttachmentRelation);\r
-\r
-            if (DEBUG)\r
-                System.out.println("  connection point " + NameUtils.getSafeName(graph, result.connectionPoint, true)\r
-                        + " connects component " + NameUtils.getSafeName(graph, result.component, true)\r
-                        + " with attachment " + NameUtils.getSafeName(graph, result.attachmentRelation));\r
-\r
-            // This code tries to find component and connector behind signals\r
-            Resource connector = graph.getPossibleObject(result.component, MOD.ComponentToConnector);\r
-            if (connector != null) {\r
-                if (DEBUG)\r
-                    System.out.println("connector: " + NameUtils.getSafeName(graph, connector, true));\r
-\r
-                for (Statement s : graph.getStatements(connector, STR.Connects)) {\r
-                    Resource element = s.getObject();\r
-                    Resource diagramRelation = graph.getInverse(s.getPredicate());\r
-                    Resource componentCandidate = graph.getPossibleObject(element, MOD.ElementToComponent);\r
-                    Resource cpCandidate = graph.getPossibleObject(diagramRelation, MOD.DiagramConnectionRelationToConnectionRelation);\r
-\r
-                    if (DEBUG) {\r
-                        System.out.println("element: " + NameUtils.getSafeName(graph, element, true));\r
-                        System.out.println("diagram connection relation: " + NameUtils.getSafeName(graph, diagramRelation, true));\r
-                        System.out.println("component candidate: " + NameUtils.getSafeName(graph, componentCandidate, true));\r
-                        System.out.println("connection point candidate: " + NameUtils.getSafeName(graph, cpCandidate, true));\r
-                    }\r
-\r
-                    if (componentCandidate != null && cpCandidate != null) {\r
-                        result.component = componentCandidate;\r
-                        result.connectionPoint = cpCandidate;\r
-                        result.attachmentRelation = graph.getPossibleObject(cpCandidate, STR.HasAttachmentRelation);\r
-\r
-                        if (DEBUG)\r
-                            System.out.println("attachmentRelation: " + NameUtils.getSafeName(graph, result.attachmentRelation));\r
-\r
-                        if (result.attachmentRelation != null\r
-                                && graph.isSubrelationOf(result.attachmentRelation, DIA.HasTailConnector))\r
-                            // Found an output terminal, this is the one we want.\r
-                            break findOutputTerminal;\r
-                    }\r
-                }\r
-            }\r
-        }\r
-\r
-        // Find component type\r
-        Resource componentType = null;\r
-        for (Resource curComponent = result.component; true;) {\r
-            componentType = graph.getPossibleObject(curComponent, STR.Defines);\r
-            if (componentType != null) {\r
-                result.componentType = componentType;\r
-                break;\r
-            }\r
-            curComponent = graph.getPossibleObject(curComponent, L0.PartOf);\r
-            if (curComponent == null)\r
-                break;  \r
-        }\r
-\r
-        return result;\r
-    }\r
-\r
-    /**\r
-     * @param graph\r
-     * @param componentType\r
-     * @param connectionPoint\r
-     * @param proper\r
-     * @return <code>null</code> if connection point is valid\r
-     * @throws DatabaseException\r
-     */\r
-    public static String isConnectionPointValid(ReadGraph graph, Resource componentType, Resource connectionPoint,\r
-            LiftedConnectionPoint proper) throws DatabaseException {\r
-        Layer0 L0 = Layer0.getInstance(graph);\r
-        DiagramResource DIA = DiagramResource.getInstance(graph);\r
-        ModelingResources MOD = ModelingResources.getInstance(graph);\r
-        StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
-\r
-        Resource existingHasAttachment = graph.getPossibleObject(connectionPoint, STR.HasAttachmentRelation);\r
-        if (!ObjectUtils.objectEquals(existingHasAttachment, proper.attachmentRelation))\r
-            return "Wrong connection point (" + connectionPoint + ") attachment relation: is " + existingHasAttachment\r
-                    + ", should be " + proper.attachmentRelation;\r
-\r
-        {\r
-            Set<Resource> existingTypes = new THashSet<Resource>(graph.getObjects(connectionPoint, L0.InstanceOf));\r
-            Set<Resource> properTypes = new THashSet<Resource>(proper.connectionPoint != null\r
-                    ? graph.getObjects(proper.connectionPoint, L0.InstanceOf)\r
-                            : Collections.<Resource>emptySet());\r
-            if (!existingTypes.equals(properTypes))\r
-                return "Incorrect connection point relation (" + connectionPoint + ") types (existing " + existingTypes + " vs. proper " + properTypes + ")";\r
-        }\r
-\r
-        Resource diagramConnectionPoint = graph.getPossibleObject(connectionPoint, MOD.ConnectionRelationToDiagramConnectionRelation);\r
-        if (diagramConnectionPoint != null) {\r
-            Set<Resource> existingTypes = new THashSet<Resource>(graph.getObjects(diagramConnectionPoint, L0.InstanceOf));\r
-            Set<Resource> properTypes = new THashSet<Resource>(proper.connectionPoint != null\r
-                    ? graph.getObjects(proper.connectionPoint, MOD.ImpliesDiagramConnectionRelationType)\r
-                            : Collections.<Resource>emptySet());\r
-            if (!existingTypes.equals(properTypes))\r
-                return "Incorrect diagram connection point relation (" + diagramConnectionPoint + ") types (existing " + existingTypes + " vs. proper " + properTypes + ")";\r
-\r
-            Set<Resource> properTerminalTypes = new THashSet<Resource>(graph.getObjects(connectionPoint, MOD.ConnectionRelationToTerminal));\r
-            for (Resource terminal : graph.getObjects(diagramConnectionPoint, DIA.HasConnectionPoint_Inverse)) {\r
-                Set<Resource> existingTerminalTypes = new THashSet<Resource>(graph.getObjects(terminal, L0.InstanceOf));\r
-                if (!existingTerminalTypes.equals(properTerminalTypes))\r
-                    return "Incorrect diagram connection point relation types (existing " + existingTypes + " vs. proper " + properTypes + ")";\r
-            }\r
-        }\r
-\r
-        return null;\r
-    }\r
-\r
-    /**\r
-     * @param graph\r
-     * @param componentType\r
-     * @param connectionPoint\r
-     * @param proper\r
-     * @return <code>null</code> if connection point was properly validated\r
-     * @throws DatabaseException\r
-     */\r
-    public static String validateConnectionPoint(WriteGraph graph, Resource componentType, Resource connectionPoint,\r
-            LiftedConnectionPoint proper) throws DatabaseException {\r
-\r
-        Layer0 L0 = Layer0.getInstance(graph);\r
-        DiagramResource DIA = DiagramResource.getInstance(graph);\r
-        ModelingResources MOD = ModelingResources.getInstance(graph);\r
-        StructuralResource2 STR = StructuralResource2.getInstance(graph);\r
-\r
-        // Fix HasAttachmentRelation of connectionPoint\r
-        Resource existingHasAttachment = graph.getPossibleObject(connectionPoint, STR.HasAttachmentRelation);\r
-        if (!ObjectUtils.objectEquals(existingHasAttachment, proper.attachmentRelation)) {\r
-            graph.deny(connectionPoint, STR.HasAttachmentRelation);\r
-            if (proper.attachmentRelation != null)\r
-                graph.claim(connectionPoint, STR.HasAttachmentRelation, proper.attachmentRelation);\r
-        }\r
-\r
-        // Fix InstanceOf's of connectionPoint\r
-        fixDirectTypes(graph, connectionPoint, proper.connectionPoint != null\r
-                ? new THashSet<Resource>( graph.getObjects(proper.connectionPoint, L0.InstanceOf) )\r
-                        : Collections.<Resource>emptySet());\r
-\r
-        // Fix InstanceOf's of connection point's diagram connection relation\r
-        Resource diagramConnectionPoint = graph.getPossibleObject(connectionPoint, MOD.ConnectionRelationToDiagramConnectionRelation);\r
-        if (diagramConnectionPoint != null) {\r
-            fixDirectTypes(graph, diagramConnectionPoint, proper.connectionPoint != null\r
-                    ? new THashSet<Resource>( graph.getObjects(proper.connectionPoint, MOD.ImpliesDiagramConnectionRelationType) )\r
-                            : Collections.<Resource>emptySet());\r
-\r
-            // Fix InstanceOf's of connection point's diagram connection relation's symbol terminal\r
-            Set<Resource> properTerminalTypes = new THashSet<Resource>(graph.getObjects(connectionPoint, MOD.ConnectionRelationToTerminal));\r
-            for (Resource terminal : graph.getObjects(diagramConnectionPoint, DIA.HasConnectionPoint_Inverse)) {\r
-                fixDirectTypes(graph, terminal, properTerminalTypes);\r
-            }\r
-        }\r
-\r
-        return null;\r
-    }\r
-\r
-    /**\r
-     * @param graph\r
-     * @param r\r
-     * @param properTypes\r
-     * @throws DatabaseException\r
-     */\r
-    private static void fixDirectTypes(WriteGraph graph, Resource r, Set<Resource> properTypes) throws DatabaseException {\r
-        Layer0 L0 = Layer0.getInstance(graph);\r
-        Set<Resource> existingTypes = new THashSet<Resource>( graph.getObjects(r, L0.InstanceOf) );\r
-        if (!existingTypes.equals(properTypes)) {\r
-            Set<Resource> addTypes = new THashSet<Resource>(properTypes);\r
-            properTypes.removeAll(existingTypes);\r
-            existingTypes.removeAll(properTypes);\r
-            for (Resource remove : existingTypes)\r
-                graph.deny(r, L0.InstanceOf, remove);\r
-            for (Resource add : addTypes)\r
-                graph.claim(r, L0.InstanceOf, null, add);\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.flags;
+
+import gnu.trove.set.hash.THashSet;
+
+import java.util.Collections;
+import java.util.Set;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.databoard.annotations.Optional;
+import org.simantics.databoard.util.Bean;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.Statement;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.utils.NameUtils;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.diagram.content.ConnectionUtil;
+import org.simantics.diagram.stubs.DiagramResource;
+import org.simantics.layer0.Layer0;
+import org.simantics.modeling.ModelingResources;
+import org.simantics.structural.stubs.StructuralResource2;
+import org.simantics.structural2.utils.StructuralUtils;
+import org.simantics.utils.ObjectUtils;
+
+/**
+ * @author Hannu Niemist&ouml;
+ * @author Tuukka Lehtonen
+ */
+public class LiftFlag {
+
+    private static final boolean DEBUG = false;
+
+    public static class LiftedConnectionPoint extends Bean {
+        @Optional
+        public Resource component;
+        @Optional
+        public Resource componentType;
+        @Optional
+        public Resource connectionPoint;
+        /**
+         * Read through STR.HasAttachmentRelation from configuration connection
+         * point.
+         */
+        @Optional
+        public Resource attachmentRelation;
+    }
+
+    /**
+     * Creates a connection point for the flag. Returns null
+     * if the operation succeeded, otherwise returns an error message.
+     */
+    public static String liftFlag(WriteGraph g, Resource flag) throws DatabaseException {
+        Layer0 L0 = Layer0.getInstance(g);
+        StructuralResource2 STR = StructuralResource2.getInstance(g);
+        DiagramResource DIA = DiagramResource.getInstance(g);
+        ModelingResources MOD = ModelingResources.getInstance(g);
+
+        // Check preconditions
+        if (g.hasStatement(flag, STR.IsJoinedBy))
+            return "Flag is already connected to other flag.";
+        if (g.hasStatement(flag, DIA.IsLiftedAs))
+            return "Flag is already lifted.";
+
+        // Find configuration connection
+        Resource connection = findConfigurationConnection(g, flag);
+        if (connection == null)
+            return "Couldn't find configuration connection.";
+
+        // Find component and connection point
+        LiftedConnectionPoint lcp = calculateLiftedConnectionPointForConnection(g, connection);
+
+        // Validate calculated result
+        if (lcp.component == null)
+            return "Didn't find a component where the flag is connected to.";
+        if (lcp.componentType == null)
+            return "Didn't find an enclosing user component.";
+
+        // Generate default name
+        if (DEBUG)
+            System.out.println("found user component : " + NameUtils.getSafeName(g, lcp.componentType, true));
+        String newName = generateTerminalName(g, lcp);
+        newName = NameUtils.findFreshName(g, newName, lcp.componentType);
+
+        // Create the connection point
+        Resource connectionPoint = g.newResource();
+        Resource connectionPointInv = g.newResource();
+
+        for (Resource superrelation : g.getObjects(lcp.connectionPoint, L0.SubrelationOf)) {
+            g.claim(connectionPoint, L0.SubrelationOf, null, superrelation);
+            g.claim(connectionPointInv, L0.SubrelationOf, null, g.getInverse(superrelation));
+        }
+        for (Resource type : g.getObjects(lcp.connectionPoint, L0.InstanceOf)) {
+            g.claim(connectionPoint, L0.InstanceOf, null, type);
+        }
+        g.claim(connectionPoint, L0.InverseOf, connectionPointInv);
+        g.claimLiteral(connectionPoint, L0.HasName, newName, Bindings.STRING);
+        g.claim(connectionPoint, L0.ConsistsOf, connectionPointInv);
+        g.claimLiteral(connectionPointInv, L0.HasName, "Inverse", Bindings.STRING);
+        g.claim(connectionPoint, L0.HasDomain, lcp.componentType);
+
+        // Copy custom connection point terminal definitions from referenced
+        // lifted connection point. Assertions from types may also bring some
+        // definitions in already.
+        for (Statement terminalStm : g.getStatements(lcp.connectionPoint, MOD.ConnectionRelationToTerminal)) {
+            if (!terminalStm.isAsserted(lcp.connectionPoint)) {
+                g.claim(connectionPoint, MOD.ConnectionRelationToTerminal, terminalStm.getObject());
+            }
+        }
+
+        StructuralUtils.addConnectionPoint(g, lcp.componentType, connectionPoint);
+
+        g.claim(flag, DIA.IsLiftedAs, connectionPoint);
+        // This is now somewhat redundant, because statement is also added
+        // in mapping. But maybe flag is lifted when mapping is not active?
+        g.claim(connection, STR.Binds, connectionPoint);
+
+        // See platform issue https://www.simantics.org/redmine/issues/3482
+        if (lcp.attachmentRelation != null)
+            g.claim(connectionPoint, STR.HasAttachmentRelation, lcp.attachmentRelation);
+
+        g.claim(lcp.componentType, L0.ConsistsOf, connectionPoint);
+
+        return null;
+    }
+
+    /**
+     * @param g
+     * @param element
+     * @return
+     * @throws DatabaseException
+     */
+    public static Resource findConfigurationConnection(ReadGraph g, Resource element) throws DatabaseException {
+        StructuralResource2 STR = StructuralResource2.getInstance(g);
+        ModelingResources MOD = ModelingResources.getInstance(g);
+
+        for (Resource connector : g.getObjects(element, STR.IsConnectedTo)) {
+            Resource diagramConnection = ConnectionUtil.tryGetConnection(g, connector);
+            if (diagramConnection != null) {
+                Resource connection = g.getPossibleObject(diagramConnection, MOD.DiagramConnectionToConnection);
+                if (connection != null)
+                    return connection;
+            }
+            Resource mappedConnection = ConnectionUtil.tryGetMappedConnection(g, connector);
+            if(mappedConnection != null) return mappedConnection;
+        }
+        return null;
+    }
+
+    /**
+     * @param g
+     * @param lcp
+     * @return
+     * @throws DatabaseException 
+     */
+    public static String generateTerminalName(ReadGraph g, LiftedConnectionPoint lcp) throws DatabaseException {
+        String componentName = NameUtils.getSafeName(g, lcp.component);
+        String cpName = NameUtils.getSafeName(g, lcp.connectionPoint);
+
+        StringBuilder sb = new StringBuilder();
+
+        // NOTE: NameUtils.getSafeName never returns null so part of this logic below is a bit useless.
+        if (componentName == null) {
+            if (cpName == null)
+                sb.append("ConnectionPoint");
+            else
+                sb.append("Lifted").append(cpName);
+        }
+        else {
+            if (cpName == null)
+                sb.append(componentName).append("Lifted");
+            else
+                sb.append(componentName).append("_").append(cpName);
+        }
+
+        return sb.toString();
+    }
+
+    /**
+     * @param graph
+     * @param flag
+     * @return
+     * @throws DatabaseException
+     */
+    public static LiftedConnectionPoint calculateLiftedConnectionPointForFlag(ReadGraph graph, Resource flag)
+            throws DatabaseException {
+        Resource connection = findConfigurationConnection(graph, flag);
+        return connection == null
+                ? new LiftedConnectionPoint()
+                : calculateLiftedConnectionPointForConnection(graph, connection);
+    }
+
+    /**
+     * @param graph
+     * @param connection
+     * @return
+     * @throws DatabaseException
+     */
+    public static LiftedConnectionPoint calculateLiftedConnectionPointForConnection(ReadGraph graph, Resource connection)
+            throws DatabaseException {
+        Layer0 L0 = Layer0.getInstance(graph);
+        DiagramResource DIA = DiagramResource.getInstance(graph);
+        ModelingResources MOD = ModelingResources.getInstance(graph);
+        StructuralResource2 STR = StructuralResource2.getInstance(graph);
+
+        if (DEBUG)
+            System.out.println("calculateLiftedConnectionPoint from connection: " + NameUtils.getSafeName(graph, connection, true));
+
+        LiftedConnectionPoint result = new LiftedConnectionPoint();
+
+        findOutputTerminal: for (Statement stat : graph.getStatements(connection, STR.Connects)) {
+            result.component = stat.getObject();
+            result.connectionPoint = graph.getInverse(stat.getPredicate());
+            result.attachmentRelation = graph.getPossibleObject(result.connectionPoint, STR.HasAttachmentRelation);
+
+            if (DEBUG)
+                System.out.println("  connection point " + NameUtils.getSafeName(graph, result.connectionPoint, true)
+                        + " connects component " + NameUtils.getSafeName(graph, result.component, true)
+                        + " with attachment " + NameUtils.getSafeName(graph, result.attachmentRelation));
+
+            // This code tries to find component and connector behind signals
+            Resource connector = graph.getPossibleObject(result.component, MOD.ComponentToConnector);
+            if (connector != null) {
+                if (DEBUG)
+                    System.out.println("connector: " + NameUtils.getSafeName(graph, connector, true));
+
+                for (Statement s : graph.getStatements(connector, STR.Connects)) {
+                    Resource element = s.getObject();
+                    Resource diagramRelation = graph.getInverse(s.getPredicate());
+                    Resource componentCandidate = graph.getPossibleObject(element, MOD.ElementToComponent);
+                    Resource cpCandidate = graph.getPossibleObject(diagramRelation, MOD.DiagramConnectionRelationToConnectionRelation);
+
+                    if (DEBUG) {
+                        System.out.println("element: " + NameUtils.getSafeName(graph, element, true));
+                        System.out.println("diagram connection relation: " + NameUtils.getSafeName(graph, diagramRelation, true));
+                        System.out.println("component candidate: " + NameUtils.getSafeName(graph, componentCandidate, true));
+                        System.out.println("connection point candidate: " + NameUtils.getSafeName(graph, cpCandidate, true));
+                    }
+
+                    if (componentCandidate != null && cpCandidate != null) {
+                        result.component = componentCandidate;
+                        result.connectionPoint = cpCandidate;
+                        result.attachmentRelation = graph.getPossibleObject(cpCandidate, STR.HasAttachmentRelation);
+
+                        if (DEBUG)
+                            System.out.println("attachmentRelation: " + NameUtils.getSafeName(graph, result.attachmentRelation));
+
+                        if (result.attachmentRelation != null
+                                && graph.isSubrelationOf(result.attachmentRelation, DIA.HasTailConnector))
+                            // Found an output terminal, this is the one we want.
+                            break findOutputTerminal;
+                    }
+                }
+            }
+        }
+
+        // Find component type
+        Resource componentType = null;
+        for (Resource curComponent = result.component; true;) {
+            componentType = graph.getPossibleObject(curComponent, STR.Defines);
+            if (componentType != null) {
+                result.componentType = componentType;
+                break;
+            }
+            curComponent = graph.getPossibleObject(curComponent, L0.PartOf);
+            if (curComponent == null)
+                break;  
+        }
+
+        return result;
+    }
+
+    /**
+     * @param graph
+     * @param componentType
+     * @param connectionPoint
+     * @param proper
+     * @return <code>null</code> if connection point is valid
+     * @throws DatabaseException
+     */
+    public static String isConnectionPointValid(ReadGraph graph, Resource componentType, Resource connectionPoint,
+            LiftedConnectionPoint proper) throws DatabaseException {
+        Layer0 L0 = Layer0.getInstance(graph);
+        DiagramResource DIA = DiagramResource.getInstance(graph);
+        ModelingResources MOD = ModelingResources.getInstance(graph);
+        StructuralResource2 STR = StructuralResource2.getInstance(graph);
+
+        Resource existingHasAttachment = graph.getPossibleObject(connectionPoint, STR.HasAttachmentRelation);
+        if (!ObjectUtils.objectEquals(existingHasAttachment, proper.attachmentRelation))
+            return "Wrong connection point (" + connectionPoint + ") attachment relation: is " + existingHasAttachment
+                    + ", should be " + proper.attachmentRelation;
+
+        {
+            Set<Resource> existingTypes = new THashSet<Resource>(graph.getObjects(connectionPoint, L0.InstanceOf));
+            Set<Resource> properTypes = new THashSet<Resource>(proper.connectionPoint != null
+                    ? graph.getObjects(proper.connectionPoint, L0.InstanceOf)
+                            : Collections.<Resource>emptySet());
+            if (!existingTypes.equals(properTypes))
+                return "Incorrect connection point relation (" + connectionPoint + ") types (existing " + existingTypes + " vs. proper " + properTypes + ")";
+        }
+
+        Resource diagramConnectionPoint = graph.getPossibleObject(connectionPoint, MOD.ConnectionRelationToDiagramConnectionRelation);
+        if (diagramConnectionPoint != null) {
+            Set<Resource> existingTypes = new THashSet<Resource>(graph.getObjects(diagramConnectionPoint, L0.InstanceOf));
+            Set<Resource> properTypes = new THashSet<Resource>(proper.connectionPoint != null
+                    ? graph.getObjects(proper.connectionPoint, MOD.ImpliesDiagramConnectionRelationType)
+                            : Collections.<Resource>emptySet());
+            if (!existingTypes.equals(properTypes))
+                return "Incorrect diagram connection point relation (" + diagramConnectionPoint + ") types (existing " + existingTypes + " vs. proper " + properTypes + ")";
+
+            Set<Resource> properTerminalTypes = new THashSet<Resource>(graph.getObjects(connectionPoint, MOD.ConnectionRelationToTerminal));
+            for (Resource terminal : graph.getObjects(diagramConnectionPoint, DIA.HasConnectionPoint_Inverse)) {
+                Set<Resource> existingTerminalTypes = new THashSet<Resource>(graph.getObjects(terminal, L0.InstanceOf));
+                if (!existingTerminalTypes.equals(properTerminalTypes))
+                    return "Incorrect diagram connection point relation types (existing " + existingTypes + " vs. proper " + properTypes + ")";
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * @param graph
+     * @param componentType
+     * @param connectionPoint
+     * @param proper
+     * @return <code>null</code> if connection point was properly validated
+     * @throws DatabaseException
+     */
+    public static String validateConnectionPoint(WriteGraph graph, Resource componentType, Resource connectionPoint,
+            LiftedConnectionPoint proper) throws DatabaseException {
+
+        Layer0 L0 = Layer0.getInstance(graph);
+        DiagramResource DIA = DiagramResource.getInstance(graph);
+        ModelingResources MOD = ModelingResources.getInstance(graph);
+        StructuralResource2 STR = StructuralResource2.getInstance(graph);
+
+        // Fix HasAttachmentRelation of connectionPoint
+        Resource existingHasAttachment = graph.getPossibleObject(connectionPoint, STR.HasAttachmentRelation);
+        if (!ObjectUtils.objectEquals(existingHasAttachment, proper.attachmentRelation)) {
+            graph.deny(connectionPoint, STR.HasAttachmentRelation);
+            if (proper.attachmentRelation != null)
+                graph.claim(connectionPoint, STR.HasAttachmentRelation, proper.attachmentRelation);
+        }
+
+        // Fix InstanceOf's of connectionPoint
+        fixDirectTypes(graph, connectionPoint, proper.connectionPoint != null
+                ? new THashSet<Resource>( graph.getObjects(proper.connectionPoint, L0.InstanceOf) )
+                        : Collections.<Resource>emptySet());
+
+        // Fix InstanceOf's of connection point's diagram connection relation
+        Resource diagramConnectionPoint = graph.getPossibleObject(connectionPoint, MOD.ConnectionRelationToDiagramConnectionRelation);
+        if (diagramConnectionPoint != null) {
+            fixDirectTypes(graph, diagramConnectionPoint, proper.connectionPoint != null
+                    ? new THashSet<Resource>( graph.getObjects(proper.connectionPoint, MOD.ImpliesDiagramConnectionRelationType) )
+                            : Collections.<Resource>emptySet());
+
+            // Fix InstanceOf's of connection point's diagram connection relation's symbol terminal
+            Set<Resource> properTerminalTypes = new THashSet<Resource>(graph.getObjects(connectionPoint, MOD.ConnectionRelationToTerminal));
+            for (Resource terminal : graph.getObjects(diagramConnectionPoint, DIA.HasConnectionPoint_Inverse)) {
+                fixDirectTypes(graph, terminal, properTerminalTypes);
+            }
+        }
+
+        return null;
+    }
+
+    /**
+     * @param graph
+     * @param r
+     * @param properTypes
+     * @throws DatabaseException
+     */
+    private static void fixDirectTypes(WriteGraph graph, Resource r, Set<Resource> properTypes) throws DatabaseException {
+        Layer0 L0 = Layer0.getInstance(graph);
+        Set<Resource> existingTypes = new THashSet<Resource>( graph.getObjects(r, L0.InstanceOf) );
+        if (!existingTypes.equals(properTypes)) {
+            Set<Resource> addTypes = new THashSet<Resource>(properTypes);
+            properTypes.removeAll(existingTypes);
+            existingTypes.removeAll(properTypes);
+            for (Resource remove : existingTypes)
+                graph.deny(r, L0.InstanceOf, remove);
+            for (Resource add : addTypes)
+                graph.claim(r, L0.InstanceOf, null, add);
+        }
+    }
+
+}