blob: 2ace2d76c8077ca54728c6c39702c88bdf34ab9d [file] [log] [blame]
/**
* 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();
}
}
}