blob: a1f61fa8abab7d3160f2a5d0904222360ca118c1 [file] [log] [blame]
/*******************************************************************************
* <copyright>
*
* Copyright (c) 2005, 2016 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
* mwenz - Bug 489681 - EmfService.getFile fails with some URIs
*
* </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;
}
public IFile getFile(URI uri) {
if (uri == null) {
return null;
}
String filePath = getWorkspaceFilePath(uri.trimFragment());
if (filePath != null) {
// Platform resource URIs
IResource workspaceResource = getWorkspaceRoot().findMember(filePath);
if (workspaceResource instanceof IFile) {
return (IFile) workspaceResource;
}
} else {
// File URIs
IFile file = getFileForUriString(uri.toFileString());
if (file != null) {
return file;
}
file = getFileForUriString(uri.toString());
if (file != null) {
return file;
}
}
return null;
}
protected IFile getFileForUriString(String uriString) {
if (uriString != null) {
IPath location = Path.fromOSString(uriString);
if (location != null) {
IFile file = getWorkspaceRoot().getFileForLocation(location);
if (file != null) {
return file;
}
}
}
return null;
}
private IWorkspaceRoot getWorkspaceRoot() {
return ResourcesPlugin.getWorkspace().getRoot();
}
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;
}
}