public Object read(XMLStreamReader xmlStreamReader, Class<?> declaredType, Boolean jaxbElementWrap, RuntimeContext runtimeContext) throws JAXBException {
if (xmlStreamReader == null) throw new IllegalArgumentException("xmlStreamReader is null");
if (runtimeContext == null) throw new IllegalArgumentException("runtimeContext is null");
XoXMLStreamReader reader = new XoXMLStreamReaderImpl(xmlStreamReader);
try {
int event = reader.getEventType();
while (event != XMLStreamConstants.START_ELEMENT && reader.hasNext()) {
event = reader.next();
}
if (event != XMLStreamConstants.START_ELEMENT) {
// TODO: empty document - figure out what is appropriate per spec
return null;
}
// read and save element name before stream advances
QName name = reader.getName();
Object o = null;
if (reader.isXsiNil()) {
// was xsi:nil
return null;
} else if (reader.getXsiType() != null) {
// find the marshaller by xsi:type
JAXBObject instance = introspector.getJaxbMarshallerBySchemaType(reader.getXsiType());
if (instance != null) {
if (declaredType == null) declaredType = Object.class;
if (jaxbElementWrap == null) jaxbElementWrap = instance.getXmlRootElement() == null;
// check assignment is possible
if (declaredType.isAssignableFrom(instance.getType())) {
// read the object
o = instance.read(reader, runtimeContext);
} else {
String message = "Expected instance of " + declaredType.getName() + ", but found xsi:type " + reader.getXsiType() + " which is mapped to " + instance.getType().getName();
if (getEventHandler() == null || !getEventHandler().handleEvent(new ValidationEventImpl(ValidationEvent.ERROR, message, new ValidationEventLocatorImpl(reader.getLocation())))) {
throw new UnmarshalException(message);
}
jaxbElementWrap = false;
}
} else {
String message = "No JAXB object for XML type " + reader.getXsiType();
if (getEventHandler() == null || !getEventHandler().handleEvent(new ValidationEventImpl(ValidationEvent.ERROR, message, new ValidationEventLocatorImpl(reader.getLocation())))) {
throw new UnmarshalException(message);
}
jaxbElementWrap = false;
}
} else if (declaredType != null && !Object.class.equals(declaredType)) {
// check built in types first
if (String.class.equals(declaredType)) {
o = reader.getElementAsString();
} else if (Boolean.class.equals(declaredType)) {
o = reader.getElementAsBoolean();
} else if (Double.class.equals(declaredType)) {
o = reader.getElementAsDouble();
} else if (Long.class.equals(declaredType)) {
o = reader.getElementAsLong();
} else if (Float.class.equals(declaredType)) {
o = reader.getElementAsFloat();
} else if (Short.class.equals(declaredType)) {
o = reader.getElementAsShort();
} else if (QName.class.equals(declaredType)) {
o = reader.getElementAsQName();
} else if (byte[].class.equals(declaredType)) {
o = BinaryUtils.decodeAsBytes(reader);
} else if (XMLGregorianCalendar.class.equals(declaredType)) {
String s = reader.getElementAsString();
o = dtFactory.newXMLGregorianCalendar(s);
} else if (Duration.class.equals(declaredType)) {
String s = reader.getElementAsString();
o = dtFactory.newDuration(s);
} else if (Node.class.equals(declaredType)) {
Element element = reader.getElementAsDomElement();
o = element;
} else {
// find marshaller by expected type
JAXBObject instance = introspector.getJaxbMarshaller(declaredType);
if (instance != null) {
if (declaredType == null) {
declaredType = Object.class;
}
if (jaxbElementWrap == null) jaxbElementWrap = instance.getXmlRootElement() == null;
// read the object
o = instance.read(reader, runtimeContext);
} else {
String message = declaredType.getName() + " is not a JAXB object";
if (getEventHandler() == null || !getEventHandler().handleEvent(new ValidationEventImpl(ValidationEvent.ERROR, message, new ValidationEventLocatorImpl(reader.getLocation())))) {
throw new UnmarshalException(message);
}
jaxbElementWrap = false;
}
}
} else {
// find the marshaller by root element name
JAXBObject instance = introspector.getJaxbMarshallerByElementName(name);
if (instance != null) {
if (jaxbElementWrap == null) jaxbElementWrap = instance.getXmlRootElement() == null;
declaredType = Object.class;
// read the object
o = instance.read(reader, runtimeContext);
} else if (Object.class.equals(declaredType)) {
// @XmlAnyType(lax = true)
Element element = reader.getElementAsDomElement();
o = element;
} else {
String message = "No JAXB object mapped to root element " + name + "; known root elemnts are " + introspector.getElementNames();
if (getEventHandler() == null || !getEventHandler().handleEvent(new ValidationEventImpl(ValidationEvent.ERROR, message, new ValidationEventLocatorImpl(reader.getLocation())))) {
throw new UnmarshalException(message);
}
jaxbElementWrap = false;
}
}
// wrap if necessary
if (jaxbElementWrap != null && jaxbElementWrap) {
return new JAXBElement(name, declaredType, o);
} else {
return o;
}
} catch (Exception e) {
if (e instanceof RuntimeXMLStreamException) {
e = ((RuntimeXMLStreamException) e).getCause();
}
if (e instanceof XMLStreamException) {
Throwable cause = e.getCause();
if (cause instanceof JAXBException) {
throw (JAXBException) e;
}
throw new UnmarshalException(cause == null ? e : cause);
}
if (e instanceof JAXBException) {
throw (JAXBException) e;
}
// report fatal error
if (getEventHandler() != null) {
getEventHandler().handleEvent(new ValidationEventImpl(ValidationEvent.FATAL_ERROR, "Fatal error", new ValidationEventLocatorImpl(reader.getLocation()), e));
}
throw new UnmarshalException(e);
}
}