Return-Path: Delivered-To: apmail-ws-tuscany-commits-archive@locus.apache.org Received: (qmail 51831 invoked from network); 2 Mar 2007 06:32:53 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 2 Mar 2007 06:32:53 -0000 Received: (qmail 56762 invoked by uid 500); 2 Mar 2007 06:33:01 -0000 Delivered-To: apmail-ws-tuscany-commits-archive@ws.apache.org Received: (qmail 56740 invoked by uid 500); 2 Mar 2007 06:33:01 -0000 Mailing-List: contact tuscany-commits-help@ws.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: tuscany-dev@ws.apache.org Delivered-To: mailing list tuscany-commits@ws.apache.org Received: (qmail 56729 invoked by uid 99); 2 Mar 2007 06:33:01 -0000 Received: from herse.apache.org (HELO herse.apache.org) (140.211.11.133) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 01 Mar 2007 22:33:01 -0800 X-ASF-Spam-Status: No, hits=-99.5 required=10.0 tests=ALL_TRUSTED,NO_REAL_NAME X-Spam-Check-By: apache.org Received: from [140.211.11.3] (HELO eris.apache.org) (140.211.11.3) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 01 Mar 2007 22:32:48 -0800 Received: by eris.apache.org (Postfix, from userid 65534) id 970561A9820; Thu, 1 Mar 2007 22:32:28 -0800 (PST) Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: 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... Date: Fri, 02 Mar 2007 06:32:27 -0000 To: tuscany-commits@ws.apache.org From: rfeng@apache.org X-Mailer: svnmailer-1.1.0 Message-Id: <20070302063228.970561A9820@eris.apache.org> X-Virus-Checked: Checked by ClamAV on apache.org 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 + *
    + *
  • String name/QName name - String value + *
  • String name/QName name - String[] value + *
  • QName name/String name - XMLStreamReader value + *
  • QName name/String name - XMLStreamable value + *
  • QName name/String name - Java bean + *
  • QName name/String name - Datahandler + * + *
+ *

As for the attributes, these are the possible combinations in the array + *

    + *
  • String name/QName name - String value + *
+ * 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

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

+ * + * @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 declaredNamespaceMap = new HashMap(); + 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 @@ + " " + ""; + private static final String CRAZY_XML = "" + ""; + /** * @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("1999-12-05") != -1); + assertTrue(xml != null && xml.indexOf("1999-12-05") != -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("" + + "123Name" + + "1ABC", + 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