X-Git-Url: https://gerrit.simantics.org/r/gitweb?a=blobdiff_plain;f=bundles%2Forg.simantics.modeling%2Fsrc%2Forg%2Fsimantics%2Fmodeling%2Fflags%2FLiftFlag.java;h=0ff83117868fec5ecb1fb05b2261a30925e9adc8;hb=0ae2b770234dfc3cbb18bd38f324125cf0faca07;hp=dd668eb074b6c26ba0d1a525a710cc4a6fc7a60b;hpb=24e2b34260f219f0d1644ca7a138894980e25b14;p=simantics%2Fplatform.git diff --git a/bundles/org.simantics.modeling/src/org/simantics/modeling/flags/LiftFlag.java b/bundles/org.simantics.modeling/src/org/simantics/modeling/flags/LiftFlag.java index dd668eb07..0ff831178 100644 --- a/bundles/org.simantics.modeling/src/org/simantics/modeling/flags/LiftFlag.java +++ b/bundles/org.simantics.modeling/src/org/simantics/modeling/flags/LiftFlag.java @@ -1,398 +1,398 @@ -/******************************************************************************* - * 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ö - * @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 null 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 existingTypes = new THashSet(graph.getObjects(connectionPoint, L0.InstanceOf)); - Set properTypes = new THashSet(proper.connectionPoint != null - ? graph.getObjects(proper.connectionPoint, L0.InstanceOf) - : Collections.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 existingTypes = new THashSet(graph.getObjects(diagramConnectionPoint, L0.InstanceOf)); - Set properTypes = new THashSet(proper.connectionPoint != null - ? graph.getObjects(proper.connectionPoint, MOD.ImpliesDiagramConnectionRelationType) - : Collections.emptySet()); - if (!existingTypes.equals(properTypes)) - return "Incorrect diagram connection point relation (" + diagramConnectionPoint + ") types (existing " + existingTypes + " vs. proper " + properTypes + ")"; - - Set properTerminalTypes = new THashSet(graph.getObjects(connectionPoint, MOD.ConnectionRelationToTerminal)); - for (Resource terminal : graph.getObjects(diagramConnectionPoint, DIA.HasConnectionPoint_Inverse)) { - Set existingTerminalTypes = new THashSet(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 null 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( graph.getObjects(proper.connectionPoint, L0.InstanceOf) ) - : Collections.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( graph.getObjects(proper.connectionPoint, MOD.ImpliesDiagramConnectionRelationType) ) - : Collections.emptySet()); - - // Fix InstanceOf's of connection point's diagram connection relation's symbol terminal - Set properTerminalTypes = new THashSet(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 properTypes) throws DatabaseException { - Layer0 L0 = Layer0.getInstance(graph); - Set existingTypes = new THashSet( graph.getObjects(r, L0.InstanceOf) ); - if (!existingTypes.equals(properTypes)) { - Set addTypes = new THashSet(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); - } - } - -} +/******************************************************************************* + * 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ö + * @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 null 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 existingTypes = new THashSet(graph.getObjects(connectionPoint, L0.InstanceOf)); + Set properTypes = new THashSet(proper.connectionPoint != null + ? graph.getObjects(proper.connectionPoint, L0.InstanceOf) + : Collections.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 existingTypes = new THashSet(graph.getObjects(diagramConnectionPoint, L0.InstanceOf)); + Set properTypes = new THashSet(proper.connectionPoint != null + ? graph.getObjects(proper.connectionPoint, MOD.ImpliesDiagramConnectionRelationType) + : Collections.emptySet()); + if (!existingTypes.equals(properTypes)) + return "Incorrect diagram connection point relation (" + diagramConnectionPoint + ") types (existing " + existingTypes + " vs. proper " + properTypes + ")"; + + Set properTerminalTypes = new THashSet(graph.getObjects(connectionPoint, MOD.ConnectionRelationToTerminal)); + for (Resource terminal : graph.getObjects(diagramConnectionPoint, DIA.HasConnectionPoint_Inverse)) { + Set existingTerminalTypes = new THashSet(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 null 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( graph.getObjects(proper.connectionPoint, L0.InstanceOf) ) + : Collections.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( graph.getObjects(proper.connectionPoint, MOD.ImpliesDiagramConnectionRelationType) ) + : Collections.emptySet()); + + // Fix InstanceOf's of connection point's diagram connection relation's symbol terminal + Set properTerminalTypes = new THashSet(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 properTypes) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + Set existingTypes = new THashSet( graph.getObjects(r, L0.InstanceOf) ); + if (!existingTypes.equals(properTypes)) { + Set addTypes = new THashSet(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); + } + } + +}