1 package org.simantics.structural2.utils;
3 import gnu.trove.set.hash.THashSet;
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;
19 public class StructuralMetadataUtils {
21 private static ChangeVisitor getChangeVisitor(final ReadGraph graph, final Resource model, final StructuralChangeVisitor visitor) throws DatabaseException {
23 return new ChangeVisitor() {
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");
31 public void visit(ReadGraph graph, Change change, boolean inverted)
32 throws DatabaseException {
34 switch(change.getType()) {
35 case COMPONENT_ADDITION: {
36 ComponentAddition addition = (ComponentAddition)change;
38 visitor.visitComponentChange(graph, addition.parent, false);
40 visitor.visitComponentChange(graph, addition.component, true);
42 case COMPONENT_MODIFICATION: {
43 ComponentModification modification = (ComponentModification)change;
44 handleModification(graph, modification.component);
46 case COMPONENT_REMOVAL: {
47 ComponentRemoval removal = (ComponentRemoval)change;
49 visitor.visitComponentChange(graph, removal.component, true);
51 visitor.visitComponentChange(graph, removal.parent, false);
54 // Link changes should not affect the structural configuration
59 void handleModification(ReadGraph graph, Resource resource) throws DatabaseException {
60 if(!visited.add(resource))
62 if(!graph.hasStatement(resource))
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);
77 Resource connectionRelation = graph.getPossibleObject(resource, IsLiftedAs);
78 if(connectionRelation != null)
79 handleConnectionRelation(graph, connectionRelation);
81 for(Resource parent : graph.getObjects(resource, L0.IsDependencyOf))
82 handleModification(graph, parent);
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);
93 void handleConnectionRelation(ReadGraph graph, Resource connectionRelation) throws DatabaseException {
94 Resource componentType = graph.getPossibleObject(connectionRelation, L0.HasDomain);
95 if(componentType == null)
97 for(Resource instance : graph.syncRequest(new ModelInstances(model, componentType)).values())
98 for(Resource connection2 : graph.getObjects(instance, connectionRelation))
99 handleConnectionChange(graph, connection2);
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:
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>
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));
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));