]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.modeling/src/org/simantics/modeling/mapping/DiagramToCompositeMapping3.java
Fixed multiple issues causing dangling references to discarded queries
[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(
199                                     deny(b(new Tag(MOD.ComponentToElement), Component)),
200                                     deny(b(new Tag(STR.IsConnectedTo), Component)),
201                                     deny(exists(Component)))
202                         )
203                     )
204                 ),
205                 if_(b(mappedFromConnector, Component), // handle only mapped components
206                     query(
207                         unless(bf(MOD.ComponentToConnector, Component, Connector),
208                             and(
209                                     deny(b(new Tag(MOD.ComponentToElement), Component)),
210                                     deny(b(new Tag(STR.IsConnectedTo), Component)),
211                                     deny(exists(Component)))
212                         )
213                     )
214                 )
215             )
216         ),
217         // Destroy connections 
218         if_(and(bf(STR.HasConnectionJoin, Configuration, Join),
219                         b(internalJoin, Join),
220                         bf(STR.Joins, Join, Connection), 
221                         b(mapped, Connection)),
222                         unless(and(bf(MOD.ConnectionMapsTo, Connection, Connection2),
223                                         or(b(new Negation(new Tag(MOD.ConnectionToDiagramConnectionSpecial)), Connection),
224                                          b(new Tag(MOD.ElementToComponent), Connection2)
225                                          )
226                             ),
227                                 and(deny(b(new Tag(MOD.ConnectionMapsTo), Connection)), deny(exists(Connection)))
228                         )
229         ),
230         if_(and(bf(STR.HasConnectionJoin, Configuration, Join),
231                 bf(STR.Joins, Join, Connection), 
232                 b(mapped, Connection),                
233                 b(not(new Tag(STR.Connects)), Connection),
234                 b(not(new Tag(MOD.ConnectionMapsTo)), Connection)),
235                 deny(exists(Connection))
236         ),
237         if_(and(bf(STR.HasConnectionJoin, Configuration, Join),
238                 bf(STR.Joins, Join, Connection),
239                 bf(MOD.ConnectionToDiagramConnection, Connection, Connection2)), 
240                 unless(and(
241                         bf(DIA.HasConnector, Connection2, Connector),
242                         bf(DIA.Flag_ConnectionPoint_Inverse, Connector, Element),
243                         bb(DIA.FlagIsJoinedBy, Element, Join)
244                         ),
245                         deny(bb(STR.Joins, Join, Connection)))
246         ),
247         if_(and(bf(L0.ConsistsOf, Diagram, Element),
248                 bf(MOD.DiagramConnectionToConnectionSpecial, Element, Connection),
249                 not(b(new Tag(STR.Connects), Connection))),
250                 deny(exists(Connection))
251         ));
252         }
253         
254         protected IRuleInstruction destructiveConnectionRule() {
255                 // If component has a mapped connection
256         return if_(
257             and(bf(MOD.ConnectionMapsTo, Connection, Connection2),
258                 or(b(new Negation(new Tag(MOD.ConnectionToDiagramConnectionSpecial)), Connection),
259                    b(new Tag(MOD.ElementToComponent), Connection2)
260                 )
261             ),
262             unless(or(
263                    new DiagramConnectionExistence(Element, ConnectionRelation, Connection2),
264                    /*and(bf(MOD.ConnectionRelationToDiagramConnectionRelation, ConnectionRelation, DiagramConnectionRelation),
265                        statement_bbf(Element, DiagramConnectionRelation, Connector),
266                        bb(DIA.IsConnectorOf, Connector, Connection2)
267                    ),*/
268                    b(DIA.Connection, Element), 
269                    b(DIA.Flag, Element), /* This is not entirely correct.
270                                            It is new not possible to replace
271                                            a connection to an external signal 
272                                            flag.
273                                          */
274                    b(new Negation(new Tag(MOD.ConnectionRelationToDiagramConnectionRelation)), ConnectionRelation),
275                    fb(MOD.HasReferenceRelation, CElement, ConnectionRelation)
276                 ),
277                 deny(statement(Component, ConnectionRelation, Connection))
278             ),
279             // If the configuration connection does not have a correspondence in the diagram remove it
280             and(deny(b(new Tag(MOD.ConnectionMapsTo), Connection)), deny(exists(Connection)))
281         );
282         }
283         
284         protected IRuleInstruction createComponentRule() { 
285             return              
286                 claim(
287                     // Create a component corresponding to element, if it does not exist, and name it.
288                     exists(
289                     bf(MOD.ElementToComponent, Element, Component),
290                     componentCreationInstruction(Component, ComponentType, Configuration)
291                 ),                    
292                     bb(L0.InstanceOf, Component, ComponentType),
293                     bb(L0.PartOf, Component, Configuration),
294                     b(mapped, Component) // Mark the component mapped (for destructive rules)
295                 );
296         }
297
298         IRuleInstruction createConnectionRule() {
299                 return if_(
300                                 b(DIA.Connection, Element),
301                                 // If element is a connection
302                                 createNormalConnectionRule()
303                 );  
304         }
305         
306         protected Resource getConfigurationConnectionType() {
307                 return STR.Connection;
308         }
309         
310         protected IInstruction claimBasicConnection() {
311                 return and(exists(
312                 bf(MOD.DiagramConnectionToConnection, Element, Connection),
313                 Connection
314             ),
315             b(getConfigurationConnectionType(), Connection),
316             b(mapped, Connection)
317         );
318         }
319         
320         protected IRuleInstruction createNormalConnectionRule() {
321             return claim(claimBasicConnection(),
322                 if_(and(bf(STR.IsConnectedTo, Element, Connector),
323                     statement_ffb(CElement, DiagramConnectionRelation, Connector, STR.IsConnectedTo)
324                 ),
325                 
326                     if_(and(bf(MOD.DiagramConnectionRelationToConnectionRelation, DiagramConnectionRelation, ConnectionRelation),
327                             bf(MOD.ElementToComponent, CElement, Component)
328                         ),                   
329                            
330                         // then
331                         if_(or(and(bf(MOD.DiagramConnectionRelationToConnectionRelationB, DiagramConnectionRelation, ConnectionRelation2),
332                                    b(hasOutputConnector, Element),
333                                    bf(MOD.DiagramConnectionRelationToConnectionRelationC, DiagramConnectionRelation, ConnectionRelation3),
334                                    bf(MOD.DiagramConnectionRelationToComponentType, DiagramConnectionRelation, ComponentType)
335                                ),
336                                and(bf(MOD.HasConnectionMappingSpecification, Connector, ConnectionMappingSpecification),
337                                    b(hasOutputConnector, Element),
338                                    bf(MOD.DiagramConnectionRelationToConnectionRelationB, ConnectionMappingSpecification, ConnectionRelation2),                            
339                                    bf(MOD.DiagramConnectionRelationToConnectionRelationC, ConnectionMappingSpecification, ConnectionRelation3),
340                                    bf(MOD.DiagramConnectionRelationToComponentType, ConnectionMappingSpecification, ComponentType)
341                                )
342                             ),
343                             
344                             // then
345                             claim(
346                                     // Create a component corresponding to connector, if it does not exist, and name it.
347                                     exists(
348                                     bf(MOD.ElementToComponent, Element, Component2),
349                                     new NamingCreationInstruction(project, ConfigurationRoot, Component2, ComponentType, Configuration)
350                                 ),                    
351                                     bb(L0.InstanceOf, Component2, ComponentType),
352                                     bb(L0.PartOf, Component2, Configuration),
353                                     bb(MOD.ConnectorToComponent, Connector, Component2),
354                                     b(mappedFromConnector, Component2), // Mark the component mapped (for destructive rules)                                
355                                     
356                                     // Create a connection
357                                     exists(
358                                         bf(MOD.DiagramConnectionToConnectionSpecial, Element, Connection2),                                 
359                                     Connection2
360                                 ),
361                                 statement(Component2, ConnectionRelation2, Connection2),
362                             statement(Component,  ConnectionRelation,  Connection2),
363                                 b(getConfigurationConnectionType(), Connection2),
364                                 b(mapped, Connection2),
365                                     
366                                     // 
367                                     statement(Component2, ConnectionRelation3, Connection)
368                             ),
369                             
370                             // else
371                             claim(statement(Component, ConnectionRelation, Connection))
372                         ),                 
373                         
374                         // else
375                         if_(bf(MOD.HasReferenceRelation, CElement, ConnectionRelation),
376                                 if_(bf(MOD.HasParentComponent, CElement, Component),
377                                 // then
378                                 claim(statement(Component, ConnectionRelation, Connection)),
379                                 // else
380                             claim(statement(CElement, ConnectionRelation, Connection))
381                         )
382                         )
383                     )
384                 )
385         );
386         }
387    
388         protected IRuleInstruction createFlagRule() {
389
390            return 
391            and(
392                //print("Flag rule"),
393                if_(and(bf(DIA.FlagIsJoinedBy, Element, ConnectionJoin),
394                            bf(compose(STR.IsConnectedTo, STR.Connects, MOD.DiagramConnectionToConnection), 
395                                            Element, Connection)                            
396                        ),
397                        claim(
398                            bb(STR.Joins, ConnectionJoin, Connection),
399                            bb(STR.HasConnectionJoin, Configuration, ConnectionJoin)
400                        ),
401                // This is maybe Apros specific                 
402                        if_(and(b(and(external, inputFlag, flagIsConnected), Element),
403                                bf(compose(STR.IsConnectedTo, STR.Connects), Element, Connection2),
404                            bf(MOD.DiagramConnectionToConnection, Connection2, Connection),
405                            bf(STR.HasConnectionType, Connection2, ConnectionType),
406                            bf(MOD.ConnectionTypeToComponentType, ConnectionType, ComponentType),
407                            bf(MOD.ConnectionTypeToConnectionRelation, ConnectionType, ConnectionRelation)
408                            ),
409                            claim(
410                                exists(
411                                bf(MOD.ElementToComponent, Element, Component),
412                                new NamingCreationInstruction(project, ConfigurationRoot, Component, ComponentType, Configuration)
413                            ),
414                                bb(L0.InstanceOf, Component, ComponentType),
415                        bb(L0.PartOf, Component, Configuration),
416                        b(mapped, Component),
417                        
418                        statement(Component, ConnectionRelation, Connection)
419                            )
420                        )
421                ),
422                if_(and(bf(DIA.IsLiftedAs, Element, ConnectionRelation),
423                        bf(fromFlagToConnection, Element, Connection)),
424                    claim(
425                        bb(STR.Binds, Connection, ConnectionRelation)
426                    )
427                )
428            );
429    }
430
431         class RuleQuery implements Read<IRuleInstruction> {
432
433                 @Override
434                 public boolean equals(Object other) {
435                         return other != null && other.getClass() == RuleQuery.class &&
436                                         getParentClass().equals(((RuleQuery)other).getParentClass());
437                 }
438
439                 private Class<? extends DiagramToCompositeMapping3> getParentClass() {
440                         return DiagramToCompositeMapping3.this.getClass();
441                 }
442
443                 @Override
444                 public int hashCode() {
445                         return DiagramToCompositeMapping3.this.getClass().hashCode();
446                 }
447
448                 @Override
449                 public IRuleInstruction perform(ReadGraph g) {
450                         try {
451                                 return createMappingRule();
452                         } catch (DatabaseException e) {
453                                 e.printStackTrace();
454                         }
455                         return null;
456                         
457                 }
458                 
459         }
460         
461         IRuleInstruction instruction;
462         public Resource source;
463         public Resource target;
464         protected IProject project;
465         protected Resource configurationRoot;
466         
467         protected void setup(ReadGraph graph) {
468                 
469         }
470         
471         public DiagramToCompositeMapping3(ReadGraph g, Resource mapping) throws DatabaseException {
472
473                 setup(g);
474
475                 this.session = g.getSession();
476
477                 this.source = g.getPossibleObject(mapping, g.getInverse(Layer0X.getInstance(g).HasTrigger));
478                 if (source != null)
479                         this.target = g.getPossibleObject(this.source, ModelingResources.getInstance(g).DiagramToComposite);
480                 if (target != null) {
481                         configurationRoot = ComponentUtils.getCompositeConfigurationRoot(g, target);
482                         assert configurationRoot != null;
483                 }
484
485                 this.project = Simantics.peekProject();
486                 this.instruction = g.syncRequest(new RuleQuery());
487
488 //              System.out.println(this + "(mapping=" + mapping
489 //                              + ", source=" + source
490 //                              + ", target=" + target
491 //                              + ", configurationRoot=" + configurationRoot
492 //                              + ")");
493
494         }
495         
496         @Override
497         public boolean equals(Object other) {
498                 if(this==other)
499                         return true;
500                 if(!(other instanceof DiagramToCompositeMapping3))
501                         return false;
502                 DiagramToCompositeMapping3 map = (DiagramToCompositeMapping3)other;
503                 return ObjectUtils.objectEquals(map.source, source) && ObjectUtils.objectEquals(map.target, target);
504         }
505
506         @Override
507         public int hashCode() {
508                 return ObjectUtils.hashCode(source) + 31 * ObjectUtils.hashCode(target);
509         }
510
511         @Override
512         public IModification perform(ReadGraph g) throws DatabaseException {
513 //              System.out.println(this + ": Find modification (source=" + source + ", target=" + target + ", configurationRoot=" + configurationRoot + ")");
514
515             if(IInstruction.DEBUG_MODI)
516                 System.out.println("--- MAPPING ROUND -------------------------------- " + NameUtils.getURIOrSafeNameInternal(g, target));
517             
518                 if (source == null || target == null)
519                         return null;
520
521                 final Object[] bindings = new Object[VARIABLE_COUNT];
522                 bindings[Diagram] = source;
523                 bindings[Configuration] = target;
524                 bindings[ConfigurationRoot] = configurationRoot;
525                 IModification modi = instruction.execute(g, bindings);
526                 //System.out.println("modi = " + modi);
527                 return modi;
528         }
529 }