/* * Logs a message about the conditional part of a piecewise function * that should have dimensionless units */ void ArgumentsUnitsCheck::logInconsistentPiecewiseCondition (const ASTNode & node, const SBase & sb) { char * formula = SBML_formulaToString(&node); msg = "The formula '"; msg += formula; msg += "' in the math element of the <"; msg += sb.getElementName(); msg += "> "; switch(sb.getTypeCode()) { case SBML_INITIAL_ASSIGNMENT: case SBML_EVENT_ASSIGNMENT: case SBML_ASSIGNMENT_RULE: case SBML_RATE_RULE: //LS DEBUG: could use other attribute values, or 'isSetActualId'. break; default: if (sb.isSetId()) { msg += "with id '"; msg += sb.getId() + "' "; } break; } msg += "uses a piecewise function"; msg += " where the conditional statement is not dimensionless."; safe_free(formula); logFailure(sb, msg); }
/* * @return the error message to use when logging constraint violations. * This method is called by logFailure. * * Returns a message that the given @p id and its corresponding object are * in conflict with an object previously defined. */ const string CiElementMathCheck::getMessage (const ASTNode& node, const SBase& object) { ostringstream msg; //msg << getPreamble(); char * formula = SBML_formulaToString(&node); msg << "The formula '" << formula; msg << "' in the " << getFieldname() << " element of the <" << object.getElementName(); msg << "> "; switch(object.getTypeCode()) { case SBML_INITIAL_ASSIGNMENT: case SBML_EVENT_ASSIGNMENT: case SBML_ASSIGNMENT_RULE: case SBML_RATE_RULE: //LS DEBUG: could use other attribute values, or 'isSetActualId'. break; default: if (object.isSetId()) { msg << "with id '" << object.getId() << "' "; } break; } if (object.getLevel() == 2 && object.getVersion() == 1) msg << "uses '" << node.getName() << "' that is not the id of a species/compartment/parameter."; else if (object.getLevel() < 3) msg << "uses '" << node.getName() << "' that is not the id of a species/compartment/parameter/reaction."; else msg << "uses '" << node.getName() << "' that is not the id of a species/compartment/parameter/reaction/speciesReference."; safe_free(formula); return msg.str(); }
/* * @return the error message to use when logging constraint violations. * This method is called by logFailure. * * Returns a message that the given @p id and its corresponding object are * in conflict with an object previously defined. */ const string FunctionApplyMathCheck::getMessage (const ASTNode& node, const SBase& object) { ostringstream msg; //msg << getPreamble(); char * formula = SBML_formulaToString(&node); msg << "The formula '" << formula; msg << "' in the " << getFieldname() << " element of the <" << object.getElementName(); msg << "> "; switch(object.getTypeCode()) { case SBML_INITIAL_ASSIGNMENT: case SBML_EVENT_ASSIGNMENT: case SBML_ASSIGNMENT_RULE: case SBML_RATE_RULE: //LS DEBUG: could use other attribute values, or 'isSetActualId'. break; default: if (object.isSetId()) { msg << "with id '" << object.getId() << "' "; } break; } msg << "uses '" << node.getName() << "' which is not a function definition id."; safe_free(formula); return msg.str(); }
/* * Logs a message about a function that should return same units * as the arguments */ void ArgumentsUnitsCheck::logInconsistentSameUnits (const ASTNode & node, const SBase & sb) { char * formula = SBML_formulaToString(&node); msg = "The formula '" ; msg += formula; msg += "' in the math element of the <"; msg += sb.getElementName(); msg += "> "; switch(sb.getTypeCode()) { case SBML_INITIAL_ASSIGNMENT: case SBML_EVENT_ASSIGNMENT: case SBML_ASSIGNMENT_RULE: case SBML_RATE_RULE: //LS DEBUG: could use other attribute values, or 'isSetActualId'. break; default: if (sb.isSetId()) { msg += "with id '"; msg += sb.getId() + "' "; } break; } msg += "can only act on variables with the same units."; safe_free(formula); logFailure(sb, msg); }
/* * @return the error message to use when logging constraint violations. * This method is called by logFailure. * * Returns a message that the given @p id and its corresponding object are * in conflict with an object previously defined. */ const string ArgumentsUnitsCheck::getMessage (const ASTNode& node, const SBase& object) { ostringstream msg; //msg << getPreamble(); char * formula = SBML_formulaToString(&node); msg << "The formula '" << formula; msg << "' in the " << getFieldname() << " element of the <" << object.getElementName(); msg << "> "; switch(object.getTypeCode()) { case SBML_INITIAL_ASSIGNMENT: case SBML_EVENT_ASSIGNMENT: case SBML_ASSIGNMENT_RULE: case SBML_RATE_RULE: //LS DEBUG: could use other attribute values, or 'isSetActualId'. break; default: if (object.isSetId()) { msg << "with id '" << object.getId() << "' "; } break; } msg << "produces an exponent that is not an integer and thus may produce "; msg << "invalid units."; safe_free(formula); return msg.str(); }
/* * @return the error message to use when logging constraint violations. * This method is called by logFailure. * * Returns a message that the given @p id and its corresponding object are * in conflict with an object previously defined. */ const string NumericArgsMathCheck::getMessage (const ASTNode& node, const SBase& object) { ostringstream msg; //msg << getPreamble(); char * formula = SBML_formulaToString(&node); msg << "The formula '" << formula; msg << "' in the " << getFieldname() << " element of the <" << object.getElementName(); msg << "> "; switch(object.getTypeCode()) { case SBML_INITIAL_ASSIGNMENT: case SBML_EVENT_ASSIGNMENT: case SBML_ASSIGNMENT_RULE: case SBML_RATE_RULE: //LS DEBUG: could use other attribute values, or 'isSetActualId'. break; default: if (object.isSetId()) { msg << "with id '" << object.getId() << "' "; } break; } msg << "uses an argument to a operator that expects a numeric value."; safe_free(formula); return msg.str(); }
/* * @return the error message to use when logging constraint violations. * This method is called by logFailure. * * Returns a message that the given @p id and its corresponding object are * in conflict with an object previously defined. */ const string PieceBooleanMathCheck::getMessage (const ASTNode& node, const SBase& object) { ostringstream oss_msg; //oss_msg << getPreamble(); char * formula = SBML_formulaToString(&node); oss_msg << "The formula '" << formula; oss_msg << "' in the " << getFieldname() << " element of the <" << object.getElementName(); oss_msg << "> "; switch(object.getTypeCode()) { case SBML_INITIAL_ASSIGNMENT: case SBML_EVENT_ASSIGNMENT: case SBML_ASSIGNMENT_RULE: case SBML_RATE_RULE: //LS DEBUG: could use other attribute values, or 'isSetActualId'. break; default: if (object.isSetId()) { oss_msg << "with id '" << object.getId() << "' "; } break; } oss_msg << "uses a piecewise function that does not return a Boolean."; safe_free(formula); return oss_msg.str(); }
/* * @return the error message to use when logging constraint violations. * This method is called by logFailure. * * Returns a message that the given @p id and its corresponding object are * in conflict with an object previously defined. */ const string GroupsUniqueModelWideIds::getMessage (const string& id, const SBase& object) { IdObjectMap::iterator iter = mIdMap.find(id); if (iter == mIdMap.end()) { return "Internal (but non-fatal) Validator error in " "GroupsUniqueModelWideIds::getMessage(). The SBML object with duplicate id was " "not found when it came time to construct a descriptive error message."; } ostringstream msg; const SBase& previous = *(iter->second); //msg << getPreamble(); // // Example message: // // The <compartment> id 'cell' conflicts with the previously defined // <parameter> id 'cell' at line 10. // msg << " The <" << object.getElementName() << "> id '" << id << "' conflicts with the previously defined <" << previous.getElementName() << "> id '" << id << "'"; if (previous.getLine() != 0) { msg << " at line " << previous.getLine(); } msg << '.'; return msg.str(); }
int CompModelPlugin::saveAllReferencedElements(set<SBase*> uniqueRefs, set<SBase*> replacedBys) { SBMLDocument* doc = getSBMLDocument(); Model* model = static_cast<Model*>(getParentSBMLObject()); if (model==NULL) { if (doc) { string error = "Unable to discover any referenced elements in CompModelPlugin::saveAllReferencedElements: no Model parent of the 'comp' model plugin."; doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error); } return LIBSBML_OPERATION_FAILED; } int ret = LIBSBML_OPERATION_SUCCESS; //Get a list of everything, pull out anything that's a deletion, replacement, or port, and save what they're pointing to. //At the same time, make sure that no two things point to the same thing. set<SBase*> RE_deletions = set<SBase*>(); //Deletions only point to things in the same model. List* allElements = model->getAllElements(); string modname = "the main model in the document"; if (model->isSetId()) { modname = "the model '" + model->getId() + "'"; } set<SBase*> todelete; for (unsigned int el=0; el<allElements->getSize(); el++) { SBase* element = static_cast<SBase*>(allElements->get(el)); int type = element->getTypeCode(); if (type==SBML_COMP_DELETION || type==SBML_COMP_REPLACEDBY || type==SBML_COMP_REPLACEDELEMENT || type==SBML_COMP_PORT) { //Don't worry about SBML_COMP_SBASEREF because they're all children of one of the above types. SBaseRef* reference = static_cast<SBaseRef*>(element); ReplacedElement* re = static_cast<ReplacedElement*>(element); ret = reference->saveReferencedElement(); if (ret != LIBSBML_OPERATION_SUCCESS) { if (type != SBML_COMP_REPLACEDBY && doc) { SBMLErrorLog* errlog = doc->getErrorLog(); SBMLError* lasterr = const_cast<SBMLError*> (doc->getErrorLog()->getError(doc->getNumErrors()-1)); if ( (errlog->contains(UnrequiredPackagePresent) || errlog->contains(RequiredPackagePresent))) { if ( lasterr->getErrorId() == CompIdRefMustReferenceObject) { //Change the error into a warning string fullmsg = lasterr->getMessage() + " However, this may be because of the unrecognized " + "package present in this document: ignoring this " + "element and flattening anyway."; errlog->remove(lasterr->getErrorId()); errlog->logPackageError("comp", CompIdRefMayReferenceUnknownPackage, getPackageVersion(), getLevel(), getVersion(), fullmsg, element->getLine(), element->getColumn(), LIBSBML_SEV_WARNING); } else if ( lasterr->getErrorId() == CompMetaIdRefMustReferenceObject) { //Change the error into a warning string fullmsg = lasterr->getMessage() + " However, this may be because of the unrecognized " + "package present in this document: ignoring this " + "element and flattening anyway."; errlog->remove(lasterr->getErrorId()); errlog->logPackageError("comp", CompMetaIdRefMayReferenceUnknownPkg, getPackageVersion(), getLevel(), getVersion(), fullmsg, element->getLine(), element->getColumn(), LIBSBML_SEV_WARNING); } } //Whether or not we could figure out the error, we can always still continue flattening. todelete.insert(element); continue; } else { delete allElements; return ret; } } SBase* direct = reference->getDirectReference(); bool adddirect = true; if (type == SBML_COMP_REPLACEDBY) { SBase* rbParent = reference->getParentSBMLObject(); if (uniqueRefs.insert(rbParent).second == false) { if (doc) { string error = "Error discovered in CompModelPlugin::saveAllReferencedElements when checking " + modname + ": a <" + rbParent->getElementName() + "> "; if (direct->isSetId()) { error += "with the id '" + rbParent->getId() + "'"; if (rbParent->isSetMetaId()) { error += ", and the metaid '" + rbParent->getMetaId() + "'"; } } else if (rbParent->isSetMetaId()) { error += "with the metaId '" + rbParent->getMetaId() + "'"; } error += " has a <replacedBy> child and is also pointed to by a <port>, <deletion>, <replacedElement>, or one or more <replacedBy> objects."; doc->getErrorLog()->logPackageError("comp", CompNoMultipleReferences, getPackageVersion(), getLevel(), getVersion(), error); } delete allElements; return LIBSBML_OPERATION_FAILED; } adddirect = replacedBys.insert(direct).second; } if (type==SBML_COMP_REPLACEDELEMENT && re->isSetDeletion()) { adddirect = RE_deletions.insert(direct).second; } if (adddirect) { if (uniqueRefs.insert(direct).second == false) { if (doc) { string error = "Error discovered in CompModelPlugin::saveAllReferencedElements when checking " + modname + ": "; if (replacedBys.find(direct) != replacedBys.end()) { error += "one or more <replacedBy> elements, plus a <deletion>, <replacedElement>, or <port> element"; } else if (RE_deletions.find(direct) != RE_deletions.end()) { error += "one or more <replacedElement> elements using a 'deletion' attribute, plus a <deletion>, <replacedElement>, or <port> element"; } else { error += "multiple <deletion>, <replacedElement>, and/or <port> elements"; } error += " point directly to the <" + direct->getElementName() + "> "; if (direct->isSetId()) { error += "with the id '" + direct->getId() + "'"; if (direct->isSetMetaId()) { error += ", and the metaid '" + direct->getMetaId() + "'"; } error += "."; } else if (direct->isSetMetaId()) { error += "with the metaId '" + direct->getMetaId() + "'."; } doc->getErrorLog()->logPackageError("comp", CompNoMultipleReferences, getPackageVersion(), getLevel(), getVersion(), error); } delete allElements; return LIBSBML_OPERATION_FAILED; } } } } for(set<SBase*>::iterator el=todelete.begin(); el != todelete.end(); el++) { (*el)->removeFromParentAndDelete(); } delete allElements; //Now call saveAllReferencedElements for all instantiated submodels. for (unsigned long sm=0; sm<getNumSubmodels(); ++sm) { Model* sub = getSubmodel((unsigned int)sm)->getInstantiation(); if (sub==NULL) { return LIBSBML_OPERATION_FAILED; } CompModelPlugin* subplug = static_cast<CompModelPlugin*>(sub->getPlugin(getPrefix())); if (subplug==NULL) { return LIBSBML_OPERATION_FAILED; } ret = subplug->saveAllReferencedElements(uniqueRefs, replacedBys); if (ret != LIBSBML_OPERATION_SUCCESS) { return ret; } } return LIBSBML_OPERATION_SUCCESS; }
int ReplacedElement::performReplacementAndCollect(set<SBase*>* removed, set<SBase*>* toremove) { SBMLDocument* doc = getSBMLDocument(); if (isSetDeletion()) { //Deletions don't need to be replaced. return LIBSBML_OPERATION_SUCCESS; } //Find the various objects and plugin objects we need for this to work. SBase* lore = getParentSBMLObject(); ListOf* lorelist = static_cast<ListOf*>(lore); if (lore == NULL) { if (doc) { string error = "Cannot carry out replacement in ReplacedElement::performReplacement: no parent <listOfReplacedElements> could be found for the given replacement element."; doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn()); } return LIBSBML_INVALID_OBJECT; } if (lore->getTypeCode() != SBML_LIST_OF || lorelist->getItemTypeCode() != SBML_COMP_REPLACEDELEMENT) { if (doc) { string error = "Cannot carry out replacement in ReplacedElement::performReplacement: no parent <listOfReplacedElements> could be found for the given replacement element."; doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn()); } return LIBSBML_INVALID_OBJECT; } SBase* parent = lore->getParentSBMLObject(); if (parent==NULL) { if (doc) { string error = "Cannot carry out replacement in ReplacedElement::performReplacement: no parent could be found for the parent <listOfReplacedElements> object."; doc->getErrorLog()->logPackageError("comp", CompModelFlatteningFailed, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn()); } return LIBSBML_INVALID_OBJECT; } SBase* ref = getReferencedElement(); if (ref==NULL) { //getReferencedElement sets its own error messages. return LIBSBML_INVALID_OBJECT; } if (removed && removed->find(ref)!=removed->end()) { //Already deleted: can't get the deleted element's ID to if (doc) { string error = "Cannot carry out replacement in ReplacedElement::performReplacement: a <" + parent->getElementName() + ">"; if (parent->isSetId()) { error += " with the ID '" + parent->getId() + "'"; } error += " has a child <replacedElement> that points to something that has already been deleted, probably because its parent was deleted."; doc->getErrorLog()->logPackageError("comp", CompDeletedReplacement, getPackageVersion(), getLevel(), getVersion(), error, getLine(), getColumn()); } return LIBSBML_INVALID_OBJECT; } //Update the IDs. int ret = updateIDs(ref, parent); if (ret != LIBSBML_OPERATION_SUCCESS) { return ret; } //Perform any conversions on references in the submodel. ASTNode* blank = NULL; ret = performConversions(parent, &blank); if (ret != LIBSBML_OPERATION_SUCCESS) { if (blank != NULL) { delete blank; } return ret; } CompSBasePlugin* refplug = static_cast<CompSBasePlugin*>(ref->getPlugin(getPrefix())); if (refplug != NULL) { //Now recurse down the 'replace*' tree, renaming IDs and deleting things as we go. for (unsigned int re=0; re<refplug->getNumReplacedElements(); re++) { refplug->getReplacedElement(re)->replaceWithAndMaybeDelete(parent, true, blank); if (toremove) { toremove->insert(refplug->getReplacedElement(re)->getReferencedElement()); } } if (refplug->isSetReplacedBy()) { //Even if the subelement used to be replaced by something further down, it is now being replaced by the parent. It just can't catch a break, it seems. refplug->getReplacedBy()->replaceWithAndMaybeDelete(parent, true, blank); if (toremove) { toremove->insert(refplug->getReplacedBy()->getReferencedElement()); } } } if (toremove) { toremove->insert(ref); } if (blank != NULL) { delete blank; } return LIBSBML_OPERATION_SUCCESS; }