1 package org.simantics.db.layer0.genericrelation;
\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
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
24 import gnu.trove.map.hash.THashMap;
\r
26 public class DependencyChangesWriter {
\r
30 THashMap<Resource, Change> changesByResource = new THashMap<>();
\r
31 ArrayList<ComponentRemoval> removals = new ArrayList<>();
\r
33 public DependencyChangesWriter(ReadGraph g) {
\r
35 this.l0 = Layer0.getInstance(g);
\r
38 public void addComponentModification(Resource component) throws DatabaseException {
\r
39 if (!component.isPersistent())
\r
41 if(!changesByResource.contains(component))
\r
42 changesByResource.put(component, new ComponentModification(component));
\r
45 public void addLinkChange(Resource component) throws DatabaseException {
\r
46 if (!component.isPersistent())
\r
48 //if(!changesByResource.contains(component))
\r
49 changesByResource.put(component, new LinkChange(component));
\r
52 public void addComponentAddition(Resource parent, Resource component) throws DatabaseException {
\r
53 if (!component.isPersistent())
\r
55 changesByResource.put(component, new ComponentAddition(component, parent));
\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
66 removals.add(new ComponentRemoval(component, parent));
\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
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
88 if (modelFound && change.getType() == ChangeType.COMPONENT_ADDITION) {
\r
89 hasUnresolved = true;
\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
105 modelChanges.add(removal);
\r
107 if(models.isEmpty() && !removedComponents.contains(parent)) {
\r
108 hasUnresolved = true;
\r
113 return new DependencyChanges(changes, hasUnresolved);
\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
122 modelChanges.add(change);
\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
130 return Collections.singleton(model);
\r
131 return graph.syncRequest(new IndexRoots(resource), TransientCacheListener.<Collection<Resource>>instance());
\r
133 return getModelsForRemoved(graph, removal.parent, removedComponents);
\r