package org.apache.axis2.databinding.utils.reader; | |
import org.apache.axiom.om.OMAttribute; | |
import org.apache.axiom.om.OMElement; | |
import org.apache.axiom.om.OMNamespace; | |
import org.apache.axis2.databinding.ADBBean; | |
import org.apache.axis2.databinding.utils.BeanUtil; | |
import org.apache.ws.java2wsdl.utils.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 javax.xml.stream.XMLStreamReader; | |
import java.util.Arrays; | |
import java.util.HashMap; | |
import java.util.Map; | |
/* | |
* Copyright 2004,2005 The Apache Software Foundation. | |
* | |
* Licensed under the Apache License, Version 2.0 (the "License"); | |
* you may not use this file except in compliance with the License. | |
* You may obtain a copy of the License at | |
* | |
* http://www.apache.org/licenses/LICENSE-2.0 | |
* | |
* Unless required by applicable law or agreed to in writing, software | |
* distributed under the License is distributed on an "AS IS" BASIS, | |
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
* See the License for the specific language governing permissions and | |
* limitations under the License. | |
*/ | |
/** | |
* 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 { | |
private Object[] properties; | |
private Object[] attributes; | |
private QName elementQName; | |
//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; | |
} | |
/** | |
* 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 { | |
if (state == START_ELEMENT_STATE || state == END_ELEMENT_STATE) { | |
if (OPTIMIZATION_ENABLED.equals(key)) { | |
return Boolean.TRUE; | |
} else { | |
return null; | |
} | |
} else if (state == TEXT_STATE) { | |
if (IS_BINARY.equals(key)) { | |
return Boolean.FALSE; | |
} else { | |
return null; | |
} | |
} else if (state == DELEGATED_STATE) { | |
return childReader.getProperty(key); | |
} else { | |
return null; | |
} | |
} | |
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) { | |
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) { | |
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); | |
} | |
//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 String[]) { | |
//string[] are handled by the NameValueArrayStreamReader | |
//if the array is empty - skip it | |
if (((String[]) propertyValue).length == 0) { | |
//advance the index | |
currentPropertyIndex = currentPropertyIndex + 2; | |
return processProperties(); | |
} else { | |
childReader = | |
new NameValueArrayStreamReader(propertyQName, | |
(String[]) propertyValue); | |
childReader.addNamespaceContext(this.namespaceContext); | |
childReader.init(); | |
} | |
} else if (propertyValue instanceof ADBBean) { | |
//ADBbean has it's own method to get a reader | |
XMLStreamReader reader = ((ADBBean) propertyValue). | |
getPullParser(propertyQName); | |
// we know for sure that this is an ADB XMLStreamreader. | |
// However we need to make sure that it is compatible | |
if (reader instanceof ADBXMLStreamReader) { | |
childReader = (ADBXMLStreamReader) reader; | |
childReader.addNamespaceContext(this.namespaceContext); | |
childReader.init(); | |
} else { | |
//wrap it to make compatible | |
childReader = new WrappingXMLStreamReader( | |
reader); | |
} | |
} 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 = new WrappingXMLStreamReader | |
(BeanUtil.getPullParser(propertyValue, | |
propertyQName, typeTable, qualified)); | |
//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; | |
return childReader.getEventType(); | |
} | |
/** | |
* are we done ? | |
*/ | |
public boolean isDone() { | |
return (state == END_ELEMENT_STATE); | |
} | |
} |