blob: e40a95a6ce9d018561c29f3b64aca33c86611e0c [file] [log] [blame]
/*******************************************************************************
* <copyright>
*
* Copyright (c) 2005, 2012 SAP AG.
* 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:
* SAP AG - initial API, implementation and documentation
* mwenz - Bug 346932 - Navigation history broken
* Bug 336488 - DiagramEditor API
* mwenz - Bug 378342 - Cannot store more than a diagram per file
* pjpaulin - Bug 352120 - Now uses IDiagramContainerUI interface
* fvelasco - Bug 415888 - DiagramEditorInput should adapt to IResource
*
* </copyright>
*
*******************************************************************************/
package org.eclipse.graphiti.ui.editor;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Assert;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.emf.common.util.URI;
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.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.graphiti.mm.pictograms.Diagram;
import org.eclipse.graphiti.ui.internal.services.GraphitiUiInternal;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IMemento;
import org.eclipse.ui.IPersistableElement;
/**
* The editor input object for {@link IDiagramContainerUI}s. Wraps the {@link URI} of
* a {@link Diagram} and an ID of a diagram type provider for displaying it with
* a Graphiti diagram editor.<br>
*
* @see {@link IEditorInput}
* @see {@link IPersistableElement}
* @see {@link DiagramEditorInputFactory}
* @see {@link IDiagramContainerUI}
*/
public class DiagramEditorInput implements IEditorInput, IPersistableElement, IDiagramEditorInput {
/**
* The memento key for the stored {@link URI} string
*/
public static final String KEY_URI = "org.eclipse.graphiti.uri"; //$NON-NLS-1$
/**
* The memento key for the ID of the diagram type provider.
*/
public static String KEY_PROVIDER_ID = "org.eclipse.graphiti.providerId"; //$NON-NLS-1$
/**
* The stored {@link URI} string
*/
private URI uri;
/**
* The ID of the diagram type provider.
*/
private String providerId;
/**
* The cached input name (e.g. for displaying the name in the navigation
* history without having to instantiate the {@link EObject})
*
* @see #getLiveName()
*/
private String name;
/**
* The cached input tooltip
*
* @see #getLiveToolTipText()
*/
private String tooltip;
/**
* Creates a new {@link DiagramEditorInput} out of a {@link URI} string and
* a Graphiti diagram type provider ID. For resolving the {@link URI} to an
* {@link EObject} the {@link ResourceSet} that will be created when a
* diagram editor starts is taken. This input object will not resolve the
* diagram.<br>
* A diagram type provider ID is held in this class.
*
* @param diagramUri
* A {@link URI} that denotes the input's {@link EObject}. This
* can either be a URI of a Graphiti diagram or the URI of an EMF
* resource storing a Graphiti diagram. In the latter case the
* given URI will b e trimmed to point to the first element in
* the resource; make sure that this element is a Graphiti
* diagram, otherwise an exception will be thrown when the
* diagram editor opens. No check on this is done inside the
* input object itself!
* @param providerId
* A {@link String} which holds the diagram type id. When it is
* null, it is set later in
* {@link DiagramBehavior#setInput(IEditorInput)}
* @throws IllegalArgumentException
* if <code>uriString</code> parameter is null <br>
*
* @see URI
* @since 0.9
*/
public DiagramEditorInput(URI diagramUri, String providerId) {
Assert.isNotNull(diagramUri, "diagram must not be null"); //$NON-NLS-1$
// Normalize URI for later compare operations
this.uri = normalizeUriString(diagramUri);
setProviderId(providerId);
}
private URI normalizeUriString(URI diagramUri) {
URI normalizedURI = new ResourceSetImpl().getURIConverter().normalize(diagramUri);
// Do the trimming only in case no explicit fragment (no specific
// diagram inside the resource) was provided. In case a fragment was
// provided, use it, otherwise simply take the first element in the
// resource (#0)
if (!normalizedURI.hasFragment() || "/".equals(normalizedURI.fragment())) {
URI trimFragment = normalizedURI.trimFragment();
normalizedURI = GraphitiUiInternal.getEmfService().mapDiagramFileUriToDiagramUri(trimFragment);
}
return normalizedURI;
}
/**
* Creates a new {@link DiagramEditorInput} for the given {@link Diagram}
* and the given diagram type provider ID.
*
* @param diagram
* A {@link Diagram}
* @param providerId
* A {@link String} which holds the diagram type provider id.
* @return A {@link DiagramEditorInput} editor input
* @since 0.9
*/
public static DiagramEditorInput createEditorInput(Diagram diagram, String providerId) {
final Resource resource = diagram.eResource();
if (resource == null) {
throw new IllegalArgumentException("Diagram must be contained within a resource");
}
URI diagramUri = EcoreUtil.getURI(diagram);
DiagramEditorInput diagramEditorInput = new DiagramEditorInput(diagramUri, providerId);
return diagramEditorInput;
}
/**
* Returns the diagram type provider id.
*
* @return The providerId.
*/
public String getProviderId() {
return this.providerId;
}
/**
* Sets the diagram type provider id.
*
* @param providerId
* The providerId to set.
*/
public void setProviderId(String providerId) {
this.providerId = providerId;
}
/**
* Returns the factory ID for creating {@link DiagramEditorInput}s from
* mementos.
*
* @return The ID of the associated factory
*/
public String getFactoryId() {
return DiagramEditorInputFactory.class.getName();
}
/**
* @return Simply returns <code>null</code>.
*/
public ImageDescriptor getImageDescriptor() {
return null;
}
/**
* @return The cached name or the input's {@link URI} string
* @see #getLiveName()
*/
public String getName() {
if (this.name != null) {
return this.name;
}
return this.uri.toString();
}
/**
* Checks if a name is set for this instance
*
* @return <code>true</code> in case a name is set, <code>false</code> in
* name is <code>null</code>.
*/
protected boolean hasName() {
return this.name != null;
}
/**
* Sets the name for this instance.
*
* @param name
* The name to set.
*/
protected void setName(String name) {
this.name = name;
}
/**
* @return The cached tooltip or the input's {@link URI} string
* @see #getLiveToolTipText()
*/
public String getToolTipText() {
if (this.tooltip != null) {
return this.tooltip;
}
return getName();
}
/**
* Adapter method as defined in {@link IAdaptable}, supports adaptation to
* {@link IFile}.
*
* @param adapter
* The adapter class to look up
* @return A object castable to the given class, or <code>null</code> if
* this object does not have an adapter for the given class
*/
public Object getAdapter(@SuppressWarnings("rawtypes") Class adapter) {
if (IFile.class.isAssignableFrom(adapter) || IResource.class.equals(adapter)) {
return GraphitiUiInternal.getEmfService().getFile(getUri());
}
return null;
}
/**
* Saves {@link URI} string, object name and provider ID to the given
* {@link IMemento}.
*
* @param memento
* The memento to store the information in
*/
public void saveState(IMemento memento) {
// Do not store anything for deleted objects
boolean exists = exists();
if (!exists) {
return;
}
// Store object name, URI and diagram type provider ID
memento.putString(KEY_URI, this.uri.toString());
memento.putString(KEY_PROVIDER_ID, this.providerId);
}
/**
* @return The {@link URI} string this input and its editors operate on
*/
public final String getUriString() {
return this.uri.toString();
}
/**
* Checks if the diagram this input represents exist.
* <p>
* Note: The editor gets only restored, when <code>true</code> is returned.
*
* @return <code>true</code> if the input's state denotes a living EMF
* object <br>
*/
public boolean exists() {
if (uri == null) {
return false;
}
// TODO check if URI points to something
return true;
}
/**
* @return this input if it is persistable, otherwise null
*/
public IPersistableElement getPersistable() {
if (uri != null && providerId != null) {
return this;
}
return null;
}
/**
* @return the resolved {@link URI} or <code>null</code> in case of failures
* @since 0.9
*/
public URI getUri() {
return this.uri;
}
/**
* Checks if this instance of the input represent the same object as the
* given instance.
*
* @param obj
* The object to compare this instance with.
* @return <code>true</code> if the represented objects are the same
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
DiagramEditorInput other = (DiagramEditorInput) obj;
if (uri == null) {
if (other.uri != null) {
return false;
}
} else if (!uri.equals(other.uri)) {
return false;
}
if (providerId == null) {
if (other.providerId != null) {
return false;
}
} else if (!providerId.equals(other.providerId)) {
return false;
}
return true;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((uri == null) ? 0 : uri.hashCode());
result = prime * result + ((providerId == null) ? 0 : providerId.hashCode());
return result;
}
/**
* Used for logging only!
*/
@Override
public String toString() {
final String s = super.toString() + " uri: " + this.uri; //$NON-NLS-1$
return s;
}
/**
* @since 0.9
*/
public void updateUri(URI diagramFileUri) {
URI uri = GraphitiUiInternal.getEmfService().mapDiagramFileUriToDiagramUri(diagramFileUri);
URI normalizedUri = normalizeUriString(uri);
this.uri = normalizedUri;
}
}