1 package org.simantics.structural.synchronization;
\r
3 import gnu.trove.map.hash.THashMap;
\r
4 import gnu.trove.map.hash.TObjectIntHashMap;
\r
6 import java.util.ArrayList;
\r
7 import java.util.Map;
\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
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
28 * @author Hannu Niemistö
\r
30 public class StructuralChangeFlattener {
\r
32 private static Variable[] EMPTY_VARIABLE_ARRAY = new Variable[0];
\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
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
49 return visitor.modifiedComponents;
\r
52 private static class Visitor implements StructuralChangeVisitor {
\r
54 Variable rootVariable;
\r
55 Resource rootResource;
\r
57 THashMap<Resource, Variable[]> visitedVariables = new THashMap<Resource, Variable[]>();
\r
59 StructuralResource2 STR;
\r
60 TObjectIntHashMap<Variable> modifiedComponents = new TObjectIntHashMap<Variable>();
\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
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
78 if(componentItselfModified)
\r
79 for(Variable variable : variables)
\r
80 modifiedComponents.put(variable, 2);
\r
82 for(Variable variable : variables)
\r
83 modifiedComponents.putIfAbsent(variable, 1);
\r
86 private Variable[] visitUnseenComponent(ReadGraph graph, Resource component) throws DatabaseException {
\r
88 if(component.equals(rootResource))
\r
89 return new Variable[] { rootVariable };
\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
101 if(result.isEmpty())
\r
102 return EMPTY_VARIABLE_ARRAY;
\r
104 return result.toArray(new Variable[result.size()]);
\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
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
121 if(result.isEmpty())
\r
122 return EMPTY_VARIABLE_ARRAY;
\r
124 return result.toArray(new Variable[result.size()]);
\r