]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.structural2/src/org/simantics/structural2/utils/StructuralMetadataUtils.java
Fixed multiple issues causing dangling references to discarded queries
[simantics/platform.git] / bundles / org.simantics.structural2 / src / org / simantics / structural2 / utils / StructuralMetadataUtils.java
1 package org.simantics.structural2.utils;
2
3 import gnu.trove.set.hash.THashSet;
4
5 import org.simantics.db.ReadGraph;
6 import org.simantics.db.Resource;
7 import org.simantics.db.exception.DatabaseException;
8 import org.simantics.db.layer0.changeset.ChangeVisitor;
9 import org.simantics.db.layer0.changeset.MetadataUtils;
10 import org.simantics.db.layer0.genericrelation.DependencyChanges;
11 import org.simantics.db.layer0.genericrelation.DependencyChanges.Change;
12 import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentAddition;
13 import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentModification;
14 import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentRemoval;
15 import org.simantics.db.layer0.request.ModelInstances;
16 import org.simantics.layer0.Layer0;
17 import org.simantics.structural.stubs.StructuralResource2;
18
19 public class StructuralMetadataUtils {
20
21         private static ChangeVisitor getChangeVisitor(final ReadGraph graph, final Resource model, final StructuralChangeVisitor visitor) throws DatabaseException {
22                 
23                 return new ChangeVisitor() {
24             
25             Layer0 L0 = Layer0.getInstance(graph);
26             StructuralResource2 STR = StructuralResource2.getInstance(graph);
27             THashSet<Resource> visited = new THashSet<Resource>();
28             Resource IsLiftedAs = graph.getResource("http://www.simantics.org/Diagram-2.2/IsLiftedAs");
29             
30             @Override
31             public void visit(ReadGraph graph, Change change, boolean inverted)
32                     throws DatabaseException {
33                 
34                 switch(change.getType()) {
35                 case COMPONENT_ADDITION: {
36                     ComponentAddition addition = (ComponentAddition)change;
37                     if(inverted)
38                         visitor.visitComponentChange(graph, addition.parent, false);
39                     else
40                         visitor.visitComponentChange(graph, addition.component, true);
41                 } break;
42                 case COMPONENT_MODIFICATION: {
43                     ComponentModification modification = (ComponentModification)change;
44                     handleModification(graph, modification.component);
45                 } break;
46                 case COMPONENT_REMOVAL: {
47                     ComponentRemoval removal = (ComponentRemoval)change;
48                     if(inverted)
49                         visitor.visitComponentChange(graph, removal.component, true);
50                     else
51                         visitor.visitComponentChange(graph, removal.parent, false);
52                 } break;
53                 case LINK_CHANGE:
54                     // Link changes should not affect the structural configuration 
55                     break;
56                 }
57             }
58             
59             void handleModification(ReadGraph graph, Resource resource) throws DatabaseException {
60                 if(!visited.add(resource))
61                     return;
62                 if(!graph.hasStatement(resource))
63                     return;
64                 //System.out.println("handleModification: " + graph.getPossibleURI(resource));
65                 if(graph.isInstanceOf(resource, STR.Component))
66                     visitor.visitComponentChange(graph, resource, true);
67                 else if(graph.isInstanceOf(resource, STR.Connection))
68                     for(Resource connection : StructuralUtils.getRelatedConnections(graph, resource))
69                         handleConnectionChange(graph, connection);
70                 else if(graph.isInstanceOf(resource, STR.ConnectionJoin))
71                     for(Resource connection : StructuralUtils.getRelatedConnectionsOfConnectionJoin(graph, resource))
72                         handleConnectionChange(graph, connection);
73                 else if(graph.isInstanceOf(resource, STR.ComponentType))
74                     for(Resource instance : graph.syncRequest(new ModelInstances(model, resource)).values())
75                         visitor.visitComponentChange(graph, instance, true);
76                 else {
77                     Resource connectionRelation = graph.getPossibleObject(resource, IsLiftedAs);
78                     if(connectionRelation != null)
79                         handleConnectionRelation(graph, connectionRelation);
80                     else
81                         for(Resource parent : graph.getObjects(resource, L0.IsDependencyOf))
82                             handleModification(graph, parent);
83                 }
84             }
85
86             void handleConnectionChange(ReadGraph graph, Resource connection) throws DatabaseException {
87                 for(Resource component : graph.getObjects(connection, STR.Connects))
88                     visitor.visitComponentChange(graph, component, true);
89                 for(Resource connectionRelation : graph.getObjects(connection, STR.Binds))
90                     handleConnectionRelation(graph, connectionRelation);
91             }
92             
93             void handleConnectionRelation(ReadGraph graph, Resource connectionRelation) throws DatabaseException {
94                 Resource componentType = graph.getPossibleObject(connectionRelation, L0.HasDomain);
95                 if(componentType == null)
96                     return;
97                 for(Resource instance : graph.syncRequest(new ModelInstances(model, componentType)).values())
98                     for(Resource connection2 : graph.getObjects(instance, connectionRelation))
99                         handleConnectionChange(graph, connection2);
100             }
101             
102         };
103         }
104         
105     /**
106      * Finds all structural changes made to the given {@code model} from the given revision and calls 
107      * the {@code visitor} for them.
108      * The function processes raw metadata about modifications to resources and produces changes
109      * to components. It implements the following rules:
110      * <ul>
111      *     <li>Component removal implies a change to the parent of the component</li>
112      *     <li>Component addition implies a change to the added component.</li>
113      *     <li>A modification in the connection or join implies a change to all reachable components of the connection</li>
114      *     <li>A modification in a component type implies a change to all its instances</li>  
115      * </ul>
116      */
117     public static void visitStructuralChangesFrom(final ReadGraph graph, final Resource model, long fromRevision,
118             final StructuralChangeVisitor visitor) throws DatabaseException {
119         MetadataUtils.visitDependencyChangesFrom(graph, model, fromRevision, getChangeVisitor(graph, model, visitor));
120     }
121
122     public static void visitStructuralChangesFrom(final ReadGraph graph, final Resource model, DependencyChanges.Change[] changes,
123             final StructuralChangeVisitor visitor) throws DatabaseException {
124         MetadataUtils.visitDependencyChangesFrom2(graph, model, changes, getChangeVisitor(graph, model, visitor));
125     }
126     
127 }