/* * 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.axis2.databinding.utils.reader; import org.apache.axiom.ext.stax.datahandler.DataHandlerProvider; import org.apache.axiom.ext.stax.datahandler.DataHandlerReader; import org.apache.axiom.om.OMAttribute; import org.apache.axiom.om.OMElement; import org.apache.axiom.om.OMNamespace; import org.apache.axiom.util.stax.XMLStreamReaderUtils; import org.apache.axis2.databinding.typemapping.SimpleTypeMapper; import org.apache.axis2.databinding.utils.BeanUtil; import org.apache.axis2.databinding.utils.ConverterUtil; import org.apache.axis2.description.java2wsdl.TypeTable; import javax.activation.DataHandler; import javax.xml.namespace.NamespaceContext; import javax.xml.namespace.QName; import javax.xml.stream.Location; import javax.xml.stream.XMLStreamException; import java.util.*; import java.util.concurrent.atomic.AtomicInteger; import java.lang.reflect.Array; /** * This is the new implementation of the ADBpullaparser. 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 1. String name/QName name - String value 2. String * name/QName name - String[] value 3. OMElementkey - OMElement value 4. QName name/String name - * ADBBean value 5. QName name/String name - Java bean 5. QName name/String name - Datahandler * <p/> * As for the attributes, these are the possible combinations in the array 1. String name/QName name * - String value 2. OMAttributeKey - OMAttribute * <p/> * 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/> */ public class ADBXMLStreamReaderImpl implements ADBXMLStreamReader, DataHandlerReader { private static final AtomicInteger nsPrefix = new AtomicInteger(); private Object[] properties; private Object[] attributes; private QName elementQName; //This is to store the QName which are in the typeTable after setting the correct prefix private HashMap qnameMap = new HashMap(); //we always create a new namespace context private ADBNamespaceContext namespaceContext = new ADBNamespaceContext(); private Map declaredNamespaceMap = new HashMap(); //states for this pullparser - it can only have four states private static final int START_ELEMENT_STATE = 0; private static final int END_ELEMENT_STATE = 1; private static final int DELEGATED_STATE = 2; private static final int TEXT_STATE = 3; //integer field that keeps the state of this //parser. private int state = START_ELEMENT_STATE; //reference to the child reader private ADBXMLStreamReader childReader; //current property index //initialized at zero private int currentPropertyIndex = 0; //To keep element formdefault qualified or not private boolean qualified = false; //to keep the current types which are in AxisService private TypeTable typeTable = null; /* * 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 ADBXMLStreamReaderImpl(QName adbBeansQName, Object[] properties, Object[] attributes) { //validate the lengths, since both the arrays are supposed //to have this.properties = properties; this.elementQName = adbBeansQName; this.attributes = attributes; } public ADBXMLStreamReaderImpl(QName adbBeansQName, Object[] properties, Object[] attributes, TypeTable typeTable, boolean qualified) { this(adbBeansQName, properties, attributes); this.qualified = qualified; this.typeTable = typeTable; if(this.typeTable!=null){ Map complexTypeMap = this.typeTable.getComplexSchemaMap(); if(complexTypeMap !=null){ Iterator keys = complexTypeMap.keySet().iterator(); while (keys.hasNext()) { String key = (String) keys.next(); QName qname = (QName) complexTypeMap.get(key); if(qname !=null){ String prefix =qname.getPrefix(); if(prefix == null || "".equals(prefix)){ prefix = getNextNSPrefix(); } qname = new QName(qname.getNamespaceURI(),qname.getLocalPart(),prefix); this.typeTable.getComplexSchemaMap().put(key,qname); qnameMap.put(qname.getNamespaceURI(),prefix); addToNsMap(prefix, qname.getNamespaceURI()); } } } } } private static String getNextNSPrefix() { return "ns" + nsPrefix.incrementAndGet(); } /** add the namespace context */ public void addNamespaceContext(NamespaceContext nsContext) { // register the namespace context passed in to this this.namespaceContext.setParentNsContext(nsContext); } /** * 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(); } /** * @param key * @throws IllegalArgumentException */ public Object getProperty(String key) throws IllegalArgumentException { return XMLStreamReaderUtils.processGetProperty(this, key); } @Override public boolean isBinary() { return state == DELEGATED_STATE && childReader instanceof DataHandlerReader && ((DataHandlerReader)childReader).isBinary(); } @Override public boolean isOptimized() { return ((DataHandlerReader)childReader).isOptimized(); } @Override public boolean isDeferred() { return ((DataHandlerReader)childReader).isDeferred(); } @Override public String getContentID() { return ((DataHandlerReader)childReader).getContentID(); } @Override public DataHandler getDataHandler() throws XMLStreamException { return ((DataHandlerReader)childReader).getDataHandler(); } @Override public DataHandlerProvider getDataHandlerProvider() { return ((DataHandlerReader)childReader).getDataHandlerProvider(); } public void require(int i, String string, String string1) throws XMLStreamException { throw new UnsupportedOperationException(); } /** * todo implement the right contract for this * * @throws XMLStreamException */ public String getElementText() throws XMLStreamException { if (state == DELEGATED_STATE) { return childReader.getElementText(); } else { return null; } } /** * todo implement this * * @throws XMLStreamException */ public int nextTag() throws XMLStreamException { return 0; } /** @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); } } public void close() throws XMLStreamException { //do nothing here - we have no resources to free } public String getNamespaceURI(String prefix) { return namespaceContext.getNamespaceURI(prefix); } public boolean isStartElement() { if (state == START_ELEMENT_STATE) { return true; } else if (state == END_ELEMENT_STATE) { return false; } return childReader.isStartElement(); } public boolean isEndElement() { if (state == START_ELEMENT_STATE) { return false; } else if (state == END_ELEMENT_STATE) { return true; } return childReader.isEndElement(); } public boolean isCharacters() { if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) { return false; } return childReader.isCharacters(); } public boolean isWhiteSpace() { if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) { return false; } return childReader.isWhiteSpace(); } /////////////////////////////////////////////////////////////////////////// /// attribute handling /////////////////////////////////////////////////////////////////////////// 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 int getAttributeCount() { return (state == DELEGATED_STATE) ? childReader.getAttributeCount() : ((attributes != null) && (state == START_ELEMENT_STATE) ? attributes.length / 2 : 0); } /** @param i */ public QName getAttributeName(int i) { if (state == DELEGATED_STATE) { return childReader.getAttributeName(i); } else if (state == START_ELEMENT_STATE) { if (attributes == null) { return null; } else { if ((i >= (attributes.length / 2)) || i < 0) { //out of range return null; } else { //get the attribute pointer Object attribPointer = attributes[i * 2]; //case one - attrib name is null //this should be the pointer to the OMAttribute then if (attribPointer == null) { Object omAttribObj = attributes[(i * 2) + 1]; if (omAttribObj == null || !(omAttribObj instanceof OMAttribute)) { // wrong object set to have in the attrib array - // this should have been detected by now but just be // sure throw new UnsupportedOperationException(); } OMAttribute att = (OMAttribute)omAttribObj; return att.getQName(); } else if (attribPointer instanceof OMAttribKey) { Object omAttribObj = attributes[(i * 2) + 1]; if (omAttribObj == null || !(omAttribObj instanceof OMAttribute)) { // wrong object set to have in the attrib array - // this should have been detected by now but just be // sure throw new UnsupportedOperationException(); } OMAttribute att = (OMAttribute)omAttribObj; return att.getQName(); //case two - attrib name is a plain string } else if (attribPointer instanceof String) { return new QName((String)attribPointer); } 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 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(); } } 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 (attributes == null) { return null; } else { if ((i >= (attributes.length / 2)) || i < 0) { //out of range return null; } else { //get the attribute pointer Object attribPointer = attributes[i * 2]; Object omAttribObj = attributes[(i * 2) + 1]; //case one - attrib name is null //this should be the pointer to the OMAttribute then if (attribPointer == null) { if (omAttribObj == null || !(omAttribObj instanceof OMAttribute)) { // wrong object set to have in the attrib array - // this should have been detected by now but just be // sure throw new UnsupportedOperationException(); } OMAttribute att = (OMAttribute)omAttribObj; return att.getAttributeValue(); } else if (attribPointer instanceof OMAttribKey) { if (omAttribObj == null || !(omAttribObj instanceof OMAttribute)) { // wrong object set to have in the attrib array - // this should have been detected by now but just be // sure throw new UnsupportedOperationException(); } OMAttribute att = (OMAttribute)omAttribObj; return att.getAttributeValue(); //case two - attrib name is a plain string } else if (attribPointer instanceof String) { return (String)omAttribObj; } else if (attribPointer instanceof QName) { if (omAttribObj instanceof QName){ QName attributeQName = (QName) omAttribObj; // first check it is already there if not add the namespace. String prefix = namespaceContext.getPrefix(attributeQName.getNamespaceURI()); if (prefix == null){ prefix = getNextNSPrefix(); addToNsMap(prefix,attributeQName.getNamespaceURI()); } String attributeValue = null; if (prefix.equals("")){ // i.e. this is the default namespace attributeValue = attributeQName.getLocalPart(); } else { attributeValue = prefix + ":" + attributeQName.getLocalPart(); } return attributeValue; } else { return (String)omAttribObj; } } else { return null; } } } } else { throw new IllegalStateException(); } } public boolean isAttributeSpecified(int i) { return false; //not supported } /////////////////////////////////////////////////////////////////////////// ////////////// end of attribute handling /////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////// ////////////// namespace handling //////////////////////////////////////////////////////////////////////////// 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(); } } /** 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; } 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 NamespaceContext getNamespaceContext() { if (state == DELEGATED_STATE) { return childReader.getNamespaceContext(); } else { return namespaceContext; } } /////////////////////////////////////////////////////////////////////////// ///////// end of namespace handling /////////////////////////////////////////////////////////////////////////// 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 getText() { if (state == DELEGATED_STATE) { return childReader.getText(); } else if (state == TEXT_STATE) { Object property = properties[currentPropertyIndex - 1]; if (property instanceof DataHandler){ return ConverterUtil.getStringFromDatahandler((DataHandler)property); } else { return (String)properties[currentPropertyIndex - 1]; } } else { throw new IllegalStateException(); } } public char[] getTextCharacters() { if (state == DELEGATED_STATE) { return childReader.getTextCharacters(); } else if (state == TEXT_STATE) { return properties[currentPropertyIndex - 1] == null ? new char[0] : ((String)properties[currentPropertyIndex - 1]).toCharArray(); } else { throw new IllegalStateException(); } } 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) { //todo - implement this return 0; } 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 int getTextLength() { if (state == DELEGATED_STATE) { return childReader.getTextLength(); } else if (state == TEXT_STATE) { return 0;//assume text always starts at 0 } else { throw new IllegalStateException(); } } 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; } } /** check the validity of this implementation */ public boolean hasText() { if (state == DELEGATED_STATE) { return childReader.hasText(); } else return state == TEXT_STATE; } /** */ public Location getLocation() { //return a default location return new Location() { public int getLineNumber() { return 0; } public int getColumnNumber() { return 0; } public int getCharacterOffset() { return 0; } public String getPublicId() { return null; } public String getSystemId() { return null; } }; } public QName getName() { if (state == DELEGATED_STATE) { return childReader.getName(); } else if (state != TEXT_STATE) { return elementQName; } else { throw new IllegalStateException(); } } public String getLocalName() { if (state == DELEGATED_STATE) { return childReader.getLocalName(); } else if (state != TEXT_STATE) { return elementQName.getLocalPart(); } else { throw new IllegalStateException(); } } 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; } public String getNamespaceURI() { if (state == DELEGATED_STATE) { return childReader.getNamespaceURI(); } else if (state == TEXT_STATE) { return null; } else { return elementQName.getNamespaceURI(); } } 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; } } public String getVersion() { return null; } public boolean isStandalone() { return true; } public boolean standaloneSet() { return true; } public String getCharacterEncodingScheme() { return null; //todo - should we return something for this ? } public String getPITarget() { throw new UnsupportedOperationException("Yet to be implemented !!"); } public String getPIData() { throw new UnsupportedOperationException("Yet to be implemented !!"); } /////////////////////////////////////////////////////////////////////////// /// Other utility methods ////////////////////////////////////////////////////////////////////////// /** 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()); //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 if (attributes != null) { for (int i = 0; i < attributes.length; i = i + 2) { //jump in two Object attribName = attributes[i]; if (attribName == null) { //this should be the OMAttrib case! OMAttribute OMAttrib = (OMAttribute)attributes[i + 1]; OMNamespace namespace = OMAttrib.getNamespace(); if (namespace != null) { addToNsMap(namespace.getPrefix(), namespace.getNamespaceURI()); } } else if (attribName instanceof OMAttribKey) { //this is definitely the OMAttribute case OMAttribute OMAttrib = (OMAttribute)attributes[i + 1]; OMNamespace namespace = OMAttrib.getNamespace(); if (namespace != null) { addToNsMap(namespace.getPrefix(), namespace.getNamespaceURI()); } } else if (attribName instanceof String) { //ignore this case - Nothing to do } else if (attribName instanceof QName) { QName attribQName = ((QName)attribName); addToNsMap(attribQName.getPrefix(), attribQName.getNamespaceURI()); } } } } /** * @param prefix * @param uri */ private void addToNsMap(String prefix, String uri) { if (!uri.equals(namespaceContext.getNamespaceURI(prefix))) { namespaceContext.pushNamespace(prefix, uri); declaredNamespaceMap.put(prefix, uri); } } /** * 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 (properties == null || properties.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 (currentPropertyIndex > (properties.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 (currentPropertyIndex > (properties.length - 1)) { state = END_ELEMENT_STATE; returnEvent = END_ELEMENT; } else { returnEvent = processProperties(); } break; } return returnEvent; } /** * 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 Object propPointer = properties[currentPropertyIndex]; QName propertyQName = null; boolean textFound = false; if (propPointer == null) { throw new XMLStreamException("property key cannot be null!"); } else if (propPointer instanceof String) { // propPointer being a String has a special case // that is it can be a the special constant ELEMENT_TEXT that // says this text event if (ELEMENT_TEXT.equals(propPointer)) { textFound = true; } else { propertyQName = new QName((String)propPointer); } } else if (propPointer instanceof QName) { propertyQName = (QName)propPointer; } else if (propPointer instanceof OMElementKey) { // ah - in this case there's nothing to be done //about the propertyQName in this case - we'll just leave //it as it is } else { //oops - we've no idea what kind of key this is throw new XMLStreamException( "unidentified property key!!!" + propPointer); } if(propertyQName!=null){ String prefix = (String) qnameMap.get(propertyQName.getNamespaceURI()); if(prefix!=null){ propertyQName = new QName(propertyQName.getNamespaceURI(),propertyQName.getLocalPart(),prefix); } } //ok! we got the key. Now look at the value Object propertyValue = properties[currentPropertyIndex + 1]; //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; currentPropertyIndex = currentPropertyIndex + 2; return CHARACTERS; } else if (propertyValue == null) { //if the value is null we delegate the work to a nullable // parser childReader = new NullXMLStreamReader(propertyQName); childReader.addNamespaceContext(this.namespaceContext); childReader.init(); //we've a special pullparser for a datahandler! } else if (propertyValue instanceof DataHandler) { childReader = new ADBDataHandlerStreamReader(propertyQName, (DataHandler)propertyValue); childReader.addNamespaceContext(this.namespaceContext); childReader.init(); } else if (propertyValue instanceof String) { //strings are handled by the NameValuePairStreamReader childReader = new NameValuePairStreamReader(propertyQName, (String)propertyValue); childReader.addNamespaceContext(this.namespaceContext); childReader.init(); } else if (propertyValue instanceof Integer || propertyValue instanceof Long || propertyValue instanceof Double || propertyValue instanceof Float || propertyValue instanceof Character || propertyValue instanceof Short) { //all primitive wrapped generic type instances are converted to Strings and handled by the // NameValuePairStreamReader childReader = new NameValuePairStreamReader(propertyQName, String.valueOf(propertyValue)); childReader.addNamespaceContext(this.namespaceContext); childReader.init(); } else if (propertyValue.getClass().isArray()) { // this is an arrary object and we need to get the pull parser for that int length = Array.getLength(propertyValue); if (length == 0) { //advance the index currentPropertyIndex = currentPropertyIndex + 2; return processProperties(); } else { List objects = new ArrayList(); Object valueObject = null; for (int i = 0; i < length; i++) { //for innter Arrary Complex types we use the special local name array objects.add(new QName(propertyQName.getNamespaceURI(), "array")); valueObject = Array.get(propertyValue, i); if ((valueObject != null) && SimpleTypeMapper.isSimpleType(valueObject)){ objects.add(SimpleTypeMapper.getStringValue(valueObject)); } else { objects.add(valueObject); } } childReader = new ADBXMLStreamReaderImpl(propertyQName, objects.toArray(), new ArrayList().toArray(), typeTable, qualified); } } else if (propertyValue instanceof OMElement) { //OMElements do not provide the kind of parser we need //there is no other option than wrapping childReader = new WrappingXMLStreamReader( ((OMElement)propertyValue).getXMLStreamReader()); //we cannot register the namespace context here!! } else { //all special possiblilities has been tried! Let's treat //the thing as a bean and try generating events from it childReader = (ADBXMLStreamReader) BeanUtil.getPullParser(propertyValue, propertyQName, typeTable, qualified, false); //we cannot register the namespace context here } //set the state here state = DELEGATED_STATE; //we are done with the delegation //increment the property index currentPropertyIndex = currentPropertyIndex + 2; // If necessary, discard the START_DOCUMENT element (AXIS2-4271) int eventType = childReader.getEventType(); return eventType == START_DOCUMENT ? childReader.next() : eventType; } /** are we done ? */ public boolean isDone() { return (state == END_ELEMENT_STATE); } }