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