/** * Sets the type of an ASTNode based on the given MathML <ci> element. * Errors will be logged in the stream's SBMLErrorLog object. */ static void setTypeCI (ASTNode& node, const XMLToken& element, XMLInputStream& stream) { if (element.getName() == "csymbol") { string url; element.getAttributes().readInto("definitionURL", url); if ( url == URL_DELAY ) node.setType(AST_FUNCTION_DELAY); else if ( url == URL_TIME ) node.setType(AST_NAME_TIME); else if ( url == URL_AVOGADRO ) node.setType(AST_NAME_AVOGADRO); else { static_cast <SBMLErrorLog*> (stream.getErrorLog())->logError(BadCsymbolDefinitionURLValue, stream.getSBMLNamespaces()->getLevel(), stream.getSBMLNamespaces()->getVersion()); } } else if (element.getName() == "ci") { node.setDefinitionURL(element.getAttributes()); } const string name = trim( stream.next().getCharacters() ); node.setName( name.c_str() ); }
bool XMLTokenizer::containsChild(bool & valid, const std::string& qualifier, const std::string& container) { valid = false; //unsigned int numQualifiers = 0; size_t size = mTokens.size(); if (size < 2) { return false; } unsigned int index = 0; //unsigned int depth = 0; std::string name; XMLToken next = mTokens.at(index); name = next.getName(); while (index < size-2) { // skip any text elements while(next.isText() == true && index < size-1) { index++; next = mTokens.at(index); } if (next.getName() == qualifier) { valid = true; return true; } index++; if (index < size) { next = mTokens.at(index); } } // we might have hit the end of the loop and the end of the correct tag if (valid == false && index >= size-2) { valid = true; } return false; }
bool ArraysASTPlugin::readMatrixRow(XMLInputStream& stream, const std::string& reqd_prefix, const XMLToken& currentElement) { bool read = false; stream.skipText(); const XMLToken nextElement = stream.peek(); const string& nextName = nextElement.getName(); unsigned int numChildren = determineNumChildren(stream, "matrixrow"); mVector = new ASTArraysVectorFunctionNode(AST_LINEAR_ALGEBRA_MATRIXROW_CONSTRUCTOR); mVector->setExpectedNumChildren(numChildren); // read attributes on this element here since we have already consumed // the element ExpectedAttributes expectedAttributes; mVector->addExpectedAttributes(expectedAttributes, stream); read = mVector->ASTBase::readAttributes(currentElement.getAttributes(), expectedAttributes, stream, currentElement); if (read == false) { mVector = NULL; } else { read = mVector->read(stream, reqd_prefix); } return read; }
bool ArraysASTPlugin::read(XMLInputStream& stream, const std::string& reqd_prefix, const XMLToken& currentElement) { bool read = false; stream.skipText(); const string& currentName = currentElement.getName(); //ASTBase::checkPrefix(stream, reqd_prefix, currentElement); // create appropriate sub class if (currentName == "vector") { read = readVector(stream, reqd_prefix, currentElement); } #if (0) else if (currentName == "matrix") { read = readMatrix(stream, reqd_prefix, currentElement); } else if (currentName == "matrixrow") { read = readMatrixRow(stream, reqd_prefix, currentElement); } #endif return read; }
bool ASTCiNumberNode::read(XMLInputStream& stream, const std::string& reqd_prefix) { bool read = false; const XMLToken element = stream.next (); const string& nameE = element.getName(); ASTBase::checkPrefix(stream, reqd_prefix, element); if (nameE != "ci") { #if 0 cout << "HELP\n"; #endif return read; } ExpectedAttributes expectedAttributes; addExpectedAttributes(expectedAttributes, stream); read = readAttributes(element.getAttributes(), expectedAttributes, stream, element); const string name = trim( stream.next().getCharacters() ); setName((name)); ASTBase::setType(AST_NAME); if (read == true) stream.skipPastEnd(element); return read; }
bool ASTUnaryFunctionNode::read(XMLInputStream& stream, const std::string& reqd_prefix) { bool read = false; ASTBase * child = NULL; const XMLToken element = stream.peek (); ASTBase::checkPrefix(stream, reqd_prefix, element); const char* name = element.getName().c_str(); setType(getTypeFromName(name)); ASTBase::read(stream, reqd_prefix); unsigned int numChildrenAdded = 0; if (getExpectedNumChildren() > 0) { while (stream.isGood() && numChildrenAdded < getExpectedNumChildren()) { stream.skipText(); name = stream.peek().getName().c_str(); if (representsNumber(ASTBase::getTypeFromName(name)) == true) { child = new ASTNumber(); } else { child = new ASTFunction(); } read = child->read(stream, reqd_prefix); stream.skipText(); if (read == true && addChild(child) == LIBSBML_OPERATION_SUCCESS) { numChildrenAdded++; } else { delete child; child = NULL; read = false; break; } } } else { stream.skipPastEnd(element); read = true; } return read; }
/* * @return @c true if this XMLToken is an XML end element for the given XML * start element, false otherwise. */ bool XMLToken::isEndFor (const XMLToken& element) const { return isEnd() && !isStart() && element.isStart() && element.getName() == getName() && element.getURI () == getURI (); }
void ASTBase::checkPrefix(XMLInputStream &stream, const std::string& reqd_prefix, const XMLToken& element) { if (!reqd_prefix.empty()) { std::string prefix = element.getPrefix(); if (prefix != reqd_prefix) { const string message = "Element <" + element.getName() + "> should have prefix \"" + reqd_prefix + "\"."; logError(stream, element, InvalidMathElement, message); } } }
bool ASTCnRealNode::read(XMLInputStream& stream, const std::string& reqd_prefix) { bool read = false; const XMLToken element = stream.peek (); const string& name = element.getName(); ASTBase::checkPrefix(stream, reqd_prefix, element); if (name != "cn") { #if 0 cout << "HELP\n"; #endif return read; } ASTCnBase::read(stream, reqd_prefix); std::string type = "real"; element.getAttributes().readInto("type", type); if (type == "real") { double value = 0; istringstream isreal; isreal.str( stream.next().getCharacters() ); isreal >> value; setReal(value); ASTBase::setType(AST_REAL); if (isreal.fail() || (util_isInf(getValue()) > 0) || (util_isInf(getValue()) < 0) ) { logError(stream, element, FailedMathMLReadOfDouble); } read = true; }
/* * Copy constructor; creates a copy of this XMLToken. */ XMLToken::XMLToken(const XMLToken& orig) : mTriple() , mAttributes() , mNamespaces() , mChars (orig.mChars) , mIsStart (orig.mIsStart) , mIsEnd (orig.mIsEnd) , mIsText (orig.mIsText) , mLine (orig.mLine) , mColumn (orig.mColumn) { if (!orig.mTriple.isEmpty()) mTriple = XMLTriple(orig.getName(), orig.getURI(), orig.getPrefix()); if (!orig.mAttributes.isEmpty()) mAttributes = XMLAttributes(orig.getAttributes()); if (!orig.mNamespaces.isEmpty()) mNamespaces = XMLNamespaces(orig.getNamespaces()); }
bool ASTCnIntegerNode::read(XMLInputStream& stream, const std::string& reqd_prefix) { bool read = false; const XMLToken element = stream.peek (); const string& name = element.getName(); ASTBase::checkPrefix(stream, reqd_prefix, element); if (name != "cn") { cout << "HELP\n"; return read; } ASTCnBase::read(stream, reqd_prefix); std::string type; element.getAttributes().readInto("type", type); if (type == "integer") { int value = 0; istringstream isint; isint.str( stream.next().getCharacters() ); isint >> value; if (isint.fail()) { logError(stream, element, FailedMathMLReadOfInteger); } else if ( sizeof(int) > 4 && ( (value > SBML_INT_MAX) || (value < SBML_INT_MIN) ) ) { logError(stream, element, FailedMathMLReadOfInteger); } setInteger(value); ASTBase::setType(AST_INTEGER); read = true; }
bool ASTCnExponentialNode::read(XMLInputStream& stream, const std::string& reqd_prefix) { bool read = false; const XMLToken element = stream.peek (); const string& name = element.getName(); ASTBase::checkPrefix(stream, reqd_prefix, element); if (name != "cn") { #if 0 cout << "HELP\n"; #endif return read; } ASTCnBase::read(stream, reqd_prefix); std::string type; element.getAttributes().readInto("type", type); if (type == "e-notation") { double mantissa = 0; long exponent = 0; istringstream ismantissa; istringstream isexponent; ismantissa.str( stream.next().getCharacters() ); ismantissa >> mantissa; if (stream.peek().getName() == "sep") { stream.next(); isexponent.str( stream.next().getCharacters() ); isexponent >> exponent; }
unsigned int XMLTokenizer::determineNumSpecificChildren(bool & valid, const std::string& qualifier, const std::string& container) { valid = false; unsigned int numQualifiers = 0; size_t size = mTokens.size(); if (size < 2) { return numQualifiers; } unsigned int depth = 0; unsigned int index = 0; std::string name; std::string prevName = ""; std::string rogueTag = ""; XMLToken next = mTokens.at(index); name = next.getName(); if (next.isStart() == true && next.isEnd() == true && name == qualifier && index < size) { numQualifiers++; index++; next = mTokens.at(index); } bool cleanBreak = false; while (index < size-2) { // skip any text elements while(next.isText() == true && index < size-1) { index++; next = mTokens.at(index); } if (next.isEnd() == true) { if (next.getName() == container) { valid = true; break; } //else if (!rogueTag.empty() && next.getName() == rogueTag) //{ // index++; // next = mTokens.at(index); // break; //} } // iterate to first start element while (next.isStart() == false && index < size-1) { index++; next = mTokens.at(index); } if (next.isStart() == true && next.isEnd() == true) { if (qualifier.empty() == true) { // if we are not looking for a specifc element then // we may have a child that is a start and end // such as <true/> numQualifiers++; } index++; if (index < size) { next = mTokens.at(index); continue; } } // check we have not reached the end // this would be a bad place if we have so set num children to zero if (index == size) { numQualifiers = 0; break; } // record the name of the start element name = next.getName(); // need to deal with the weird situation where someone has used a tag // after the piece but before the next correct element //if (container == "piecewise") //{ // if (prevName == "piece") // { // if (name != "piece" && name != "otherwise") // { // rogueTag = name; // index++; // next = mTokens.at(index); // continue; // } // } //} if (qualifier.empty() == true || name == qualifier) { numQualifiers++; } // index++; // check we have not reached the end if (index+1 == size) { numQualifiers = 0; break; } else { index++; next = mTokens.at(index); } // iterate to the end of </name> // checking that we have not got a nested element <name></name> cleanBreak = false; while (index < size-1) { if (next.isStart() == true && next.getName() == name) { depth++; } if (next.isEnd() == true && next.getName() == name) { if (depth == 0) { cleanBreak = true; break; } else { depth--; } } index++; if (index < size) { next = mTokens.at(index); } } prevName = name; index++; if (index < size) { next = mTokens.at(index); } } // we might have hit the end of the loop and the end of the correct tag if (valid == false && cleanBreak == true) { if (index >= size-2 && next.isEnd() == true && next.getName() == container) { valid = true; } } return numQualifiers; }
bool ASTCSymbolDelayNode::read(XMLInputStream& stream, const std::string& reqd_prefix) { bool read = false; XMLToken element = stream.peek (); const string& nameE = element.getName(); if (nameE != "csymbol") { #if 0 cout << "HELP\n"; #endif return read; } ASTBase::read(stream, reqd_prefix); const string nameDelay = trim( stream.next().getCharacters() ); setName((nameDelay)); ASTBase::setType(AST_FUNCTION_DELAY); stream.skipPastEnd(element); const char * name; ASTBase * child = NULL; unsigned int numChildrenAdded = 0; // catch if we do not have two children if (getExpectedNumChildren() > 0) { while (stream.isGood() && numChildrenAdded < getExpectedNumChildren()) { stream.skipText(); name = stream.peek().getName().c_str(); if (representsNumber(ASTBase::getTypeFromName(name)) == true) { child = new ASTNumber(); } else { child = new ASTFunction(); } read = child->read(stream, reqd_prefix); stream.skipText(); if (read == true && addChild(child) == LIBSBML_OPERATION_SUCCESS) { numChildrenAdded++; } else { read = false; break; } } } else { stream.skipPastEnd(element); read = true; } return read; }
bool ASTBase::readAttributes(const XMLAttributes& attributes, const ExpectedAttributes& expectedAttributes, XMLInputStream& stream, const XMLToken& element) { bool read = true; // // check that all attributes are expected // for (int i = 0; i < attributes.getLength(); i++) { std::string name = attributes.getName(i); std::string uri = attributes.getURI(i); std::string prefix = attributes.getPrefix(i); // // To allow prefixed attribute whose namespace doesn't belong to // core or extension package. // // (e.g. xsi:type attribute in Curve element in layout extension) // if (!prefix.empty()) { if ( expectedAttributes.hasAttribute(prefix + ":" + name) ) continue; } if (!expectedAttributes.hasAttribute(name)) { std::string message = "The attribute '" + name + "' is not permitted" + " on a <" + element.getName() + "> element."; if (name == "type") { logError(stream, element, DisallowedMathTypeAttributeUse, message); } else if (name == "encoding") { logError(stream, element, DisallowedMathMLEncodingUse, message); } else if (name == "definitionURL") { logError(stream, element, DisallowedDefinitionURLUse, message); } else if (name == "units") { if (stream.getSBMLNamespaces() != NULL && stream.getSBMLNamespaces()->getLevel() > 2) { logError(stream, element, DisallowedMathUnitsUse, message); } else { message = "The 'units' attribute was introduced in SBML Level 3."; logError(stream, element, InvalidMathMLAttribute, message); } } else { logError(stream, element, InvalidMathElement, message); } // not sufficient to make the read bad //return false; } } string id; string className; string style; attributes.readInto( "id" , id ); attributes.readInto( "class" , className ); attributes.readInto( "style" , style ); if (!id.empty()) { if (setId(id) != LIBSBML_OPERATION_SUCCESS) { read = false; } } if (!className.empty()) { if (setClass(className) != LIBSBML_OPERATION_SUCCESS) { read = false; } } if (!style.empty()) { if (setStyle(style) != LIBSBML_OPERATION_SUCCESS) { read = false; } } unsigned int i = 0; while (read == true && i < getNumPlugins()) { read = getPlugin(i)->readAttributes(attributes, expectedAttributes, stream, element, getExtendedType()); i++; } return read; }
bool ASTNaryFunctionNode::read(XMLInputStream& stream, const std::string& reqd_prefix) { bool read = false; ASTBase * child = NULL; const XMLToken element = stream.peek (); ASTBase::checkPrefix(stream, reqd_prefix, element); const char* name = element.getName().c_str(); int type = getTypeFromName(name); setType(type); ASTBase::read(stream, reqd_prefix); unsigned int numChildrenAdded = 0; if (getExpectedNumChildren() > 0) { while (stream.isGood() && numChildrenAdded < getExpectedNumChildren()) { stream.skipText(); name = stream.peek().getName().c_str(); if (representsNumber(ASTBase::getTypeFromName(name)) == true) { child = new ASTNumber(); } else { child = new ASTFunction(); } read = child->read(stream, reqd_prefix); stream.skipText(); if (read == true && addChild(child) == LIBSBML_OPERATION_SUCCESS) { numChildrenAdded++; } else { delete child; child = NULL; read = false; break; } } } else { stream.skipPastEnd(element); read = true; } if (read == true && type == AST_FUNCTION_ROOT && getExpectedNumChildren() == 1 && ASTFunctionBase::getChild(0)->getType() != AST_QUALIFIER_DEGREE) { /* HACK TO REPLICATE OLD BEHAVIOUR */ /* we need to add the qualifier child for the degree 2 */ ASTFunction * degree = new ASTFunction(AST_QUALIFIER_DEGREE); ASTNumber * int2 = new ASTNumber(AST_INTEGER); int2->setInteger(2); degree->addChild(int2->deepCopy()); this->prependChild(degree->deepCopy()); delete int2; delete degree; } //if (read == false) //{ // stream.skipPastEnd(element); //} return read; }
unsigned int XMLTokenizer::determineNumberChildren(bool & valid, const std::string element) { valid = false; unsigned int numChildren = 0; std::string closingTag = element; bool forcedElement = true; if (closingTag.empty() == true) { closingTag = "apply"; forcedElement = false; } // if there is only one token there cannot be any children size_t size = mTokens.size(); if (size < 2) { return numChildren; } // we assume that the first unread token is a // function and that at some point in the // list of tokens we will hit the end of the // element for that function // need to count the number of starts unsigned int index = 0; XMLToken firstUnread = mTokens.at(index); while (firstUnread.isText() && index < size - 1) { // skip any text index++; firstUnread = mTokens.at(index); } // if we have an apply the firstToken should be a function // that is both a start and an end // unless we are reading a user function // or a csymbol // if the tag is not a start and an end this is an error // we want to exit // but be happy that the read is ok // and the error gets logged elsewhere if (closingTag == "apply") { std::string firstName = firstUnread.getName(); if (firstName != "ci" && firstName != "csymbol") { if (firstUnread.isStart() != true || (firstUnread.isStart() == true && firstUnread.isEnd() != true)) { valid = true; return numChildren; } } } index = 1; if (forcedElement == true) { index = 0; } unsigned int depth = 0; std::string name; bool cleanBreak = false; XMLToken next = mTokens.at(index); while (index < size-2) { // skip any text elements while(next.isText() == true && index < size-1) { index++; next = mTokens.at(index); } if (next.isEnd() == true && next.getName() == closingTag) { valid = true; break; } // iterate to first start element while (next.isStart() == false && index < size-1) { index++; next = mTokens.at(index); } // check we have not reached the end // this would be a bad place if we have so set num children to zero if (index == size) { numChildren = 0; break; } // record the name of the start element name = next.getName(); numChildren++; // index++; // check we have not reached the end if (index + 1 == size) { numChildren = 0; break; } else if (next.isEnd() == false) { index++; if (index < size) { next = mTokens.at(index); } else { break; } } // iterate to the end of </name> // checking that we have not got a nested element <name></name> cleanBreak = false; while (index < size-1) { if (next.isStart() == true && next.isEnd() == false && next.getName() == name) { depth++; } if (next.isEnd() == true && next.getName() == name) { if (depth == 0) { cleanBreak = true; break; } else { depth--; } } index++; next = mTokens.at(index); } index++; if (index < size) { next = mTokens.at(index); } } // we might have hit the end of the loop and the end of the correct tag // but the loop hits before it can record that it was valid if (valid == false && cleanBreak == true) { if (index >= size-2 && next.isEnd() == true && next.getName() == closingTag) { valid = true; } } return numChildren; }