/**
* <copyright>
*
* Copyright (c) 2005, 2009 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
*
* </copyright>
*
* $Id: EditUIUtil.java,v 1.8 2008/05/23 21:49:17 davidms Exp $
*/
package net.enilink.komma.edit.ui.util;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.content.IContentDescription;
import org.eclipse.core.runtime.content.IContentType;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PartInitException;
import org.eclipse.ui.PlatformUI;
import net.enilink.komma.common.AbstractKommaPlugin;
import net.enilink.komma.common.ui.EclipseUtil;
import net.enilink.komma.common.ui.URIEditorInput;
import net.enilink.komma.common.util.UniqueExtensibleList;
import net.enilink.komma.core.IReference;
import net.enilink.komma.core.URI;
import net.enilink.komma.core.URIs;
import net.enilink.komma.edit.domain.IEditingDomain;
import net.enilink.komma.edit.domain.IEditingDomainProvider;
import net.enilink.komma.edit.ui.KommaEditUIPlugin;
import net.enilink.komma.model.IModelSet;
import net.enilink.komma.model.IObject;
import net.enilink.komma.model.IURIConverter;
import net.enilink.komma.model.ModelUtil;
import net.enilink.komma.model.base.ExtensibleURIConverter;
public class EditUIUtil {
public static class URIEditorInputWithProject extends URIEditorInput {
IProject project;
public URIEditorInputWithProject(URI uri, IProject project) {
super(uri);
this.project = project;
}
public URIEditorInputWithProject(IMemento memento) {
super(memento);
}
@Override
protected void loadState(IMemento memento) {
super.loadState(memento);
String projectName = memento.getString("project");
if (AbstractKommaPlugin.IS_RESOURCES_BUNDLE_AVAILABLE) {
project = ResourcesPlugin.getWorkspace().getRoot().getProject(projectName);
}
}
@Override
public void saveState(IMemento memento) {
super.saveState(memento);
memento.putString("project", project.getName());
}
@Override
public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
if (IProject.class.equals(adapter)) {
return project;
}
return super.getAdapter(adapter);
}
@Override
protected String getBundleSymbolicName() {
return KommaEditUIPlugin.PLUGIN_ID;
}
}
/**
* Opens the default editor for the resource. This method only works if the
* model's URI is a platform resource URI.
*/
public static boolean openEditor(IReference resource) throws PartInitException {
URI uri = resource.getURI();
if (uri != null) {
IProject project = null;
URI normalizedURI = uri;
if (resource instanceof IObject) {
IModelSet modelSet = ((IObject) resource).getModel().getModelSet();
normalizedURI = modelSet.getURIConverter().normalize(uri);
try {
Method getProject = modelSet.getClass().getMethod("getProject");
if (IProject.class.isAssignableFrom(getProject.getReturnType())) {
project = (IProject) getProject.invoke(modelSet);
}
} catch (Exception e) {
// method does not exists
}
}
IEditorInput editorInput = null;
if (normalizedURI.isPlatformResource()) {
String path = normalizedURI.toPlatformString(true);
IResource workspaceResource = ResourcesPlugin.getWorkspace().getRoot().findMember(new Path(path));
if (workspaceResource instanceof IFile) {
editorInput = EclipseUtil.createEditorInput((IFile) workspaceResource);
}
}
if (editorInput == null) {
if (project == null) {
editorInput = new URIEditorInput(uri);
} else {
editorInput = new URIEditorInputWithProject(uri, project);
}
}
IEditorDescriptor editorDesc = getDefaultEditor(normalizedURI.toString());
if (editorDesc == null) {
editorDesc = getDefaultEditor(uri, resource instanceof IObject
? ((IObject) resource).getModel().getModelSet().getURIConverter() : null);
}
if (editorDesc != null) {
IWorkbenchPage page = PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage();
IEditorPart editorPart = page.openEditor(editorInput, editorDesc.getId());
return editorPart != null;
}
}
return false;
}
public static URI getURI(IEditorInput editorInput) {
URI result = null;
if (AbstractKommaPlugin.IS_ECLIPSE_RUNNING) {
result = EclipseUtil.getURI(editorInput);
}
if (result == null) {
if (editorInput instanceof URIEditorInput) {
result = ((URIEditorInput) editorInput).getURI().trimFragment();
} else {
result = URIs.createURI(editorInput.getName());
}
}
return result;
}
/**
* Returns the default editor for a given file name. This method is like
* {@link IEditorRegistry#getDefaultEditor(String)}, but it will not return
* <code>null</code> unless all applicable content types have no associated
* editor.
*
* @param fileName
* the file name in the system
* @return the descriptor of the default editor, or <code>null</code> if not
* found
*/
public static IEditorDescriptor getDefaultEditor(String fileName) {
return fileName != null && fileName.length() != 0
? getDefaultEditor(fileName, Platform.getContentTypeManager().findContentTypesFor(fileName)) : null;
}
private static IEditorDescriptor getDefaultEditor(String fileName, IContentType... contentTypes) {
IEditorRegistry editorRegistry = PlatformUI.getWorkbench().getEditorRegistry();
if (contentTypes.length == 0) {
return editorRegistry.getDefaultEditor(fileName, null);
}
IEditorDescriptor result = null;
for (int i = 0; result == null && i < contentTypes.length; i++) {
result = editorRegistry.getDefaultEditor(fileName, contentTypes[i]);
}
return result;
}
/**
* Returns the default editor for a given URI. This method actually attempts
* to open an input stream for the URI and uses its contents, along with the
* filename (the URI's last segment), to obtain appropriate content types.
* <p>
* If a URI converter is specified, it is used to open the stream.
* Otherwise, the global default {@link URIConverter#INSTANCE instance} is
* used.
*
* @param uri
* a URI
* @param uriConverter
* URI converter from which to obtain an input stream, or
* <code>null</code>
* @return the descriptor of the default editor, or <code>null</code> if not
* found
*/
public static IEditorDescriptor getDefaultEditor(URI uri, IURIConverter uriConverter) {
String fileName = URIs.decode(uri.lastSegment());
if (!fileName.matches(".*\\.[^.]+$")) {
fileName = null;
}
if (uriConverter == null) {
uriConverter = new ExtensibleURIConverter();
}
try {
IContentDescription contentDescription = ModelUtil.determineContentDescription(uri, uriConverter,
Collections.emptyMap());
if (contentDescription != null) {
return getDefaultEditor(fileName, contentDescription.getContentType());
}
} catch (IOException e) {
KommaEditUIPlugin.INSTANCE.log(e);
}
return getDefaultEditor(fileName);
}
private static void close(InputStream stream) {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
KommaEditUIPlugin.INSTANCE.log(e);
}
}
}
/**
* Returns the editors for a given file name. This method is like
* {@link IEditorRegistry#getEditors(String)}, but its result will include
* editors for all applicable content types.
*
* @param fileName
* the file name in the system
* @param defaultsOnly
* if <code>true</code>, only the default editor for each content
* type will be included in the result
* @return the descriptors of the editors
*/
public static IEditorDescriptor[] getEditors(String fileName, boolean defaultsOnly) {
return fileName != null && fileName.length() != 0
? getEditors(fileName, Platform.getContentTypeManager().findContentTypesFor(fileName), defaultsOnly)
: new IEditorDescriptor[0];
}
/**
* Returns the editors for a given contents and file name.
* <p>
* If a file name is not provided, the entire content type registry will be
* queried. For performance reasons, it is highly recommended to provide a
* file name if available.
*
* @param contents
* an input stream
* @param fileName
* the file name associated to the contents, or <code>null</code>
* @param defaultsOnly
* if <code>true</code>, only the default editor for each content
* type will be included in the result
* @return the descriptors of the editors
*/
public static IEditorDescriptor[] getEditors(InputStream contents, String fileName, boolean defaultsOnly) {
if (contents != null) {
try {
return getEditors(fileName, Platform.getContentTypeManager().findContentTypesFor(contents, fileName),
defaultsOnly);
} catch (IOException e) {
KommaEditUIPlugin.INSTANCE.log(e);
}
}
return getEditors(fileName, defaultsOnly);
}
private static IEditorDescriptor[] getEditors(String fileName, IContentType[] contentTypes, boolean defaultsOnly) {
IEditorRegistry editorRegistry = PlatformUI.getWorkbench().getEditorRegistry();
if (contentTypes.length == 0) {
return editorRegistry.getEditors(fileName, null);
}
List<IEditorDescriptor> result = new UniqueExtensibleList<IEditorDescriptor>();
for (IContentType contentType : contentTypes) {
if (defaultsOnly) {
IEditorDescriptor editor = editorRegistry.getDefaultEditor(fileName, contentType);
if (editor != null) {
result.add(editor);
}
} else {
result.addAll(Arrays.asList(editorRegistry.getEditors(fileName, contentType)));
}
}
return result.toArray(new IEditorDescriptor[result.size()]);
}
/**
* Returns the editors for a given URI. This method actually attempts to
* open an input stream for the URI and uses its contents, along with the
* filename (the URI's last segment), to obtain appropriate content types.
* <p>
* If a URI converter is specified, it is used to open the stream.
* Otherwise, the global default {@link URIConverter#INSTANCE instance} is
* used.
*
* @param uri
* a URI
* @param uriConverter
* a URI converter from which to obtain an input stream, or
* <code>null</code>
* @param defaultsOnly
* if <code>true</code>, only the default editor for each content
* type will be included in the result
* @return the descriptors of the editors
*/
public static IEditorDescriptor[] getEditors(URI uri, IURIConverter uriConverter, boolean defaultsOnly) {
String fileName = URIs.decode(uri.lastSegment());
if (uriConverter == null) {
uriConverter = new ExtensibleURIConverter();
}
InputStream stream = null;
try {
stream = uriConverter.createInputStream(uri);
return getEditors(stream, fileName, defaultsOnly);
} catch (IOException e) {
KommaEditUIPlugin.INSTANCE.log(e);
return getEditors(fileName, defaultsOnly);
} finally {
close(stream);
}
}
/**
* Creates a corresponding error status object for the given
* <code>exception</code>.
*
* @param exception
* The exception for which an error status object should be
* created.
* @return The error status.
*/
public static IStatus createErrorStatus(Exception exception) {
return new Status(Status.ERROR, KommaEditUIPlugin.PLUGIN_ID, exception.getMessage(), exception);
}
}