diff options
author | nash <nash@13f79535-47bb-0310-9956-ffa450edef68> | 2011-04-06 22:03:35 +0000 |
---|---|---|
committer | nash <nash@13f79535-47bb-0310-9956-ffa450edef68> | 2011-04-06 22:03:35 +0000 |
commit | 6d685c8e138af8d18bc71181ec630ccb9a17bdd9 (patch) | |
tree | 75276a59fe0a20761ea59ed312adaeb0a9006c81 /sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml | |
parent | a6eaa1356a4db131566cfe7f7e4c3fe81a0ad0b6 (diff) |
Tag for 1.6.2-RC1
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@1089647 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml')
52 files changed, 7413 insertions, 0 deletions
diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/BeanXMLStreamReaderImpl.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/BeanXMLStreamReaderImpl.java new file mode 100644 index 0000000000..3423d3e3b0 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/BeanXMLStreamReaderImpl.java @@ -0,0 +1,296 @@ +/* + * 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.sca.databinding.xml; + +import java.beans.BeanInfo; +import java.beans.Introspector; +import java.beans.PropertyDescriptor; +import java.lang.reflect.Array; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.Comparator; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.databinding.impl.SimpleTypeMapperImpl; +import org.apache.tuscany.sca.interfacedef.util.TypeInfo; + +/** + * @version $Rev$ $Date$ + */ +public class BeanXMLStreamReaderImpl extends XmlTreeStreamReaderImpl { + private static final Comparator<Accessor> COMPARATOR = new Comparator<Accessor>() { + public int compare(Accessor o1, Accessor o2) { + return o1.getName().compareTo(o2.getName()); + } + }; + + public static class BeanXmlNodeImpl extends SimpleXmlNodeImpl implements XmlNode { + private static final Object[] NULL = null; + private static final SimpleTypeMapperImpl MAPPER = new SimpleTypeMapperImpl(); + + public BeanXmlNodeImpl(Object bean) { + super(getName(bean == null ? null : bean.getClass()), bean); + } + + public BeanXmlNodeImpl(QName name, Object bean) { + super(name, bean); + } + + private static boolean isSimpleType(Class<?> javaType) { + return SimpleTypeMapperImpl.getXMLType(javaType) != null; + } + + private static String getStringValue(Object o) { + if (o == null) { + return null; + } + TypeInfo info = SimpleTypeMapperImpl.getXMLType(o.getClass()); + if (info != null) { + return MAPPER.toXMLLiteral(info.getQName(), o, null); + } else { + return String.valueOf(o); + } + } + + @Override + public Iterator<XmlNode> children() { + if (name == null) { + return null; + } + if (value == null) { + return super.children(); + } + if (isSimpleType(value.getClass())) { + XmlNode textNode = new BeanXmlNodeImpl(null, value); + return Arrays.asList(textNode).iterator(); + } + if (Map.class.isAssignableFrom(value.getClass())) { + List<XmlNode> entries = new ArrayList<XmlNode>(); + QName entryName = new QName(name.getNamespaceURI(), "entry"); + Map map = (Map)value; + if (map != null) { + for (Object e : map.entrySet()) { + Map.Entry entry = (Map.Entry)e; + entries.add(new BeanXmlNodeImpl(entryName, entry)); + } + } + return entries.iterator(); + } + try { + Map<String, Accessor> accessorMap = getAccessors(value); + List<Accessor> accessorList = new ArrayList<Accessor>(accessorMap.values()); + Collections.sort(accessorList, COMPARATOR); + + List<XmlNode> props = new ArrayList<XmlNode>(); + for (Accessor accessor : accessorList) { + Class<?> pType = accessor.getType(); + + QName pName = new QName(name.getNamespaceURI(), accessor.getName()); + Object pValue = accessor.getValue(); + if (pType.isArray()) { + if (pValue != null) { + int i1 = Array.getLength(pValue); + for (int j = 0; j < i1; j++) { + Object o = Array.get(pValue, j); + props.add(new BeanXmlNodeImpl(pName, o)); + } + } else { + // TODO: How to handle null? + } + } else if (Collection.class.isAssignableFrom(pType)) { + Collection objList = (Collection)pValue; + if (objList != null && objList.size() > 0) { + for (Iterator j = objList.iterator(); j.hasNext();) { + Object o = j.next(); + props.add(new BeanXmlNodeImpl(pName, o)); + } + + } else { + // How to handle null + } + } else { + props.add(new BeanXmlNodeImpl(pName, pValue)); + } + } + return props.iterator(); + } catch (Exception e) { + throw new IllegalArgumentException(e); + } + } + + @Override + public QName getName() { + return name; + } + + @Override + public String getValue() { + return getStringValue(value); + } + + private static String getPackageName(Class<?> cls) { + String name = cls.getName(); + int index = name.lastIndexOf('.'); + return index == -1 ? "" : name.substring(0, index); + } + + public static QName getName(Class<?> cls) { + if (cls == null) { + return null; + } + + String packageName = getPackageName(cls); + + if ("".equals(packageName)) { + return new QName("", cls.getSimpleName()); + } + StringBuffer ns = new StringBuffer("http://"); + String[] names = packageName.split("\\."); + for (int i = names.length - 1; i >= 0; i--) { + ns.append(names[i]); + if (i != 0) { + ns.append('.'); + } + } + ns.append('/'); + return new QName(ns.toString(), cls.getSimpleName()); + } + + } + + public BeanXMLStreamReaderImpl(QName name, Object bean) { + super(getXmlNode(name, bean)); + } + + private static BeanXmlNodeImpl getXmlNode(QName name, Object bean) { + BeanXmlNodeImpl root = null; + if (name != null) { + root = new BeanXmlNodeImpl(name, bean); + } else { + root = new BeanXmlNodeImpl(bean); + } + return root; + } + + public static interface Accessor { + String getName(); + + Class<?> getType(); + + Object getValue() throws Exception; + + void setValue(Object value) throws Exception; + } + + private static class FieldAccessor implements Accessor { + private Object target; + private Field field; + + public FieldAccessor(Object target, Field field) { + super(); + this.target = target; + this.field = field; + this.field.setAccessible(true); + } + + public String getName() { + return field.getName(); + } + + public Object getValue() throws Exception { + return field.get(target); + } + + public void setValue(Object value) throws Exception { + field.set(target, value); + } + + public Class<?> getType() { + return field.getType(); + } + + } + + private static class PropertyAccessor implements Accessor { + private Object target; + private PropertyDescriptor prop; + + public PropertyAccessor(Object target, PropertyDescriptor prop) { + super(); + this.target = target; + this.prop = prop; + } + + public String getName() { + return prop.getName(); + } + + public Class<?> getType() { + return prop.getPropertyType(); + } + + public Object getValue() throws Exception { + Method getter = prop.getReadMethod(); + if (getter != null) { + getter.setAccessible(true); + return getter.invoke(target); + } + throw new IllegalAccessException("The property cannot be read: " + getName()); + } + + public void setValue(Object value) throws Exception { + Method setter = prop.getWriteMethod(); + if (setter != null) { + setter.setAccessible(true); + setter.invoke(target); + } + throw new IllegalAccessException("The property cannot be written: " + getName()); + } + + } + + private static Map<String, Accessor> getAccessors(Object target) throws Exception { + if (target == null) { + return Collections.emptyMap(); + } + Map<String, Accessor> map = new HashMap<String, Accessor>(); + Class<?> type = target.getClass(); + for (Field f : type.getFields()) { + map.put(f.getName(), new FieldAccessor(target, f)); + } + BeanInfo info = Introspector.getBeanInfo(type, Object.class); + for (PropertyDescriptor p : info.getPropertyDescriptors()) { + // if (p.getReadMethod() != null && p.getWriteMethod() != null) { + map.put(p.getName(), new PropertyAccessor(target, p)); + // } + } + return map; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMDataBinding.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMDataBinding.java new file mode 100644 index 0000000000..e029604722 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMDataBinding.java @@ -0,0 +1,71 @@ +/* + * 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.sca.databinding.xml; + + +import javax.xml.namespace.QName; + +import org.apache.tuscany.sca.databinding.WrapperHandler; +import org.apache.tuscany.sca.databinding.impl.BaseDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.w3c.dom.Node; + +/** + * DOM DataBinding + * + * @version $Rev$ $Date$ + */ +public class DOMDataBinding extends BaseDataBinding { + public static final String NAME = Node.class.getName(); + + public static final String ROOT_NAMESPACE = "http://tuscany.apache.org/xmlns/sca/databinding/dom/1.0"; + public static final QName ROOT_ELEMENT = new QName(ROOT_NAMESPACE, "root"); + + public DOMDataBinding() { + super(NAME, Node.class); + } + + @Override + public WrapperHandler getWrapperHandler() { + return new DOMWrapperHandler(); + } + + @Override + public Object copy(Object source, DataType dataType, Operation operation) { + if (Node.class.isAssignableFrom(source.getClass())) { + Node nodeSource = (Node)source; + return nodeSource.cloneNode(true); + } + return super.copy(source, dataType, operation); + } + + @Override + public boolean introspect(DataType type, Operation operation) { + if (Node.class.isAssignableFrom(type.getPhysical())) { + if (type.getLogical() == null) { + type.setLogical(new XMLType(ROOT_ELEMENT, null)); + } + type.setDataBinding(NAME); + return true; + } + return false; + } +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMWrapperHandler.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMWrapperHandler.java new file mode 100644 index 0000000000..19a8fe32d3 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMWrapperHandler.java @@ -0,0 +1,146 @@ +/* + * 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.sca.databinding.xml; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import javax.xml.namespace.QName; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.WrapperHandler; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; +import org.apache.tuscany.sca.interfacedef.util.ElementInfo; +import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +public class DOMWrapperHandler implements WrapperHandler<Node> { + + public DOMWrapperHandler() { + super(); + } + + public Node create(Operation operation, boolean input) { + try { + WrapperInfo inputWrapperInfo = operation.getInputWrapper(); + WrapperInfo outputWrapperInfo = operation.getOutputWrapper(); + ElementInfo element = input ? inputWrapperInfo.getWrapperElement() : outputWrapperInfo.getWrapperElement(); + + Document document = DOMHelper.newDocument(); + QName name = element.getQName(); + return DOMHelper.createElement(document, name); + } catch (ParserConfigurationException e) { + throw new TransformationException(e); + } + } + + public void setChildren(Node wrapper, + Object[] childObjects, + Operation operation, boolean input) { + List<ElementInfo> childElements = input? operation.getInputWrapper().getChildElements(): + operation.getOutputWrapper().getChildElements(); + for (int i = 0; i < childElements.size(); i++) { + setChild(wrapper, i, childElements.get(i), childObjects[i]); + } + + } + public void setChild(Node wrapper, int i, ElementInfo childElement, Object value) { + Node node = (Node)value; + if (node.getNodeType() == Node.DOCUMENT_NODE) { + node = ((Document)node).getDocumentElement(); + } + wrapper.appendChild(wrapper.getOwnerDocument().importNode(node, true)); + } + + public List getChildren(Node wrapper, Operation operation, boolean input) { + assert wrapper != null; + List<ElementInfo> childElements = input? operation.getInputWrapper().getChildElements(): + operation.getOutputWrapper().getChildElements(); + if (wrapper.getNodeType() == Node.DOCUMENT_NODE) { + wrapper = ((Document)wrapper).getDocumentElement(); + } + List<Node> elements = new ArrayList<Node>(); + NodeList nodes = wrapper.getChildNodes(); + for (int j = 0; j < nodes.getLength(); j++) { + Node node = nodes.item(j); + if (node.getNodeType() == Node.ELEMENT_NODE) { + elements.add(node); + } + } + return elements; + } + + /** + * @see org.apache.tuscany.sca.databinding.WrapperHandler#getWrapperType(Operation, boolean) + */ + public DataType getWrapperType(Operation operation, boolean input) { + WrapperInfo inputWrapperInfo = operation.getInputWrapper(); + WrapperInfo outputWrapperInfo = operation.getOutputWrapper(); + ElementInfo element = input ? inputWrapperInfo.getWrapperElement() : outputWrapperInfo.getWrapperElement(); + DataType<XMLType> wrapperType = + new DataTypeImpl<XMLType>(DOMDataBinding.NAME, Node.class, new XMLType(element)); + return wrapperType; + } + + public boolean isInstance(Object wrapperObj, + Operation operation, + boolean input) { + WrapperInfo inputWrapperInfo = operation.getInputWrapper(); + WrapperInfo outputWrapperInfo = operation.getOutputWrapper(); + ElementInfo element = input ? inputWrapperInfo.getWrapperElement() : outputWrapperInfo.getWrapperElement(); + + List<ElementInfo> childElements = input? inputWrapperInfo.getChildElements(): + outputWrapperInfo.getChildElements(); + + Node wrapper = (Node)wrapperObj; + if (wrapper.getNodeType() == Node.DOCUMENT_NODE) { + wrapper = ((Document)wrapper).getDocumentElement(); + } + QName elementName = new QName(wrapper.getNamespaceURI(), wrapper.getLocalName()); + if (!element.getQName().equals(elementName)) { + return false; + } + Set<QName> names = new HashSet<QName>(); + for (ElementInfo e : childElements) { + names.add(e.getQName()); + } + NodeList nodes = wrapper.getChildNodes(); + for (int j = 0; j < nodes.getLength(); j++) { + Node node = nodes.item(j); + if (node.getNodeType() == Node.ELEMENT_NODE) { + elementName = new QName(wrapper.getNamespaceURI(), wrapper.getLocalName()); + if (!names.contains(elementName)) { + return false; + } + } + } + return true; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMXMLStreamReader.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMXMLStreamReader.java new file mode 100644 index 0000000000..8c7a742cdd --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMXMLStreamReader.java @@ -0,0 +1,36 @@ +/* + * 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.sca.databinding.xml; + +import org.w3c.dom.Node; + +public class DOMXMLStreamReader extends XmlTreeStreamReaderImpl { + + public DOMXMLStreamReader(Node node) { + super(new DOMXmlNodeImpl(node)); + switch (node.getNodeType()) { + case Node.DOCUMENT_NODE: + break; + case Node.ELEMENT_NODE: + break; + default: + throw new IllegalArgumentException("Illegal node type: " + node); + } + } +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMXmlNodeImpl.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMXmlNodeImpl.java new file mode 100644 index 0000000000..507c141c33 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DOMXmlNodeImpl.java @@ -0,0 +1,156 @@ +/* + * 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.sca.databinding.xml; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; + +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; + +/** + * @version $Rev$ $Date$ + */ +public class DOMXmlNodeImpl implements XmlNode { + private Node node; + private Map<String, String> namespaces; + private Type type; + + /** + * @param element + */ + public DOMXmlNodeImpl(Node element) { + super(); + if (element.getNodeType() == Node.DOCUMENT_NODE) { + this.node = ((Document)element).getDocumentElement(); + } else { + this.node = element; + } + switch (node.getNodeType()) { + case Node.CDATA_SECTION_NODE: + this.type = Type.CHARACTERS; + break; + case Node.ELEMENT_NODE: + this.type = Type.ELEMENT; + break; + case Node.TEXT_NODE: + this.type = Type.CHARACTERS; + break; + } + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#attributes() + */ + public List<XmlNode> attributes() { + if (type != Type.ELEMENT) { + return null; + } + NamedNodeMap attrs = node.getAttributes(); + List<XmlNode> xmlAttrs = new ArrayList<XmlNode>(); + for (int i = 0; i < attrs.getLength(); i++) { + Attr attr = (Attr)attrs.item(i); + if (!attr.getName().equals("xmlns") && !attr.getName().startsWith("xmlns:")) { + xmlAttrs.add(new SimpleXmlNodeImpl(getQName(attr), attr.getValue(), XmlNode.Type.ATTRIBUTE)); + } + } + return xmlAttrs; + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#children() + */ + public Iterator<XmlNode> children() { + if (type != Type.ELEMENT) { + return null; + } + NodeList nodes = node.getChildNodes(); + List<XmlNode> xmlNodes = new ArrayList<XmlNode>(); + for (int i = 0; i < nodes.getLength(); i++) { + Node child = (Node)nodes.item(i); + int nodeType = child.getNodeType(); + if (nodeType == Node.ELEMENT_NODE || nodeType == Node.TEXT_NODE || nodeType == Node.CDATA_SECTION_NODE) { + xmlNodes.add(new DOMXmlNodeImpl(child)); + } + } + return xmlNodes.iterator(); + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#getName() + */ + public QName getName() { + return getQName(node); + } + + private static QName getQName(Node node) { + int type = node.getNodeType(); + if (type == Node.ELEMENT_NODE || type == Node.ATTRIBUTE_NODE) { + String ns = node.getNamespaceURI(); + String prefix = node.getPrefix(); + String localName = node.getLocalName(); + return new QName(ns == null ? "" : ns, localName, prefix == null ? "" : prefix); + } + return null; + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#getValue() + */ + public String getValue() { + return node.getNodeValue(); + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#namespaces() + */ + public Map<String, String> namespaces() { + if (type != Type.ELEMENT) { + return null; + } + if (namespaces == null) { + namespaces = new HashMap<String, String>(); + NamedNodeMap attrs = node.getAttributes(); + for (int i = 0; i < attrs.getLength(); i++) { + Attr attr = (Attr)attrs.item(i); + if ("xmlns".equals(attr.getPrefix())) { + namespaces.put(attr.getLocalName(), attr.getValue()); + } + if ("xmlns".equals(attr.getName())) { + namespaces.put("", attr.getValue()); + } + } + } + return namespaces; + } + + public Type getType() { + return type; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DelegatingNamespaceContext.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DelegatingNamespaceContext.java new file mode 100644 index 0000000000..7f49a50e1e --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/DelegatingNamespaceContext.java @@ -0,0 +1,310 @@ +/* + * 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.sca.databinding.xml; + +import java.util.ArrayList; +import java.util.EmptyStackException; +import java.util.Iterator; +import java.util.List; + +import javax.xml.namespace.NamespaceContext; + +public class DelegatingNamespaceContext implements NamespaceContext { + private static int count; + + private class WrappingIterator implements Iterator { + + private Iterator containedIterator; + + public WrappingIterator(Iterator containedIterator) { + this.containedIterator = containedIterator; + } + + public Iterator getContainedIterator() { + return containedIterator; + } + + public boolean hasNext() { + return containedIterator.hasNext(); + } + + public Object next() { + return containedIterator.next(); + } + + /** + * As per the contract on the API of Namespace context the returned iterator should be immutable + */ + public void remove() { + throw new UnsupportedOperationException(); + } + + public void setContainedIterator(Iterator containedIterator) { + this.containedIterator = containedIterator; + } + } + + private NamespaceContext parentNsContext; + + private FastStack<String> prefixStack = new FastStack<String>(); + + // Keep two ArrayLists for the prefixes and namespaces. They should be in + // sync + // since the index of the entry will be used to relate them + // use the minimum initial capacity to let things handle memory better + + private FastStack<String> uriStack = new FastStack<String>(); + + /** + * Generates a unique namespace prefix that is not in the scope of the NamespaceContext + * + * @return string + */ + public String generateUniquePrefix() { + String prefix = "p" + count++; + // null should be returned if the prefix is not bound! + while (getNamespaceURI(prefix) != null) { + prefix = "p" + count++; + } + + return prefix; + } + + public String getNamespaceURI(String prefix) { + // do the corrections as per the Javadoc + int index = prefixStack.search(prefix); + if (index != -1) { + return uriStack.get(index); + } + if (parentNsContext != null) { + return parentNsContext.getPrefix(prefix); + } + return null; + } + + public NamespaceContext getParentNsContext() { + return parentNsContext; + } + + public String getPrefix(String uri) { + // do the corrections as per the Javadoc + int index = uriStack.search(uri); + if (index != -1) { + return prefixStack.get(index); + } + + if (parentNsContext != null) { + return parentNsContext.getPrefix(uri); + } + return null; + } + + public Iterator getPrefixes(String uri) { + // create an ArrayList that contains the relevant prefixes + String[] uris = uriStack.toArray(new String[uriStack.size()]); + List<String> tempList = new ArrayList<String>(); + for (int i = uris.length - 1; i >= 0; i--) { + if (uris[i].equals(uri)) { + tempList.add(prefixStack.get(i)); + // we assume that array conversion preserves the order + } + } + // by now all the relevant prefixes are collected + // make a new iterator and provide a wrapper iterator to + // obey the contract on the API + return new WrappingIterator(tempList.iterator()); + } + + /** + * Pop a namespace + */ + public void popNamespace() { + prefixStack.pop(); + uriStack.pop(); + } + + /** + * Register a namespace in this context + * + * @param prefix + * @param uri + */ + public void pushNamespace(String prefix, String uri) { + prefixStack.push(prefix); + uriStack.push(uri); + + } + + public void setParentNsContext(NamespaceContext parentNsContext) { + this.parentNsContext = parentNsContext; + } + + /** + * An implementation of the {@link java.util.Stack} API that is based on an <code>ArrayList</code> instead of a + * <code>Vector</code>, so it is not synchronized to protect against multi-threaded access. The implementation is + * therefore operates faster in environments where you do not need to worry about multiple thread contention. + * <p> + * The removal order of an <code>ArrayStack</code> is based on insertion order: The most recently added element is + * removed first. The iteration order is <i>not</i> the same as the removal order. The iterator returns elements + * from the bottom up, whereas the {@link #remove()} method removes them from the top down. + * <p> + * Unlike <code>Stack</code>, <code>ArrayStack</code> accepts null entries. + */ + public static class FastStack<T> extends ArrayList<T> { + + /** Ensure Serialization compatibility */ + private static final long serialVersionUID = 2130079159931574599L; + + /** + * Constructs a new empty <code>ArrayStack</code>. The initial size is controlled by <code>ArrayList</code> + * and is currently 10. + */ + public FastStack() { + super(); + } + + /** + * Constructs a new empty <code>ArrayStack</code> with an initial size. + * + * @param initialSize the initial size to use + * @throws IllegalArgumentException if the specified initial size is negative + */ + public FastStack(int initialSize) { + super(initialSize); + } + + /** + * Return <code>true</code> if this stack is currently empty. + * <p> + * This method exists for compatibility with <code>java.util.Stack</code>. New users of this class should use + * <code>isEmpty</code> instead. + * + * @return true if the stack is currently empty + */ + public boolean empty() { + return isEmpty(); + } + + /** + * Returns the top item off of this stack without removing it. + * + * @return the top item on the stack + * @throws EmptyStackException if the stack is empty + */ + public T peek() throws EmptyStackException { + int n = size(); + if (n <= 0) { + throw new EmptyStackException(); + } else { + return get(n - 1); + } + } + + /** + * Returns the n'th item down (zero-relative) from the top of this stack without removing it. + * + * @param n the number of items down to go + * @return the n'th item on the stack, zero relative + * @throws EmptyStackException if there are not enough items on the stack to satisfy this request + */ + public T peek(int n) throws EmptyStackException { + int m = (size() - n) - 1; + if (m < 0) { + throw new EmptyStackException(); + } else { + return get(m); + } + } + + /** + * Pops the top item off of this stack and return it. + * + * @return the top item on the stack + * @throws EmptyStackException if the stack is empty + */ + public T pop() throws EmptyStackException { + int n = size(); + if (n <= 0) { + throw new EmptyStackException(); + } else { + return remove(n - 1); + } + } + + /** + * Pushes a new item onto the top of this stack. The pushed item is also returned. This is equivalent to calling + * <code>add</code>. + * + * @param item the item to be added + * @return the item just pushed + */ + public Object push(T item) { + add(item); + return item; + } + + /** + * Returns the top-most index for the object in the stack + * + * @param object the object to be searched for + * @return top-most index, or -1 if not found + */ + public int search(T object) { + int i = size() - 1; // Current index + while (i >= 0) { + T current = get(i); + if ((object == null && current == null) || (object != null && object.equals(current))) { + return i; + } + i--; + } + return -1; + } + + /** + * Returns the element on the top of the stack. + * + * @return the element on the top of the stack + * @throws EmptyStackException if the stack is empty + */ + public T get() { + int size = size(); + if (size == 0) { + throw new EmptyStackException(); + } + return get(size - 1); + } + + /** + * Removes the element on the top of the stack. + * + * @return the removed element + * @throws EmptyStackException if the stack is empty + */ + public T remove() { + int size = size(); + if (size == 0) { + throw new EmptyStackException(); + } + return remove(size - 1); + } + + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputSource2Node.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputSource2Node.java new file mode 100644 index 0000000000..5f583da283 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputSource2Node.java @@ -0,0 +1,67 @@ +/* + * 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.sca.databinding.xml; + +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.stream.StreamSource; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +/** + * Push DOM InputSource to Node + * + * @version $Rev$ $Date$ + */ +public class InputSource2Node extends BaseTransformer<InputSource, Node> implements + PullTransformer<InputSource, Node> { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public Node transform(InputSource source, TransformationContext context) { + try { + Source streamSource = new StreamSource(source.getCharacterStream()); + DOMResult result = new DOMResult(); + TRANSFORMER.transform(streamSource, result, context); + return result.getNode(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public Class<InputSource> getSourceType() { + return InputSource.class; + } + + @Override + public Class<Node> getTargetType() { + return Node.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputSource2SAX.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputSource2SAX.java new file mode 100644 index 0000000000..39116ba4a1 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputSource2SAX.java @@ -0,0 +1,65 @@ +/* + * 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.sca.databinding.xml; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * Push InputSource to SAX + * + * @version $Rev$ $Date$ + */ +public class InputSource2SAX extends BaseTransformer<InputSource, ContentHandler> implements + PushTransformer<InputSource, ContentHandler> { + + public void transform(InputSource source, ContentHandler target, TransformationContext context) { + try { + XMLReader reader = XMLReaderFactory.createXMLReader(); + reader.setFeature("http://xml.org/sax/features/namespaces", true); + reader.setFeature("http://xml.org/sax/features/namespace-prefixes", false); + reader.setContentHandler(target); + reader.parse(source); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public Class<InputSource> getSourceType() { + return InputSource.class; + } + + @Override + public Class<ContentHandler> getTargetType() { + return ContentHandler.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputStream2Node.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputStream2Node.java new file mode 100644 index 0000000000..e40c3006fb --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputStream2Node.java @@ -0,0 +1,69 @@ +/* + * 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.sca.databinding.xml; + +import java.io.InputStream; + +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.sax.SAXSource; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +/** + * Push DOM InputSource to Node + * + * @version $Rev$ $Date$ + */ +public class InputStream2Node extends BaseTransformer<InputStream, Node> implements + PullTransformer<InputStream, Node> { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public Node transform(InputStream source, TransformationContext context) { + try { + Source streamSource = new SAXSource(new InputSource(source)); + DOMResult result = new DOMResult(); + TRANSFORMER.transform(streamSource, result, context); + return result.getNode(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public Class<InputStream> getSourceType() { + return InputStream.class; + } + + @Override + public Class<Node> getTargetType() { + return Node.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputStream2SAX.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputStream2SAX.java new file mode 100644 index 0000000000..3b7bd3088a --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/InputStream2SAX.java @@ -0,0 +1,64 @@ +/* + * 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.sca.databinding.xml; + +import java.io.InputStream; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; +import org.xml.sax.XMLReader; +import org.xml.sax.helpers.XMLReaderFactory; + +/** + * Push InputStream to SAX + * + * @version $Rev$ $Date$ + */ +public class InputStream2SAX extends BaseTransformer<InputStream, ContentHandler> implements + PushTransformer<InputStream, ContentHandler> { + public void transform(InputStream source, ContentHandler target, TransformationContext context) { + try { + XMLReader reader = XMLReaderFactory.createXMLReader(); + reader.setContentHandler(target); + reader.parse(new InputSource(source)); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public Class<InputStream> getSourceType() { + return InputStream.class; + } + + @Override + public Class<ContentHandler> getTargetType() { + return ContentHandler.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NameValueArrayStreamReader.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NameValueArrayStreamReader.java new file mode 100644 index 0000000000..5a31d9db91 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NameValueArrayStreamReader.java @@ -0,0 +1,403 @@ +/* + * 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.sca.databinding.xml; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +public class NameValueArrayStreamReader implements XMLFragmentStreamReader { + + private static final int START_ELEMENT_STATE = 0; + private static final int TEXT_STATE = 1; + private static final int END_ELEMENT_STATE = 2; + private static final int FINAL_END_ELEMENT_STATE = 3; + private static final int START_ELEMENT_STATE_WITH_NULL = 4; + + private DelegatingNamespaceContext namespaceContext = new DelegatingNamespaceContext(); + // the index of the array + private int arrayIndex; + + private QName name; + private String[] values; + + // start element is the default state + private int state = START_ELEMENT_STATE; + + public NameValueArrayStreamReader(QName name, String[] values) { + this.name = name; + this.values = values; + } + + public void setParentNamespaceContext(NamespaceContext nsContext) { + this.namespaceContext.setParentNsContext(nsContext); + } + + public void init() { + // TODO what if the QName namespace has not been declared + } + + public Object getProperty(String string) throws IllegalArgumentException { + return null; + } + + /** + * @throws XMLStreamException + */ + public int next() throws XMLStreamException { + switch (state) { + case START_ELEMENT_STATE: + if (values.length > 0) { + state = TEXT_STATE; + return CHARACTERS; + } else { + state = FINAL_END_ELEMENT_STATE; + return END_ELEMENT; + } + + case START_ELEMENT_STATE_WITH_NULL: + if (arrayIndex == (values.length - 1)) { + state = FINAL_END_ELEMENT_STATE; + } else { + state = END_ELEMENT_STATE; + } + return END_ELEMENT; + case FINAL_END_ELEMENT_STATE: + // oops, not supposed to happen! + throw new XMLStreamException("end already reached!"); + case END_ELEMENT_STATE: + // we've to have more values since this is not the + // last value + // increment the counter + arrayIndex++; + if (values[arrayIndex] == null) { + state = START_ELEMENT_STATE_WITH_NULL; + } else { + state = START_ELEMENT_STATE; + } + return START_ELEMENT; + case TEXT_STATE: + if (arrayIndex == (values.length - 1)) { + state = FINAL_END_ELEMENT_STATE; + return END_ELEMENT; + } else { + state = END_ELEMENT_STATE; + return END_ELEMENT; + } + + default: + throw new XMLStreamException("unknown event type!"); + } + } + + public void require(int i, String string, String string1) throws XMLStreamException { + // nothing done here + } + + public String getElementText() throws XMLStreamException { + return null; // not implemented + } + + public int nextTag() throws XMLStreamException { + return 0; // not implemented + } + + public String getAttributeValue(String string, String string1) { + if (state == TEXT_STATE) { + // TODO something + return null; + } else { + return null; + } + + } + + public int getAttributeCount() { + if (state == START_ELEMENT_STATE_WITH_NULL) { + return 1; + } + if (state == START_ELEMENT_STATE) { + return 0; + } else { + throw new IllegalStateException(); + } + + } + + public QName getAttributeName(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return NIL_QNAME; + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeNamespace(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return NIL_QNAME.getNamespaceURI(); + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeLocalName(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return NIL_QNAME.getLocalPart(); + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributePrefix(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return NIL_QNAME.getPrefix(); + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeType(int i) { + return null; // not implemented + } + + public String getAttributeValue(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && i == 0) { + return NIL_VALUE_TRUE; + } + if (state == START_ELEMENT_STATE) { + return null; + } else { + throw new IllegalStateException(); + } + } + + public boolean isAttributeSpecified(int i) { + return false; // not supported + } + + public int getNamespaceCount() { + if (state == START_ELEMENT_STATE_WITH_NULL && isXsiNamespacePresent()) { + return 1; + } else { + return 0; + } + + } + + public String getNamespacePrefix(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && isXsiNamespacePresent() && i == 0) { + return NIL_QNAME.getPrefix(); + } else { + return null; + } + } + + public String getNamespaceURI(int i) { + if (state == START_ELEMENT_STATE_WITH_NULL && isXsiNamespacePresent() && i == 0) { + return NIL_QNAME.getNamespaceURI(); + } else { + return null; + } + } + + public NamespaceContext getNamespaceContext() { + return this.namespaceContext; + } + + public boolean isDone() { + return state == FINAL_END_ELEMENT_STATE; + } + + public int getEventType() { + switch (state) { + case START_ELEMENT_STATE: + return START_ELEMENT; + case END_ELEMENT_STATE: + return END_ELEMENT; + case TEXT_STATE: + return CHARACTERS; + case FINAL_END_ELEMENT_STATE: + return END_ELEMENT; + default: + throw new UnsupportedOperationException(); + // we've no idea what this is!!!!! + } + + } + + public String getText() { + if (state == TEXT_STATE) { + return values[arrayIndex]; + } else { + throw new IllegalStateException(); + } + } + + public char[] getTextCharacters() { + if (state == TEXT_STATE) { + return values[arrayIndex].toCharArray(); + } else { + throw new IllegalStateException(); + } + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + // not implemented + throw new UnsupportedOperationException(); + } + + public int getTextStart() { + if (state == TEXT_STATE) { + return 0; + } else { + throw new IllegalStateException(); + } + } + + public int getTextLength() { + if (state == TEXT_STATE) { + return values[arrayIndex].length(); + } else { + throw new IllegalStateException(); + } + + } + + public String getEncoding() { + return null; + } + + public boolean hasText() { + return state == TEXT_STATE; + } + + public Location getLocation() { + return null; // not supported + } + + public QName getName() { + if (state != TEXT_STATE) { + return name; + } else { + return null; + } + } + + public String getLocalName() { + if (state != TEXT_STATE) { + return name.getLocalPart(); + } else { + return null; + } + } + + public boolean hasName() { + return state != TEXT_STATE; + + } + + public String getNamespaceURI() { + if (state != TEXT_STATE) { + return name.getNamespaceURI(); + } else { + return null; + } + + } + + public String getPrefix() { + if (state != TEXT_STATE) { + return name.getPrefix(); + } else { + return null; + } + } + + public String getVersion() { + return null; // TODO 1.0 ? + } + + public boolean isStandalone() { + return false; + } + + public boolean standaloneSet() { + return false; + } + + public String getCharacterEncodingScheme() { + return null; + } + + public String getPITarget() { + return null; + } + + public String getPIData() { + return null; + } + + public boolean hasNext() throws XMLStreamException { + return state != FINAL_END_ELEMENT_STATE; + } + + public void close() throws XMLStreamException { + // Do nothing - we've nothing to free here + } + + public String getNamespaceURI(String prefix) { + return namespaceContext.getNamespaceURI(prefix); + } + + public boolean isStartElement() { + return state == START_ELEMENT_STATE; + } + + public boolean isEndElement() { + return state == END_ELEMENT_STATE; + } + + public boolean isCharacters() { + return state == TEXT_STATE; + } + + public boolean isWhiteSpace() { + return false; // no whitespaces here + } + + /** + * Test whether the xsi namespace is present + */ + private boolean isXsiNamespacePresent() { + return namespaceContext.getNamespaceURI(NIL_QNAME.getPrefix()) != null; + } +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NameValuePairStreamReader.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NameValuePairStreamReader.java new file mode 100644 index 0000000000..fdc3c4139b --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NameValuePairStreamReader.java @@ -0,0 +1,347 @@ +/* + * 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.sca.databinding.xml; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + + +public class NameValuePairStreamReader implements XMLFragmentStreamReader { + + private static final int START_ELEMENT_STATE = 0; + private static final int TEXT_STATE = 1; + private static final int END_ELEMENT_STATE = 2; + + private DelegatingNamespaceContext namespaceContext = new DelegatingNamespaceContext(); + + private QName name; + private String value; + + private int state = START_ELEMENT_STATE; + // initiate at the start element state + + // keeps track whether the namespace is declared + // false by default + private boolean nsDeclared; + + public NameValuePairStreamReader(QName name, String value) { + this.name = name; + this.value = value; + } + + public Object getProperty(String key) throws IllegalArgumentException { + return null; + } + + public int next() throws XMLStreamException { + // no need to handle null here. it should have been handled + // already + switch (state) { + case START_ELEMENT_STATE: + state = TEXT_STATE; + return CHARACTERS; + case END_ELEMENT_STATE: + // oops, not supposed to happen! + throw new XMLStreamException("end already reached!"); + case TEXT_STATE: + state = END_ELEMENT_STATE; + return END_ELEMENT; + default: + throw new XMLStreamException("unknown event type!"); + } + } + + public void require(int i, String string, String string1) throws XMLStreamException { + // not implemented + } + + public String getElementText() throws XMLStreamException { + if (state == START_ELEMENT) { + // move to the end state and return the value + state = END_ELEMENT_STATE; + return value; + } else { + throw new XMLStreamException(); + } + + } + + public int nextTag() throws XMLStreamException { + return 0; // TODO + } + + public boolean hasNext() throws XMLStreamException { + return state != END_ELEMENT_STATE; + } + + public void close() throws XMLStreamException { + // Do nothing - we've nothing to free here + } + + public String getNamespaceURI(String prefix) { + return namespaceContext.getNamespaceURI(prefix); + } + + public boolean isStartElement() { + return state == START_ELEMENT_STATE; + } + + public boolean isEndElement() { + return state == END_ELEMENT_STATE; + } + + public boolean isCharacters() { + return state == TEXT_STATE; + } + + public boolean isWhiteSpace() { + return false; // no whitespaces here + } + + public String getAttributeValue(String string, String string1) { + return null; + } + + public int getAttributeCount() { + return 0; + } + + public QName getAttributeName(int i) { + return null; + } + + public String getAttributeNamespace(int i) { + return null; + } + + public String getAttributeLocalName(int i) { + return null; + } + + public String getAttributePrefix(int i) { + return null; + } + + public String getAttributeType(int i) { + return null; + } + + public String getAttributeValue(int i) { + return null; + } + + public boolean isAttributeSpecified(int i) { + return false; // no attributes here + } + + public int getNamespaceCount() { + return nsDeclared ? 1 : 0; + } + + public String getNamespacePrefix(int i) { + return (nsDeclared && i == 0) ? name.getPrefix() : null; + } + + public String getNamespaceURI(int i) { + return (nsDeclared && i == 0) ? name.getNamespaceURI() : null; + } + + public NamespaceContext getNamespaceContext() { + return this.namespaceContext; + } + + public int getEventType() { + switch (state) { + case START_ELEMENT_STATE: + return START_ELEMENT; + case END_ELEMENT_STATE: + return END_ELEMENT; + case TEXT_STATE: + return CHARACTERS; + default: + throw new UnsupportedOperationException(); + // we've no idea what this is!!!!! + } + + } + + public String getText() { + if (state == TEXT_STATE) { + return value; + } else { + throw new IllegalStateException(); + } + } + + public char[] getTextCharacters() { + if (state == TEXT_STATE) { + return value.toCharArray(); + } else { + throw new IllegalStateException(); + } + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + // not implemented + throw new UnsupportedOperationException(); + } + + public int getTextStart() { + if (state == TEXT_STATE) { + return 0; + } else { + throw new IllegalStateException(); + } + } + + public int getTextLength() { + if (state == TEXT_STATE) { + return value.length(); + } else { + throw new IllegalStateException(); + } + + } + + public String getEncoding() { + return null; + } + + public boolean hasText() { + return state == TEXT_STATE; + } + + public Location getLocation() { + return new Location() { + public int getLineNumber() { + return 0; + } + + public int getColumnNumber() { + return 0; + } + + public int getCharacterOffset() { + return 0; + } + + public String getPublicId() { + return null; + } + + public String getSystemId() { + return null; + } + }; + } + + public QName getName() { + if (state != TEXT_STATE) { + return name; + } else { + return null; + } + } + + public String getLocalName() { + if (state != TEXT_STATE) { + return name.getLocalPart(); + } else { + return null; + } + } + + public boolean hasName() { + return state != TEXT_STATE; + + } + + public String getNamespaceURI() { + if (state != TEXT_STATE) { + return name.getNamespaceURI(); + } else { + return null; + } + + } + + public String getPrefix() { + if (state != TEXT_STATE) { + return name.getPrefix(); + } else { + return null; + } + } + + public String getVersion() { + return null; // TODO 1.0 ? + } + + public boolean isStandalone() { + return false; + } + + public boolean standaloneSet() { + return false; + } + + public String getCharacterEncodingScheme() { + return null; + } + + public String getPITarget() { + return null; + } + + public String getPIData() { + return null; + } + + public boolean isDone() { + return state == END_ELEMENT_STATE; + } + + public void setParentNamespaceContext(NamespaceContext nsContext) { + this.namespaceContext.setParentNsContext(nsContext); + } + + public void init() { + // just add the current elements namespace and prefix to the this + // elements nscontext + addToNsMap(name.getPrefix(), name.getNamespaceURI()); + + } + + /** + * @param prefix + * @param uri + */ + private void addToNsMap(String prefix, String uri) { + // TODO - need to fix this up to cater for cases where + // namespaces are having no prefixes + if (!uri.equals(namespaceContext.getNamespaceURI(prefix))) { + // this namespace is not there. Need to declare it + namespaceContext.pushNamespace(prefix, uri); + nsDeclared = true; + } + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NamedProperty.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NamedProperty.java new file mode 100644 index 0000000000..04d7d65a0d --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NamedProperty.java @@ -0,0 +1,59 @@ +/* + * 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.sca.databinding.xml; + +import java.util.Map; + +import javax.xml.namespace.QName; + +/** + * A named property + * + * @version $Rev$ $Date$ + */ +public class NamedProperty implements Map.Entry<QName, Object> { + private QName key; + + private Object value; + + public NamedProperty(QName key, Object value) { + this.key = key; + this.value = value; + } + + public NamedProperty(String key, Object value) { + this.key = new QName(key); + this.value = value; + } + + public QName getKey() { + return key; + } + + public Object getValue() { + return value; + } + + public Object setValue(Object value) { + Object v = this.value; + this.value = value; + return v; + } +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NilElementStreamReader.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NilElementStreamReader.java new file mode 100644 index 0000000000..abc4bf3785 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/NilElementStreamReader.java @@ -0,0 +1,279 @@ +/* + * 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.sca.databinding.xml; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; + +public class NilElementStreamReader implements XMLFragmentStreamReader { + + private static final int END_ELEMENT_STATE = 2; + + private static final int START_ELEMENT_STATE = 1; + private int currentState = START_ELEMENT; + + private QName elementQName; + + public NilElementStreamReader(QName elementQName) { + this.elementQName = elementQName; + } + + public void setParentNamespaceContext(NamespaceContext nsContext) { + // NOOP + } + + public void close() throws XMLStreamException { + // do nothing + } + + public int getAttributeCount() { + return 1; + } + + public String getAttributeLocalName(int i) { + return (i == 0) ? NIL_QNAME.getLocalPart() : null; + } + + public QName getAttributeName(int i) { + return (i == 0) ? NIL_QNAME : null; + } + + public String getAttributeNamespace(int i) { + return (i == 0) ? NIL_QNAME.getNamespaceURI() : null; + } + + public String getAttributePrefix(int i) { + return (i == 0) ? NIL_QNAME.getPrefix() : null; + } + + public String getAttributeType(int i) { + throw new UnsupportedOperationException(); + } + + public String getAttributeValue(int i) { + return (i == 0) ? NIL_VALUE_TRUE : null; + } + + public String getAttributeValue(String string, String string1) { + if (string == null && NIL_QNAME.getLocalPart().equals(string1)) { + return NIL_VALUE_TRUE; + } + return null; + } + + public String getCharacterEncodingScheme() { + throw new UnsupportedOperationException(); + } + + public String getElementText() throws XMLStreamException { + return null; + } + + public String getEncoding() { + return null; + } + + public int getEventType() { + int returnEvent = START_DOCUMENT; + switch (currentState) { + case START_ELEMENT_STATE: + returnEvent = START_ELEMENT; + break; + case END_ELEMENT_STATE: + returnEvent = END_ELEMENT; + break; + } + return returnEvent; + } + + public String getLocalName() { + return elementQName.getLocalPart(); + } + + public Location getLocation() { + return new Location() { + public int getCharacterOffset() { + return 0; + } + + public int getColumnNumber() { + return 0; + } + + public int getLineNumber() { + return 0; + } + + public String getPublicId() { + return null; + } + + public String getSystemId() { + return null; + } + }; + } + + public QName getName() { + return elementQName; + } + + public NamespaceContext getNamespaceContext() { + throw new UnsupportedOperationException(); + } + + public int getNamespaceCount() { + return 0; + } + + public String getNamespacePrefix(int i) { + return null; + } + + public String getNamespaceURI() { + return elementQName.getNamespaceURI(); + } + + public String getNamespaceURI(int i) { + return null; + } + + public String getNamespaceURI(String string) { + if (elementQName.getPrefix() != null && elementQName.getPrefix().equals(string)) { + return elementQName.getNamespaceURI(); + } else { + return null; + } + } + + public String getPIData() { + throw new UnsupportedOperationException(); + } + + public String getPITarget() { + throw new UnsupportedOperationException(); + } + + public String getPrefix() { + return elementQName.getPrefix(); + } + + public Object getProperty(String key) throws IllegalArgumentException { + // since optimization is a global property + // we've to implement it everywhere + return null; + } + + public String getText() { + return null; + } + + public char[] getTextCharacters() { + return new char[0]; + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + return 0; + } + + public int getTextLength() { + return 0; + } + + public int getTextStart() { + return 0; + } + + public String getVersion() { + throw new UnsupportedOperationException(); + } + + public boolean hasName() { + return true; + } + + public boolean hasNext() throws XMLStreamException { + return currentState != END_ELEMENT_STATE; + + } + + public boolean hasText() { + return false; + } + + public void init() { + // NOOP + } + + public boolean isAttributeSpecified(int i) { + return i == 0; + } + + public boolean isCharacters() { + return false; + } + + public boolean isDone() { + return currentState == END_ELEMENT_STATE; + } + + public boolean isEndElement() { + return currentState == END_ELEMENT_STATE; + } + + public boolean isStandalone() { + throw new UnsupportedOperationException(); + } + + public boolean isStartElement() { + return currentState == START_ELEMENT_STATE; + } + + public boolean isWhiteSpace() { + return false; + } + + public int next() throws XMLStreamException { + int returnEvent = START_DOCUMENT; + switch (currentState) { + case START_ELEMENT_STATE: + currentState = END_ELEMENT_STATE; + returnEvent = END_ELEMENT; + break; + case END_ELEMENT_STATE: + throw new XMLStreamException("parser completed!"); + + } + return returnEvent; + } + + public int nextTag() throws XMLStreamException { + throw new UnsupportedOperationException(); + } + + public void require(int i, String string, String string1) throws XMLStreamException { + // nothing + } + + public boolean standaloneSet() { + throw new UnsupportedOperationException(); + } +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2OutputStream.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2OutputStream.java new file mode 100644 index 0000000000..5500d0bcca --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2OutputStream.java @@ -0,0 +1,68 @@ +/* + * 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.sca.databinding.xml; + +import java.io.OutputStream; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; + +/** + * Push DOM Node to OutputStream + * + * @version $Rev$ $Date$ + */ +public class Node2OutputStream extends BaseTransformer<Node, OutputStream> implements + PushTransformer<Node, OutputStream> { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public void transform(Node source, OutputStream writer, TransformationContext context) { + try { + Source domSource = new DOMSource(source); + Result result = new StreamResult(writer); + TRANSFORMER.transform(domSource, result, context); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Node> getSourceType() { + return Node.class; + } + + @Override + protected Class<OutputStream> getTargetType() { + return OutputStream.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2SimpleJavaType.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2SimpleJavaType.java new file mode 100644 index 0000000000..d5bf7e76b5 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2SimpleJavaType.java @@ -0,0 +1,45 @@ +/* + * 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.sca.databinding.xml; + +import org.apache.tuscany.sca.databinding.impl.SimpleType2JavaTransformer; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/** + * Transformer to convert data from a simple java Object to OMElement. + * + * @version $Rev$ $Date$ + */ +public class Node2SimpleJavaType extends SimpleType2JavaTransformer<Node> { + + @Override + protected String getText(Node source) { + if (source instanceof Document) { + source = ((Document)source).getDocumentElement(); + } + return source.getTextContent(); + + } + + @Override + public Class getSourceType() { + return Node.class; + } +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2SourceTransformer.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2SourceTransformer.java new file mode 100644 index 0000000000..3c9022bc3c --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2SourceTransformer.java @@ -0,0 +1,61 @@ +/* + * 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.sca.databinding.xml; + +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; + +/** + * Transform TrAX Node to Source + * + * @version $Rev$ $Date$ + */ +public class Node2SourceTransformer extends BaseTransformer<Node, Source> implements + PullTransformer<Node, Source> { + + public Source transform(Node source, TransformationContext context) { + try { + return new DOMSource(source); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Node> getSourceType() { + return Node.class; + } + + @Override + protected Class<Source> getTargetType() { + return Source.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2String.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2String.java new file mode 100644 index 0000000000..1b54b1fd1e --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2String.java @@ -0,0 +1,62 @@ +/* + * 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.sca.databinding.xml; + +import java.io.StringWriter; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; + +/** + * Transform DOM Node to XML String + * + * @version $Rev$ $Date$ + */ +public class Node2String extends BaseTransformer<Node, String> implements PullTransformer<Node, String> { + private static final Node2Writer TRANSFORMER = new Node2Writer(); + + public String transform(Node source, TransformationContext context) { + try { + StringWriter writer = new StringWriter(); + TRANSFORMER.transform(source, writer, context); + return writer.toString(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + public Class<Node> getSourceType() { + return Node.class; + } + + @Override + public Class<String> getTargetType() { + return String.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2Writer.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2Writer.java new file mode 100644 index 0000000000..c9631595dc --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2Writer.java @@ -0,0 +1,67 @@ +/* + * 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.sca.databinding.xml; + +import java.io.Writer; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; + +/** + * Push DOM Node to Writer + * + * @version $Rev$ $Date$ + */ +public class Node2Writer extends BaseTransformer<Node, Writer> implements PushTransformer<Node, Writer> { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public void transform(Node source, Writer writer, TransformationContext context) { + try { + Source domSource = new DOMSource(source); + Result result = new StreamResult(writer); + TRANSFORMER.transform(domSource, result, context); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Node> getSourceType() { + return Node.class; + } + + @Override + protected Class<Writer> getTargetType() { + return Writer.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2XMLStreamReader.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2XMLStreamReader.java new file mode 100644 index 0000000000..1e8d14a151 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Node2XMLStreamReader.java @@ -0,0 +1,64 @@ +/* + * 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.sca.databinding.xml; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; + +/** + * Transform DOM Node to XML XMLStreamReader + * + * @version $Rev$ $Date$ + */ +public class Node2XMLStreamReader extends BaseTransformer<Node, XMLStreamReader> implements + PullTransformer<Node, XMLStreamReader> { + + public XMLStreamReader transform(Node source, TransformationContext context) { + if (source == null) { + return null; + } + try { + DOMXMLStreamReader reader = new DOMXMLStreamReader(source); + return reader; + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Node> getSourceType() { + return Node.class; + } + + @Override + protected Class<XMLStreamReader> getTargetType() { + return XMLStreamReader.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Reader2Node.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Reader2Node.java new file mode 100644 index 0000000000..70387fa862 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Reader2Node.java @@ -0,0 +1,67 @@ +/* + * 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.sca.databinding.xml; + +import java.io.Reader; + +import javax.xml.transform.Source; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.stream.StreamSource; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; + +/** + * Push DOM Reader to Node + * + * @version $Rev$ $Date$ + */ +public class Reader2Node extends BaseTransformer<Reader, Node> implements PullTransformer<Reader, Node> { + private static final Source2ResultTransformer TRANSFORMER = new Source2ResultTransformer(); + + public Node transform(Reader source, TransformationContext context) { + try { + Source streamSource = new StreamSource(source); + DOMResult result = new DOMResult(); + TRANSFORMER.transform(streamSource, result, context); + return result.getNode(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Reader> getSourceType() { + return Reader.class; + } + + @Override + protected Class<Node> getTargetType() { + return Node.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Reader2SAX.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Reader2SAX.java new file mode 100644 index 0000000000..188ecaffa3 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Reader2SAX.java @@ -0,0 +1,60 @@ +/* + * 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.sca.databinding.xml; + +import java.io.Reader; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; + +/** + * Transform XML string to SAX + * + * @version $Rev$ $Date$ + */ +public class Reader2SAX extends BaseTransformer<Reader, ContentHandler> implements + PushTransformer<Reader, ContentHandler> { + public void transform(Reader source, ContentHandler target, TransformationContext context) { + try { + new InputSource2SAX().transform(new InputSource(source), target, context); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Reader> getSourceType() { + return Reader.class; + } + + @Override + protected Class<ContentHandler> getTargetType() { + return ContentHandler.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SAX2DOM.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SAX2DOM.java new file mode 100644 index 0000000000..38c61d64c8 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SAX2DOM.java @@ -0,0 +1,246 @@ +/* + * Copyright 2001-2004 The Apache Software Foundation. + * + * Licensed 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.sca.databinding.xml; + +import java.util.ArrayList; +import java.util.List; +import java.util.Stack; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.w3c.dom.Comment; +import org.w3c.dom.Document; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.ProcessingInstruction; +import org.w3c.dom.Text; +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.ext.LexicalHandler; + +/** + * SAX2DOM adapter + * + * @version $Rev$ $Date$ + */ +public class SAX2DOM implements ContentHandler, LexicalHandler { + public static final String EMPTYSTRING = ""; + public static final String XML_PREFIX = "xml"; + public static final String XMLNS_PREFIX = "xmlns"; + public static final String XMLNS_STRING = "xmlns:"; + public static final String XMLNS_URI = "http://www.w3.org/2000/xmlns/"; + + private Node root; + + private Document document; + + private Node nextSibling; + + private Stack<Node> nodeStk = new Stack<Node>(); + + private List<String> namespaceDecls; + + private Node lastSibling; + + public SAX2DOM() throws ParserConfigurationException { + this.document = DOMHelper.newDocument(); + this.root = document; + } + + public SAX2DOM(Node root, Node nextSibling) throws ParserConfigurationException { + this.root = root; + if (root instanceof Document) { + this.document = (Document)root; + } else if (root != null) { + this.document = root.getOwnerDocument(); + } else { + this.document = DOMHelper.newDocument(); + this.root = document; + } + + this.nextSibling = nextSibling; + } + + public SAX2DOM(Node root) throws ParserConfigurationException { + this(root, null); + } + + public Node getDOM() { + return root; + } + + public void characters(char[] ch, int start, int length) { + final Node last = nodeStk.peek(); + + // No text nodes can be children of root (DOM006 exception) + if (last != document) { + final String text = new String(ch, start, length); + if (lastSibling != null && lastSibling.getNodeType() == Node.TEXT_NODE) { + ((Text)lastSibling).appendData(text); + } else if (last == root && nextSibling != null) { + lastSibling = last.insertBefore(document.createTextNode(text), nextSibling); + } else { + lastSibling = last.appendChild(document.createTextNode(text)); + } + + } + } + + public void startDocument() { + nodeStk.push(root); + } + + public void endDocument() { + nodeStk.pop(); + } + + public void startElement(String namespace, String localName, String qName, Attributes attrs) { + final Element tmp = document.createElementNS(namespace, qName); + + // Add namespace declarations first + if (namespaceDecls != null) { + final int nDecls = namespaceDecls.size(); + for (int i = 0; i < nDecls; i++) { + final String prefix = namespaceDecls.get(i++); + + if (prefix == null || prefix.equals(EMPTYSTRING)) { + tmp.setAttributeNS(XMLNS_URI, XMLNS_PREFIX, namespaceDecls.get(i)); + } else { + tmp.setAttributeNS(XMLNS_URI, XMLNS_STRING + prefix, namespaceDecls.get(i)); + } + } + namespaceDecls.clear(); + } + + // Add attributes to element + final int nattrs = attrs.getLength(); + for (int i = 0; i < nattrs; i++) { + if (attrs.getLocalName(i) == null) { + tmp.setAttribute(attrs.getQName(i), attrs.getValue(i)); + } else { + tmp.setAttributeNS(attrs.getURI(i), attrs.getQName(i), attrs.getValue(i)); + } + } + + // Append this new node onto current stack node + Node last = nodeStk.peek(); + + // If the SAX2DOM is created with a non-null next sibling node, + // insert the result nodes before the next sibling under the root. + if (last == root && nextSibling != null) { + last.insertBefore(tmp, nextSibling); + } else { + last.appendChild(tmp); + } + + // Push this node onto stack + nodeStk.push(tmp); + lastSibling = null; + } + + public void endElement(String namespace, String localName, String qName) { + nodeStk.pop(); + lastSibling = null; + } + + public void startPrefixMapping(String prefix, String uri) { + if (namespaceDecls == null) { + namespaceDecls = new ArrayList<String>(2); + } + namespaceDecls.add(prefix); + namespaceDecls.add(uri); + } + + public void endPrefixMapping(String prefix) { + // do nothing + } + + /** + * This class is only used internally so this method should never be called. + */ + public void ignorableWhitespace(char[] ch, int start, int length) { + } + + /** + * adds processing instruction node to DOM. + */ + public void processingInstruction(String target, String data) { + final Node last = nodeStk.peek(); + ProcessingInstruction pi = document.createProcessingInstruction(target, data); + if (pi != null) { + if (last == root && nextSibling != null) { + last.insertBefore(pi, nextSibling); + } else { + last.appendChild(pi); + } + + lastSibling = pi; + } + } + + /** + * This class is only used internally so this method should never be called. + */ + public void setDocumentLocator(Locator locator) { + } + + /** + * This class is only used internally so this method should never be called. + */ + public void skippedEntity(String name) { + } + + /** + * Lexical Handler method to create comment node in DOM tree. + */ + public void comment(char[] ch, int start, int length) { + final Node last = nodeStk.peek(); + Comment comment = document.createComment(new String(ch, start, length)); + if (comment != null) { + if (last == root && nextSibling != null) { + last.insertBefore(comment, nextSibling); + } else { + last.appendChild(comment); + } + + lastSibling = comment; + } + } + + // Lexical Handler methods- not implemented + public void startCDATA() { + } + + public void endCDATA() { + } + + public void startEntity(java.lang.String name) { + } + + public void endDTD() { + } + + public void endEntity(String name) { + } + + public void startDTD(String name, String publicId, String systemId) throws SAXException { + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SAX2DOMPipe.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SAX2DOMPipe.java new file mode 100644 index 0000000000..cb9d538389 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SAX2DOMPipe.java @@ -0,0 +1,81 @@ +/* + * 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.sca.databinding.xml; + +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.tuscany.sca.databinding.DataPipe; +import org.apache.tuscany.sca.databinding.DataPipeTransformer; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.w3c.dom.Node; +import org.xml.sax.ContentHandler; + +public class SAX2DOMPipe extends BaseTransformer<ContentHandler, Node> implements DataPipeTransformer<ContentHandler, Node> { + + /** + * + */ + public SAX2DOMPipe() { + super(); + } + + /** + * @see org.apache.tuscany.sca.databinding.DataPipeTransformer#newInstance() + */ + public DataPipe<ContentHandler, Node> newInstance() { + return new Pipe(); + } + + @Override + protected Class<Node> getTargetType() { + return Node.class; + } + + @Override + protected Class<ContentHandler> getSourceType() { + return ContentHandler.class; + } + + @Override + public int getWeight() { + return 30; + } + + private static class Pipe implements DataPipe<ContentHandler, Node> { + private SAX2DOM pipe; + + public Pipe() { + super(); + try { + this.pipe = new SAX2DOM(); + } catch (ParserConfigurationException e) { + throw new IllegalArgumentException(e); + } + } + + public Node getResult() { + return pipe.getDOM(); + } + + public ContentHandler getSink() { + return pipe; + } + + } +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SimpleJavaType2Node.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SimpleJavaType2Node.java new file mode 100644 index 0000000000..d2625fba11 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SimpleJavaType2Node.java @@ -0,0 +1,71 @@ +/* + * 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.sca.databinding.xml; + +import javax.xml.namespace.QName; +import javax.xml.parsers.ParserConfigurationException; + +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.apache.tuscany.sca.databinding.impl.Java2SimpleTypeTransformer; +import org.apache.tuscany.sca.databinding.javabeans.Java2XMLMapperException; +import org.w3c.dom.Attr; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/** + * Transformer to convert data from an simple OMElement to Java Object + * + * @version $Rev$ $Date$ + */ +public class SimpleJavaType2Node extends Java2SimpleTypeTransformer<Node> { + + private Document factory; + + public SimpleJavaType2Node() { + super(); + try { + factory = DOMHelper.newDocument(); + } catch (ParserConfigurationException e) { + throw new Java2XMLMapperException(e); + } + } + + @Override + protected Node createElement(QName element, String text, TransformationContext context) { + if (element == null) { + element = DOMDataBinding.ROOT_ELEMENT; + } + Node root = DOMHelper.createElement(factory, element); + if (text != null) { + root.appendChild(factory.createTextNode(text)); + } else { + Attr nil = factory.createAttributeNS("http://www.w3.org/2001/XMLSchema-instance", "xsi:nil"); + nil.setValue("true"); + root.appendChild(nil); + } + return root; + } + + @Override + public Class getTargetType() { + return Node.class; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SimpleXmlNodeImpl.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SimpleXmlNodeImpl.java new file mode 100644 index 0000000000..e041f85214 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/SimpleXmlNodeImpl.java @@ -0,0 +1,112 @@ +/* + * 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.sca.databinding.xml; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; + +/** + * @version $Rev$ $Date$ + */ +public class SimpleXmlNodeImpl implements XmlNode { + private static final String XSI_PREFIX = "xsi"; + private static final String XSI_NS = "http://www.w3.org/2001/XMLSchema-instance"; + private static final QName XSI_NIL = new QName(XSI_NS, "nil", XSI_PREFIX); + private static final Map<String, String> NS_MAP = new HashMap<String, String>(); + static { + NS_MAP.put(XSI_PREFIX, XSI_NS); + } + + protected Type type; + protected QName name; + protected Object value; + + public SimpleXmlNodeImpl(QName name, Object value) { + this(name, value, name != null ? Type.ELEMENT : Type.CHARACTERS); + } + + public SimpleXmlNodeImpl(QName name, Object value, Type type) { + super(); + this.type = type; + this.name = name; + this.value = value; + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#attributes() + */ + public List<XmlNode> attributes() { + if (type == Type.ELEMENT && value == null) { + // Nil element + XmlNode attr = new SimpleXmlNodeImpl(XSI_NIL, "true"); + return Arrays.asList(attr); + } + return null; + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#children() + */ + public Iterator<XmlNode> children() { + if (type == Type.ELEMENT && value != null) { + // Nil element + XmlNode node = new SimpleXmlNodeImpl(null, value); + return Arrays.asList(node).iterator(); + } + return null; + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#getName() + */ + public QName getName() { + return name; + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#getValue() + */ + public String getValue() { + return value == null ? null : String.valueOf(value); + } + + /** + * @see org.apache.tuscany.sca.databinding.xml.XmlNode#namespaces() + */ + public Map<String, String> namespaces() { + if (type == Type.ELEMENT && value == null) { + return NS_MAP; + } + return null; + } + + public Type getType() { + return type; + } + + public void setType(Type type) { + this.type = type; + } +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2NodeTransformer.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2NodeTransformer.java new file mode 100644 index 0000000000..ee9aa1bb76 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2NodeTransformer.java @@ -0,0 +1,69 @@ +/* + * 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.sca.databinding.xml; + +import javax.xml.transform.Source; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +/** + * Transform TrAX Source to Node + * + * @version $Rev$ $Date$ + */ +public class Source2NodeTransformer extends BaseTransformer<Source, Node> implements + PullTransformer<Source, Node> { + private static final TransformerFactory FACTORY = TransformerFactory.newInstance(); + + public Node transform(Source source, TransformationContext context) { + try { + javax.xml.transform.Transformer transformer = FACTORY.newTransformer(); + DOMResult result = new DOMResult(); + transformer.transform(source, result); + Document doc = (Document) result.getNode(); + return DOMHelper.adjustElementName(context, doc.getDocumentElement()); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Source> getSourceType() { + return Source.class; + } + + @Override + protected Class<Node> getTargetType() { + return Node.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2ResultTransformer.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2ResultTransformer.java new file mode 100644 index 0000000000..8a2b6b39aa --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2ResultTransformer.java @@ -0,0 +1,63 @@ +/* + * 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.sca.databinding.xml; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import javax.xml.transform.TransformerFactory; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +/** + * Transform TrAX Source to Result + * + * @version $Rev$ $Date$ + */ +public class Source2ResultTransformer extends BaseTransformer<Source, Result> implements + PushTransformer<Source, Result> { + private static final TransformerFactory FACTORY = TransformerFactory.newInstance(); + + public void transform(Source source, Result result, TransformationContext context) { + try { + javax.xml.transform.Transformer transformer = FACTORY.newTransformer(); + transformer.transform(source, result); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Source> getSourceType() { + return Source.class; + } + + @Override + protected Class<Result> getTargetType() { + return Result.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2StringTransformer.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2StringTransformer.java new file mode 100644 index 0000000000..2ed548ad76 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Source2StringTransformer.java @@ -0,0 +1,68 @@ +/* + * 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.sca.databinding.xml; + +import java.io.StringWriter; + +import javax.xml.transform.Source; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.stream.StreamResult; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +/** + * Transform TrAX Source to String + * + * @version $Rev$ $Date$ + */ +public class Source2StringTransformer extends BaseTransformer<Source, String> implements + PullTransformer<Source, String> { + private static final TransformerFactory FACTORY = TransformerFactory.newInstance(); + + public String transform(Source source, TransformationContext context) { + try { + javax.xml.transform.Transformer transformer = FACTORY.newTransformer(); + StringWriter sw = new StringWriter(); + StreamResult result = new StreamResult(sw); + transformer.transform(source, result); + return sw.toString(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<Source> getSourceType() { + return Source.class; + } + + @Override + protected Class<String> getTargetType() { + return String.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StAX2SAXAdapter.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StAX2SAXAdapter.java new file mode 100644 index 0000000000..6257681091 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StAX2SAXAdapter.java @@ -0,0 +1,256 @@ +/* + * 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.sca.databinding.xml; + +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.xml.sax.Attributes; +import org.xml.sax.ContentHandler; +import org.xml.sax.Locator; +import org.xml.sax.SAXException; +import org.xml.sax.helpers.AttributesImpl; + +/** + * Adapter that converts from StAX to SAX event streams. Currently the following + * SAX events are not generated: + * <ul> + * <li>ignorableWhitespace</li> + * <li>skippedEntity</li> + * <ul> + * Also the following StAX events are not mapped: + * <ul> + * <li>CDATA</li> + * <li>COMMENT</li> + * <li>DTD</li> + * <li>ENTITY_DECLARATION</li> + * <li>ENTITY_REFERENCE</li> + * <li>NOTATION_DECLARATION</li> + * <li>SPACE</li> + * </ul> + * StAX ATTRIBUTE events are ignored but the equivalent attributes (derived from + * the START_ELEMENT event) are supplied in the SAX startElement event's + * Attributes parameter. If the adaptor is configured to pass namespace prefixes + * then namespace information will also be included in the Attributes; StAX + * NAMESPACE events are ignored. <p/> Another issue is namespace processing. If + * the reader is positioned at a sub-node, we cannot capture all the in-scope + * namespace bindings. Therefore we cannot re-create a proper SAX event stream + * from a StAX parser. <p/> For example <p/> <a:root xmlns:a="foo" + * xmlns:b="bar"><b:sub>a:foo</b:sub></a:root> <p/> And if + * you are handed a parser at <b:sub>, then your SAX events should look + * like: <p/> <b:sub xmlns:a="foo" xmlns:b="bar">a:foo</b:sub> <p/> + * not: <p/> <b:sub>a:foo</b:sub> <p/> <p/> Proposal: we change the + * receiver of SAX events (SDOXMLResourceImpl) so that it uses NamespaceContext + * to resolve prefix (as opposed to record start/endPrefixMappings and use it + * for resolution.) + * + * @version $Rev$ $Date$ + */ +public class StAX2SAXAdapter { + private final boolean namespacePrefixes; + + /** + * Construct a new StAX to SAX adapter that will convert a StAX event stream + * into a SAX event stream. + * + * @param namespacePrefixes whether xmlns attributes should be included in + * startElement events; + */ + public StAX2SAXAdapter(boolean namespacePrefixes) { + this.namespacePrefixes = namespacePrefixes; + } + + /** + * Pull events from the StAX stream and dispatch to the SAX ContentHandler. + * The StAX stream would typically be located on a START_DOCUMENT or + * START_ELEMENT event and when this method returns it will be located on + * the associated END_DOCUMENT or END_ELEMENT event. Behaviour with other + * start events is undefined. + * + * @param reader StAX event source to read + * @param handler SAX ContentHandler for processing events + * @throws XMLStreamException if there was a problem reading the stream + * @throws SAXException passed through from the ContentHandler + */ + public void parse(XMLStreamReader reader, ContentHandler handler) throws XMLStreamException, SAXException { + handler.setDocumentLocator(new LocatorAdaptor(reader.getLocation())); + + // remembers the nest level of elements to know when we are done + int level = 0; + int event = reader.getEventType(); + while (true) { + switch (event) { + case XMLStreamConstants.START_DOCUMENT: + level++; + handler.startDocument(); + break; + case XMLStreamConstants.START_ELEMENT: + level++; + handleStartElement(reader, handler); + break; + case XMLStreamConstants.PROCESSING_INSTRUCTION: + handler.processingInstruction(reader.getPITarget(), reader.getPIData()); + break; + case XMLStreamConstants.CHARACTERS: + handler.characters(reader.getTextCharacters(), reader.getTextStart(), reader + .getTextLength()); + break; + case XMLStreamConstants.END_ELEMENT: + handleEndElement(reader, handler); + level--; + if (level == 0) { + return; + } + break; + case XMLStreamConstants.END_DOCUMENT: + handler.endDocument(); + return; + /* + * uncomment to handle all events rather than just mapped + * ones // StAX events that are not mapped to SAX case + * XMLStreamConstants.COMMENT: case + * XMLStreamConstants.SPACE: case + * XMLStreamConstants.ENTITY_REFERENCE: case + * XMLStreamConstants.DTD: case XMLStreamConstants.CDATA: + * case XMLStreamConstants.NOTATION_DECLARATION: case + * XMLStreamConstants.ENTITY_DECLARATION: break; // StAX + * events handled in START_ELEMENT case + * XMLStreamConstants.ATTRIBUTE: case + * XMLStreamConstants.NAMESPACE: break; default: throw new + * AssertionError("Unknown StAX event: " + event); + */ + } + event = reader.next(); + } + } + + private void handleStartElement(XMLStreamReader reader, ContentHandler handler) throws SAXException { + // send startPrefixMapping events immediately before startElement event + int nsCount = reader.getNamespaceCount(); + for (int i = 0; i < nsCount; i++) { + String prefix = reader.getNamespacePrefix(i); + if (prefix == null) { // true for default namespace + prefix = ""; + } + handler.startPrefixMapping(prefix, reader.getNamespaceURI(i)); + } + + // fire startElement + QName qname = reader.getName(); + String prefix = qname.getPrefix(); + String rawname; + if (prefix == null || prefix.length() == 0) { + rawname = qname.getLocalPart(); + } else { + rawname = prefix + ':' + qname.getLocalPart(); + } + Attributes attrs = getAttributes(reader); + handler.startElement(qname.getNamespaceURI(), qname.getLocalPart(), rawname, attrs); + } + + private static void handleEndElement(XMLStreamReader reader, ContentHandler handler) throws SAXException { + // fire endElement + QName qname = reader.getName(); + handler.endElement(qname.getNamespaceURI(), qname.getLocalPart(), qname.toString()); + + // send endPrefixMapping events immediately after endElement event + // we send them in the opposite order to that returned but this is not + // actually required by SAX + int nsCount = reader.getNamespaceCount(); + for (int i = nsCount - 1; i >= 0; i--) { + String prefix = reader.getNamespacePrefix(i); + if (prefix == null) { // true for default namespace + prefix = ""; + } + handler.endPrefixMapping(prefix); + } + } + + /** + * Get the attributes associated with the current START_ELEMENT event. + * + * @return the StAX attributes converted to org.xml.sax.Attributes + */ + private Attributes getAttributes(XMLStreamReader reader) { + assert reader.getEventType() == XMLStreamConstants.START_ELEMENT; + + AttributesImpl attrs = new AttributesImpl(); + + // add namespace declarations if required + if (namespacePrefixes) { + for (int i = 0; i < reader.getNamespaceCount(); i++) { + String prefix = reader.getNamespacePrefix(i); + String uri = reader.getNamespaceURI(i); + attrs.addAttribute(null, prefix, "xmlns:" + prefix, "CDATA", uri); + } + } + + // Regular attributes + for (int i = 0; i < reader.getAttributeCount(); i++) { + String uri = reader.getAttributeNamespace(i); + if (uri == null) { + uri = ""; + } + String localName = reader.getAttributeLocalName(i); + String prefix = reader.getAttributePrefix(i); + String qname; + if (prefix == null || prefix.length() == 0) { + qname = localName; + } else { + qname = prefix + ':' + localName; + } + String type = reader.getAttributeType(i); + String value = reader.getAttributeValue(i); + + attrs.addAttribute(uri, localName, qname, type, value); + } + + return attrs; + } + + /** + * Adaptor for mapping Locator information. + */ + private static final class LocatorAdaptor implements Locator { + private final Location location; + + private LocatorAdaptor(Location location) { + this.location = location; + } + + public int getColumnNumber() { + return location == null ? 0 : location.getColumnNumber(); + } + + public int getLineNumber() { + return location == null ? 0 : location.getLineNumber(); + } + + public String getPublicId() { + return location == null ? "" : location.getPublicId(); + } + + public String getSystemId() { + return location == null ? "" : location.getSystemId(); + } + } +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StAXDataBinding.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StAXDataBinding.java new file mode 100644 index 0000000000..ed57992910 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StAXDataBinding.java @@ -0,0 +1,53 @@ +/* + * 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.sca.databinding.xml; + + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.impl.BaseDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * A DataBinding for the StAX + * + * @version $Rev$ $Date$ + */ +public class StAXDataBinding extends BaseDataBinding { + public static final String NAME = XMLStreamReader.class.getName(); + + public StAXDataBinding() { + super(NAME, XMLStreamReader.class); + } + + @Override + public boolean introspect(DataType type, Operation operation) { + if (super.introspect(type, operation)) { + type.setLogical(XMLType.UNKNOWN); + type.setDataBinding(NAME); + return true; + } else { + return false; + } + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StAXHelper.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StAXHelper.java new file mode 100644 index 0000000000..103ecbd7d1 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StAXHelper.java @@ -0,0 +1,86 @@ +/* + * 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.sca.databinding.xml; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; + +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLOutputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; +import javax.xml.transform.Source; + + +public final class StAXHelper { + private static final XMLInputFactory INPUT_FACTORY = XMLInputFactory.newInstance(); + private static final XMLOutputFactory OUTPUT_FACTORY = XMLOutputFactory.newInstance(); + + private StAXHelper() { + } + + public static XMLStreamReader createXMLStreamReader(InputStream inputStream) throws XMLStreamException { + return INPUT_FACTORY.createXMLStreamReader(inputStream); + } + + public static XMLStreamReader createXMLStreamReader(Reader reader) throws XMLStreamException { + return INPUT_FACTORY.createXMLStreamReader(reader); + } + + public static XMLStreamReader createXMLStreamReader(Source source) throws XMLStreamException { + return INPUT_FACTORY.createXMLStreamReader(source); + } + + public static XMLStreamReader createXMLStreamReader(String string) throws XMLStreamException { + StringReader reader = new StringReader(string); + return createXMLStreamReader(reader); + } + + public static String save(XMLStreamReader reader) throws XMLStreamException { + StringWriter writer = new StringWriter(); + save(reader, writer); + return writer.toString(); + } + + public static void save(XMLStreamReader reader, OutputStream outputStream) throws XMLStreamException { + XMLStreamSerializer serializer = new XMLStreamSerializer(); + XMLStreamWriter streamWriter = OUTPUT_FACTORY.createXMLStreamWriter(outputStream); + serializer.serialize(reader, streamWriter); + streamWriter.flush(); + } + + public static void save(XMLStreamReader reader, Writer writer) throws XMLStreamException { + XMLStreamSerializer serializer = new XMLStreamSerializer(); + XMLStreamWriter streamWriter = OUTPUT_FACTORY.createXMLStreamWriter(writer); + serializer.serialize(reader, streamWriter); + streamWriter.flush(); + } + + public static void save(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + XMLStreamSerializer serializer = new XMLStreamSerializer(); + serializer.serialize(reader, writer); + writer.flush(); + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StreamDataPipe.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StreamDataPipe.java new file mode 100644 index 0000000000..f8967e35b6 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/StreamDataPipe.java @@ -0,0 +1,65 @@ +/* + * 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.sca.databinding.xml; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.io.OutputStream; + +import org.apache.tuscany.sca.databinding.DataPipe; +import org.apache.tuscany.sca.databinding.DataPipeTransformer; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +public class StreamDataPipe extends BaseTransformer<OutputStream, InputStream> implements + DataPipeTransformer<OutputStream, InputStream> { + + public DataPipe<OutputStream, InputStream> newInstance() { + return new Pipe(); + } + + @Override + protected Class<InputStream> getTargetType() { + return InputStream.class; + } + + @Override + public int getWeight() { + return 50; + } + + @Override + protected Class<OutputStream> getSourceType() { + return OutputStream.class; + } + + public static class Pipe implements DataPipe<OutputStream, InputStream> { + private ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + + public InputStream getResult() { + return new ByteArrayInputStream(outputStream.toByteArray()); + } + + public OutputStream getSink() { + return outputStream; + } + + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2Node.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2Node.java new file mode 100644 index 0000000000..062e10cc45 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2Node.java @@ -0,0 +1,60 @@ +/* + * 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.sca.databinding.xml; + +import java.io.StringReader; + +import javax.xml.parsers.DocumentBuilder; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.w3c.dom.Node; +import org.xml.sax.InputSource; + +public class String2Node extends BaseTransformer<String, Node> implements PullTransformer<String, Node> { + + public Node transform(String source, TransformationContext context) { + try { + DocumentBuilder builder = DOMHelper.newDocumentBuilder(); + InputSource inputSource = new InputSource(new StringReader(source)); + return builder.parse(inputSource); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<String> getSourceType() { + return String.class; + } + + @Override + protected Class<Node> getTargetType() { + return Node.class; + } + + @Override + public int getWeight() { + return 50; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2SAX.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2SAX.java new file mode 100644 index 0000000000..c56dba1843 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2SAX.java @@ -0,0 +1,61 @@ +/* + * 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.sca.databinding.xml; + +import java.io.StringReader; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; + +/** + * Transform XML string to SAX + * + * @version $Rev$ $Date$ + */ +public class String2SAX extends BaseTransformer<String, ContentHandler> implements + PushTransformer<String, ContentHandler> { + + public void transform(String source, ContentHandler target, TransformationContext context) { + try { + new InputSource2SAX().transform(new InputSource(new StringReader(source)), target, context); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<String> getSourceType() { + return String.class; + } + + @Override + protected Class<ContentHandler> getTargetType() { + return ContentHandler.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2SourceTransformer.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2SourceTransformer.java new file mode 100644 index 0000000000..c2de202a9b --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2SourceTransformer.java @@ -0,0 +1,62 @@ +/* + * 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.sca.databinding.xml; + +import java.io.StringReader; + +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +/** + * Transform XML String to Source + * + * @version $Rev$ $Date$ + */ +public class String2SourceTransformer extends BaseTransformer<String, Source> implements + PullTransformer<String, Source> { + + public Source transform(String source, TransformationContext context) { + try { + return new StreamSource(new StringReader(source)); + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<String> getSourceType() { + return String.class; + } + + @Override + protected Class<Source> getTargetType() { + return Source.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2XMLStreamReader.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2XMLStreamReader.java new file mode 100644 index 0000000000..a7364006d0 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/String2XMLStreamReader.java @@ -0,0 +1,55 @@ +/* + * 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.sca.databinding.xml; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +public class String2XMLStreamReader extends BaseTransformer<String, XMLStreamReader> implements + PullTransformer<String, XMLStreamReader> { + + public XMLStreamReader transform(String source, TransformationContext context) { + try { + return StAXHelper.createXMLStreamReader(source); + } catch (XMLStreamException e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<String> getSourceType() { + return String.class; + } + + @Override + protected Class<XMLStreamReader> getTargetType() { + return XMLStreamReader.class; + } + + @Override + public int getWeight() { + return 50; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/WrappingXMLStreamReader.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/WrappingXMLStreamReader.java new file mode 100644 index 0000000000..d73e495798 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/WrappingXMLStreamReader.java @@ -0,0 +1,100 @@ +/* + * 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.sca.databinding.xml; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.util.StreamReaderDelegate; + +public class WrappingXMLStreamReader extends StreamReaderDelegate implements XMLFragmentStreamReader { + + private boolean done; + private int level; + + public WrappingXMLStreamReader(XMLStreamReader realReader) throws XMLStreamException { + super(realReader); + if (realReader == null) { + throw new UnsupportedOperationException("Reader cannot be null"); + } + + if (realReader instanceof XMLFragmentStreamReader) { + ((XMLFragmentStreamReader)realReader).init(); + } + + if (realReader.getEventType() == START_DOCUMENT) { + // Position to the 1st element + realReader.nextTag(); + } + if (realReader.getEventType() != START_ELEMENT) { + throw new IllegalStateException("The reader is not positioned at START_DOCUMENT or START_ELEMENT"); + } + this.done = false; + this.level = 1; + } + + @Override + public boolean hasNext() throws XMLStreamException { + return !done && super.hasNext(); + } + + @Override + public int next() throws XMLStreamException { + if (!hasNext()) { + throw new IllegalStateException("No more events"); + } + int event = super.next(); + if (!super.hasNext()) { + done = true; + } + if (event == START_ELEMENT) { + level++; + } else if (event == END_ELEMENT) { + level--; + if (level == 0) { + done = true; + } + } + return event; + } + + @Override + public int nextTag() throws XMLStreamException { + int event = 0; + while (true) { + event = next(); + if (event == START_ELEMENT || event == END_ELEMENT) { + return event; + } + } + } + + public void setParentNamespaceContext(NamespaceContext nsContext) { + // nothing to do here + } + + public void init() { + // Nothing to do here + } + + public boolean isDone() { + return done; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Writer2ReaderDataPipe.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Writer2ReaderDataPipe.java new file mode 100644 index 0000000000..5ab7272d58 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/Writer2ReaderDataPipe.java @@ -0,0 +1,63 @@ +/* + * 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.sca.databinding.xml; + +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; + +import org.apache.tuscany.sca.databinding.DataPipe; +import org.apache.tuscany.sca.databinding.DataPipeTransformer; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +public class Writer2ReaderDataPipe extends BaseTransformer<Writer, Reader> implements DataPipeTransformer<Writer, Reader> { + + public DataPipe<Writer, Reader> newInstance() { + return new Pipe(); + } + + @Override + protected Class<Reader> getTargetType() { + return Reader.class; + } + + @Override + public int getWeight() { + return 50; + } + + @Override + protected Class<Writer> getSourceType() { + return Writer.class; + } + + private static class Pipe implements DataPipe<Writer, Reader> { + private StringWriter writer = new StringWriter(); + + public Reader getResult() { + return new StringReader(writer.toString()); + } + + public Writer getSink() { + return writer; + } + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLDocumentStreamReader.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLDocumentStreamReader.java new file mode 100644 index 0000000000..a7088eada3 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLDocumentStreamReader.java @@ -0,0 +1,482 @@ +/* + * 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.sca.databinding.xml; + +import java.util.NoSuchElementException; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +/** + * This class is derived from Apache Axis2 class + * org.apache.axis2.util.StreamWrapper</a>. It's used wrap a XMLStreamReader to + * create a XMLStreamReader representing a document and it will produce + * START_DOCUMENT, END_DOCUMENT events. + * + * @version $Rev$ $Date$ + */ +public class XMLDocumentStreamReader implements XMLStreamReader { + private static final int STATE_COMPLETE_AT_NEXT = 2; // The wrapper + // will produce + // END_DOCUMENT + + private static final int STATE_COMPLETED = 3; // Done + + private static final int STATE_INIT = 0; // The wrapper will produce + // START_DOCUMENT + + private static final int STATE_SWITCHED = 1; // The real reader will + // produce events + + private XMLStreamReader realReader; + private boolean fragment; + private int level = 1; + + private int state = STATE_INIT; + + public XMLDocumentStreamReader(XMLStreamReader realReader) { + if (realReader == null) { + throw new UnsupportedOperationException("Reader cannot be null"); + } + + this.realReader = realReader; + + if (realReader instanceof XMLFragmentStreamReader) { + ((XMLFragmentStreamReader)realReader).init(); + } + + // If the real reader is positioned at START_DOCUMENT, always use + // the real reader + if (realReader.getEventType() == START_DOCUMENT) { + fragment = false; + state = STATE_SWITCHED; + } + } + + public void close() throws XMLStreamException { + realReader.close(); + } + + public int getAttributeCount() { + if (isDelegating()) { + return realReader.getAttributeCount(); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeLocalName(int i) { + if (isDelegating()) { + return realReader.getAttributeLocalName(i); + } else { + throw new IllegalStateException(); + } + } + + public QName getAttributeName(int i) { + if (isDelegating()) { + return realReader.getAttributeName(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeNamespace(int i) { + if (isDelegating()) { + return realReader.getAttributeNamespace(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributePrefix(int i) { + if (isDelegating()) { + return realReader.getAttributePrefix(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeType(int i) { + if (isDelegating()) { + return realReader.getAttributeType(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeValue(int i) { + if (isDelegating()) { + return realReader.getAttributeValue(i); + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeValue(String s, String s1) { + if (isDelegating()) { + return realReader.getAttributeValue(s, s1); + } else { + throw new IllegalStateException(); + } + } + + public String getCharacterEncodingScheme() { + return realReader.getCharacterEncodingScheme(); + } + + public String getElementText() throws XMLStreamException { + if (isDelegating()) { + return realReader.getElementText(); + } else { + throw new XMLStreamException(); + } + } + + public String getEncoding() { + return realReader.getEncoding(); + } + + public int getEventType() { + int event = -1; + switch (state) { + case STATE_SWITCHED: + case STATE_COMPLETE_AT_NEXT: + event = realReader.getEventType(); + break; + case STATE_INIT: + event = START_DOCUMENT; + break; + case STATE_COMPLETED: + event = END_DOCUMENT; + break; + } + return event; + } + + public String getLocalName() { + if (isDelegating()) { + return realReader.getLocalName(); + } else { + throw new IllegalStateException(); + } + } + + public Location getLocation() { + if (isDelegating()) { + return realReader.getLocation(); + } else { + return null; + } + } + + public QName getName() { + if (isDelegating()) { + return realReader.getName(); + } else { + throw new IllegalStateException(); + } + } + + public NamespaceContext getNamespaceContext() { + return realReader.getNamespaceContext(); + } + + public int getNamespaceCount() { + if (isDelegating()) { + return realReader.getNamespaceCount(); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespacePrefix(int i) { + if (isDelegating()) { + return realReader.getNamespacePrefix(i); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespaceURI() { + if (isDelegating()) { + return realReader.getNamespaceURI(); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespaceURI(int i) { + if (isDelegating()) { + return realReader.getNamespaceURI(i); + } else { + throw new IllegalStateException(); + } + } + + public String getNamespaceURI(String s) { + if (isDelegating()) { + return realReader.getNamespaceURI(s); + } else { + throw new IllegalStateException(); + } + } + + public String getPIData() { + if (isDelegating()) { + return realReader.getPIData(); + } else { + throw new IllegalStateException(); + } + } + + public String getPITarget() { + if (isDelegating()) { + return realReader.getPITarget(); + } else { + throw new IllegalStateException(); + } + } + + public String getPrefix() { + if (isDelegating()) { + return realReader.getPrefix(); + } else { + throw new IllegalStateException(); + } + } + + public Object getProperty(String s) throws IllegalArgumentException { + if (isDelegating()) { + return realReader.getProperty(s); + } else { + throw new IllegalArgumentException(); + } + } + + public String getText() { + if (isDelegating()) { + return realReader.getText(); + } else { + throw new IllegalStateException(); + } + } + + public char[] getTextCharacters() { + if (isDelegating()) { + return realReader.getTextCharacters(); + } else { + throw new IllegalStateException(); + } + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + if (isDelegating()) { + return realReader.getTextCharacters(i, chars, i1, i2); + } else { + throw new IllegalStateException(); + } + } + + public int getTextLength() { + if (isDelegating()) { + return realReader.getTextLength(); + } else { + throw new IllegalStateException(); + } + } + + public int getTextStart() { + if (isDelegating()) { + return realReader.getTextStart(); + } else { + throw new IllegalStateException(); + } + } + + public String getVersion() { + if (isDelegating()) { + return realReader.getVersion(); + } else { + return null; + } + } + + public boolean hasName() { + if (isDelegating()) { + return realReader.hasName(); + } else { + return false; + } + } + + public boolean hasNext() throws XMLStreamException { + if (state == STATE_COMPLETE_AT_NEXT) { + return true; + } else if (state == STATE_COMPLETED) { + return false; + } else if (state == STATE_SWITCHED) { + return realReader.hasNext(); + } else { + return true; + } + } + + public boolean hasText() { + if (isDelegating()) { + return realReader.hasText(); + } else { + return false; + } + } + + public boolean isAttributeSpecified(int i) { + if (isDelegating()) { + return realReader.isAttributeSpecified(i); + } else { + return false; + } + } + + public boolean isCharacters() { + if (isDelegating()) { + return realReader.isCharacters(); + } else { + return false; + } + } + + private boolean isDelegating() { + return state == STATE_SWITCHED || state == STATE_COMPLETE_AT_NEXT; + } + + public boolean isEndElement() { + if (isDelegating()) { + return realReader.isEndElement(); + } else { + return false; + } + } + + public boolean isStandalone() { + if (isDelegating()) { + return realReader.isStandalone(); + } else { + return false; + } + } + + public boolean isStartElement() { + if (isDelegating()) { + return realReader.isStartElement(); + } else { + return false; + } + } + + public boolean isWhiteSpace() { + if (isDelegating()) { + return realReader.isWhiteSpace(); + } else { + return false; + } + } + + public int next() throws XMLStreamException { + int returnEvent; + + switch (state) { + case STATE_SWITCHED: + returnEvent = realReader.next(); + if (returnEvent == END_DOCUMENT) { + state = STATE_COMPLETED; + } else if (!realReader.hasNext()) { + state = STATE_COMPLETE_AT_NEXT; + } + if (fragment && returnEvent == END_ELEMENT) { + level--; + if (level == 0) { + // We are now at the end of the top-level element in the fragment + state = STATE_COMPLETE_AT_NEXT; + } + } + if (fragment && returnEvent == START_ELEMENT) { + level++; + } + break; + case STATE_INIT: + state = STATE_SWITCHED; + returnEvent = realReader.getEventType(); + if (returnEvent == START_ELEMENT) { + // The real reader is positioned at the top-level element in the fragment + level = 0; + fragment = true; + } + break; + case STATE_COMPLETE_AT_NEXT: + state = STATE_COMPLETED; + returnEvent = END_DOCUMENT; + break; + case STATE_COMPLETED: + // oops - no way we can go beyond this + throw new NoSuchElementException("End of stream has reached."); + default: + throw new UnsupportedOperationException(); + } + + return returnEvent; + } + + public int nextTag() throws XMLStreamException { + if (isDelegating()) { + int returnEvent = realReader.nextTag(); + if (fragment && returnEvent == END_ELEMENT) { + level--; + if (level == 0) { + // We are now at the end of the top-level element in the fragment + state = STATE_COMPLETE_AT_NEXT; + } + } + if (fragment && returnEvent == START_ELEMENT) { + level++; + } + return returnEvent; + } else { + throw new XMLStreamException(); + } + } + + public void require(int i, String s, String s1) throws XMLStreamException { + if (isDelegating()) { + realReader.require(i, s, s1); + } + } + + public boolean standaloneSet() { + if (isDelegating()) { + return realReader.standaloneSet(); + } else { + return false; + } + } +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLFragmentStreamReader.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLFragmentStreamReader.java new file mode 100644 index 0000000000..a42d6acc9a --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLFragmentStreamReader.java @@ -0,0 +1,53 @@ +/* + * 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.sca.databinding.xml; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamReader; + +public interface XMLFragmentStreamReader extends XMLStreamReader { + QName NIL_QNAME = new QName("http://www.w3.org/2001/XMLSchema-instance", "nil", "xsi"); + String NIL_VALUE_TRUE = "true"; + + /** + * this will help to handle Text within the current element. user should + * pass the element text to the property list as this ELEMENT_TEXT as the + * key. This key deliberately has a space in it so that it is not a valid + * XML name + */ + String ELEMENT_TEXT = "Element Text"; + + /** + * Extra method to query the state of the pullparser + */ + boolean isDone(); + + /** + * add the parent namespace context to this parser + */ + void setParentNamespaceContext(NamespaceContext nsContext); + + /** + * Initiate the parser - this will do whatever the needed tasks to initiate + * the parser and must be called before attempting any specific parsing + * using this parser + */ + void init(); +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLFragmentStreamReaderImpl.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLFragmentStreamReaderImpl.java new file mode 100644 index 0000000000..f1084cf2a3 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLFragmentStreamReaderImpl.java @@ -0,0 +1,857 @@ +/* + * 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.sca.databinding.xml; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +/** + * This is the new implementation of the XMLFramentStreamReader. The approach + * here is simple When the pull parser needs to generate events for a particular + * name-value(s) pair it always hands over (delegates) the task to another pull + * parser which knows how to deal with it The common types of name value pairs + * we'll come across are + * <ul> + * <li> String name/QName name - String value + * <li> String name/QName name - String[] value + * <li> QName name/String name - XMLStreamReader value + * <li> QName name/String name - XMLStreamable value + * <li> QName name/String name - Java bean + * <li> QName name/String name - Datahandler + * + * </ul> + * <p/> As for the attributes, these are the possible combinations in the array + * <ul> + * <li> String name/QName name - String value + * </ul> + * Note that certain array methods have been deliberately removed to avoid + * complications. The generated code will take the trouble to lay the elements + * of the array in the correct order <p/> <p/> Hence there will be a parser impl + * that knows how to handle these types, and this parent parser will always + * delegate these tasks to the child pullparasers in effect this is one huge + * state machine that has only a few states and delegates things down to the + * child parsers whenever possible <p/> + * + * @version $Rev$ $Date$ + */ +public class XMLFragmentStreamReaderImpl implements XMLFragmentStreamReader { + + private static final int DELEGATED_STATE = 2; + private static final int END_ELEMENT_STATE = 1; + // states for this pullparser - it can only have four states + private static final int START_ELEMENT_STATE = 0; + private static final int TEXT_STATE = 3; + + protected NamedProperty[] attributes; + + // reference to the child reader + protected XMLFragmentStreamReader childReader; + // current property index + // initialized at zero + protected int index; + protected Map<String, String> declaredNamespaceMap = new HashMap<String, String>(); + protected QName elementQName; + + // we always create a new namespace context + protected DelegatingNamespaceContext namespaceContext = new DelegatingNamespaceContext(); + + protected NamedProperty[] elements; + + // integer field that keeps the state of this + // parser. + protected int state = START_ELEMENT_STATE; + + /* + * we need to pass in a namespace context since when delegated, we've no + * idea of the current namespace context. So it needs to be passed on here! + */ + public XMLFragmentStreamReaderImpl(QName elementQName, NamedProperty[] elements, NamedProperty[] attributes) { + // validate the lengths, since both the arrays are supposed + // to have + this.elements = elements == null ? new NamedProperty[0] : elements; + this.elementQName = elementQName; + this.attributes = attributes == null ? new NamedProperty[0] : attributes; + } + + protected XMLFragmentStreamReaderImpl(QName elementQName) { + this.elementQName = elementQName; + } + + /** + * add the namespace context + */ + + public void setParentNamespaceContext(NamespaceContext nsContext) { + // register the namespace context passed in to this + this.namespaceContext.setParentNsContext(nsContext); + + } + + protected NamedProperty[] getElements() { + return elements; + } + + protected NamedProperty[] getAttributes() { + return attributes; + } + + protected QName[] getNamespaces() { + return new QName[0]; + } + + /** + * @param prefix + * @param uri + */ + protected void addToNsMap(String prefix, String uri) { + if (!uri.equals(namespaceContext.getNamespaceURI(prefix))) { + namespaceContext.pushNamespace(prefix, uri); + declaredNamespaceMap.put(prefix, uri); + } + } + + public void close() throws XMLStreamException { + // do nothing here - we have no resources to free + } + + public int getAttributeCount() { + return (state == DELEGATED_STATE) ? childReader.getAttributeCount() : (state == START_ELEMENT_STATE + ? getAttributes().length : 0); + } + + public String getAttributeLocalName(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeLocalName(i); + } else if (state == START_ELEMENT_STATE) { + QName name = getAttributeName(i); + if (name == null) { + return null; + } else { + return name.getLocalPart(); + } + } else { + throw new IllegalStateException(); + } + } + + /** + * @param i + */ + public QName getAttributeName(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeName(i); + } else if (state == START_ELEMENT_STATE) { + if ((i >= (getAttributes().length)) || i < 0) { // out of range + return null; + } else { + // get the attribute pointer + QName attribPointer = getAttributes()[i].getKey(); + // case one - attrib name is null + // this should be the pointer to the OMAttribute then + if (attribPointer == null) { + throw new UnsupportedOperationException(); + } else if (attribPointer instanceof QName) { + return attribPointer; + } else { + return null; + } + } + } else { + throw new IllegalStateException(); // as per the API contract + } + + } + + public String getAttributeNamespace(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeNamespace(i); + } else if (state == START_ELEMENT_STATE) { + QName name = getAttributeName(i); + if (name == null) { + return null; + } else { + return name.getNamespaceURI(); + } + } else { + throw new IllegalStateException(); + } + } + + public String getAttributePrefix(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributePrefix(i); + } else if (state == START_ELEMENT_STATE) { + QName name = getAttributeName(i); + if (name == null) { + return null; + } else { + return name.getPrefix(); + } + } else { + throw new IllegalStateException(); + } + } + + public String getAttributeType(int i) { + return null; // not supported + } + + public String getAttributeValue(int i) { + if (state == DELEGATED_STATE) { + return childReader.getAttributeValue(i); + } else if (state == START_ELEMENT_STATE) { + if ((i >= (getAttributes().length)) || i < 0) { // out of range + return null; + } else { + // get the attribute pointer + QName attribPointer = getAttributes()[i].getKey(); + Object omAttribObj = getAttributes()[i].getValue(); + // case one - attrib name is null + // this should be the pointer to the OMAttribute then + if (attribPointer == null) { + throw new UnsupportedOperationException(); + } else if (attribPointer instanceof QName) { + return (String)omAttribObj; + } else { + return null; + } + } + } else { + throw new IllegalStateException(); + } + + } + + public String getAttributeValue(String nsUri, String localName) { + + int attribCount = getAttributeCount(); + String returnValue = null; + QName attribQualifiedName; + for (int i = 0; i < attribCount; i++) { + attribQualifiedName = getAttributeName(i); + if (nsUri == null) { + if (localName.equals(attribQualifiedName.getLocalPart())) { + returnValue = getAttributeValue(i); + break; + } + } else { + if (localName.equals(attribQualifiedName.getLocalPart()) && nsUri.equals(attribQualifiedName + .getNamespaceURI())) { + returnValue = getAttributeValue(i); + break; + } + } + + } + + return returnValue; + } + + public String getCharacterEncodingScheme() { + return null; // TODO - should we return something for this ? + } + + /** + * TODO implement the right contract for this + * + * @throws XMLStreamException + */ + public String getElementText() throws XMLStreamException { + if (state == DELEGATED_STATE) { + return childReader.getElementText(); + } else { + return null; + } + + } + + // ///////////////////////////////////////////////////////////////////////// + // / attribute handling + // ///////////////////////////////////////////////////////////////////////// + + public String getEncoding() { + if (state == DELEGATED_STATE) { + return childReader.getEncoding(); + } else { + // we've no idea what the encoding is going to be in this case + // perhaps we ought to return some constant here, which the user + // might + // have access to change! + return null; + } + } + + public int getEventType() { + if (state == START_ELEMENT_STATE) { + return START_ELEMENT; + } else if (state == END_ELEMENT_STATE) { + return END_ELEMENT; + } else if (state == TEXT_STATE) { + return CHARACTERS; + } else { // this is the delegated state + return childReader.getEventType(); + } + } + + public String getLocalName() { + if (state == DELEGATED_STATE) { + return childReader.getLocalName(); + } else if (state != TEXT_STATE) { + return elementQName.getLocalPart(); + } else { + throw new IllegalStateException(); + } + } + + /** + */ + public Location getLocation() { + // return a default location + return new Location() { + public int getCharacterOffset() { + return 0; + } + + public int getColumnNumber() { + return 0; + } + + public int getLineNumber() { + return 0; + } + + public String getPublicId() { + return null; + } + + public String getSystemId() { + return null; + } + }; + } + + public QName getName() { + if (state == DELEGATED_STATE) { + return childReader.getName(); + } else if (state != TEXT_STATE) { + return elementQName; + } else { + throw new IllegalStateException(); + } + + } + + public NamespaceContext getNamespaceContext() { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceContext(); + } else { + return namespaceContext; + } + + } + + public int getNamespaceCount() { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceCount(); + } else { + return declaredNamespaceMap.size(); + } + } + + /** + * @param i + */ + public String getNamespacePrefix(int i) { + if (state == DELEGATED_STATE) { + return childReader.getNamespacePrefix(i); + } else if (state != TEXT_STATE) { + // order the prefixes + String[] prefixes = makePrefixArray(); + if ((i >= prefixes.length) || (i < 0)) { + return null; + } else { + return prefixes[i]; + } + + } else { + throw new IllegalStateException(); + } + + } + + public String getNamespaceURI() { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceURI(); + } else if (state == TEXT_STATE) { + return null; + } else { + return elementQName.getNamespaceURI(); + } + } + + // ///////////////////////////////////////////////////////////////////////// + // //////////// end of attribute handling + // ///////////////////////////////////////////////////////////////////////// + + // ////////////////////////////////////////////////////////////////////////// + // //////////// namespace handling + // ////////////////////////////////////////////////////////////////////////// + + public String getNamespaceURI(int i) { + if (state == DELEGATED_STATE) { + return childReader.getNamespaceURI(i); + } else if (state != TEXT_STATE) { + String namespacePrefix = getNamespacePrefix(i); + return namespacePrefix == null ? null : (String)declaredNamespaceMap.get(namespacePrefix); + } else { + throw new IllegalStateException(); + } + + } + + public String getNamespaceURI(String prefix) { + return namespaceContext.getNamespaceURI(prefix); + } + + public String getPIData() { + throw new UnsupportedOperationException("Yet to be implemented !!"); + } + + public String getPITarget() { + throw new UnsupportedOperationException("Yet to be implemented !!"); + } + + public String getPrefix() { + if (state == DELEGATED_STATE) { + return childReader.getPrefix(); + } else if (state == TEXT_STATE) { + return null; + } else { + String prefix = elementQName.getPrefix(); + return "".equals(prefix) ? null : prefix; + } + } + + // ///////////////////////////////////////////////////////////////////////// + // /////// end of namespace handling + // ///////////////////////////////////////////////////////////////////////// + + /** + * @param key + * @throws IllegalArgumentException + */ + public Object getProperty(String key) throws IllegalArgumentException { + if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) { + return null; + } else if (state == TEXT_STATE) { + return null; + } else if (state == DELEGATED_STATE) { + return childReader.getProperty(key); + } else { + return null; + } + + } + + public String getText() { + if (state == DELEGATED_STATE) { + return childReader.getText(); + } else if (state == TEXT_STATE) { + return (String)getElements()[index - 1].getValue(); + } else { + throw new IllegalStateException(); + } + } + + public char[] getTextCharacters() { + if (state == DELEGATED_STATE) { + return childReader.getTextCharacters(); + } else if (state == TEXT_STATE) { + return getElements()[index - 1].getValue() == null ? new char[0] : ((String)getElements()[index - 1] + .getValue()).toCharArray(); + } else { + throw new IllegalStateException(); + } + } + + private int copy(int sourceStart, char[] target, int targetStart, int length) { + char[] source = getTextCharacters(); + if (sourceStart > source.length) { + throw new IndexOutOfBoundsException("source start > source length"); + } + int sourceLen = source.length - sourceStart; + if (length > sourceLen) { + length = sourceLen; + } + System.arraycopy(source, sourceStart, target, targetStart, length); + return sourceLen; + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + if (state == DELEGATED_STATE) { + return childReader.getTextCharacters(i, chars, i1, i2); + } else if (state == TEXT_STATE) { + return copy(i, chars, i1, i2); + } else { + throw new IllegalStateException(); + } + } + + public int getTextLength() { + if (state == DELEGATED_STATE) { + return childReader.getTextLength(); + } else if (state == TEXT_STATE) { + return getTextCharacters().length; + } else { + throw new IllegalStateException(); + } + } + + public int getTextStart() { + if (state == DELEGATED_STATE) { + return childReader.getTextStart(); + } else if (state == TEXT_STATE) { + return 0; // assume text always starts at 0 + } else { + throw new IllegalStateException(); + } + } + + public String getVersion() { + return null; + } + + public boolean hasName() { + // since this parser always has a name, the hasName + // has to return true if we are still navigating this element + // if not we should ask the child reader for it. + if (state == DELEGATED_STATE) { + return childReader.hasName(); + } else { + return state != TEXT_STATE; + } + } + + /** + * @throws XMLStreamException + */ + public boolean hasNext() throws XMLStreamException { + if (state == DELEGATED_STATE) { + if (childReader.isDone()) { + // the child reader is done. We shouldn't be getting the + // hasNext result from the child pullparser then + return true; + } else { + return childReader.hasNext(); + } + } else { + return state == START_ELEMENT_STATE || state == TEXT_STATE; + + } + } + + /** + * check the validity of this implementation + */ + public boolean hasText() { + if (state == DELEGATED_STATE) { + return childReader.hasText(); + } else { + return state == TEXT_STATE; + } + + } + + /** + * we need to split out the calling to the populate namespaces separately + * since this needs to be done *after* setting the parent namespace context. + * We cannot assume it will happen at construction! + */ + public void init() { + // here we have an extra issue to attend to. we need to look at the + // prefixes and URIs (the combination) and populate a HashMap of + // namespaces. The HashMap of namespaces will be used to serve the + // namespace context + + populateNamespaceContext(); + } + + public boolean isAttributeSpecified(int i) { + return false; // not supported + } + + public boolean isCharacters() { + if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) { + return false; + } + return childReader.isCharacters(); + } + + /** + * are we done ? + */ + public boolean isDone() { + return state == END_ELEMENT_STATE; + } + + public boolean isEndElement() { + if (state == START_ELEMENT_STATE) { + return false; + } else if (state == END_ELEMENT_STATE) { + return true; + } + return childReader.isEndElement(); + } + + public boolean isStandalone() { + return true; + } + + public boolean isStartElement() { + if (state == START_ELEMENT_STATE) { + return true; + } else if (state == END_ELEMENT_STATE) { + return false; + } + return childReader.isStartElement(); + } + + public boolean isWhiteSpace() { + if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) { + return false; + } + return childReader.isWhiteSpace(); + } + + /** + * Get the prefix list from the HashTable and take that into an array + */ + private String[] makePrefixArray() { + String[] prefixes = declaredNamespaceMap.keySet().toArray(new String[declaredNamespaceMap.size()]); + Arrays.sort(prefixes); + return prefixes; + } + + /** + * By far this should be the most important method in this class this method + * changes the state of the parser + */ + public int next() throws XMLStreamException { + int returnEvent = -1; // invalid state is the default state + switch (state) { + case START_ELEMENT_STATE: + // current element is start element. We should be looking at the + // property list and making a pullparser for the property value + if (getElements() == null || getElements().length == 0) { + // no properties - move to the end element state + // straight away + state = END_ELEMENT_STATE; + returnEvent = END_ELEMENT; + } else { + // there are properties. now we should delegate this task to + // a + // child reader depending on the property type + returnEvent = processProperties(); + + } + break; + case END_ELEMENT_STATE: + // we've reached the end element already. If the user tries to + // push + // further ahead then it is an exception + throw new XMLStreamException("Trying to go beyond the end of the pullparser"); + + case DELEGATED_STATE: + if (childReader.isDone()) { + // we've reached the end! + if (index > (getElements().length - 1)) { + state = END_ELEMENT_STATE; + returnEvent = END_ELEMENT; + } else { + returnEvent = processProperties(); + } + } else { + returnEvent = childReader.next(); + } + break; + + case TEXT_STATE: + // if there are any more event we should be delegating to + // processProperties. if not we just return an end element + if (index > (getElements().length - 1)) { + state = END_ELEMENT_STATE; + returnEvent = END_ELEMENT; + } else { + returnEvent = processProperties(); + } + break; + } + return returnEvent; + } + + // ///////////////////////////////////////////////////////////////////////// + // / Other utility methods + // //////////////////////////////////////////////////////////////////////// + + /** + * TODO implement this + * + * @throws XMLStreamException + */ + public int nextTag() throws XMLStreamException { + return 0; + } + + /** + * Populates a namespace context + */ + private void populateNamespaceContext() { + + // first add the current element namespace to the namespace context + // declare it if not found + addToNsMap(elementQName.getPrefix(), elementQName.getNamespaceURI()); + + for (QName n : getNamespaces()) { + addToNsMap(n.getPrefix(), n.getNamespaceURI()); + } + + // traverse through the attributes and populate the namespace context + // the attrib list can be of many combinations + // the valid combinations are + // String - String + // QName - QName + // null - OMAttribute + + for (int i = 0; i < getAttributes().length; i++) { // jump in two + QName attrQName = getAttributes()[i].getKey(); + if (!"".equals(attrQName.getNamespaceURI())) { + addToNsMap(attrQName.getPrefix(), attrQName.getNamespaceURI()); + } + } + } + + /** + * A convenient method to reuse the properties + * + * @return event to be thrown + * @throws XMLStreamException + */ + private int processProperties() throws XMLStreamException { + // move to the next property depending on the current property + // index + QName propertyQName = getElements()[index].getKey(); + boolean textFound = false; + if (propertyQName == null) { + throw new XMLStreamException("property key cannot be null!"); + } else if (ELEMENT_TEXT.equals(propertyQName.getLocalPart())) { + // propPointer being a String has a special case + // that is it can be a the special constant ELEMENT_TEXT that + // says this text event + textFound = true; + } + + // OK! we got the key. Now look at the value + Object propertyValue = getElements()[index].getValue(); + // cater for the special case now + if (textFound) { + // no delegation here - make the parser null and immediately + // return with the event characters + childReader = null; + state = TEXT_STATE; + ++index; + return CHARACTERS; + } else if (propertyValue == null) { + // if the value is null we delegate the work to a nullable + // parser + childReader = new NilElementStreamReader(propertyQName); + childReader.setParentNamespaceContext(this.namespaceContext); + childReader.init(); + } else if (propertyValue instanceof String) { + // strings are handled by the NameValuePairStreamReader + childReader = new NameValuePairStreamReader(propertyQName, (String)propertyValue); + childReader.setParentNamespaceContext(this.namespaceContext); + childReader.init(); + } else if (propertyValue instanceof String[]) { + // string[] are handled by the NameValueArrayStreamReader + // if the array is empty - skip it + if (((String[])propertyValue).length == 0) { + // advance the index + ++index; + return processProperties(); + } else { + childReader = new NameValueArrayStreamReader(propertyQName, (String[])propertyValue); + childReader.setParentNamespaceContext(this.namespaceContext); + childReader.init(); + } + + } else if (propertyValue instanceof XMLStreamable) { + // ADBbean has it's own method to get a reader + XMLStreamReader reader = ((XMLStreamable)propertyValue).getXMLStreamReader(propertyQName); + // we know for sure that this is an ADB XMLStreamreader. + // However we need to make sure that it is compatible + if (reader instanceof XMLFragmentStreamReader) { + childReader = (XMLFragmentStreamReader)reader; + childReader.setParentNamespaceContext(this.namespaceContext); + childReader.init(); + } else { + // wrap it to make compatible + childReader = new WrappingXMLStreamReader(reader); + } + } else if (propertyValue instanceof XMLStreamReader) { + XMLStreamReader reader = (XMLStreamReader)propertyValue; + if (reader instanceof XMLFragmentStreamReader) { + childReader = (XMLFragmentStreamReader)reader; + childReader.setParentNamespaceContext(this.namespaceContext); + childReader.init(); + } else { + // wrap it to make compatible + childReader = new WrappingXMLStreamReader(reader); + } + + } else { + // all special possibilities has been tried! Let's treat + // the thing as a bean and try generating events from it + childReader = new WrappingXMLStreamReader(new BeanXMLStreamReaderImpl(propertyQName, propertyValue)); + // we cannot register the namespace context here + } + + // set the state here + state = DELEGATED_STATE; + // we are done with the delegation + // increment the property index + ++index; + return childReader.getEventType(); + } + + public void require(int i, String string, String string1) throws XMLStreamException { + throw new UnsupportedOperationException(); + } + + public boolean standaloneSet() { + return true; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLGroupDataBinding.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLGroupDataBinding.java new file mode 100644 index 0000000000..f7c895db1e --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLGroupDataBinding.java @@ -0,0 +1,57 @@ +/* + * 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.sca.databinding.xml; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; + +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLEventWriter; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +import org.apache.tuscany.sca.databinding.impl.GroupDataBinding; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.XMLType; +import org.xml.sax.ContentHandler; +import org.xml.sax.InputSource; + +/** + * A Group DataBinding + * + * @version $Rev$ $Date$ + */ +public class XMLGroupDataBinding extends GroupDataBinding { + + public XMLGroupDataBinding() { + super(new Class[] {InputStream.class, OutputStream.class, Reader.class, Writer.class, + // Source.class, Result.class, + InputSource.class, ContentHandler.class, XMLStreamReader.class, + XMLStreamWriter.class, XMLEventReader.class, XMLEventWriter.class}); + } + + @Override + protected Object getLogical(Class<?> markerType, Operation operation) { + return XMLType.UNKNOWN; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2Node.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2Node.java new file mode 100644 index 0000000000..e2d0416aec --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2Node.java @@ -0,0 +1,75 @@ +/* + * 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.sca.databinding.xml; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.DataPipe; +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.apache.tuscany.sca.databinding.impl.DOMHelper; +import org.w3c.dom.Document; +import org.w3c.dom.Node; +import org.xml.sax.ContentHandler; + +/** + * Transform DOM Node to XML XMLStreamReader + * + * @version $Rev$ $Date$ + */ +public class XMLStreamReader2Node extends BaseTransformer<XMLStreamReader, Node> implements + PullTransformer<XMLStreamReader, Node> { + + private XMLStreamReader2SAX stax2sax = new XMLStreamReader2SAX(); + + public Node transform(XMLStreamReader source, TransformationContext context) { + try { + DataPipe<ContentHandler, Node> pipe = new SAX2DOMPipe().newInstance(); + stax2sax.transform(source, pipe.getSink(), context); + Node node = pipe.getResult(); + source.close(); + if (node instanceof Document) { + Document doc = (Document)node; + return DOMHelper.adjustElementName(context, doc.getDocumentElement()); + } else { + return node; + } + } catch (Exception e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<XMLStreamReader> getSourceType() { + return XMLStreamReader.class; + } + + @Override + protected Class<Node> getTargetType() { + return Node.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2SAX.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2SAX.java new file mode 100644 index 0000000000..9b39f039b1 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2SAX.java @@ -0,0 +1,70 @@ +/* + * 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.sca.databinding.xml; + +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PushTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; +import org.xml.sax.ContentHandler; + +/** + * XMLStreamReader to SAX events + * + * @version $Rev$ $Date$ + */ +public class XMLStreamReader2SAX extends BaseTransformer<XMLStreamReader, ContentHandler> implements + PushTransformer<XMLStreamReader, ContentHandler> { + + @Override + protected Class<ContentHandler> getTargetType() { + return ContentHandler.class; + } + + @Override + protected Class<XMLStreamReader> getSourceType() { + return XMLStreamReader.class; + } + + /** + * @see org.apache.tuscany.sca.databinding.PushTransformer#getWeight() + */ + @Override + public int getWeight() { + return 20; + } + + /** + * @see org.apache.tuscany.sca.databinding.PushTransformer#transform(java.lang.Object, + * java.lang.Object, + * org.apache.tuscany.sca.databinding.TransformationContext) + */ + public void transform(XMLStreamReader source, ContentHandler sink, TransformationContext context) { + StAX2SAXAdapter adapter = new StAX2SAXAdapter(false); + try { + adapter.parse(source, sink); + source.close(); + } catch (Exception e) { + throw new TransformationException(e); + } + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2String.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2String.java new file mode 100644 index 0000000000..6db731bc9f --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamReader2String.java @@ -0,0 +1,57 @@ +/* + * 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.sca.databinding.xml; + +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +import org.apache.tuscany.sca.databinding.PullTransformer; +import org.apache.tuscany.sca.databinding.TransformationContext; +import org.apache.tuscany.sca.databinding.TransformationException; +import org.apache.tuscany.sca.databinding.impl.BaseTransformer; + +public class XMLStreamReader2String extends BaseTransformer<XMLStreamReader, String> implements + PullTransformer<XMLStreamReader, String> { + + public String transform(XMLStreamReader source, TransformationContext context) { + try { + String str = StAXHelper.save(source); + source.close(); + return str; + } catch (XMLStreamException e) { + throw new TransformationException(e); + } + } + + @Override + protected Class<XMLStreamReader> getSourceType() { + return XMLStreamReader.class; + } + + @Override + protected Class<String> getTargetType() { + return String.class; + } + + @Override + public int getWeight() { + return 40; + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamSerializer.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamSerializer.java new file mode 100644 index 0000000000..920ebb511c --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamSerializer.java @@ -0,0 +1,287 @@ +/* + * 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.sca.databinding.xml; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import javax.xml.stream.XMLStreamWriter; + +/** + * The XMLStreamSerializer pulls events from the XMLStreamReader and dumps into the XMLStreamWriter + * + * @version $Rev$ $Date$ + */ +public class XMLStreamSerializer implements XMLStreamConstants { + public static final String NAMESPACE_PREFIX = "ns"; + private static int namespaceSuffix; + + /* + * The behavior of the Serializer is such that it returns when it encounters the starting element for the second + * time. The depth variable tracks the depth of the Serializer and tells it when to return. Note that it is assumed + * that this Serialization starts on an Element. + */ + + /** + * Field depth + */ + private int depth; + + /** + * Generates a unique namespace prefix that is not in the scope of the NamespaceContext + * + * @param nsCtxt + * @return string + */ + private String generateUniquePrefix(NamespaceContext nsCtxt) { + String prefix = NAMESPACE_PREFIX + namespaceSuffix++; + // null should be returned if the prefix is not bound! + while (nsCtxt.getNamespaceURI(prefix) != null) { + prefix = NAMESPACE_PREFIX + namespaceSuffix++; + } + + return prefix; + } + + /** + * Method serialize. + * + * @param node + * @param writer + * @throws XMLStreamException + */ + public void serialize(XMLStreamReader node, XMLStreamWriter writer) throws XMLStreamException { + serializeNode(node, writer); + } + + /** + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeAttributes(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + int count = reader.getAttributeCount(); + String prefix; + String namespaceName; + String writerPrefix; + for (int i = 0; i < count; i++) { + prefix = reader.getAttributePrefix(i); + namespaceName = reader.getAttributeNamespace(i); + /* + * Due to parser implementations returning null as the namespace URI (for the empty namespace) we need to + * make sure that we deal with a namespace name that is not null. The best way to work around this issue is + * to set the namespace URI to "" if it is null + */ + if (namespaceName == null) { + namespaceName = ""; + } + + writerPrefix = writer.getPrefix(namespaceName); + + if (!"".equals(namespaceName)) { + // prefix has already being declared but this particular + // attrib has a + // no prefix attached. So use the prefix provided by the + // writer + if (writerPrefix != null && (prefix == null || prefix.equals(""))) { + writer.writeAttribute(writerPrefix, namespaceName, reader.getAttributeLocalName(i), reader + .getAttributeValue(i)); + + // writer prefix is available but different from the + // current + // prefix of the attrib. We should be declaring the new + // prefix + // as a namespace declaration + } else if (prefix != null && !"".equals(prefix) && !prefix.equals(writerPrefix)) { + writer.writeNamespace(prefix, namespaceName); + writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader + .getAttributeValue(i)); + + // prefix is null (or empty), but the namespace name is + // valid! it has not + // being written previously also. So we need to generate + // a prefix + // here + } else if (prefix == null || prefix.equals("")) { + prefix = generateUniquePrefix(writer.getNamespaceContext()); + writer.writeNamespace(prefix, namespaceName); + writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader + .getAttributeValue(i)); + } else { + writer.writeAttribute(prefix, namespaceName, reader.getAttributeLocalName(i), reader + .getAttributeValue(i)); + } + } else { + // empty namespace is equal to no namespace! + writer.writeAttribute(reader.getAttributeLocalName(i), reader.getAttributeValue(i)); + } + + } + } + + /** + * Method serializeCData. + * + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeCData(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + writer.writeCData(reader.getText()); + } + + /** + * Method serializeComment. + * + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeComment(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + writer.writeComment(reader.getText()); + } + + /** + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeElement(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + String prefix = reader.getPrefix(); + String nameSpaceName = reader.getNamespaceURI(); + if (nameSpaceName != null) { + String writerPrefix = writer.getPrefix(nameSpaceName); + if (writerPrefix != null) { + writer.writeStartElement(nameSpaceName, reader.getLocalName()); + } else { + if (prefix != null) { + writer.writeStartElement(prefix, reader.getLocalName(), nameSpaceName); + writer.writeNamespace(prefix, nameSpaceName); + // writer.setPrefix(prefix, nameSpaceName); + } else { + // [rfeng] We need to set default NS 1st before calling writeStateElement + writer.setDefaultNamespace(nameSpaceName); + writer.writeStartElement(nameSpaceName, reader.getLocalName()); + writer.writeDefaultNamespace(nameSpaceName); + } + } + } else { + writer.writeStartElement(reader.getLocalName()); + } + + // add the namespaces + int count = reader.getNamespaceCount(); + String namespacePrefix; + for (int i = 0; i < count; i++) { + namespacePrefix = reader.getNamespacePrefix(i); + // [rfeng] The following is commented out to allow to default ns + // if (namespacePrefix != null && namespacePrefix.length() == 0) { + // continue; + // } + + serializeNamespace(namespacePrefix, reader.getNamespaceURI(i), writer); + } + + // add attributes + serializeAttributes(reader, writer); + + } + + /** + * Method serializeEndElement. + * + * @param writer + * @throws XMLStreamException + */ + protected void serializeEndElement(XMLStreamWriter writer) throws XMLStreamException { + writer.writeEndElement(); + } + + /** + * Method serializeNamespace. + * + * @param prefix + * @param uri + * @param writer + * @throws XMLStreamException + */ + private void serializeNamespace(String prefix, String uri, XMLStreamWriter writer) throws XMLStreamException { + String prefix1 = writer.getPrefix(uri); + if (prefix1 == null) { + writer.writeNamespace(prefix, uri); + // writer.setPrefix(prefix, uri); + } + } + + /** + * Method serializeNode. + * + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeNode(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + while (true) { + int event = reader.getEventType(); + if (event == START_ELEMENT) { + serializeElement(reader, writer); + depth++; + } else if (event == ATTRIBUTE) { + serializeAttributes(reader, writer); + } else if (event == CHARACTERS) { + serializeText(reader, writer); + } else if (event == COMMENT) { + serializeComment(reader, writer); + } else if (event == CDATA) { + serializeCData(reader, writer); + } else if (event == END_ELEMENT) { + serializeEndElement(writer); + depth--; + } else if (event == START_DOCUMENT) { + depth++; // if a start document is found then increment + writer.writeStartDocument(); + // the depth + } else if (event == END_DOCUMENT) { + if (depth != 0) { + depth--; // for the end document - reduce the depth + } + writer.writeEndDocument(); + } + if (depth == 0) { + break; + } + if (reader.hasNext()) { + reader.next(); + } else { + break; + } + } + } + + /** + * @param reader + * @param writer + * @throws XMLStreamException + */ + protected void serializeText(XMLStreamReader reader, XMLStreamWriter writer) throws XMLStreamException { + writer.writeCharacters(reader.getText()); + } +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamable.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamable.java new file mode 100644 index 0000000000..f32f93d098 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStreamable.java @@ -0,0 +1,37 @@ +/* + * 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.sca.databinding.xml; + +import javax.xml.namespace.QName; +import javax.xml.stream.XMLStreamReader; + +/** + * An interface represents data that can be read using StAX streaming + * + * @version $Rev$ $Date$ + */ +public interface XMLStreamable { + /** + * Get the XMLStreamReader for StAX processing + * + * @param rootElementName the name of the element to be generated + * @return Returns a pull parser. + */ + XMLStreamReader getXMLStreamReader(QName rootElementName); +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStringDataBinding.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStringDataBinding.java new file mode 100644 index 0000000000..22b173dce5 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XMLStringDataBinding.java @@ -0,0 +1,50 @@ +/* + * 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.sca.databinding.xml; + + +import org.apache.tuscany.sca.databinding.impl.BaseDataBinding; +import org.apache.tuscany.sca.interfacedef.DataType; +import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.util.XMLType; + +/** + * A DataBinding for the XML string + * + * @version $Rev$ $Date$ + */ +public class XMLStringDataBinding extends BaseDataBinding { + public static final String NAME = String.class.getName(); + + public XMLStringDataBinding() { + super(NAME, String.class); + } + + @Override + public boolean introspect(DataType type, Operation operation) { + if (type.getPhysical() == String.class && NAME.equals(type.getDataBinding())) { + type.setDataBinding(NAME); + type.setLogical(XMLType.UNKNOWN); + return true; + } else { + return false; + } + } +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XmlNode.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XmlNode.java new file mode 100644 index 0000000000..86ebd627f7 --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XmlNode.java @@ -0,0 +1,69 @@ +/* + * 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.sca.databinding.xml; + +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.QName; + +/** + * @version $Rev$ $Date$ + */ +public interface XmlNode { + enum Type {ELEMENT, ATTRIBUTE, CHARACTERS, READER}; + /** + * Returns the children of the receiver as an <code>Iterator</code>. + */ + Iterator<XmlNode> children(); + + /** + * Returns the attributes of the element as an <code>List</code>. Namespace declarations + * should be excluded. + * + * @return + */ + List<XmlNode> attributes(); + + /** + * Returns a map of prefix to namespace URI + * @return + */ + Map<String, String> namespaces(); + + /** + * Return the QName of the element. If it's for a text node, the name is null. + * @return + */ + QName getName(); + + /** + * Return the text value of the leaf element + * @return + */ + <T> T getValue(); + + /** + * Return the type of the XML node + * @return + */ + Type getType(); +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XmlNodeIterator.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XmlNodeIterator.java new file mode 100644 index 0000000000..3dd125463e --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XmlNodeIterator.java @@ -0,0 +1,355 @@ +/* + * 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.sca.databinding.xml; + +import java.util.ArrayList; +import java.util.EmptyStackException; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.NamespaceContext; + +/** + * @version $Rev$ $Date$ + */ +public class XmlNodeIterator implements Iterator<XmlNode> { + public static final int START = 0; + public static final int END = 1; + + protected FastStack<ElementHolder> stack; + protected int state; + protected NamespaceContextImpl nsContext; + + public XmlNodeIterator(XmlNode rootNode) { + super(); + List<XmlNode> v = new ArrayList<XmlNode>(1); + v.add(rootNode); + stack = new FastStack<ElementHolder>(); + Iterator<XmlNode> i = v.iterator(); + stack.push(new ElementHolder(null, i)); + this.state = START; + this.nsContext = new NamespaceContextImpl(null); + } + + public boolean hasNext() { + return !(stack.empty() || (state == END && stack.peek().parent == null)); + } + + public XmlNode next() { + this.state = START; + ElementHolder element = stack.peek(); + Iterator<XmlNode> it = element.children; + if (it == null || (!it.hasNext())) { + // End of the children, return END event of parent + stack.pop(); + this.state = END; + this.nsContext = (NamespaceContextImpl)nsContext.getParent(); + return element.parent; + } + XmlNode node = it.next(); + stack.push(new ElementHolder(node, node.children())); + this.nsContext = new NamespaceContextImpl(this.nsContext); + populateNamespaces(node); + return node; + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + public int getState() { + return state; + } + + public NamespaceContext getNamespaceContext() { + return nsContext; + } + + private void populateNamespaces(XmlNode element) { + if (element.getName() != null) { + if (element.namespaces() != null) { + for (Map.Entry<String, String> e : element.namespaces().entrySet()) { + nsContext.register(e.getKey(), e.getValue()); + } + } + } + } + + private static class ElementHolder { + private XmlNode parent; + private Iterator<XmlNode> children; + + public ElementHolder(XmlNode parent, Iterator<XmlNode> children) { + this.parent = parent; + this.children = children; + } + } + + private static class NamespaceContextImpl implements NamespaceContext { + private NamespaceContext parent; + private Map<String, String> map = new HashMap<String, String>(); + + /** + * @param parent + */ + public NamespaceContextImpl(NamespaceContext parent) { + super(); + this.parent = parent; + if (parent == null) { + map.put("xml", "http://www.w3.org/XML/1998/namespace"); + map.put("xmlns", "http://www.w3.org/2000/xmlns/"); + } + } + + public String getNamespaceURI(String prefix) { + if (prefix == null) { + throw new IllegalArgumentException("Prefix is null"); + } + + String ns = (String)map.get(prefix); + if (ns != null) { + return ns; + } + if (parent != null) { + return parent.getNamespaceURI(prefix); + } + return null; + } + + public String getPrefix(String nsURI) { + if (nsURI == null) + throw new IllegalArgumentException("Namespace is null"); + for (Iterator<Map.Entry<String, String>> i = map.entrySet().iterator(); i.hasNext();) { + Map.Entry<String, String> entry = i.next(); + if (entry.getValue().equals(nsURI)) { + return entry.getKey(); + } + } + if (parent != null) { + return parent.getPrefix(nsURI); + } + return null; + } + + public Iterator getPrefixes(String nsURI) { + List<String> prefixList = new ArrayList<String>(); + for (Iterator<Map.Entry<String, String>> i = map.entrySet().iterator(); i.hasNext();) { + Map.Entry<String, String> entry = i.next(); + if (entry.getValue().equals(nsURI)) { + prefixList.add(entry.getKey()); + } + } + final Iterator currentIterator = prefixList.iterator(); + final Iterator parentIterator = parent != null ? null : parent.getPrefixes(nsURI); + return new Iterator() { + + public boolean hasNext() { + return currentIterator.hasNext() || (parentIterator != null && parentIterator.hasNext()); + } + + public Object next() { + if (!hasNext()) { + throw new IllegalStateException("End of iterator has reached"); + } + return currentIterator.hasNext() ? currentIterator.next() : parentIterator.next(); + } + + public void remove() { + throw new UnsupportedOperationException(); + } + + }; + + } + + public void register(String prefix, String ns) { + map.put(prefix, ns); + } + + public NamespaceContext getParent() { + return parent; + } + + @Override + public String toString() { + StringBuffer sb = new StringBuffer(map.toString()); + if (parent != null) { + sb.append("\nParent: "); + sb.append(parent); + } + return sb.toString(); + } + } + + /** + * An implementation of the {@link java.util.Stack} API that is based on an <code>ArrayList</code> instead of a + * <code>Vector</code>, so it is not synchronized to protect against multi-threaded access. The implementation is + * therefore operates faster in environments where you do not need to worry about multiple thread contention. + * <p> + * The removal order of an <code>ArrayStack</code> is based on insertion order: The most recently added element is + * removed first. The iteration order is <i>not</i> the same as the removal order. The iterator returns elements + * from the bottom up, whereas the {@link #remove()} method removes them from the top down. + * <p> + * Unlike <code>Stack</code>, <code>ArrayStack</code> accepts null entries. + */ + public static class FastStack<T> extends ArrayList<T> { + + /** Ensure Serialization compatibility */ + private static final long serialVersionUID = 2130079159931574599L; + + /** + * Constructs a new empty <code>ArrayStack</code>. The initial size is controlled by <code>ArrayList</code> + * and is currently 10. + */ + public FastStack() { + super(); + } + + /** + * Constructs a new empty <code>ArrayStack</code> with an initial size. + * + * @param initialSize the initial size to use + * @throws IllegalArgumentException if the specified initial size is negative + */ + public FastStack(int initialSize) { + super(initialSize); + } + + /** + * Return <code>true</code> if this stack is currently empty. + * <p> + * This method exists for compatibility with <code>java.util.Stack</code>. New users of this class should use + * <code>isEmpty</code> instead. + * + * @return true if the stack is currently empty + */ + public boolean empty() { + return isEmpty(); + } + + /** + * Returns the top item off of this stack without removing it. + * + * @return the top item on the stack + * @throws EmptyStackException if the stack is empty + */ + public T peek() throws EmptyStackException { + int n = size(); + if (n <= 0) { + throw new EmptyStackException(); + } else { + return get(n - 1); + } + } + + /** + * Returns the n'th item down (zero-relative) from the top of this stack without removing it. + * + * @param n the number of items down to go + * @return the n'th item on the stack, zero relative + * @throws EmptyStackException if there are not enough items on the stack to satisfy this request + */ + public T peek(int n) throws EmptyStackException { + int m = (size() - n) - 1; + if (m < 0) { + throw new EmptyStackException(); + } else { + return get(m); + } + } + + /** + * Pops the top item off of this stack and return it. + * + * @return the top item on the stack + * @throws EmptyStackException if the stack is empty + */ + public T pop() throws EmptyStackException { + int n = size(); + if (n <= 0) { + throw new EmptyStackException(); + } else { + return remove(n - 1); + } + } + + /** + * Pushes a new item onto the top of this stack. The pushed item is also returned. This is equivalent to calling + * <code>add</code>. + * + * @param item the item to be added + * @return the item just pushed + */ + public Object push(T item) { + add(item); + return item; + } + + /** + * Returns the top-most index for the object in the stack + * + * @param object the object to be searched for + * @return top-most index, or -1 if not found + */ + public int search(T object) { + int i = size() - 1; // Current index + while (i >= 0) { + T current = get(i); + if ((object == null && current == null) || (object != null && object.equals(current))) { + return i; + } + i--; + } + return -1; + } + + /** + * Returns the element on the top of the stack. + * + * @return the element on the top of the stack + * @throws EmptyStackException if the stack is empty + */ + public T get() { + int size = size(); + if (size == 0) { + throw new EmptyStackException(); + } + return get(size - 1); + } + + /** + * Removes the element on the top of the stack. + * + * @return the removed element + * @throws EmptyStackException if the stack is empty + */ + public T remove() { + int size = size(); + if (size == 0) { + throw new EmptyStackException(); + } + return remove(size - 1); + } + + } + +} diff --git a/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XmlTreeStreamReaderImpl.java b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XmlTreeStreamReaderImpl.java new file mode 100644 index 0000000000..f4bc357c7d --- /dev/null +++ b/sca-java-1.x/tags/1.6.2-RC1/modules/databinding/src/main/java/org/apache/tuscany/sca/databinding/xml/XmlTreeStreamReaderImpl.java @@ -0,0 +1,531 @@ +/* + * 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.sca.databinding.xml; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.Map; + +import javax.xml.namespace.NamespaceContext; +import javax.xml.namespace.QName; +import javax.xml.stream.Location; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; + +/** + * + * @version $Rev$ $Date$ + */ +public class XmlTreeStreamReaderImpl implements XMLStreamReader { + + protected int state; + protected XmlNodeIterator iterator; + protected XmlNode current; + + protected XMLStreamReader reader; + + /* + * we need to pass in a namespace context since when delegated, we've no + * idea of the current namespace context. So it needs to be passed on here! + */ + public XmlTreeStreamReaderImpl(XmlNode root) { + this.iterator = new XmlNodeIterator(root); + this.current = null; + this.state = START_DOCUMENT; + this.reader = null; + } + + public void close() throws XMLStreamException { + if (reader != null) { + reader.close(); + } + } + + private void checkElementState() { + if (getEventType() != START_ELEMENT && getEventType() != END_ELEMENT) { + throw new IllegalStateException(); + } + } + + private List<XmlNode> getAttributes() { + if (current != null && current.attributes() != null) { + return current.attributes(); + } else { + return Collections.emptyList(); + } + } + + public int getAttributeCount() { + checkElementState(); + if (reader != null) { + return reader.getAttributeCount(); + } + return getAttributes().size(); + } + + public String getAttributeLocalName(int i) { + checkElementState(); + if (reader != null) { + return reader.getAttributeLocalName(i); + } + return getAttributes().get(i).getName().getLocalPart(); + } + + /** + * @param i + */ + public QName getAttributeName(int i) { + checkElementState(); + if (reader != null) { + return reader.getAttributeName(i); + } + return getAttributes().get(i).getName(); + } + + public String getAttributeNamespace(int i) { + checkElementState(); + if (reader != null) { + return reader.getAttributeNamespace(i); + } + return getAttributes().get(i).getName().getNamespaceURI(); + } + + public String getAttributePrefix(int i) { + checkElementState(); + if (reader != null) { + return reader.getAttributePrefix(i); + } + return getAttributes().get(i).getName().getPrefix(); + } + + public String getAttributeType(int i) { + if (reader != null) { + return reader.getAttributeType(i); + } + return null; // not supported + } + + public String getAttributeValue(int i) { + checkElementState(); + if (reader != null) { + return reader.getAttributeValue(i); + } + return getAttributes().get(i).getValue(); + } + + public String getAttributeValue(String nsUri, String localName) { + checkElementState(); + if (reader != null) { + return reader.getAttributeValue(nsUri, localName); + } + int count = getAttributeCount(); + String value = null; + QName attrQName; + for (int i = 0; i < count; i++) { + attrQName = getAttributeName(i); + if (nsUri == null) { + if (localName.equals(attrQName.getLocalPart())) { + value = getAttributeValue(i); + break; + } + } else { + if (localName.equals(attrQName.getLocalPart()) && nsUri.equals(attrQName.getNamespaceURI())) { + value = getAttributeValue(i); + break; + } + } + + } + + return value; + } + + public String getCharacterEncodingScheme() { + if (reader != null) { + return reader.getCharacterEncodingScheme(); + } + return "UTF-8"; + } + + public String getElementText() throws XMLStreamException { + checkElementState(); + if (reader != null) { + return reader.getElementText(); + } + return current.getValue(); + } + + public String getEncoding() { + if (reader != null) { + return reader.getEncoding(); + } + return "UTF-8"; + } + + public int getEventType() { + return state; + } + + public String getLocalName() { + checkElementState(); + if (reader != null) { + return reader.getLocalName(); + } + return current.getName().getLocalPart(); + } + + /** + */ + public Location getLocation() { + if (reader != null) { + return reader.getLocation(); + } + // return a default location + return new Location() { + public int getCharacterOffset() { + return 0; + } + + public int getColumnNumber() { + return 0; + } + + public int getLineNumber() { + return 0; + } + + public String getPublicId() { + return null; + } + + public String getSystemId() { + return null; + } + }; + } + + public QName getName() { + checkElementState(); + if (reader != null) { + return reader.getName(); + } + return current.getName(); + } + + public NamespaceContext getNamespaceContext() { + if (reader != null) { + return reader.getNamespaceContext(); + } + return iterator.getNamespaceContext(); + } + + private Map<String, String> getNamespaces() { + if (current != null && current.namespaces() != null) { + return current.namespaces(); + } else { + return Collections.emptyMap(); + } + } + + public int getNamespaceCount() { + checkElementState(); + if (reader != null) { + return reader.getNamespaceCount(); + } + return getNamespaces().size(); + } + + /** + * @param i + */ + public String getNamespacePrefix(int i) { + checkElementState(); + if (reader != null) { + return reader.getNamespacePrefix(i); + } + return new ArrayList<Map.Entry<String, String>>(getNamespaces().entrySet()).get(i).getKey(); + } + + public String getNamespaceURI() { + checkElementState(); + if (reader != null) { + return reader.getNamespaceURI(); + } + return current.getName().getNamespaceURI(); + } + + public String getNamespaceURI(int i) { + checkElementState(); + if (reader != null) { + return reader.getNamespaceURI(i); + } + return new ArrayList<Map.Entry<String, String>>(getNamespaces().entrySet()).get(i).getValue(); + } + + public String getNamespaceURI(String prefix) { + if (reader != null) { + return reader.getNamespaceURI(prefix); + } + return getNamespaceContext().getNamespaceURI(prefix); + } + + public String getPIData() { + if (reader != null) { + return reader.getPIData(); + } + throw new UnsupportedOperationException("Yet to be implemented !!"); + } + + public String getPITarget() { + if (reader != null) { + return reader.getPITarget(); + } + throw new UnsupportedOperationException("Yet to be implemented !!"); + } + + public String getPrefix() { + if (reader != null) { + return reader.getPrefix(); + } + if (state == START_ELEMENT || state == END_ELEMENT) { + String prefix = current.getName().getPrefix(); + return "".equals(prefix) ? null : prefix; + } else if (state == START_DOCUMENT) { + return null; + } else { + throw new IllegalStateException("State==" + state); + } + } + + /** + * @param key + * @throws IllegalArgumentException + */ + public Object getProperty(String key) throws IllegalArgumentException { + if (reader != null) { + return reader.getProperty(key); + } + return null; + } + + public String getText() { + if (reader != null) { + return reader.getText(); + } + return current.getValue(); + } + + public char[] getTextCharacters() { + if (reader != null) { + return reader.getTextCharacters(); + } + String value = current.getValue(); + return value == null ? new char[0] : value.toCharArray(); + } + + private int copy(int sourceStart, char[] target, int targetStart, int length) { + char[] source = getTextCharacters(); + if (sourceStart > source.length) { + throw new IndexOutOfBoundsException("source start > source length"); + } + int sourceLen = source.length - sourceStart; + if (length > sourceLen) { + length = sourceLen; + } + System.arraycopy(source, sourceStart, target, targetStart, length); + return sourceLen; + } + + public int getTextCharacters(int i, char[] chars, int i1, int i2) throws XMLStreamException { + if (reader != null) { + return reader.getTextCharacters(i, chars, i1, i2); + } + return copy(i, chars, i1, i2); + } + + public int getTextLength() { + if (reader != null) { + return reader.getTextLength(); + } + return getTextCharacters().length; + } + + public int getTextStart() { + if (reader != null) { + return reader.getTextStart(); + } + return 0; + } + + public String getVersion() { + return "1.0"; + } + + public boolean hasName() { + if (reader != null) { + return reader.hasName(); + } + return current.getName() != null; + } + + /** + * @throws XMLStreamException + */ + public boolean hasNext() throws XMLStreamException { + return iterator.hasNext() || state != END_DOCUMENT || (reader != null && reader.hasNext()); + } + + public boolean hasText() { + if (reader != null) { + return reader.hasText(); + } + return current.getType() == XmlNode.Type.CHARACTERS; + } + + public boolean isAttributeSpecified(int i) { + if (reader != null) { + return reader.isAttributeSpecified(i); + } + return false; // not supported + } + + public boolean isCharacters() { + if (reader != null) { + return reader.isCharacters(); + } + return current.getType() == XmlNode.Type.CHARACTERS; + } + + public boolean isEndElement() { + if (reader != null) { + return reader.isEndElement(); + } + return getEventType() == END_ELEMENT; + } + + public boolean isStandalone() { + return true; + } + + public boolean isStartElement() { + if (reader != null) { + return reader.isStartElement(); + } + return getEventType() == START_ELEMENT; + } + + public boolean isWhiteSpace() { + if (reader != null) { + return reader.isWhiteSpace(); + } + return false; + } + + /** + * By far this should be the most important method in this class this method + * changes the state of the parser + */ + public int next() throws XMLStreamException { + if (!hasNext()) { + throw new IllegalStateException("No more events"); + } + if (reader != null) { + if (!reader.hasNext()) { + this.reader = null; + } else { + // Go to the delegation mode + state = reader.next(); + return state; + } + } + if (!iterator.hasNext()) { + state = END_DOCUMENT; + current = null; + return state; + } + current = iterator.next(); + XmlNode.Type type = current.getType(); + + int itState = iterator.getState(); + if (itState == XmlNodeIterator.END) { + if (type == XmlNode.Type.ELEMENT) { + state = END_ELEMENT; + } else { + // Ignore the pop + state = next(); + } + } + if (itState == XmlNodeIterator.START) { + if (type == XmlNode.Type.ELEMENT) { + state = START_ELEMENT; + } else if (type == XmlNode.Type.CHARACTERS) { + state = CHARACTERS; + } else if (type == XmlNode.Type.READER) { + XMLStreamReader value = current.getValue(); + this.reader = new WrappingXMLStreamReader(value); + state = reader.getEventType(); + return state; + } + } + return state; + } + + /** + * TODO implement this + * + * @throws XMLStreamException + */ + public int nextTag() throws XMLStreamException { + while (true) { + int event = next(); + if (event == START_ELEMENT || event == END_ELEMENT) { + return event; + } + } + } + + public void require(int i, String ns, String localPart) throws XMLStreamException { + if (reader != null) { + reader.require(i, ns, localPart); + return; + } + int event = getEventType(); + if (event != i) { + throw new IllegalStateException("Event type is " + event + " (!=" + i + ")"); + } + QName name = getName(); + String ns1 = name.getNamespaceURI(); + String localName1 = name.getLocalPart(); + + if (ns != null && !ns.equals(ns1)) { + throw new IllegalStateException("Namespace URI is " + ns1 + " (!=" + ns + ")"); + } + + if (localPart != null && !localPart.equals(localName1)) { + throw new IllegalStateException("Local name is " + localName1 + " (!=" + localPart + ")"); + } + + } + + public boolean standaloneSet() { + return true; + } + +} |