-package org.simantics.structural.synchronization;\r
-\r
-import gnu.trove.map.hash.THashMap;\r
-import gnu.trove.map.hash.TObjectIntHashMap;\r
-\r
-import java.util.ArrayList;\r
-import java.util.Map;\r
-\r
-import org.simantics.databoard.Bindings;\r
-import org.simantics.db.ReadGraph;\r
-import org.simantics.db.Resource;\r
-import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;\r
-import org.simantics.db.exception.DatabaseException;\r
-import org.simantics.db.layer0.genericrelation.DependencyChanges;\r
-import org.simantics.db.layer0.request.ModelInstances;\r
-import org.simantics.db.layer0.variable.Variable;\r
-import org.simantics.db.layer0.variable.Variables;\r
-import org.simantics.layer0.Layer0;\r
-import org.simantics.structural.stubs.StructuralResource2;\r
-import org.simantics.structural2.utils.StructuralChangeVisitor;\r
-import org.simantics.structural2.utils.StructuralMetadataUtils;\r
-\r
-/**\r
- * Browses change metadata from the requested revision and\r
- * marks the components in a flat structural configuration\r
- * where changes have been occured.\r
- * \r
- * @author Hannu Niemistö\r
- */\r
-public class StructuralChangeFlattener {\r
- \r
- private static Variable[] EMPTY_VARIABLE_ARRAY = new Variable[0];\r
- \r
- public static TObjectIntHashMap<Variable> getModifiedComponents(ReadGraph graph,\r
- Variable rootVariable, long fromRevision) throws DatabaseException {\r
- Visitor visitor = new Visitor(graph, rootVariable);\r
- StructuralMetadataUtils.visitStructuralChangesFrom(graph,\r
- Variables.getModel(graph, rootVariable),\r
- fromRevision, visitor);\r
- return visitor.modifiedComponents;\r
- }\r
-\r
- public static TObjectIntHashMap<Variable> getModifiedComponents(ReadGraph graph,\r
- Variable rootVariable, DependencyChanges.Change[] changes) throws DatabaseException {\r
- Visitor visitor = new Visitor(graph, rootVariable);\r
- StructuralMetadataUtils.visitStructuralChangesFrom(graph,\r
- Variables.getModel(graph, rootVariable),\r
- changes, visitor);\r
- return visitor.modifiedComponents;\r
- }\r
-\r
- private static class Visitor implements StructuralChangeVisitor {\r
-\r
- Variable rootVariable;\r
- Resource rootResource;\r
- Resource model;\r
- THashMap<Resource, Variable[]> visitedVariables = new THashMap<Resource, Variable[]>();\r
- Layer0 L0;\r
- StructuralResource2 STR;\r
- TObjectIntHashMap<Variable> modifiedComponents = new TObjectIntHashMap<Variable>(); \r
- \r
- public Visitor(ReadGraph graph, Variable rootVariable) throws DatabaseException {\r
- this.rootVariable = rootVariable;\r
- this.rootResource = rootVariable.getRepresents(graph);\r
- this.model = Variables.getModel(graph, rootVariable);\r
- this.L0 = Layer0.getInstance(graph);\r
- this.STR = StructuralResource2.getInstance(graph);\r
- }\r
- \r
- @Override\r
- public void visitComponentChange(ReadGraph graph, Resource component, boolean componentItselfModified)\r
- throws DatabaseException {\r
- Variable[] variables = visitedVariables.get(component);\r
- if(variables == null) {\r
- variables = visitUnseenComponent(graph, component);\r
- visitedVariables.put(component, variables);\r
- }\r
- if(componentItselfModified)\r
- for(Variable variable : variables)\r
- modifiedComponents.put(variable, 2);\r
- else\r
- for(Variable variable : variables)\r
- modifiedComponents.putIfAbsent(variable, 1);\r
- }\r
- \r
- private Variable[] visitUnseenComponent(ReadGraph graph, Resource component) throws DatabaseException {\r
- // Is root?\r
- if(component.equals(rootResource))\r
- return new Variable[] { rootVariable };\r
- \r
- // Check if this a component type root\r
- Resource componentType = graph.getPossibleObject(component, STR.Defines);\r
- if(componentType != null) {\r
- ArrayList<Variable> result = new ArrayList<Variable>();\r
- Map<String,Resource> instances = graph.syncRequest(new ModelInstances(model, componentType), TransientCacheAsyncListener.<Map<String,Resource>>instance());\r
- for(Resource instance : instances.values()) {\r
- visitComponentChange(graph, instance, false);\r
- for(Variable variable : visitedVariables.get(instance))\r
- result.add(variable);\r
- }\r
- if(result.isEmpty())\r
- return EMPTY_VARIABLE_ARRAY;\r
- else\r
- return result.toArray(new Variable[result.size()]);\r
- }\r
- \r
- // Check parent\r
- Resource parent = graph.getPossibleObject(component, L0.PartOf);\r
- String name = graph.getPossibleRelatedValue(component, L0.HasName, Bindings.STRING);\r
- if(parent == null || name == null || !graph.isInstanceOf(component, STR.Component))\r
- return EMPTY_VARIABLE_ARRAY;\r
- \r
- visitComponentChange(graph, parent, false);\r
- Variable[] parentCorrespondences = visitedVariables.get(parent);\r
- ArrayList<Variable> result = new ArrayList<Variable>(parentCorrespondences.length);\r
- for(Variable parentCorrespondence : parentCorrespondences) {\r
- Variable correspondence = parentCorrespondence.getPossibleChild(graph, name);\r
- if(correspondence != null)\r
- result.add(correspondence);\r
- }\r
- if(result.isEmpty())\r
- return EMPTY_VARIABLE_ARRAY;\r
- else\r
- return result.toArray(new Variable[result.size()]);\r
- }\r
- \r
- }\r
-}\r
+package org.simantics.structural.synchronization;
+
+import gnu.trove.map.hash.THashMap;
+import gnu.trove.map.hash.TObjectIntHashMap;
+
+import java.util.ArrayList;
+import java.util.Map;
+
+import org.simantics.databoard.Bindings;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.procedure.adapter.TransientCacheAsyncListener;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.genericrelation.DependencyChanges;
+import org.simantics.db.layer0.request.ModelInstances;
+import org.simantics.db.layer0.variable.Variable;
+import org.simantics.db.layer0.variable.Variables;
+import org.simantics.layer0.Layer0;
+import org.simantics.structural.stubs.StructuralResource2;
+import org.simantics.structural2.utils.StructuralChangeVisitor;
+import org.simantics.structural2.utils.StructuralMetadataUtils;
+
+/**
+ * Browses change metadata from the requested revision and
+ * marks the components in a flat structural configuration
+ * where changes have been occured.
+ *
+ * @author Hannu Niemistö
+ */
+public class StructuralChangeFlattener {
+
+ private static Variable[] EMPTY_VARIABLE_ARRAY = new Variable[0];
+
+ public static TObjectIntHashMap<Variable> getModifiedComponents(ReadGraph graph,
+ Variable rootVariable, long fromRevision) throws DatabaseException {
+ Visitor visitor = new Visitor(graph, rootVariable);
+ StructuralMetadataUtils.visitStructuralChangesFrom(graph,
+ Variables.getModel(graph, rootVariable),
+ fromRevision, visitor);
+ return visitor.modifiedComponents;
+ }
+
+ public static TObjectIntHashMap<Variable> getModifiedComponents(ReadGraph graph,
+ Variable rootVariable, DependencyChanges.Change[] changes) throws DatabaseException {
+ Visitor visitor = new Visitor(graph, rootVariable);
+ StructuralMetadataUtils.visitStructuralChangesFrom(graph,
+ Variables.getModel(graph, rootVariable),
+ changes, visitor);
+ return visitor.modifiedComponents;
+ }
+
+ private static class Visitor implements StructuralChangeVisitor {
+
+ Variable rootVariable;
+ Resource rootResource;
+ Resource model;
+ THashMap<Resource, Variable[]> visitedVariables = new THashMap<Resource, Variable[]>();
+ Layer0 L0;
+ StructuralResource2 STR;
+ TObjectIntHashMap<Variable> modifiedComponents = new TObjectIntHashMap<Variable>();
+
+ public Visitor(ReadGraph graph, Variable rootVariable) throws DatabaseException {
+ this.rootVariable = rootVariable;
+ this.rootResource = rootVariable.getRepresents(graph);
+ this.model = Variables.getModel(graph, rootVariable);
+ this.L0 = Layer0.getInstance(graph);
+ this.STR = StructuralResource2.getInstance(graph);
+ }
+
+ @Override
+ public void visitComponentChange(ReadGraph graph, Resource component, boolean componentItselfModified)
+ throws DatabaseException {
+ Variable[] variables = visitedVariables.get(component);
+ if(variables == null) {
+ variables = visitUnseenComponent(graph, component);
+ visitedVariables.put(component, variables);
+ }
+ if(componentItselfModified)
+ for(Variable variable : variables)
+ modifiedComponents.put(variable, 2);
+ else
+ for(Variable variable : variables)
+ modifiedComponents.putIfAbsent(variable, 1);
+ }
+
+ private Variable[] visitUnseenComponent(ReadGraph graph, Resource component) throws DatabaseException {
+ // Is root?
+ if(component.equals(rootResource))
+ return new Variable[] { rootVariable };
+
+ // Check if this a component type root
+ Resource componentType = graph.getPossibleObject(component, STR.Defines);
+ if(componentType != null) {
+ ArrayList<Variable> result = new ArrayList<Variable>();
+ Map<String,Resource> instances = graph.syncRequest(new ModelInstances(model, componentType), TransientCacheAsyncListener.<Map<String,Resource>>instance());
+ for(Resource instance : instances.values()) {
+ visitComponentChange(graph, instance, false);
+ for(Variable variable : visitedVariables.get(instance))
+ result.add(variable);
+ }
+ if(result.isEmpty())
+ return EMPTY_VARIABLE_ARRAY;
+ else
+ return result.toArray(new Variable[result.size()]);
+ }
+
+ // Check parent
+ Resource parent = graph.getPossibleObject(component, L0.PartOf);
+ String name = graph.getPossibleRelatedValue(component, L0.HasName, Bindings.STRING);
+ if(parent == null || name == null || !graph.isInstanceOf(component, STR.Component))
+ return EMPTY_VARIABLE_ARRAY;
+
+ visitComponentChange(graph, parent, false);
+ Variable[] parentCorrespondences = visitedVariables.get(parent);
+ ArrayList<Variable> result = new ArrayList<Variable>(parentCorrespondences.length);
+ for(Variable parentCorrespondence : parentCorrespondences) {
+ Variable correspondence = parentCorrespondence.getPossibleChild(graph, name);
+ if(correspondence != null)
+ result.add(correspondence);
+ }
+ if(result.isEmpty())
+ return EMPTY_VARIABLE_ARRAY;
+ else
+ return result.toArray(new Variable[result.size()]);
+ }
+
+ }
+}