]> gerrit.simantics Code Review - simantics/platform.git/blob - 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
1 /*******************************************************************************
2  * Copyright (c) 2019 Association for Decentralized Information Management in
3  * Industry THTH ry.
4  * All rights reserved. This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License v1.0
6  * which accompanies this distribution, and is available at
7  * http://www.eclipse.org/legal/epl-v10.html
8  *
9  * Contributors:
10  *     VTT Technical Research Centre of Finland - initial API and implementation
11  *     Semantum Oy - Reorganization
12  *******************************************************************************/
13 package org.simantics.issues.common;
14
15 import java.util.Map;
16 import java.util.Set;
17
18 import org.eclipse.core.runtime.IProgressMonitor;
19 import org.simantics.Simantics;
20 import org.simantics.db.Issue;
21 import org.simantics.db.ReadGraph;
22 import org.simantics.db.Resource;
23 import org.simantics.db.Session;
24 import org.simantics.db.Statement;
25 import org.simantics.db.VirtualGraph;
26 import org.simantics.db.WriteGraph;
27 import org.simantics.db.common.request.WriteRequest;
28 import org.simantics.db.exception.DatabaseException;
29 import org.simantics.db.layer0.util.RemoverUtil;
30 import org.simantics.db.service.VirtualGraphSupport;
31 import org.simantics.issues.ontology.IssueResource;
32 import org.simantics.layer0.Layer0;
33
34 import gnu.trove.set.hash.THashSet;
35
36 public class BatchValidations {
37
38         private static final boolean PERF = false;
39
40         public static Map<Resource, Set<Issue>> validate(IProgressMonitor monitor, BatchIssueSource source, BatchIssueValidationContext context) throws DatabaseException {
41                 Session session = Simantics.getSession();
42                 return session.syncRequest(new ComposedValidation(monitor, source, context));
43         }
44
45         /**
46          * @param monitor
47          * @param source
48          * @param issues
49          * @return
50          * @throws DatabaseException
51          */
52         public static int store(final IProgressMonitor monitor,
53                         final Resource source, final Map<Resource, Set<Issue>> issues)
54                         throws DatabaseException {
55                 return store(monitor, source, issues, Integer.MAX_VALUE);
56         }
57
58         /**
59          * @param monitor
60          * @param source
61          * @param issues
62          * @param maxIssuesToWrite
63          * @return number of issues written (added)
64          * @throws DatabaseException
65          */
66         public static int store(final IProgressMonitor monitor,
67                         final Resource source, final Map<Resource, Set<Issue>> issues,
68                         final int maxIssuesToWrite) throws DatabaseException {
69
70                 if (issues.isEmpty() || maxIssuesToWrite <= 0)
71                         return 0;
72
73                 Session session = Simantics.getSession();
74                 VirtualGraphSupport support = session.getService(VirtualGraphSupport.class);
75                 VirtualGraph vg = support.getWorkspacePersistent(IssueConstants.ISSUE_VG);
76                 final int[] writtenIssues = { 0 };
77
78                 session.syncRequest(new WriteRequest(vg) {
79
80                         @Override
81                         public void perform(WriteGraph graph) throws DatabaseException {
82
83                                 for(Map.Entry<Resource, Set<Issue>> entry : issues.entrySet()) {
84
85                                         if (monitor.isCanceled())
86                                                 return;
87
88                                         Resource context = entry.getKey();
89
90                                         Set<Issue> current = entry.getValue();
91                                         Set<Issue> existing = graph.sync(new BatchIssueDescriptions(source, context));
92
93                                         if(!existing.equals(current)) {
94
95                                                 Set<Issue> added = new THashSet<Issue>(current);
96                                                 Set<Issue> removed = new THashSet<Issue>(existing);
97                                                 added.removeAll(existing);
98                                                 removed.removeAll(current);
99
100                                                 for(Issue add : added) {
101                                                         add.write(graph, source);
102                                                         // Stop if write limit is reached.
103                                                         if (++writtenIssues[0] >= maxIssuesToWrite)
104                                                                 return;
105                                                 }
106                                                 for(Issue remove : removed) {
107                                                         Resource issue = graph.sync(new IssueByList(source, remove));
108                                                         if (issue == null)
109                                                                 // FIXME: when can this happen and what should be done in this case?
110                                                                 continue;
111                                                         graph.deny(issue, Layer0.getInstance(graph).PartOf);
112                                                         graph.deny(source, IssueResource.getInstance(graph).IssueSource_Manages, issue);
113                                                         RemoverUtil.remove(graph, issue);
114                                                 }
115
116                                         }
117
118                                 }
119
120                         }
121                 });
122
123                 return writtenIssues[0];
124
125         }
126
127         /**
128          * @param map
129          * @return
130          */
131         @SuppressWarnings("rawtypes")
132         private static int count(Map map) {
133                 int result = 0;
134                 for (Object obj : map.values()) {
135                         if (obj instanceof Set<?>) {
136                                 Set<?> set = (Set<?>) obj;
137                                 result += set.size();
138                         }
139                 }
140                 return result;
141         }
142
143         /**
144          * Checks if the specified <code>resourceToCheckForLinks</code> is linked to
145          * anything else besides itself and <code>excludeLinksTo</code>.
146          * 
147          * <p>
148          * This is used to if an issue context is still valid. We consider any issue
149          * context that is not attached to something else besides its issue context to
150          * be an invalid issue. Assertions and L0.InstanceOf do not count as external
151          * links.
152          * 
153          * @param graph database access handle
154          * @param resourceToCheckForLinks the resource to check for "external" links
155          * @param excludeLinksTo exclude links to this resource from evaluation
156          * @return <code>true</code> if there are links, <code>false</code> otherwise
157          * @throws DatabaseException 
158          */
159         public static boolean isLinkedToOtherThan(ReadGraph graph, Resource resourceToCheckForLinks,
160                         Resource excludeLinksTo)
161                                         throws DatabaseException
162         {
163                 Layer0 L0 = Layer0.getInstance(graph);
164                 for (Statement stm : graph.getStatements(resourceToCheckForLinks, L0.IsWeaklyRelatedTo)) {
165                         if (stm.isAsserted(resourceToCheckForLinks))
166                                 continue;
167                         if (stm.getPredicate().equals(L0.InstanceOf))
168                                 continue;
169                         Resource o = stm.getObject();
170                         if (o.equals(excludeLinksTo) || o.equals(resourceToCheckForLinks))
171                                 continue;
172
173                         return true;
174                 }
175                 return false;
176         }
177
178 }