blob: 9e81f6d8df272e099fe1771a6dd17bb43e31668b [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2011 Tasktop Technologies.
* 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:
* Tasktop Technologies - initial API and implementation
*******************************************************************************/
package org.eclipse.mylyn.mft.emf.core;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.Path;
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.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EcorePackage;
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.mylyn.context.core.AbstractContextStructureBridge;
import org.eclipse.mylyn.context.core.ContextCore;
/**
* @author Miles Parker
* @author Benjamin Muskalla
*/
public abstract class EmfStructureBridge extends DomainModelContextStructureBridge {
/**
* Returns a unique path to the object within an actual resource. EMF-based implementations typically shouldn't need
* to override this.
*/
@Override
public String getDomainHandleIdentifier(Object object) {
return getGenericDomainHandleIdentifier(object, parentContentType);
}
/**
* Made static so we can reuse generic functionality.
*
* @param object
* @param parentContentType
* @return
*/
public static String getGenericDomainHandleIdentifier(Object object, String parentContentType) {
if (object instanceof EObject) {
EObject eobject = ((EObject) object);
URI uri = EcoreUtil.getURI(eobject);
// if (eobject instanceof EPackage) {
// EPackage pack = (EPackage) eobject;
// if (pack.eResource() != null) {
// IFile file = getFile(pack.eResource());
// if (file != null && file.exists()) {
// AbstractContextStructureBridge parentBridge = ContextCore.getStructureBridge(parentContentType);
// return parentBridge.getHandleIdentifier(file);
// }
//
// }
// }
return uri.toString();
}
return null;
}
@Override
public String getHandleIdentifier(Object object) {
if (object instanceof Resource) {
Resource resource = (Resource) object;
URI uri = resource.getResourceSet().getURIConverter().normalize(resource.getURI());
return uri.toString();
}
return super.getHandleIdentifier(object);
}
/**
* If it's a domain object, we accept it. Implementors generally should not override.
*/
@Override
public boolean acceptsObject(Object object) {
return getDomainObject(object) != null;
}
@Override
public Object getObjectForHandle(String handle) {
if (isDocument(handle)) {
AbstractContextStructureBridge parentBridge = ContextCore.getStructureBridge(parentContentType);
Object objectForHandle = parentBridge.getObjectForHandle(handle);
if (objectForHandle instanceof IFile) {
IFile file = (IFile) objectForHandle;
ResourceSet rs = getDomainObjectResourceSet();
URI createFileURI = URI.createPlatformResourceURI(file.getFullPath().toString(), true);
Resource createResource = rs.getResource(createFileURI, true);
return createResource;
}
return null;
}
return super.getObjectForHandle(handle);
}
/**
* Must return a class that is an equivalent (e.g. a deep copy) but not necessarily the same object as the original
* mapped object. This allows us to make generic references to objects that might not have equivalent mappings in
* memory, e.g. an EMF object that is loaded from a new resource set. EMF-based implementations typically shouldn't
* need to override this.
*
* @see #getDomainObjectResourceSet()
*/
@Override
public Object getDomainObjectForHandle(String handle) {
URI uri = URI.createURI(handle);
ResourceSet resourceSet = getDomainObjectResourceSet();
String fragment = uri.fragment();
if (fragment.equals("/")) { //$NON-NLS-1$
Resource resource = resourceSet.getResource(uri, true);
return resource;
}
try {
EObject eObject = resourceSet.getEObject(uri, true);
if (eObject != null) {
return eObject;
}
return resourceSet.getResource(uri, true);
} catch (WrappedException e) {
// this is a reasonable thing to happen in the case where the resource is no longer available.
}
return null;
}
/**
* Returns a ResourceSet that can be used to obtain domain objects from domain handles. The default implementation
* returns a new {@link ResourceSetImpl} on each call. EMF-based implementations needing specific ResourceSet
* implementations or instances can override this.
*/
protected ResourceSet getDomainObjectResourceSet() {
return new ResourceSetImpl();
}
/**
* Returns all of the "children" that a given object is responsible for. Here we just use EMF containment. This is
* similar to org.eclipse.emf.edit.provider.ITreeItemContentProvider#getChildren. You shouldn't need to override
* this unless you want to use some other references for children.
*/
@Override
public List<String> getChildHandles(String handle) {
Object domainObject = getObjectForHandle(handle);
if (domainObject instanceof EObject) {
List<String> childHandles = new ArrayList<String>();
EObject eo = (EObject) domainObject;
for (EObject child : eo.eContents()) {
childHandles.add(getDomainHandleIdentifier(child));
}
return childHandles;
}
return Collections.emptyList();
}
/**
* The inverse of {@link #getChildHandles(String)}. Again, you typically don't need to override this.
*/
@Override
public String getParentHandle(String handle) {
Object object = getObjectForHandle(handle);
if (object instanceof EObject) {
EObject eObject = (EObject) object;
if (eObject.eContainer() != null) {
return getHandleIdentifier(eObject.eContainer());
} else {
//must be base package
return getHandleIdentifier(eObject.eResource());
}
} else if (object instanceof Resource) {
Resource resource = (Resource) object;
IFile file = getFile(resource);
if (file != null && file.exists()) {
AbstractContextStructureBridge parentBridge = ContextCore.getStructureBridge(parentContentType);
return parentBridge.getHandleIdentifier(file);
}
} else if (object instanceof EPackage) {
EPackage pack = (EPackage) object;
if (pack.eContainer() == null && pack.eResource() != null) {
return getDomainHandleIdentifier(pack.eContainer());
}
} else if (object instanceof IFile) {
// String fileHandle = parentBridge.getParentHandle(handle);
AbstractContextStructureBridge parentBridge = ContextCore.getStructureBridge(parentContentType);
return parentBridge.getParentHandle(handle);
}
//Resources don't have parents, unless we want to get the file hierarchy, which probably isn't what we want.
return null;
}
public static IFile getFile(Resource resource) {
URI uri = resource.getURI();
uri = resource.getResourceSet().getURIConverter().normalize(uri);
String scheme = uri.scheme();
if ("platform".equals(scheme) && uri.segmentCount() > 1 && "resource".equals(uri.segment(0))) { //$NON-NLS-1$//$NON-NLS-2$
StringBuffer platformResourcePath = new StringBuffer();
for (int j = 1, size = uri.segmentCount(); j < size; ++j) {
platformResourcePath.append('/');
platformResourcePath.append(uri.segment(j));
}
IFile file = ResourcesPlugin.getWorkspace().getRoot().getFile(new Path(platformResourcePath.toString()));
return file;
}
return null;
}
/**
* Override to specify a feature giving a unique name for the given object.
*
* @return
*/
public EAttribute getNameFeature(Object object) {
return EcorePackage.Literals.ENAMED_ELEMENT__NAME;
}
/**
* Returns the textual representation for Mylyn editors. Uses the feature specified by getNameFeature, so shouldn't
* need to override this directly. We should consider using EMF Item Provider adapters to obtain an
* IItemLabelProvider for some EMF implementations.
*/
@Override
public String getLabel(Object object) {
if (object instanceof EObject) {
EObject eo = (EObject) object;
return (String) eo.eGet(getNameFeature(object));
}
return super.getLabel(object);
}
@Override
public String getContentType(String handle) {
Object objectForHandle = getObjectForHandle(handle);
if (objectForHandle instanceof Resource) {
return parentContentType;
}
return getContentType();
}
public String[] getFileExtensions() {
return new String[] { getContentType() };
}
@Override
public boolean isDocument(String handle) {
if (handle == null || handle.equals("")) { //$NON-NLS-1$
return false;
}
URI uri = URI.createURI(handle);
return uri.isFile() && !uri.isEmpty();
}
}