blob: c9d9d138ff772f50ba33fe2abed2941a2815b2d8 [file] [log] [blame]
/**
* Copyright (c) 2002-2008 IBM Corporation, Embarcadero Technologies, 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 - Initial API and implementation
* Kenn Hussey (Embarcadero Technologies) - 218759
*/
package org.eclipse.emf.ecore.xmi.impl;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import org.eclipse.emf.common.util.BasicEList;
import org.eclipse.emf.common.util.EMap;
import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EAttribute;
import org.eclipse.emf.ecore.EClass;
import org.eclipse.emf.ecore.EClassifier;
import org.eclipse.emf.ecore.EFactory;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.EReference;
import org.eclipse.emf.ecore.EStructuralFeature;
import org.eclipse.emf.ecore.EcorePackage;
import org.eclipse.emf.ecore.InternalEObject;
import org.eclipse.emf.ecore.resource.ContentHandler;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.ResourceSet;
import org.eclipse.emf.ecore.resource.URIConverter;
import org.eclipse.emf.ecore.resource.impl.ExtensibleURIConverterImpl;
import org.eclipse.emf.ecore.util.BasicExtendedMetaData;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.ExtendedMetaData;
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.xmi.ClassNotFoundException;
import org.eclipse.emf.ecore.xmi.EcoreBuilder;
import org.eclipse.emf.ecore.xmi.FeatureNotFoundException;
import org.eclipse.emf.ecore.xmi.IllegalValueException;
import org.eclipse.emf.ecore.xmi.PackageNotFoundException;
import org.eclipse.emf.ecore.xmi.UnresolvedReferenceException;
import org.eclipse.emf.ecore.xmi.XMIException;
import org.eclipse.emf.ecore.xmi.XMIPlugin;
import org.eclipse.emf.ecore.xmi.XMLDefaultHandler;
import org.eclipse.emf.ecore.xmi.XMLHelper;
import org.eclipse.emf.ecore.xmi.XMLOptions;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xmi.util.DefaultEcoreBuilder;
import org.eclipse.emf.ecore.xml.type.AnyType;
import org.eclipse.emf.ecore.xml.type.SimpleAnyType;
import org.eclipse.emf.ecore.xml.type.XMLTypeFactory;
import org.eclipse.emf.ecore.xml.type.XMLTypePackage;
import org.eclipse.emf.ecore.xml.type.util.XMLTypeUtil;
import org.xml.sax.Attributes;
import org.xml.sax.InputSource;
import org.xml.sax.Locator;
import org.xml.sax.SAXException;
import org.xml.sax.SAXParseException;
import org.xml.sax.helpers.DefaultHandler;
/**
* This class is a generic interface for loading XML files and
* creating EObjects from them. Its subclasses include the SAXXMLHandler
* class, which wraps this class in a SAX default handler.
*/
public abstract class XMLHandler extends DefaultHandler implements XMLDefaultHandler
{
protected static final String ERROR_TYPE = "error";
protected static final String OBJECT_TYPE = "object";
protected static final String UNKNOWN_FEATURE_TYPE = "unknownFeature";
protected static final String DOCUMENT_ROOT_TYPE = "documentRoot";
protected final static String TYPE_ATTRIB = XMLResource.XSI_NS + ":" + XMLResource.TYPE;
protected final static String NIL_ATTRIB = XMLResource.XSI_NS + ":" + XMLResource.NIL;
protected final static String SCHEMA_LOCATION_ATTRIB = XMLResource.XSI_NS + ":" + XMLResource.SCHEMA_LOCATION;
protected final static String NO_NAMESPACE_SCHEMA_LOCATION_ATTRIB = XMLResource.XSI_NS + ":" + XMLResource.NO_NAMESPACE_SCHEMA_LOCATION;
protected final static boolean DEBUG_DEMANDED_PACKAGES = false;
protected static class MyStack<E> extends BasicEList<E>
{
private static final long serialVersionUID = 1L;
public MyStack()
{
super();
}
@SuppressWarnings("unchecked")
public final E peek()
{
return size == 0 ? null : (E)data[size - 1];
}
public final void push(E o)
{
grow(size + 1);
data[size++] = o;
}
@SuppressWarnings("unchecked")
public final E pop()
{
return size == 0 ? null : (E)data[--size];
}
}
protected static class MyEObjectStack extends MyStack<EObject>
{
private static final long serialVersionUID = 1L;
protected EObject [] eObjectData;
public MyEObjectStack()
{
super();
}
@Override
protected final Object[] newData(int capacity)
{
return eObjectData = new EObject[capacity];
}
public final EObject peekEObject()
{
return size == 0 ? null : eObjectData[size - 1];
}
public final EObject popEObject()
{
return size == 0 ? null : eObjectData[--size];
}
@Override
public void clear()
{
eObjectData = null;
super.clear();
}
}
/**
* For unresolved forward references, the line number where the incorrect id
* appeared in an XML resource is needed, so the Value for the forward reference
* and the line number where the forward reference occurred must be saved until
* the end of the XML resource is encountered.
*/
protected static class SingleReference
{
private EObject object;
private EStructuralFeature feature;
private Object value;
private int position;
private int lineNumber;
private int columnNumber;
public SingleReference(EObject object,
EStructuralFeature feature,
Object value,
int position,
int lineNumber,
int columnNumber)
{
this.object = object;
this.feature = feature;
this.value = value;
this.position = position;
this.lineNumber = lineNumber;
this.columnNumber = columnNumber;
}
public EObject getObject()
{
return object;
}
public EStructuralFeature getFeature()
{
return feature;
}
public Object getValue()
{
return value;
}
public int getPosition()
{
return position;
}
public int getLineNumber()
{
return lineNumber;
}
public int getColumnNumber()
{
return columnNumber;
}
}
protected static class ManyReference implements XMLHelper.ManyReference
{
private EObject object;
private EStructuralFeature feature;
private Object[] values;
private int[] positions;
private int lineNumber;
private int columnNumber;
public ManyReference(EObject object,
EStructuralFeature feature,
Object[] values,
int[] positions,
int lineNumber,
int columnNumber)
{
this.object = object;
this.feature = feature;
this.values = values;
this.positions = positions;
this.lineNumber = lineNumber;
this.columnNumber = columnNumber;
}
public EObject getObject()
{
return object;
}
public EStructuralFeature getFeature()
{
return feature;
}
public Object[] getValues()
{
return values;
}
public int[] getPositions()
{
return positions;
}
public int getLineNumber()
{
return lineNumber;
}
public int getColumnNumber()
{
return columnNumber;
}
}
protected XMLResource xmlResource;
protected XMLHelper helper;
protected MyStack<String> elements;
protected MyEObjectStack objects;
protected MyStack<Object> types;
protected MyStack<FeatureMap> mixedTargets;
protected Map<String, EFactory> prefixesToFactories;
protected Map<String, URI> urisToLocations;
protected Map<String, URI> externalURIToLocations;
protected boolean processSchemaLocations;
protected InternalEList<EObject> extent;
protected List<EObject> deferredExtent;
protected ResourceSet resourceSet;
protected EPackage.Registry packageRegistry;
protected URI resourceURI;
protected boolean resolve;
protected boolean oldStyleProxyURIs;
protected boolean disableNotify;
protected StringBuffer text;
protected boolean isIDREF;
protected boolean isSimpleFeature;
protected List<InternalEObject> sameDocumentProxies;
protected List<SingleReference> forwardSingleReferences;
protected List<ManyReference> forwardManyReferences;
protected Object[] identifiers;
protected int[] positions;
protected static final int ARRAY_SIZE = 64;
protected static final int REFERENCE_THRESHOLD = 5;
protected int capacity;
protected Set<String> notFeatures;
protected String idAttribute;
protected String hrefAttribute;
protected XMLResource.XMLMap xmlMap;
protected ExtendedMetaData extendedMetaData;
protected EClass anyType;
protected EClass anySimpleType;
protected boolean recordUnknownFeature;
protected boolean useNewMethods;
protected boolean recordAnyTypeNSDecls;
protected Map<EObject, AnyType> eObjectToExtensionMap;
protected EStructuralFeature contextFeature;
protected EPackage xmlSchemaTypePackage = XMLTypePackage.eINSTANCE;
protected boolean deferIDREFResolution;
protected boolean processAnyXML;
protected EcoreBuilder ecoreBuilder;
protected boolean isRoot;
protected Locator locator;
protected Attributes attribs;
protected Map<EStructuralFeature, Integer> featuresToKinds;
protected boolean useConfigurationCache;
protected boolean needsPushContext;
protected XMLResource.ResourceEntityHandler resourceEntityHandler;
protected XMLResource.URIHandler uriHandler;
protected EObject documentRoot;
protected boolean usedNullNamespacePackage;
protected boolean isNamespaceAware;
protected boolean suppressDocumentRoot;
protected boolean laxWildcardProcessing;
/**
* @since 2.9
*/
protected boolean usePackageNsURIAsLocation;
/**
* @since 2.9
*/
protected XMLResource.MissingPackageHandler missingPackageHandler;
/**
*/
public XMLHandler(XMLResource xmlResource, XMLHelper helper, Map<?, ?> options)
{
this.xmlResource = xmlResource;
this.helper = helper;
elements = new MyStack<String>();
objects = new MyEObjectStack();
mixedTargets = new MyStack<FeatureMap>();
types = new MyStack<Object>();
prefixesToFactories = new HashMap<String, EFactory>();
forwardSingleReferences = new ArrayList<SingleReference>();
forwardManyReferences = new ArrayList<ManyReference>();
sameDocumentProxies = new ArrayList<InternalEObject>();
identifiers = new Object[ARRAY_SIZE];
positions = new int[ARRAY_SIZE];
capacity = ARRAY_SIZE;
resourceSet = xmlResource.getResourceSet();
packageRegistry = resourceSet == null ? EPackage.Registry.INSTANCE : resourceSet.getPackageRegistry();
resourceURI = xmlResource.getURI();
extent = (InternalEList<EObject>)xmlResource.getContents();
if (Boolean.TRUE.equals(options.get(XMLResource.OPTION_DEFER_ATTACHMENT)))
{
deferredExtent = new ArrayList<EObject>();
}
resolve = resourceURI != null && resourceURI.isHierarchical() && !resourceURI.isRelative();
eObjectToExtensionMap = xmlResource.getEObjectToExtensionMap();
eObjectToExtensionMap.clear();
helper.setOptions(options);
if (Boolean.TRUE.equals(options.get(XMLResource.OPTION_DISABLE_NOTIFY)))
disableNotify = true;
notFeatures = new HashSet<String>();
notFeatures.add(TYPE_ATTRIB);
notFeatures.add(SCHEMA_LOCATION_ATTRIB);
notFeatures.add(NO_NAMESPACE_SCHEMA_LOCATION_ATTRIB);
xmlMap = (XMLResource.XMLMap) options.get(XMLResource.OPTION_XML_MAP);
helper.setXMLMap(xmlMap);
if (xmlMap != null)
{
idAttribute = xmlMap.getIDAttributeName();
}
Object extendedMetaDataOption = options.get(XMLResource.OPTION_EXTENDED_META_DATA);
setExtendedMetaDataOption(extendedMetaDataOption);
recordUnknownFeature = Boolean.TRUE.equals(options.get(XMLResource.OPTION_RECORD_UNKNOWN_FEATURE));
if (recordUnknownFeature && extendedMetaData == null)
{
setExtendedMetaDataOption(Boolean.TRUE);
}
useNewMethods = Boolean.FALSE.equals(options.get(XMLResource.OPTION_USE_DEPRECATED_METHODS));
XMLOptions xmlOptions = (XMLOptions)options.get(XMLResource.OPTION_XML_OPTIONS);
if (xmlOptions != null)
{
processSchemaLocations = xmlOptions.isProcessSchemaLocations();
externalURIToLocations = xmlOptions.getExternalSchemaLocations();
if (processSchemaLocations || externalURIToLocations != null)
{
if (extendedMetaData == null)
{
setExtendedMetaDataOption(Boolean.TRUE);
}
ecoreBuilder = xmlOptions.getEcoreBuilder();
if (ecoreBuilder == null)
{
ecoreBuilder = createEcoreBuilder(options, extendedMetaData);
}
else
{
ecoreBuilder.setExtendedMetaData(extendedMetaData);
}
}
processAnyXML = xmlOptions.isProcessAnyXML();
if (processAnyXML && extendedMetaData == null)
{
setExtendedMetaDataOption(Boolean.TRUE);
}
}
if (extendedMetaData != null)
{
AnyType anyType = XMLTypeFactory.eINSTANCE.createAnyType();
mixedTargets.push(anyType.getMixed());
text = new StringBuffer();
}
anyType = (EClass)options.get(XMLResource.OPTION_ANY_TYPE);
anySimpleType = (EClass)options.get(XMLResource.OPTION_ANY_SIMPLE_TYPE);
if (anyType == null)
{
anyType = XMLTypePackage.eINSTANCE.getAnyType();
anySimpleType = XMLTypePackage.eINSTANCE.getSimpleAnyType();
}
helper.setAnySimpleType(anySimpleType);
@SuppressWarnings("unchecked") Map<EClassFeatureNamePair, EStructuralFeature> newEClassFeatureNamePairToEStructuralFeatureMap =
(Map<EClassFeatureNamePair, EStructuralFeature>)options.get(XMLResource.OPTION_USE_XML_NAME_TO_FEATURE_MAP);
eClassFeatureNamePairToEStructuralFeatureMap = newEClassFeatureNamePairToEStructuralFeatureMap;
if (eClassFeatureNamePairToEStructuralFeatureMap == null)
{
eClassFeatureNamePairToEStructuralFeatureMap = new HashMap<EClassFeatureNamePair, EStructuralFeature>();
}
else
{
isOptionUseXMLNameToFeatureSet = true;
}
recordAnyTypeNSDecls = Boolean.TRUE.equals(options.get(XMLResource.OPTION_RECORD_ANY_TYPE_NAMESPACE_DECLARATIONS));
hrefAttribute = XMLResource.HREF;
if (Boolean.TRUE.equals(options.get(XMLResource.OPTION_USE_ENCODED_ATTRIBUTE_STYLE)))
{
hrefAttribute = null;
}
if (Boolean.TRUE.equals(options.get(XMLResource.OPTION_DEFER_IDREF_RESOLUTION)))
{
helper.setCheckForDuplicates(deferIDREFResolution = true);
}
if (Boolean.TRUE.equals(options.get(XMLResource.OPTION_CONFIGURATION_CACHE)))
{
useConfigurationCache = true;
}
// The entity handler is the best place to resolve and deresolve URIs since it can do it there just once to produce the entity.
// So most often the entity handler will be a URI handler as well and when used as a URI handler will be an identity handler.
//
uriHandler = (XMLResource.URIHandler)options.get(XMLResource.OPTION_URI_HANDLER);
resourceEntityHandler = (XMLResource.ResourceEntityHandler)options.get(XMLResource.OPTION_RESOURCE_ENTITY_HANDLER);
if (resourceEntityHandler != null)
{
resourceEntityHandler.reset();
if (uriHandler == null && resourceEntityHandler instanceof XMLResource.URIHandler)
{
uriHandler = (XMLResource.URIHandler)resourceEntityHandler;
uriHandler.setBaseURI(resourceURI);
}
}
if (Boolean.TRUE.equals(options.get(XMLResource.OPTION_SUPPRESS_DOCUMENT_ROOT)))
{
suppressDocumentRoot = true;
}
if (Boolean.TRUE.equals(options.get(XMLResource.OPTION_LAX_WILDCARD_PROCESSING)))
{
laxWildcardProcessing = true;
}
usePackageNsURIAsLocation = !Boolean.FALSE.equals(options.get(XMLResource.OPTION_USE_PACKAGE_NS_URI_AS_LOCATION));
missingPackageHandler = (XMLResource.MissingPackageHandler)options.get(XMLResource.OPTION_MISSING_PACKAGE_HANDLER);
}
protected void setExtendedMetaDataOption(Object extendedMetaDataOption)
{
if (extendedMetaDataOption instanceof Boolean)
{
if (extendedMetaDataOption.equals(Boolean.TRUE))
{
extendedMetaData =
resourceSet == null ?
ExtendedMetaData.INSTANCE :
new BasicExtendedMetaData(resourceSet.getPackageRegistry());
if (xmlResource != null)
{
xmlResource.getDefaultSaveOptions().put(XMLResource.OPTION_EXTENDED_META_DATA, extendedMetaData);
}
}
else
{
extendedMetaData = null;
}
}
else
{
extendedMetaData = (ExtendedMetaData)extendedMetaDataOption;
}
helper.setExtendedMetaData(extendedMetaData);
}
public void prepare(XMLResource resource, XMLHelper helper, Map<?, ?> options)
{
this.xmlResource = resource;
this.helper = helper;
resourceSet = xmlResource.getResourceSet();
packageRegistry = resourceSet == null ? EPackage.Registry.INSTANCE : resourceSet.getPackageRegistry();
resourceURI = xmlResource.getURI();
extent = (InternalEList<EObject>)xmlResource.getContents();
if (Boolean.TRUE.equals(options.get(XMLResource.OPTION_DEFER_ATTACHMENT)))
{
deferredExtent = new ArrayList<EObject>();
}
resolve = resourceURI != null && resourceURI.isHierarchical() && !resourceURI.isRelative();
eObjectToExtensionMap = xmlResource.getEObjectToExtensionMap();
eObjectToExtensionMap.clear();
setExtendedMetaDataOption(options.get(XMLResource.OPTION_EXTENDED_META_DATA));
helper.setOptions(options);
if (extendedMetaData != null)
{
if (ecoreBuilder != null)
{
ecoreBuilder.setExtendedMetaData(extendedMetaData);
}
AnyType anyType = XMLTypeFactory.eINSTANCE.createAnyType();
mixedTargets.push(anyType.getMixed());
text = new StringBuffer();
}
// bug #126072
@SuppressWarnings("unchecked") Map<EClassFeatureNamePair, EStructuralFeature> newEClassFeatureNamePairToEStructuralFeatureMap =
(Map<EClassFeatureNamePair, EStructuralFeature>)options.get(XMLResource.OPTION_USE_XML_NAME_TO_FEATURE_MAP);
eClassFeatureNamePairToEStructuralFeatureMap =
newEClassFeatureNamePairToEStructuralFeatureMap;
if (eClassFeatureNamePairToEStructuralFeatureMap == null)
{
eClassFeatureNamePairToEStructuralFeatureMap = new HashMap<EClassFeatureNamePair, EStructuralFeature>();
isOptionUseXMLNameToFeatureSet = false;
}
else
{
isOptionUseXMLNameToFeatureSet = true;
if (helper instanceof XMLHelperImpl && featuresToKinds != null)
{
((XMLHelperImpl)helper).featuresToKinds = featuresToKinds;
}
}
// The entity handler is the best place to resolve and deresolve URIs since it can do it there just once to produce the entity.
// So most often the entity handler will be a URI handler as well and when used as a URI handler will be an identity handler.
//
uriHandler = (XMLResource.URIHandler)options.get(XMLResource.OPTION_URI_HANDLER);
resourceEntityHandler = (XMLResource.ResourceEntityHandler)options.get(XMLResource.OPTION_RESOURCE_ENTITY_HANDLER);
if (resourceEntityHandler != null)
{
resourceEntityHandler.reset();
if (uriHandler == null && resourceEntityHandler instanceof XMLResource.URIHandler)
{
uriHandler = (XMLResource.URIHandler)resourceEntityHandler;
uriHandler.setBaseURI(resourceURI);
}
}
}
public void reset()
{
this.xmlResource = null;
this.extendedMetaData = null;
// bug #126072
eClassFeatureNamePair.eClass = null;
eClassFeatureNamePairToEStructuralFeatureMap = null;
if (isOptionUseXMLNameToFeatureSet && helper instanceof XMLHelperImpl)
{
featuresToKinds = ((XMLHelperImpl)helper).featuresToKinds;
}
else
{
featuresToKinds = null;
}
if (ecoreBuilder != null)
{
this.ecoreBuilder.setExtendedMetaData(null);
}
this.helper = null;
elements.clear();
objects.clear();
mixedTargets.clear();
contextFeature = null;
eObjectToExtensionMap = null;
// external schema locations should only be processed once, i.e. in the subsequent parse
// there is no need to process those again.
externalURIToLocations = null;
types.clear();
prefixesToFactories.clear();
forwardSingleReferences.clear();
forwardManyReferences.clear();
sameDocumentProxies.clear();
for (int i = 0; i < identifiers.length; i++)
{
identifiers[i] = null;
}
for (int i = 0; i < positions.length; i++)
{
positions[i] = 0;
}
capacity = ARRAY_SIZE;
resourceSet = null;
packageRegistry = null;
resourceURI = null;
extent = null;
deferredExtent = null;
attribs = null;
locator = null;
urisToLocations = null;
resourceEntityHandler = null;
uriHandler = null;
documentRoot = null;
usedNullNamespacePackage = false;
isNamespaceAware = false;
}
//
// Overwrite DefaultHandler methods
//
@Override
public void ignorableWhitespace(char[] ch, int start, int length) throws SAXException
{
// Do nothing.
}
@Override
public void skippedEntity(String name) throws SAXException
{
// Do nothing.
}
protected XMIException toXMIException(SAXParseException e)
{
XMIException xmiException =
new XMIException
(e.getException() == null ? e : e.getException(),
e.getSystemId() == null ? getLocation() : e.getSystemId(),
e.getLineNumber(),
e.getColumnNumber());
return xmiException;
}
@Override
public void warning(SAXParseException e) throws SAXException
{
warning(toXMIException(e));
}
@Override
public void error(SAXParseException e) throws SAXException
{
error(toXMIException(e));
}
@Override
public void fatalError(SAXParseException e) throws SAXException
{
fatalError(toXMIException(e));
throw e;
}
@Override
public void setDocumentLocator(Locator locator)
{
setLocator(locator);
}
@Override
public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException
{
setAttributes(attributes);
startElement(uri, localName, qName);
}
//
// Implement LexicalHandler methods
//
public void startEntity(java.lang.String name)
{
if (resourceEntityHandler != null)
{
text = new StringBuffer();
}
}
public void endEntity(java.lang.String name)
{
if (resourceEntityHandler != null)
{
resourceEntityHandler.handleEntity(name, text.toString());
}
}
public void comment(char[] ch, int start, int length) // throws SAXException
{
if (mixedTargets.peek() != null)
{
if (text != null)
{
handleMixedText();
}
handleComment(new String(ch, start, length));
}
}
public void startCDATA()
{
if (mixedTargets.peek() != null)
{
if (text != null)
{
handleMixedText();
}
text = new StringBuffer();
}
}
public void endCDATA()
{
if (mixedTargets.peek() != null && text != null)
{
handleCDATA();
}
}
//
// Implement DTDHandler methods
//
public void startDTD(String name, String publicId, String systemId)
{
xmlResource.setDoctypeInfo(publicId, systemId);
}
public void endDTD()
{
// Do nothing.
}
@Override
public void unparsedEntityDecl(String name, String publicId, String systemId, String notationName) throws SAXException
{
// Do nothing.
}
@Override
public void notationDecl(String name, String publicId, String systemId) throws SAXException
{
// Do nothing.
}
//
// Implement EntityResolver methods
//
@Override
public InputSource resolveEntity(String publicId, String systemId) throws SAXException
{
try
{
Map<Object, Object> options = new HashMap<Object, Object>();
options.put("publicId", publicId);
options.put("systemId", systemId);
options.put("baseLocation", resourceURI == null ? null : resourceURI.toString());
URI uri = URI.createURI(systemId);
if (resolve && uri.isRelative() && uri.hasRelativePath())
{
uri = helper.resolve(uri, resourceURI);
}
InputStream inputStream = getURIConverter().createInputStream(uri, options);
InputSource result = new InputSource(inputStream);
result.setPublicId(publicId);
result.setSystemId(systemId);
return result;
}
catch (IOException exception)
{
throw new SAXException(exception);
}
}
/**
* Returns the xsi type attribute's value.
*/
protected abstract String getXSIType();
/**
* Process the XML attributes for the newly created object.
*/
protected abstract void handleObjectAttribs(EObject obj);
/**
* Process the XML namespace declarations.
* @deprecated since 2.2
*/
@Deprecated
protected void handleNamespaceAttribs()
{
for (int i = 0, size = attribs.getLength(); i < size; ++i)
{
String attrib = attribs.getQName(i);
if (attrib.startsWith(XMLResource.XML_NS))
{
handleXMLNSAttribute(attrib, attribs.getValue(i));
}
else if (SCHEMA_LOCATION_ATTRIB.equals(attrib))
{
handleXSISchemaLocation(attribs.getValue(i));
}
else if (NO_NAMESPACE_SCHEMA_LOCATION_ATTRIB.equals(attrib))
{
handleXSINoNamespaceSchemaLocation(attribs.getValue(i));
}
}
}
protected void handleSchemaLocation()
{
String xsiSchemLocation = attribs.getValue(ExtendedMetaData.XSI_URI, XMLResource.SCHEMA_LOCATION);
if (xsiSchemLocation != null)
{
handleXSISchemaLocation(xsiSchemLocation);
}
String xsiNoNamespaceSchemLocation = attribs.getValue(ExtendedMetaData.XSI_URI, XMLResource.NO_NAMESPACE_SCHEMA_LOCATION);
if (xsiNoNamespaceSchemLocation != null)
{
handleXSINoNamespaceSchemaLocation(xsiNoNamespaceSchemLocation);
}
}
/**
* Returns true if the xsi:nil attribute is in the list of attributes.
*/
protected boolean isNull()
{
String value = isNamespaceAware ? attribs.getValue(ExtendedMetaData.XSI_URI, XMLResource.NIL) : attribs.getValue(NIL_ATTRIB);
if (value != null)
{
try
{
return XMLTypeFactory.eINSTANCE.createBoolean(value);
}
catch (RuntimeException exception)
{
error(new XMIException(exception));
}
}
return false;
}
/**
* Sets the current attributes and returns the old ones.
*/
protected Object setAttributes(Object attributes)
{
Object oldAttribs = attribs;
this.attribs = (Attributes)attributes;
return oldAttribs;
}
/**
* Sets the object that might be used for determining the line and
* column number.
*/
protected void setLocator(Object locator)
{
this.locator = (Locator)locator;
}
protected void recordHeaderInformation()
{
if (locator != null)
{
Class<?> locatorClass = locator.getClass();
try
{
Method encodingMethod = locatorClass.getMethod("getEncoding");
String encoding = (String)encodingMethod.invoke(locator);
if (encoding != null)
{
this.xmlResource.setEncoding(encoding);
}
Method versionMethod = locatorClass.getMethod("getXMLVersion");
String version = (String)versionMethod.invoke(locator);
if (version != null)
{
this.xmlResource.setXMLVersion(version);
}
}
catch (NoSuchMethodException e)
{
// Ignore.
}
catch (IllegalAccessException e)
{
// Ignore.
}
catch (InvocationTargetException e)
{
// Ignore.
}
}
}
@Override
public void startDocument()
{
isRoot = true;
helper.pushContext();
needsPushContext = true;
}
/**
* This method determines whether to make an object or not, then makes an
* object based on the XML attributes and the metamodel.
*/
public void startElement(String uri, String localName, String name)
{
if (needsPushContext)
{
helper.pushContext();
}
needsPushContext = true;
if (text != null && text.length() > 0)
{
if (mixedTargets.peek() != null)
{
handleMixedText();
}
else
{
text = null;
}
}
elements.push(name);
String prefix = "";
if (useNewMethods)
{
if (isRoot)
{
handleSchemaLocation();
}
prefix = helper.getPrefix((uri.length() == 0) ? null : uri);
prefix = (prefix == null) ? "" : prefix;
}
else
{
handleNamespaceAttribs();
int index = name.indexOf(':', 0);
localName = name;
if (index != -1)
{
prefix = name.substring(0, index);
localName = name.substring(index + 1);
}
}
processElement(name, prefix, localName);
}
protected void processElement(String name, String prefix, String localName)
{
if (isRoot)
{
isRoot = false;
recordHeaderInformation();
}
if (isError())
{
types.push(ERROR_TYPE);
}
else
{
if (objects.isEmpty())
{
createTopObject(prefix, localName);
}
else
{
handleFeature(prefix, localName);
}
}
}
protected void handleForwardReferences()
{
handleForwardReferences(false);
}
/**
* Check if the values of the forward references have been set (they may
* have been set due to a bidirectional reference being set). If not, set them.
* If this is called during end document processing, errors should be diagnosed.
* If it is called in the middle of a document,
* we need to clean up the forward reference lists to avoid processing resolved references again later.
*/
protected void handleForwardReferences(boolean isEndDocument)
{
// Handle the same document proxies, which may have problems resulting from the
// other end of a bidirectional reference being handled as an IDREF rather than as a proxy.
// When we are done with these, we know that funny proxies are now resolved as if they were handled as IDREFs.
//
for (Iterator<InternalEObject> i = sameDocumentProxies.iterator(); i.hasNext(); )
{
InternalEObject proxy = i.next();
// Look through all the references...
//
LOOP:
for (EReference eReference : proxy.eClass().getEAllReferences())
{
// And find the one that holds this proxy.
//
EReference oppositeEReference = eReference.getEOpposite();
if (oppositeEReference != null && oppositeEReference.isChangeable() && proxy.eIsSet(eReference))
{
// Try to resolve the proxy locally.
//
EObject resolvedEObject = xmlResource.getEObject(proxy.eProxyURI().fragment());
if (resolvedEObject != null)
{
// We won't need to process this again later.
//
if (!isEndDocument)
{
i.remove();
}
// Compute the holder of the proxy
//
EObject proxyHolder = (EObject)(eReference.isMany() ? ((List<?>)proxy.eGet(eReference)).get(0) : proxy.eGet(eReference));
// If the proxy holder can hold many values,
// it may contain a duplicate that resulted when the other end was processed as an IDREF
// and hence did both sides of the bidirectional relation.
//
if (oppositeEReference.isMany())
{
// So if the resolved object is also present...
//
InternalEList<?> holderContents = (InternalEList<?>)proxyHolder.eGet(oppositeEReference);
int resolvedEObjectIndex = holderContents.basicIndexOf(resolvedEObject);
if (resolvedEObjectIndex != -1)
{
// Move the resolved object to the right place, remove the proxy, and we're done.
//
int proxyIndex = holderContents.basicIndexOf(proxy);
holderContents.move(proxyIndex, resolvedEObjectIndex);
holderContents.remove(proxyIndex > resolvedEObjectIndex ? proxyIndex - 1 : proxyIndex + 1);
break LOOP;
}
}
if (!oppositeEReference.getEType().isInstance(resolvedEObject))
{
error
(new IllegalValueException
(proxyHolder,
oppositeEReference,
resolvedEObject,
null,
getLocation(),
getLineNumber(),
getColumnNumber()));
break LOOP;
}
// If the resolved object doesn't contain a reference to the proxy holder as it should.
//
if (eReference.isMany() ?
!((InternalEList<?>)resolvedEObject.eGet(eReference)).basicContains(proxyHolder) :
resolvedEObject.eGet(eReference) != proxyHolder)
{
// The proxy needs to be replaced in a way that updates both ends of the reference.
//
if (oppositeEReference.isMany())
{
@SuppressWarnings("unchecked") InternalEList<EObject> proxyHolderList = (InternalEList<EObject>)proxyHolder.eGet(oppositeEReference);
proxyHolderList.setUnique(proxyHolderList.basicIndexOf(proxy), resolvedEObject);
}
else
{
proxyHolder.eSet(oppositeEReference, resolvedEObject);
}
}
}
break;
}
}
}
for (Iterator<SingleReference> i = forwardSingleReferences.iterator(); i.hasNext(); )
{
SingleReference ref = i.next();
EObject obj = xmlResource.getEObject((String) ref.getValue());
if (obj != null)
{
// We won't need to process this again later.
if (!isEndDocument)
{
i.remove();
}
EStructuralFeature feature = ref.getFeature();
setFeatureValue(ref.getObject(), feature, obj, ref.getPosition());
}
else if (isEndDocument)
{
error
(new UnresolvedReferenceException
((String) ref.getValue(),
getLocation(),
ref.getLineNumber(),
ref.getColumnNumber()));
}
}
for (Iterator<ManyReference> i = forwardManyReferences.iterator(); i.hasNext(); )
{
ManyReference ref = i.next();
Object[] values = ref.getValues();
boolean failure = false;
for (int j = 0, l = values.length; j < l; j++)
{
String id = (String) values[j];
EObject obj = xmlResource.getEObject(id);
values[j] = obj;
if (obj == null)
{
failure = true;
if (isEndDocument)
{
error
(new UnresolvedReferenceException
(id,
getLocation(),
ref.getLineNumber(),
ref.getColumnNumber()));
}
}
}
if (!failure)
{
if (!isEndDocument)
{
i.remove();
}
setFeatureValues(ref);
}
else if (isEndDocument)
{
// At least set the references that we were able to resolve, if any.
//
setFeatureValues(ref);
}
}
}
/**
* Check if the values of the forward references have been set (they may
* have been set due to a bi-directional reference being set). If not,
* set them.
*/
@Override
public void endDocument()
{
if (deferredExtent != null)
{
extent.addAll(deferredExtent);
}
// Pretend there is an xmlns="" because we really need to ensure that the null prefix
// isn't used to denote something other than the null namespace.
//
if (usedNullNamespacePackage)
{
helper.addPrefix("", "");
}
helper.recordPrefixToURIMapping();
helper.popContext();
handleForwardReferences(true);
if (disableNotify)
{
for (Iterator<?> i = EcoreUtil.getAllContents(xmlResource.getContents(), false); i.hasNext(); )
{
EObject eObject = (EObject)i.next();
eObject.eSetDeliver(true);
}
}
if (extendedMetaData != null)
{
if (extent.size() == 1)
{
EObject root = extent.get(0);
recordNamespacesSchemaLocations(root);
}
if (DEBUG_DEMANDED_PACKAGES)
{
// EATM temporary for debug purposes only.
//
Collection<EPackage> demandedPackages = EcoreUtil.copyAll(extendedMetaData.demandedPackages());
for (EPackage ePackage : demandedPackages)
{
ePackage.setName(ePackage.getNsURI());
}
extent.addAll(demandedPackages);
}
}
}
protected EMap<String, String> recordNamespacesSchemaLocations(EObject root)
{
EClass eClass = root.eClass();
EReference xmlnsPrefixMapFeature = extendedMetaData.getXMLNSPrefixMapFeature(eClass);
EMap<String, String> xmlnsPrefixMap = null;
if (xmlnsPrefixMapFeature != null)
{
@SuppressWarnings("unchecked") EMap<String, String> newXMLNSPrefixMap = (EMap<String, String>)root.eGet(xmlnsPrefixMapFeature);
xmlnsPrefixMap = newXMLNSPrefixMap;
xmlnsPrefixMap.putAll(helper.getPrefixToNamespaceMap());
}
if (urisToLocations != null)
{
EReference xsiSchemaLocationMapFeature = extendedMetaData.getXSISchemaLocationMapFeature(eClass);
if (xsiSchemaLocationMapFeature != null)
{
@SuppressWarnings("unchecked") EMap<String, String> newXSISchemaLocationMap = (EMap<String, String>)root.eGet(xsiSchemaLocationMapFeature);
EMap<String, String> xsiSchemaLocationMap = newXSISchemaLocationMap;
for (Map.Entry<String, URI> entry : urisToLocations.entrySet())
{
xsiSchemaLocationMap.put(entry.getKey(), entry.getValue().toString());
}
}
}
return xmlnsPrefixMap;
}
/**
* Create an object based on the prefix and type name.
*/
protected EObject createObjectByType(String prefix, String name, boolean top)
{
if (top)
{
handleTopLocations(prefix, name);
}
EFactory eFactory = getFactoryForPrefix(prefix);
String uri = helper.getURI(prefix);
if (eFactory == null && prefix.equals("") && uri == null)
{
EPackage ePackage = handleMissingPackage(null);
if (ePackage == null)
{
error
(new PackageNotFoundException
(null,
getLocation(),
getLineNumber(),
getColumnNumber()));
}
else
{
eFactory = ePackage.getEFactoryInstance();
}
}
documentRoot= createDocumentRoot(prefix, uri, name, eFactory, top);
if (documentRoot != null) return documentRoot;
EObject newObject = null;
if (useNewMethods)
{
newObject = createObject(eFactory, helper.getType(eFactory, name) , false);
}
else
{
newObject = createObjectFromFactory(eFactory, name);
}
newObject = validateCreateObjectFromFactory(eFactory, name, newObject, top);
if (top)
{
processTopObject(newObject);
// check for simple feature
if (extendedMetaData != null && newObject != null)
{
EStructuralFeature simpleFeature = extendedMetaData.getSimpleFeature(newObject.eClass());
if (simpleFeature != null)
{
isSimpleFeature = true;
isIDREF = simpleFeature instanceof EReference;
objects.push(null);
mixedTargets.push(null);
types.push(simpleFeature);
text = new StringBuffer();
}
}
}
return newObject;
}
protected EObject createDocumentRoot(String prefix, String uri, String name, EFactory eFactory, boolean top)
{
if (extendedMetaData != null && eFactory != null)
{
EPackage ePackage = eFactory.getEPackage();
EClass eClass = null;
if (useConfigurationCache)
{
eClass = ConfigurationCache.INSTANCE.getDocumentRoot(ePackage);
if (eClass == null)
{
eClass = extendedMetaData.getDocumentRoot(ePackage);
ConfigurationCache.INSTANCE.putDocumentRoot(ePackage, eClass);
}
}
else
{
eClass = extendedMetaData.getDocumentRoot(ePackage);
}
if (eClass != null)
{
// EATM Kind of hacky.
String typeName = extendedMetaData.getName(eClass);
@SuppressWarnings("deprecation") EObject newObject =
useNewMethods ?
createObject(eFactory, eClass, true) :
helper.createObject(eFactory, typeName);
validateCreateObjectFromFactory(eFactory, typeName, newObject);
if (top)
{
if (suppressDocumentRoot)
{
// Set up a deferred extent so the document root we create definitely will not be added to the resource.
//
List<EObject> oldDeferredExtent = deferredExtent;
try
{
deferredExtent = new ArrayList<EObject>();
processTopObject(newObject);
}
finally
{
deferredExtent = oldDeferredExtent;
}
handleFeature(prefix, name);
// Remove the document root's information from the top of the stacks.
//
objects.remove(0);
mixedTargets.remove(0);
types.remove(0);
// Process the new root object if any.
//
EObject peekObject = objects.peek();
if (peekObject == null)
{
// There's an EObject on the stack already.
//
if (objects.size() > 1)
{
// Excise the new root from the document root.
//
EcoreUtil.remove(peekObject = objects.get(0));
}
else
{
// If there is no root object, we're dealing with an EAttribute feature instead of an EReference feature.
// So create an instance of simple any type and prepare it to handle the text content.
//
SimpleAnyType simpleAnyType = (SimpleAnyType)EcoreUtil.create(anySimpleType);
simpleAnyType.setInstanceType(((EAttribute)types.peek()).getEAttributeType());
objects.set(0, simpleAnyType);
types.set(0, XMLTypePackage.Literals.SIMPLE_ANY_TYPE__RAW_VALUE);
mixedTargets.set(0, simpleAnyType.getMixed());
peekObject = simpleAnyType;
}
}
else
{
// Excise the new root from the document root.
//
EcoreUtil.remove(peekObject);
}
// Do the extent processing that should have been done for the root but was actualljy done for the document root.
//
if (deferredExtent != null)
{
deferredExtent.add(peekObject);
}
else
{
extent.addUnique(peekObject);
}
// The new root object is the actual new object since all sign of the document root will now have disappeared.
//
newObject = peekObject;
}
else
{
processTopObject(newObject);
handleFeature(prefix, name);
}
}
return newObject;
}
}
return null;
}
protected void createTopObject(String prefix, String name)
{
createObjectByType(prefix, name, true);
}
/**
* Add object to extent and call processObject.
*/
protected void processTopObject(EObject object)
{
if (object != null)
{
if (deferredExtent != null)
{
deferredExtent.add(object);
}
else
{
extent.addUnique(object);
}
if (extendedMetaData != null && !mixedTargets.isEmpty())
{
FeatureMap featureMap = mixedTargets.pop();
EStructuralFeature target = extendedMetaData.getMixedFeature(object.eClass());
if (target != null)
{
FeatureMap otherFeatureMap = (FeatureMap)object.eGet(target);
for (FeatureMap.Entry entry : new ArrayList<FeatureMap.Entry>(featureMap))
{
// Ignore a whitespace only text entry at the beginning.
//
if (entry.getEStructuralFeature() != XMLTypePackage.Literals.XML_TYPE_DOCUMENT_ROOT__TEXT ||
!"".equals(XMLTypeUtil.normalize(entry.getValue().toString(), true)))
{
otherFeatureMap.add(entry.getEStructuralFeature(), entry.getValue());
}
}
}
text = null;
}
}
processObject(object);
}
/**
* Pop the appropriate stacks and set features whose values are in
* the content of XML elements.
*/
@Override
public void endElement(String uri, String localName, String name)
{
elements.pop();
Object type = types.pop();
if (type == OBJECT_TYPE)
{
if (text == null)
{
objects.pop();
mixedTargets.pop();
}
else
{
EObject object = objects.popEObject();
if (mixedTargets.peek() != null &&
(object.eContainer() != null ||
suppressDocumentRoot ||
recordUnknownFeature &&
(eObjectToExtensionMap.containsValue(object) || ((InternalEObject)object).eDirectResource() != null)))
{
handleMixedText();
mixedTargets.pop();
}
else
{
if (text.length() != 0)
{
handleProxy((InternalEObject)object, text.toString().trim());
}
mixedTargets.pop();
text = null;
}
}
}
else if (isIDREF)
{
objects.pop();
mixedTargets.pop();
if (text != null)
{
setValueFromId(objects.peekEObject(), (EReference)type, text.toString());
text = null;
}
isIDREF= false;
}
else if (isTextFeatureValue(type))
{
EObject eObject = objects.popEObject();
mixedTargets.pop();
if (eObject == null)
{
eObject = objects.peekEObject();
}
setFeatureValue(eObject, (EStructuralFeature) type, text == null ? null : text.toString());
text = null;
}
if (isSimpleFeature)
{
types.pop();
objects.pop();
mixedTargets.pop();
isSimpleFeature = false;
}
helper.popContext(prefixesToFactories);
}
protected boolean isTextFeatureValue(Object type)
{
return type != ERROR_TYPE;
}
@Override
public void startPrefixMapping(String prefix, String uri)
{
isNamespaceAware = true;
if (needsPushContext)
{
helper.pushContext();
needsPushContext = false;
}
//if (useNonDeprecatedMethods)
//{
helper.addPrefix(prefix, uri);
prefixesToFactories.remove(prefix);
//}
}
@Override
public void endPrefixMapping(String prefix)
{
// Do nothing.
}
@Override
public void characters(char [] ch, int start, int length)
{
if (text == null && mixedTargets.peek() != null)
{
text = new StringBuffer();
}
if (text != null)
{
text.append(ch, start, length);
}
}
@Override
public void processingInstruction(String target, String data)
{
if (mixedTargets.peek() != null)
{
if (text != null)
{
handleMixedText();
}
handleProcessingInstruction(target, data);
}
}
protected void handleXMLNSAttribute(String attrib, String value)
{
// Handle namespaces
int index = attrib.indexOf(':', 0);
String prefix = index == -1 ? "" : attrib.substring(index + 1);
helper.addPrefix(prefix, value);
prefixesToFactories.remove(prefix);
}
protected void handleXSISchemaLocation(String schemaLocations)
{
if (urisToLocations == null)
{
urisToLocations = new HashMap<String, URI>();
xmlResource.getDefaultSaveOptions().put(XMLResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE);
}
for (StringTokenizer stringTokenizer = new StringTokenizer(schemaLocations, " "); stringTokenizer.hasMoreTokens(); )
{
String key = stringTokenizer.nextToken();
if (stringTokenizer.hasMoreTokens())
{
String value = stringTokenizer.nextToken();
URI uri = URI.createURI(value);
if (uriHandler != null)
{
uri = uriHandler.resolve(uri);
}
else if (resolve && uri.isRelative() && uri.hasRelativePath())
{
uri = helper.resolve(uri, resourceURI);
}
urisToLocations.put(key, uri);
}
}
}
protected void handleXSINoNamespaceSchemaLocation(String noNamespaceSchemaLocation)
{
if (urisToLocations == null)
{
urisToLocations = new HashMap<String, URI>();
xmlResource.getDefaultSaveOptions().put(XMLResource.OPTION_SCHEMA_LOCATION, Boolean.TRUE);
}
URI uri = URI.createURI(noNamespaceSchemaLocation);
if (uriHandler != null)
{
uri = uriHandler.resolve(uri);
}
else if (resolve && uri.isRelative() && uri.hasRelativePath())
{
uri = helper.resolve(uri, resourceURI);
}
urisToLocations.put(null, uri);
}
protected void processSchemaLocations(String prefix, String name)
{
if (urisToLocations != null)
{
// If processSchemaLocations is specified, treat these as XML Schema locations
if (processSchemaLocations)
{
try
{
ecoreBuilder.generate(urisToLocations);
}
catch (Exception exception)
{
XMIPlugin.INSTANCE.log(exception);
}
}
// If externalSchemaLocations are specified, process these ones as well
try
{
if (externalURIToLocations != null)
{
ecoreBuilder.generate(externalURIToLocations);
}
}
catch (Exception exception)
{
XMIPlugin.INSTANCE.log(exception);
}
URI locationForNull = urisToLocations.get(null);
if (locationForNull != null && helper.getNoNamespacePackage() == null)
{
helper.setNoNamespacePackage(getPackageForURI(locationForNull.toString()));
}
}
else if (externalURIToLocations != null)
{
try
{
ecoreBuilder.generate(externalURIToLocations);
}
catch (Exception exception)
{
XMIPlugin.INSTANCE.log(exception);
}
}
}
protected void handleTopLocations(String prefix, String name)
{
processSchemaLocations(prefix, name);
if (processAnyXML)
{
// Ensure that anything can be handled, even if it's not recognized.
//
String uri = helper.getURI(prefix);
if (extendedMetaData.getPackage(uri) == null)
{
extendedMetaData.demandFeature(uri, name, true);
}
}
}
/**
* The XML element represents a feature. There are two
* cases to handle:
* 1. The feature has a type that is a datatype.
* 2. The feature has a type that is a class.
*/
protected void handleFeature(String prefix, String name)
{
EObject peekObject = objects.peekEObject();
// This happens when processing an element with simple content that has elements content even though it shouldn't.
//
if (peekObject == null)
{
types.push(ERROR_TYPE);
error
(new FeatureNotFoundException
(name,
null,
getLocation(),
getLineNumber(),
getColumnNumber()));
return;
}
EStructuralFeature feature = getFeature(peekObject, prefix, name, true);
if (feature != null)
{
int kind = helper.getFeatureKind(feature);
if (kind == XMLHelper.DATATYPE_SINGLE || kind == XMLHelper.DATATYPE_IS_MANY)
{
objects.push(null);
mixedTargets.push(null);
types.push(feature);
if (!isNull())
{
text = new StringBuffer();
}
}
else if (extendedMetaData != null)
{
EReference eReference = (EReference)feature;
boolean isContainment = eReference.isContainment();
if (!isContainment && !eReference.isResolveProxies() && extendedMetaData.getFeatureKind(feature) != ExtendedMetaData.UNSPECIFIED_FEATURE)
{
isIDREF = true;
objects.push(null);
mixedTargets.push(null);
types.push(feature);
text = new StringBuffer();
}
else
{
createObject(peekObject, feature);
EObject childObject = objects.peekEObject();
if (childObject != null)
{
if (isContainment)
{
EStructuralFeature simpleFeature = extendedMetaData.getSimpleFeature(childObject.eClass());
if (simpleFeature != null)
{
isSimpleFeature = true;
isIDREF = simpleFeature instanceof EReference;
objects.push(null);
mixedTargets.push(null);
types.push(simpleFeature);
text = new StringBuffer();
}
}
else if (!childObject.eIsProxy())
{
text = new StringBuffer();
}
}
}
}
else
{
createObject(peekObject, feature);
}
}
else
{
// Try to get a general-content feature.
// Use a pattern that's not possible any other way.
//
if (xmlMap != null && (feature = getFeature(peekObject, null, "", true)) != null)
{
EFactory eFactory = getFactoryForPrefix(prefix);
// This is for the case for a local unqualified element that has been bound.
//
if (eFactory == null)
{
eFactory = feature.getEContainingClass().getEPackage().getEFactoryInstance();
}
EObject newObject = null;
if (useNewMethods)
{
newObject = createObject(eFactory, helper.getType(eFactory, name), false);
}
else
{
newObject = createObjectFromFactory(eFactory, name);
}
newObject = validateCreateObjectFromFactory(eFactory, name, newObject, feature);
if (newObject != null)
{
setFeatureValue(peekObject, feature, newObject);
}
processObject(newObject);
}
else
{
// This handles the case of a substitution group.
//
if (xmlMap != null)
{
EFactory eFactory = getFactoryForPrefix(prefix);
EObject newObject = createObjectFromFactory(eFactory, name);
validateCreateObjectFromFactory(eFactory, name, newObject);
if (newObject != null)
{
for (EReference eReference : peekObject.eClass().getEAllReferences())
{
if (eReference.getEType().isInstance(newObject))
{
setFeatureValue(peekObject, eReference, newObject);
processObject(newObject);
return;
}
}
}
}
handleUnknownFeature(prefix, name, true, peekObject, null);
}
}
}
protected int getLineNumber()
{
if (locator != null)
{
return locator.getLineNumber();
}
else
{
return -1;
}
}
protected int getColumnNumber()
{
if (locator != null)
{
return locator.getColumnNumber();
}
else
{
return -1;
}
}
protected String getLocation()
{
return
locator != null && locator.getSystemId() != null ?
locator.getSystemId() :
resourceURI == null ? "" : resourceURI.toString();
}
protected AnyType getExtension(EObject peekObject)
{
AnyType anyType = eObjectToExtensionMap.get(peekObject);
if (anyType == null)
{
anyType = XMLTypeFactory.eINSTANCE.createAnyType();
eObjectToExtensionMap.put(peekObject, anyType);
}
return anyType;
}
protected void handleUnknownFeature(String prefix, String name, boolean isElement, EObject peekObject, String value)
{
if (recordUnknownFeature)
{
recordUnknownFeature(prefix, name, isElement, peekObject, value);
}
else
{
reportUnknownFeature(prefix, name, isElement, peekObject, value);
}
}
protected void recordUnknownFeature(String prefix, String name, boolean isElement, EObject peekObject, String value)
{
if (isElement)
{
AnyType anyType = getExtension(peekObject);
int objectsIndex = objects.size();
objects.push(anyType);
int mixedTargetsIndex = mixedTargets.size();
mixedTargets.push(anyType.getAny());
int typesIndex = types.size();
types.push(UNKNOWN_FEATURE_TYPE);
handleFeature(prefix, name);
objects.remove(objectsIndex);
mixedTargets.remove(mixedTargetsIndex);
types.remove(typesIndex);
}
else
{
AnyType anyType = getExtension(peekObject);
setAttribValue(anyType, prefix == null ? name : prefix + ":" + name, value);
}
}
protected void reportUnknownFeature(String prefix, String name, boolean isElement, EObject peekObject, String value)
{
if (isElement)
{
types.push(ERROR_TYPE);
}
error
(new FeatureNotFoundException
(name,
peekObject,
getLocation(),
getLineNumber(),
getColumnNumber()));
}
public void error(XMIException e)
{
xmlResource.getErrors().add(e);
}
public void warning(XMIException e)
{
xmlResource.getWarnings().add(e);
}
public void fatalError(XMIException e)
{
xmlResource.getErrors().add(e);
}
/**
* Create an object based on the given feature and attributes.
*/
protected void createObject(EObject peekObject, EStructuralFeature feature)
{
if (isNull())
{
setFeatureValue(peekObject, feature, null);
objects.push(null);
mixedTargets.push(null);
types.push(OBJECT_TYPE);
}
else
{
String xsiType = getXSIType();
if (xsiType != null)
{
createObjectFromTypeName(peekObject, xsiType, feature);
}
else
{
createObjectFromFeatureType(peekObject, feature);
// This check is redundant -- see handleFeature method (EL)
/*if (extendedMetaData != null && !((EReference)feature).isContainment())
{
text = new StringBuffer();
}*/
if (xmlMap != null && !((EReference)feature).isContainment())
{
XMLResource.XMLInfo info = xmlMap.getInfo(feature);
if (info != null && info.getXMLRepresentation() == XMLResource.XMLInfo.ELEMENT)
{
text = new StringBuffer();
}
}
}
}
}
/**
* Create an object from the given qualified type name.
*/
protected EObject createObjectFromTypeName(EObject peekObject, String typeQName, EStructuralFeature feature)
{
String typeName = null;
String prefix = "";
int index = typeQName.indexOf(':', 0);
if (index > 0)
{
prefix = typeQName.substring(0, index);
typeName = typeQName.substring(index + 1);
}
else
{
typeName = typeQName;
}
contextFeature = feature;
EFactory eFactory = getFactoryForPrefix(prefix);
contextFeature = null;
if (eFactory == null && prefix.equals("") && helper.getURI(prefix) == null)
{
contextFeature = feature;
EPackage ePackage = handleMissingPackage(null);
contextFeature = null;
if (ePackage == null)
{
error(new PackageNotFoundException(null, getLocation(), getLineNumber(), getColumnNumber()));
}
else
{
eFactory = ePackage.getEFactoryInstance();
}
}
EObject obj = null;
if (useNewMethods)
{
obj = createObject(eFactory, helper.getType(eFactory, typeName), false);
}
else
{
obj = createObjectFromFactory(eFactory, typeName);
}
obj = validateCreateObjectFromFactory(eFactory, typeName, obj, feature);
if (obj != null)
{
if (contextFeature == null)
{
setFeatureValue(peekObject, feature, obj);
}
else
{
contextFeature = null;
}
}
processObject(obj);
return obj;
}
/**
* Create an object based on the type of the given feature.
*/
protected EObject createObjectFromFeatureType(EObject peekObject, EStructuralFeature feature)
{
String typeName = null;
EFactory factory = null;
EClassifier eType = null;
EObject obj = null;
if (feature != null && (eType = feature.getEType()) != null)
{
if (useNewMethods)
{
if (extendedMetaData != null && eType == EcorePackage.Literals.EOBJECT && extendedMetaData.getFeatureKind(feature) != ExtendedMetaData.UNSPECIFIED_FEATURE)
{
eType = anyType;
typeName = extendedMetaData.getName(anyType);
factory = anyType.getEPackage().getEFactoryInstance();
}
else
{
factory = eType.getEPackage().getEFactoryInstance();
typeName = extendedMetaData == null ? eType.getName() : extendedMetaData.getName(eType);
}
obj = createObject(factory, eType, false);
}
else
{
if (extendedMetaData != null && eType == EcorePackage.Literals.EOBJECT && extendedMetaData.getFeatureKind(feature) != ExtendedMetaData.UNSPECIFIED_FEATURE)
{
typeName = extendedMetaData.getName(anyType);
factory = anyType.getEPackage().getEFactoryInstance();
}
else
{
EClass eClass = (EClass)eType;
typeName = extendedMetaData == null ? eClass.getName() : extendedMetaData.getName(eClass);
factory = eClass.getEPackage().getEFactoryInstance();
}
obj = createObjectFromFactory(factory, typeName);
}
}
obj = validateCreateObjectFromFactory(factory, typeName, obj, feature);
if (obj != null)
{
setFeatureValue(peekObject, feature, obj);
}
processObject(obj);
return obj;
}
/**
* @deprecated since 2.2
* Create an object given a content helper, a factory, and a type name,
* and process the XML attributes.
*/
@Deprecated
protected EObject createObjectFromFactory(EFactory factory, String typeName)
{
EObject newObject = null;
if (factory != null)
{
newObject = helper.createObject(factory, typeName);
if (newObject != null)
{
if (disableNotify)
newObject.eSetDeliver(false);
handleObjectAttribs(newObject);
}
}
return newObject;
}
protected EObject createObject(EFactory eFactory, EClassifier type, boolean documentRoot)
{
EObject newObject = helper.createObject(eFactory, type);
if (newObject != null && !documentRoot)
{
if (disableNotify)
{
newObject.eSetDeliver(false);
}
handleObjectAttribs(newObject);
}
return newObject;
}
protected EObject validateCreateObjectFromFactory(EFactory factory, String typeName, EObject newObject, boolean top)
{
if (newObject == null && top && (recordUnknownFeature || processAnyXML) && factory != null && extendedMetaData != null)
{
String namespace = extendedMetaData.getNamespace(factory.getEPackage());
if (namespace == null)
{
usedNullNamespacePackage = true;
}
if (useNewMethods)
{
EClassifier type = extendedMetaData.demandType(namespace, typeName);
newObject = createObject(type.getEPackage().getEFactoryInstance(), type, false);
}
else
{
factory = extendedMetaData.demandType(namespace, typeName).getEPackage().getEFactoryInstance();
newObject = createObjectFromFactory(factory, typeName);
}
}
validateCreateObjectFromFactory(factory, typeName, newObject);
return newObject;
}
protected void validateCreateObjectFromFactory(EFactory factory, String typeName, EObject newObject)
{
if (newObject == null)
{
error
(new ClassNotFoundException
(typeName,
factory,
getLocation(),
getLineNumber(),
getColumnNumber()));
}
}
protected EObject validateCreateObjectFromFactory(EFactory factory, String typeName, EObject newObject, EStructuralFeature feature)
{
if (newObject != null)
{
if (extendedMetaData != null)
{
Collection<EPackage> demandedPackages = extendedMetaData.demandedPackages();
if (!demandedPackages.isEmpty() && demandedPackages.contains(newObject.eClass().getEPackage()))
{
if (recordUnknownFeature)
{
EObject peekObject = objects.peekEObject();
if (!(peekObject instanceof AnyType))
{
AnyType anyType = getExtension(objects.peekEObject());
EStructuralFeature entryFeature =
extendedMetaData.demandFeature(extendedMetaData.getNamespace(feature), extendedMetaData.getName(feature), true);
anyType.getAny().add(entryFeature, newObject);
contextFeature = entryFeature;
}
return newObject;
}
else
{
String namespace = extendedMetaData.getNamespace(feature);
String name = extendedMetaData.getName(feature);
EStructuralFeature wildcardFeature =
extendedMetaData.getElementWildcardAffiliation((objects.peekEObject()).eClass(), namespace, name);
if (wildcardFeature != null)
{
int processingKind = laxWildcardProcessing ? ExtendedMetaData.LAX_PROCESSING : extendedMetaData.getProcessingKind(wildcardFeature);
switch (processingKind)
{
case ExtendedMetaData.LAX_PROCESSING:
case ExtendedMetaData.SKIP_PROCESSING:
{
return newObject;
}
}
}
}
newObject = null;
}
}
}
else if (feature != null && factory != null && extendedMetaData != null)
{
// processing unknown feature with xsi:type (xmi:type)
if (recordUnknownFeature || processAnyXML)
{
EObject result = null;
String namespace = extendedMetaData.getNamespace(factory.getEPackage());
if (namespace == null)
{
usedNullNamespacePackage = true;
}
if (useNewMethods)
{
EClassifier type = extendedMetaData.demandType(namespace, typeName);
result = createObject(type.getEPackage().getEFactoryInstance(), type, false);
}
else
{
factory = extendedMetaData.demandType(namespace, typeName).getEPackage().getEFactoryInstance();
result = createObjectFromFactory(factory, typeName);
}
EObject peekObject = objects.peekEObject();
if (!(peekObject instanceof AnyType))
{
AnyType anyType = getExtension(peekObject);
EStructuralFeature entryFeature =
extendedMetaData.demandFeature(extendedMetaData.getNamespace(feature), extendedMetaData.getName(feature), true);
anyType.getAny().add(entryFeature, result);
contextFeature = entryFeature;
}
return result;
}
else
{
String namespace = extendedMetaData.getNamespace(feature);
String name = extendedMetaData.getName(feature);
EStructuralFeature wildcardFeature =
extendedMetaData.getElementWildcardAffiliation((objects.peekEObject()).eClass(), namespace, name);
if (wildcardFeature != null)
{
int processingKind = laxWildcardProcessing ? ExtendedMetaData.LAX_PROCESSING : extendedMetaData.getProcessingKind(wildcardFeature);
switch (processingKind)
{
case ExtendedMetaData.LAX_PROCESSING:
case ExtendedMetaData.SKIP_PROCESSING:
{
// EATM Demand create metadata; needs to depend on processing mode...
String factoryNamespace = extendedMetaData.getNamespace(factory.getEPackage());
if (factoryNamespace == null)
{
usedNullNamespacePackage = true;
}
if (useNewMethods)
{
EClassifier type = extendedMetaData.demandType(factoryNamespace, typeName);
return createObject(type.getEPackage().getEFactoryInstance(), type, false);
}
else
{
factory = extendedMetaData.demandType(factoryNamespace, typeName).getEPackage().getEFactoryInstance();
return createObjectFromFactory(factory, typeName);
}
}
}
}
}
}
validateCreateObjectFromFactory(factory, typeName, newObject);
return newObject;
}
/**
* Add object to appropriate stacks.
*/
protected void processObject(EObject object)
{
if (recordAnyTypeNSDecls && object instanceof AnyType)
{
FeatureMap featureMap = ((AnyType)object).getAnyAttribute();
for (Map.Entry<String, String> entry : helper.getAnyContentPrefixToURIMapping().entrySet())
{
Object uri = entry.getValue();
featureMap.add(extendedMetaData.demandFeature(ExtendedMetaData.XMLNS_URI, entry.getKey(), false), uri == null ? "" : uri);
}
}
if (object != null)
{
objects.push(object);
types.push(OBJECT_TYPE);
if (extendedMetaData != null)
{
EStructuralFeature mixedFeature = extendedMetaData.getMixedFeature(object.eClass());
if (mixedFeature != null)
{
mixedTargets.push((FeatureMap)object.eGet(mixedFeature));
}
else
{
mixedTargets.push(null);
}
}
else
{
mixedTargets.push(null);
}
}
else
{
types.push(ERROR_TYPE);
}
}
protected EFactory getFactoryForPrefix(String prefix)
{
EFactory factory = prefixesToFactories.get(prefix);
if (factory == null)
{
String uri = helper.getURI(prefix);
EPackage ePackage = getPackageForURI(uri);
if (ePackage == null && uri == null && prefix.equals(""))
{
ePackage = helper.getNoNamespacePackage();
}
if (ePackage != null)
{
factory = ePackage.getEFactoryInstance();
prefixesToFactories.put(prefix, factory);
if (uri == null)
{
usedNullNamespacePackage = true;
}
}
}
return factory;
}
/**
* Attempt to get the namespace for the given prefix, then return
* ERegister.getPackage() or null.
*/
protected EPackage getPackageForURI(String uriString)
{
if (uriString == null)
{
return null;
}
EPackage ePackage =
extendedMetaData == null ?
packageRegistry.getEPackage(uriString) :
extendedMetaData.getPackage(uriString);
if (ePackage != null && ePackage.eIsProxy())
{
ePackage = null;
}
if (ePackage == null)
{
URI uri = URI.createURI(uriString);
if (uri.scheme() == null)
{
// This only works for old globally registered things.
for (Map.Entry<String, Object> entry : packageRegistry.entrySet())
{
String nsURI = entry.getKey();
if (nsURI != null &&
nsURI.length() > uriString.length() &&
nsURI.endsWith(uriString) &&
nsURI.charAt(nsURI.length() - uriString.length() - 1) == '/')
{
oldStyleProxyURIs = true;
return (EPackage)entry.getValue();
}
}
}
URI nsURI = uri;
if (urisToLocations != null)
{
URI locationURI = urisToLocations.get(uriString);
if (locationURI != null)
{
uri = locationURI;
}
}
String fragment = uri.fragment();
Resource resource = null;
if ("java".equalsIgnoreCase(uri.scheme()) && uri.authority() != null)
{
try
{
String className = uri.authority();
Class<?> javaClass = Class.forName(className, true, Thread.currentThread().getContextClassLoader());
Field field = javaClass.getField("eINSTANCE");
resource = ((EPackage)field.get(null)).eResource();
}
catch (Exception exception)
{
// Ignore it if we can't find it since we'll fail anyway.
}
}
if (resource == null && resourceSet != null)
{
URI trimmedURI = uri.trimFragment();
resource = resourceSet.getResource(trimmedURI, false);
if (resource != null)
{
if (!resource.isLoaded())
{
try
{
resource.load(resourceSet.getLoadOptions());
}
catch (IOException exception)
{
// Continue with a different approach.
}
}
}
else if (!XMLResource.XML_SCHEMA_URI.equals(uriString) && (usePackageNsURIAsLocation || uri != nsURI))
{
try
{
InputStream inputStream = getURIConverter().createInputStream(trimmedURI, null);
resource = resourceSet.createResource(trimmedURI, ContentHandler.UNSPECIFIED_CONTENT_TYPE);
if (resource == null)
{
inputStream.close();
}
else
{
resource.load(inputStream, resourceSet.getLoadOptions());
}
}
catch (IOException exception)
{
// Continue with a different approach.
}
}
}
if (resource != null)
{
Object content = null;
if (fragment != null)
{
content = resource.getEObject(fragment);
}
else
{
List<EObject> contents = resource.getContents();
if (!contents.isEmpty())
{
content = contents.get(0);
}
}
if (content instanceof EPackage)
{
ePackage = (EPackage)content;
if (extendedMetaData != null)
{
extendedMetaData.putPackage(extendedMetaData.getNamespace(ePackage), ePackage);
}
else
{
packageRegistry.put(ePackage.getNsURI(), ePackage);
}
}
}
}
if (ePackage == null)
{
ePackage = handleMissingPackage(uriString);
}
if (ePackage == null)
{
error
(new PackageNotFoundException
(uriString,
getLocation(),
getLineNumber(),
getColumnNumber()));
}
return ePackage;
}
protected EPackage handleMissingPackage(String uriString)
{
if (XMLResource.XML_SCHEMA_URI.equals(uriString))
{
return xmlSchemaTypePackage;
}
else if (extendedMetaData != null)
{
if (recordUnknownFeature)
{
return extendedMetaData.demandPackage(uriString);
}
else if (processAnyXML && objects.isEmpty())
{
return extendedMetaData.demandPackage(uriString);
}
else if (contextFeature != null)
{
String namespace = extendedMetaData.getNamespace(contextFeature);
String name = extendedMetaData.getName(contextFeature);
EStructuralFeature wildcardFeature =
extendedMetaData.getElementWildcardAffiliation((objects.peekEObject()).eClass(), namespace, name);
if (wildcardFeature != null)
{
int processingKind = laxWildcardProcessing ? ExtendedMetaData.LAX_PROCESSING : extendedMetaData.getProcessingKind(wildcardFeature);
switch (processingKind)
{
case ExtendedMetaData.LAX_PROCESSING:
case ExtendedMetaData.SKIP_PROCESSING:
{
return extendedMetaData.demandPackage(uriString);
}
}
}
}
}
return missingPackageHandler != null ? missingPackageHandler.getPackage(uriString) : null;
}
protected URIConverter getURIConverter()
{
return resourceSet != null ? resourceSet.getURIConverter() : new ExtensibleURIConverterImpl();
}
protected void setFeatureValue(EObject object, EStructuralFeature feature, Object value)
{
setFeatureValue(object, feature, value, -1);
}
/**
* Set the given feature of the given object to the given value.
*/
protected void setFeatureValue(EObject object, EStructuralFeature feature, Object value, int position)
{
try
{
helper.setValue(object, feature, value, position);
}
catch (RuntimeException e)
{
error
(new IllegalValueException
(object,
feature,
value,
e,
getLocation(),
getLineNumber(),
getColumnNumber()));
}
}
/**
* Set the values for the given multi-valued forward reference.
*/
protected void setFeatureValues(ManyReference reference)
{
List<XMIException> xmiExceptions = helper.setManyReference(reference, getLocation());
if (xmiExceptions != null)
{
for (XMIException exception : xmiExceptions)
{
error(exception);
}
}
}
/**
* Create a feature with the given name for the given object with the
* given values.
*/
protected void setAttribValue(EObject object, String name, String value)
{
int index = name.indexOf(':', 0);
// We use null here instead of "" because an attribute without a prefix is considered to have the null target namespace...
String prefix = null;
String localName = name;
if (index != -1)
{
prefix = name.substring(0, index);
localName = name.substring(index + 1);
}
EStructuralFeature feature = getFeature(object, prefix, localName, false);
if (feature == null)
{
handleUnknownFeature(prefix, localName, false, object, value);
}
else
{
int kind = helper.getFeatureKind(feature);
if (kind == XMLHelper.DATATYPE_SINGLE || kind == XMLHelper.DATATYPE_IS_MANY)
{
setFeatureValue(object, feature, value, -2);
}
else
{
setValueFromId(object, (EReference)feature, value);
}
}
}
/**
* Create a ValueLine object and put it in the list
* of references to resolve at the end of the document.
*/
protected void setValueFromId(EObject object, EReference eReference, String ids)
{
StringTokenizer st = new StringTokenizer(ids);
boolean isFirstID = true;
boolean mustAdd = deferIDREFResolution;
boolean mustAddOrNotOppositeIsMany = false;
int size = 0;
String qName = null;
int position = 0;
while (st.hasMoreTokens())
{
String id = st.nextToken();
int index = id.indexOf('#', 0);
if (index != -1)
{
if (index == 0)
{
id = id.substring(1);
}
else
{
Object oldAttributes = setAttributes(null);
// Create a proxy in the correct way and pop it.
//
InternalEObject proxy =
(InternalEObject)
(qName == null ?
createObjectFromFeatureType(object, eReference) :
createObjectFromTypeName(object, qName, eReference));
setAttributes(oldAttributes);
if (proxy != null)
{
handleProxy(proxy, id);
}
objects.pop();
types.pop();
mixedTargets.pop();
qName = null;
++position;
continue;
}
}
else if (id.indexOf(':', 0) != -1)
{
qName = id;
continue;
}
// Ensure that references corresponding to repeating elements are always deferred and processed in order at the end.
//
if (isFirstID && extendedMetaData != null && eReference.isMany() && extendedMetaData.getFeatureKind(eReference) == ExtendedMetaData.ELEMENT_FEATURE)
{
SingleReference ref = new SingleReference
(object,
eReference,
id,
-1,
getLineNumber(),
getColumnNumber());
forwardSingleReferences.add(ref);
return;
}
if (!deferIDREFResolution)
{
if (isFirstID)
{
EReference eOpposite = eReference.getEOpposite();
if (eOpposite == null)
{
mustAdd = true;
mustAddOrNotOppositeIsMany = true;
}
else
{
mustAdd = eOpposite.isTransient() || eReference.isMany();
mustAddOrNotOppositeIsMany = mustAdd || !eOpposite.isMany();
}
isFirstID = false;
}
if (mustAddOrNotOppositeIsMany)
{
EObject resolvedEObject = xmlResource.getEObject(id);
if (resolvedEObject != null)
{
setFeatureValue(object, eReference, resolvedEObject);
qName = null;
++position;
continue;
}
}
}
if (mustAdd)
{
if (size == capacity)
growArrays();
identifiers[size] = id;
positions[size] = position;
++size;
}
qName = null;
++position;
}
if (position == 0)
{
setFeatureValue(object, eReference, null, -2);
}
else if (size <= REFERENCE_THRESHOLD)
{
for (int i = 0; i < size; i++)
{
SingleReference ref = new SingleReference
(object,
eReference,
identifiers[i],
positions[i],
getLineNumber(),
getColumnNumber());
forwardSingleReferences.add(ref);
}
}
else
{
Object[] values = new Object[size];
int[] currentPositions = new int[size];
System.arraycopy(identifiers, 0, values, 0, size);
System.arraycopy(positions, 0, currentPositions, 0, size);
ManyReference ref = new ManyReference
(object,
eReference,
values,
currentPositions,
getLineNumber(),
getColumnNumber());
forwardManyReferences.add(ref);
}
}
protected void handleProxy(InternalEObject proxy, String uriLiteral)
{
URI proxyURI;
if (oldStyleProxyURIs)
{
proxy.eSetProxyURI(proxyURI = URI.createURI(uriLiteral.startsWith("/") ? uriLiteral : "/" + uriLiteral));
}
else
{
URI uri = URI.createURI(uriLiteral);
if (uriHandler != null)
{
uri = uriHandler.resolve(uri);
}
else if (resolve &&
uri.isRelative() &&
uri.hasRelativePath() &&
(extendedMetaData == null ?
!packageRegistry.containsKey(uri.trimFragment().toString()) :
extendedMetaData.getPackage(uri.trimFragment().toString()) == null))
{
uri = helper.resolve(uri, resourceURI);
}
proxy.eSetProxyURI(proxyURI = uri);
}
// Test for a same document reference that would usually be handled as an IDREF.
//
if (proxyURI.trimFragment().equals(resourceURI))
{
sameDocumentProxies.add(proxy);
}
}
protected void growArrays() {
int oldCapacity = capacity;
capacity = capacity * 2;
Object[] newIdentifiers = new Object[capacity];
int[] newPositions = new int[capacity];
System.arraycopy(identifiers, 0, newIdentifiers, 0, oldCapacity);
System.arraycopy(positions, 0, newPositions, 0, oldCapacity);
identifiers = newIdentifiers;
positions = newPositions;
}
/**
* Returns true if there was an error in the last XML element; false otherwise.
*/
protected boolean isError()
{
return types.peek() == ERROR_TYPE;
}
static class EClassFeatureNamePair
{
public EClass eClass;
public String featureName;
public String namespaceURI;
public boolean isElement;
@Override
public boolean equals(Object that)
{
EClassFeatureNamePair typedThat = (EClassFeatureNamePair)that;
return
typedThat.eClass == eClass &&
typedThat.isElement == isElement &&
typedThat.featureName.equals(featureName) &&
(typedThat.namespaceURI != null ? typedThat.namespaceURI.equals(namespaceURI): namespaceURI == null);
}
@Override
public int hashCode()
{
return eClass.hashCode() ^ featureName.hashCode() ^ (namespaceURI == null ? 0 : namespaceURI.hashCode()) + (isElement ? 0 : 1);
}
}
Map<EClassFeatureNamePair, EStructuralFeature> eClassFeatureNamePairToEStructuralFeatureMap;
boolean isOptionUseXMLNameToFeatureSet;
EClassFeatureNamePair eClassFeatureNamePair = new EClassFeatureNamePair();
/**
* @deprecated
*/
@Deprecated
protected EStructuralFeature getFeature(EObject object, String prefix, String name)
{
EClass eClass = object.eClass();
String uri = helper.getURI(prefix);
EStructuralFeature result = helper.getFeature(eClass, uri, name, true);
if (result == null)
{
helper.getFeature(eClass, uri, name, false);
}
return result;
}
/**
* Get the EStructuralFeature from the metaObject for the given object
* and feature name.
*/
protected EStructuralFeature getFeature(EObject object, String prefix, String name, boolean isElement)
{
String uri = helper.getURI(prefix);
EClass eClass = object.eClass();
eClassFeatureNamePair.eClass = eClass;
eClassFeatureNamePair.featureName = name;
eClassFeatureNamePair.namespaceURI = uri;
eClassFeatureNamePair.isElement = isElement;
EStructuralFeature result = eClassFeatureNamePairToEStructuralFeatureMap.get(eClassFeatureNamePair);
if (result == null)
{
result = helper.getFeature(eClass, uri, name, isElement);
if (result == null)
{
if (extendedMetaData != null)
{
EStructuralFeature wildcardFeature =
isElement ?
extendedMetaData.getElementWildcardAffiliation(eClass, uri, name) :
extendedMetaData.getAttributeWildcardAffiliation(eClass, uri, name);
if (wildcardFeature != null)
{
int processingKind = laxWildcardProcessing ? ExtendedMetaData.LAX_PROCESSING : extendedMetaData.getProcessingKind(wildcardFeature);
switch (processingKind)
{
case ExtendedMetaData.LAX_PROCESSING:
case ExtendedMetaData.SKIP_PROCESSING:
{
// EATM Demand create metadata.
result = extendedMetaData.demandFeature(uri, name, isElement);
break;
}
}
}
}
else
{
// EATM Call the deprecated method which does the same thing
// but might have an override in older code.
result = getFeature(object, prefix, name);
}
}
EClassFeatureNamePair entry = new EClassFeatureNamePair();
entry.eClass = eClass;
entry.featureName = name;
entry.namespaceURI = uri;
entry.isElement = isElement;
eClassFeatureNamePairToEStructuralFeatureMap.put(entry, result);
}
return result;
}
/**
* Searches the array of bytes to determine the XML
* encoding.
*/
public static String getXMLEncoding(byte[] bytes)
{
String javaEncoding = null;
if (bytes.length >= 4)
{
if (((bytes[0] == -2) && (bytes[1] == -1)) ||
((bytes[0] == 0) && (bytes[1] == 60)))
javaEncoding = "UnicodeBig";
else if (((bytes[0] == -1) && (bytes[1] == -2)) ||
((bytes[0] == 60) && (bytes[1] == 0)))
javaEncoding = "UnicodeLittle";
else if ((bytes[0] == -17) && (bytes[1] == -69) && (bytes[2] == -65))
javaEncoding = "UTF8";
}
String header = null;
try
{
if (javaEncoding != null)
header = new String(bytes, 0, bytes.length, javaEncoding);
else
header = new String(bytes, 0, bytes.length);
}
catch (UnsupportedEncodingException e)
{
return null;
}
if (!header.startsWith("<?xml"))
return "UTF-8";
int endOfXMLPI = header.indexOf("?>");
int encodingIndex = header.indexOf("encoding", 6);
if ((encodingIndex == -1) || (encodingIndex > endOfXMLPI))
return "UTF-8";
int firstQuoteIndex = header.indexOf('"', encodingIndex);
int lastQuoteIndex;
if ((firstQuoteIndex == -1) || (firstQuoteIndex > endOfXMLPI))
{
firstQuoteIndex = header.indexOf('\'', encodingIndex);
lastQuoteIndex = header.indexOf('\'', firstQuoteIndex + 1);
}
else
lastQuoteIndex = header.indexOf('"', firstQuoteIndex + 1);
return header.substring(firstQuoteIndex + 1, lastQuoteIndex);
}
protected void handleComment(String comment)
{
FeatureMap featureMap = mixedTargets.peek();
featureMap.add(XMLTypePackage.Literals.XML_TYPE_DOCUMENT_ROOT__COMMENT, comment);
text = null;
}
protected void handleMixedText()
{
FeatureMap featureMap = mixedTargets.peek();
featureMap.add(XMLTypePackage.Literals.XML_TYPE_DOCUMENT_ROOT__TEXT, text.toString());
text = null;
}
protected void handleCDATA()
{
FeatureMap featureMap = mixedTargets.peek();
featureMap.add(XMLTypePackage.Literals.XML_TYPE_DOCUMENT_ROOT__CDATA, text.toString());
text = null;
}
protected void handleProcessingInstruction(String target, String data)
{
FeatureMap featureMap = mixedTargets.peek();
FeatureMapUtil.addProcessingInstruction(featureMap, target, data);
text = null;
}
protected EcoreBuilder createEcoreBuilder(Map<?, ?> options, ExtendedMetaData extendedMetaData)
{
return new DefaultEcoreBuilder(extendedMetaData);
}
}