blob: d148c0b79105529f6b333fbcb4fdef999720f60e [file] [log] [blame]
/**
* <copyright>
*
* Copyright (c) 2008-2015 See4sys, itemis and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v2.0
* which accompanies this distribution, and is available at
* https://www.eclipse.org/org/documents/epl-2.0/EPL-2.0.html
*
* Contributors:
* See4sys - Initial API and implementation
* itemis - [477076] Access to the "ordered" attributes in metamodels that are optimized for deterministic code generation using QVTO or OCL
*
* </copyright>
*/
package org.eclipse.sphinx.emf.resource;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import java.util.Map;
import org.eclipse.core.runtime.Assert;
import org.eclipse.emf.ecore.EAnnotation;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EModelElement;
import org.eclipse.emf.ecore.EPackage.Registry;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.sphinx.emf.metamodel.IMetaModelDescriptor;
import org.eclipse.sphinx.emf.metamodel.MetaModelDescriptorRegistry;
/**
* Enables {@link XMLResource XML resource}s which have been created with older but still compatible versions of a
* metamodel to be loaded with the most recent version of that metamodel. Relies on the {@link IMetaModelDescriptor
* descriptor} of the metamodel in question to find out with XML resources can be deemed compatible and which not.
*/
public class BasicMigrationExtendedMetaData extends ExtendedBasicExtendedMetaData {
public BasicMigrationExtendedMetaData() {
super();
}
public BasicMigrationExtendedMetaData(Registry registry) {
super(registry);
}
public BasicMigrationExtendedMetaData(String annotationURI, Registry registry, Map<EModelElement, EAnnotation> annotationMap) {
super(annotationURI, registry, annotationMap);
}
public BasicMigrationExtendedMetaData(String annotationURI, Registry registry) {
super(annotationURI, registry);
}
/**
* Does the same as the super implementation but maps given XML element to corresponding {@link EStructuralFeature
* feature} of given {@link EClass} if underlying namespaces are compatible instead of doing so only when they are
* equal.
*
* @see org.eclipse.emf.ecore.util.BasicExtendedMetaData#getLocalElement(org.eclipse.emf.ecore.EClass,
* java.lang.String, java.lang.String)
*/
@Override
protected EStructuralFeature getLocalElement(EClass eClass, String namespace, String name) {
EStructuralFeature result = null;
if (isFeatureKindSpecific()) {
List<EStructuralFeature> allElements = getAllElements(eClass);
for (int i = 0, size = allElements.size(); i < size; ++i) {
EStructuralFeature eStructuralFeature = allElements.get(i);
if (name.equals(getName(eStructuralFeature))) {
String featureNamespace = getNamespace(eStructuralFeature);
if (namespace == null) {
if (featureNamespace == null) {
return eStructuralFeature;
} else if (result == null) {
result = eStructuralFeature;
}
} else if (isSameOrCompatibleNamespace(namespace, featureNamespace)) {
return eStructuralFeature;
} else if (featureNamespace == null && result == null) {
result = eStructuralFeature;
}
}
}
} else {
for (int i = 0, size = eClass.getFeatureCount(); i < size; ++i) {
EStructuralFeature eStructuralFeature = eClass.getEStructuralFeature(i);
switch (getFeatureKind(eStructuralFeature)) {
case UNSPECIFIED_FEATURE:
case ELEMENT_FEATURE: {
if (name.equals(getName(eStructuralFeature))) {
String featureNamespace = getNamespace(eStructuralFeature);
if (namespace == null) {
if (featureNamespace == null) {
return eStructuralFeature;
} else if (result == null) {
result = eStructuralFeature;
}
} else if (namespace.equals(featureNamespace)) {
return eStructuralFeature;
} else if (featureNamespace == null && result == null) {
result = eStructuralFeature;
}
}
break;
}
}
}
}
return isFeatureNamespaceMatchingLax() ? result : null;
}
/**
* Tests if given XML namespace is equal to or compatible with the given {@link EStructuralFeature feature}
* namespace.
*
* @param xmlNamespace
* The XML element namespace to be investigated.
* @param featureNamespace
* The {@link EStructuralFeature feature} namespace to be used as reference.
* @return <code>true</code> if given XML namespace and {@link EStructuralFeature feature} namespace are equal or
* compatible, or <code>false</code> otherwise.
*/
protected boolean isSameOrCompatibleNamespace(String xmlNamespace, String featureNamespace) {
Assert.isNotNull(xmlNamespace);
try {
URI xmlNamespaceURI = new URI(xmlNamespace);
IMetaModelDescriptor xmlMMDescriptor = MetaModelDescriptorRegistry.INSTANCE.getDescriptor(xmlNamespaceURI);
if (xmlMMDescriptor != null) {
return xmlMMDescriptor.getNamespace().equals(featureNamespace);
}
} catch (URISyntaxException ex) {
// Ignore exception
}
// Fall back to behavior provided by super implementation
return xmlNamespace.equals(featureNamespace);
}
}