package org.simantics.db.layer0.genericrelation; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.common.procedure.adapter.TransientCacheListener; import org.simantics.db.common.request.IndexRoots; import org.simantics.db.common.request.PossibleIndexRoot; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.genericrelation.DependencyChanges.Change; import org.simantics.db.layer0.genericrelation.DependencyChanges.ChangeType; import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentAddition; import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentModification; import org.simantics.db.layer0.genericrelation.DependencyChanges.ComponentRemoval; import org.simantics.db.layer0.genericrelation.DependencyChanges.LinkChange; import org.simantics.db.service.CollectionSupport; import org.simantics.layer0.Layer0; import gnu.trove.map.hash.THashMap; public class DependencyChangesWriter { ReadGraph g; Layer0 l0; THashMap changesByResource = new THashMap<>(); ArrayList removals = new ArrayList<>(); public DependencyChangesWriter(ReadGraph g) { this.g = g; this.l0 = Layer0.getInstance(g); } public void addComponentModification(Resource component) throws DatabaseException { if (!component.isPersistent()) return; if(!changesByResource.contains(component)) changesByResource.put(component, new ComponentModification(component)); } public void addLinkChange(Resource component) throws DatabaseException { if (!component.isPersistent()) return; //if(!changesByResource.contains(component)) changesByResource.put(component, new LinkChange(component)); } public void addComponentAddition(Resource parent, Resource component) throws DatabaseException { if (!component.isPersistent()) return; changesByResource.put(component, new ComponentAddition(component, parent)); } public void addComponentRemoval(Resource parent, Resource component) throws DatabaseException { // System.err.println("addComponentRemoval " + component); // NOTE: removals are registered by their parent resource because the // (component, PartOf, parent) link no longer exists and the model cannot // be found otherwise. // changesByResource.put(parent, new ComponentRemoval(component, parent)); if (!component.isPersistent()) return; removals.add(new ComponentRemoval(component, parent)); } public DependencyChanges getResult() throws DatabaseException { THashMap> changes = new THashMap<>(); CollectionSupport cs = g.getService(CollectionSupport.class); List keys = cs.asSortedList(changesByResource.keySet()); boolean hasUnresolved = false; for(Resource key : keys) { Change change = changesByResource.get(key); // Default logic with simpler index root resolution. Resource model = g.syncRequest(new PossibleIndexRoot(key), TransientCacheListener.instance()); boolean modelFound = model != null; if (model != null) { addChange(model, change, changes); } else { // Very heavy fallback logic Collection models = g.syncRequest(new IndexRoots(key), TransientCacheListener.>instance()); for(Resource m : models) addChange(m, change, changes); modelFound = !models.isEmpty(); } if (modelFound && change.getType() == ChangeType.COMPONENT_ADDITION) { hasUnresolved = true; } } if (!removals.isEmpty()) { THashMap removedComponents = new THashMap<>(removals.size()); for(ComponentRemoval removal : removals) removedComponents.put(removal.component, removal); for(ComponentRemoval removal : removals) { Resource parent = removal.parent; Collection models = getModelsForRemoved(g, parent, removedComponents); for(Resource model : models) { ArrayList modelChanges = changes.get(model); if(modelChanges == null) { modelChanges = new ArrayList<>(); changes.put(model, modelChanges); } modelChanges.add(removal); } if(models.isEmpty() && !removedComponents.contains(parent)) { hasUnresolved = true; } } } return new DependencyChanges(changes, hasUnresolved); } private void addChange(Resource model, Change change, Map> changes) { ArrayList modelChanges = changes.get(model); if(modelChanges == null) { modelChanges = new ArrayList<>(); changes.put(model, modelChanges); } modelChanges.add(change); } private Collection getModelsForRemoved(ReadGraph graph, Resource resource, THashMap removedComponents) throws DatabaseException { ComponentRemoval removal = removedComponents.get(resource); if(removal == null) { Resource model = g.syncRequest(new PossibleIndexRoot(resource), TransientCacheListener.instance()); if (model != null) return Collections.singleton(model); return graph.syncRequest(new IndexRoots(resource), TransientCacheListener.>instance()); } return getModelsForRemoved(graph, removal.parent, removedComponents); } }