package openadk.library.impl.surrogates;
import javax.xml.stream.XMLStreamConstants;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import openadk.library.ADK;
import openadk.library.ADKParsingException;
import openadk.library.ADKTypeParseException;
import openadk.library.DTD;
import openadk.library.Element;
import openadk.library.ElementDef;
import openadk.library.ElementVersionInfo;
import openadk.library.SIFElement;
import openadk.library.SIFErrorCategory;
import openadk.library.SIFErrorCodes;
import openadk.library.SIFException;
import openadk.library.SIFFormatter;
import openadk.library.SIFParser;
import openadk.library.SIFVersion;
import openadk.library.Zone;
import openadk.library.common.XMLData;
import openadk.library.impl.SIFPullParser;
import openadk.util.XMLNodeReader;
import openadk.util.XMLStreamDocumentBuilder;
public class StudentAddressPullParser extends SIFPullParser {
public SIFElement parseOneElementFromStream(XMLStreamReader reader, SIFVersion version, DTD dtd, Zone zone, int flags) throws ADKParsingException, SIFException {
boolean legacyParse = version.compareTo(SIFVersion.SIF20) < 0;
// The current SIFElement being parsed
SIFElement currentElement = null;
SIFFormatter formatter = ADK.DTD().getFormatter(version);
String xmlName = "";
try {
int nodeType = reader.getEventType();
while (reader.hasNext()) {
if (nodeType == XMLStreamConstants.CHARACTERS) {
if (reader.isWhiteSpace()) {
// JEN Alert Message problem - here
try {
nodeType = reader.nextTag();
} catch (Exception e) {
String errorMessage = xmlName + " Tag Parse Exception:";
ADK.getLog().warn(errorMessage, e);
nodeType = reader.next();
}
continue;
}
if (currentElement.getElementDef().hasSimpleContent()) {
// This is a SIFElement that allows a Text value to be
// set to it.
// The XMLStreamReader cursor will automatically be
// advanced by this method to what should be the
// END_ELEMENT
setFieldValueFromElement(currentElement.getElementDef(), currentElement, reader, version, formatter, zone);
nodeType = reader.getEventType();
continue;
}
} else if (nodeType == XMLStreamConstants.START_ELEMENT) {
if (reader.getLocalName().equals("SIF_Message")) {
// Special case for embedded SIF_Message envelopes
if ((flags & SIFParser.FLG_EXPECT_INNER_ENVELOPE) != 0) {
SIFElement msgElement = readSIFMessageElement(reader, dtd, zone, 0, version);
currentElement.addChild(msgElement);
currentElement = msgElement;
} else {
throw new ADKParsingException("Unexpected SIF_Message encountered in parsing", zone);
}
} else {
xmlName = reader.getLocalName();
ElementDef foundDef = lookupElementDef(currentElement, xmlName, dtd, version, zone);
if (foundDef == null) {
if (legacyParse) {
nodeType = parseLegacyXML(reader, version, zone, currentElement, formatter, xmlName);
continue;
} else if (currentElement != null && currentElement.getElementDef().name().equals("XMLData")) {
// Parse this into a DOM and set on the XMLData
// element
XMLNodeReader nestedReader = new XMLNodeReader(reader);
org.w3c.dom.Document doc = XMLStreamDocumentBuilder.build(nestedReader, false, true, null);
((XMLData) currentElement).setXML(doc);
nodeType = reader.nextTag();
continue;
} else {
String _tag = currentElement != null ? currentElement.getElementDef().name() + "/" + xmlName : xmlName;
throw new SIFException(SIFErrorCategory.XML_VALIDATION, SIFErrorCodes.XML_GENERIC_VALIDATION_3, "Unknown element or attribute", _tag + " is not a recognized element of SIF " + version.toString(), zone);
}
}
if (legacyParse) {
ElementVersionInfo evi = foundDef.getVersionInfo(version);
if (evi != null) {
RenderSurrogate rs = evi.getSurrogate();
if (rs != null) {
try {
if (rs.readRaw(reader, version, currentElement, formatter)) {
nodeType = reader.getEventType();
continue;
} else {
throw new SIFException(SIFErrorCategory.XML_VALIDATION, SIFErrorCodes.XML_GENERIC_VALIDATION_3, "Unknown element or attribute", reader.getLocalName() + " was not able to be parsed by " + rs, zone);
}
} catch (ADKTypeParseException atpe) {
handleTypeParseException("Unable to parse value: " + atpe.getMessage(), atpe, zone);
nodeType = reader.getEventType();
continue;
}
}
}
}
if (foundDef.isField()) {
setFieldValueFromElement(foundDef, currentElement, reader, version, formatter, zone);
nodeType = reader.nextTag();
continue;
} else {
currentElement = readSIFElementFromElementNode(foundDef, reader, version, dtd, currentElement, formatter, zone);
// TODO: Empty repeatable fields, such as Email,
// that contain no data are not getting set to nil.
// Should treat <Email Type="Primary"/> equivalent
// to <Email Type="Primary" xsi:nil="true"/>
}
}
} else if (nodeType == XMLStreamConstants.END_ELEMENT) {
if ( currentElement.getParent() == null ) {
return currentElement;
} else {
currentElement = (SIFElement) currentElement.getParent();
while (legacyParse && currentElement.getElementDef().isCollapsed(version)) {
currentElement = (SIFElement) currentElement.getParent();
}
}
if (reader.getLocalName().equals("SIF_Message")) {
// We need to return here. If we let the reader keep
// reading, and we are reading an embedded
// SIF_Message, it will keep parsing the end tags and
// not let the stack of SIFElement objects
// properly unwind. We're done anyway.
break;
}
// Advance to the nexttag (faster than calling next())
if (!reader.isEndElement()) {
nodeType = reader.nextTag();
continue;
}
}
// Advance the cursor
nodeType = reader.next();
}
} catch (XMLStreamException xse) {
throw new ADKParsingException(xse.getLocalizedMessage(), zone, xse);
}
if (currentElement == null) {
return null;
} else {
// Now, unwind and pop off the top element parsed
Element top = currentElement;
Element current;
while ((current = top.getParent()) != null) {
top = current;
}
return (SIFElement) top;
}
}
}