]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.structural.synchronization.client/src/org/simantics/structural/synchronization/StructuralChangeFlattener.java
Sync git svn branch with SVN repository r33366.
[simantics/platform.git] / bundles / org.simantics.structural.synchronization.client / src / org / simantics / structural / synchronization / StructuralChangeFlattener.java
1 package org.simantics.structural.synchronization;\r
2 \r
3 import gnu.trove.map.hash.THashMap;\r
4 import gnu.trove.map.hash.TObjectIntHashMap;\r
5 \r
6 import java.util.ArrayList;\r
7 import java.util.Map;\r
8 \r
9 import org.simantics.databoard.Bindings;\r
10 import org.simantics.db.ReadGraph;\r
11 import org.simantics.db.Resource;\r
12 import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;\r
13 import org.simantics.db.exception.DatabaseException;\r
14 import org.simantics.db.layer0.genericrelation.DependencyChanges;\r
15 import org.simantics.db.layer0.request.ModelInstances;\r
16 import org.simantics.db.layer0.variable.Variable;\r
17 import org.simantics.db.layer0.variable.Variables;\r
18 import org.simantics.layer0.Layer0;\r
19 import org.simantics.structural.stubs.StructuralResource2;\r
20 import org.simantics.structural2.utils.StructuralChangeVisitor;\r
21 import org.simantics.structural2.utils.StructuralMetadataUtils;\r
22 \r
23 /**\r
24  * Browses change metadata from the requested revision and\r
25  * marks the components in a flat structural configuration\r
26  * where changes have been occured.\r
27  * \r
28  * @author Hannu Niemistö\r
29  */\r
30 public class StructuralChangeFlattener {\r
31     \r
32     private static Variable[] EMPTY_VARIABLE_ARRAY = new Variable[0];\r
33     \r
34     public static TObjectIntHashMap<Variable> getModifiedComponents(ReadGraph graph,\r
35             Variable rootVariable, long fromRevision) throws DatabaseException {\r
36         Visitor visitor = new Visitor(graph, rootVariable);\r
37         StructuralMetadataUtils.visitStructuralChangesFrom(graph,\r
38                 Variables.getModel(graph, rootVariable),\r
39                 fromRevision, visitor);\r
40         return visitor.modifiedComponents;\r
41     }\r
42 \r
43     public static TObjectIntHashMap<Variable> getModifiedComponents(ReadGraph graph,\r
44             Variable rootVariable, DependencyChanges.Change[] changes) throws DatabaseException {\r
45         Visitor visitor = new Visitor(graph, rootVariable);\r
46         StructuralMetadataUtils.visitStructuralChangesFrom(graph,\r
47                 Variables.getModel(graph, rootVariable),\r
48                 changes, visitor);\r
49         return visitor.modifiedComponents;\r
50     }\r
51 \r
52     private static class Visitor implements StructuralChangeVisitor {\r
53 \r
54         Variable rootVariable;\r
55         Resource rootResource;\r
56         Resource model;\r
57         THashMap<Resource, Variable[]> visitedVariables = new THashMap<Resource, Variable[]>();\r
58         Layer0 L0;\r
59         StructuralResource2 STR;\r
60         TObjectIntHashMap<Variable> modifiedComponents = new TObjectIntHashMap<Variable>(); \r
61         \r
62         public Visitor(ReadGraph graph, Variable rootVariable) throws DatabaseException {\r
63             this.rootVariable = rootVariable;\r
64             this.rootResource = rootVariable.getRepresents(graph);\r
65             this.model = Variables.getModel(graph, rootVariable);\r
66             this.L0 = Layer0.getInstance(graph);\r
67             this.STR = StructuralResource2.getInstance(graph);\r
68         }\r
69         \r
70         @Override\r
71         public void visitComponentChange(ReadGraph graph, Resource component, boolean componentItselfModified)\r
72                 throws DatabaseException {\r
73             Variable[] variables = visitedVariables.get(component);\r
74             if(variables == null) {\r
75                 variables = visitUnseenComponent(graph, component);\r
76                 visitedVariables.put(component, variables);\r
77             }\r
78             if(componentItselfModified)\r
79                 for(Variable variable : variables)\r
80                     modifiedComponents.put(variable, 2);\r
81             else\r
82                 for(Variable variable : variables)\r
83                     modifiedComponents.putIfAbsent(variable, 1);\r
84         }\r
85         \r
86         private Variable[] visitUnseenComponent(ReadGraph graph, Resource component) throws DatabaseException {\r
87             // Is root?\r
88             if(component.equals(rootResource))\r
89                 return new Variable[] { rootVariable };\r
90             \r
91             // Check if this a component type root\r
92             Resource componentType = graph.getPossibleObject(component, STR.Defines);\r
93             if(componentType != null) {\r
94                 ArrayList<Variable> result = new ArrayList<Variable>();\r
95                 Map<String,Resource> instances = graph.syncRequest(new ModelInstances(model, componentType), TransientCacheAsyncListener.<Map<String,Resource>>instance());\r
96                 for(Resource instance : instances.values()) {\r
97                     visitComponentChange(graph, instance, false);\r
98                     for(Variable variable : visitedVariables.get(instance))\r
99                         result.add(variable);\r
100                 }\r
101                 if(result.isEmpty())\r
102                     return EMPTY_VARIABLE_ARRAY;\r
103                 else\r
104                     return result.toArray(new Variable[result.size()]);\r
105             }\r
106             \r
107             // Check parent\r
108             Resource parent = graph.getPossibleObject(component, L0.PartOf);\r
109             String name = graph.getPossibleRelatedValue(component, L0.HasName, Bindings.STRING);\r
110             if(parent == null || name == null || !graph.isInstanceOf(component, STR.Component))\r
111                 return EMPTY_VARIABLE_ARRAY;\r
112             \r
113             visitComponentChange(graph, parent, false);\r
114             Variable[] parentCorrespondences = visitedVariables.get(parent);\r
115             ArrayList<Variable> result = new ArrayList<Variable>(parentCorrespondences.length);\r
116             for(Variable parentCorrespondence : parentCorrespondences) {\r
117                 Variable correspondence = parentCorrespondence.getPossibleChild(graph, name);\r
118                 if(correspondence != null)\r
119                     result.add(correspondence);\r
120             }\r
121             if(result.isEmpty())\r
122                 return EMPTY_VARIABLE_ARRAY;\r
123             else\r
124                 return result.toArray(new Variable[result.size()]);\r
125         }\r
126         \r
127     }\r
128 }\r