blob: 2d7634fcd4686e1803b0c80760a1c6fe3d2656a0 [file] [log] [blame]
/**
* <copyright>
*
* Copyright (c) 2008-2013 See4sys, itemis 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:
* See4sys - Initial API and implementation
* itemis - [418005] Add support for model files with multiple root elements
*
* </copyright>
*/
package org.eclipse.sphinx.emf.ui.util;
import java.net.MalformedURLException;
import java.util.HashSet;
import java.util.Set;
import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.emf.common.ui.URIEditorInput;
import org.eclipse.emf.common.ui.viewer.IViewerProvider;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.FeatureMap;
import org.eclipse.emf.edit.domain.AdapterFactoryEditingDomain;
import org.eclipse.emf.edit.provider.IWrapperItemProvider;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.jface.util.OpenStrategy;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.window.Window;
import org.eclipse.jface.wizard.IWizard;
import org.eclipse.jface.wizard.WizardDialog;
import org.eclipse.sphinx.emf.ui.actions.providers.OpenWithMenu;
import org.eclipse.sphinx.emf.ui.internal.Activator;
import org.eclipse.sphinx.emf.util.EcorePlatformUtil;
import org.eclipse.sphinx.emf.util.WorkspaceTransactionUtil;
import org.eclipse.sphinx.platform.ui.util.ExtendedPlatformUI;
import org.eclipse.sphinx.platform.util.PlatformLogUtil;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IURIEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.part.FileEditorInput;
/**
*
*/
public class EcoreUIUtil {
// Prevent from instantiation
private EcoreUIUtil() {
}
/**
* Open the editor using the active workbench page for the given object. If {@link OpenStrategy#OPEN_ON_RESOURCE} is
* given, the method will retrieve the resource behind the object before opening the editor.
*
* @param object
* The object for which to open the editor or the resource behind it.
* @param openStrategy
* A flag to indicate whether to open the editor on the given object or on the resource behind it.
* @see org.eclipse.sphinx.emf.ui.util.OpenStrategy
*/
public static void openEditor(Object object, int openStrategy) {
openEditor(ExtendedPlatformUI.getActivePage(), object, openStrategy);
}
public static void openEditor(IWorkbenchPage page, Object object, int openStrategy) {
Assert.isLegal(openStrategy == org.eclipse.sphinx.emf.ui.util.OpenStrategy.OPEN_ON_OBJECT
|| openStrategy == org.eclipse.sphinx.emf.ui.util.OpenStrategy.OPEN_ON_RESOURCE);
try {
IEditorPart editor = null;
if (openStrategy == org.eclipse.sphinx.emf.ui.util.OpenStrategy.OPEN_ON_OBJECT) {
IEditorInput editorInput = EcoreUIUtil.createURIEditorInput(object);
IEditorDescriptor defaultEditor = getDefaultEditor(object);
if (defaultEditor != null) {
editor = page.openEditor(editorInput, defaultEditor.getId());
}
} else if (openStrategy == org.eclipse.sphinx.emf.ui.util.OpenStrategy.OPEN_ON_RESOURCE) {
IFile file = EcorePlatformUtil.getFile(object);
editor = IDE.openEditor(page, file, OpenStrategy.activateOnOpen());
}
if (editor != null && editor instanceof IViewerProvider) {
Viewer editorViewer = ((IViewerProvider) editor).getViewer();
editorViewer.setSelection(new StructuredSelection(object), true);
}
} catch (PartInitException ex) {
PlatformLogUtil.logAsError(Activator.getDefault(), ex);
}
}
public static void openWizardDialog(final IWizard wizard) throws OperationCanceledException, ExecutionException {
openWizardDialog(wizard, null);
}
/**
* @param wizard
* The wizard the dialog to open is supposed to work on.
* @param editingDomain
* The transactional editing domain to use for the transaction.
* @throws OperationCanceledException
* that is mandatory to force underlying operation to abort without commit if user clicks on the cancel
* button.
* @throws ExecutionException
* if an execution exception occurs.
*/
public static void openWizardDialog(final IWizard wizard, TransactionalEditingDomain editingDomain) throws OperationCanceledException,
ExecutionException {
Assert.isNotNull(wizard);
final Runnable runnable = new Runnable() {
@Override
public void run() {
// Creates and opens the wizard dialog
int result = new WizardDialog(ExtendedPlatformUI.getDisplay().getActiveShell(), wizard).open();
if (result == Window.CANCEL) {
// OperationCanceledException is mandatory to force underlying operation to abort without commit
throw new OperationCanceledException(wizard.getWindowTitle());
}
}
};
if (editingDomain != null) {
WorkspaceTransactionUtil.executeInWriteTransaction(editingDomain, runnable, wizard.getWindowTitle());
} else {
runnable.run();
}
}
public static URIEditorInput createURIEditorInput(Object object) {
URI uri = null;
if (object instanceof URI) {
uri = (URI) object;
} else if (object instanceof Resource) {
uri = ((Resource) object).getURI();
} else if (object instanceof EObject) {
if (!((EObject) object).eIsProxy()) {
uri = EcoreUtil.getURI((EObject) object);
}
} else if (object instanceof IWrapperItemProvider) {
Object unwrapped = AdapterFactoryEditingDomain.unwrap(object);
return createURIEditorInput(unwrapped);
} else if (object instanceof FeatureMap.Entry) {
Object unwrapped = AdapterFactoryEditingDomain.unwrap(object);
return createURIEditorInput(unwrapped);
}
if (uri != null) {
return new ExtendedURIEditorInput(uri);
}
return null;
}
public static IEditorDescriptor getDefaultEditor(Object object) {
if (object instanceof EObject) {
return getDefaultEditor(((EObject) object).eClass());
} else if (object instanceof IWrapperItemProvider) {
Object unwrapped = AdapterFactoryEditingDomain.unwrap(object);
return getDefaultEditor(unwrapped);
} else if (object instanceof FeatureMap.Entry) {
Object unwrapped = AdapterFactoryEditingDomain.unwrap(object);
return getDefaultEditor(unwrapped);
} else if (object instanceof Resource) {
String fileName = ((Resource) object).getURI().lastSegment();
return PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor(fileName);
}
return null;
}
/**
* A convenience method usually used to populate an {@linkplain OpenWithMenu}
*
* @param object
* @return
*/
public static IEditorDescriptor[] getEditors(Object object) {
if (object instanceof EObject) {
return getEditors(((EObject) object).eClass());
} else if (object instanceof IWrapperItemProvider) {
Object unwrapped = AdapterFactoryEditingDomain.unwrap(object);
return getEditors(unwrapped);
} else if (object instanceof FeatureMap.Entry) {
Object unwrapped = AdapterFactoryEditingDomain.unwrap(object);
return getEditors(unwrapped);
} else if (object instanceof Resource) {
String fileName = ((Resource) object).getURI().lastSegment();
return PlatformUI.getWorkbench().getEditorRegistry().getEditors(fileName);
}
return null;
}
public static IEditorDescriptor[] getEditors(EClass eClass) {
return findEditorsForType(eClass);
}
/**
* @deprecated Use {@link EcoreUIUtil#getDummyFileName(EClass)} instead.
*/
@Deprecated
public static String getDummyFileName(Class<?> objectType) {
String dummyFileName = "*." + objectType.getName(); //$NON-NLS-1$
return dummyFileName;
}
public static String getDummyFileName(EClass eClass) {
String dummyFileName = "*." + eClass.getInstanceClassName(); //$NON-NLS-1$
return dummyFileName;
}
/**
* @deprecated Use {@link EcoreUIUtil#getDefaultEditor(EClass)} instead.
*/
@Deprecated
public static IEditorDescriptor getDefaultEditor(Class<?> type) {
IEditorDescriptor descriptor = findDefaultEditorForType(type);
if (descriptor == null) {
descriptor = findDefaultEditorForSuperType(type);
}
return descriptor;
}
public static IEditorDescriptor getDefaultEditor(EClass eClass) {
IEditorDescriptor descriptor = findDefaultEditorForType(eClass);
if (descriptor == null) {
descriptor = findDefaultEditorForSuperType(eClass);
}
return descriptor;
}
public static URI getURIFromEditorInput(IEditorInput editorInput) {
if (editorInput instanceof FileEditorInput) {
FileEditorInput fileEditorInput = (FileEditorInput) editorInput;
return URI.createPlatformResourceURI(fileEditorInput.getFile().getFullPath().toString(), true);
}
if (editorInput instanceof URIEditorInput) {
return ((URIEditorInput) editorInput).getURI();
}
if (editorInput instanceof IURIEditorInput) {
IURIEditorInput uriEditorInput = (IURIEditorInput) editorInput;
java.net.URI uri = uriEditorInput.getURI();
if (uri != null) {
try {
return URI.createFileURI(uri.toURL().getFile());
} catch (MalformedURLException ex) {
PlatformLogUtil.logAsError(Activator.getPlugin(), ex);
}
}
}
if (editorInput != null) {
IFile file = (IFile) editorInput.getAdapter(IFile.class);
if (file != null) {
return EcorePlatformUtil.createURI(file.getFullPath());
}
}
return null;
}
/**
* Returns the file behind the editor input
*
* @param editorInput
* @return as specified above
*/
public static IFile getFileFromEditorInput(IEditorInput editorInput) {
if (editorInput instanceof URIEditorInput) {
return EcorePlatformUtil.getFile(((URIEditorInput) editorInput).getURI());
}
if (editorInput != null) {
return (IFile) editorInput.getAdapter(IFile.class);
}
return null;
}
private static IEditorDescriptor[] findEditorsForType(EClass eClass) {
Set<IEditorDescriptor> result = new HashSet<IEditorDescriptor>();
if (eClass != null) {
// Try to find editors registered with qualified or simple EClass name
for (IEditorDescriptor descriptor : PlatformUI.getWorkbench().getEditorRegistry().getEditors(getDummyFileName(eClass))) {
if (!isInapplicableTextBasedEditor(descriptor)) {
result.add(descriptor);
}
}
// Try to find editors registered for all super types
for (EClass superType : eClass.getEAllSuperTypes()) {
for (IEditorDescriptor descriptor : PlatformUI.getWorkbench().getEditorRegistry().getEditors(getDummyFileName(superType))) {
if (!isInapplicableTextBasedEditor(descriptor)) {
result.add(descriptor);
}
}
}
}
return result.toArray(new IEditorDescriptor[result.size()]);
}
private static IEditorDescriptor findDefaultEditorForSuperType(Class<?> objectType) {
if (objectType != null) {
// Try to find matching super class
Set<Class<?>> superTypes = new HashSet<Class<?>>();
if (!objectType.isInterface()) {
Class<?> superClass = objectType.getSuperclass();
if (superClass != null) {
superTypes.add(superClass);
IEditorDescriptor descriptor = findDefaultEditorForType(superClass);
if (descriptor != null) {
return descriptor;
}
}
}
// Try to find matching interface
Class<?>[] interfaces = objectType.getInterfaces();
for (Class<?> interfaze : interfaces) {
superTypes.add(interfaze);
IEditorDescriptor descriptor = findDefaultEditorForType(interfaze);
if (descriptor != null) {
return descriptor;
}
}
// Try to find matching super type of super class and interfaces
for (Class<?> superType : superTypes) {
IEditorDescriptor descriptor = findDefaultEditorForSuperType(superType);
if (descriptor != null) {
return descriptor;
}
}
}
return null;
}
private static IEditorDescriptor findDefaultEditorForSuperType(EClass eClass) {
if (eClass != null) {
for (EClass superType : eClass.getEAllSuperTypes()) {
IEditorDescriptor defaultEditor = findDefaultEditorForType(superType);
if (defaultEditor != null) {
return defaultEditor;
}
}
}
return null;
}
private static IEditorDescriptor findDefaultEditorForType(Class<?> objectType) {
if (objectType != null) {
// Try to find editor registered with qualified or simple object type name
String dummyFileName = "*." + objectType.getName(); //$NON-NLS-1$
IEditorDescriptor descriptor = PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor(dummyFileName);
if (descriptor != null) {
if (!isInapplicableTextBasedEditor(descriptor)) {
return descriptor;
} else {
// Try to find alternative editor
for (IEditorDescriptor alternativeDescriptor : PlatformUI.getWorkbench().getEditorRegistry().getEditors(dummyFileName)) {
if (alternativeDescriptor != descriptor && !isInapplicableTextBasedEditor(alternativeDescriptor)) {
return alternativeDescriptor;
}
}
}
}
}
return null;
}
private static IEditorDescriptor findDefaultEditorForType(EClass eClass) {
if (eClass != null) {
// Try to find editor registered with qualified or simple object type name
IEditorDescriptor descriptor = PlatformUI.getWorkbench().getEditorRegistry().getDefaultEditor(getDummyFileName(eClass));
if (descriptor != null) {
if (!isInapplicableTextBasedEditor(descriptor)) {
return descriptor;
} else {
// Try to find alternative editor
for (IEditorDescriptor alternativeDescriptor : PlatformUI.getWorkbench().getEditorRegistry().getEditors(getDummyFileName(eClass))) {
if (alternativeDescriptor != descriptor && !isInapplicableTextBasedEditor(alternativeDescriptor)) {
return alternativeDescriptor;
}
}
}
}
}
return null;
}
/**
* Avoid that model objects are opened in file-based editors. This may happen in case that file-based editors are
* registered upon file extensions which are equal to the simple class name of some model object (e.g. model object
* type = Library, file extension = *.library)
*/
// TODO This hard-coded kind of file editor exclusions could eventually be avoided by providing a separate extension
// point for model editors or by handing in a list of inapplicable editor id patterns via the API
private static boolean isInapplicableTextBasedEditor(IEditorDescriptor editorDescriptor) {
if (editorDescriptor.getId().startsWith("org.eclipse.ui") || editorDescriptor.getId().startsWith("org.eclipse.wst")) { //$NON-NLS-1$ //$NON-NLS-2$
return true;
}
return false;
}
}