/*****************************************************************************
* Copyright (c) 2011 Atos Origin.
*
*
* 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:
* Atos Origin - Initial API and implementation
*
*****************************************************************************/
package org.eclipse.papyrus.uml.controlmode.profile.providers;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedList;
import java.util.List;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.emf.validation.model.IClientSelector;
import org.eclipse.emf.validation.model.IConstraintStatus;
import org.eclipse.emf.validation.service.IValidationListener;
import org.eclipse.emf.validation.service.ModelValidationService;
import org.eclipse.emf.validation.service.ValidationEvent;
import org.eclipse.gmf.runtime.emf.core.util.EMFCoreUtil;
import org.eclipse.papyrus.infra.core.resource.ModelSet;
import org.eclipse.papyrus.infra.widgets.toolbox.notification.builders.NotificationBuilder;
import org.eclipse.papyrus.uml.controlmode.profile.Activator;
import org.eclipse.papyrus.uml.controlmode.profile.helpers.SafeDialogOpenerDuringValidation;
/**
* Provides validation for UML models
*/
public class UMLValidationProvider {
/**
* Whether constraints are active
*/
private static boolean constraintsActive = false;
/**
* Ids of constraints which report is already managed by themselves.
*/
protected static final Collection<String> SELF_MANAGING_CONSTRAINTS = Arrays.asList("org.eclipse.papyrus.uml.controlmode.profile.validation.ProfileApplicationDuplicationChecker");
/**
* Validation listener which reports problems to the user
*/
private static class ValidationReportListener implements IValidationListener {
/**
* Report the validation result to the user in case operation did not fully succeed
*
* @see org.eclipse.emf.validation.service.IValidationListener#validationOccurred(org.eclipse.emf.validation.service.ValidationEvent)
*
* @param event
* provides the validation operation results
*/
public void validationOccurred(ValidationEvent event) {
boolean needReport = false;
if(event.getSeverity() >= IStatus.WARNING) {
needReport = true;
}
if(needReport && event.getEvaluationMode().isLive()) {
StringBuffer messageBuff = new StringBuffer();
List<String> handledConstraints = new LinkedList<String>(SELF_MANAGING_CONSTRAINTS);
for(IConstraintStatus status : event.getValidationResults()) {
// report only major problems
if(status.getSeverity() >= event.getSeverity()) {
String constraintId = status.getConstraint().getDescriptor().getId();
String constraintPlugin = status.getConstraint().getDescriptor().getPluginId();
if(Activator.PLUGIN_ID.equals(constraintPlugin) && !handledConstraints.contains(constraintId)) {
handledConstraints.add(constraintId);
messageBuff.append(status.getMessage());
}
}
}
if(messageBuff.length() == 0) {
// no error to report
return;
}
final String message = messageBuff.toString();
if(event.getSeverity() >= IStatus.ERROR) {
SafeDialogOpenerDuringValidation<Void> opener = new SafeDialogOpenerDuringValidation<Void>() {
protected Void openDialog() {
NotificationBuilder.createWarningPopup(message).run();
return null;
}
};
opener.execute();
} else {
SafeDialogOpenerDuringValidation<Void> opener = new SafeDialogOpenerDuringValidation<Void>() {
protected Void openDialog() {
NotificationBuilder.createInfoPopup(message).run();
return null;
}
};
opener.execute();
}
}
}
}
/**
* Add a validation listener to report problems
*/
static {
ModelValidationService.getInstance().addValidationListener(new ValidationReportListener());
}
/**
* Run an operation with checking of the constraints
*
* @param editingDomain
* editing domain
* @param operation
* operation to run
*/
public static void runWithConstraints(TransactionalEditingDomain editingDomain, Runnable operation) {
final Runnable op = operation;
Runnable task = new Runnable() {
public void run() {
try {
constraintsActive = true;
op.run();
} finally {
constraintsActive = false;
}
}
};
if(editingDomain != null) {
try {
editingDomain.runExclusive(task);
} catch (Exception e) {
Activator.getDefault().getLog().log(new Status(IStatus.ERROR, Activator.PLUGIN_ID, "Validation failed", e));
}
} else {
task.run();
}
}
/**
* Context for validation
*/
public static class DefaultCtx implements IClientSelector {
/**
* Indicate whether validation is activated
*
* @see org.eclipse.emf.validation.model.IClientSelector#selects(java.lang.Object)
*
* @param object
* object to eventually validate
* @return true if validation is required
*/
public boolean selects(Object object) {
if(constraintsActive) {
return true;
}
if(object instanceof EObject) {
EObject eObj = (EObject)object;
Resource resource = eObj.eResource();
if (resource != null) {
ResourceSet set = resource.getResourceSet();
return set instanceof ModelSet;
}
}
return false;
}
}
/**
* Format a model element
*
* @param object
* element to format
* @return text
*/
static String formatElement(EObject object) {
return EMFCoreUtil.getQualifiedName(object, true);
}
}