/*************************************************************************** * Copyright (c) 2008 Conselleria de Infraestructuras y Transporte, * Generalitat de la Comunitat Valenciana . 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: Francisco Javier Cano Muñoz (Prodevelop) - initial api implementation * ******************************************************************************/ package org.eclipse.papyrus.uml.diagram.common.actions; import java.lang.reflect.InvocationTargetException; import java.util.Iterator; import java.util.List; import org.eclipse.core.resources.IFile; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.core.runtime.IStatus; import org.eclipse.core.runtime.NullProgressMonitor; import org.eclipse.emf.common.util.Diagnostic; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.util.Diagnostician; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.emf.transaction.util.TransactionUtil; import org.eclipse.emf.workspace.util.WorkspaceSynchronizer; import org.eclipse.gmf.runtime.common.ui.util.IWorkbenchPartDescriptor; import org.eclipse.gmf.runtime.diagram.ui.editparts.DiagramEditPart; import org.eclipse.gmf.runtime.diagram.ui.parts.IDiagramWorkbenchPart; import org.eclipse.gmf.runtime.emf.core.util.EMFCoreUtil; import org.eclipse.gmf.runtime.notation.View; import org.eclipse.jface.action.Action; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.papyrus.uml.diagram.common.Activator; import org.eclipse.papyrus.uml.diagram.common.providers.DiagramValidationMarkerNavigationProvider; import org.eclipse.papyrus.uml.diagram.common.providers.DiagramValidationProvider; import org.eclipse.papyrus.uml.diagram.common.util.DiagramEditPartsUtil; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.actions.WorkspaceModifyDelegatingOperation; /** * An {@link Action} that launches the diagram validation. * After the validation it marks the diagram file to show decoratos where errors occurred. * * @author <a href="mailto:fjcano@prodevelop.es">Francisco Javier Cano Muñoz</a> * */ public class ValidationAction extends Action { public static final String VALIDATE_ACTION_KEY = "validateDiagramAction"; //$NON-NLS-1$ private IWorkbenchPartDescriptor workbenchPartDescriptor; public ValidationAction(IWorkbenchPartDescriptor workbenchPartDescriptor) { setId(VALIDATE_ACTION_KEY); setText("Diagram Validation"); this.workbenchPartDescriptor = workbenchPartDescriptor; } /** * Executes the action */ public void run() { IWorkbenchPart workbenchPart = workbenchPartDescriptor.getPartPage().getActivePart(); if(workbenchPart instanceof IDiagramWorkbenchPart) { final IDiagramWorkbenchPart part = (IDiagramWorkbenchPart)workbenchPart; try { new WorkspaceModifyDelegatingOperation(new IRunnableWithProgress() { public void run(IProgressMonitor monitor) throws InterruptedException, InvocationTargetException { runValidation(part.getDiagramEditPart(), part.getDiagram()); } }).run(new NullProgressMonitor()); } catch (Exception e) { Activator.getDefault().logError("Diagram Validation action failed", e); } } } /** * Runs the validation for the given diagram * * @param diagramEditPart * @param view */ public static void runValidation(DiagramEditPart diagramEditPart, View view) { final DiagramEditPart fpart = diagramEditPart; final View fview = view; TransactionalEditingDomain txDomain = TransactionUtil.getEditingDomain(view); DiagramValidationProvider.runWithConstraints(txDomain, new Runnable() { public void run() { validate(fpart, fview); } }); } /** * Executes the validation for the given diagram * * @param diagramEditPart * @param view */ private static void validate(DiagramEditPart diagramEditPart, View view) { IFile target = view.eResource() != null ? WorkspaceSynchronizer.getFile(view.eResource()) : null; if(target != null) { DiagramValidationMarkerNavigationProvider.deleteMarkers(target); } Diagnostic diagnostic = runEMFValidator(view); createMarkers(target, diagnostic, diagramEditPart); } /** * Runs the EMF Validations andCheck Validations for the given View * * @param target * @return */ private static Diagnostic runEMFValidator(View target) { if(target.isSetElement() && target.getElement() != null) { // do the validation on the root element to check all the elements // contained into the model EObject eo = target.getElement(); while(eo.eContainer() != null) eo = eo.eContainer(); return new Diagnostician() { public String getObjectLabel(EObject eObject) { return EMFCoreUtil.getQualifiedName(eObject, true); } }.validate(eo); } return Diagnostic.OK_INSTANCE; } /** * Add the Markers for all the views affected by the validation * * @param target * @param emfValidationStatus * @param diagramEditPart */ private static void createMarkers(IFile target, Diagnostic emfValidationStatus, DiagramEditPart diagramEditPart) { if(emfValidationStatus.getSeverity() == Diagnostic.OK) { return; } for(Iterator<?> it = emfValidationStatus.getChildren().iterator(); it.hasNext();) { Diagnostic nextDiagnostic = (Diagnostic)it.next(); List<?> data = nextDiagnostic.getData(); if(data != null && !data.isEmpty() && data.get(0) instanceof EObject) { EObject element = (EObject)data.get(0); List<?> list = DiagramEditPartsUtil.getEObjectViews(element); // add the marker to the file if affected element has no // graphical representation if(list.size() == 0) { addMarker(target, element.eResource().getURI().toString(), EMFCoreUtil.getQualifiedName(element, true), nextDiagnostic.getMessage(), diagnosticToStatusSeverity(nextDiagnostic.getSeverity())); } // add the marker to the views if the element has representation for(Object o : list) { if(o instanceof View) { View v = (View)o; addMarker(target, v.eResource().getURIFragment(v), EMFCoreUtil.getQualifiedName(element, true), nextDiagnostic.getMessage(), diagnosticToStatusSeverity(nextDiagnostic.getSeverity())); } } } } } /** * Add one marker to the given element * * @param target * @param elementId * @param location * @param message * @param statusSeverity */ private static void addMarker(IFile target, String elementId, String location, String message, int statusSeverity) { if(target == null) { return; } DiagramValidationMarkerNavigationProvider.addMarker(target, elementId, location, message, statusSeverity); } /** * Check the severity of the Diagnostic * * @param diagnosticSeverity * @return */ private static int diagnosticToStatusSeverity(int diagnosticSeverity) { if(diagnosticSeverity == Diagnostic.OK) { return IStatus.OK; } else if(diagnosticSeverity == Diagnostic.INFO) { return IStatus.INFO; } else if(diagnosticSeverity == Diagnostic.WARNING) { return IStatus.WARNING; } else if(diagnosticSeverity == Diagnostic.ERROR || diagnosticSeverity == Diagnostic.CANCEL) { return IStatus.ERROR; } return IStatus.INFO; } }