]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling/src/org/simantics/modeling/mapping/DiagramToCompositeMapping3.java
Layer0Utils.addL0Identifier to prevent possible differentiation of code
[simantics/platform.git] / bundles / org.simantics.modeling / src / org / simantics / modeling / mapping / DiagramToCompositeMapping3.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2010 Association for Decentralized Information Management
3  * in Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *******************************************************************************/
12 package org.simantics.modeling.mapping;
13
14 import java.util.ArrayList;
15 import java.util.Collection;
16
17 import org.simantics.Simantics;
18 import org.simantics.db.ReadGraph;
19 import org.simantics.db.Resource;
20 import org.simantics.db.Session;
21 import org.simantics.db.common.utils.NameUtils;
22 import org.simantics.db.exception.DatabaseException;
23 import org.simantics.db.request.Read;
24 import org.simantics.diagram.stubs.DiagramResource;
25 import org.simantics.layer0.Layer0;
26 import org.simantics.layer0.utils.binaryPredicates.BinaryPredicateAdapter;
27 import org.simantics.layer0.utils.binaryPredicates.IBinaryPredicate;
28 import org.simantics.layer0.utils.binaryPredicates.InversePredicate;
29 import org.simantics.layer0.utils.binaryPredicates.OrderedSetElementsPredicate;
30 import org.simantics.layer0.utils.predicates.IUnaryPredicate;
31 import org.simantics.layer0.utils.predicates.Negation;
32 import org.simantics.layer0.utils.predicates.Type;
33 import org.simantics.layer0.utils.predicates.UnaryTest;
34 import org.simantics.layer0.utils.triggers.IModification;
35 import org.simantics.mapping.constraint.instructions.IInstruction;
36 import org.simantics.mapping.constraint.instructions.TypedBracketInstruction.CreationInstruction;
37 import org.simantics.mapping.rule.instructions.IRuleInstruction;
38 import org.simantics.modeling.ComponentUtils;
39 import org.simantics.modeling.ModelingResources;
40 import org.simantics.operation.Layer0X;
41 import org.simantics.project.IProject;
42 import org.simantics.structural.stubs.StructuralResource2;
43 import org.simantics.utils.ObjectUtils;
44
45 public class DiagramToCompositeMapping3 extends MappingBase {
46
47         static public int VARIABLE_COUNT = 0;
48         
49         final static protected int Diagram = VARIABLE_COUNT++;
50         final static protected int Configuration = VARIABLE_COUNT++;
51         final static protected int Element = VARIABLE_COUNT++;
52         final static protected int ElementType = VARIABLE_COUNT++;
53         final static protected int ComponentType = VARIABLE_COUNT++;
54         final static protected int Component = VARIABLE_COUNT++;
55         
56         final static protected int DiagramConnectionRelation = VARIABLE_COUNT++;
57         final static protected int DiagramConnectionRelation2 = VARIABLE_COUNT++;
58         final static protected int CElement = VARIABLE_COUNT++;
59         final static protected int ConnectionRelation = VARIABLE_COUNT++;
60         final static protected int Connector = VARIABLE_COUNT++;
61         final static protected int Connection = VARIABLE_COUNT++; 
62         final static protected int Connection2 = VARIABLE_COUNT++; 
63         final static protected int ConnectionType = VARIABLE_COUNT++;
64         final static protected int ConnectionRelation2 = VARIABLE_COUNT++;
65         final static protected int ConnectionRelation3 = VARIABLE_COUNT++;
66         final static protected int Component2 = VARIABLE_COUNT++;
67         final static protected int FlagType = VARIABLE_COUNT++;
68         final static protected int ConnectionDirection = VARIABLE_COUNT++;
69         final static protected int ConnectionJoin = VARIABLE_COUNT++;
70         final static protected int ConfigurationRoot = VARIABLE_COUNT++;
71         
72         final static protected int Join = VARIABLE_COUNT++;
73         final static protected int ConnectionMappingSpecification = VARIABLE_COUNT++;
74
75         protected Session session;
76         
77         protected Layer0 L0;
78         protected DiagramResource DIA;
79         protected ModelingResources MOD;
80         protected StructuralResource2 STR;
81     
82         protected IUnaryPredicate mapped;
83         protected IUnaryPredicate mappedFromConnector;
84         protected IUnaryPredicate external;
85         protected IUnaryPredicate inputFlag;
86         protected IUnaryPredicate hasOutputConnector;
87         protected IUnaryPredicate flagIsConnected;
88         protected IUnaryPredicate internalJoin;
89         protected IBinaryPredicate fromFlagToConnection;
90     
91         IRuleInstruction createMappingRule() throws DatabaseException { 
92                 L0 = Layer0.getInstance(session);
93                 DIA = DiagramResource.getInstance(session);
94                 MOD = ModelingResources.getInstance(session);
95                 STR = StructuralResource2.getInstance(session);
96                 mapped = new Tag(MOD.Mapped);
97                 mappedFromConnector = new Tag(MOD.MappedFromConnector);
98                 external = new Tag(DIA.ExternalFlag);
99                 inputFlag = new UnaryTest() {
100             @Override
101             public boolean has(ReadGraph g, Resource resource) throws DatabaseException {
102                 return g.hasStatement(resource, DIA.HasFlagType, DIA.FlagType_InputFlag);
103             }
104         };
105         hasOutputConnector = new UnaryTest() {            
106             @Override
107             public boolean has(ReadGraph g, Resource resource) throws DatabaseException {
108                 Resource connection = g.getPossibleObject(resource, MOD.DiagramConnectionToConnection);
109                 if(connection == null)
110                     return false;
111                 for(Resource connectionRelation : g.getObjects(connection, STR.Binds)) {
112                     if (!g.hasStatement(connectionRelation, MOD.GeneratesConnectionComponentInternally))
113                         return false;
114                 }
115                 for(Resource join : g.getObjects(connection, STR.IsJoinedBy))
116                         for(Resource connection2 : g.getObjects(join, STR.Joins))
117                                 if(!connection.equals(connection2) && g.hasStatement(connection, STR.Binds))
118                                         return false;
119                 return true;                
120             }
121         };
122         flagIsConnected = new UnaryTest() {            
123             @Override
124             public boolean has(ReadGraph g, Resource resource) throws DatabaseException {
125                 return g.hasStatement(resource, DIA.Flag_ConnectionPoint);           
126             }
127         };
128         internalJoin = new UnaryTest() {            
129             @Override
130             public boolean has(ReadGraph g, Resource resource) throws DatabaseException {
131                 return g.getObjects(resource, STR.JoinsComposite).size() <= 1;           
132             }
133         };
134         fromFlagToConnection = new BinaryPredicateAdapter() {
135                 @Override
136                 public boolean supportsGetObjects() {
137                         return true;
138                 }
139                 
140                         @Override
141                         public Collection<Resource> getObjects(ReadGraph g, Resource flag)
142                                         throws DatabaseException {
143                                 ArrayList<Resource> result = new ArrayList<Resource>(2);
144                                 for(Resource connector : g.getObjects(flag, DIA.Flag_ConnectionPoint))
145                                         for(Resource routeGraph : g.getObjects(connector, DIA.IsConnectorOf))
146                                                 if(!flag.equals(routeGraph))                                                    
147                                                         result.addAll(g.getObjects(routeGraph, MOD.DiagramConnectionToConnection));
148                                 return result;
149                         }
150                 };
151                 return and(destructiveRule(), additiveRule());
152         }       
153         
154         public CreationInstruction componentCreationInstruction(int component, int componentType, int configuration) {
155                 return new NamingCreationInstruction(project, ConfigurationRoot, component, componentType, configuration);
156         }
157         
158         protected IRuleInstruction additiveRule() {
159                 return 
160                 if_(bf(OrderedSetElementsPredicate.INSTANCE, Diagram, Element),
161                 query(
162                         if_(and(bf(L0.InstanceOf, Element, ElementType),
163                                        bf(MOD.SymbolToComponentType, ElementType, ComponentType)
164                                 ),
165                                 // If element type of the element has a corresponding component type
166                                 createComponentRule(),
167                     
168                         if_(b(DIA.Connection, Element),
169                             createNormalConnectionRule(),
170                             
171                             if_(b(DIA.Flag, Element),
172                                 createFlagRule()
173                             )
174                         )
175                     )
176                 )
177             );
178         }
179         
180         protected IRuleInstruction destructiveRule() {
181                 return and(
182                 if_(bf(L0.ConsistsOf, Configuration, Component),
183             and(
184                 if_(b(mapped, Component), // handle only mapped components
185                     query(
186                         if_(and(bf(MOD.ComponentToElement, Component, Element),
187                                 bf(new InversePredicate(OrderedSetElementsPredicate.INSTANCE), Element, Diagram),                                
188                                 b(implies(new Type(DIA.Flag), and(external, flagIsConnected)), Element),
189                                 b(implies(new Type(DIA.Connection), hasOutputConnector), Element)
190                             ),
191                             // If component has a corresponding element in the diagram
192                             if_(and(statement_bff(Component, ConnectionRelation, Connection, STR.IsConnectedTo),
193                                     b(mapped, Connection)
194                                 ),
195                                 destructiveConnectionRule()
196                             ),
197                             // If component does not have a corresponding element in the diagram, remove it
198                             and(deny(b(new Tag(MOD.ComponentToElement), Component)), deny(exists(Component)))
199                         )
200                     )
201                 ),
202                 if_(b(mappedFromConnector, Component), // handle only mapped components
203                     query(
204                         unless(bf(MOD.ComponentToConnector, Component, Connector),
205                             and(deny(b(new Tag(MOD.ComponentToElement), Component)), deny(exists(Component)))
206                         )
207                     )
208                 )
209             )
210         ),
211         // Destroy connections 
212         if_(and(bf(STR.HasConnectionJoin, Configuration, Join),
213                         b(internalJoin, Join),
214                         bf(STR.Joins, Join, Connection), 
215                         b(mapped, Connection)),
216                         unless(and(bf(MOD.ConnectionMapsTo, Connection, Connection2),
217                                         or(b(new Negation(new Tag(MOD.ConnectionToDiagramConnectionSpecial)), Connection),
218                                          b(new Tag(MOD.ElementToComponent), Connection2)
219                                          )
220                             ),
221                                 and(deny(b(new Tag(MOD.ConnectionMapsTo), Connection)), deny(exists(Connection)))
222                         )
223         ),
224         if_(and(bf(STR.HasConnectionJoin, Configuration, Join),
225                 bf(STR.Joins, Join, Connection), 
226                 b(mapped, Connection),                
227                 b(not(new Tag(STR.Connects)), Connection),
228                 b(not(new Tag(MOD.ConnectionMapsTo)), Connection)),
229                 deny(exists(Connection))
230         ),
231         if_(and(bf(STR.HasConnectionJoin, Configuration, Join),
232                 bf(STR.Joins, Join, Connection),
233                 bf(MOD.ConnectionToDiagramConnection, Connection, Connection2)), 
234                 unless(and(
235                         bf(DIA.HasConnector, Connection2, Connector),
236                         bf(DIA.Flag_ConnectionPoint_Inverse, Connector, Element),
237                         bb(DIA.FlagIsJoinedBy, Element, Join)
238                         ),
239                         deny(bb(STR.Joins, Join, Connection)))
240         ),
241         if_(and(bf(L0.ConsistsOf, Diagram, Element),
242                 bf(MOD.DiagramConnectionToConnectionSpecial, Element, Connection),
243                 not(b(new Tag(STR.Connects), Connection))),
244                 deny(exists(Connection))
245         ));
246         }
247         
248         protected IRuleInstruction destructiveConnectionRule() {
249                 // If component has a mapped connection
250         return if_(
251             and(bf(MOD.ConnectionMapsTo, Connection, Connection2),
252                 or(b(new Negation(new Tag(MOD.ConnectionToDiagramConnectionSpecial)), Connection),
253                    b(new Tag(MOD.ElementToComponent), Connection2)
254                 )
255             ),
256             unless(or(
257                    new DiagramConnectionExistence(Element, ConnectionRelation, Connection2),
258                    /*and(bf(MOD.ConnectionRelationToDiagramConnectionRelation, ConnectionRelation, DiagramConnectionRelation),
259                        statement_bbf(Element, DiagramConnectionRelation, Connector),
260                        bb(DIA.IsConnectorOf, Connector, Connection2)
261                    ),*/
262                    b(DIA.Connection, Element), 
263                    b(DIA.Flag, Element), /* This is not entirely correct.
264                                            It is new not possible to replace
265                                            a connection to an external signal 
266                                            flag.
267                                          */
268                    b(new Negation(new Tag(MOD.ConnectionRelationToDiagramConnectionRelation)), ConnectionRelation),
269                    fb(MOD.HasReferenceRelation, CElement, ConnectionRelation)
270                 ),
271                 deny(statement(Component, ConnectionRelation, Connection))
272             ),
273             // If the configuration connection does not have a correspondence in the diagram remove it
274             and(deny(b(new Tag(MOD.ConnectionMapsTo), Connection)), deny(exists(Connection)))
275         );
276         }
277         
278         protected IRuleInstruction createComponentRule() { 
279             return              
280                 claim(
281                     // Create a component corresponding to element, if it does not exist, and name it.
282                     exists(
283                     bf(MOD.ElementToComponent, Element, Component),
284                     componentCreationInstruction(Component, ComponentType, Configuration)
285                 ),                    
286                     bb(L0.InstanceOf, Component, ComponentType),
287                     bb(L0.PartOf, Component, Configuration),
288                     b(mapped, Component) // Mark the component mapped (for destructive rules)
289                 );
290         }
291
292         IRuleInstruction createConnectionRule() {
293                 return if_(
294                                 b(DIA.Connection, Element),
295                                 // If element is a connection
296                                 createNormalConnectionRule()
297                 );  
298         }
299         
300         protected Resource getConfigurationConnectionType() {
301                 return STR.Connection;
302         }
303         
304         protected IInstruction claimBasicConnection() {
305                 return and(exists(
306                 bf(MOD.DiagramConnectionToConnection, Element, Connection),
307                 Connection
308             ),
309             b(getConfigurationConnectionType(), Connection),
310             b(mapped, Connection)
311         );
312         }
313         
314         protected IRuleInstruction createNormalConnectionRule() {
315             return claim(claimBasicConnection(),
316                 if_(and(bf(STR.IsConnectedTo, Element, Connector),
317                     statement_ffb(CElement, DiagramConnectionRelation, Connector, STR.IsConnectedTo)
318                 ),
319                 
320                     if_(and(bf(MOD.DiagramConnectionRelationToConnectionRelation, DiagramConnectionRelation, ConnectionRelation),
321                             bf(MOD.ElementToComponent, CElement, Component)
322                         ),                   
323                            
324                         // then
325                         if_(or(and(bf(MOD.DiagramConnectionRelationToConnectionRelationB, DiagramConnectionRelation, ConnectionRelation2),
326                                    b(hasOutputConnector, Element),
327                                    bf(MOD.DiagramConnectionRelationToConnectionRelationC, DiagramConnectionRelation, ConnectionRelation3),
328                                    bf(MOD.DiagramConnectionRelationToComponentType, DiagramConnectionRelation, ComponentType)
329                                ),
330                                and(bf(MOD.HasConnectionMappingSpecification, Connector, ConnectionMappingSpecification),
331                                    b(hasOutputConnector, Element),
332                                    bf(MOD.DiagramConnectionRelationToConnectionRelationB, ConnectionMappingSpecification, ConnectionRelation2),                            
333                                    bf(MOD.DiagramConnectionRelationToConnectionRelationC, ConnectionMappingSpecification, ConnectionRelation3),
334                                    bf(MOD.DiagramConnectionRelationToComponentType, ConnectionMappingSpecification, ComponentType)
335                                )
336                             ),
337                             
338                             // then
339                             claim(
340                                     // Create a component corresponding to connector, if it does not exist, and name it.
341                                     exists(
342                                     bf(MOD.ElementToComponent, Element, Component2),
343                                     new NamingCreationInstruction(project, ConfigurationRoot, Component2, ComponentType, Configuration)
344                                 ),                    
345                                     bb(L0.InstanceOf, Component2, ComponentType),
346                                     bb(L0.PartOf, Component2, Configuration),
347                                     bb(MOD.ConnectorToComponent, Connector, Component2),
348                                     b(mappedFromConnector, Component2), // Mark the component mapped (for destructive rules)                                
349                                     
350                                     // Create a connection
351                                     exists(
352                                         bf(MOD.DiagramConnectionToConnectionSpecial, Element, Connection2),                                 
353                                     Connection2
354                                 ),
355                                 statement(Component2, ConnectionRelation2, Connection2),
356                             statement(Component,  ConnectionRelation,  Connection2),
357                                 b(getConfigurationConnectionType(), Connection2),
358                                 b(mapped, Connection2),
359                                     
360                                     // 
361                                     statement(Component2, ConnectionRelation3, Connection)
362                             ),
363                             
364                             // else
365                             claim(statement(Component, ConnectionRelation, Connection))
366                         ),                 
367                         
368                         // else
369                         if_(bf(MOD.HasReferenceRelation, CElement, ConnectionRelation),
370                                 if_(bf(MOD.HasParentComponent, CElement, Component),
371                                 // then
372                                 claim(statement(Component, ConnectionRelation, Connection)),
373                                 // else
374                             claim(statement(CElement, ConnectionRelation, Connection))
375                         )
376                         )
377                     )
378                 )
379         );
380         }
381    
382         protected IRuleInstruction createFlagRule() {
383
384            return 
385            and(
386                //print("Flag rule"),
387                if_(and(bf(DIA.FlagIsJoinedBy, Element, ConnectionJoin),
388                            bf(compose(STR.IsConnectedTo, STR.Connects, MOD.DiagramConnectionToConnection), 
389                                            Element, Connection)                            
390                        ),
391                        claim(
392                            bb(STR.Joins, ConnectionJoin, Connection),
393                            bb(STR.HasConnectionJoin, Configuration, ConnectionJoin)
394                        ),
395                // This is maybe Apros specific                 
396                        if_(and(b(and(external, inputFlag, flagIsConnected), Element),
397                                bf(compose(STR.IsConnectedTo, STR.Connects), Element, Connection2),
398                            bf(MOD.DiagramConnectionToConnection, Connection2, Connection),
399                            bf(STR.HasConnectionType, Connection2, ConnectionType),
400                            bf(MOD.ConnectionTypeToComponentType, ConnectionType, ComponentType),
401                            bf(MOD.ConnectionTypeToConnectionRelation, ConnectionType, ConnectionRelation)
402                            ),
403                            claim(
404                                exists(
405                                bf(MOD.ElementToComponent, Element, Component),
406                                new NamingCreationInstruction(project, ConfigurationRoot, Component, ComponentType, Configuration)
407                            ),
408                                bb(L0.InstanceOf, Component, ComponentType),
409                        bb(L0.PartOf, Component, Configuration),
410                        b(mapped, Component),
411                        
412                        statement(Component, ConnectionRelation, Connection)
413                            )
414                        )
415                ),
416                if_(and(bf(DIA.IsLiftedAs, Element, ConnectionRelation),
417                        bf(fromFlagToConnection, Element, Connection)),
418                    claim(
419                        bb(STR.Binds, Connection, ConnectionRelation)
420                    )
421                )
422            );
423    }
424
425         class RuleQuery implements Read<IRuleInstruction> {
426
427                 @Override
428                 public boolean equals(Object other) {
429                         return other != null && other.getClass() == RuleQuery.class &&
430                                         getParentClass().equals(((RuleQuery)other).getParentClass());
431                 }
432
433                 private Class<? extends DiagramToCompositeMapping3> getParentClass() {
434                         return DiagramToCompositeMapping3.this.getClass();
435                 }
436
437                 @Override
438                 public int hashCode() {
439                         return DiagramToCompositeMapping3.this.getClass().hashCode();
440                 }
441
442                 @Override
443                 public IRuleInstruction perform(ReadGraph g) {
444                         try {
445                                 return createMappingRule();
446                         } catch (DatabaseException e) {
447                                 e.printStackTrace();
448                         }
449                         return null;
450                         
451                 }
452                 
453         }
454         
455         IRuleInstruction instruction;
456         public Resource source;
457         public Resource target;
458         protected IProject project;
459         protected Resource configurationRoot;
460         
461         protected void setup(ReadGraph graph) {
462                 
463         }
464         
465         public DiagramToCompositeMapping3(ReadGraph g, Resource mapping) throws DatabaseException {
466
467                 setup(g);
468
469                 this.session = g.getSession();
470
471                 this.source = g.getPossibleObject(mapping, g.getInverse(Layer0X.getInstance(g).HasTrigger));
472                 if (source != null)
473                         this.target = g.getPossibleObject(this.source, ModelingResources.getInstance(g).DiagramToComposite);
474                 if (target != null) {
475                         configurationRoot = ComponentUtils.getCompositeConfigurationRoot(g, target);
476                         assert configurationRoot != null;
477                 }
478
479                 this.project = Simantics.peekProject();
480                 this.instruction = g.syncRequest(new RuleQuery());
481
482 //              System.out.println(this + "(mapping=" + mapping
483 //                              + ", source=" + source
484 //                              + ", target=" + target
485 //                              + ", configurationRoot=" + configurationRoot
486 //                              + ")");
487
488         }
489         
490         @Override
491         public boolean equals(Object other) {
492                 if(this==other)
493                         return true;
494                 if(!(other instanceof DiagramToCompositeMapping3))
495                         return false;
496                 DiagramToCompositeMapping3 map = (DiagramToCompositeMapping3)other;
497                 return ObjectUtils.objectEquals(map.source, source) && ObjectUtils.objectEquals(map.target, target);
498         }
499
500         @Override
501         public int hashCode() {
502                 return ObjectUtils.hashCode(source) + 31 * ObjectUtils.hashCode(target);
503         }
504
505         @Override
506         public IModification perform(ReadGraph g) throws DatabaseException {
507 //              System.out.println(this + ": Find modification (source=" + source + ", target=" + target + ", configurationRoot=" + configurationRoot + ")");
508
509             if(IInstruction.DEBUG_MODI)
510                 System.out.println("--- MAPPING ROUND -------------------------------- " + NameUtils.getURIOrSafeNameInternal(g, target));
511             
512                 if (source == null || target == null)
513                         return null;
514
515                 final Object[] bindings = new Object[VARIABLE_COUNT];
516                 bindings[Diagram] = source;
517                 bindings[Configuration] = target;
518                 bindings[ConfigurationRoot] = configurationRoot;
519                 IModification modi = instruction.execute(g, bindings);
520                 //System.out.println("modi = " + modi);
521                 return modi;
522         }
523 }