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;
}
Example #5
0
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;
}