| /* Copyright 2004 The Apache Software Foundation |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| |
| package org.apache.xmlbeans.impl.marshal; |
| |
| import org.apache.xmlbeans.GDate; |
| import org.apache.xmlbeans.GDuration; |
| import org.apache.xmlbeans.ObjectFactory; |
| import org.apache.xmlbeans.XmlCalendar; |
| import org.apache.xmlbeans.XmlError; |
| import org.apache.xmlbeans.XmlException; |
| import org.apache.xmlbeans.XmlOptions; |
| import org.apache.xmlbeans.impl.binding.bts.BindingLoader; |
| import org.apache.xmlbeans.impl.binding.bts.BindingType; |
| import org.apache.xmlbeans.impl.binding.bts.BindingTypeName; |
| import org.apache.xmlbeans.impl.binding.bts.JavaTypeName; |
| import org.apache.xmlbeans.impl.binding.bts.SimpleDocumentBinding; |
| import org.apache.xmlbeans.impl.binding.bts.XmlTypeName; |
| import org.apache.xmlbeans.impl.common.InvalidLexicalValueException; |
| import org.apache.xmlbeans.impl.common.XmlStreamUtils; |
| import org.apache.xmlbeans.impl.richParser.XMLStreamReaderExt; |
| import org.apache.xmlbeans.impl.richParser.XMLStreamReaderExtImpl; |
| |
| 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.io.InputStream; |
| import java.math.BigDecimal; |
| import java.math.BigInteger; |
| import java.util.BitSet; |
| import java.util.Collection; |
| import java.util.Date; |
| |
| /** |
| * An UnmarshalResult holds the mutable state using by an Unmarshaller |
| * during unmarshalling. Example contents are an id -> object table |
| * for href processing, and the position in the xml document. |
| * |
| * The UnmarshalResult is purposefullly unsynchronized. |
| * Only one thread should ever be accessing this object, and a new one will be |
| * required for each unmarshalling pass. |
| */ |
| abstract class UnmarshalResult |
| { |
| //per binding context objects |
| private final BindingLoader bindingLoader; |
| private final RuntimeBindingTypeTable typeTable; |
| |
| //our state |
| protected XMLStreamReaderExt baseReader; |
| protected final XmlOptions options; |
| protected final Collection errors; |
| private final XsiAttributeHolder xsiAttributeHolder = |
| new XsiAttributeHolder(); |
| private boolean gotXsiAttributes; |
| private BitSet defaultAttributeBits; |
| private int currentAttributeIndex = INVALID; |
| private int currentAttributeCount = INVALID; |
| |
| private static final int INVALID = -1; |
| |
| |
| UnmarshalResult(BindingLoader bindingLoader, |
| RuntimeBindingTypeTable typeTable, |
| XmlOptions options) |
| { |
| this.bindingLoader = bindingLoader; |
| this.typeTable = typeTable; |
| this.options = options; |
| this.errors = BindingContextImpl.extractErrorHandler(options); |
| } |
| |
| protected RuntimeBindingType getRuntimeType(BindingType type) |
| throws XmlException |
| { |
| return typeTable.createRuntimeType(type, bindingLoader); |
| } |
| |
| private void enrichXmlStream(XMLStreamReader reader) |
| { |
| assert reader != null; |
| |
| baseReader = createExtendedReader(reader); |
| updateAttributeState(); |
| } |
| |
| |
| private static XMLStreamReaderExt createExtendedReader(XMLStreamReader reader) |
| { |
| if (reader instanceof XMLStreamReaderExt) { |
| return (XMLStreamReaderExt)reader; |
| } else { |
| return new XMLStreamReaderExtImpl(reader); |
| } |
| } |
| |
| private BindingType lookupBindingType(QName xsi_type) |
| { |
| XmlTypeName xname = XmlTypeName.forTypeNamed(xsi_type); |
| final BindingTypeName btname = bindingLoader.lookupPojoFor(xname); |
| if (btname == null) { |
| addError("unknown type: " + xsi_type); |
| return null; |
| } |
| final BindingType binding_type = bindingLoader.getBindingType(btname); |
| if (binding_type == null) { |
| addError("unknown binding type: " + binding_type); |
| } |
| return binding_type; |
| } |
| |
| |
| NamespaceContext getNamespaceContext() |
| { |
| return baseReader.getNamespaceContext(); |
| } |
| |
| private void addError(String msg) |
| { |
| addError(msg, baseReader.getLocation()); |
| } |
| |
| private void addWarning(String msg) |
| { |
| Location location = baseReader.getLocation(); |
| assert location != null; |
| MarshalStreamUtils.addError(errors, msg, |
| XmlError.SEVERITY_WARNING, |
| location); |
| } |
| |
| |
| final void addError(String msg, Location location) |
| { |
| assert location != null; |
| MarshalStreamUtils.addError(errors, msg, location); |
| } |
| |
| Collection getErrors() |
| { |
| return errors; |
| } |
| |
| final Object unmarshalDocument(XMLStreamReader reader) |
| throws XmlException |
| { |
| enrichXmlStream(getValidatingStream(reader)); |
| advanceToFirstItemOfInterest(); |
| BindingType bindingType = determineRootType(); |
| return unmarshalBindingType(bindingType); |
| } |
| |
| |
| protected Object unmarshalBindingType(BindingType bindingType) |
| throws XmlException |
| { |
| updateAttributeState(); |
| |
| final TypeUnmarshaller um; |
| final ObjectFactory of = extractObjectFactory(); |
| |
| try { |
| final RuntimeBindingType rtt = getRuntimeType(bindingType); |
| if (of == null) { |
| if (hasXsiNil()) |
| um = NullUnmarshaller.getInstance(); |
| else |
| um = rtt.getUnmarshaller(); |
| return um.unmarshal(this); |
| } else { |
| final Object initial_obj = of.createObject(rtt.getJavaType()); |
| um = rtt.getUnmarshaller(); |
| final Object inter = rtt.createIntermediary(this, initial_obj); |
| um.unmarshalIntoIntermediary(inter, this); |
| return rtt.getFinalObjectFromIntermediary(inter, this); |
| } |
| } |
| catch (InvalidLexicalValueException ilve) { |
| //top level simple types can end up here for invalid lexical values |
| assert !errors.isEmpty(); |
| return null; |
| } |
| } |
| |
| protected ObjectFactory extractObjectFactory() |
| { |
| if (options == null) return null; |
| |
| return |
| (ObjectFactory)options.get(XmlOptions.UNMARSHAL_INITIAL_OBJECT_FACTORY); |
| } |
| |
| final Object unmarshalType(XMLStreamReader reader, |
| QName schemaType, |
| String javaType) |
| throws XmlException |
| { |
| doctorStream(schemaType, reader); |
| |
| final QName xsi_type = getXsiType(); |
| |
| BindingType btype = null; |
| |
| if (xsi_type != null) { |
| btype = getPojoTypeFromXsiType(xsi_type); |
| } |
| |
| if (btype == null) { |
| btype = determineBindingType(schemaType, javaType); |
| } |
| |
| if (btype == null) { |
| final String msg = "unable to find binding type for " + |
| schemaType + " : " + javaType; |
| throw new XmlException(msg); |
| } |
| return unmarshalBindingType(btype); |
| } |
| |
| private void doctorStream(QName schemaType, |
| XMLStreamReader reader) |
| throws XmlException |
| { |
| reader = getValidatingStream(schemaType, reader); |
| enrichXmlStream(reader); |
| } |
| |
| |
| protected abstract XMLStreamReader getValidatingStream(XMLStreamReader reader) |
| throws XmlException; |
| |
| protected abstract XMLStreamReader getValidatingStream(QName schemaType, |
| XMLStreamReader reader) |
| throws XmlException; |
| |
| |
| final Object unmarshalElement(XMLStreamReader reader, |
| QName globalElement, |
| String javaType) |
| throws XmlException |
| { |
| final BindingType binding_type = |
| determineTypeForGlobalElement(globalElement); |
| final XmlTypeName type_name = binding_type.getName().getXmlName(); |
| assert type_name.isGlobal(); |
| assert type_name.isSchemaType(); |
| final QName schema_type = type_name.getQName(); |
| doctorStream(schema_type, reader); |
| |
| final QName xsi_type = getXsiType(); |
| |
| BindingType btype = null; |
| |
| if (xsi_type != null) { |
| btype = getPojoTypeFromXsiType(xsi_type); |
| } |
| |
| if (btype == null) { |
| btype = determineBindingType(schema_type, javaType); |
| } |
| |
| if (btype == null) { |
| final String msg = "unable to find binding type for " + |
| schema_type + " : " + javaType; |
| throw new XmlException(msg); |
| } |
| return unmarshalBindingType(btype); |
| } |
| |
| |
| private BindingType determineBindingType(QName schemaType, String javaType) |
| { |
| XmlTypeName xname = XmlTypeName.forTypeNamed(schemaType); |
| JavaTypeName jname = JavaTypeName.forClassName(javaType); |
| BindingTypeName btname = BindingTypeName.forPair(jname, xname); |
| return bindingLoader.getBindingType(btname); |
| } |
| |
| private BindingType determineRootType() |
| throws XmlException |
| { |
| QName xsi_type = this.getXsiType(); |
| |
| BindingType retval = null; |
| if (xsi_type != null) { |
| retval = getPojoTypeFromXsiType(xsi_type); |
| } |
| |
| if (retval == null) { |
| QName root_elem_qname = new QName(this.getNamespaceURI(), |
| this.getLocalName()); |
| retval = determineTypeForGlobalElement(root_elem_qname); |
| } |
| |
| return retval; |
| } |
| |
| private BindingType determineTypeForGlobalElement(QName elem) |
| throws XmlException |
| { |
| final XmlTypeName type_name = |
| XmlTypeName.forGlobalName(XmlTypeName.ELEMENT, elem); |
| BindingType doc_binding_type = getPojoBindingType(type_name, true); |
| SimpleDocumentBinding sd = (SimpleDocumentBinding)doc_binding_type; |
| return getPojoBindingType(sd.getTypeOfElement(), true); |
| } |
| |
| //will return null on error and log errors |
| private BindingType getPojoTypeFromXsiType(QName xsi_type) |
| throws XmlException |
| { |
| final XmlTypeName type_name = XmlTypeName.forTypeNamed(xsi_type); |
| final BindingType pojoBindingType = getPojoBindingType(type_name, false); |
| assert !(pojoBindingType instanceof SimpleDocumentBinding); |
| return pojoBindingType; |
| } |
| |
| |
| private BindingType getPojoBindingType(final XmlTypeName type_name, |
| boolean fail_fast) |
| throws XmlException |
| { |
| final BindingTypeName btName = bindingLoader.lookupPojoFor(type_name); |
| if (btName == null) { |
| final String msg = "failed to load java type corresponding " + |
| "to " + type_name; |
| if (fail_fast) { |
| throw new XmlException(msg); |
| } else { |
| addError(msg); |
| return null; |
| } |
| |
| } |
| |
| BindingType bt = bindingLoader.getBindingType(btName); |
| |
| if (bt == null) { |
| final String msg = "failed to load BindingType for " + btName; |
| if (fail_fast) { |
| throw new XmlException(msg); |
| } else { |
| addError(msg); |
| return null; |
| } |
| } |
| |
| return bt; |
| } |
| |
| |
| // ======================= xml access methods ======================= |
| |
| |
| Location getLocation() |
| { |
| return baseReader.getLocation(); |
| } |
| |
| String getStringValue() throws XmlException |
| { |
| try { |
| return baseReader.getStringValue(); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| String getStringValue(int ws) throws XmlException |
| { |
| try { |
| return baseReader.getStringValue(ws); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| boolean getBooleanValue() throws XmlException |
| { |
| try { |
| return baseReader.getBooleanValue(); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| byte getByteValue() throws XmlException |
| { |
| try { |
| return baseReader.getByteValue(); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| short getShortValue() throws XmlException |
| { |
| try { |
| return baseReader.getShortValue(); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| int getIntValue() throws XmlException |
| { |
| try { |
| return baseReader.getIntValue(); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| long getLongValue() throws XmlException |
| { |
| try { |
| return baseReader.getLongValue(); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| BigInteger getBigIntegerValue() throws XmlException |
| { |
| try { |
| return baseReader.getBigIntegerValue(); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| BigDecimal getBigDecimalValue() throws XmlException |
| { |
| try { |
| return baseReader.getBigDecimalValue(); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| float getFloatValue() throws XmlException |
| { |
| try { |
| return baseReader.getFloatValue(); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| double getDoubleValue() throws XmlException |
| { |
| try { |
| return baseReader.getDoubleValue(); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| InputStream getHexBinaryValue() throws XmlException |
| { |
| try { |
| return baseReader.getHexBinaryValue(); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| InputStream getBase64Value() throws XmlException |
| { |
| try { |
| return baseReader.getBase64Value(); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| XmlCalendar getCalendarValue() throws XmlException |
| { |
| try { |
| return baseReader.getCalendarValue(); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| String getAnyUriValue() throws XmlException |
| { |
| try { |
| return baseReader.getStringValue(XMLStreamReaderExt.WS_COLLAPSE); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| Date getDateValue() throws XmlException |
| { |
| try { |
| final GDate val = baseReader.getGDateValue(); |
| return val == null ? null : val.getDate(); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| GDate getGDateValue() throws XmlException |
| { |
| try { |
| return baseReader.getGDateValue(); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| GDuration getGDurationValue() throws XmlException |
| { |
| try { |
| return baseReader.getGDurationValue(); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| QName getQNameValue() throws XmlException |
| { |
| try { |
| return baseReader.getQNameValue(); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| String getAttributeStringValue() throws XmlException |
| { |
| try { |
| return baseReader.getAttributeStringValue(currentAttributeIndex); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| String getAttributeStringValue(int whitespace_style) |
| throws XmlException |
| { |
| try { |
| return baseReader.getAttributeStringValue(currentAttributeIndex, |
| whitespace_style); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| boolean getAttributeBooleanValue() throws XmlException |
| { |
| try { |
| return baseReader.getAttributeBooleanValue(currentAttributeIndex); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| byte getAttributeByteValue() throws XmlException |
| { |
| try { |
| return baseReader.getAttributeByteValue(currentAttributeIndex); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| short getAttributeShortValue() throws XmlException |
| { |
| try { |
| return baseReader.getAttributeShortValue(currentAttributeIndex); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| int getAttributeIntValue() throws XmlException |
| { |
| try { |
| return baseReader.getAttributeIntValue(currentAttributeIndex); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| long getAttributeLongValue() throws XmlException |
| { |
| try { |
| return baseReader.getAttributeLongValue(currentAttributeIndex); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| BigInteger getAttributeBigIntegerValue() throws XmlException |
| { |
| try { |
| return baseReader.getAttributeBigIntegerValue(currentAttributeIndex); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| BigDecimal getAttributeBigDecimalValue() throws XmlException |
| { |
| try { |
| return baseReader.getAttributeBigDecimalValue(currentAttributeIndex); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| float getAttributeFloatValue() throws XmlException |
| { |
| try { |
| return baseReader.getAttributeFloatValue(currentAttributeIndex); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| double getAttributeDoubleValue() throws XmlException |
| { |
| try { |
| return baseReader.getAttributeDoubleValue(currentAttributeIndex); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| String getAttributeAnyUriValue() throws XmlException |
| { |
| try { |
| return baseReader.getAttributeStringValue(currentAttributeIndex, |
| XMLStreamReaderExt.WS_COLLAPSE); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| InputStream getAttributeHexBinaryValue() throws XmlException |
| { |
| try { |
| return baseReader.getAttributeHexBinaryValue(currentAttributeIndex); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| InputStream getAttributeBase64Value() throws XmlException |
| { |
| try { |
| return baseReader.getAttributeBase64Value(currentAttributeIndex); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| XmlCalendar getAttributeCalendarValue() throws XmlException |
| { |
| try { |
| return baseReader.getAttributeCalendarValue(currentAttributeIndex); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| Date getAttributeDateValue() throws XmlException |
| { |
| try { |
| GDate val = baseReader.getAttributeGDateValue(currentAttributeIndex); |
| return val == null ? null : val.getDate(); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| GDate getAttributeGDateValue() throws XmlException |
| { |
| try { |
| return baseReader.getAttributeGDateValue(currentAttributeIndex); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| GDuration getAttributeGDurationValue() throws XmlException |
| { |
| try { |
| return baseReader.getAttributeGDurationValue(currentAttributeIndex); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| QName getAttributeQNameValue() throws XmlException |
| { |
| try { |
| return baseReader.getAttributeQNameValue(currentAttributeIndex); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| |
| /** |
| * return the QName value found for xsi:type |
| * or null if neither one was found |
| */ |
| protected QName getXsiType() |
| throws XmlException |
| { |
| if (!gotXsiAttributes) { |
| getXsiAttributes(); |
| } |
| assert gotXsiAttributes; |
| return xsiAttributeHolder.xsiType; |
| } |
| |
| protected final boolean hasXsiNil() throws XmlException |
| { |
| if (!gotXsiAttributes) { |
| getXsiAttributes(); |
| } |
| assert gotXsiAttributes; |
| return xsiAttributeHolder.hasXsiNil; |
| } |
| |
| private void getXsiAttributes() throws XmlException |
| { |
| try { |
| MarshalStreamUtils.getXsiAttributes(xsiAttributeHolder, |
| baseReader, errors); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| gotXsiAttributes = true; |
| } |
| |
| /** |
| * |
| * @return false if we hit an end element (any end element at all) |
| */ |
| final boolean advanceToNextStartElement() |
| throws XmlException |
| { |
| final boolean ret = |
| MarshalStreamUtils.advanceToNextStartElement(baseReader); |
| |
| |
| updateAttributeState(); |
| |
| //System.out.println("AT: " + XmlStreamUtils.printEvent(baseReader)); |
| |
| return ret; |
| } |
| |
| |
| private void advanceToFirstItemOfInterest() |
| throws XmlException |
| { |
| assert baseReader != null; |
| MarshalStreamUtils.advanceToFirstItemOfInterest(baseReader); |
| } |
| |
| int next() throws XmlException |
| { |
| try { |
| final int new_state = baseReader.next(); |
| if (new_state == XMLStreamReader.START_ELEMENT) { |
| updateAttributeState(); |
| } |
| return new_state; |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| boolean hasNext() throws XmlException |
| { |
| try { |
| return baseReader.hasNext(); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| |
| protected final void updateAttributeState() |
| { |
| xsiAttributeHolder.reset(); |
| gotXsiAttributes = false; |
| if (defaultAttributeBits != null) { |
| defaultAttributeBits.clear(); |
| } |
| |
| //TODO: in many calls to this method, we already know that |
| //we are on a start element... |
| if (baseReader.isStartElement()) { |
| currentAttributeCount = baseReader.getAttributeCount(); |
| currentAttributeIndex = 0; |
| } else { |
| currentAttributeIndex = INVALID; |
| currentAttributeCount = INVALID; |
| } |
| } |
| |
| |
| boolean isStartElement() |
| { |
| return baseReader.isStartElement(); |
| } |
| |
| boolean isEndElement() |
| { |
| return baseReader.isEndElement(); |
| } |
| |
| private int getAttributeCount() |
| { |
| assert baseReader.isStartElement(); |
| |
| return baseReader.getAttributeCount(); |
| } |
| |
| String getLocalName() |
| { |
| return baseReader.getLocalName(); |
| } |
| |
| String getNamespaceURI() |
| { |
| return baseReader.getNamespaceURI(); |
| } |
| |
| final void skipElement() |
| throws XmlException |
| { |
| MarshalStreamUtils.skipElement(baseReader); |
| updateAttributeState(); |
| } |
| |
| |
| final void advanceAttribute() |
| { |
| assert hasMoreAttributes(); |
| assert currentAttributeCount != INVALID; |
| assert currentAttributeIndex != INVALID; |
| |
| currentAttributeIndex++; |
| |
| assert currentAttributeIndex <= currentAttributeCount; |
| } |
| |
| boolean hasMoreAttributes() |
| { |
| assert baseReader.isStartElement(); |
| |
| assert currentAttributeCount != INVALID; |
| assert currentAttributeIndex != INVALID; |
| |
| return (currentAttributeIndex < currentAttributeCount); |
| } |
| |
| String getCurrentAttributeNamespaceURI() |
| { |
| assert currentAttributeCount != INVALID; |
| assert currentAttributeIndex != INVALID; |
| |
| return baseReader.getAttributeNamespace(currentAttributeIndex); |
| } |
| |
| String getCurrentAttributeLocalName() |
| { |
| assert currentAttributeCount != INVALID; |
| assert currentAttributeIndex != INVALID; |
| |
| return baseReader.getAttributeLocalName(currentAttributeIndex); |
| } |
| |
| final void attributePresent(int att_idx) |
| { |
| if (defaultAttributeBits == null) { |
| int bits_size = getAttributeCount(); |
| defaultAttributeBits = new BitSet(bits_size); |
| } |
| |
| defaultAttributeBits.set(att_idx); |
| } |
| |
| boolean isAttributePresent(int att_idx) |
| { |
| if (defaultAttributeBits == null) |
| return false; |
| |
| return defaultAttributeBits.get(att_idx); |
| } |
| |
| void setNextElementDefault(String lexical_default) |
| throws XmlException |
| { |
| try { |
| baseReader.setDefaultValue(lexical_default); |
| } |
| catch (XMLStreamException e) { |
| throw new XmlException(e); |
| } |
| } |
| |
| /** |
| * Do the supplied localname, uri pair match the given qname? |
| * |
| * @param qn name of element |
| * @param localname candidate localname |
| * @param uri candidtate uri |
| * @return |
| */ |
| static boolean doesElementMatch(QName qn, String localname, String uri) |
| { |
| if (qn.getLocalPart().equals(localname)) { |
| //QNames always uses "" for no namespace, but the incoming uri |
| //might use null or "". |
| return qn.getNamespaceURI().equals(uri == null ? "" : uri); |
| } |
| return false; |
| } |
| |
| final RuntimeBindingType determineActualRuntimeType(RuntimeBindingType expected) |
| throws XmlException |
| { |
| final QName xsi_type = getXsiType(); |
| |
| |
| if (xsi_type != null && !xsi_type.equals(expected.getSchemaTypeName())) { |
| final BindingType binding_type = lookupBindingType(xsi_type); |
| if (binding_type != null) { |
| final RuntimeBindingType actual_rtt = |
| typeTable.createRuntimeType(binding_type, bindingLoader); |
| if (isCompatibleTypeSubstitution(expected, actual_rtt)) { |
| return actual_rtt; |
| } else { |
| String e = "invalid type substitution: " + |
| xsi_type + " for " + expected.getSchemaTypeName() + |
| " due to incompatible java types (" + |
| actual_rtt.getJavaType().getName() + |
| " for " + expected.getJavaType().getName() + |
| ") -- using declared type"; |
| addWarning(e); |
| } |
| } |
| } |
| |
| return expected; |
| } |
| |
| |
| //is xsi:type substitution ok. only checks java compat for now. |
| private static boolean isCompatibleTypeSubstitution(RuntimeBindingType expected, |
| RuntimeBindingType actual) |
| { |
| if (expected == actual) return true; |
| |
| final Class expected_type = expected.getJavaType(); |
| final Class actual_type = actual.getJavaType(); |
| if (expected_type == actual_type) return true; |
| if (expected_type.equals(actual_type)) return true; |
| |
| if (expected_type.isAssignableFrom(actual_type)) return true; |
| |
| //TODO: FIXME! deal with cases where reflection gives us autoboxing. |
| if (actual_type.isPrimitive()) return true; |
| |
| return false; |
| } |
| |
| abstract void extractAndFillElementProp(RuntimeBindingProperty prop, |
| Object inter) |
| throws XmlException; |
| |
| |
| protected TypeUnmarshaller getUnmarshaller(RuntimeBindingType actual_rtt) |
| throws XmlException |
| { |
| final TypeUnmarshaller um; |
| if (hasXsiNil()) { |
| um = NullUnmarshaller.getInstance(); |
| } else { |
| um = actual_rtt.getUnmarshaller(); |
| } |
| return um; |
| } |
| |
| } |
| |