blob: 01c043b074c84319f30b5ca7964ff953f3ef72ad [file] [log] [blame]
/**
*
* 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.util.resource;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.xml.namespace.NamespaceContext;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import org.apache.tuscany.sdo.helper.HelperContextImpl;
import org.apache.tuscany.sdo.helper.TypeHelperImpl;
import org.apache.tuscany.sdo.helper.XMLStreamHelper;
import org.apache.tuscany.sdo.helper.XMLStreamHelperImpl;
import org.apache.tuscany.sdo.util.StreamDeserializer;
import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.common.util.EList;
import org.eclipse.emf.common.util.TreeIterator;
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.resource.Resource;
import org.eclipse.emf.ecore.util.EcoreUtil;
import org.eclipse.emf.ecore.util.ExtendedMetaData;
import org.eclipse.emf.ecore.xmi.XMLResource;
import commonj.sdo.Property;
import commonj.sdo.Type;
import commonj.sdo.helper.HelperContext;
import commonj.sdo.helper.TypeHelper;
import commonj.sdo.helper.XSDHelper;
/**
* SDO StAX Deserializer. The instance isn't thread-safe, however it's safe to use the instance any times on the same thread.
*/
public class SDODeserializer extends StreamDeserializer {
private HelperContext hc;
protected final void initialize(XMLStreamReader stream, HelperContext scope, Object rootObject) {
hc = scope;
reader = stream;
xsdHelper = scope.getXSDHelper();
typeHelper = scope.getTypeHelper();
extendedMetaData = ((TypeHelperImpl) typeHelper).getExtendedMetaData();
deserializer = (XMLStreamHelperImpl)((HelperContextImpl)scope).getXMLStreamHelper();;
root = (EObject) rootObject;
}
XSDHelper xsdHelper;
protected Property propertyInSequence;
Property getProperty(Object type) {
EClass c = (EClass) type;
EStructuralFeature containment = (EStructuralFeature) propertyInSequence;
Object containing = extendedMetaData.getAffiliation(c, containment);
// if (containing == null) report error?
if (containment == containing && containment.isDerived()) {
containing = extendedMetaData.getMixedFeature(c);
if (containing == null) {
containing = extendedMetaData.getGroup(containment);
if (containing == null)
return propertyInSequence;
}
}
return (Property) containing;
}
protected final Property getProperty(Type type, String nameSpace, String name, boolean element) {
for (Iterator iterator = type.getProperties().iterator(); iterator.hasNext();) {
propertyInSequence = (Property) iterator.next();
if (name.equals(xsdHelper.getLocalName(propertyInSequence))
&& nameSpace.equals(xsdHelper.getNamespaceURI(propertyInSequence)))
return getProperty(type);
}
propertyInSequence = xsdHelper.getGlobalProperty(nameSpace, name, element);
// if (propertyInSequence == null) report error?
return getProperty(type);
}
protected final Property getProperty(Type type, String name) {
propertyInSequence = type.getProperty(name);
// if (propertyInSequence == null) report error?
return getProperty(type);
}
protected final Property getProperty(String nameSpace, String name, Type type) {
return null == nameSpace ? getProperty(type, name) : getProperty(type, nameSpace, name, true);
}
XMLStreamHelperImpl deserializer;
TypeHelper typeHelper;
protected Object load(XMLStreamReader reader, Map options) throws XMLStreamException {
return deserializer.loadObject(reader, options);
}
static Object value(Type type, XMLStreamReader reader) throws XMLStreamException {
return value(type, reader.getElementText(), reader.getNamespaceContext());
}
protected final Object value(Type type) throws XMLStreamException {
return "true".equals(reader.getAttributeValue(ExtendedMetaData.XSI_URI, XMLResource.NIL)) ? null : type.isDataType() ? value(type, reader)
: load(reader, null);
}
Map options/* = null */;
protected final Object value(XMLStreamReader reader) throws XMLStreamException {
Type propertyType = propertyInSequence.getType();
if (propertyType.isDataType())
return value(propertyType, reader);
if (options == null)
options = new HashMap();
options.put(XMLStreamHelper.OPTION_DEFAULT_ROOT_TYPE, propertyType);
return load(reader, options);
}
private boolean match(String name, String space, EStructuralFeature feature) {
return name.equals(extendedMetaData.getName(feature)) && space.equals(extendedMetaData.getNamespace(feature));
}
EObject step(String ref, int step, int index, EObject container, String prefix, NamespaceContext nameSpaces) {
String name = ref.substring(step, index);
Iterator iterator = container.eContents().iterator();
if (iterator.hasNext())
if (prefix == null)
do {
container = (EObject) iterator.next();
// if( container == null )continue;
if (name.equals(extendedMetaData.getName(container.eContainmentFeature())))
return container;
} while (iterator.hasNext());
else {
prefix = nameSpaces.getNamespaceURI(prefix);
do {
container = (EObject) iterator.next();
// if( container == null )continue;
if (match(name, prefix, container.eContainmentFeature()))
return container;
} while (iterator.hasNext());
}
return null;
}
EObject root;
ExtendedMetaData extendedMetaData;
protected final EObject referent(String ref, NamespaceContext nameSpaces) {
int length = ref.length();
switch (length) {
case 0:
return null;
case 1: // #
return root;
}
EObject container;
int step;
if (ref.charAt(1) == '/') {
container = EcoreUtil.getRootContainer(root);
if (length == 2)
return container;
if (ref.charAt(2) == '/') {
for (Iterator iterator = container.eContents().iterator();/* true */;) {
if (!iterator.hasNext())
return null;
container = (EObject) iterator.next();
// if( container != null )
break;
}
/*#// is invalid
if (length == 3)
return container; */
step = 3;
} else
step = 2;
} else {
container = root;
step = 1;
}
String prefix = null;
for (int index = step; ++index != length;) {
switch (ref.charAt(index)) {
case '/':
container = step(ref, step, index, container, prefix, nameSpaces);
if (container == null)
return null;
break;
case ':':
prefix = ref.substring(step, index);
if (++index == length)
return container; // report error?
step = index;
default:
continue;
case '[':
name = ref.substring(step, index);
step = ref.indexOf(']', index + 2);
if (step == -1)
return container; // report error?
index = Integer.parseInt(ref.substring(++index, step));
EStructuralFeature feature;
Iterator iterator = container.eContents().iterator();
if (prefix == null)
do {
if (!iterator.hasNext())
return null;
EObject content = (EObject) iterator.next();
// if( content == null )continue;
feature = content.eContainmentFeature();
} while (!name.equals(extendedMetaData.getName(feature)));
else {
prefix = nameSpaces.getNamespaceURI(prefix);
do {
if (!iterator.hasNext())
return null;
EObject content = (EObject) iterator.next();
// if( content == null )continue;
feature = content.eContainmentFeature();
} while (!match(name, prefix, feature));
}
Object value = container.eGet(feature);
if (value instanceof List) {
List values = (List) value;
if (index > values.size())
return null;
container = (EObject) values.get(--index);
} else if (index == 1)
container = (EObject) value;
else
return null;
index = ref.indexOf('/', ++step);
if (index == -1)
return container;
}
if (++index == length)
return container;
step = index;
prefix = null;
}
return step(ref, step, length, container, prefix, nameSpaces);
}
static protected class Ref implements EObject // FeatureMapEntry value
{
protected Ref(String path, NamespaceContext context) {
ref = path;
nameSpaces = context;
}
final String ref;
final NamespaceContext nameSpaces;
public TreeIterator eAllContents() {
return null;
}
public EClass eClass() {
return null;
}
public EObject eContainer() {
return null;
}
public EStructuralFeature eContainingFeature() {
return null;
}
public EReference eContainmentFeature() {
return null;
}
public EList eContents() {
return null;
}
public EList eCrossReferences() {
return null;
}
public Object eGet(EStructuralFeature feature) {
return null;
}
public Object eGet(EStructuralFeature feature, boolean resolve) {
return null;
}
public boolean eIsProxy() {
return false;
}
public boolean eIsSet(EStructuralFeature feature) {
return false;
}
public Resource eResource() {
return null;
}
public void eSet(EStructuralFeature feature, Object newValue) {
}
public void eUnset(EStructuralFeature feature) {
}
public EList eAdapters() {
return null;
}
public boolean eDeliver() {
return false;
}
public void eNotify(Notification notification) {
}
public void eSetDeliver(boolean deliver) {
}
}
protected final EObject referent(Ref path) {
return referent(path.ref, path.nameSpaces);
}
protected final Type typeXSI() {
return typedXSI() ? typeHelper.getType(nameSpace, name) : null;
}
protected final Type globalElementType(String nameSpace, String name) {
return xsdHelper.getGlobalProperty(nameSpace, name, true).getType();
}
}