blob: de85cb3a5e02e5844c6e0ef0aa2ec078b0229d34 [file] [log] [blame]
//------------------------------------------------------------------------------
// Copyright (c) 2005, 2006 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 implementation
//------------------------------------------------------------------------------
package org.eclipse.epf.persistence;
import java.util.Iterator;
import java.util.List;
import org.eclipse.emf.common.CommonPlugin;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.common.util.UniqueEList;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EReference;
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.InternalEList;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xmi.impl.XMIHelperImpl;
import org.eclipse.epf.resourcemanager.ResourceDescriptor;
import org.eclipse.epf.uma.MethodConfiguration;
import org.eclipse.epf.uma.ecore.impl.MultiResourceEObject;
/**
* XMLHelper implementation for library XMI persistence
*
* @author Phong Nguyen Le
* @since 1.0
*/
public class MultiFileXMIHelperImpl extends XMIHelperImpl {
/**
* Platform-specific line separator.
*/
private static final String LINE_SEP = System.getProperty("line.separator"); //$NON-NLS-1$
protected boolean logError = true;
protected List sameDocReferences;
private boolean discardUnresolvedRef;
/**
* Creates a new instance.
*/
public MultiFileXMIHelperImpl(MultiFileXMIResourceImpl xmiRes) {
super(xmiRes);
sameDocReferences = new UniqueEList();
Boolean b = (Boolean) ((MultiFileResourceSetImpl) xmiRes
.getResourceSet()).getDefaultSaveOptions().get(
MultiFileXMISaveImpl.DISCARD_UNRESOLVED_REFERENCES);
discardUnresolvedRef = b != null ? b.booleanValue() : false;
}
/* (non-Javadoc)
* @see org.eclipse.emf.ecore.xmi.impl.XMLHelperImpl#setResource(org.eclipse.emf.ecore.xmi.XMLResource)
*/
public void setResource(XMLResource resource) {
super.setResource(resource);
if(resource instanceof MultiFileXMIResourceImpl) {
resourceURI = ((MultiFileXMIResourceImpl)resource).getFinalURI();
deresolve = resourceURI != null && !resourceURI.isRelative() && resourceURI.isHierarchical();
}
}
/*
* (non-Javadoc)
*
* @see org.eclipse.emf.ecore.xmi.impl.XMLHelperImpl#getHREF(org.eclipse.emf.ecore.EObject)
*/
public String getHREF(EObject obj) {
if (discardUnresolvedRef) {
// remove unresolved references
//
if (obj instanceof MultiResourceEObject
&& !((MultiResourceEObject) obj).isValid()) {
return null;
}
}
if (obj instanceof MultiResourceEObject) {
InternalEObject o = (InternalEObject) obj;
URI objectURI = o.eProxyURI();
if (objectURI == null) {
Resource otherResource = obj.eResource();
if (otherResource == null) {
objectURI = handleDanglingHREF(obj);
if (objectURI == null) {
return null;
}
} else if (resource == otherResource) {
return "#" + resource.getURIFragment(obj); //$NON-NLS-1$
} else {
if (obj instanceof MethodConfiguration) {
// Special handling for MethodConfiguration.
// See
// org.eclipse.epf.persistence.MultiFileResourceSetImpl.loadConfigurations()
//
EObject lib = obj.eContainer();
if (lib != null) {
otherResource = lib.eResource();
} else {
return null;
}
}
if (otherResource != null) {
ResourceSet resourceSet = otherResource.getResourceSet();
if(resourceSet instanceof MultiFileResourceSetImpl
&& ((MultiFileResourceSetImpl)resourceSet).getResourceManager() == null) {
objectURI = MultiFileSaveUtil.getFinalURI(otherResource).appendFragment(getURIFragment(otherResource, obj));
return deresolve(objectURI).toString();
}
ResourceDescriptor resDesc = MultiFileSaveUtil
.getResourceDescriptor(otherResource);
if (resDesc != null) {
objectURI = MultiFileURIConverter.createURI(
resDesc.getId()).appendFragment(
getURIFragment(otherResource, obj));
return objectURI.toString();
} else {
return null;
}
}
}
} else {
if (!objectURI.scheme().equals(MultiFileURIConverter.SCHEME)) {
String fragment = objectURI.fragment();
if (resource instanceof MultiFileXMIResourceImpl
&& ((MultiFileXMIResourceImpl) resource)
.getEObjectByID(fragment) != null) {
return "#" + fragment; //$NON-NLS-1$
} else {
objectURI = deresolve(objectURI);
}
}
return objectURI.toString();
}
}
return super.getHREF(obj);
}
protected static class ProxyReference {
private InternalEObject owner;
private EReference reference;
private InternalEObject proxy;
/**
* @param owner
* @param reference
* @param proxy
*/
public ProxyReference(InternalEObject owner, EReference reference,
InternalEObject proxy) {
super();
this.owner = owner;
this.reference = reference;
this.proxy = proxy;
}
public InternalEObject getOwner() {
return owner;
}
public InternalEObject getProxy() {
return proxy;
}
public EReference getReference() {
return reference;
}
}
public void setValue(EObject object, EStructuralFeature feature,
Object value, int position) {
// TODO: more efficient way to do this replacement
// should look at MultiFileXMISaveImpl.MyEscape.convertText()
//
if (value instanceof String) {
String str = (String) value;
if (str.indexOf("\n") > 0) { //$NON-NLS-1$
value = str.replaceAll("\n", LINE_SEP); //$NON-NLS-1$
}
}
;
int kind = getFeatureKind(feature);
try {
// TODO: temporary fix to avoid ArrayIndexOutOfBoundsException,
// needs revisit
//
if (kind == IS_MANY_MOVE) {
List list = (List) object.eGet(feature);
if (position > -1 && list.indexOf(value) == -1) {
return;
}
}
super.setValue(object, feature, value, position);
switch (kind) {
case IS_MANY_ADD:
case IS_MANY_MOVE:
InternalEList list = (InternalEList) object.eGet(feature);
// save same document forward (unidirectional) references to
// resolve at the end of document parsing
//
if (feature instanceof EReference) {
EReference ref = (EReference) feature;
if (ref.getEOpposite() != null) {
InternalEObject owner = (InternalEObject) object;
for (Iterator iter = list.basicIterator(); iter
.hasNext();) {
InternalEObject element = (InternalEObject) iter
.next();
if (element.eIsProxy()
&& element.eProxyURI().trimFragment()
.equals(resourceURI)) {
sameDocReferences.add(new ProxyReference(owner,
ref, element));
}
}
}
}
break;
}
} catch (RuntimeException e) {
if (logError) {
if(MultiFileSaveUtil.DEBUG) {
e.printStackTrace();
}
CommonPlugin.INSTANCE.log(e);
String errMsg = new StringBuffer(
"MultiFileXMIHelperImpl.setValue(): ERROR") //$NON-NLS-1$
.append("\n object: ").append(object) //$NON-NLS-1$
.append("\n feature: ").append(feature) //$NON-NLS-1$
.append("\n value: ").append(value) //$NON-NLS-1$
.append("\n position: ").append(position) //$NON-NLS-1$
.append("\n kind: ").append(kind) //$NON-NLS-1$
.toString();
if(MultiFileSaveUtil.DEBUG) {
System.err.println(errMsg);
}
CommonPlugin.INSTANCE.log(errMsg);
}
throw e;
}
}
/* (non-Javadoc)
* @see org.eclipse.emf.ecore.xmi.impl.XMLHelperImpl#getValue(org.eclipse.emf.ecore.EObject, org.eclipse.emf.ecore.EStructuralFeature)
*/
public Object getValue(EObject obj, EStructuralFeature f) {
Object value = super.getValue(obj, f);
// remove any value that does not belong to any resource
//
if(f instanceof EReference) {
if(f.isMany()) {
if(f.isChangeable() && value instanceof InternalEList) {
InternalEList list = (InternalEList) value;
for (Iterator iter = list.iterator(); iter.hasNext();) {
EObject o = (EObject) iter.next();
if(!o.eIsProxy() && o.eResource() == null) {
iter.remove();
}
}
}
}
else {
EObject o = (EObject) value;
if(!o.eIsProxy() && o.eResource() == null) {
value = null;
}
}
}
return value;
}
}