X-Git-Url: https://gerrit.simantics.org/r/gitweb?p=simantics%2Fplatform.git;a=blobdiff_plain;f=bundles%2Forg.simantics.issues.common%2Fsrc%2Forg%2Fsimantics%2Fissues%2Fcommon%2FDependencyIssueSource2.java;fp=bundles%2Forg.simantics.issues.common%2Fsrc%2Forg%2Fsimantics%2Fissues%2Fcommon%2FDependencyIssueSource2.java;h=37669ab581ec74b6878da15cad9476287846b907;hp=0000000000000000000000000000000000000000;hb=969bd23cab98a79ca9101af33334000879fb60c5;hpb=866dba5cd5a3929bbeae85991796acb212338a08 diff --git a/bundles/org.simantics.issues.common/src/org/simantics/issues/common/DependencyIssueSource2.java b/bundles/org.simantics.issues.common/src/org/simantics/issues/common/DependencyIssueSource2.java new file mode 100644 index 000000000..37669ab58 --- /dev/null +++ b/bundles/org.simantics.issues.common/src/org/simantics/issues/common/DependencyIssueSource2.java @@ -0,0 +1,183 @@ +package org.simantics.issues.common; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.CopyOnWriteArraySet; + +import org.simantics.Simantics; +import org.simantics.db.MetadataI; +import org.simantics.db.ReadGraph; +import org.simantics.db.Resource; +import org.simantics.db.WriteGraph; +import org.simantics.db.common.Indexing; +import org.simantics.db.common.changeset.GenericChangeListener; +import org.simantics.db.common.procedure.adapter.TransientCacheListener; +import org.simantics.db.common.request.PossibleTypedParent; +import org.simantics.db.common.utils.Functions; +import org.simantics.db.common.utils.NameUtils; +import org.simantics.db.event.ChangeListener; +import org.simantics.db.exception.DatabaseException; +import org.simantics.db.layer0.genericrelation.DependenciesRelation.DependencyChangesRequest; +import org.simantics.db.layer0.genericrelation.DependencyChanges; +import org.simantics.db.service.GraphChangeListenerSupport; +import org.simantics.issues.ontology.IssueResource; +import org.simantics.layer0.Layer0; +import org.simantics.scl.runtime.function.Function2; +import org.simantics.simulation.ontology.SimulationResource; + +public class DependencyIssueSource2 implements IssueSource { + + public static final boolean DEBUG = false; + + private Resource source; + private Resource model; + private Resource type; + private Set searchTypes; + private Resource base; + private Resource extensionFunction; + + private CopyOnWriteArraySet, Boolean>> listeners = new CopyOnWriteArraySet<>(); + private ConcurrentMap, Boolean>, ChangeListener> listenerMap = new ConcurrentHashMap<>(); + + public DependencyIssueSource2(ReadGraph graph, Resource source) throws DatabaseException { + Layer0 L0 = Layer0.getInstance(graph); + IssueResource IR = IssueResource.getInstance(graph); + this.source = source; + this.model = graph.syncRequest(new PossibleTypedParent(source, SimulationResource.getInstance(graph).Model)); + this.extensionFunction = graph.getPossibleObject(source, IR.Sources_DependencyTracker_HasExtension); + this.type = graph.getSingleObject(source, IR.Sources_DependencyTracker_HasType); + HashSet _searchTypes = new HashSet<>(); + _searchTypes.addAll(graph.getObjects(source, IR.Sources_DependencyTracker_HasSearchType)); + _searchTypes.add(type); + this.searchTypes = new HashSet<>(_searchTypes); + Resource baseFunction = graph.getSingleObject(source, IR.Sources_DependencyTracker_HasBaseFunction); + this.base = Functions.exec(graph, baseFunction, graph, graph.getSingleObject(source, L0.PartOf)); + } + + private List resourcesToCheck(ReadGraph graph, DependencyChanges event) throws DatabaseException { + + HashSet depSet = new HashSet<>(); + + if(DEBUG) { + System.err.println("resourcesToCheck[" + NameUtils.getSafeName(graph, source) + "] - component changes for type " + NameUtils.getSafeName(graph, searchTypes)); + } + + depSet.addAll(IssueSourceUtils.getChangedDependencies(graph, model, base, searchTypes, event)); + depSet.addAll(IssueSourceUtils.getChangedDependencies(graph, source, model, base, searchTypes)); + + List deps = new ArrayList<>(depSet); + + if(DEBUG) { + System.err.println("resourcesToCheck[" + NameUtils.getSafeName(graph, source) + "] " + deps); + for(Resource r : deps) { + System.err.println("dep " + NameUtils.getSafeName(graph, r)); + } + } + + if(extensionFunction != null) { + try { + deps = Functions.exec(graph, extensionFunction, graph, deps); + } catch (Throwable t) { + t.printStackTrace(); + } + } + + if(DEBUG) { + for(Resource r : deps) { + System.err.println("dep extension " + NameUtils.getSafeName(graph, r)); + } + } + + ArrayList result = new ArrayList<>(); + for(Resource dep : deps) { + // TODO: still not complete - e.g. someone can replace the InstanceOf + Set types = graph.getTypes(dep); + if(types.isEmpty() || types.contains(type)) result.add(dep); + } + return result; + + } + + class DependencyChangeListener extends GenericChangeListener { + + private boolean isValid(ReadGraph graph, List toCheck) throws DatabaseException { + for(Resource resource : toCheck) { + if(!graph.syncRequest(new DependencyIssueValidator2(resource, model, source), TransientCacheListener.instance())) { + return false; + } + } + return true; + } + + @Override + public boolean preEventRequest() { + return !Indexing.isDependenciesIndexingDisabled(); + } + + @Override + public void onEvent(ReadGraph graph, MetadataI metadata, DependencyChanges event) throws DatabaseException { + + List toCheck = resourcesToCheck(graph, event); + if(!isValid(graph, toCheck)) { + for(Function2, Boolean> r : listeners) { + r.apply(graph, toCheck); + } + } + + if(graph instanceof WriteGraph) { + IssueSourceUtils.update((WriteGraph)graph, source); + } + } + + } + + @Override + public void addDirtyListener(Function2, Boolean> runnable) { + boolean added = listeners.add(runnable); + if (added) { + GraphChangeListenerSupport changeSupport = Simantics.getSession().getService(GraphChangeListenerSupport.class); + ChangeListener metadataListener = new DependencyChangeListener(); + listenerMap.put(runnable, metadataListener); + changeSupport.addMetadataListener(metadataListener); + } + } + + @Override + public void removeDirtyListener(Function2, Boolean> runnable) { + boolean removed = listeners.remove(runnable); + ChangeListener metadataListener = listenerMap.remove(runnable); + if (removed && metadataListener != null) { + GraphChangeListenerSupport changeSupport = Simantics.getSession().getService(GraphChangeListenerSupport.class); + changeSupport.removeMetadataListener(metadataListener); + } + } + + @Override + public void update(WriteGraph graph, List resources) throws DatabaseException { + + for(Resource resource : resources) { + if(!graph.syncRequest(new DependencyIssueValidator2(resource, model, source), TransientCacheListener.instance())) { + new DependencyIssueSynchronizer2(resource, source).perform(graph); + } + } + + IssueSourceUtils.update(graph, source); + + } + + @Override + public boolean needUpdate(ReadGraph graph, List resources) throws DatabaseException { + + for(Resource resource : resources) { + if(!graph.syncRequest(new DependencyIssueValidator2(resource, model, source), TransientCacheListener.instance())) return true; + } + + return false; + + } + +}