/******************************************************************************* * <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; } }