blob: 23c75603a86b9db0270cd6bc1154eda343478056 [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2004, 2008 IBM Corporation and others.
* 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:
* IBM Corporation - initial API and implementation
****************************************************************************/
package org.eclipse.gmf.runtime.emf.core.clipboard;
import java.io.IOException;
import java.io.InputStream;
import java.util.Iterator;
import java.util.Map;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.InternalEList;
import org.eclipse.emf.ecore.xmi.XMLHelper;
import org.eclipse.emf.ecore.xmi.XMLLoad;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xmi.XMLSave;
import org.eclipse.emf.ecore.xmi.impl.XMIHelperImpl;
import org.eclipse.emf.ecore.xmi.impl.XMIResourceImpl;
import org.eclipse.emf.ecore.xmi.impl.XMISaveImpl;
import org.eclipse.gmf.runtime.common.core.util.Trace;
import org.eclipse.gmf.runtime.emf.core.internal.plugin.EMFCoreDebugOptions;
import org.eclipse.gmf.runtime.emf.core.internal.plugin.EMFCorePlugin;
import org.eclipse.gmf.runtime.emf.core.internal.util.EMFCoreConstants;
/**
* @author Yasser Lulu
*/
public class CopyingResource
extends XMIResourceImpl {
private XMLResource xmlResource;
private CopyingResourceSet copyingResourceSet;
public CopyingResource(XMLResource resource, URI uri,
CopyingResourceSet copyingResourceSet) {
this(resource, uri, copyingResourceSet, true);
}
public CopyingResource(XMLResource resource, URI uri,
CopyingResourceSet copyingResourceSet, boolean regenerateIds) {
super(uri);
this.xmlResource = resource;
this.copyingResourceSet = copyingResourceSet;
setEncoding(resource.getEncoding());
//needed to allow calls to unload() to proceed
setLoaded(true);
getDefaultSaveOptions().putAll(resource.getDefaultSaveOptions());
copyingResourceSet.getResources().add(this);
copyingResourceSet.getResourcesMap().put(resource, this);
if (regenerateIds) {
createNewIDs();
} else {
copyIDs();
}
}
/**
*
*/
private void createNewIDs() {
// OK to get all contents because we have to copy
// the entire model content of this resource
Iterator it = getXMLResource().getAllContents();
while (it.hasNext()) {
setID((EObject) it.next(), EcoreUtil.generateUUID());
}
}
protected XMLLoad createXMLLoad() {
throwUnsupportedOperationException("createXMLLoad", //$NON-NLS-1$
new UnsupportedOperationException(
"Can't call load on CopyingResource resource"));//$NON-NLS-1$
return null;
}
protected XMLHelper createXMLHelper() {
return new CopyingHelper(this);
}
protected void unloaded(InternalEObject internalEObject) {
//disable parent
}
/**
* @see org.eclipse.emf.common.notify.impl.NotifierImpl#eNotificationRequired()
*/
public boolean eNotificationRequired() {
return false;
}
private void throwUnsupportedOperationException(String methodName,
UnsupportedOperationException ex) {
Trace.throwing(EMFCorePlugin.getDefault(),
EMFCoreDebugOptions.EXCEPTIONS_THROWING, getClass(), methodName, ex);
throw ex;
}
/**
* @return Returns the resourcesMap.
*/
private Map getResourcesMap() {
return getMslCopyingResourceSet().getResourcesMap();
}
public void doLoad(InputStream inputStream, Map options)
throws IOException {
throwUnsupportedOperationException("doLoad", //$NON-NLS-1$
new UnsupportedOperationException(
"Can't call load on CopyingResource resource"));//$NON-NLS-1$
}
protected XMLSave createXMLSave() {
return new CopyingSave(createXMLHelper());
}
private boolean isInResource(EObject eObject) {
// in case of cross-resource containment, the 'eObject' may be in a
// different resource than xmlResource, though one of its containers
// may be
while (eObject != null) {
if (((InternalEObject) eObject).eDirectResource() == getXMLResource()) {
return true;
}
eObject = eObject.eContainer();
}
return false;
}
public EList getContents() {
return getXMLResource().getContents();
}
/**
* @see org.eclipse.emf.ecore.resource.impl.ResourceImpl#doUnload()
*/
protected void doUnload() {
//disable parent's
}
public EObject getEObject(String uriFragment) {
int index = uriFragment.indexOf('?');
if (-1 != index) {
uriFragment = uriFragment.substring(0, index);
}
return super.getEObject(uriFragment);
}
/**
* Returns the object based on the fragment as an ID.
*/
protected EObject getEObjectByID(String id) {
EObject eObj = getXMLResource().getEObject(id);
if (eObj == null) {
return super.getEObjectByID(id);
}
return eObj;
}
/**
* @return Returns the CopyingResourceSet.
*/
public CopyingResourceSet getMslCopyingResourceSet() {
return copyingResourceSet;
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.resource.impl.ResourceImpl#getResourceSet()
*/
public ResourceSet getResourceSet() {
return getMslCopyingResourceSet();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.resource.Resource.Internal#attached(org.eclipse.emf.ecore.EObject)
*/
public void attached(EObject eObject) {
//disable
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.resource.Resource.Internal#detached(org.eclipse.emf.ecore.EObject)
*/
public void detached(EObject eObject) {
//disable
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.xmi.XMLResource#getEObjectToExtensionMap()
*/
public Map getEObjectToExtensionMap() {
return getXMLResource().getEObjectToExtensionMap();
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.resource.Resource#isTrackingModification()
*/
public boolean isTrackingModification() {
return false;
}
private void copyIDs() {
// OK to get all contents because we have to copy
// the entire model content of this resource
XMLResource lastRes = null;
for (Iterator iter = getXMLResource().getAllContents(); iter.hasNext(); ) {
InternalEObject eObject = (InternalEObject)iter.next();
if (eObject.eDirectResource() != null) {
// ensure that we only ask the resource that actually contains
// an object for that object's ID
lastRes = (XMLResource) eObject.eDirectResource();
}
getEObjectToIDMap().put(eObject, lastRes.getID(eObject));
getIDToEObjectMap().put(lastRes.getID(eObject), eObject);
}
}
/**
* Gets the XML resource that contains the model content to be copied.
*
* @return the XML resource
*/
protected XMLResource getXMLResource() {
return xmlResource;
}
/**
* Helper implementation for the CopyingResource.
*/
protected class CopyingHelper extends XMIHelperImpl {
public CopyingHelper() {
super();
}
public CopyingHelper(XMLResource resource) {
super(resource);
}
/**
* @see org.eclipse.emf.ecore.xmi.XMLHelper#deresolve(org.eclipse.emf.common.util.URI)
*/
public URI deresolve(URI anUri) {
// if this both target and container are within a platform resource and
// projects
// or plugins are different then do not deresolve.
if (((EMFCoreConstants.PLATFORM_SCHEME.equals(anUri.scheme())) && (EMFCoreConstants.PLATFORM_SCHEME
.equals(resourceURI.scheme())))
&& ((anUri.segmentCount() > 2) && (resourceURI.segmentCount() > 2))
&& ((!anUri.segments()[0].equals(resourceURI.segments()[0])) || (!anUri
.segments()[1].equals(resourceURI.segments()[1]))))
return anUri;
return super.deresolve(anUri);
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.xmi.impl.XMLHelperImpl#getHREF(org.eclipse.emf.ecore.EObject)
*/
public String getHREF(EObject obj) {
EObject eObj = obj;
if (obj.eIsProxy()) {
eObj = EcoreUtil.resolve(obj, getXMLResource());
if (eObj == obj) {
// use super.getHREF() if we can't resolve the proxy
eObj = null;
}
}
if (eObj != null) {
Resource resource = eObj.eResource();
if (resource != null) {
URI objectURI = getHREF(resource, eObj);
objectURI = deresolve(objectURI);
return objectURI.toString();
}
}
return super.getHREF(obj);
}
protected URI getHREF(Resource otherResource, EObject obj) {
if (!(otherResource instanceof CopyingResource)) {
CopyingResource copyingResource = (CopyingResource) getResourcesMap()
.get(otherResource);
if (copyingResource != null) {
otherResource = copyingResource;
}
}
return super.getHREF(otherResource, obj);
}
};
/**
* Save implementation for the CopyingResource.
*/
public class CopyingSave extends XMISaveImpl {
public CopyingSave(XMLHelper helper) {
super(helper);
}
public CopyingSave(Map options, XMLHelper helper, String encoding) {
super(options, helper, encoding);
}
public CopyingSave(Map options, XMLHelper helper, String encoding,
String xmlVersion) {
super(options, helper, encoding, xmlVersion);
}
/**
* @see org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl#sameDocMany(org.eclipse.emf.ecore.EObject,
* org.eclipse.emf.ecore.EStructuralFeature)
*/
protected int sameDocMany(EObject o, EStructuralFeature f) {
InternalEList values = (InternalEList) helper.getValue(o, f);
if (values.isEmpty()) {
return SKIP;
}
for (Iterator i = values.basicIterator(); i.hasNext();) {
EObject value = (EObject) i.next();
if (value.eIsProxy() || (isInResource(value) == false)) {
return CROSS_DOC;
}
}
return SAME_DOC;
}
/**
* @see org.eclipse.emf.ecore.xmi.impl.XMLSaveImpl#sameDocSingle(org.eclipse.emf.ecore.EObject,
* org.eclipse.emf.ecore.EStructuralFeature)
*/
protected int sameDocSingle(EObject o, EStructuralFeature f) {
EObject value = (EObject) helper.getValue(o, f);
if (value == null) {
return SKIP;
} else if (value.eIsProxy()) {
return CROSS_DOC;
} else {
return (isInResource(value)) ? SAME_DOC
: CROSS_DOC;
}
}
};
}