]> gerrit.simantics Code Review - simantics/platform.git/blob - bundles/org.simantics.issues.ui/src/org/simantics/issues/ui/handler/RunActiveValidations.java
Allow batch issue validation to remove issues with disconnected context
[simantics/platform.git] / bundles / org.simantics.issues.ui / src / org / simantics / issues / ui / handler / RunActiveValidations.java
1 /*******************************************************************************
2  * Copyright (c) 2007, 2011 Association for Decentralized Information Management
3  * in 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  *******************************************************************************/
12 package org.simantics.issues.ui.handler;
13
14 import java.lang.reflect.InvocationTargetException;
15 import java.util.ArrayList;
16 import java.util.Collection;
17 import java.util.Collections;
18 import java.util.List;
19 import java.util.Map;
20 import java.util.Set;
21
22 import org.eclipse.core.commands.AbstractHandler;
23 import org.eclipse.core.commands.ExecutionEvent;
24 import org.eclipse.core.commands.ExecutionException;
25 import org.eclipse.core.runtime.IProgressMonitor;
26 import org.eclipse.core.runtime.OperationCanceledException;
27 import org.eclipse.core.runtime.SubMonitor;
28 import org.eclipse.jface.operation.IRunnableWithProgress;
29 import org.eclipse.ui.PlatformUI;
30 import org.simantics.Simantics;
31 import org.simantics.SleepingDatabaseJob;
32 import org.simantics.db.Issue;
33 import org.simantics.db.ReadGraph;
34 import org.simantics.db.RequestProcessor;
35 import org.simantics.db.Resource;
36 import org.simantics.db.Session;
37 import org.simantics.db.common.request.Queries;
38 import org.simantics.db.common.request.ResourceRead;
39 import org.simantics.db.common.utils.ListUtils;
40 import org.simantics.db.exception.DatabaseException;
41 import org.simantics.db.layer0.request.PossibleActiveModel;
42 import org.simantics.db.layer0.util.ModelTransferableGraphSourceRequest;
43 import org.simantics.db.layer0.util.SessionGarbageCollection;
44 import org.simantics.issues.common.BatchIssueSource;
45 import org.simantics.issues.common.BatchIssueValidationContext;
46 import org.simantics.issues.common.ManagedIssues;
47 import org.simantics.issues.common.SelectedModelBatchIssueSources;
48 import org.simantics.issues.ontology.IssueResource;
49 import org.simantics.issues.preferences.IssuePreferenceUtil;
50 import org.simantics.modeling.utils.BatchValidations;
51 import org.simantics.utils.ui.ExceptionUtils;
52
53 /**
54  * @author Tuukka Lehtonen
55  */
56 public class RunActiveValidations extends AbstractHandler {
57
58     @Override
59     public Object execute(ExecutionEvent event) throws ExecutionException {
60         Runnable postValidation = null;
61         run(postValidation);
62         return null;
63     }
64
65     public void run(Runnable postValidation) {
66
67         final Session session = Simantics.getSession();
68
69         // 1. query for which composites to run the validation
70         final Collection<BatchIssueSource> validations = new ArrayList<>();
71         final BatchIssueValidationContext context = new BatchIssueValidationContext();
72
73         try {
74             SleepingDatabaseJob dbLock = new SleepingDatabaseJob(Messages.RunActiveValidations_ValidationPreparation).scheduleAndWaitForRunning();
75             try {
76                 PlatformUI.getWorkbench().getProgressService().run(true, true, new IRunnableWithProgress() {
77                     @Override
78                     public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
79                         try {
80                             Resource model = session.sync(new PossibleActiveModel(Simantics.getProjectResource()));
81                             if(model == null) return;
82
83                             toBatchIssueSources(session,
84                                     session.syncRequest(new SelectedModelBatchIssueSources(model)),
85                                     validations);
86
87                             SubMonitor.convert(monitor, Messages.RunActiveValidations_MonitorPreparingResourcesForValidation, 100);
88                             context.contexts = Collections.singletonList(model);
89                             context.domain = ModelTransferableGraphSourceRequest.getDomainOnly(session, monitor, model);
90
91                             if (monitor.isCanceled())
92                                 throw new OperationCanceledException();
93                         } catch (DatabaseException e) {
94                             throw new InvocationTargetException(e);
95                         } finally {
96                             monitor.done();
97                         }
98                     }
99                 });
100             } finally {
101                 dbLock.disposeAndJoin();
102             }
103         } catch (InvocationTargetException e) {
104             if (e.getTargetException() instanceof OperationCanceledException)
105                 return;
106             ExceptionUtils.logAndShowError(e.getTargetException());
107             return;
108         } catch (InterruptedException e) {
109             // Operation cancelled, ignore.
110             return;
111         }
112
113         if(!validations.isEmpty() && !context.contexts.isEmpty())
114             run(postValidation, validations, context);
115
116     }
117
118     static Collection<BatchIssueSource> toBatchIssueSources(RequestProcessor processor, Collection<Resource> sources, Collection<BatchIssueSource> result) throws DatabaseException {
119         for (Resource source : sources) {
120             BatchIssueSource bis = processor.syncRequest(Queries.adapt(source, BatchIssueSource.class, true));
121             if (bis != null)
122                 result.add(bis);
123         }
124         return result;
125     }
126
127     public static void run(Runnable postValidation, final Collection<BatchIssueSource> validations, final BatchIssueValidationContext context) {
128         // Run the validations for the selected composites
129         SleepingDatabaseJob dbLock = new SleepingDatabaseJob(Messages.RunActiveValidations_Validation);
130         try {
131             dbLock.scheduleAndWaitForRunning();
132             try {
133                 PlatformUI.getWorkbench().getProgressService().run(true, true, new IRunnableWithProgress() {
134                     @Override
135                     public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
136                         try {
137                             SubMonitor progress = SubMonitor.convert(monitor, Messages.RunActiveValidations_ValidateModel, 100);
138                             int maxWrittenIssues = IssuePreferenceUtil.getPreferences().maxBatchIssuesToWrite;
139                             int writtenIssues = 0;
140                             for (BatchIssueSource source : validations) {
141                                 Map<Resource, Set<Issue>> results = BatchValidations.validate(progress.newChild(90, SubMonitor.SUPPRESS_NONE), source, context);
142                                 if (progress.isCanceled())
143                                     throw new OperationCanceledException();
144
145                                 Collection<Resource> removed = Simantics.getSession().syncRequest(new ResourceRead<Collection<Resource>>(source.getResource()) {
146                                     @Override
147                                     public Collection<Resource> perform(ReadGraph graph) throws DatabaseException {
148                                         IssueResource ISSUE = IssueResource.getInstance(graph);
149                                         ArrayList<Resource> result = new ArrayList<>();
150                                         for (Resource issue : graph.syncRequest(new ManagedIssues(resource))) {
151                                             Resource list = graph.getSingleObject(issue, ISSUE.Issue_HasContexts);
152                                             List<Resource> l = ListUtils.toList(graph, list);
153                                             if (l.size() > 0) {
154                                                 Resource mainContext = l.get(0); 
155                                                 if (!BatchValidations.isLinkedToOtherThan(graph, mainContext, issue))
156                                                     result.add(mainContext);
157                                             }
158                                         }
159                                         return result;
160                                     }
161                                 });
162
163                                 for(Resource r : removed) {
164                                     results.put(r, Collections.<Issue>emptySet());
165                                 }
166                                 if (progress.isCanceled())
167                                     throw new OperationCanceledException();
168
169                                 int wroteIssues = BatchValidations.store(progress.newChild(10, SubMonitor.SUPPRESS_NONE), source.getResource(), results, Math.max(0, maxWrittenIssues - writtenIssues));
170                                 writtenIssues += wroteIssues;
171
172                                 // Try to keep resource consumption down.
173                                 SessionGarbageCollection.gc(null, Simantics.getSession(), true, null);
174
175                             }
176                         } catch (OperationCanceledException e) {
177                                 throw e;
178                         } catch (Exception e) {
179                             throw new InvocationTargetException(e);
180                         } finally {
181                             monitor.done();
182                         }
183                     }
184                 });
185             } finally {
186                 dbLock.disposeAndJoin();
187             }
188
189             if (postValidation != null)
190                 postValidation.run();
191
192         } catch (OperationCanceledException e) {
193             // Operation cancelled, ignore.
194         } catch (InvocationTargetException e) {
195             ExceptionUtils.logAndShowError(e.getTargetException());
196         } catch (InterruptedException e) {
197             // Operation cancelled, ignore.
198         }
199     }
200
201 }