]> gerrit.simantics Code Review - simantics/platform.git/blobdiff - bundles/org.simantics.issues.common/src/org/simantics/issues/common/BatchValidations.java
Improvements to constraint-based issues
[simantics/platform.git] / bundles / org.simantics.issues.common / src / org / simantics / issues / common / BatchValidations.java
diff --git a/bundles/org.simantics.issues.common/src/org/simantics/issues/common/BatchValidations.java b/bundles/org.simantics.issues.common/src/org/simantics/issues/common/BatchValidations.java
new file mode 100644 (file)
index 0000000..0800560
--- /dev/null
@@ -0,0 +1,178 @@
+/*******************************************************************************
+ * 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:
+ *     VTT Technical Research Centre of Finland - initial API and implementation
+ *     Semantum Oy - Reorganization
+ *******************************************************************************/
+package org.simantics.issues.common;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.eclipse.core.runtime.IProgressMonitor;
+import org.simantics.Simantics;
+import org.simantics.db.Issue;
+import org.simantics.db.ReadGraph;
+import org.simantics.db.Resource;
+import org.simantics.db.Session;
+import org.simantics.db.Statement;
+import org.simantics.db.VirtualGraph;
+import org.simantics.db.WriteGraph;
+import org.simantics.db.common.request.WriteRequest;
+import org.simantics.db.exception.DatabaseException;
+import org.simantics.db.layer0.util.RemoverUtil;
+import org.simantics.db.service.VirtualGraphSupport;
+import org.simantics.issues.ontology.IssueResource;
+import org.simantics.layer0.Layer0;
+
+import gnu.trove.set.hash.THashSet;
+
+public class BatchValidations {
+
+       private static final boolean PERF = false;
+
+       public static Map<Resource, Set<Issue>> validate(IProgressMonitor monitor, BatchIssueSource source, BatchIssueValidationContext context) throws DatabaseException {
+               Session session = Simantics.getSession();
+               return session.syncRequest(new ComposedValidation(monitor, source, context));
+       }
+
+       /**
+        * @param monitor
+        * @param source
+        * @param issues
+        * @return
+        * @throws DatabaseException
+        */
+       public static int store(final IProgressMonitor monitor,
+                       final Resource source, final Map<Resource, Set<Issue>> issues)
+                       throws DatabaseException {
+               return store(monitor, source, issues, Integer.MAX_VALUE);
+       }
+
+       /**
+        * @param monitor
+        * @param source
+        * @param issues
+        * @param maxIssuesToWrite
+        * @return number of issues written (added)
+        * @throws DatabaseException
+        */
+       public static int store(final IProgressMonitor monitor,
+                       final Resource source, final Map<Resource, Set<Issue>> issues,
+                       final int maxIssuesToWrite) throws DatabaseException {
+
+               if (issues.isEmpty() || maxIssuesToWrite <= 0)
+                       return 0;
+
+               Session session = Simantics.getSession();
+               VirtualGraphSupport support = session.getService(VirtualGraphSupport.class);
+               VirtualGraph vg = support.getWorkspacePersistent(IssueConstants.ISSUE_VG);
+               final int[] writtenIssues = { 0 };
+
+               session.syncRequest(new WriteRequest(vg) {
+
+                       @Override
+                       public void perform(WriteGraph graph) throws DatabaseException {
+
+                               for(Map.Entry<Resource, Set<Issue>> entry : issues.entrySet()) {
+
+                                       if (monitor.isCanceled())
+                                               return;
+
+                                       Resource context = entry.getKey();
+
+                                       Set<Issue> current = entry.getValue();
+                                       Set<Issue> existing = graph.sync(new BatchIssueDescriptions(source, context));
+
+                                       if(!existing.equals(current)) {
+
+                                               Set<Issue> added = new THashSet<Issue>(current);
+                                               Set<Issue> removed = new THashSet<Issue>(existing);
+                                               added.removeAll(existing);
+                                               removed.removeAll(current);
+
+                                               for(Issue add : added) {
+                                                       add.write(graph, source);
+                                                       // Stop if write limit is reached.
+                                                       if (++writtenIssues[0] >= maxIssuesToWrite)
+                                                               return;
+                                               }
+                                               for(Issue remove : removed) {
+                                                       Resource issue = graph.sync(new IssueByList(source, remove));
+                                                       if (issue == null)
+                                                               // FIXME: when can this happen and what should be done in this case?
+                                                               continue;
+                                                       graph.deny(issue, Layer0.getInstance(graph).PartOf);
+                                                       graph.deny(source, IssueResource.getInstance(graph).IssueSource_Manages, issue);
+                                                       RemoverUtil.remove(graph, issue);
+                                               }
+
+                                       }
+
+                               }
+
+                       }
+               });
+
+               return writtenIssues[0];
+
+       }
+
+       /**
+        * @param map
+        * @return
+        */
+       @SuppressWarnings("rawtypes")
+       private static int count(Map map) {
+               int result = 0;
+               for (Object obj : map.values()) {
+                       if (obj instanceof Set<?>) {
+                               Set<?> set = (Set<?>) obj;
+                               result += set.size();
+                       }
+               }
+               return result;
+       }
+
+       /**
+        * Checks if the specified <code>resourceToCheckForLinks</code> is linked to
+        * anything else besides itself and <code>excludeLinksTo</code>.
+        * 
+        * <p>
+        * This is used to if an issue context is still valid. We consider any issue
+        * context that is not attached to something else besides its issue context to
+        * be an invalid issue. Assertions and L0.InstanceOf do not count as external
+        * links.
+        * 
+        * @param graph database access handle
+        * @param resourceToCheckForLinks the resource to check for "external" links
+        * @param excludeLinksTo exclude links to this resource from evaluation
+        * @return <code>true</code> if there are links, <code>false</code> otherwise
+        * @throws DatabaseException 
+        */
+       public static boolean isLinkedToOtherThan(ReadGraph graph, Resource resourceToCheckForLinks,
+                       Resource excludeLinksTo)
+                                       throws DatabaseException
+       {
+               Layer0 L0 = Layer0.getInstance(graph);
+               for (Statement stm : graph.getStatements(resourceToCheckForLinks, L0.IsWeaklyRelatedTo)) {
+                       if (stm.isAsserted(resourceToCheckForLinks))
+                               continue;
+                       if (stm.getPredicate().equals(L0.InstanceOf))
+                               continue;
+                       Resource o = stm.getObject();
+                       if (o.equals(excludeLinksTo) || o.equals(resourceToCheckForLinks))
+                               continue;
+
+                       return true;
+               }
+               return false;
+       }
+
+}