/** * Copyright (c) 2004-2008 IBM Corporation and others. * 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: * IBM - Initial API and implementation */ package org.eclipse.emf.edit.ui.action; import java.lang.reflect.InvocationTargetException; import java.util.ArrayList; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import org.eclipse.core.resources.IMarker; import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.action.Action; import org.eclipse.jface.dialogs.Dialog; import org.eclipse.jface.dialogs.MessageDialog; import org.eclipse.jface.dialogs.ProgressMonitorDialog; import org.eclipse.jface.operation.IRunnableWithProgress; import org.eclipse.jface.viewers.ISelectionChangedListener; import org.eclipse.jface.viewers.ISelectionProvider; import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.Viewer; import org.eclipse.jface.window.Window; import org.eclipse.swt.widgets.Shell; import org.eclipse.ui.IWorkbenchPart; import org.eclipse.ui.PlatformUI; import org.eclipse.ui.actions.WorkspaceModifyDelegatingOperation; import org.eclipse.ui.part.ISetSelectionTarget; import org.eclipse.emf.common.EMFPlugin; import org.eclipse.emf.common.notify.AdapterFactory; import org.eclipse.emf.common.ui.dialogs.DiagnosticDialog; import org.eclipse.emf.common.ui.viewer.IViewerProvider; import org.eclipse.emf.common.util.BasicDiagnostic; import org.eclipse.emf.common.util.Diagnostic; import org.eclipse.emf.common.util.DiagnosticChain; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EValidator; import org.eclipse.emf.ecore.resource.Resource; import org.eclipse.emf.ecore.resource.ResourceSet; import org.eclipse.emf.ecore.util.Diagnostician; import org.eclipse.emf.ecore.util.EObjectValidator; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain; import org.eclipse.emf.edit.domain.EditingDomain; import org.eclipse.emf.edit.domain.IEditingDomainProvider; import org.eclipse.emf.edit.provider.IItemLabelProvider; import org.eclipse.emf.edit.ui.EMFEditUIPlugin; import org.eclipse.emf.edit.ui.provider.DiagnosticDecorator; import org.eclipse.emf.edit.ui.util.EditUIMarkerHelper; public class ValidateAction extends Action implements ISelectionChangedListener { public static class EclipseResourcesUtil extends EditUIMarkerHelper { public IRunnableWithProgress getWorkspaceModifyOperation(IRunnableWithProgress runnableWithProgress) { try { return new WorkspaceModifyDelegatingOperation(runnableWithProgress); } catch (NoClassDefFoundError exception) { return runnableWithProgress; } } @Override protected String getMarkerID() { return EValidator.MARKER; } public void createMarkers(Resource resource, Diagnostic diagnostic) { try { createMarkers(getFile(resource), diagnostic, null); } catch (CoreException e) { EMFEditUIPlugin.INSTANCE.log(e); } } @Override protected String composeMessage(Diagnostic diagnostic, Diagnostic parentDiagnostic) { String message = diagnostic.getMessage(); if (parentDiagnostic != null) { String parentMessage = parentDiagnostic.getMessage(); if (parentMessage != null) { message = message != null ? parentMessage + ". " + message : parentMessage; } } return message; } @Override protected void adjustMarker(IMarker marker, Diagnostic diagnostic, Diagnostic parentDiagnostic) throws CoreException { List<?> data = diagnostic.getData(); StringBuilder relatedURIs = new StringBuilder(); boolean first = true; for (Object object : data) { if (object instanceof EObject) { EObject eObject = (EObject)object; if (first) { first = false; marker.setAttribute(EValidator.URI_ATTRIBUTE, EcoreUtil.getURI(eObject).toString()); } else { if (relatedURIs.length() != 0) { relatedURIs.append(' '); } relatedURIs.append(URI.encodeFragment(EcoreUtil.getURI(eObject).toString(), false)); } } } if (relatedURIs.length() > 0) { marker.setAttribute(EValidator.RELATED_URIS_ATTRIBUTE, relatedURIs.toString()); } super.adjustMarker(marker, diagnostic, parentDiagnostic); } } protected ISelectionProvider selectionProvider; protected List<EObject> selectedObjects; protected EditingDomain domain; protected EclipseResourcesUtil eclipseResourcesUtil = EMFPlugin.IS_RESOURCES_BUNDLE_AVAILABLE ? new EclipseResourcesUtil() : null; public ValidateAction() { super(EMFEditUIPlugin.INSTANCE.getString("_UI_Validate_menu_item")); setDescription(EMFEditUIPlugin.INSTANCE.getString("_UI_Validate_simple_description")); } @Override public void run() { final Diagnostic[] diagnostic = new Diagnostic[1]; IRunnableWithProgress validationRunnable = new IRunnableWithProgress() { public void run(final IProgressMonitor progressMonitor) throws InvocationTargetException, InterruptedException { try { diagnostic[0] = validate(progressMonitor); } finally { progressMonitor.done(); } } }; Shell shell = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(); try { new ProgressMonitorDialog(shell).run(true, true, validationRunnable); IRunnableWithProgress createMarkersRunnable = new IRunnableWithProgress() { public void run(final IProgressMonitor progressMonitor) throws InvocationTargetException, InterruptedException { try { handleDiagnostic(diagnostic[0]); } finally { progressMonitor.done(); } } }; if (eclipseResourcesUtil != null) { createMarkersRunnable = eclipseResourcesUtil.getWorkspaceModifyOperation(createMarkersRunnable); } try { new ProgressMonitorDialog(shell).run(false, true, createMarkersRunnable); } catch (Exception exception) { EMFEditUIPlugin.INSTANCE.log(exception); } } catch (Exception exception) { EMFEditUIPlugin.INSTANCE.log(exception); } } protected Diagnostic validate(IProgressMonitor progressMonitor) { int selectionSize = selectedObjects.size(); int count = selectionSize; synchronized (domain.getResourceSet()) { for (EObject eObject : selectedObjects) { for (Iterator<?> i = eObject.eAllContents(); i.hasNext(); i.next()) { ++count; } } } progressMonitor.beginTask("", count); AdapterFactory adapterFactory = domain instanceof AdapterFactoryEditingDomain ? ((AdapterFactoryEditingDomain)domain).getAdapterFactory() : null; Diagnostician diagnostician = createDiagnostician(adapterFactory, progressMonitor); BasicDiagnostic diagnostic; if (selectionSize == 1) { diagnostic = diagnostician.createDefaultDiagnostic(selectedObjects.get(0)); } else { diagnostic = new BasicDiagnostic (EObjectValidator.DIAGNOSTIC_SOURCE, 0, EMFEditUIPlugin.INSTANCE.getString("_UI_DiagnosisOfNObjects_message", new String[] { Integer.toString(selectionSize) }), selectedObjects.toArray()); } Map<Object, Object> context = diagnostician.createDefaultContext(); for (EObject eObject : selectedObjects) { progressMonitor.setTaskName(EMFEditUIPlugin.INSTANCE.getString("_UI_Validating_message", new Object [] { diagnostician.getObjectLabel(eObject) })); diagnostician.validate(eObject, diagnostic, context); context.remove(EObjectValidator.ROOT_OBJECT); } return diagnostic; } protected Diagnostician createDiagnostician(final AdapterFactory adapterFactory, final IProgressMonitor progressMonitor) { final ResourceSet resourceSet = domain.getResourceSet(); return new Diagnostician() { @Override public String getObjectLabel(EObject eObject) { if (adapterFactory != null && !eObject.eIsProxy()) { IItemLabelProvider itemLabelProvider = (IItemLabelProvider)adapterFactory.adapt(eObject, IItemLabelProvider.class); if (itemLabelProvider != null) { return itemLabelProvider.getText(eObject); } } return super.getObjectLabel(eObject); } @Override protected boolean doValidate(EValidator eValidator, EClass eClass, EObject eObject, DiagnosticChain diagnostics, Map<Object, Object> context) { progressMonitor.worked(1); Resource resource = eObject.eResource(); if (resource == null) { synchronized (resourceSet) { return super.doValidate(eValidator, eClass, eObject, diagnostics, context); } } else { synchronized (resource) { synchronized (resourceSet) { return super.doValidate(eValidator, eClass, eObject, diagnostics, context); } } } } }; } protected void handleDiagnostic(Diagnostic diagnostic) { int severity = diagnostic.getSeverity(); String title = null; String message = null; if (severity == Diagnostic.ERROR || severity == Diagnostic.WARNING) { title = EMFEditUIPlugin.INSTANCE.getString("_UI_ValidationProblems_title"); message = EMFEditUIPlugin.INSTANCE.getString("_UI_ValidationProblems_message"); } else { title = EMFEditUIPlugin.INSTANCE.getString("_UI_ValidationResults_title"); message = EMFEditUIPlugin.INSTANCE.getString(severity == Diagnostic.OK ? "_UI_ValidationOK_message" : "_UI_ValidationResults_message"); } int result = 0; if (diagnostic.getSeverity() == Diagnostic.OK) { MessageDialog.openInformation(PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), title, message); result = Window.CANCEL; } else { result = DiagnosticDialog.open (PlatformUI.getWorkbench().getActiveWorkbenchWindow().getShell(), title, message, diagnostic); } ResourceSet resourceSet = domain.getResourceSet(); Resource resource = eclipseResourcesUtil != null ? resourceSet.getResources().get(0) : null; if (resource != null) { eclipseResourcesUtil.deleteMarkers(resource); } if (result == Window.OK) { if (!diagnostic.getChildren().isEmpty()) { List<?> data = (diagnostic.getChildren().get(0)).getData(); if (!data.isEmpty() && data.get(0) instanceof EObject) { Object part = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().getActivePart(); if (part instanceof ISetSelectionTarget) { ((ISetSelectionTarget)part).selectReveal(new StructuredSelection(data.get(0))); } else if (part instanceof IViewerProvider) { Viewer viewer = ((IViewerProvider)part).getViewer(); if (viewer != null) { viewer.setSelection(new StructuredSelection(data.get(0)), true); } } } } if (resource != null) { for (Diagnostic childDiagnostic : diagnostic.getChildren()) { eclipseResourcesUtil.createMarkers(resource, childDiagnostic); } } } else { // Trigger direct updating of decorations, if there are adapters. // resource = null; } if (resource == null) { // If no markers are produced the decorator won't be able to respond to marker resource deltas, so inform it directly. // // Create a diagnostic for the resource set as a whole. // BasicDiagnostic resourceSetDiagnostic = new BasicDiagnostic(EObjectValidator.DIAGNOSTIC_SOURCE, 0, null, new Object [] { resourceSet }); // Create a diagnostic for each resource. // Map<Resource, BasicDiagnostic> resourceDiagnostics = new LinkedHashMap<Resource, BasicDiagnostic>(); for (Resource r : resourceSet.getResources()) { BasicDiagnostic resourceDiagnostic = new BasicDiagnostic(EObjectValidator.DIAGNOSTIC_SOURCE, 0, null, new Object [] { r }); resourceDiagnostics.put(r, resourceDiagnostic); } // Just clean up decorations if the dialog was cancelled. // if (result == Dialog.OK) { // Partition the children among the resource diagnostics. // for (Diagnostic child : diagnostic.getChildren()) { List<?> data = child.getData(); if (!data.isEmpty()) { Object object = data.get(0); if (object instanceof EObject) { BasicDiagnostic resourceDiagnostic = resourceDiagnostics.get(((EObject)object).eResource()); if (resourceDiagnostic != null) { resourceDiagnostic.add(child); } } } } } // Add the resource diagnostics to the resource set diagnostic. // for (Diagnostic resourceDiagnostic : resourceDiagnostics.values()) { resourceSetDiagnostic.add(resourceDiagnostic); } // Inform any decorators. // DiagnosticDecorator.DiagnosticAdapter.update(resourceSet, resourceSetDiagnostic); } } public void selectionChanged(SelectionChangedEvent event) { selectionProvider = event.getSelectionProvider(); if (event.getSelection() instanceof IStructuredSelection) { setEnabled(updateSelection((IStructuredSelection)event.getSelection())); } else { setEnabled(false); } } public boolean updateSelection(IStructuredSelection selection) { selectedObjects = new ArrayList<EObject>(); for (Iterator<?> objects = selection.iterator(); objects.hasNext(); ) { Object object = AdapterFactoryEditingDomain.unwrap(objects.next()); if (object instanceof EObject) { selectedObjects.add((EObject)object); } else if (object instanceof Resource) { selectedObjects.addAll(((Resource)object).getContents()); } else { return false; } } selectedObjects = EcoreUtil.filterDescendants(selectedObjects); return !selectedObjects.isEmpty(); } /** * @since 2.1.0 */ public void setActiveWorkbenchPart(IWorkbenchPart workbenchPart) { if (workbenchPart instanceof IEditingDomainProvider) { domain = ((IEditingDomainProvider)workbenchPart).getEditingDomain(); } } }