1 package org.simantics.structural2.utils;
\r
3 import gnu.trove.set.hash.THashSet;
\r
5 import org.simantics.db.ReadGraph;
\r
6 import org.simantics.db.Resource;
\r
7 import org.simantics.db.exception.DatabaseException;
\r
8 import org.simantics.db.layer0.changeset.ChangeVisitor;
\r
9 import org.simantics.db.layer0.changeset.MetadataUtils;
\r
10 import org.simantics.db.layer0.genericrelation.DependencyChanges;
\r
11 import org.simantics.db.layer0.genericrelation.DependencyChanges.Change;
\r
12 import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentAddition;
\r
13 import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentModification;
\r
14 import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentRemoval;
\r
15 import org.simantics.db.layer0.request.ModelInstances;
\r
16 import org.simantics.layer0.Layer0;
\r
17 import org.simantics.structural.stubs.StructuralResource2;
\r
19 public class StructuralMetadataUtils {
\r
21 private static ChangeVisitor getChangeVisitor(final ReadGraph graph, final Resource model, final StructuralChangeVisitor visitor) throws DatabaseException {
\r
23 return new ChangeVisitor() {
\r
25 Layer0 L0 = Layer0.getInstance(graph);
\r
26 StructuralResource2 STR = StructuralResource2.getInstance(graph);
\r
27 THashSet<Resource> visited = new THashSet<Resource>();
\r
28 Resource IsLiftedAs = graph.getResource("http://www.simantics.org/Diagram-2.2/IsLiftedAs");
\r
31 public void visit(ReadGraph graph, Change change, boolean inverted)
\r
32 throws DatabaseException {
\r
34 switch(change.getType()) {
\r
35 case COMPONENT_ADDITION: {
\r
36 ComponentAddition addition = (ComponentAddition)change;
\r
38 visitor.visitComponentChange(graph, addition.parent, false);
\r
40 visitor.visitComponentChange(graph, addition.component, true);
\r
42 case COMPONENT_MODIFICATION: {
\r
43 ComponentModification modification = (ComponentModification)change;
\r
44 handleModification(graph, modification.component);
\r
46 case COMPONENT_REMOVAL: {
\r
47 ComponentRemoval removal = (ComponentRemoval)change;
\r
49 visitor.visitComponentChange(graph, removal.component, true);
\r
51 visitor.visitComponentChange(graph, removal.parent, false);
\r
54 // Link changes should not affect the structural configuration
\r
59 void handleModification(ReadGraph graph, Resource resource) throws DatabaseException {
\r
60 if(!visited.add(resource))
\r
62 if(!graph.hasStatement(resource))
\r
64 //System.out.println("handleModification: " + graph.getPossibleURI(resource));
\r
65 if(graph.isInstanceOf(resource, STR.Component))
\r
66 visitor.visitComponentChange(graph, resource, true);
\r
67 else if(graph.isInstanceOf(resource, STR.Connection))
\r
68 for(Resource connection : StructuralUtils.getRelatedConnections(graph, resource))
\r
69 handleConnectionChange(graph, connection);
\r
70 else if(graph.isInstanceOf(resource, STR.ConnectionJoin))
\r
71 for(Resource connection : StructuralUtils.getRelatedConnectionsOfConnectionJoin(graph, resource))
\r
72 handleConnectionChange(graph, connection);
\r
73 else if(graph.isInstanceOf(resource, STR.ComponentType))
\r
74 for(Resource instance : graph.syncRequest(new ModelInstances(model, resource)).values())
\r
75 visitor.visitComponentChange(graph, instance, true);
\r
77 Resource connectionRelation = graph.getPossibleObject(resource, IsLiftedAs);
\r
78 if(connectionRelation != null)
\r
79 handleConnectionRelation(graph, connectionRelation);
\r
81 for(Resource parent : graph.getObjects(resource, L0.IsDependencyOf))
\r
82 handleModification(graph, parent);
\r
86 void handleConnectionChange(ReadGraph graph, Resource connection) throws DatabaseException {
\r
87 for(Resource component : graph.getObjects(connection, STR.Connects))
\r
88 visitor.visitComponentChange(graph, component, true);
\r
89 for(Resource connectionRelation : graph.getObjects(connection, STR.Binds))
\r
90 handleConnectionRelation(graph, connectionRelation);
\r
93 void handleConnectionRelation(ReadGraph graph, Resource connectionRelation) throws DatabaseException {
\r
94 Resource componentType = graph.getPossibleObject(connectionRelation, L0.HasDomain);
\r
95 if(componentType == null)
\r
97 for(Resource instance : graph.syncRequest(new ModelInstances(model, componentType)).values())
\r
98 for(Resource connection2 : graph.getObjects(instance, connectionRelation))
\r
99 handleConnectionChange(graph, connection2);
\r
106 * Finds all structural changes made to the given {@code model} from the given revision and calls
\r
107 * the {@code visitor} for them.
\r
108 * The function processes raw metadata about modifications to resources and produces changes
\r
109 * to components. It implements the following rules:
\r
111 * <li>Component removal implies a change to the parent of the component</li>
\r
112 * <li>Component addition implies a change to the added component.</li>
\r
113 * <li>A modification in the connection or join implies a change to all reachable components of the connection</li>
\r
114 * <li>A modification in a component type implies a change to all its instances</li>
\r
117 public static void visitStructuralChangesFrom(final ReadGraph graph, final Resource model, long fromRevision,
\r
118 final StructuralChangeVisitor visitor) throws DatabaseException {
\r
119 MetadataUtils.visitDependencyChangesFrom(graph, model, fromRevision, getChangeVisitor(graph, model, visitor));
\r
122 public static void visitStructuralChangesFrom(final ReadGraph graph, final Resource model, DependencyChanges.Change[] changes,
\r
123 final StructuralChangeVisitor visitor) throws DatabaseException {
\r
124 MetadataUtils.visitDependencyChangesFrom2(graph, model, changes, getChangeVisitor(graph, model, visitor));
\r