/******************************************************************************* * <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 329523 - Add notification of DiagramTypeProvider after saving a diagram * mwenz - Bug 320635 - Could not open an existing diagram * tkaiser - Bug 340939 - Only one instance of an Graphiti editor may exist, for each editor input * Bug 336488 - DiagramEditor API * mwenz - Bug 372753 - save shouldn't (necessarily) flush the command stack * mwenz - Bug 371513 - Save failed with NPE when switching editors * mwenz - Bug 393074 - Save Editor Progress Monitor Argument * fvelasco - Bug 412838 - Check for read-only resources before saving * * </copyright> * *******************************************************************************/ package org.eclipse.graphiti.ui.internal.services.impl; import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Map.Entry; import java.util.Set; import java.util.TreeMap; import org.eclipse.core.commands.operations.DefaultOperationHistory; import org.eclipse.core.resources.IFile; import org.eclipse.core.resources.IResource; import org.eclipse.core.resources.IWorkspaceRoot; import org.eclipse.core.resources.ResourcesPlugin; import org.eclipse.core.runtime.IPath; import org.eclipse.core.runtime.Path; import org.eclipse.emf.common.util.EList; import org.eclipse.emf.common.util.URI; import org.eclipse.emf.common.util.WrappedException; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.ENamedElement; 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.emf.edit.provider.ComposedAdapterFactory; import org.eclipse.emf.transaction.TransactionalEditingDomain; import org.eclipse.emf.transaction.impl.TransactionalEditingDomainImpl; import org.eclipse.emf.workspace.IWorkspaceCommandStack; import org.eclipse.emf.workspace.WorkspaceEditingDomainFactory; import org.eclipse.graphiti.mm.pictograms.Diagram; import org.eclipse.graphiti.ui.internal.editor.GFWorkspaceCommandStackImpl; import org.eclipse.graphiti.ui.internal.services.IEmfService; import org.eclipse.graphiti.ui.internal.util.ModelElementNameComparator; import org.eclipse.jface.viewers.IStructuredSelection; /** * @noinstantiate This class is not intended to be instantiated by clients. * @noextend This class is not intended to be subclassed by clients. */ public class EmfService implements IEmfService { private final String LINE_SEP = System.getProperty("line.separator"); //$NON-NLS-1$ private final String ATTRIBUTE_OBJ_NAME = "name";//$NON-NLS-1$ private final String ATTRIBUTE_OBJ_ID = "id";//$NON-NLS-1$ public String getObjectName(final Object obj) { if (obj == null) { throw new IllegalArgumentException("Obj must not be null"); //$NON-NLS-1$ } if (obj instanceof ENamedElement) { final ENamedElement elem = (ENamedElement) obj; final String name = elem.getName(); if (name != null) { return name; } } if (obj instanceof EObject) { final EObject refObject = (EObject) obj; final Entry<EAttribute, String> attr = getObjectNameAttribute(refObject); if (attr != null) { final String value = attr.getValue(); if (value != null) { return value; } } } return obj.toString(); } public EObject getEObject(Object object) { EObject eObject = null; if (object != null && object instanceof EObject) { eObject = (EObject) object; return eObject; } // unwrap a structured selection if (object instanceof IStructuredSelection) { if (((IStructuredSelection) object).isEmpty()) { return null; } final Object element = ((IStructuredSelection) object).getFirstElement(); return getEObject(element); } return null; } /** * Returns the EMF attribute that contains a human readable name of a given * object as its value. The method tries to access a modeled attribute * "name" or "id" in this order. If no attribute with this name is modeled, * the first attribute whose value is a String is returned, otherwise * <code>null</code> . * * @param eObject * the object to get a name for * @return the attribute (currently "name", id") and the readable name * * @see #getObjectName(Object) */ private Entry<EAttribute, String> getObjectNameAttribute(final EObject eObject) { final EClass metaObject = eObject.eClass(); final EList<EAttribute> attrs = metaObject.getEAllAttributes(); if (attrs != null) { for (final EAttribute attr : attrs) { final Object value = eObject.eGet(attr); // "name" if (ATTRIBUTE_OBJ_NAME.equalsIgnoreCase(attr.getName())) { if (value != null) { final String v = String.valueOf(value); return Collections.singletonMap(attr, v).entrySet().iterator().next(); } } // "id" if (ATTRIBUTE_OBJ_ID.equalsIgnoreCase(attr.getName())) { if (value != null) { final String v = String.valueOf(value); return Collections.singletonMap(attr, v).entrySet().iterator().next(); } } // string value if (value instanceof String) { return Collections.singletonMap(attr, (String) value).entrySet().iterator().next(); } } } return null; } public IFile getFile(EObject object) { IFile result = null; final Resource resource = object.eResource(); if (resource != null) { final ResourceSet resourceSet = resource.getResourceSet(); if (resourceSet != null) { result = getFile(resource.getURI()); } } return result; } @Deprecated public IFile getFile(URI uri, TransactionalEditingDomain editingDomain) { return getFile(uri); } @Deprecated public IFile getFile(URI uri, ResourceSet resourceSet) { return getFile(uri); } public IFile getFile(URI uri) { if (uri == null) { return null; } final IWorkspaceRoot workspaceRoot = ResourcesPlugin.getWorkspace().getRoot(); // File URIs final String filePath = getWorkspaceFilePath(uri.trimFragment()); if (filePath == null) { final IPath location = Path.fromOSString(uri.toString()); final IFile file = workspaceRoot.getFileForLocation(location); if (file != null) { return file; } return null; } // Platform resource URIs else { final IResource workspaceResource = workspaceRoot.findMember(filePath); return (IFile) workspaceResource; } } private String getWorkspaceFilePath(URI uri) { if (uri.isPlatform()) { return uri.toPlatformString(true); } return null; } public StringBuilder toString(final EObject o, final StringBuilder result) { final EClass metaObject = o.eClass(); // type result.append(metaObject.getName()); result.append(" \""); //$NON-NLS-1$ // human-readable name result.append(getObjectName(o)); result.append("\": "); //$NON-NLS-1$ // URI result.append(EcoreUtil.getURI(o)); result.append(LINE_SEP); // all attributes with values (sorted by name) if (o instanceof EObject) { final Map<EAttribute, Object> atts = new TreeMap<EAttribute, Object>(ModelElementNameComparator.INSTANCE_IGNORING_CASE); atts.putAll(getAttributesWithValues(o, true)); final Set<Entry<EAttribute, Object>> attsWithValues = atts.entrySet(); for (final Entry<EAttribute, Object> attr : attsWithValues) { result.append(" "); //$NON-NLS-1$ result.append(attr.getKey().getName()); result.append("="); //$NON-NLS-1$ result.append(String.valueOf(attr.getValue())); result.append(LINE_SEP); } } // class name of Jmi interface result.append(" class="); //$NON-NLS-1$ result.append(o.eClass().getInstanceClassName()); return result; } private Map<EAttribute, Object> getAttributesWithValues(EObject refObject, boolean b) { final EClass metaObject = refObject.eClass(); final EList<EAttribute> attrs = metaObject.getEAllAttributes(); final HashMap<EAttribute, Object> result = new HashMap<EAttribute, Object>(attrs.size()); for (final EAttribute attr : attrs) { final Object value = refObject.eGet(attr); result.put(attr, value); } return result; } public Diagram getDiagramFromFile(IFile file, ResourceSet resourceSet) { // Get the URI of the model file. URI resourceURI = getFileURI(file); // Demand load the resource for this file. Resource resource; try { resource = resourceSet.getResource(resourceURI, true); if (resource != null) { // does resource contain a diagram as root object? URI diagramUri = mapDiagramFileUriToDiagramUri(resourceURI); EObject eObject = resource.getEObject(diagramUri.fragment()); if (eObject instanceof Diagram) return (Diagram) eObject; } } catch (WrappedException e) { } return null; } public URI getFileURI(IFile file) { String pathName = file.getFullPath().toString(); URI resourceURI = URI.createPlatformResourceURI(pathName, true); ResourceSet resourceSet = new ResourceSetImpl(); resourceURI = resourceSet.getURIConverter().normalize(resourceURI); return resourceURI; } public URI mapDiagramFileUriToDiagramUri(URI diagramFileUri) { return diagramFileUri.appendFragment("/0"); //$NON-NLS-1$ } public TransactionalEditingDomain createResourceSetAndEditingDomain() { final ResourceSet resourceSet = new ResourceSetImpl(); final IWorkspaceCommandStack workspaceCommandStack = new GFWorkspaceCommandStackImpl(new DefaultOperationHistory()); final TransactionalEditingDomainImpl editingDomain = new TransactionalEditingDomainImpl(new ComposedAdapterFactory( ComposedAdapterFactory.Descriptor.Registry.INSTANCE), workspaceCommandStack, resourceSet); WorkspaceEditingDomainFactory.INSTANCE.mapResourceSet(editingDomain); return editingDomain; } }