1 /**
2  * @file    GeneAssociation.cpp
3  * @brief   Implementation of GeneAssociation, the SBase derived class of the fbc package.
4  * @author  Akiya Jouraku
5  *
6  *<!---------------------------------------------------------------------------
7  * This file is part of libSBML.  Please visit http://sbml.org for more
8  * information about SBML, and the latest version of libSBML.
9  *
10  * Copyright (C) 2020 jointly by the following organizations:
11  *     1. California Institute of Technology, Pasadena, CA, USA
12  *     2. University of Heidelberg, Heidelberg, Germany
13  *     3. University College London, London, UK
14  *
15  * Copyright (C) 2019 jointly by the following organizations:
16  *     1. California Institute of Technology, Pasadena, CA, USA
17  *     2. University of Heidelberg, Heidelberg, Germany
18  *
19  * Copyright (C) 2013-2018 jointly by the following organizations:
20  *     1. California Institute of Technology, Pasadena, CA, USA
21  *     2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK
22  *     3. University of Heidelberg, Heidelberg, Germany
23  *
24  * Copyright (C) 2009-2013 jointly by the following organizations:
25  *     1. California Institute of Technology, Pasadena, CA, USA
26  *     2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK
27  *
28  * This library is free software; you can redistribute it and/or modify it
29  * under the terms of the GNU Lesser General Public License as published by
30  * the Free Software Foundation.  A copy of the license agreement is provided
31  * in the file named "LICENSE.txt" included with this software distribution
32  * and also available online as http://sbml.org/software/libsbml/license.html
33  *------------------------------------------------------------------------- -->
34  */
35 
36 #include <iostream>
37 #include <limits>
38 
39 #include <sbml/SBMLVisitor.h>
40 #include <sbml/xml/XMLNode.h>
41 #include <sbml/xml/XMLToken.h>
42 #include <sbml/xml/XMLAttributes.h>
43 #include <sbml/xml/XMLInputStream.h>
44 #include <sbml/xml/XMLOutputStream.h>
45 
46 #include <sbml/packages/fbc/sbml/GeneAssociation.h>
47 #include <sbml/packages/fbc/extension/FbcExtension.h>
48 
49 using namespace std;
50 
51 LIBSBML_CPP_NAMESPACE_BEGIN
52 #ifdef __cplusplus
53 
54 /*
55  * Creates a new GeneAssociation with the given level, version, and package version.
56  */
GeneAssociation(unsigned int level,unsigned int version,unsigned int pkgVersion)57 GeneAssociation::GeneAssociation (unsigned int level, unsigned int version, unsigned int pkgVersion)
58   : SBase (level,version)
59 //   ,mId("")
60    ,mReaction("")
61    ,mAssociation(NULL)
62 {
63   // set an SBMLNamespaces derived object (FbcPkgNamespaces) of this package.
64   setSBMLNamespacesAndOwn(new FbcPkgNamespaces(level,version,pkgVersion));
65 }
66 
67 
68 /*
69  * Creates a new GeneAssociation with the given FbcPkgNamespaces object.
70  */
GeneAssociation(FbcPkgNamespaces * fbcns)71 GeneAssociation::GeneAssociation(FbcPkgNamespaces* fbcns)
72  : SBase(fbcns)
73 //  ,mId("")
74   ,mReaction("")
75   ,mAssociation(NULL)
76 {
77   //
78   // set the element namespace of this object
79   //
80   setElementNamespace(fbcns->getURI());
81 
82   // load package extensions bound with this object (if any)
83   loadPlugins(fbcns);
84 }
85 
86 
87 /*
88  * Copy constructor.
89  */
GeneAssociation(const GeneAssociation & source)90 GeneAssociation::GeneAssociation(const GeneAssociation& source)
91   : SBase(source)
92 //  , mId(source.mId)
93   , mReaction(source.mReaction)
94   , mAssociation(NULL)
95 {
96     if (source.mAssociation != NULL)
97       this->mAssociation = new Association(*source.mAssociation);
98     else
99       this->mAssociation = NULL;
100 }
101 
102 
103 
104 /*
105  * Creates a new GeneAssociation from the given XMLNode
106  */
GeneAssociation(const XMLNode & node,FbcPkgNamespaces * fbcns)107 GeneAssociation::GeneAssociation(const XMLNode& node, FbcPkgNamespaces* fbcns)
108 : SBase(fbcns)
109 //,mId("")
110 ,mReaction("")
111 ,mAssociation(NULL)
112 {
113   //
114   // set the element namespace of this object
115   //
116   setElementNamespace(fbcns->getURI());
117 
118   // load package extensions bound with this object (if any)
119   loadPlugins(fbcns);
120 
121   const XMLAttributes& attributes=node.getAttributes();
122   const XMLNode* child;
123 
124   //ExpectedAttributes ea(getElementName());
125   ExpectedAttributes ea;
126   addExpectedAttributes(ea);
127   this->readAttributes(attributes,ea);
128   unsigned int n=0,nMax = node.getNumChildren();
129   while(n<nMax)
130   {
131     child=&node.getChild(n);
132     const std::string& childName=child->getName();
133 
134     if(childName=="gene" || childName=="or" || childName == "and")
135     {
136       mAssociation = new Association(*child, new FbcPkgNamespaces(*fbcns));
137     }
138     else if(childName=="annotation")
139     {
140       this->mAnnotation=new XMLNode(*child);
141     }
142     else if(childName=="notes")
143     {
144       this->mNotes=new XMLNode(*child);
145     }
146     else
147     {
148       //throw;
149     }
150     ++n;
151   }
152   setSBMLNamespacesAndOwn(fbcns);
153   connectToChild();
154 }
155 
156 
157 /*
158  * Creates an XMLNode object from this.
159  */
toXML() const160 XMLNode GeneAssociation::toXML() const
161 {
162   XMLNamespaces xmlns = XMLNamespaces();
163   XMLTriple triple = XMLTriple(getElementName(), "", "");
164   XMLAttributes att = XMLAttributes();
165 
166   if (isSetId())
167   {
168     att.add("id", mId);
169   }
170   if (isSetReaction())
171   {
172     att.add("reaction", mReaction);
173   }
174 
175   XMLToken token = XMLToken(triple, att, xmlns);
176   XMLNode node(token);
177   // add the notes and annotations
178   if(mNotes) node.addChild(*this->mNotes);
179   if(mAnnotation) node.addChild(*this->mAnnotation);
180 
181   if (isSetAssociation())
182   {
183     node.addChild(mAssociation->toXML());
184   }
185   return node;
186 }
187 
188 
189 /*
190  * Assignment operator.
191  */
operator =(const GeneAssociation & source)192 GeneAssociation& GeneAssociation::operator=(const GeneAssociation& source)
193 {
194   if(&source!=this)
195   {
196     this->SBase::operator=(source);
197     this->mId = source.mId;
198     this->mReaction = source.mReaction;
199     if (mAssociation != NULL)
200       delete mAssociation;
201     if (source.mAssociation != NULL)
202       this->mAssociation = new Association(*source.mAssociation);
203     else
204       this->mAssociation = NULL;
205   }
206 
207   return *this;
208 }
209 
210 
211 /*
212  * Destructor.
213  */
~GeneAssociation()214 GeneAssociation::~GeneAssociation ()
215 {
216   if (isSetAssociation())
217   {
218     delete mAssociation;
219     mAssociation = NULL;
220   }
221 }
222 
223 
224 /*
225   * Returns the value of the "id" attribute of this GeneAssociation.
226   */
227 const std::string&
getId() const228 GeneAssociation::getId () const
229 {
230   return mId;
231 }
232 
233 
234 /*
235   * Predicate returning @c true or @c false depending on whether this
236   * GeneAssociation's "id" attribute has been set.
237   */
238 bool
isSetId() const239 GeneAssociation::isSetId () const
240 {
241   return (mId.empty() == false);
242 }
243 
244 /*
245   * Sets the value of the "id" attribute of this GeneAssociation.
246   */
247 int
setId(const std::string & id)248 GeneAssociation::setId (const std::string& id)
249 {
250   return SyntaxChecker::checkAndSetSId(id ,mId);
251 }
252 
253 
254 /*
255   * Unsets the value of the "id" attribute of this GeneAssociation.
256   */
257 int
unsetId()258 GeneAssociation::unsetId ()
259 {
260   mId.erase();
261   if (mId.empty())
262   {
263     return LIBSBML_OPERATION_SUCCESS;
264   }
265   else
266   {
267     return LIBSBML_OPERATION_FAILED;
268   }
269 }
270 
271 
272 
273 /*
274   * Returns the value of the "reaction" attribute of this GeneAssociation.
275   */
276 const std::string&
getReaction() const277 GeneAssociation::getReaction () const
278 {
279   return mReaction;
280 }
281 
282 
283 /*
284   * Predicate returning @c true or @c false depending on whether this
285   * GeneAssociation's "reaction" attribute has been set.
286   */
287 bool
isSetReaction() const288 GeneAssociation::isSetReaction () const
289 {
290   return (mReaction.empty() == false);
291 }
292 
293 /*
294   * Sets the value of the "reaction" attribute of this GeneAssociation.
295   */
296 int
setReaction(const std::string & reaction)297 GeneAssociation::setReaction (const std::string& reaction)
298 {
299   return SyntaxChecker::checkAndSetSId(reaction ,mReaction);
300 }
301 
302 
303 /*
304   * Unsets the value of the "reaction" attribute of this GeneAssociation.
305   */
306 int
unsetReaction()307 GeneAssociation::unsetReaction ()
308 {
309   mReaction.erase();
310   if (mReaction.empty())
311   {
312     return LIBSBML_OPERATION_SUCCESS;
313   }
314   else
315   {
316     return LIBSBML_OPERATION_FAILED;
317   }
318 }
319 
320 
321 /*
322  * Returns the value of the "association" attribute of this GeneAssociation.
323  */
324 const Association*
getAssociation() const325 GeneAssociation::getAssociation () const
326 {
327   return mAssociation;
328 }
329 
330 /*
331  * Returns the value of the "association" attribute of this GeneAssociation.
332  */
333 Association*
getAssociation()334 GeneAssociation::getAssociation ()
335 {
336   return mAssociation;
337 }
338 
339 /*
340   * Predicate returning @c true or @c false depending on whether this
341   * GeneAssociation's "association" attribute has been set.
342   */
343 bool
isSetAssociation() const344 GeneAssociation::isSetAssociation () const
345 {
346   return (mAssociation != NULL);
347 }
348 
349 
createAssociation()350 Association* GeneAssociation::createAssociation()
351 {
352   Association* result = NULL;
353   try
354   {
355     FBC_CREATE_NS_WITH_VERSION(fbcns, getSBMLNamespaces(), getPackageVersion());
356     result = new Association(fbcns);
357     unsetAssociation();
358     mAssociation = result;
359     mAssociation->connectToParent(this);
360     delete fbcns;
361   }
362   catch(...)
363   {
364     /*
365     * NULL will be returned if the mSBMLNS is invalid (basically this
366     * should not happen) or some exception is thrown (e.g. std::bad_alloc)
367     *
368     * (Maybe this should be changed so that caller can detect what kind
369     *  of error happened in this function.)
370     */
371   }
372 
373   return result;
374 }
375 
376 /*
377   * Sets the value of the "association" attribute of this GeneAssociation.
378   */
379 int
setAssociation(const Association * association)380   GeneAssociation::setAssociation (const Association* association)
381 {
382  if (mAssociation == association)
383   {
384     return LIBSBML_OPERATION_SUCCESS;
385   }
386   else if (association == NULL)
387   {
388     return unsetAssociation();
389   }
390   else if (getLevel() != association->getLevel())
391   {
392     return LIBSBML_LEVEL_MISMATCH;
393   }
394   else if (getVersion() != association->getVersion())
395   {
396     return LIBSBML_VERSION_MISMATCH;
397   }
398   else
399   {
400     if (mAssociation != NULL)
401       delete mAssociation;
402 
403     mAssociation = (association != NULL) ?
404       static_cast<Association*>( association->clone() ) : NULL;
405 
406     if (mAssociation != NULL)
407       mAssociation->connectToParent(this);
408 
409     return LIBSBML_OPERATION_SUCCESS;
410   }
411 }
412 
413 
414 /*
415   * Unsets the value of the "association" attribute of this GeneAssociation.
416   */
417 int
unsetAssociation()418 GeneAssociation::unsetAssociation ()
419 {
420   if (mAssociation != NULL)
421   delete mAssociation;
422   mAssociation=NULL;
423   return LIBSBML_OPERATION_SUCCESS;
424 }
425 
426 
427 /*
428  * Returns the XML element name of
429  * this SBML object.
430  */
431 const std::string&
getElementName() const432 GeneAssociation::getElementName () const
433 {
434   static const std::string name = "geneAssociation";
435   return name;
436 }
437 
438 
439 /** @cond doxygenLibsbmlInternal */
440 SBase*
createObject(XMLInputStream & stream)441 GeneAssociation::createObject (XMLInputStream& stream)
442 {
443   SBase* object = NULL;
444 
445   const string& name = stream.peek().getName();
446   if (name == "gene" || name == "or" || name == "and")
447   {
448     if (mAssociation != NULL)
449     {
450       logError(NotSchemaConformant, getLevel(), getVersion(),
451          "Only one <association> element is permitted "
452          "in a single <geneAssociation> element.");
453     }
454 
455       mAssociation = new Association(getLevel(), getVersion());
456       if (name == "gene")
457         mAssociation->setType(GENE_ASSOCIATION);
458       else if (name == "and")
459         mAssociation->setType(AND_ASSOCIATION);
460       else if (name == "or")
461         mAssociation->setType(OR_ASSOCIATION);
462       object = mAssociation;
463   }
464   return object;
465 }
466 /** @endcond */
467 
468 /** @cond doxygenLibsbmlInternal */
469 void
addExpectedAttributes(ExpectedAttributes & attributes)470 GeneAssociation::addExpectedAttributes(ExpectedAttributes& attributes)
471 {
472   SBase::addExpectedAttributes(attributes);
473 
474   attributes.add("id");
475   attributes.add("reaction");
476 }
477 /** @endcond */
478 
479 /** @cond doxygenLibsbmlInternal */
480 void
readAttributes(const XMLAttributes & attributes,const ExpectedAttributes & expectedAttributes)481 GeneAssociation::readAttributes (const XMLAttributes& attributes,
482                         const ExpectedAttributes& expectedAttributes)
483 {
484   SBase::readAttributes(attributes,expectedAttributes);
485 
486   const unsigned int sbmlLevel   = getLevel  ();
487   const unsigned int sbmlVersion = getVersion();
488 
489   bool assigned = attributes.readInto("id", mId, getErrorLog(), true, getLine(), getColumn());
490   if (assigned && mId.empty())
491   {
492     logEmptyString(mId, sbmlLevel, sbmlVersion, "<geneAssociation>");
493   }
494   if (!SyntaxChecker::isValidSBMLSId(mId))
495     logError(InvalidIdSyntax, sbmlLevel, sbmlVersion, "The id '" + mId + "' does not conform to the syntax.");
496 
497   assigned = attributes.readInto("reaction", mReaction, getErrorLog(), true, getLine(), getColumn());
498   if (assigned && mReaction.empty())
499   {
500     logEmptyString(mReaction, sbmlLevel, sbmlVersion, "<geneAssociation>");
501   }
502   if (!SyntaxChecker::isValidSBMLSId(mReaction))
503     logError(InvalidIdSyntax, getLevel(), getVersion(),
504     "The syntax of the attribute reaction='" + mReaction + "' does not conform.");
505 }
506 /** @endcond */
507 
508 /** @cond doxygenLibsbmlInternal */
509 void
writeAttributes(XMLOutputStream & stream) const510 GeneAssociation::writeAttributes (XMLOutputStream& stream) const
511 {
512   SBase::writeAttributes(stream);
513 
514   stream.writeAttribute("id",   getPrefix(), mId);
515   stream.writeAttribute("reaction",   getPrefix(), mReaction);
516 
517   //
518   // (EXTENSION)
519   //
520   SBase::writeExtensionAttributes(stream);
521 }
522 /** @endcond */
523 
524 /** @cond doxygenLibsbmlInternal */
525 void
writeElements(XMLOutputStream & stream) const526 GeneAssociation::writeElements (XMLOutputStream& stream) const
527 {
528   SBase::writeElements(stream);
529 
530   if (isSetAssociation())
531     mAssociation ->write(stream);
532 
533 
534   //
535   // (EXTENSION)
536   //
537   SBase::writeExtensionElements(stream);
538 }
539 /** @endcond */
540 
541 
542 /*
543  * @return the typecode (int) of this SBML object or SBML_UNKNOWN
544  * (default).
545  *
546  * @see getElementName()
547  */
548 int
getTypeCode() const549 GeneAssociation::getTypeCode () const
550 {
551   return SBML_FBC_GENEASSOCIATION;
552 }
553 
554 GeneAssociation*
clone() const555 GeneAssociation::clone() const
556 {
557     return new GeneAssociation(*this);
558 }
559 
560 
561 /** @cond doxygenLibsbmlInternal */
562 bool
accept(SBMLVisitor & v) const563 GeneAssociation::accept (SBMLVisitor& v) const
564 {
565   v.visit(*this);
566   v.leave(*this);
567 
568   return true;
569 }
570 /** @endcond */
571 
572 
573 /*
574  * Constructor.
575  */
ListOfGeneAssociations(FbcPkgNamespaces * fbcns)576 ListOfGeneAssociations::ListOfGeneAssociations(FbcPkgNamespaces* fbcns)
577  : ListOf(fbcns)
578 {
579   //
580   // set the element namespace of this object
581   //
582   setElementNamespace(fbcns->getURI());
583 }
584 
585 
586 /*
587  * Constructor.
588  */
ListOfGeneAssociations(unsigned int level,unsigned int version,unsigned int pkgVersion)589 ListOfGeneAssociations::ListOfGeneAssociations(unsigned int level, unsigned int version, unsigned int pkgVersion)
590  : ListOf(level,version)
591 {
592   setSBMLNamespacesAndOwn(new FbcPkgNamespaces(level,version,pkgVersion));
593 };
594 
595 
596 /*
597  * @return a (deep) copy of this ListOfGeneAssociations.
598  */
599 ListOfGeneAssociations*
clone() const600 ListOfGeneAssociations::clone () const
601 {
602   return new ListOfGeneAssociations(*this);
603 }
604 
605 
606 /* return nth item in list */
607 GeneAssociation *
get(unsigned int n)608 ListOfGeneAssociations::get(unsigned int n)
609 {
610   return static_cast<GeneAssociation*>(ListOf::get(n));
611 }
612 
613 
614 /* return nth item in list */
615 const GeneAssociation *
get(unsigned int n) const616 ListOfGeneAssociations::get(unsigned int n) const
617 {
618   return static_cast<const GeneAssociation*>(ListOf::get(n));
619 }
620 
621 
622 /* return item by symbol */
623 GeneAssociation*
get(const std::string & symbol)624 ListOfGeneAssociations::get (const std::string& symbol)
625 {
626   return const_cast<GeneAssociation*>(
627     static_cast<const ListOfGeneAssociations&>(*this).get(symbol) );
628 }
629 
630 
631 /* return item by symbol */
632 const GeneAssociation*
get(const std::string & symbol) const633 ListOfGeneAssociations::get (const std::string& symbol) const
634 {
635   vector<SBase*>::const_iterator result;
636 
637   result = find_if( mItems.begin(), mItems.end(), IdEq<GeneAssociation>(symbol) );
638   return (result == mItems.end()) ? 0 : static_cast <GeneAssociation*> (*result);
639 }
640 
641 
642 /* Removes the nth item from this list */
643 GeneAssociation*
remove(unsigned int n)644 ListOfGeneAssociations::remove (unsigned int n)
645 {
646    return static_cast<GeneAssociation*>(ListOf::remove(n));
647 }
648 
649 
650 /* Removes item in this list by symbol */
651 GeneAssociation*
remove(const std::string & symbol)652 ListOfGeneAssociations::remove (const std::string& symbol)
653 {
654   SBase* item = 0;
655   vector<SBase*>::iterator result;
656 
657   result = find_if( mItems.begin(), mItems.end(), IdEq<GeneAssociation>(symbol) );
658 
659   if (result != mItems.end())
660   {
661     item = *result;
662     mItems.erase(result);
663   }
664 
665   return static_cast <GeneAssociation*> (item);
666 }
667 
668 
669 /*
670  * @return the typecode (int) of SBML objects contained in this ListOf or
671  * SBML_UNKNOWN (default).
672  */
673 int
getItemTypeCode() const674 ListOfGeneAssociations::getItemTypeCode () const
675 {
676   return SBML_FBC_GENEASSOCIATION;
677 }
678 
679 
680 /*
681  * Returns the XML element name of
682  * this SBML object.
683  */
684 const std::string&
getElementName() const685 ListOfGeneAssociations::getElementName () const
686 {
687   static const std::string name = "listOfGeneAssociations";
688   return name;
689 }
690 
691 
692 /** @cond doxygenLibsbmlInternal */
693 SBase*
createObject(XMLInputStream & stream)694 ListOfGeneAssociations::createObject (XMLInputStream& stream)
695 {
696   const std::string& name   = stream.peek().getName();
697   SBase*        object = 0;
698 
699 
700   if (name == "geneAssociation")
701   {
702     try
703     {
704       FBC_CREATE_NS_WITH_VERSION(fbcns, getSBMLNamespaces(), getPackageVersion());
705       object = new GeneAssociation(fbcns);
706       appendAndOwn(object);
707       delete fbcns;
708       //mItems.push_back(object);
709     }
710     catch(...)
711     {
712       /*
713       * NULL will be returned if the mSBMLNS is invalid (basically this
714       * should not happen) or some exception is thrown (e.g. std::bad_alloc)
715       *
716       * (Maybe this should be changed so that caller can detect what kind
717       *  of error happened in this function.)
718       */
719     }
720   }
721 
722   return object;
723 }
724 /** @endcond */
725 
726 
727 #endif /* __cplusplus */
728 LIBSBML_CPP_NAMESPACE_END
729 
730