blob: 2518a36387b587aa0620004777049253ab1907d7 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2014, 2018 CEA LIST and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v20.html
*
* Contributors:
* E.D.Willink (CEA LIST) - initial API and implementation
*******************************************************************************/
package org.eclipse.ocl.xtext.base.ui.commands;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.eclipse.core.commands.HandlerEvent;
import org.eclipse.core.commands.IHandlerListener;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IProgressMonitor;
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.ecore.EObject;
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.ui.EMFEditUIPlugin;
import org.eclipse.emf.edit.ui.action.ValidateAction;
import org.eclipse.emf.edit.ui.provider.DiagnosticDecorator;
import org.eclipse.jdt.annotation.Nullable;
import org.eclipse.jface.dialogs.Dialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.Window;
import org.eclipse.ocl.pivot.internal.utilities.PivotDiagnostician;
import org.eclipse.ocl.pivot.utilities.ClassUtil;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.part.ISetSelectionTarget;
public class ValidateCommand extends ValidateAction
{
@Override
protected Diagnostician createDiagnostician(AdapterFactory adapterFactory, @Nullable IProgressMonitor progressMonitor) {
ResourceSet resourceSet = ClassUtil.nonNullEMF(domain.getResourceSet());
return PivotDiagnostician.createDiagnostician(resourceSet, adapterFactory, progressMonitor);
}
/**
* Fires an event to all registered listeners describing changes to this
* instance.
* <p>
* Subclasses may extend the definition of this method (i.e., if a different
* type of listener can be attached to a subclass). This is used primarily
* for support of <code>AbstractHandler</code> in
* <code>org.eclipse.ui.workbench</code>, and clients should be wary of
* overriding this behaviour. If this method is overridden, then the first
* line of the method should be "<code>super.fireHandlerChanged(handlerEvent);</code>".
* </p>
*
* @param handlerEvent
* the event describing changes to this instance. Must not be
* <code>null</code>.
*/
protected void fireHandlerChanged(final HandlerEvent handlerEvent) {
if (handlerEvent == null) {
throw new NullPointerException();
}
final Object[] listeners = getListeners();
for (int i = 0; i < listeners.length; i++) {
final IHandlerListener listener = (IHandlerListener) listeners[i];
listener.handlerChanged(handlerEvent);
}
}
@Override // FIXME BUG 435735 Overridden to select resource more intelligently for Papyrus
protected void handleDiagnostic(Diagnostic diagnostic) {
IWorkbenchWindow activeWorkbenchWindow = PlatformUI.getWorkbench().getActiveWorkbenchWindow();
if (activeWorkbenchWindow == null) {
return;
}
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(activeWorkbenchWindow.getShell(), title, message);
result = Window.CANCEL;
} else {
result = DiagnosticDialog.open(activeWorkbenchWindow.getShell(), title, message, diagnostic);
}
ResourceSet resourceSet = domain.getResourceSet();
// The following lines replace the simple inherited assumption of resourceSet.getResources().get(0)
Resource resource = null;
if (eclipseResourcesUtil != null) {
List<?> data = diagnostic.getData();
if ((data != null) && (data.size() >= 1)) {
Object object = data.get(0);
if (object instanceof EObject) {
resource = ((EObject)object).eResource();
}
}
if (resource == null) {
resource = resourceSet.getResources().get(0);
}
}
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 = activeWorkbenchWindow.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.
//
try {
DiagnosticDecorator.DiagnosticAdapter.update(resourceSet, resourceSetDiagnostic);
}
catch (Throwable e) {} // Expect class load failure on EMF 2.8
}
}
/**
* <p>
* Returns true iff there is one or more IHandlerListeners attached to this
* AbstractHandler.
* </p>
* <p>
* Subclasses may extend the definition of this method (i.e., if a different
* type of listener can be attached to a subclass). This is used primarily
* for support of <code>AbstractHandler</code> in
* <code>org.eclipse.ui.workbench</code>, and clients should be wary of
* overriding this behaviour. If this method is overridden, then the return
* value should include "<code>super.hasListeners() ||</code>".
* </p>
*
* @return true iff there is one or more IHandlerListeners attached to this
* AbstractHandler
*/
protected boolean hasListeners() {
return isListenerAttached();
}
@Override
public void setActiveWorkbenchPart(IWorkbenchPart workbenchPart) {
Object object = workbenchPart.getAdapter(EditingDomain.class);
if (object instanceof EditingDomain) {
domain = (EditingDomain)object;
return;
}
object = workbenchPart.getAdapter(IEditingDomainProvider.class);
if (object instanceof IEditingDomainProvider) {
domain = ((IEditingDomainProvider)object).getEditingDomain();
return;
}
if (workbenchPart instanceof IEditingDomainProvider) {
domain = ((IEditingDomainProvider) workbenchPart).getEditingDomain();
}
}
@Override
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 IAdaptable) {
object = ((IAdaptable) object).getAdapter(EObject.class);
}
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();
}
}