Skip to main content
summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorpelder2008-09-25 16:32:13 -0400
committerpelder2008-09-25 16:32:13 -0400
commitb1c3cc26bf87606220a2076183c4cbd0bb37e82e (patch)
tree40d7184b6d5918bc89ebc98de8d8efed3be9ef23
parent69b4723e9482c8086419f1d80dce54a0146ce64f (diff)
downloadorg.eclipse.jet-b1c3cc26bf87606220a2076183c4cbd0bb37e82e.tar.gz
org.eclipse.jet-b1c3cc26bf87606220a2076183c4cbd0bb37e82e.tar.xz
org.eclipse.jet-b1c3cc26bf87606220a2076183c4cbd0bb37e82e.zip
[248653] c:copyElement incorrectly copies entire XML documents
[247530] NPE in XPath engine
-rw-r--r--plugins/org.eclipse.jet/src/org/eclipse/jet/internal/xpath/inspectors/EObjectInspector.java260
1 files changed, 147 insertions, 113 deletions
diff --git a/plugins/org.eclipse.jet/src/org/eclipse/jet/internal/xpath/inspectors/EObjectInspector.java b/plugins/org.eclipse.jet/src/org/eclipse/jet/internal/xpath/inspectors/EObjectInspector.java
index 9de85df..214fbd7 100644
--- a/plugins/org.eclipse.jet/src/org/eclipse/jet/internal/xpath/inspectors/EObjectInspector.java
+++ b/plugins/org.eclipse.jet/src/org/eclipse/jet/internal/xpath/inspectors/EObjectInspector.java
@@ -17,7 +17,6 @@ package org.eclipse.jet.internal.xpath.inspectors;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
@@ -68,6 +67,96 @@ import org.eclipse.jet.xpath.inspector.SimpleElementRequiresValueException;
public class EObjectInspector implements IElementInspector, INodeInspectorExtension1
{
+ static final class ElementNameTester implements IXMLElementTester
+ {
+
+ private final ExpandedName expandedName;
+ private final ExtendedMetaData exMD;
+
+ public ElementNameTester(ExtendedMetaData exMD, ExpandedName expandedName)
+ {
+ this.expandedName = expandedName;
+ this.exMD = exMD;
+ }
+
+ public boolean matches(Object child)
+ {
+ if (child instanceof EObject)
+ {
+ final EObject eChild = (EObject)child;
+ final EReference containmentFeature = eChild.eContainmentFeature();
+ // Note, the final condition on class names prevents subclasses of the
+ // declared feature type from being accepted. This is necessary to handle
+ // matches against substitution group head elements, which must only return
+ // elements of the head type, not sub-types
+ if (expandedName.getLocalPart().equals(exMD.getName(containmentFeature)) &&
+ (expandedName.getNamespaceURI() == null
+ || expandedName.getNamespaceURI().equals(exMD.getNamespace(containmentFeature))) &&
+ (eChild instanceof AnyType || eChild.eClass().getName().equals(containmentFeature.getEType().getName())))
+ {
+ return true;
+ }
+ else {
+ // See whether this is a substitution element containmentFeature
+ final String childNS = exMD.getNamespace(eChild.eClass());
+ // If so, the child element's NS has a feature whose name is the test feature
+ final EStructuralFeature testFeature = exMD.getElement(childNS, expandedName.getLocalPart());
+ // and whose affiliation is the containment feature
+ final EStructuralFeature affiliation = testFeature != null ? exMD.getAffiliation(testFeature) : null;
+ if(affiliation != null
+ && affiliation.getName().equals(containmentFeature.getName())
+ && testFeature.getEType().equals(eChild.eClass())) {
+ return true;
+ }
+ }
+ }
+ else if (child instanceof EMFEAttrAsElementWrapper)
+ {
+ final EMFEAttrAsElementWrapper wrapper = (EMFEAttrAsElementWrapper)child;
+ final EStructuralFeature feature = wrapper.getFeature();
+ if (expandedName.getLocalPart().equals(exMD.getName(feature)) &&
+ (expandedName.getNamespaceURI() == null || expandedName.getNamespaceURI().equals(exMD.getNamespace(feature))))
+ {
+ return true;
+ }
+
+ }
+ return false;
+ }
+
+ }
+
+
+ static class SchemaElementTester implements IXMLElementTester
+ {
+ private final ExpandedName expandedName;
+ private final ExtendedMetaData exMD;
+
+ public SchemaElementTester(ExtendedMetaData exMD, ExpandedName expandedName)
+ {
+ this.expandedName = expandedName;
+ this.exMD = exMD;
+ }
+
+ public boolean matches(Object child)
+ {
+ if(child instanceof EObject) {
+ final EObject eChild = (EObject)child;
+ final EReference containmentFeature = eChild.eContainmentFeature();
+ final EStructuralFeature affiliation = exMD.getAffiliation(containmentFeature);
+ final EStructuralFeature testFeature = affiliation != null ? affiliation : containmentFeature;
+ if(expandedName.getLocalPart().equals(exMD.getName(testFeature))
+ && (expandedName.getNamespaceURI() == null
+ || expandedName.getNamespaceURI().equals(exMD.getNamespace(testFeature)))) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ }
+
+
private static final String SCHEMA_ELEMENT_PREFIX = "_schema-element_"; //$NON-NLS-1$
private static final String EMPTY_STRING = ""; //$NON-NLS-1$
@@ -730,7 +819,7 @@ public class EObjectInspector implements IElementInspector, INodeInspectorExtens
if (isXMLNode(eClass))
{
- return getXMLNamedElement(eObject, eClass, nameTestExpandedName);
+ return getXMLNamedElement2(eObject, eClass, nameTestExpandedName);
}
else
@@ -769,132 +858,47 @@ public class EObjectInspector implements IElementInspector, INodeInspectorExtens
}
}
- private Object[] getXMLNamedElement(EObject eObject, EClass eClass, ExpandedName nameTestExpandedName)
+ interface IXMLElementTester {
+ public abstract boolean matches(Object child);
+ }
+
+ private Object[] getXMLNamedElement2(EObject eObject, EClass eClass, ExpandedName expandedName)
{
- final ExtendedMetaData exMD = getExtendedMetaData(eObject);
-// exMD.get
- final String testNsURI = nameTestExpandedName.getNamespaceURI();
- boolean isSchemaElementTest = false;
- String testLocalPart = nameTestExpandedName.getLocalPart();
- if(testLocalPart.startsWith(SCHEMA_ELEMENT_PREFIX)) {
- testLocalPart = testLocalPart.substring(SCHEMA_ELEMENT_PREFIX.length());
- isSchemaElementTest = true;
- }
+ final Object[] children = getChildren(eObject);
+ final List result = new ArrayList(children.length);
- final String[] namespacesToTry = testNsURI != null ? new String[] {testNsURI} : getApplicableNamespaces(exMD, eObject,eClass);
- EStructuralFeature feature = null;
- for (int i = 0; i < namespacesToTry.length && feature == null; i++)
- {
- feature = exMD.getElement(eClass, namespacesToTry[i], testLocalPart);
- }
-
- if(feature == null && namespacesToTry.length == 1 && namespacesToTry[0] == null) {
- // if the document has not namespace, getElement doesn't find elements registered on document root
- // try to find it ourselves...
- EObject rootContainer = EcoreUtil.getRootContainer(eObject);
- feature = exMD.getElement(rootContainer.eClass(), null, testLocalPart);
- }
- if(feature == null) {
- // didn't find a direct feature, see if there is a 'demand' feature...
- feature = exMD.demandFeature(testNsURI, testLocalPart, true);
- }
+ final IXMLElementTester test = getElementTester(eObject, expandedName);
- if(feature != null) {
- EStructuralFeature affiliation = exMD.getAffiliation(eClass, feature);
- final int affiliationKind = exMD.getFeatureKind(affiliation);
- if(affiliationKind == ExtendedMetaData.ELEMENT_WILDCARD_FEATURE) {
- FeatureMap fm = (FeatureMap)eObject.eGet(affiliation);
- return fm.list(feature).toArray();
- } else {
- Object[] values = getFeatureValue(eObject, affiliation);
- // Can get here in the following cases:
- // 1) testLocalPart(feature) is the head of a substitution group
- // In this case, affiliation == feature, but values includes all group members.
- // Unless isSchemaElementTest == true, must filter for actual instances of feature.getEType()
- // 2) testLocalPart(feature) is a substitution group member (not the head)
- // In this case, affiliation is the head and values includes all group members.
- // Must filter for actual instances of feature.getEType()
- // 3) testLocalPart(feature) is a local or global element not associated with a feature map
- // In this case, affiliation == feature and values contains only feature.getEType() instances.
- // 4) testLocalPart(feature) is a global type and
- // So, unless isSchemaElementTest is true, we must filter...
- if(!isSchemaElementTest) {
- // Filter the result to those that match the declared type of the feature
- // This is necessary because as of EMF 2.4, substitution groups map to a single
- // e-feature without a feature map
- List newValues = new ArrayList(Arrays.asList(values));
- for (Iterator i = newValues.iterator(); i.hasNext();)
- {
- Object candidate = i.next();
- // candidate may be an instance of AnyType, which indicates
- // an element for which no schema information was available. In such
- // cases, there is no possibility of substitution, and there is no
- // need to filter the element
- if(candidate instanceof EObject
- && !(candidate instanceof AnyType)
- && ((EObject)candidate).eClass() != feature.getEType()) {
- i.remove();
- }
- }
- values = newValues.toArray();
- }
- return values;
+ for(int i = 0; i < children.length; i++) {
+ Object child = children[i];
+ if(test.matches(child)) {
+ result.add(child);
}
- } else {
- return new Object[0];
- }
- }
-
- private String[] getApplicableNamespaces(ExtendedMetaData exMD, EObject eObject, EClass eClass)
- {
- EObject rootContainer = EcoreUtil.getRootContainer(eObject);
- EReference prefixMapFeature = exMD.getXMLNSPrefixMapFeature(rootContainer.eClass());
- if(prefixMapFeature != null) {
- EcoreEMap map = (EcoreEMap)rootContainer.eGet(prefixMapFeature);
- String[] nsArray = (String[])map.values().toArray(new String[map.values().size()+1]);
- nsArray[nsArray.length - 1] = null;
- return nsArray;
- } else {
- return new String[] {null};
}
+ return result.toArray();
}
/**
+ * Factory method for an {@link IXMLElementTester}
* @param eObject
- * @param feature
+ * @param expandedName
* @return
*/
- private Object[] getFeatureValue(EObject eObject, EStructuralFeature feature)
+ private IXMLElementTester getElementTester(EObject eObject, ExpandedName expandedName)
{
- Object objResult = eObject.eGet(feature);
- if(objResult == null) {
- return new Object[0];
- }
- if(feature instanceof EReference) {
- if(feature.isMany()) {
- return ((List)objResult).toArray();
- } else {
- return new Object[] {objResult};
- }
+ final ExtendedMetaData exMD = getExtendedMetaData(eObject);
+ final String localPart = expandedName.getLocalPart();
+ final IXMLElementTester test;
+ if(localPart.startsWith(SCHEMA_ELEMENT_PREFIX)) {
+ test = new SchemaElementTester(exMD,
+ new ExpandedName(expandedName.getNamespaceURI(), localPart.substring(SCHEMA_ELEMENT_PREFIX.length())));
} else {
- // its an EAttribute, wrap...
- final Setting setting = ((InternalEObject)eObject).eSetting(feature);
- if(feature.isMany())
- {
- Object[] result = new Object[((List)objResult).size()];
- for(int j = 0; j < result.length; j++ ) {
- result[j] = new EMFEAttrAsElementWrapper(setting, j);
- }
- return result;
- }
- else
- {
- return new Object[] {new EMFEAttrAsElementWrapper(setting)};
- }
+ test = new ElementNameTester(exMD, expandedName);
}
+ return test;
}
-
+
/**
* @param eClass
* @param featureURI
@@ -1140,7 +1144,8 @@ public class EObjectInspector implements IElementInspector, INodeInspectorExtens
Object newElement = null;
- if (srcElement instanceof EObject)
+ final NodeKind nodeKind = getNodeKind(srcElement);
+ if (srcElement instanceof EObject && nodeKind == NodeKind.ELEMENT)
{
EObject srcEObject = (EObject)srcElement;
if (recursive)
@@ -1169,6 +1174,35 @@ public class EObjectInspector implements IElementInspector, INodeInspectorExtens
addElementToParent(eObject, feature, newElement, null);
}
+ else if( srcElement instanceof EObject && nodeKind == NodeKind.ROOT)
+ {
+ try
+ {
+ newElement = addElement(eObject, new ExpandedName(name), null);
+ if(recursive) {
+ final Object[] children = getChildren(srcElement);
+ Object root = null;
+ for (int i = 0; i < children.length; i++)
+ {
+ if(children[i] instanceof EObject && getNodeKind(children[i]) == NodeKind.ELEMENT) {
+ root = children[i];
+ break;
+ }
+ }
+ if(root != null) {
+ copyElement(newElement, root, expandedNameOf(root).getLocalPart(), true);
+ }
+ }
+ }
+ catch (SimpleElementRequiresValueException e)
+ {
+ throw new CopyElementException(e);
+ }
+ catch (InvalidChildException e)
+ {
+ throw new CopyElementException(e);
+ }
+ }
else if (srcElement instanceof EMFEAttrAsElementWrapper)
{
EMFEAttrAsElementWrapper wrapper = (EMFEAttrAsElementWrapper)srcElement;

Back to the top