]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.db.layer0/src/org/simantics/db/layer0/genericrelation/DependencyChangesWriter.java
Migrated source code from Simantics SVN
[simantics/platform.git] / bundles / org.simantics.db.layer0 / src / org / simantics / db / layer0 / genericrelation / DependencyChangesWriter.java
1 package org.simantics.db.layer0.genericrelation;\r
2 \r
3 import java.util.ArrayList;\r
4 import java.util.Collection;\r
5 import java.util.Collections;\r
6 import java.util.List;\r
7 import java.util.Map;\r
8 \r
9 import org.simantics.db.ReadGraph;\r
10 import org.simantics.db.Resource;\r
11 import org.simantics.db.common.procedure.adapter.TransientCacheListener;\r
12 import org.simantics.db.common.request.IndexRoots;\r
13 import org.simantics.db.common.request.PossibleIndexRoot;\r
14 import org.simantics.db.exception.DatabaseException;\r
15 import org.simantics.db.layer0.genericrelation.DependencyChanges.Change;\r
16 import org.simantics.db.layer0.genericrelation.DependencyChanges.ChangeType;\r
17 import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentAddition;\r
18 import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentModification;\r
19 import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentRemoval;\r
20 import org.simantics.db.layer0.genericrelation.DependencyChanges.LinkChange;\r
21 import org.simantics.db.service.CollectionSupport;\r
22 import org.simantics.layer0.Layer0;\r
23 \r
24 import gnu.trove.map.hash.THashMap;\r
25 \r
26 public class DependencyChangesWriter {\r
27     ReadGraph g;\r
28     Layer0 l0;\r
29 \r
30     THashMap<Resource, Change> changesByResource = new THashMap<>();\r
31     ArrayList<ComponentRemoval> removals = new ArrayList<>();\r
32 \r
33     public DependencyChangesWriter(ReadGraph g) {\r
34         this.g = g;\r
35         this.l0 = Layer0.getInstance(g);\r
36     }\r
37 \r
38     public void addComponentModification(Resource component) throws DatabaseException {\r
39         if (!component.isPersistent())\r
40             return;\r
41         if(!changesByResource.contains(component))\r
42             changesByResource.put(component, new ComponentModification(component));\r
43     }\r
44 \r
45     public void addLinkChange(Resource component) throws DatabaseException {\r
46         if (!component.isPersistent())\r
47             return;\r
48         //if(!changesByResource.contains(component))\r
49             changesByResource.put(component, new LinkChange(component));\r
50     }\r
51 \r
52     public void addComponentAddition(Resource parent, Resource component) throws DatabaseException {\r
53         if (!component.isPersistent())\r
54             return;\r
55         changesByResource.put(component, new ComponentAddition(component, parent));\r
56     }\r
57 \r
58     public void addComponentRemoval(Resource parent, Resource component) throws DatabaseException {\r
59 //      System.err.println("addComponentRemoval " + component);\r
60         // NOTE: removals are registered by their parent resource because the\r
61         // (component, PartOf, parent) link no longer exists and the model cannot\r
62         // be found otherwise.\r
63 //        changesByResource.put(parent, new ComponentRemoval(component, parent));\r
64         if (!component.isPersistent())\r
65             return;\r
66         removals.add(new ComponentRemoval(component, parent));\r
67     }\r
68 \r
69     public DependencyChanges getResult() throws DatabaseException {\r
70         THashMap<Resource, ArrayList<Change>> changes = new THashMap<>();\r
71         CollectionSupport cs = g.getService(CollectionSupport.class);\r
72         List<Resource> keys = cs.asSortedList(changesByResource.keySet());\r
73         boolean hasUnresolved = false;\r
74         for(Resource key : keys) {\r
75             Change change = changesByResource.get(key);\r
76             // Default logic with simpler index root resolution.\r
77             Resource model = g.syncRequest(new PossibleIndexRoot(key), TransientCacheListener.<Resource>instance());\r
78             boolean modelFound = model != null;\r
79             if (model != null) {\r
80                 addChange(model, change, changes);\r
81             } else {\r
82                 // Very heavy fallback logic\r
83                 Collection<Resource> models = g.syncRequest(new IndexRoots(key), TransientCacheListener.<Collection<Resource>>instance());\r
84                 for(Resource m : models)\r
85                     addChange(m, change, changes);\r
86                 modelFound = !models.isEmpty();\r
87             }\r
88             if (modelFound && change.getType() == ChangeType.COMPONENT_ADDITION) {\r
89                 hasUnresolved = true;\r
90             }\r
91         }\r
92         if (!removals.isEmpty()) {\r
93             THashMap<Resource, ComponentRemoval> removedComponents = new THashMap<>(removals.size());\r
94             for(ComponentRemoval removal : removals)\r
95                 removedComponents.put(removal.component, removal);\r
96             for(ComponentRemoval removal : removals) {\r
97                 Resource parent = removal.parent;\r
98                 Collection<Resource> models = getModelsForRemoved(g, parent, removedComponents); \r
99                 for(Resource model : models) {\r
100                     ArrayList<Change> modelChanges = changes.get(model);\r
101                     if(modelChanges == null) {\r
102                         modelChanges = new ArrayList<>();\r
103                         changes.put(model, modelChanges);\r
104                     }\r
105                     modelChanges.add(removal);\r
106                 }\r
107                 if(models.isEmpty() && !removedComponents.contains(parent)) {\r
108                     hasUnresolved = true;\r
109                 }\r
110             }\r
111         }\r
112 \r
113         return new DependencyChanges(changes, hasUnresolved);\r
114     }\r
115 \r
116     private void addChange(Resource model, Change change, Map<Resource, ArrayList<Change>> changes) {\r
117         ArrayList<Change> modelChanges = changes.get(model);\r
118         if(modelChanges == null) {\r
119             modelChanges = new ArrayList<>();\r
120             changes.put(model, modelChanges);\r
121         }\r
122         modelChanges.add(change);\r
123     }\r
124 \r
125     private Collection<Resource> getModelsForRemoved(ReadGraph graph, Resource resource, THashMap<Resource, ComponentRemoval> removedComponents) throws DatabaseException {\r
126         ComponentRemoval removal = removedComponents.get(resource);\r
127         if(removal == null) {\r
128             Resource model = g.syncRequest(new PossibleIndexRoot(resource), TransientCacheListener.<Resource>instance());\r
129             if (model != null)\r
130                 return Collections.singleton(model);\r
131             return graph.syncRequest(new IndexRoots(resource), TransientCacheListener.<Collection<Resource>>instance());\r
132         }\r
133         return getModelsForRemoved(graph, removal.parent, removedComponents);\r
134     }\r
135     \r
136 }\r