/** * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. */ package org.apache.tuscany.sdo.helper; import java.util.Iterator; import java.util.Map; import org.eclipse.emf.ecore.EAttribute; import org.eclipse.emf.ecore.EClass; import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.ecore.util.FeatureMap; import org.eclipse.emf.ecore.util.FeatureMapUtil; import org.eclipse.emf.ecore.util.InternalEList; import org.eclipse.emf.ecore.util.EcoreUtil.Copier; import commonj.sdo.DataObject; import commonj.sdo.Type; import commonj.sdo.helper.CopyHelper; import commonj.sdo.helper.TypeHelper; /** * A CopyHelper implementation that creates the copy objects in a specific metadata scope. * The target scope must contain a compatible version of the Types needed to create the copy objects. */ public class CrossScopeCopyHelperImpl implements CopyHelper { protected TypeHelper scope; public CrossScopeCopyHelperImpl(TypeHelper targetScope) { scope = targetScope; } public DataObject copyShallow(DataObject dataObject) { Copier copier = new CrossScopeCopier() { protected void copyContainment(EReference eReference, EObject eObject, EObject copyEObject) { } protected void copyAttribute(EAttribute eAttribute, EObject eObject, EObject copyEObject) { if (eObject.eIsSet(eAttribute) && !FeatureMapUtil.isFeatureMap(eAttribute)) { super.copyAttribute(eAttribute,eObject,copyEObject); } } }; EObject result = copier.copy((EObject)dataObject); copier.copyReferences(); return (DataObject)result; } public DataObject copy(DataObject dataObject) { Copier copier = new CrossScopeCopier(); DataObject result = (DataObject)copier.copy((EObject)dataObject); copier.copyReferences(); return (DataObject)result; } protected class CrossScopeCopier extends EcoreUtil.Copier { protected boolean useOriginalReferences = false; protected EClass getTarget(EClass eClass) { EClass target = (EClass)get(eClass); if (target == null) { Type type = (Type)eClass; target = (EClass)scope.getType(type.getURI(), type.getName()); } return target; } protected EStructuralFeature getTarget(EStructuralFeature eStructuralFeature) { EClass eClass = getTarget(eStructuralFeature.getEContainingClass()); EStructuralFeature targetEf = eClass.getEStructuralFeature(eStructuralFeature.getName()); return targetEf; } /** * This Method WILL BE REMOVED when EMF 3.0 is available */ public void copyReferences() { for (Iterator i = entrySet().iterator(); i.hasNext();) { Map.Entry entry = (Map.Entry)i.next(); EObject eObject = (EObject)entry.getKey(); EObject copyEObject = (EObject)entry.getValue(); EClass eClass = eObject.eClass(); for (int j = 0, size = eClass.getFeatureCount(); j < size; ++j) { EStructuralFeature eStructuralFeature = eClass.getEStructuralFeature(j); if (eStructuralFeature.isChangeable() && !eStructuralFeature.isDerived()) { if (eStructuralFeature instanceof EReference) { EReference eReference = (EReference)eStructuralFeature; if (!eReference.isContainment() && !eReference.isContainer()) { copyReference(eReference, eObject, copyEObject); } } else if (FeatureMapUtil.isFeatureMap(eStructuralFeature)) { FeatureMap featureMap = (FeatureMap)eObject.eGet(eStructuralFeature); FeatureMap copyFeatureMap = (FeatureMap)copyEObject.eGet(getTarget(eStructuralFeature)); int copyFeatureMapSize = copyFeatureMap.size(); for (int k = 0, featureMapSize = featureMap.size(); k < featureMapSize; ++k) { EStructuralFeature feature = featureMap.getEStructuralFeature(k); if (feature instanceof EReference) { Object referencedEObject = featureMap.getValue(k); Object copyReferencedEObject = get(referencedEObject); if (copyReferencedEObject == null && referencedEObject != null) { EReference reference = (EReference)feature; if (!useOriginalReferences || reference.isContainment() || reference.getEOpposite() != null) { continue; } copyReferencedEObject = referencedEObject; } // If we can't add it, it must aleady be in the list so find it and move it to the end. // if (!copyFeatureMap.add(feature, copyReferencedEObject)) { for (int l = 0; l < copyFeatureMapSize; ++l) { if (copyFeatureMap.getEStructuralFeature(l) == feature && copyFeatureMap.getValue(l) == copyReferencedEObject) { copyFeatureMap.move(copyFeatureMap.size() - 1, l); --copyFeatureMapSize; break; } } } } else { copyFeatureMap.add(featureMap.get(k)); } } } } } } } /** * This Method WILL BE REMOVED when EMF 3.0 is available */ protected void copyReference(EReference eReference, EObject eObject, EObject copyEObject) { if (eObject.eIsSet(eReference)) { if (eReference.isMany()) { InternalEList source = (InternalEList)eObject.eGet(eReference); InternalEList target = (InternalEList)copyEObject.eGet(getTarget(eReference)); if (source.isEmpty()) { target.clear(); } else { boolean isBidirectional = eReference.getEOpposite() != null; int index = 0; for (Iterator k = resolveProxies ? source.iterator() : source.basicIterator(); k.hasNext();) { Object referencedEObject = k.next(); Object copyReferencedEObject = get(referencedEObject); if (copyReferencedEObject == null) { if (useOriginalReferences && !isBidirectional) { target.addUnique(index, referencedEObject); ++index; } } else { if (isBidirectional) { int position = target.indexOf(copyReferencedEObject); if (position == -1) { target.addUnique(index, copyReferencedEObject); } else if (index != position) { target.move(index, copyReferencedEObject); } } else { target.addUnique(index, copyReferencedEObject); } ++index; } } } } else { Object referencedEObject = eObject.eGet(eReference, resolveProxies); if (referencedEObject == null) { copyEObject.eSet(getTarget(eReference), null); } else { Object copyReferencedEObject = get(referencedEObject); if (copyReferencedEObject == null) { if (useOriginalReferences && eReference.getEOpposite() == null) { copyEObject.eSet(getTarget(eReference), referencedEObject); } } else { copyEObject.eSet(getTarget(eReference), copyReferencedEObject); } } } } } } }