1 /*******************************************************************************
\r
2 * Copyright (c) 2007, 2010 Association for Decentralized Information Management
\r
3 * in Industry THTH ry.
\r
4 * All rights reserved. This program and the accompanying materials
\r
5 * are made available under the terms of the Eclipse Public License v1.0
\r
6 * which accompanies this distribution, and is available at
\r
7 * http://www.eclipse.org/legal/epl-v10.html
\r
10 * VTT Technical Research Centre of Finland - initial API and implementation
\r
11 *******************************************************************************/
\r
12 package org.simantics.modeling.mapping;
\r
14 import java.util.ArrayList;
\r
15 import java.util.Collection;
\r
17 import org.simantics.Simantics;
\r
18 import org.simantics.db.ReadGraph;
\r
19 import org.simantics.db.Resource;
\r
20 import org.simantics.db.Session;
\r
21 import org.simantics.db.common.utils.NameUtils;
\r
22 import org.simantics.db.exception.DatabaseException;
\r
23 import org.simantics.db.request.Read;
\r
24 import org.simantics.diagram.stubs.DiagramResource;
\r
25 import org.simantics.layer0.Layer0;
\r
26 import org.simantics.layer0.utils.binaryPredicates.BinaryPredicateAdapter;
\r
27 import org.simantics.layer0.utils.binaryPredicates.IBinaryPredicate;
\r
28 import org.simantics.layer0.utils.binaryPredicates.InversePredicate;
\r
29 import org.simantics.layer0.utils.binaryPredicates.OrderedSetElementsPredicate;
\r
30 import org.simantics.layer0.utils.predicates.IUnaryPredicate;
\r
31 import org.simantics.layer0.utils.predicates.Negation;
\r
32 import org.simantics.layer0.utils.predicates.Type;
\r
33 import org.simantics.layer0.utils.predicates.UnaryTest;
\r
34 import org.simantics.layer0.utils.triggers.IModification;
\r
35 import org.simantics.mapping.constraint.instructions.IInstruction;
\r
36 import org.simantics.mapping.constraint.instructions.TypedBracketInstruction.CreationInstruction;
\r
37 import org.simantics.mapping.rule.instructions.IRuleInstruction;
\r
38 import org.simantics.modeling.ComponentUtils;
\r
39 import org.simantics.modeling.ModelingResources;
\r
40 import org.simantics.operation.Layer0X;
\r
41 import org.simantics.project.IProject;
\r
42 import org.simantics.structural.stubs.StructuralResource2;
\r
43 import org.simantics.utils.ObjectUtils;
\r
45 public class DiagramToCompositeMapping3 extends MappingBase {
\r
47 static public int VARIABLE_COUNT = 0;
\r
49 final static protected int Diagram = VARIABLE_COUNT++;
\r
50 final static protected int Configuration = VARIABLE_COUNT++;
\r
51 final static protected int Element = VARIABLE_COUNT++;
\r
52 final static protected int ElementType = VARIABLE_COUNT++;
\r
53 final static protected int ComponentType = VARIABLE_COUNT++;
\r
54 final static protected int Component = VARIABLE_COUNT++;
\r
56 final static protected int DiagramConnectionRelation = VARIABLE_COUNT++;
\r
57 final static protected int DiagramConnectionRelation2 = VARIABLE_COUNT++;
\r
58 final static protected int CElement = VARIABLE_COUNT++;
\r
59 final static protected int ConnectionRelation = VARIABLE_COUNT++;
\r
60 final static protected int Connector = VARIABLE_COUNT++;
\r
61 final static protected int Connection = VARIABLE_COUNT++;
\r
62 final static protected int Connection2 = VARIABLE_COUNT++;
\r
63 final static protected int ConnectionType = VARIABLE_COUNT++;
\r
64 final static protected int ConnectionRelation2 = VARIABLE_COUNT++;
\r
65 final static protected int ConnectionRelation3 = VARIABLE_COUNT++;
\r
66 final static protected int Component2 = VARIABLE_COUNT++;
\r
67 final static protected int FlagType = VARIABLE_COUNT++;
\r
68 final static protected int ConnectionDirection = VARIABLE_COUNT++;
\r
69 final static protected int ConnectionJoin = VARIABLE_COUNT++;
\r
70 final static protected int ConfigurationRoot = VARIABLE_COUNT++;
\r
72 final static protected int Join = VARIABLE_COUNT++;
\r
73 final static protected int ConnectionMappingSpecification = VARIABLE_COUNT++;
\r
75 protected Session session;
\r
77 protected Layer0 L0;
\r
78 protected DiagramResource DIA;
\r
79 protected ModelingResources MOD;
\r
80 protected StructuralResource2 STR;
\r
82 protected IUnaryPredicate mapped;
\r
83 protected IUnaryPredicate mappedFromConnector;
\r
84 protected IUnaryPredicate external;
\r
85 protected IUnaryPredicate inputFlag;
\r
86 protected IUnaryPredicate hasOutputConnector;
\r
87 protected IUnaryPredicate flagIsConnected;
\r
88 protected IUnaryPredicate internalJoin;
\r
89 protected IBinaryPredicate fromFlagToConnection;
\r
91 IRuleInstruction createMappingRule() throws DatabaseException {
\r
92 L0 = Layer0.getInstance(session);
\r
93 DIA = DiagramResource.getInstance(session);
\r
94 MOD = ModelingResources.getInstance(session);
\r
95 STR = StructuralResource2.getInstance(session);
\r
96 mapped = new Tag(MOD.Mapped);
\r
97 mappedFromConnector = new Tag(MOD.MappedFromConnector);
\r
98 external = new Tag(DIA.ExternalFlag);
\r
99 inputFlag = new UnaryTest() {
\r
101 public boolean has(ReadGraph g, Resource resource) throws DatabaseException {
\r
102 return g.hasStatement(resource, DIA.HasFlagType, DIA.FlagType_InputFlag);
\r
105 hasOutputConnector = new UnaryTest() {
\r
107 public boolean has(ReadGraph g, Resource resource) throws DatabaseException {
\r
108 Resource connection = g.getPossibleObject(resource, MOD.DiagramConnectionToConnection);
\r
109 if(connection == null)
\r
111 for(Resource connectionRelation : g.getObjects(connection, STR.Binds)) {
\r
112 if (!g.hasStatement(connectionRelation, MOD.GeneratesConnectionComponentInternally))
\r
115 for(Resource join : g.getObjects(connection, STR.IsJoinedBy))
\r
116 for(Resource connection2 : g.getObjects(join, STR.Joins))
\r
117 if(!connection.equals(connection2) && g.hasStatement(connection, STR.Binds))
\r
122 flagIsConnected = new UnaryTest() {
\r
124 public boolean has(ReadGraph g, Resource resource) throws DatabaseException {
\r
125 return g.hasStatement(resource, DIA.Flag_ConnectionPoint);
\r
128 internalJoin = new UnaryTest() {
\r
130 public boolean has(ReadGraph g, Resource resource) throws DatabaseException {
\r
131 return g.getObjects(resource, STR.JoinsComposite).size() <= 1;
\r
134 fromFlagToConnection = new BinaryPredicateAdapter() {
\r
136 public boolean supportsGetObjects() {
\r
141 public Collection<Resource> getObjects(ReadGraph g, Resource flag)
\r
142 throws DatabaseException {
\r
143 ArrayList<Resource> result = new ArrayList<Resource>(2);
\r
144 for(Resource connector : g.getObjects(flag, DIA.Flag_ConnectionPoint))
\r
145 for(Resource routeGraph : g.getObjects(connector, DIA.IsConnectorOf))
\r
146 if(!flag.equals(routeGraph))
\r
147 result.addAll(g.getObjects(routeGraph, MOD.DiagramConnectionToConnection));
\r
151 return and(destructiveRule(), additiveRule());
\r
154 public CreationInstruction componentCreationInstruction(int component, int componentType, int configuration) {
\r
155 return new NamingCreationInstruction(project, ConfigurationRoot, component, componentType, configuration);
\r
158 protected IRuleInstruction additiveRule() {
\r
160 if_(bf(OrderedSetElementsPredicate.INSTANCE, Diagram, Element),
\r
162 if_(and(bf(L0.InstanceOf, Element, ElementType),
\r
163 bf(MOD.SymbolToComponentType, ElementType, ComponentType)
\r
165 // If element type of the element has a corresponding component type
\r
166 createComponentRule(),
\r
168 if_(b(DIA.Connection, Element),
\r
169 createNormalConnectionRule(),
\r
171 if_(b(DIA.Flag, Element),
\r
180 protected IRuleInstruction destructiveRule() {
\r
182 if_(bf(L0.ConsistsOf, Configuration, Component),
\r
184 if_(b(mapped, Component), // handle only mapped components
\r
186 if_(and(bf(MOD.ComponentToElement, Component, Element),
\r
187 bf(new InversePredicate(OrderedSetElementsPredicate.INSTANCE), Element, Diagram),
\r
188 b(implies(new Type(DIA.Flag), and(external, flagIsConnected)), Element),
\r
189 b(implies(new Type(DIA.Connection), hasOutputConnector), Element)
\r
191 // If component has a corresponding element in the diagram
\r
192 if_(and(statement_bff(Component, ConnectionRelation, Connection, STR.IsConnectedTo),
\r
193 b(mapped, Connection)
\r
195 destructiveConnectionRule()
\r
197 // If component does not have a corresponding element in the diagram, remove it
\r
198 and(deny(b(new Tag(MOD.ComponentToElement), Component)), deny(exists(Component)))
\r
202 if_(b(mappedFromConnector, Component), // handle only mapped components
\r
204 unless(bf(MOD.ComponentToConnector, Component, Connector),
\r
205 and(deny(b(new Tag(MOD.ComponentToElement), Component)), deny(exists(Component)))
\r
211 // Destroy connections
\r
212 if_(and(bf(STR.HasConnectionJoin, Configuration, Join),
\r
213 b(internalJoin, Join),
\r
214 bf(STR.Joins, Join, Connection),
\r
215 b(mapped, Connection)),
\r
216 unless(and(bf(MOD.ConnectionMapsTo, Connection, Connection2),
\r
217 or(b(new Negation(new Tag(MOD.ConnectionToDiagramConnectionSpecial)), Connection),
\r
218 b(new Tag(MOD.ElementToComponent), Connection2)
\r
221 and(deny(b(new Tag(MOD.ConnectionMapsTo), Connection)), deny(exists(Connection)))
\r
224 if_(and(bf(STR.HasConnectionJoin, Configuration, Join),
\r
225 bf(STR.Joins, Join, Connection),
\r
226 b(mapped, Connection),
\r
227 b(not(new Tag(STR.Connects)), Connection),
\r
228 b(not(new Tag(MOD.ConnectionMapsTo)), Connection)),
\r
229 deny(exists(Connection))
\r
231 if_(and(bf(STR.HasConnectionJoin, Configuration, Join),
\r
232 bf(STR.Joins, Join, Connection),
\r
233 bf(MOD.ConnectionToDiagramConnection, Connection, Connection2)),
\r
235 bf(DIA.HasConnector, Connection2, Connector),
\r
236 bf(DIA.Flag_ConnectionPoint_Inverse, Connector, Element),
\r
237 bb(DIA.FlagIsJoinedBy, Element, Join)
\r
239 deny(bb(STR.Joins, Join, Connection)))
\r
243 protected IRuleInstruction destructiveConnectionRule() {
\r
244 // If component has a mapped connection
\r
246 and(bf(MOD.ConnectionMapsTo, Connection, Connection2),
\r
247 or(b(new Negation(new Tag(MOD.ConnectionToDiagramConnectionSpecial)), Connection),
\r
248 b(new Tag(MOD.ElementToComponent), Connection2)
\r
252 new DiagramConnectionExistence(Element, ConnectionRelation, Connection2),
\r
253 /*and(bf(MOD.ConnectionRelationToDiagramConnectionRelation, ConnectionRelation, DiagramConnectionRelation),
\r
254 statement_bbf(Element, DiagramConnectionRelation, Connector),
\r
255 bb(DIA.IsConnectorOf, Connector, Connection2)
\r
257 b(DIA.Connection, Element),
\r
258 b(DIA.Flag, Element), /* This is not entirely correct.
\r
259 It is new not possible to replace
\r
260 a connection to an external signal
\r
263 b(new Negation(new Tag(MOD.ConnectionRelationToDiagramConnectionRelation)), ConnectionRelation),
\r
264 fb(MOD.HasReferenceRelation, CElement, ConnectionRelation)
\r
266 deny(statement(Component, ConnectionRelation, Connection))
\r
268 // If the configuration connection does not have a correspondence in the diagram remove it
\r
269 and(deny(b(new Tag(MOD.ConnectionMapsTo), Connection)), deny(exists(Connection)))
\r
273 protected IRuleInstruction createComponentRule() {
\r
276 // Create a component corresponding to element, if it does not exist, and name it.
\r
278 bf(MOD.ElementToComponent, Element, Component),
\r
279 componentCreationInstruction(Component, ComponentType, Configuration)
\r
281 bb(L0.InstanceOf, Component, ComponentType),
\r
282 bb(L0.PartOf, Component, Configuration),
\r
283 b(mapped, Component) // Mark the component mapped (for destructive rules)
\r
287 IRuleInstruction createConnectionRule() {
\r
289 b(DIA.Connection, Element),
\r
290 // If element is a connection
\r
291 createNormalConnectionRule()
\r
295 protected Resource getConfigurationConnectionType() {
\r
296 return STR.Connection;
\r
299 protected IInstruction claimBasicConnection() {
\r
301 bf(MOD.DiagramConnectionToConnection, Element, Connection),
\r
304 b(getConfigurationConnectionType(), Connection),
\r
305 b(mapped, Connection)
\r
309 protected IRuleInstruction createNormalConnectionRule() {
\r
310 return claim(claimBasicConnection(),
\r
311 if_(and(bf(STR.IsConnectedTo, Element, Connector),
\r
312 statement_ffb(CElement, DiagramConnectionRelation, Connector, STR.IsConnectedTo)
\r
315 if_(and(bf(MOD.DiagramConnectionRelationToConnectionRelation, DiagramConnectionRelation, ConnectionRelation),
\r
316 bf(MOD.ElementToComponent, CElement, Component)
\r
320 if_(or(and(bf(MOD.DiagramConnectionRelationToConnectionRelationB, DiagramConnectionRelation, ConnectionRelation2),
\r
321 b(hasOutputConnector, Element),
\r
322 bf(MOD.DiagramConnectionRelationToConnectionRelationC, DiagramConnectionRelation, ConnectionRelation3),
\r
323 bf(MOD.DiagramConnectionRelationToComponentType, DiagramConnectionRelation, ComponentType)
\r
325 and(bf(MOD.HasConnectionMappingSpecification, Connector, ConnectionMappingSpecification),
\r
326 b(hasOutputConnector, Element),
\r
327 bf(MOD.DiagramConnectionRelationToConnectionRelationB, ConnectionMappingSpecification, ConnectionRelation2),
\r
328 bf(MOD.DiagramConnectionRelationToConnectionRelationC, ConnectionMappingSpecification, ConnectionRelation3),
\r
329 bf(MOD.DiagramConnectionRelationToComponentType, ConnectionMappingSpecification, ComponentType)
\r
335 // Create a component corresponding to connector, if it does not exist, and name it.
\r
337 bf(MOD.ElementToComponent, Element, Component2),
\r
338 new NamingCreationInstruction(project, ConfigurationRoot, Component2, ComponentType, Configuration)
\r
340 bb(L0.InstanceOf, Component2, ComponentType),
\r
341 bb(L0.PartOf, Component2, Configuration),
\r
342 bb(MOD.ConnectorToComponent, Connector, Component2),
\r
343 b(mappedFromConnector, Component2), // Mark the component mapped (for destructive rules)
\r
345 // Create a connection
\r
347 bf(MOD.DiagramConnectionToConnectionSpecial, Element, Connection2),
\r
350 statement(Component2, ConnectionRelation2, Connection2),
\r
351 statement(Component, ConnectionRelation, Connection2),
\r
352 b(getConfigurationConnectionType(), Connection2),
\r
353 b(mapped, Connection2),
\r
356 statement(Component2, ConnectionRelation3, Connection)
\r
360 claim(statement(Component, ConnectionRelation, Connection))
\r
364 if_(bf(MOD.HasReferenceRelation, CElement, ConnectionRelation),
\r
365 if_(bf(MOD.HasParentComponent, CElement, Component),
\r
367 claim(statement(Component, ConnectionRelation, Connection)),
\r
369 claim(statement(CElement, ConnectionRelation, Connection))
\r
377 protected IRuleInstruction createFlagRule() {
\r
381 //print("Flag rule"),
\r
382 if_(and(bf(DIA.FlagIsJoinedBy, Element, ConnectionJoin),
\r
383 bf(compose(STR.IsConnectedTo, STR.Connects, MOD.DiagramConnectionToConnection),
\r
384 Element, Connection)
\r
387 bb(STR.Joins, ConnectionJoin, Connection),
\r
388 bb(STR.HasConnectionJoin, Configuration, ConnectionJoin)
\r
390 // This is maybe Apros specific
\r
391 if_(and(b(and(external, inputFlag, flagIsConnected), Element),
\r
392 bf(compose(STR.IsConnectedTo, STR.Connects), Element, Connection2),
\r
393 bf(MOD.DiagramConnectionToConnection, Connection2, Connection),
\r
394 bf(STR.HasConnectionType, Connection2, ConnectionType),
\r
395 bf(MOD.ConnectionTypeToComponentType, ConnectionType, ComponentType),
\r
396 bf(MOD.ConnectionTypeToConnectionRelation, ConnectionType, ConnectionRelation)
\r
400 bf(MOD.ElementToComponent, Element, Component),
\r
401 new NamingCreationInstruction(project, ConfigurationRoot, Component, ComponentType, Configuration)
\r
403 bb(L0.InstanceOf, Component, ComponentType),
\r
404 bb(L0.PartOf, Component, Configuration),
\r
405 b(mapped, Component),
\r
407 statement(Component, ConnectionRelation, Connection)
\r
411 if_(and(bf(DIA.IsLiftedAs, Element, ConnectionRelation),
\r
412 bf(fromFlagToConnection, Element, Connection)),
\r
414 bb(STR.Binds, Connection, ConnectionRelation)
\r
420 class RuleQuery implements Read<IRuleInstruction> {
\r
423 public boolean equals(Object other) {
\r
424 return other != null && other.getClass() == RuleQuery.class &&
\r
425 getParentClass().equals(((RuleQuery)other).getParentClass());
\r
428 private Class<? extends DiagramToCompositeMapping3> getParentClass() {
\r
429 return DiagramToCompositeMapping3.this.getClass();
\r
433 public int hashCode() {
\r
434 return DiagramToCompositeMapping3.this.getClass().hashCode();
\r
438 public IRuleInstruction perform(ReadGraph g) {
\r
440 return createMappingRule();
\r
441 } catch (DatabaseException e) {
\r
442 e.printStackTrace();
\r
450 IRuleInstruction instruction;
\r
451 public Resource source;
\r
452 public Resource target;
\r
453 protected IProject project;
\r
454 protected Resource configurationRoot;
\r
456 protected void setup(ReadGraph graph) {
\r
460 public DiagramToCompositeMapping3(ReadGraph g, Resource mapping) throws DatabaseException {
\r
464 this.session = g.getSession();
\r
466 this.source = g.getPossibleObject(mapping, g.getInverse(Layer0X.getInstance(g).HasTrigger));
\r
467 if (source != null)
\r
468 this.target = g.getPossibleObject(this.source, ModelingResources.getInstance(g).DiagramToComposite);
\r
469 if (target != null) {
\r
470 configurationRoot = ComponentUtils.getCompositeConfigurationRoot(g, target);
\r
471 assert configurationRoot != null;
\r
474 this.project = Simantics.peekProject();
\r
475 this.instruction = g.syncRequest(new RuleQuery());
\r
477 // System.out.println(this + "(mapping=" + mapping
\r
478 // + ", source=" + source
\r
479 // + ", target=" + target
\r
480 // + ", configurationRoot=" + configurationRoot
\r
486 public boolean equals(Object other) {
\r
489 if(!(other instanceof DiagramToCompositeMapping3))
\r
491 DiagramToCompositeMapping3 map = (DiagramToCompositeMapping3)other;
\r
492 return ObjectUtils.objectEquals(map.source, source) && ObjectUtils.objectEquals(map.target, target);
\r
496 public int hashCode() {
\r
497 return ObjectUtils.hashCode(source) + 31 * ObjectUtils.hashCode(target);
\r
501 public IModification perform(ReadGraph g) throws DatabaseException {
\r
502 // System.out.println(this + ": Find modification (source=" + source + ", target=" + target + ", configurationRoot=" + configurationRoot + ")");
\r
504 if(IInstruction.DEBUG_MODI)
\r
505 System.out.println("--- MAPPING ROUND -------------------------------- " + NameUtils.getURIOrSafeNameInternal(g, target));
\r
507 if (source == null || target == null)
\r
510 final Object[] bindings = new Object[VARIABLE_COUNT];
\r
511 bindings[Diagram] = source;
\r
512 bindings[Configuration] = target;
\r
513 bindings[ConfigurationRoot] = configurationRoot;
\r
514 IModification modi = instruction.execute(g, bindings);
\r
515 //System.out.println("modi = " + modi);
\r