1 package org.simantics.db.layer0.genericrelation;
3 import java.util.ArrayList;
4 import java.util.Collection;
5 import java.util.Collections;
9 import org.simantics.db.ReadGraph;
10 import org.simantics.db.Resource;
11 import org.simantics.db.common.procedure.adapter.TransientCacheListener;
12 import org.simantics.db.common.request.IndexRoots;
13 import org.simantics.db.common.request.PossibleIndexRoot;
14 import org.simantics.db.exception.DatabaseException;
15 import org.simantics.db.layer0.genericrelation.DependencyChanges.Change;
16 import org.simantics.db.layer0.genericrelation.DependencyChanges.ChangeType;
17 import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentAddition;
18 import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentModification;
19 import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentRemoval;
20 import org.simantics.db.layer0.genericrelation.DependencyChanges.LinkChange;
21 import org.simantics.db.service.CollectionSupport;
22 import org.simantics.layer0.Layer0;
24 import gnu.trove.map.hash.THashMap;
26 public class DependencyChangesWriter {
30 THashMap<Resource, Change> changesByResource = new THashMap<>();
31 ArrayList<ComponentRemoval> removals = new ArrayList<>();
33 public DependencyChangesWriter(ReadGraph g) {
35 this.l0 = Layer0.getInstance(g);
38 public void addComponentModification(Resource component) throws DatabaseException {
39 if (!component.isPersistent())
41 if(!changesByResource.contains(component))
42 changesByResource.put(component, new ComponentModification(component));
45 public void addLinkChange(Resource component) throws DatabaseException {
46 if (!component.isPersistent())
48 //if(!changesByResource.contains(component))
49 changesByResource.put(component, new LinkChange(component));
52 public void addComponentAddition(Resource parent, Resource component) throws DatabaseException {
53 if (!component.isPersistent())
55 changesByResource.put(component, new ComponentAddition(component, parent));
58 public void addComponentRemoval(Resource parent, Resource component) throws DatabaseException {
59 // System.err.println("addComponentRemoval " + component);
60 // NOTE: removals are registered by their parent resource because the
61 // (component, PartOf, parent) link no longer exists and the model cannot
62 // be found otherwise.
63 // changesByResource.put(parent, new ComponentRemoval(component, parent));
64 if (!component.isPersistent())
66 removals.add(new ComponentRemoval(component, parent));
69 public DependencyChanges getResult() throws DatabaseException {
70 THashMap<Resource, ArrayList<Change>> changes = new THashMap<>();
71 CollectionSupport cs = g.getService(CollectionSupport.class);
72 List<Resource> keys = cs.asSortedList(changesByResource.keySet());
73 boolean hasUnresolved = false;
74 for(Resource key : keys) {
75 Change change = changesByResource.get(key);
76 // Default logic with simpler index root resolution.
77 Resource model = g.syncRequest(new PossibleIndexRoot(key), TransientCacheListener.<Resource>instance());
78 boolean modelFound = model != null;
80 addChange(model, change, changes);
82 // Very heavy fallback logic
83 Collection<Resource> models = g.syncRequest(new IndexRoots(key), TransientCacheListener.<Collection<Resource>>instance());
84 for(Resource m : models)
85 addChange(m, change, changes);
86 modelFound = !models.isEmpty();
88 if (modelFound && change.getType() == ChangeType.COMPONENT_ADDITION) {
92 if (!removals.isEmpty()) {
93 THashMap<Resource, ComponentRemoval> removedComponents = new THashMap<>(removals.size());
94 for(ComponentRemoval removal : removals)
95 removedComponents.put(removal.component, removal);
96 for(ComponentRemoval removal : removals) {
97 Resource parent = removal.parent;
98 Collection<Resource> models = getModelsForRemoved(g, parent, removedComponents);
99 for(Resource model : models) {
100 ArrayList<Change> modelChanges = changes.get(model);
101 if(modelChanges == null) {
102 modelChanges = new ArrayList<>();
103 changes.put(model, modelChanges);
105 modelChanges.add(removal);
107 if(models.isEmpty() && !removedComponents.contains(parent)) {
108 hasUnresolved = true;
113 return new DependencyChanges(changes, hasUnresolved);
116 private void addChange(Resource model, Change change, Map<Resource, ArrayList<Change>> changes) {
117 ArrayList<Change> modelChanges = changes.get(model);
118 if(modelChanges == null) {
119 modelChanges = new ArrayList<>();
120 changes.put(model, modelChanges);
122 modelChanges.add(change);
125 private Collection<Resource> getModelsForRemoved(ReadGraph graph, Resource resource, THashMap<Resource, ComponentRemoval> removedComponents) throws DatabaseException {
126 ComponentRemoval removal = removedComponents.get(resource);
127 if(removal == null) {
128 Resource model = g.syncRequest(new PossibleIndexRoot(resource), TransientCacheListener.<Resource>instance());
130 return Collections.singleton(model);
131 return graph.syncRequest(new IndexRoots(resource), TransientCacheListener.<Collection<Resource>>instance());
133 return getModelsForRemoved(graph, removal.parent, removedComponents);