]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.issues.common/src/org/simantics/issues/common/ConstraintIssueSource.java
Improvements to constraint-based issues
[simantics/platform.git] / bundles / org.simantics.issues.common / src / org / simantics / issues / common / ConstraintIssueSource.java
diff --git a/bundles/org.simantics.issues.common/src/org/simantics/issues/common/ConstraintIssueSource.java b/bundles/org.simantics.issues.common/src/org/simantics/issues/common/ConstraintIssueSource.java
new file mode 100644 (file)
index 0000000..0b02c0e
--- /dev/null
@@ -0,0 +1,126 @@
+/*******************************************************************************
+ * Copyright (c) 2019 Association for Decentralized Information Management in
+ * Industry THTH ry.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ *     Semantum Oy - initial API and implementation
+ *******************************************************************************/
+package org.simantics.issues.common;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.simantics.db.Issue;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.common.QueryMemoryWatcher;
+import org.simantics.db.common.utils.Logger;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.util.ModelTransferableGraphSourceRequest.DomainOnlyProcessor;
+import org.simantics.db.service.CollectionSupport;
+import org.simantics.db.service.QueryControl;
+import org.simantics.issues.ontology.IssueResource;
+import org.simantics.layer0.Layer0;
+import org.simantics.scl.db.SCLFunctions;
+import org.simantics.scl.runtime.function.Function1;
+
+import gnu.trove.set.hash.THashSet;
+
+/**
+ * @author Antti Villberg
+ */
+public class ConstraintIssueSource implements BatchIssueSource {
+
+    private final Resource resource;
+
+    public ConstraintIssueSource(Resource resource) {
+        this.resource = resource;
+    }
+
+    @Override
+    public Map<Resource, Set<Issue>> run(IProgressMonitor monitor, ReadGraph graph, BatchIssueValidationContext context) throws DatabaseException {
+
+        Layer0 L0 = Layer0.getInstance(graph);
+        Set<Issue> emptySet = Collections.emptySet();
+        CollectionSupport cs = graph.getService(CollectionSupport.class);
+        Map<Resource,Set<Issue>> result = cs.createMap(Set.class);
+        monitor.setTaskName("Constraint analysis");
+
+        DomainOnlyProcessor domain = context.domain;
+
+        int entityCount = domain.internals.size();
+
+        IssueResource ISSUE = IssueResource.getInstance(graph);
+        Resource type = graph.getSingleType(resource, ISSUE.IssueSource);
+        List<Function1<Resource, List<Issue>>> validators = new ArrayList<>();
+        for(Resource constraint : graph.getObjects(type, ISSUE.IssueSource_HasConstraint)) {
+            Function1<Resource, List<Issue>> validator = graph.getRelatedValue2(constraint, L0.Constraint_Validator, constraint);
+            //Resource function = graph.getSingleObject(constraint, L0.Constraint_Validator);
+            validators.add(validator);
+        }
+
+        QueryControl qc = graph.getService(QueryControl.class);
+        qc.flush(graph);
+
+        // Allow this process to make 50k queries
+        QueryMemoryWatcher memory = new QueryMemoryWatcher(graph, 50000, 0.5, 300);
+
+        SCLFunctions.runWithGraph(graph, () -> {
+
+            int totalExaminedCount = 0;
+            int examinedCount = 1000;
+
+            for(Resource r : domain.internals) {
+
+                Set<Issue> set = emptySet;
+                if (examinedCount >= 1000) {
+                    monitor.subTask(contextProgressMessage(totalExaminedCount, entityCount));
+                    examinedCount = 0;
+                    if(monitor.isCanceled()) return;
+                    memory.maintain();
+                }
+                for(Function1<Resource, List<Issue>> validator : validators) {
+                    try {
+                        @SuppressWarnings("unchecked")
+                        List<Issue> issues = validator.apply(r);//(List<Issue>)Functions.exec(graph, validator, graph, r);
+                        if (issues != null && !issues.isEmpty()) {
+                            if (set == emptySet)
+                                set = new THashSet<>();
+                            set.addAll(issues);
+                        }
+                    } catch (Throwable t) {
+                        Logger.defaultLogError(t);
+                    }
+                }
+                ++totalExaminedCount;
+                ++examinedCount;
+                if(!set.isEmpty())
+                    result.put(r, set);
+            }
+
+        });
+
+        return result;
+
+    }
+
+    private static String contextProgressMessage(int totalExaminedCount, int entityCount) {
+        StringBuilder sb = new StringBuilder(80)
+        .append("Validating resources").append(" ").append(100*totalExaminedCount / entityCount).append("% ready.");
+        return sb.toString();
+    }
+
+    @Override
+    public Resource getResource() {
+        return resource;
+    }
+
+}