+/*******************************************************************************\r
+ * Copyright (c) 2007, 2010 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.mapping;\r
+\r
+import java.util.ArrayList;\r
+import java.util.Collection;\r
+\r
+import org.simantics.Simantics;\r
+import org.simantics.db.ReadGraph;\r
+import org.simantics.db.Resource;\r
+import org.simantics.db.Session;\r
+import org.simantics.db.common.utils.NameUtils;\r
+import org.simantics.db.exception.DatabaseException;\r
+import org.simantics.db.request.Read;\r
+import org.simantics.diagram.stubs.DiagramResource;\r
+import org.simantics.layer0.Layer0;\r
+import org.simantics.layer0.utils.binaryPredicates.BinaryPredicateAdapter;\r
+import org.simantics.layer0.utils.binaryPredicates.IBinaryPredicate;\r
+import org.simantics.layer0.utils.binaryPredicates.InversePredicate;\r
+import org.simantics.layer0.utils.binaryPredicates.OrderedSetElementsPredicate;\r
+import org.simantics.layer0.utils.predicates.IUnaryPredicate;\r
+import org.simantics.layer0.utils.predicates.Negation;\r
+import org.simantics.layer0.utils.predicates.Type;\r
+import org.simantics.layer0.utils.predicates.UnaryTest;\r
+import org.simantics.layer0.utils.triggers.IModification;\r
+import org.simantics.mapping.constraint.instructions.IInstruction;\r
+import org.simantics.mapping.constraint.instructions.TypedBracketInstruction.CreationInstruction;\r
+import org.simantics.mapping.rule.instructions.IRuleInstruction;\r
+import org.simantics.modeling.ComponentUtils;\r
+import org.simantics.modeling.ModelingResources;\r
+import org.simantics.operation.Layer0X;\r
+import org.simantics.project.IProject;\r
+import org.simantics.structural.stubs.StructuralResource2;\r
+import org.simantics.utils.ObjectUtils;\r
+\r
+public class DiagramToCompositeMapping3 extends MappingBase {\r
+\r
+ static public int VARIABLE_COUNT = 0;\r
+ \r
+ final static protected int Diagram = VARIABLE_COUNT++;\r
+ final static protected int Configuration = VARIABLE_COUNT++;\r
+ final static protected int Element = VARIABLE_COUNT++;\r
+ final static protected int ElementType = VARIABLE_COUNT++;\r
+ final static protected int ComponentType = VARIABLE_COUNT++;\r
+ final static protected int Component = VARIABLE_COUNT++;\r
+ \r
+ final static protected int DiagramConnectionRelation = VARIABLE_COUNT++;\r
+ final static protected int DiagramConnectionRelation2 = VARIABLE_COUNT++;\r
+ final static protected int CElement = VARIABLE_COUNT++;\r
+ final static protected int ConnectionRelation = VARIABLE_COUNT++;\r
+ final static protected int Connector = VARIABLE_COUNT++;\r
+ final static protected int Connection = VARIABLE_COUNT++; \r
+ final static protected int Connection2 = VARIABLE_COUNT++; \r
+ final static protected int ConnectionType = VARIABLE_COUNT++;\r
+ final static protected int ConnectionRelation2 = VARIABLE_COUNT++;\r
+ final static protected int ConnectionRelation3 = VARIABLE_COUNT++;\r
+ final static protected int Component2 = VARIABLE_COUNT++;\r
+ final static protected int FlagType = VARIABLE_COUNT++;\r
+ final static protected int ConnectionDirection = VARIABLE_COUNT++;\r
+ final static protected int ConnectionJoin = VARIABLE_COUNT++;\r
+ final static protected int ConfigurationRoot = VARIABLE_COUNT++;\r
+ \r
+ final static protected int Join = VARIABLE_COUNT++;\r
+ final static protected int ConnectionMappingSpecification = VARIABLE_COUNT++;\r
+\r
+ protected Session session;\r
+ \r
+ protected Layer0 L0;\r
+ protected DiagramResource DIA;\r
+ protected ModelingResources MOD;\r
+ protected StructuralResource2 STR;\r
+ \r
+ protected IUnaryPredicate mapped;\r
+ protected IUnaryPredicate mappedFromConnector;\r
+ protected IUnaryPredicate external;\r
+ protected IUnaryPredicate inputFlag;\r
+ protected IUnaryPredicate hasOutputConnector;\r
+ protected IUnaryPredicate flagIsConnected;\r
+ protected IUnaryPredicate internalJoin;\r
+ protected IBinaryPredicate fromFlagToConnection;\r
+ \r
+ IRuleInstruction createMappingRule() throws DatabaseException { \r
+ L0 = Layer0.getInstance(session);\r
+ DIA = DiagramResource.getInstance(session);\r
+ MOD = ModelingResources.getInstance(session);\r
+ STR = StructuralResource2.getInstance(session);\r
+ mapped = new Tag(MOD.Mapped);\r
+ mappedFromConnector = new Tag(MOD.MappedFromConnector);\r
+ external = new Tag(DIA.ExternalFlag);\r
+ inputFlag = new UnaryTest() {\r
+ @Override\r
+ public boolean has(ReadGraph g, Resource resource) throws DatabaseException {\r
+ return g.hasStatement(resource, DIA.HasFlagType, DIA.FlagType_InputFlag);\r
+ }\r
+ };\r
+ hasOutputConnector = new UnaryTest() { \r
+ @Override\r
+ public boolean has(ReadGraph g, Resource resource) throws DatabaseException {\r
+ Resource connection = g.getPossibleObject(resource, MOD.DiagramConnectionToConnection);\r
+ if(connection == null)\r
+ return false;\r
+ for(Resource connectionRelation : g.getObjects(connection, STR.Binds)) {\r
+ if (!g.hasStatement(connectionRelation, MOD.GeneratesConnectionComponentInternally))\r
+ return false;\r
+ }\r
+ for(Resource join : g.getObjects(connection, STR.IsJoinedBy))\r
+ for(Resource connection2 : g.getObjects(join, STR.Joins))\r
+ if(!connection.equals(connection2) && g.hasStatement(connection, STR.Binds))\r
+ return false;\r
+ return true; \r
+ }\r
+ };\r
+ flagIsConnected = new UnaryTest() { \r
+ @Override\r
+ public boolean has(ReadGraph g, Resource resource) throws DatabaseException {\r
+ return g.hasStatement(resource, DIA.Flag_ConnectionPoint); \r
+ }\r
+ };\r
+ internalJoin = new UnaryTest() { \r
+ @Override\r
+ public boolean has(ReadGraph g, Resource resource) throws DatabaseException {\r
+ return g.getObjects(resource, STR.JoinsComposite).size() <= 1; \r
+ }\r
+ };\r
+ fromFlagToConnection = new BinaryPredicateAdapter() {\r
+ @Override\r
+ public boolean supportsGetObjects() {\r
+ return true;\r
+ }\r
+ \r
+ @Override\r
+ public Collection<Resource> getObjects(ReadGraph g, Resource flag)\r
+ throws DatabaseException {\r
+ ArrayList<Resource> result = new ArrayList<Resource>(2);\r
+ for(Resource connector : g.getObjects(flag, DIA.Flag_ConnectionPoint))\r
+ for(Resource routeGraph : g.getObjects(connector, DIA.IsConnectorOf))\r
+ if(!flag.equals(routeGraph)) \r
+ result.addAll(g.getObjects(routeGraph, MOD.DiagramConnectionToConnection));\r
+ return result;\r
+ }\r
+ };\r
+ return and(destructiveRule(), additiveRule());\r
+ } \r
+ \r
+ public CreationInstruction componentCreationInstruction(int component, int componentType, int configuration) {\r
+ return new NamingCreationInstruction(project, ConfigurationRoot, component, componentType, configuration);\r
+ }\r
+ \r
+ protected IRuleInstruction additiveRule() {\r
+ return \r
+ if_(bf(OrderedSetElementsPredicate.INSTANCE, Diagram, Element),\r
+ query(\r
+ if_(and(bf(L0.InstanceOf, Element, ElementType),\r
+ bf(MOD.SymbolToComponentType, ElementType, ComponentType)\r
+ ),\r
+ // If element type of the element has a corresponding component type\r
+ createComponentRule(),\r
+ \r
+ if_(b(DIA.Connection, Element),\r
+ createNormalConnectionRule(),\r
+ \r
+ if_(b(DIA.Flag, Element),\r
+ createFlagRule()\r
+ )\r
+ )\r
+ )\r
+ )\r
+ );\r
+ }\r
+ \r
+ protected IRuleInstruction destructiveRule() {\r
+ return and(\r
+ if_(bf(L0.ConsistsOf, Configuration, Component),\r
+ and(\r
+ if_(b(mapped, Component), // handle only mapped components\r
+ query(\r
+ if_(and(bf(MOD.ComponentToElement, Component, Element),\r
+ bf(new InversePredicate(OrderedSetElementsPredicate.INSTANCE), Element, Diagram), \r
+ b(implies(new Type(DIA.Flag), and(external, flagIsConnected)), Element),\r
+ b(implies(new Type(DIA.Connection), hasOutputConnector), Element)\r
+ ),\r
+ // If component has a corresponding element in the diagram\r
+ if_(and(statement_bff(Component, ConnectionRelation, Connection, STR.IsConnectedTo),\r
+ b(mapped, Connection)\r
+ ),\r
+ destructiveConnectionRule()\r
+ ),\r
+ // If component does not have a corresponding element in the diagram, remove it\r
+ and(deny(b(new Tag(MOD.ComponentToElement), Component)), deny(exists(Component)))\r
+ )\r
+ )\r
+ ),\r
+ if_(b(mappedFromConnector, Component), // handle only mapped components\r
+ query(\r
+ unless(bf(MOD.ComponentToConnector, Component, Connector),\r
+ and(deny(b(new Tag(MOD.ComponentToElement), Component)), deny(exists(Component)))\r
+ )\r
+ )\r
+ )\r
+ )\r
+ ),\r
+ // Destroy connections \r
+ if_(and(bf(STR.HasConnectionJoin, Configuration, Join),\r
+ b(internalJoin, Join),\r
+ bf(STR.Joins, Join, Connection), \r
+ b(mapped, Connection)),\r
+ unless(and(bf(MOD.ConnectionMapsTo, Connection, Connection2),\r
+ or(b(new Negation(new Tag(MOD.ConnectionToDiagramConnectionSpecial)), Connection),\r
+ b(new Tag(MOD.ElementToComponent), Connection2)\r
+ )\r
+ ),\r
+ and(deny(b(new Tag(MOD.ConnectionMapsTo), Connection)), deny(exists(Connection)))\r
+ )\r
+ ),\r
+ if_(and(bf(STR.HasConnectionJoin, Configuration, Join),\r
+ bf(STR.Joins, Join, Connection), \r
+ b(mapped, Connection), \r
+ b(not(new Tag(STR.Connects)), Connection),\r
+ b(not(new Tag(MOD.ConnectionMapsTo)), Connection)),\r
+ deny(exists(Connection))\r
+ ),\r
+ if_(and(bf(STR.HasConnectionJoin, Configuration, Join),\r
+ bf(STR.Joins, Join, Connection),\r
+ bf(MOD.ConnectionToDiagramConnection, Connection, Connection2)), \r
+ unless(and(\r
+ bf(DIA.HasConnector, Connection2, Connector),\r
+ bf(DIA.Flag_ConnectionPoint_Inverse, Connector, Element),\r
+ bb(DIA.FlagIsJoinedBy, Element, Join)\r
+ ),\r
+ deny(bb(STR.Joins, Join, Connection)))\r
+ ));\r
+ }\r
+ \r
+ protected IRuleInstruction destructiveConnectionRule() {\r
+ // If component has a mapped connection\r
+ return if_(\r
+ and(bf(MOD.ConnectionMapsTo, Connection, Connection2),\r
+ or(b(new Negation(new Tag(MOD.ConnectionToDiagramConnectionSpecial)), Connection),\r
+ b(new Tag(MOD.ElementToComponent), Connection2)\r
+ )\r
+ ),\r
+ unless(or(\r
+ new DiagramConnectionExistence(Element, ConnectionRelation, Connection2),\r
+ /*and(bf(MOD.ConnectionRelationToDiagramConnectionRelation, ConnectionRelation, DiagramConnectionRelation),\r
+ statement_bbf(Element, DiagramConnectionRelation, Connector),\r
+ bb(DIA.IsConnectorOf, Connector, Connection2)\r
+ ),*/\r
+ b(DIA.Connection, Element), \r
+ b(DIA.Flag, Element), /* This is not entirely correct.\r
+ It is new not possible to replace\r
+ a connection to an external signal \r
+ flag.\r
+ */\r
+ b(new Negation(new Tag(MOD.ConnectionRelationToDiagramConnectionRelation)), ConnectionRelation),\r
+ fb(MOD.HasReferenceRelation, CElement, ConnectionRelation)\r
+ ),\r
+ deny(statement(Component, ConnectionRelation, Connection))\r
+ ),\r
+ // If the configuration connection does not have a correspondence in the diagram remove it\r
+ and(deny(b(new Tag(MOD.ConnectionMapsTo), Connection)), deny(exists(Connection)))\r
+ );\r
+ }\r
+ \r
+ protected IRuleInstruction createComponentRule() { \r
+ return \r
+ claim(\r
+ // Create a component corresponding to element, if it does not exist, and name it.\r
+ exists(\r
+ bf(MOD.ElementToComponent, Element, Component),\r
+ componentCreationInstruction(Component, ComponentType, Configuration)\r
+ ), \r
+ bb(L0.InstanceOf, Component, ComponentType),\r
+ bb(L0.PartOf, Component, Configuration),\r
+ b(mapped, Component) // Mark the component mapped (for destructive rules)\r
+ );\r
+ }\r
+\r
+ IRuleInstruction createConnectionRule() {\r
+ return if_(\r
+ b(DIA.Connection, Element),\r
+ // If element is a connection\r
+ createNormalConnectionRule()\r
+ ); \r
+ }\r
+ \r
+ protected Resource getConfigurationConnectionType() {\r
+ return STR.Connection;\r
+ }\r
+ \r
+ protected IInstruction claimBasicConnection() {\r
+ return and(exists(\r
+ bf(MOD.DiagramConnectionToConnection, Element, Connection),\r
+ Connection\r
+ ),\r
+ b(getConfigurationConnectionType(), Connection),\r
+ b(mapped, Connection)\r
+ );\r
+ }\r
+ \r
+ protected IRuleInstruction createNormalConnectionRule() {\r
+ return claim(claimBasicConnection(),\r
+ if_(and(bf(STR.IsConnectedTo, Element, Connector),\r
+ statement_ffb(CElement, DiagramConnectionRelation, Connector, STR.IsConnectedTo)\r
+ ),\r
+ \r
+ if_(and(bf(MOD.DiagramConnectionRelationToConnectionRelation, DiagramConnectionRelation, ConnectionRelation),\r
+ bf(MOD.ElementToComponent, CElement, Component)\r
+ ), \r
+ \r
+ // then\r
+ if_(or(and(bf(MOD.DiagramConnectionRelationToConnectionRelationB, DiagramConnectionRelation, ConnectionRelation2),\r
+ b(hasOutputConnector, Element),\r
+ bf(MOD.DiagramConnectionRelationToConnectionRelationC, DiagramConnectionRelation, ConnectionRelation3),\r
+ bf(MOD.DiagramConnectionRelationToComponentType, DiagramConnectionRelation, ComponentType)\r
+ ),\r
+ and(bf(MOD.HasConnectionMappingSpecification, Connector, ConnectionMappingSpecification),\r
+ b(hasOutputConnector, Element),\r
+ bf(MOD.DiagramConnectionRelationToConnectionRelationB, ConnectionMappingSpecification, ConnectionRelation2), \r
+ bf(MOD.DiagramConnectionRelationToConnectionRelationC, ConnectionMappingSpecification, ConnectionRelation3),\r
+ bf(MOD.DiagramConnectionRelationToComponentType, ConnectionMappingSpecification, ComponentType)\r
+ )\r
+ ),\r
+ \r
+ // then\r
+ claim(\r
+ // Create a component corresponding to connector, if it does not exist, and name it.\r
+ exists(\r
+ bf(MOD.ElementToComponent, Element, Component2),\r
+ new NamingCreationInstruction(project, ConfigurationRoot, Component2, ComponentType, Configuration)\r
+ ), \r
+ bb(L0.InstanceOf, Component2, ComponentType),\r
+ bb(L0.PartOf, Component2, Configuration),\r
+ bb(MOD.ConnectorToComponent, Connector, Component2),\r
+ b(mappedFromConnector, Component2), // Mark the component mapped (for destructive rules) \r
+ \r
+ // Create a connection\r
+ exists(\r
+ bf(MOD.DiagramConnectionToConnectionSpecial, Element, Connection2), \r
+ Connection2\r
+ ),\r
+ statement(Component2, ConnectionRelation2, Connection2),\r
+ statement(Component, ConnectionRelation, Connection2),\r
+ b(getConfigurationConnectionType(), Connection2),\r
+ b(mapped, Connection2),\r
+ \r
+ // \r
+ statement(Component2, ConnectionRelation3, Connection)\r
+ ),\r
+ \r
+ // else\r
+ claim(statement(Component, ConnectionRelation, Connection))\r
+ ), \r
+ \r
+ // else\r
+ if_(bf(MOD.HasReferenceRelation, CElement, ConnectionRelation),\r
+ if_(bf(MOD.HasParentComponent, CElement, Component),\r
+ // then\r
+ claim(statement(Component, ConnectionRelation, Connection)),\r
+ // else\r
+ claim(statement(CElement, ConnectionRelation, Connection))\r
+ )\r
+ )\r
+ )\r
+ )\r
+ );\r
+ }\r
+ \r
+ protected IRuleInstruction createFlagRule() {\r
+\r
+ return \r
+ and(\r
+ //print("Flag rule"),\r
+ if_(and(bf(DIA.FlagIsJoinedBy, Element, ConnectionJoin),\r
+ bf(compose(STR.IsConnectedTo, STR.Connects, MOD.DiagramConnectionToConnection), \r
+ Element, Connection) \r
+ ),\r
+ claim(\r
+ bb(STR.Joins, ConnectionJoin, Connection),\r
+ bb(STR.HasConnectionJoin, Configuration, ConnectionJoin)\r
+ ),\r
+ // This is maybe Apros specific \r
+ if_(and(b(and(external, inputFlag, flagIsConnected), Element),\r
+ bf(compose(STR.IsConnectedTo, STR.Connects), Element, Connection2),\r
+ bf(MOD.DiagramConnectionToConnection, Connection2, Connection),\r
+ bf(STR.HasConnectionType, Connection2, ConnectionType),\r
+ bf(MOD.ConnectionTypeToComponentType, ConnectionType, ComponentType),\r
+ bf(MOD.ConnectionTypeToConnectionRelation, ConnectionType, ConnectionRelation)\r
+ ),\r
+ claim(\r
+ exists(\r
+ bf(MOD.ElementToComponent, Element, Component),\r
+ new NamingCreationInstruction(project, ConfigurationRoot, Component, ComponentType, Configuration)\r
+ ),\r
+ bb(L0.InstanceOf, Component, ComponentType),\r
+ bb(L0.PartOf, Component, Configuration),\r
+ b(mapped, Component),\r
+ \r
+ statement(Component, ConnectionRelation, Connection)\r
+ )\r
+ )\r
+ ),\r
+ if_(and(bf(DIA.IsLiftedAs, Element, ConnectionRelation),\r
+ bf(fromFlagToConnection, Element, Connection)),\r
+ claim(\r
+ bb(STR.Binds, Connection, ConnectionRelation)\r
+ )\r
+ )\r
+ );\r
+ }\r
+\r
+ class RuleQuery implements Read<IRuleInstruction> {\r
+\r
+ @Override\r
+ public boolean equals(Object other) {\r
+ return other != null && other.getClass() == RuleQuery.class &&\r
+ getParentClass().equals(((RuleQuery)other).getParentClass());\r
+ }\r
+\r
+ private Class<? extends DiagramToCompositeMapping3> getParentClass() {\r
+ return DiagramToCompositeMapping3.this.getClass();\r
+ }\r
+\r
+ @Override\r
+ public int hashCode() {\r
+ return DiagramToCompositeMapping3.this.getClass().hashCode();\r
+ }\r
+\r
+ @Override\r
+ public IRuleInstruction perform(ReadGraph g) {\r
+ try {\r
+ return createMappingRule();\r
+ } catch (DatabaseException e) {\r
+ e.printStackTrace();\r
+ }\r
+ return null;\r
+ \r
+ }\r
+ \r
+ }\r
+ \r
+ IRuleInstruction instruction;\r
+ public Resource source;\r
+ public Resource target;\r
+ protected IProject project;\r
+ protected Resource configurationRoot;\r
+ \r
+ protected void setup(ReadGraph graph) {\r
+ \r
+ }\r
+ \r
+ public DiagramToCompositeMapping3(ReadGraph g, Resource mapping) throws DatabaseException {\r
+\r
+ setup(g);\r
+\r
+ this.session = g.getSession();\r
+\r
+ this.source = g.getPossibleObject(mapping, g.getInverse(Layer0X.getInstance(g).HasTrigger));\r
+ if (source != null)\r
+ this.target = g.getPossibleObject(this.source, ModelingResources.getInstance(g).DiagramToComposite);\r
+ if (target != null) {\r
+ configurationRoot = ComponentUtils.getCompositeConfigurationRoot(g, target);\r
+ assert configurationRoot != null;\r
+ }\r
+\r
+ this.project = Simantics.peekProject();\r
+ this.instruction = g.syncRequest(new RuleQuery());\r
+\r
+// System.out.println(this + "(mapping=" + mapping\r
+// + ", source=" + source\r
+// + ", target=" + target\r
+// + ", configurationRoot=" + configurationRoot\r
+// + ")");\r
+\r
+ }\r
+ \r
+ @Override\r
+ public boolean equals(Object other) {\r
+ if(this==other)\r
+ return true;\r
+ if(!(other instanceof DiagramToCompositeMapping3))\r
+ return false;\r
+ DiagramToCompositeMapping3 map = (DiagramToCompositeMapping3)other;\r
+ return ObjectUtils.objectEquals(map.source, source) && ObjectUtils.objectEquals(map.target, target);\r
+ }\r
+\r
+ @Override\r
+ public int hashCode() {\r
+ return ObjectUtils.hashCode(source) + 31 * ObjectUtils.hashCode(target);\r
+ }\r
+\r
+ @Override\r
+ public IModification perform(ReadGraph g) throws DatabaseException {\r
+// System.out.println(this + ": Find modification (source=" + source + ", target=" + target + ", configurationRoot=" + configurationRoot + ")");\r
+\r
+ if(IInstruction.DEBUG_MODI)\r
+ System.out.println("--- MAPPING ROUND -------------------------------- " + NameUtils.getURIOrSafeNameInternal(g, target));\r
+ \r
+ if (source == null || target == null)\r
+ return null;\r
+\r
+ final Object[] bindings = new Object[VARIABLE_COUNT];\r
+ bindings[Diagram] = source;\r
+ bindings[Configuration] = target;\r
+ bindings[ConfigurationRoot] = configurationRoot;\r
+ IModification modi = instruction.execute(g, bindings);\r
+ //System.out.println("modi = " + modi);\r
+ return modi;\r
+ }\r
+}\r