/******************************************************************************* * Copyright (c) 2007, 2011 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 *******************************************************************************/ package org.simantics.issues.ui.handler; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.Set; import org.eclipse.core.commands.AbstractHandler; import org.eclipse.core.commands.ExecutionEvent; import org.eclipse.core.commands.ExecutionException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.OperationCanceledException; import org.eclipse.core.runtime.SubMonitor; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.ui.PlatformUI; import org.simantics.Simantics; import org.simantics.SleepingDatabaseJob; import org.simantics.db.Issue; import org.simantics.db.ReadGraph; import org.simantics.db.Resource; import org.simantics.db.Session; import org.simantics.db.common.request.Queries; import org.simantics.db.common.request.ResourceRead; import org.simantics.db.common.utils.ListUtils; import org.simantics.db.exception.DatabaseException; import org.simantics.db.layer0.request.PossibleActiveModel; import org.simantics.db.layer0.util.ModelTransferableGraphSourceRequest; import org.simantics.db.layer0.util.SessionGarbageCollection; import org.simantics.issues.common.BatchIssueSource; import org.simantics.issues.common.BatchIssueValidationContext; import org.simantics.issues.common.ManagedIssues; import org.simantics.issues.common.SelectedModelBatchIssueSources; import org.simantics.issues.ontology.IssueResource; import org.simantics.issues.preferences.IssuePreferenceUtil; import org.simantics.modeling.utils.BatchValidations; import org.simantics.utils.ui.ExceptionUtils; /** * @author Tuukka Lehtonen */ public class RunActiveValidations extends AbstractHandler { @Override public Object execute(ExecutionEvent event) throws ExecutionException { Runnable postValidation = null; run(postValidation); return null; } public void run(Runnable postValidation) { final Session session = Simantics.getSession(); // 1. query for which composites to run the validation final Collection validations = new ArrayList(); final BatchIssueValidationContext context = new BatchIssueValidationContext(); try { SleepingDatabaseJob dbLock = new SleepingDatabaseJob("Validation Preparation").scheduleAndWaitForRunning(); try { PlatformUI.getWorkbench().getProgressService().run(true, true, new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { Resource model = session.sync(new PossibleActiveModel(Simantics.getProjectResource())); if(model == null) return; Collection activeSources = session.syncRequest(new SelectedModelBatchIssueSources(model)); for(Resource source : activeSources) { BatchIssueSource bis = session.syncRequest(Queries.adapt(source, BatchIssueSource.class, true)); if(bis != null) validations.add(bis); } SubMonitor.convert(monitor, "Preparing resources for validation", 100); context.contexts = Collections.singletonList(model); context.domain = ModelTransferableGraphSourceRequest.getDomainOnly(session, monitor, model); if (monitor.isCanceled()) throw new OperationCanceledException(); } catch (DatabaseException e) { throw new InvocationTargetException(e); } finally { monitor.done(); } } }); } finally { dbLock.disposeAndJoin(); } } catch (InvocationTargetException e) { if (e.getTargetException() instanceof OperationCanceledException) return; ExceptionUtils.logAndShowError(e.getTargetException()); return; } catch (InterruptedException e) { // Operation cancelled, ignore. return; } if(!validations.isEmpty() && !context.contexts.isEmpty()) run(postValidation, validations, context); } public static void run(Runnable postValidation, final Collection validations, final BatchIssueValidationContext context) { // Run the validations for the selected composites SleepingDatabaseJob dbLock = new SleepingDatabaseJob("Validation"); try { dbLock.scheduleAndWaitForRunning(); try { PlatformUI.getWorkbench().getProgressService().run(true, true, new IRunnableWithProgress() { @Override public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException { try { SubMonitor progress = SubMonitor.convert(monitor, "Validate Model", 100); int maxWrittenIssues = IssuePreferenceUtil.getPreferences().maxBatchIssuesToWrite; int writtenIssues = 0; for (BatchIssueSource source : validations) { Map> results = BatchValidations.validate(progress.newChild(90, SubMonitor.SUPPRESS_NONE), source, context); if (progress.isCanceled()) throw new OperationCanceledException(); Collection removed = Simantics.getSession().syncRequest(new ResourceRead>(source.getResource()) { @Override public Collection perform(ReadGraph graph) throws DatabaseException { IssueResource ISSUE = IssueResource.getInstance(graph); ArrayList result = new ArrayList(); for (Resource issue : graph.syncRequest(new ManagedIssues(resource))) { Resource list = graph.getSingleObject(issue, ISSUE.Issue_HasContexts); List l = ListUtils.toList(graph, list); if (l.size() > 0) { Resource mainContext = l.get(0); if (!graph.hasStatement(mainContext)) result.add(mainContext); } } return result; } }); for(Resource r : removed) { results.put(r, Collections.emptySet()); } if (progress.isCanceled()) throw new OperationCanceledException(); int wroteIssues = BatchValidations.store(progress.newChild(10, SubMonitor.SUPPRESS_NONE), source.getResource(), results, Math.max(0, maxWrittenIssues - writtenIssues)); writtenIssues += wroteIssues; // Try to keep resource consumption down. SessionGarbageCollection.gc(null, Simantics.getSession(), true, null); } } catch (OperationCanceledException e) { throw e; } catch (Exception e) { throw new InvocationTargetException(e); } finally { monitor.done(); } } }); } finally { dbLock.disposeAndJoin(); } if (postValidation != null) postValidation.run(); } catch (OperationCanceledException e) { // Operation cancelled, ignore. } catch (InvocationTargetException e) { ExceptionUtils.logAndShowError(e.getTargetException()); } catch (InterruptedException e) { // Operation cancelled, ignore. } } }