blob: bcd21a6efaf716b1b7a8f0de03d7ed1af739413c [file] [log] [blame]
/**
* <copyright>
*
* Copyright (c) 2015 itemis and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
*
* Contributors:
* itemis - Initial API and implementation
* itemis - [463895] org.eclipse.sphinx.emf.check.AbstractCheckValidator.validate(EClass, EObject, DiagnosticChain, Map<Object, Object>) throws NPE
* itemis - [473260] Progress indication of check framework
* itemis - [473261] Check Validation: Cancel button unresponsive
*
* </copyright>
*/
package org.eclipse.sphinx.emf.check.operations;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubMonitor;
import org.eclipse.emf.common.util.Diagnostic;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.transaction.util.TransactionUtil;
import org.eclipse.sphinx.emf.check.internal.Activator;
import org.eclipse.sphinx.emf.check.internal.messages.Messages;
import org.eclipse.sphinx.emf.check.services.CheckProblemMarkerService;
import org.eclipse.sphinx.emf.check.util.ExtendedDiagnostician;
import org.eclipse.sphinx.platform.operations.AbstractLabeledWorkspaceRunnable;
import org.eclipse.sphinx.platform.util.StatusUtil;
public class BasicCheckValidationOperation extends AbstractLabeledWorkspaceRunnable {
protected static final Object ALL_MODEL_OBJECT_COUNT = "ALL_MODEL_OBJECT_COUNT"; //$NON-NLS-1$
protected static final float PROBLEM_MARKER_TO_VALIDATION_WORK_RATIO = 0.1f;
private List<?> modelObjects;
private Map<Object, Object> options;
private ExtendedDiagnostician diagnostician;
public BasicCheckValidationOperation(List<?> modelObjects, Map<Object, Object> options) {
this(Messages.operation_validate_label, modelObjects, options);
}
public BasicCheckValidationOperation(String label, List<? extends Object> modelObjects, Map<Object, Object> options) {
super(label);
Assert.isNotNull(modelObjects);
this.modelObjects = modelObjects;
this.options = options;
}
protected List<?> getModelObjects() {
return modelObjects;
}
protected Map<Object, Integer> getModelObjectCounts() {
List<?> objects = getModelObjects();
Map<Object, Integer> counts = new HashMap<Object, Integer>(objects.size());
int allCount = 0;
for (Object object : objects) {
int count = getModelObjectCount(object);
counts.put(object, count);
allCount += count;
}
counts.put(ALL_MODEL_OBJECT_COUNT, allCount);
return counts;
}
protected int getModelObjectCount(Object object) {
int count = 1;
if (object instanceof EObject) {
for (Iterator<?> iter = ((EObject) object).eAllContents(); iter.hasNext(); iter.next()) {
count++;
}
}
return count;
}
protected Map<Object, Object> getOptions() {
if (options == null) {
options = new HashMap<Object, Object>();
}
return options;
}
protected ExtendedDiagnostician getDiagnostician() {
if (diagnostician == null) {
diagnostician = createDiagnostician();
}
return diagnostician;
}
protected ExtendedDiagnostician createDiagnostician() {
return new ExtendedDiagnostician();
}
protected float getProblemMarkerToValidationWorkRatio() {
return PROBLEM_MARKER_TO_VALIDATION_WORK_RATIO;
}
protected TransactionalEditingDomain getEditingDomain() {
List<?> objects = getModelObjects();
if (!objects.isEmpty()) {
return TransactionUtil.getEditingDomain(objects.get(0));
}
return null;
}
@Override
public void run(final IProgressMonitor monitor) throws CoreException {
try {
Runnable runnable = new Runnable() {
@Override
public void run() {
Map<Object, Integer> modelObjectCounts = getModelObjectCounts();
float problemMarkerToValidationWorkRatio = getProblemMarkerToValidationWorkRatio();
int totalWork = Math.round(modelObjectCounts.get(ALL_MODEL_OBJECT_COUNT) * (1 + problemMarkerToValidationWorkRatio));
SubMonitor progress = SubMonitor.convert(monitor, Messages.task_validating, totalWork);
if (progress.isCanceled()) {
throw new OperationCanceledException();
}
for (Object modelObject : getModelObjects()) {
int validationWork = modelObjectCounts.get(modelObject);
int problemMarkerWork = Math.round(validationWork * problemMarkerToValidationWorkRatio);
validate(modelObject, progress.newChild(validationWork + problemMarkerWork), validationWork, problemMarkerWork);
if (progress.isCanceled()) {
throw new OperationCanceledException();
}
}
}
};
TransactionalEditingDomain editingDomain = getEditingDomain();
if (editingDomain != null) {
editingDomain.runExclusive(runnable);
} else {
runnable.run();
}
} catch (OperationCanceledException ex) {
throw ex;
} catch (Exception ex) {
IStatus status = StatusUtil.createErrorStatus(Activator.getPlugin(), ex);
throw new CoreException(status);
}
}
protected void validate(Object modelObject, SubMonitor progress, int validationWork, int problemMarkerWork) throws OperationCanceledException {
Assert.isNotNull(progress);
if (modelObject instanceof EObject) {
Diagnostic diagnostic = getDiagnostician().validate((EObject) modelObject, getOptions(), progress.newChild(validationWork));
if (progress.isCanceled()) {
throw new OperationCanceledException();
}
updateProblemMarkers((EObject) modelObject, diagnostic, progress.newChild(problemMarkerWork));
} else {
progress.done();
}
}
protected void updateProblemMarkers(EObject eObject, Diagnostic diagnostic, IProgressMonitor monitor) {
SubMonitor progress = SubMonitor.convert(monitor, 1);
if (progress.isCanceled()) {
throw new OperationCanceledException();
}
// TODO Add progress monitor support to CheckProblemMarkerService
CheckProblemMarkerService.INSTANCE.updateProblemMarkers(eObject, diagnostic);
progress.worked(1);
}
}