]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.structural2/src/org/simantics/structural2/utils/StructuralMetadataUtils.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.structural2 / src / org / simantics / structural2 / utils / StructuralMetadataUtils.java
1 package org.simantics.structural2.utils;\r
2 \r
3 import gnu.trove.set.hash.THashSet;\r
4 \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
18 \r
19 public class StructuralMetadataUtils {\r
20 \r
21         private static ChangeVisitor getChangeVisitor(final ReadGraph graph, final Resource model, final StructuralChangeVisitor visitor) throws DatabaseException {\r
22                 \r
23                 return new ChangeVisitor() {\r
24             \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
29             \r
30             @Override\r
31             public void visit(ReadGraph graph, Change change, boolean inverted)\r
32                     throws DatabaseException {\r
33                 \r
34                 switch(change.getType()) {\r
35                 case COMPONENT_ADDITION: {\r
36                     ComponentAddition addition = (ComponentAddition)change;\r
37                     if(inverted)\r
38                         visitor.visitComponentChange(graph, addition.parent, false);\r
39                     else\r
40                         visitor.visitComponentChange(graph, addition.component, true);\r
41                 } break;\r
42                 case COMPONENT_MODIFICATION: {\r
43                     ComponentModification modification = (ComponentModification)change;\r
44                     handleModification(graph, modification.component);\r
45                 } break;\r
46                 case COMPONENT_REMOVAL: {\r
47                     ComponentRemoval removal = (ComponentRemoval)change;\r
48                     if(inverted)\r
49                         visitor.visitComponentChange(graph, removal.component, true);\r
50                     else\r
51                         visitor.visitComponentChange(graph, removal.parent, false);\r
52                 } break;\r
53                 case LINK_CHANGE:\r
54                     // Link changes should not affect the structural configuration \r
55                     break;\r
56                 }\r
57             }\r
58             \r
59             void handleModification(ReadGraph graph, Resource resource) throws DatabaseException {\r
60                 if(!visited.add(resource))\r
61                     return;\r
62                 if(!graph.hasStatement(resource))\r
63                     return;\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
76                 else {\r
77                     Resource connectionRelation = graph.getPossibleObject(resource, IsLiftedAs);\r
78                     if(connectionRelation != null)\r
79                         handleConnectionRelation(graph, connectionRelation);\r
80                     else\r
81                         for(Resource parent : graph.getObjects(resource, L0.IsDependencyOf))\r
82                             handleModification(graph, parent);\r
83                 }\r
84             }\r
85 \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
91             }\r
92             \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
96                     return;\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
100             }\r
101             \r
102         };\r
103         }\r
104         \r
105     /**\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
110      * <ul>\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
115      * </ul>\r
116      */\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
120     }\r
121 \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
125     }\r
126     \r
127 }\r