int ASTLambdaFunctionNode::removeChild(unsigned int n) { int removed = LIBSBML_OPERATION_FAILED; /* need to keep track of whether we have removed a bvar */ unsigned int numBvars = getNumBvars(); if (numBvars == 0) { /* we are removing the body - if the index is appropriate */ return ASTFunctionBase::removeChild(n); } if (n < numBvars) { // we are removing a bvar setNumBvars(numBvars - 1); /* HACK TO REPLICATE OLD AST */ /* Hack to remove memory since the overall * remove does not remove memory * but the old api does not give access to the new * intermediate parents so these can never * be explicilty deleted by the user * * in this case the first remove is accessible */ ASTBase * base = ASTFunctionBase::getChild(n); ASTNode * bvar = dynamic_cast<ASTNode*>(base); if (bvar != NULL && bvar->getNumChildren() == 1) { removed = bvar->removeChild(0); if (removed == LIBSBML_OPERATION_SUCCESS) { ASTBase * removedAST = NULL; removedAST = this->ASTFunctionBase::getChild(n); removed = ASTFunctionBase::removeChild(n); if (removedAST != NULL) delete removedAST; } } } else { // we are removing the body removed = ASTFunctionBase::removeChild(n); } return removed; }
int ASTBinaryFunctionNode::removeChild (unsigned int n) { int removed = LIBSBML_OPERATION_FAILED; if (this->getType() != AST_FUNCTION_LOG) { removed = ASTFunctionBase::removeChild(n); } else { /* HACK TO REPLICATE OLD AST */ /* Hack to remove memory since the overall * remove does not remove memory * but the old api does not give access to the new * intermediate parents so these can never * be explicilty deleted by the user * * in this case the first remove is accessible */ if (ASTFunctionBase::getChild(n)->getType() == AST_QUALIFIER_LOGBASE) { ASTBase * base = ASTFunctionBase::getChild(n); ASTNode * logbase = dynamic_cast<ASTNode*>(base); if (logbase != NULL && logbase->getNumChildren() == 1) { removed = logbase->removeChild(0); if (removed == LIBSBML_OPERATION_SUCCESS) { ASTBase * removedAST = NULL; removedAST = this->ASTFunctionBase::getChild(n); removed = ASTFunctionBase::removeChild(n); if (removedAST != NULL) delete removedAST; } } } else { removed = ASTFunctionBase::removeChild(n); } } return removed; }
int ASTNaryFunctionNode::removeChild (unsigned int n) { int removed = LIBSBML_OPERATION_FAILED; if (this->getType() != AST_FUNCTION_ROOT) { removed = ASTFunctionBase::removeChild(n); } else { /* HACK TO REPLICATE OLD AST */ /* Hack to remove memory since the overall * remove does not remove memory * but the old api does not give access to the new * intermediate parents so these can never * be explicilty deleted by the user * * in this case the first remove is accessible */ if (ASTFunctionBase::getChild(n)->getType() == AST_QUALIFIER_DEGREE) { ASTBase * base = ASTFunctionBase::getChild(n); ASTNode * degree = dynamic_cast<ASTNode*>(base); if (degree != NULL && degree->getNumChildren() == 1) { removed = degree->removeChild(0); if (removed == LIBSBML_OPERATION_SUCCESS) { ASTBase * removedAST = NULL; removedAST = this->ASTFunctionBase::getChild(n); removed = ASTFunctionBase::removeChild(n); if (removedAST != NULL) delete removedAST; } } } else { removed = ASTFunctionBase::removeChild(n); } } /* HACK TO REPLICATE OLD AST */ // if we now have an odd number of children the last one // should be subject NOT the degree if (removed == LIBSBML_OPERATION_SUCCESS) { unsigned int size = getNumChildren(); unsigned int numChildren = ASTFunctionBase::getNumChildren(); if ((unsigned int)(size%2) == 1) { ASTBase * child = ASTFunctionBase::getChild(numChildren-1); if (child->getType() == AST_QUALIFIER_DEGREE) { ASTNode * degree = dynamic_cast<ASTNode *>(child); if (degree != NULL && degree->getNumChildren() == 1) { ASTNode *pChild = degree->getChild(0); degree->removeChild(0); ASTBase * temp = this->ASTFunctionBase::getChild(numChildren-1); this->ASTFunctionBase::removeChild(numChildren-1); delete temp; this->addChild(pChild); } } } } return removed; }
int ASTPiecewiseFunctionNode::removeChild(unsigned int n) { int removed = LIBSBML_INDEX_EXCEEDS_SIZE; /* HACK TO REPLICATE OLD AST */ /* do not return a node with teh piece or otherwise type * return the correct child of the piece type * or the child of the otherwise */ unsigned int numChildren = ASTFunctionBase::getNumChildren(); // determine index that we actually want unsigned int childNo = (unsigned int)(n/2); unsigned int pieceIndex = (unsigned int)(n%2); unsigned int size = getNumChildren(); if (size == 0) { return LIBSBML_OPERATION_FAILED; } if (n < size) { if (getHasOtherwise() == true && childNo == numChildren - 1) { removed = ASTFunctionBase::removeChild(childNo); mHasOtherwise = false; } else if (ASTFunctionBase::getChild(childNo)->getType() == AST_CONSTRUCTOR_PIECE) { ASTBase * base = ASTFunctionBase::getChild(childNo); ASTNode * piece = dynamic_cast<ASTNode*>(base); if (piece != NULL) { if (piece->getNumChildren() > pieceIndex) { removed = piece->removeChild(pieceIndex); if (removed == LIBSBML_OPERATION_SUCCESS && piece->getNumChildren() == 0) { removed = this->ASTFunctionBase::removeChild(childNo); mNumPiece = mNumPiece - 1; } } else { removed = LIBSBML_OPERATION_FAILED; } } else { removed = LIBSBML_OPERATION_FAILED; } } else if (n < numChildren) { removed = ASTFunctionBase::removeChild(n); } else { removed = LIBSBML_OPERATION_FAILED; } } return removed; }
int Submodel::convertTimeAndExtentWith(const ASTNode* tcf, const ASTNode* xcf, const ASTNode* klmod) { if (tcf==NULL && xcf==NULL) return LIBSBML_OPERATION_SUCCESS; Model* model = getInstantiation(); if (model==NULL) { //getInstantiation sets its own error messages. return LIBSBML_OPERATION_FAILED; } ASTNode* tcftimes = NULL; ASTNode* tcfdiv = NULL; if (tcf != NULL) { tcftimes = new ASTNode(AST_TIMES); tcftimes->addChild(tcf->deepCopy()); tcfdiv = new ASTNode(AST_DIVIDE); tcfdiv->addChild(tcf->deepCopy()); } ASTNode* rxndivide = NULL; if (klmod != NULL) { rxndivide = new ASTNode(AST_DIVIDE); ASTNode rxnref(AST_NAME); rxndivide->addChild(rxnref.deepCopy()); rxndivide->addChild(klmod->deepCopy()); } List* allelements = model->getAllElements(); for (unsigned int el=0; el<allelements->getSize(); el++) { SBase* element = static_cast<SBase*>(allelements->get(el)); assert(element != NULL); ASTNode* ast1 = NULL; ASTNode* ast2 = NULL; Constraint* constraint = NULL; Delay* delay = NULL; EventAssignment* ea = NULL; InitialAssignment* ia = NULL; KineticLaw* kl = NULL; Priority* priority = NULL; RateRule* rrule = NULL; Rule* rule = NULL; Submodel* submodel = NULL; Trigger* trigger = NULL; string cf = ""; //Reaction math will be converted below, in the bits with the kinetic law. But because of that, we need to handle references *to* the reaction: even if it has no kinetic law, the units have changed, and this needs to be reflected by the flattening routine. if (rxndivide != NULL && element->getTypeCode()==SBML_REACTION && element->isSetId()) { rxndivide->getChild(0)->setName(element->getId().c_str()); for (unsigned int sube=0; sube<allelements->getSize(); sube++) { SBase* subelement = static_cast<SBase*>(allelements->get(sube)); subelement->replaceSIDWithFunction(element->getId(), rxndivide); } } //Submodels need their timeConversionFactor and extentConversionFactor attributes converted. We're moving top-down, so all we need to do here is fix the conversion factor attributes themselves, pointing them to new parameters if need be. if ((tcf !=NULL || xcf != NULL) && element->getTypeCode()==SBML_COMP_SUBMODEL) { submodel = static_cast<Submodel*>(element); if (tcf != NULL) { if (submodel->isSetTimeConversionFactor()) { createNewConversionFactor(cf, tcf, submodel->getTimeConversionFactor(), model); submodel->setTimeConversionFactor(cf); } else { submodel->setTimeConversionFactor(tcf->getName()); } } if (xcf != NULL) { if (submodel->isSetExtentConversionFactor()) { createNewConversionFactor(cf, xcf, submodel->getExtentConversionFactor(), model); submodel->setExtentConversionFactor(cf); } else { submodel->setExtentConversionFactor(xcf->getName()); } } } if (tcf==NULL) { if (klmod !=NULL && element->getTypeCode()==SBML_KINETIC_LAW) { kl = static_cast<KineticLaw*>(element); if (kl->isSetMath()) { ast1 = new ASTNode(AST_TIMES); ast1->addChild(klmod->deepCopy()); ast1->addChild(kl->getMath()->deepCopy()); kl->setMath(ast1); delete ast1; } } } else { // All math 'time' and 'delay' csymbols must still be converted. // Also, several constructs are modified directly. switch(element->getTypeCode()) { //This would be a WHOLE LOT SIMPLER if there was a 'hasMath' class in libsbml. But even so, it would have to // handle the kinetic laws, rate rules, and delays separately. case SBML_KINETIC_LAW: //Kinetic laws are multiplied by 'klmod'. kl = static_cast<KineticLaw*>(element); ast1 = kl->getMath()->deepCopy(); convertCSymbols(ast1, tcfdiv, tcftimes); if (klmod !=NULL) { kl = static_cast<KineticLaw*>(element); if (kl->isSetMath()) { ast2 = new ASTNode(AST_TIMES); ast2->addChild(klmod->deepCopy()); ast2->addChild(ast1); kl->setMath(ast2); delete ast2; } } else { kl->setMath(ast1); delete ast1; } break; case SBML_DELAY: //Delays are multiplied by the time conversion factor. delay = static_cast<Delay*>(element); if (delay->isSetMath()) { ast1 = delay->getMath()->deepCopy(); convertCSymbols(ast1, tcfdiv, tcftimes); tcftimes->addChild(ast1); delay->setMath(tcftimes); tcftimes->removeChild(1); } break; case SBML_RATE_RULE: //Rate rules are divided by the time conversion factor. rrule = static_cast<RateRule*>(element); if (rrule->isSetMath()) { ast1 = rrule->getMath()->deepCopy(); tcfdiv->insertChild(0, rrule->getMath()->deepCopy()); rrule->setMath(tcfdiv); tcfdiv->removeChild(0); } //Fall through to: case SBML_ASSIGNMENT_RULE: case SBML_ALGEBRAIC_RULE: //Rules in general need csymbols converted. rule = static_cast<Rule*>(element); if (rule->isSetMath()) { ast1 = rule->getMath()->deepCopy(); convertCSymbols(ast1, tcfdiv, tcftimes); rule->setMath(ast1); delete ast1; } break; case SBML_EVENT_ASSIGNMENT: //Event assignments need csymbols converted. ea = static_cast<EventAssignment*>(element); if (ea->isSetMath()) { ast1 = ea->getMath()->deepCopy(); convertCSymbols(ast1, tcfdiv, tcftimes); ea->setMath(ast1); delete ast1; } break; case SBML_INITIAL_ASSIGNMENT: //Initial assignments need csymbols converted. ia = static_cast<InitialAssignment*>(element); if (ia->isSetMath()) { ast1 = ia->getMath()->deepCopy(); convertCSymbols(ast1, tcfdiv, tcftimes); ia->setMath(ast1); delete ast1; } break; case SBML_CONSTRAINT: //Constraints need csymbols converted. constraint = static_cast<Constraint*>(element); if (constraint->isSetMath()) { ast1 = constraint->getMath()->deepCopy(); convertCSymbols(ast1, tcfdiv, tcftimes); constraint->setMath(ast1); delete ast1; } break; case SBML_PRIORITY: //Priorities need csymbols converted. priority = static_cast<Priority*>(element); if (priority->isSetMath()) { ast1 = priority->getMath()->deepCopy(); convertCSymbols(ast1, tcfdiv, tcftimes); priority->setMath(ast1); delete ast1; } break; case SBML_TRIGGER: //Triggers need csymbols converted. trigger = static_cast<Trigger*>(element); if (trigger->isSetMath()) { ast1 = trigger->getMath()->deepCopy(); convertCSymbols(ast1, tcfdiv, tcftimes); trigger->setMath(ast1); delete ast1; } break; default: //Do nothing! If we wanted to call a plugin routine, this would be the place. The only other alternative is to #ifdef some code in here that deals with the math-containing package objects explicitly. Which might be the best option, all told. break; } } } delete allelements; return LIBSBML_OPERATION_SUCCESS; }