blob: fe6fa199857657dfb7923e718ab7118cebe97127 [file] [log] [blame]
/**
********************************************************************************
* Copyright (c) 2019-2021 Robert Bosch GmbH and others.
*
* This program and the accompanying materials are made
* available under the terms of the Eclipse Public License 2.0
* which is available at https://www.eclipse.org/legal/epl-2.0/
*
* SPDX-License-Identifier: EPL-2.0
*
* Contributors:
* Robert Bosch GmbH - initial API and implementation
********************************************************************************
*/
package org.eclipse.app4mc.validation.ui.util;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.CopyOnWriteArraySet;
import org.eclipse.app4mc.validation.core.IProfile;
import org.eclipse.app4mc.validation.util.CachedValidator;
import org.eclipse.app4mc.validation.util.ValidationExecutor;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.common.util.TreeIterator;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.util.EcoreUtil;
/**
* A validator for EMF models. Loads the validations from a list of
* {@link IProfile} classes
*/
public class ValidationExecutorWithMonitor extends ValidationExecutor {
public ValidationExecutorWithMonitor(Class<? extends IProfile> profileClass) {
super(profileClass);
}
public ValidationExecutorWithMonitor(Collection<Class<? extends IProfile>> profileClasses) {
super(profileClasses);
}
public ValidationExecutorWithMonitor(
ConcurrentMap<EClassifier, CopyOnWriteArraySet<CachedValidator>> validationMap) {
super(validationMap);
}
/**
* Validates the model object (and all contained objects)
*
* @param model the model object to validate
* @return the status
*/
public IStatus validateWithMonitor(final EObject model) {
return validateWithMonitor(model, new NullProgressMonitor());
}
/**
* Validates the model objects (and all contained objects)
*
* @param models the list of model objects to validate
* @return the status
*/
public IStatus validateWithMonitor(final List<EObject> models) {
return validateWithMonitor(models, new NullProgressMonitor());
}
/**
* Validates the model object (and all contained objects)
*
* @param model the model object to validate
* @param monitor the progress monitor
* @return the status
*/
public IStatus validateWithMonitor(final EObject model, final IProgressMonitor monitor) {
return validateWithMonitor(Collections.singletonList(model), monitor);
}
/**
* Validates the model objects (and all contained objects)
*
* @param models the list of model objects to validate
* @param monitor the progress monitor
* @return the status
*/
public IStatus validateWithMonitor(final List<EObject> models, final IProgressMonitor monitor) {
results.clear();
try {
// count overall number of objects
int count = 0;
for (EObject eObject : models) {
count = count + getModelObjectCount(eObject);
}
monitor.beginTask("Validating objects", count / 1000 + 1);
int i = 0;
for (EObject eObject : models) {
validateObject(eObject); // need to validate the root, because the iterator misses this one
i++;
TreeIterator<EObject> iterator = EcoreUtil.getAllContents(eObject, false);
while (iterator.hasNext()) {
validateObject(iterator.next());
i++;
if ((i % 1000) == 0) {
monitor.worked(1);
if (monitor.isCanceled()) {
return Status.CANCEL_STATUS;
}
}
}
}
return Status.OK_STATUS;
} finally {
monitor.done();
}
}
// Future extension: parallel execution
//
// requires a model that is not modified by traversal of validators !!
//
// Idea:
// ** use a JobGroup:
// - e.g. with <job name> <availableProcessors>
// ** Iterate parallel:
// - Streams.stream(iterator).parallel(). ...
private int getModelObjectCount(EObject object) {
int count = 1; // root object
for (Iterator<?> iter = object.eAllContents(); iter.hasNext(); iter.next()) {
count++;
}
return count;
}
}