You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tuscany.apache.org by rf...@apache.org on 2007/03/02 07:32:27 UTC

svn commit: r513629 [3/3] - in /incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src: main/java/org/apache/tuscany/core/databinding/javabeans/ main/java/org/apache/tuscany/core/databinding/xml/ test/java/org/apache/tuscany/core/databindi...

Added: incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLFragmentStreamReaderImpl.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLFragmentStreamReaderImpl.java?view=auto&rev=513629
==============================================================================
--- incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLFragmentStreamReaderImpl.java (added)
+++ incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLFragmentStreamReaderImpl.java Thu Mar  1 22:32:26 2007
@@ -0,0 +1,856 @@
+/*
+ * 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.core.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 handes 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 (QName)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 { // 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 seperately
+     * 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 hastable and take that into an array
+     */
+    private String[] makePrefixArray() {
+        String[] prefixes = (String[])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
+                    // straightaway
+                    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 possiblilities has been tried! Let's treat
+            // the thing as a bean and try generating events from it
+            childReader = new WrappingXMLStreamReader(BeanUtil.getXMLStreamReader(propertyValue, propertyQName));
+            // 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;
+    }
+
+}

Propchange: incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLFragmentStreamReaderImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLFragmentStreamReaderImpl.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamSerializer.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamSerializer.java?view=auto&rev=513629
==============================================================================
--- incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamSerializer.java (added)
+++ incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamSerializer.java Thu Mar  1 22:32:26 2007
@@ -0,0 +1,281 @@
+package org.apache.tuscany.core.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
+ */
+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 serilizer 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.getNamespaceContext().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 decalring 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 {
+                    writer.writeStartElement(nameSpaceName, reader.getLocalName());
+                    writer.writeDefaultNamespace(nameSpaceName);
+                    writer.setDefaultNamespace(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);
+            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 {
+        // TODO We get the StAXWriter at this point and uses it hereafter
+        // assuming that this is the only entry point
+        // to this class.
+        // If there can be other classes calling methodes of this we might
+        // need to change methode signatures to
+        // OMOutputer
+        while (reader.hasNext()) {
+            int event = reader.next();
+            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
+                // the depth
+            } else if (event == END_DOCUMENT) {
+                if (depth != 0) {
+                    depth--; // for the end document - reduce the depth
+                }
+                try {
+                    serializeEndElement(writer);
+                } catch (Exception e) {
+                    // TODO: log exceptions
+                }
+            }
+            if (depth == 0) {
+                break;
+            }
+        }
+    }
+
+    /**
+     * @param reader
+     * @param writer
+     * @throws XMLStreamException
+     */
+    protected void serializeText(XMLStreamReader reader, XMLStreamWriter writer)
+        throws XMLStreamException {
+        writer.writeCharacters(reader.getText());
+    }
+}
\ No newline at end of file

Propchange: incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamSerializer.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamSerializer.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Added: incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamable.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamable.java?view=auto&rev=513629
==============================================================================
--- incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamable.java (added)
+++ incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamable.java Thu Mar  1 22:32:26 2007
@@ -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.core.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);
+}

Propchange: incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamable.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/main/java/org/apache/tuscany/core/databinding/xml/XMLStreamable.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date

Modified: incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/DOM2StAXTestCase.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/DOM2StAXTestCase.java?view=diff&rev=513629&r1=513628&r2=513629
==============================================================================
--- incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/DOM2StAXTestCase.java (original)
+++ incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/DOM2StAXTestCase.java Thu Mar  1 22:32:26 2007
@@ -56,6 +56,8 @@
             + "  </items>"
             + "</ipo:purchaseOrder>";
 
+    private static final String CRAZY_XML = "<p:e1 xmlns:p=\"http://p1\">" + "<p:e2 xmlns:p=\"http://p2\"/></p:e1>";
+
     /**
      * @see junit.framework.TestCase#setUp()
      */
@@ -70,7 +72,17 @@
         XMLStreamReader reader = t2.transform(node, null);
         XMLStreamReader2String t3 = new XMLStreamReader2String();
         String xml = t3.transform(reader, null);
-        Assert.assertTrue(xml != null && xml.indexOf("<shipDate>1999-12-05</shipDate>") != -1);
+        assertTrue(xml != null && xml.indexOf("<shipDate>1999-12-05</shipDate>") != -1);
     }
 
+    public void testTransformation2() {
+        String2Node t1 = new String2Node();
+        Node node = t1.transform(CRAZY_XML, null);
+        Node2XMLStreamReader t2 = new Node2XMLStreamReader();
+        XMLStreamReader reader = t2.transform(node, null);
+        XMLStreamReader2String t3 = new XMLStreamReader2String();
+        String xml = t3.transform(reader, null);
+        System.out.println(xml);
+        assertTrue(xml.contains("<p:e2 xmlns:p=\"http://p2\""));
+    }
 }

Added: incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/JavaBean2XMLStreamReaderTestCase.java
URL: http://svn.apache.org/viewvc/incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/JavaBean2XMLStreamReaderTestCase.java?view=auto&rev=513629
==============================================================================
--- incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/JavaBean2XMLStreamReaderTestCase.java (added)
+++ incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/JavaBean2XMLStreamReaderTestCase.java Thu Mar  1 22:32:26 2007
@@ -0,0 +1,134 @@
+/*
+ * 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.core.databinding.xml;
+
+import javax.xml.stream.XMLStreamReader;
+
+import junit.framework.TestCase;
+
+import org.apache.tuscany.core.databinding.javabeans.JavaBean2XMLStreamReader;
+
+public class JavaBean2XMLStreamReaderTestCase extends TestCase {
+    /**
+     * @see junit.framework.TestCase#setUp()
+     */
+    protected void setUp() throws Exception {
+        super.setUp();
+    }
+
+    public void testTransformation() {
+        JavaBean2XMLStreamReader t2 = new JavaBean2XMLStreamReader();
+        MyBean bean = new MyBean();
+        bean.str = "ABC";
+        bean.i = 1;
+        bean.arr = new long[] {1, 2, 3};
+        bean.bean = new AnotherBean();
+        bean.bean.setName("Name");
+        XMLStreamReader reader = t2.transform(bean, null);
+        XMLStreamReader2String t3 = new XMLStreamReader2String();
+        String xml = t3.transform(reader, null);
+        assertEquals("<JavaBean2XMLStreamReaderTestCase$MyBean>" 
+                     + "<arr>1</arr><arr>2</arr><arr>3</arr><bean><name>Name</name></bean>"
+                     + "<i>1</i><str>ABC</str></JavaBean2XMLStreamReaderTestCase$MyBean>",
+                     xml);
+    }
+
+    private static class MyBean {
+        private String str;
+        private int i;
+        private long arr[];
+        private AnotherBean bean;
+
+        /**
+         * @return the arr
+         */
+        public long[] getArr() {
+            return arr;
+        }
+
+        /**
+         * @param arr the arr to set
+         */
+        public void setArr(long[] arr) {
+            this.arr = arr;
+        }
+
+        /**
+         * @return the i
+         */
+        public int getI() {
+            return i;
+        }
+
+        /**
+         * @param i the i to set
+         */
+        public void setI(int i) {
+            this.i = i;
+        }
+
+        /**
+         * @return the str
+         */
+        public String getStr() {
+            return str;
+        }
+
+        /**
+         * @param str the str to set
+         */
+        public void setStr(String str) {
+            this.str = str;
+        }
+
+        /**
+         * @return the bean
+         */
+        public AnotherBean getBean() {
+            return bean;
+        }
+
+        /**
+         * @param bean the bean to set
+         */
+        public void setBean(AnotherBean bean) {
+            this.bean = bean;
+        }
+
+    }
+
+    private static class AnotherBean {
+        private String name;
+
+        /**
+         * @return the name
+         */
+        public String getName() {
+            return name;
+        }
+
+        /**
+         * @param name the name to set
+         */
+        public void setName(String name) {
+            this.name = name;
+        }
+    }
+
+}

Propchange: incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/JavaBean2XMLStreamReaderTestCase.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/tuscany/branches/sca-java-integration/sca/kernel/core/src/test/java/org/apache/tuscany/core/databinding/xml/JavaBean2XMLStreamReaderTestCase.java
------------------------------------------------------------------------------
    svn:keywords = Rev Date



---------------------------------------------------------------------
To unsubscribe, e-mail: tuscany-commits-unsubscribe@ws.apache.org
For additional commands, e-mail: tuscany-commits-help@ws.apache.org