initializePackageParsers();
XMLEvent event;
StartElement startElement = null;
ReadingParser parser = null;
Stack<Object> sbmlElements = new Stack<Object>();
QName currentNode = null;
boolean isNested = false;
boolean isText = false;
boolean isHTML = false;
boolean isRDFSBMLSpecificAnnotation = false;
boolean isInsideAnnotation = false;
boolean isInsideNotes = false;
int rdfDescriptionIndex = -1;
int annotationDeepness = -1;
int level = -1, version = -1;
Object lastElement = null;
Logger logger = Logger.getLogger(SBMLReader.class);
// Read all the elements of the file
while (xmlEventReader.hasNext()) {
event = (XMLEvent2) xmlEventReader.nextEvent();
// StartDocument
if (event.isStartDocument()) {
@SuppressWarnings("unused")
StartDocument startDocument = (StartDocument) event;
// nothing to do
}
// EndDocument
else if (event.isEndDocument()) {
@SuppressWarnings("unused")
EndDocument endDocument = (EndDocument) event;
// nothing to do?
}
// StartElement
else if (event.isStartElement()) {
startElement = event.asStartElement();
currentNode = startElement.getName();
isNested = false;
isText = false;
addAnnotationParsers(startElement);
// If the XML element is the sbml element, creates the
// necessary ReadingParser instances.
// Creates an empty SBMLDocument instance and pushes it on
// the SBMLElements stack.
if (currentNode.getLocalPart().equals("sbml")) {
SBMLDocument sbmlDocument = new SBMLDocument();
// the output of the change listener is activated or not via log4j.properties
sbmlDocument.addTreeNodeChangeListener(listener == null
? new SimpleTreeNodeChangeListener() : listener);
for (@SuppressWarnings("unchecked")
Iterator<Attribute> iterator = startElement.getAttributes(); iterator.hasNext();)
{
Attribute attr = iterator.next();
if (attr.getName().toString().equals("level")) {
level = StringTools.parseSBMLInt(attr.getValue());
sbmlDocument.setLevel(level);
} else if (attr.getName().toString().equals("version")) {
version = StringTools.parseSBMLInt(attr.getValue());
sbmlDocument.setVersion(version);
}
}
sbmlElements.push(sbmlDocument);
}
else if (lastElement == null) // We are probably reading some 'free' XML, mathML or HTML
{
// We put a fake Constraint element in the stack that can take either math, notes or message.
// This a hack to be able to read some mathMl or notes by themselves.
// If the parent container is set in this SBMLReader, we use it instead.
if (currentNode.getLocalPart().equals("notes") || currentNode.getLocalPart().equals("message"))
{
initializedParsers.put("", sbmlCoreParser);
} else if (currentNode.getLocalPart().equals("math"))
{
initializedParsers.put("", new MathMLStaxParser());
initializedParsers.put(ASTNode.URI_MATHML_DEFINITION, new MathMLStaxParser());
currentNode = new QName(ASTNode.URI_MATHML_DEFINITION, "math");
}
// TODO: will not work with arbitrary SBML part
// TODO: we need to be able, somehow, to set the Model element in the Constraint
// to be able to have a fully functional parsing. Without it the functionDefinition, for examples, are
// not properly recognized.
if (astNodeParent != null)
{
sbmlElements.push(astNodeParent);
}
else
{
Constraint constraint = new Constraint(3,1);
sbmlElements.push(constraint);
}
} else if (currentNode.getLocalPart().equals("annotation")) {
// get the sbml namespace as some element can have similar names in different namespaces
SBMLDocument sbmlDoc = (SBMLDocument) sbmlElements.firstElement();
String sbmlNamespace = sbmlDoc.getSBMLDocumentNamespaces().get("xmlns");
if (currentNode.getNamespaceURI().equals(sbmlNamespace)) {
if (isInsideAnnotation) {
logger.warn("Starting to read a new annotation element while the previous annotation element is not finished.");
}
isInsideAnnotation = true;
annotationDeepness++;
}
} else if (isInsideAnnotation) {
// Count the number of open elements to know how deep we are in the annotation
// We should only parse the RDF is annotationDeepness == 1 && rdfDescriptionIndex == 0
annotationDeepness++;
}
else if (currentNode.getLocalPart().equals("notes"))
{
// get the sbml namespace as some element can have similar names in different namespaces
SBase firstElement = (SBase) sbmlElements.firstElement();
if (firstElement instanceof SBMLDocument) {
SBMLDocument sbmlDoc = (SBMLDocument) firstElement;
String sbmlNamespace = sbmlDoc.getSBMLDocumentNamespaces().get("xmlns");
if (currentNode.getNamespaceURI().equals(sbmlNamespace)) {
isInsideNotes = true;
}
} else if (firstElement instanceof Constraint) { // we are reading a partial document from SBMLReader#readNotes for example
isInsideNotes = true;
}
}
// setting isRDFSBMLSpecificAnnotation
if (currentNode.getLocalPart().equals("RDF") && currentNode.getNamespaceURI().equals(Annotation.URI_RDF_SYNTAX_NS) && annotationDeepness == 1) {
isRDFSBMLSpecificAnnotation = true;
} else if (currentNode.getLocalPart().equals("RDF") && currentNode.getNamespaceURI().equals(Annotation.URI_RDF_SYNTAX_NS)) {
isRDFSBMLSpecificAnnotation = false;
rdfDescriptionIndex = -1;
}
if (currentNode.getLocalPart().equals("Description") && currentNode.getNamespaceURI().equals(Annotation.URI_RDF_SYNTAX_NS) && isRDFSBMLSpecificAnnotation) {
rdfDescriptionIndex++;
}
if (isInsideAnnotation && logger.isDebugEnabled()) {
logger.debug("startElement: local part = " + currentNode.getLocalPart());
logger.debug("startElement: annotation deepness = " + annotationDeepness);
logger.debug("startElement: rdf description index = " + rdfDescriptionIndex);
logger.debug("startElement: isRDFSBMLSpecificAnnotation = " + isRDFSBMLSpecificAnnotation);
}
parser = processStartElement(startElement, currentNode, isHTML, sbmlElements,
isInsideNotes, annotationDeepness, isRDFSBMLSpecificAnnotation);
lastElement = sbmlElements.peek();
}
// Characters
else if (event.isCharacters()) {
Characters characters = event.asCharacters();
if (!characters.isWhiteSpace()) {
isText = true; // the characters are not only 'white spaces'
}
if (sbmlElements.peek() instanceof XMLNode || isInsideNotes) {
isText = true; // We want to keep the whitespace/formatting when reading html block
}
// process the text of a XML element.
if ((parser != null) && !sbmlElements.isEmpty() && (isText || isInsideAnnotation)) {
if (isInsideNotes) {
parser = initializedParsers.get(JSBML.URI_XHTML_DEFINITION);
}
// else if (isInsideAnnotation) {
// parser = initializedParsers.get("anyAnnotation");
// }
if (logger.isDebugEnabled()) {
logger.debug(" Parser = " + parser.getClass().getName());
logger.debug(" Characters = @" + characters.getData() + "@");
}
if (currentNode != null) {
// logger.debug("isCharacter: elementName = " + currentNode.getLocalPart());
parser.processCharactersOf(currentNode.getLocalPart(),
characters.getData(), sbmlElements.peek());
} else {
parser.processCharactersOf(null, characters.getData(),
sbmlElements.peek());
}
} else if (isText) {
logger.warn(MessageFormat.format("Some characters cannot be read: {0}", characters.getData()));
if (logger.isDebugEnabled()) {