1 /**
2  * @file    UnitDefinition.cpp
3  * @brief   Implementations of SBML's UnitDefinition and ListOfUnitDefinitions.
4  * @author  Ben Bornstein
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  * Copyright (C) 2006-2008 by the California Institute of Technology,
29  *     Pasadena, CA, USA
30  *
31  * Copyright (C) 2002-2005 jointly by the following organizations:
32  *     1. California Institute of Technology, Pasadena, CA, USA
33  *     2. Japan Science and Technology Agency, Japan
34  *
35  * This library is free software; you can redistribute it and/or modify it
36  * under the terms of the GNU Lesser General Public License as published by
37  * the Free Software Foundation.  A copy of the license agreement is provided
38  * in the file named "LICENSE.txt" included with this software distribution
39  * and also available online as http://sbml.org/software/libsbml/license.html
40  * ---------------------------------------------------------------------- -->*/
41 
42 #include <sstream>
43 
44 
45 #include <sbml/xml/XMLNode.h>
46 #include <sbml/xml/XMLAttributes.h>
47 #include <sbml/xml/XMLInputStream.h>
48 #include <sbml/xml/XMLOutputStream.h>
49 
50 #include <sbml/units/UnitKindList.h>
51 
52 #include <sbml/SBO.h>
53 #include <sbml/SBMLVisitor.h>
54 #include <sbml/SBMLError.h>
55 #include <sbml/SBMLDocument.h>
56 #include <sbml/Unit.h>
57 #include <sbml/UnitDefinition.h>
58 #include <sbml/extension/SBaseExtensionPoint.h>
59 
60 #include <sbml/util/ElementFilter.h>
61 
62 #include <math.h>
63 
64 /** @cond doxygenIgnored */
65 using namespace std;
66 /** @endcond */
67 
68 LIBSBML_CPP_NAMESPACE_BEGIN
69 #ifdef __cplusplus
70 
UnitDefinition(unsigned int level,unsigned int version)71 UnitDefinition::UnitDefinition (unsigned int level, unsigned int version) :
72    SBase  ( level, version )
73  , mUnits (level, version)
74 {
75   if (!hasValidLevelVersionNamespaceCombination())
76     throw SBMLConstructorException();
77 
78   connectToChild();
79 }
80 
81 
UnitDefinition(SBMLNamespaces * sbmlns)82 UnitDefinition::UnitDefinition (SBMLNamespaces * sbmlns) :
83    SBase  ( sbmlns )
84  , mUnits (sbmlns)
85 {
86   if (!hasValidLevelVersionNamespaceCombination())
87   {
88     throw SBMLConstructorException(getElementName(), sbmlns);
89   }
90 
91   connectToChild();
92   loadPlugins(sbmlns);
93 }
94 
95 
96 /*
97  * Destroys this UnitDefinition.
98  */
~UnitDefinition()99 UnitDefinition::~UnitDefinition ()
100 {
101 }
102 
103 
104 /*
105  * Copy constructor. Creates a copy of this UnitDefinition.
106  */
UnitDefinition(const UnitDefinition & orig)107 UnitDefinition::UnitDefinition(const UnitDefinition& orig) :
108     SBase     ( orig )
109   , mUnits    ( orig.mUnits )
110 {
111   connectToChild();
112 }
113 
114 
115 /*
116  * Assignment operator.
117  */
operator =(const UnitDefinition & rhs)118 UnitDefinition& UnitDefinition::operator=(const UnitDefinition& rhs)
119 {
120   if(&rhs!=this)
121   {
122     this->SBase::operator =(rhs);
123     mUnits = rhs.mUnits;
124   }
125 
126   connectToChild();
127 
128   return *this;
129 }
130 
131 
132 /** @cond doxygenLibsbmlInternal */
133 bool
accept(SBMLVisitor & v) const134 UnitDefinition::accept (SBMLVisitor& v) const
135 {
136   bool result = v.visit(*this);
137   mUnits.accept(v);
138 
139   return result;
140 }
141 /** @endcond */
142 \
143 
144 /*
145  * @return a (deep) copy of this UnitDefinition.
146  */
147 UnitDefinition*
clone() const148 UnitDefinition::clone () const
149 {
150   return new UnitDefinition(*this);
151 }
152 
153 
154 SBase*
getElementBySId(const std::string & id)155 UnitDefinition::getElementBySId(const std::string& id)
156 {
157   if (id.empty()) return NULL;
158   SBase* obj = mUnits.getElementBySId(id);
159   if (obj != NULL) return obj;
160 
161   return getElementFromPluginsBySId(id);
162 }
163 
164 
165 SBase*
getElementByMetaId(const std::string & metaid)166 UnitDefinition::getElementByMetaId(const std::string& metaid)
167 {
168   if (metaid.empty()) return NULL;
169   if (mUnits.getMetaId() == metaid) return &mUnits;
170   SBase* obj = mUnits.getElementByMetaId(metaid);
171   if (obj != NULL) return obj;
172 
173   return getElementFromPluginsByMetaId(metaid);
174 }
175 
176 
177 List*
getAllElements(ElementFilter * filter)178 UnitDefinition::getAllElements(ElementFilter *filter)
179 {
180   List* ret = new List();
181   List* sublist = NULL;
182 
183   ADD_FILTERED_LIST(ret, sublist, mUnits, filter);
184 
185   ADD_FILTERED_FROM_PLUGIN(ret, sublist, filter);
186 
187   return ret;
188 }
189 
190 /*
191  * @return the id of this SBML object.
192  */
193 const string&
getId() const194 UnitDefinition::getId () const
195 {
196   return mId;
197 }
198 
199 
200 /*
201  * @return the name of this SBML object.
202  */
203 const string&
getName() const204 UnitDefinition::getName () const
205 {
206   return (getLevel() == 1) ? mId : mName;
207 }
208 
209 
210 /*
211  * @return @c true if the id of this SBML object is set, false
212  * otherwise.
213  */
214 bool
isSetId() const215 UnitDefinition::isSetId () const
216 {
217   return (mId.empty() == false);
218 }
219 
220 
221 /*
222  * @return @c true if the name of this SBML object is set, false
223  * otherwise.
224  */
225 bool
isSetName() const226 UnitDefinition::isSetName () const
227 {
228   return (getLevel() == 1) ? (mId.empty() == false) :
229                             (mName.empty() == false);
230 }
231 
232 
233 /*
234  * Sets the id of this SBML object to a copy of @p sid.
235  */
236 int
setId(const std::string & sid)237 UnitDefinition::setId (const std::string& sid)
238 {
239   /* since the setId function has been used as an
240    * alias for setName we can't require it to only
241    * be used on a L2 model
242    */
243 /*  if (getLevel() == 1)
244   {
245     return LIBSBML_UNEXPECTED_ATTRIBUTE;
246   }
247 */
248   if (!(SyntaxChecker::isValidInternalSId(sid)))
249   {
250     return LIBSBML_INVALID_ATTRIBUTE_VALUE;
251   }
252   else
253   {
254     mId = sid;
255     return LIBSBML_OPERATION_SUCCESS;
256   }
257 }
258 
259 
260 /*
261  * Sets the name of this SBML object to a copy of name.
262  */
263 int
setName(const std::string & name)264 UnitDefinition::setName (const std::string& name)
265 {
266   /* if this is setting an L2 name the type is string
267    * whereas if it is setting an L1 name its type is SId
268    */
269   if (getLevel() == 1)
270   {
271     if (!(SyntaxChecker::isValidInternalSId(name)))
272     {
273       return LIBSBML_INVALID_ATTRIBUTE_VALUE;
274     }
275     else
276     {
277       mId = name;
278       return LIBSBML_OPERATION_SUCCESS;
279     }
280   }
281   else
282   {
283     mName = name;
284     return LIBSBML_OPERATION_SUCCESS;
285   }
286 }
287 
288 
289 /*
290  * Unsets the name of this SBML object.
291  */
292 int
unsetName()293 UnitDefinition::unsetName ()
294 {
295   if (getLevel() == 1)
296   {
297     mId.erase();
298   }
299   else
300   {
301     mName.erase();
302   }
303 
304   if (getLevel() == 1 && mId.empty())
305   {
306     return LIBSBML_OPERATION_SUCCESS;
307   }
308   else if (mName.empty())
309   {
310     return LIBSBML_OPERATION_SUCCESS;
311   }
312   else
313   {
314     return LIBSBML_OPERATION_FAILED;
315   }
316 }
317 
318 
319 /*
320  * @return @c true if this UnitDefinition is a variant of the built-in type
321  * area. i.e. square metres with only arbitrary variations in scale,
322  * or multiplier values, false otherwise.
323  */
324 bool
isVariantOfArea(bool relaxed) const325 UnitDefinition::isVariantOfArea (bool relaxed) const
326 {
327   bool result = false;
328 
329   UnitDefinition *ud = static_cast<UnitDefinition*>(this->clone());
330   UnitDefinition::simplify(ud);
331 
332   if (!relaxed)
333   {
334     // should be metre^2
335     if (ud->getNumUnits() == 1)
336     {
337       const Unit* u = ud->getUnit(0);
338       result        = u->isMetre() && u->getExponent() == 2;
339     }
340   }
341   else
342   {
343     // should be metre
344     if (ud->getNumUnits() == 1)
345     {
346       const Unit* u = ud->getUnit(0);
347       result        = u->isMetre();
348     }
349   }
350 
351   delete ud;
352   return result;
353 }
354 
355 
356 /*
357  * @return @c true if this UnitDefinition is a variant of the built-in type
358  * length. i.e. metres with only arbitrary variations in scale,
359  * or multiplier values, false otherwise.
360  */
361 bool
isVariantOfLength(bool relaxed) const362 UnitDefinition::isVariantOfLength (bool relaxed) const
363 {
364   bool result = false;
365 
366   UnitDefinition *ud = static_cast<UnitDefinition*>(this->clone());
367   UnitDefinition::simplify(ud);
368 
369   if (!relaxed)
370   {
371     //should be metre^1
372     if (ud->getNumUnits() == 1)
373     {
374       const Unit* u = ud->getUnit(0);
375       result        = u->isMetre() && u->getExponent() == 1;
376     }
377   }
378   else
379   {
380     //should be metre
381     if (ud->getNumUnits() == 1)
382     {
383       const Unit* u = ud->getUnit(0);
384       result        = u->isMetre();
385     }
386   }
387 
388   delete ud;
389   return result;
390 }
391 
392 
393 /*
394  * @return @c true if this UnitDefinition is a variant of the built-in type
395  * substance. i.e. moles or items with only arbitrary variations in
396  * scale or multiplier values, false otherwise.
397  */
398 bool
isVariantOfSubstance(bool relaxed) const399 UnitDefinition::isVariantOfSubstance (bool relaxed) const
400 {
401   bool result = false;
402 
403   unsigned int level = getLevel();
404   unsigned int version = getVersion();
405 
406   UnitDefinition *ud = static_cast<UnitDefinition*>(this->clone());
407   UnitDefinition::simplify(ud);
408 
409   if (!relaxed)
410   {
411     // should be L1/L2V1: mole^1/item^1
412     //                L2: mole/item/gram/kilogram ^1
413     //                L3: mole/item/gram/kilogram/avogardo ^1
414     if (ud->getNumUnits() == 1)
415     {
416       const Unit* u = ud->getUnit(0);
417       if (level == 2 && version > 1)
418       {
419         result = ((  u->isMole() || u->isItem()
420                   || u->isGram() || u->isKilogram())
421                   && u->getExponent() == 1);
422       }
423       else if (level > 2)
424       {
425         result = ((  u->isMole() || u->isItem()
426                   || u->isGram() || u->isKilogram()
427                   || u->isAvogadro())
428                   && u->getExponent() == 1);
429       }
430       else
431       {
432         result        = (u->isMole() || u->isItem())
433                       && u->getExponent() == 1;
434       }
435     }
436   }
437   else
438   {
439     // should be any combination of mole/item/gram/kilogram/avogardo ^1
440     unsigned int i = 0;
441     result = true;
442     while (result && i < ud->getNumUnits())
443     {
444       const Unit* u = ud->getUnit(i);
445       result = ((  u->isMole() || u->isItem()
446                 || u->isGram() || u->isKilogram()
447                 || u->isAvogadro()));
448 
449       i++;
450     }
451   }
452 
453   delete ud;
454   return result;
455 }
456 
457 
458 /*
459  * @return @c true if this UnitDefinition is a variant of the built-in type
460  * time. i.e. seconds with only arbitrary variations in scale,
461  * or multiplier values, false otherwise.
462  */
463 bool
isVariantOfTime(bool relaxed) const464 UnitDefinition::isVariantOfTime (bool relaxed) const
465 {
466   bool result = false;
467 
468   UnitDefinition *ud = static_cast<UnitDefinition*>(this->clone());
469   UnitDefinition::simplify(ud);
470 
471   if (!relaxed)
472   {
473     // unit should simplify to second with exponent 1
474     if (ud->getNumUnits() == 1)
475     {
476       const Unit* u = ud->getUnit(0);
477       result        = u->isSecond() && u->getExponent() == 1;
478     }
479   }
480   else
481   {
482     // from l3v1r2 unit should simplify to second with any exponent
483     if (ud->getNumUnits() == 1)
484     {
485       const Unit* u = ud->getUnit(0);
486       result        = u->isSecond();
487     }
488   }
489 
490   delete ud;
491   return result;
492 }
493 
494 
495 /*
496  * @return @c true if this UnitDefinition is a variant of the built-in type
497  * volume. i.e. litre or cubic metre with only arbitrary variations in
498  * scale or multiplier values, false otherwise.
499  */
500 bool
isVariantOfVolume(bool relaxed) const501 UnitDefinition::isVariantOfVolume (bool relaxed) const
502 {
503   bool result = false;
504 
505   UnitDefinition *ud = static_cast<UnitDefinition*>(this->clone());
506   UnitDefinition::simplify(ud);
507 
508   if (!relaxed)
509   {
510     // should be litre^1 or metre^3
511     if (ud->getNumUnits() == 1)
512     {
513       const Unit* u = ud->getUnit(0);
514       result        = (u->isLitre() && u->getExponent() == 1) ||
515                       (u->isMetre() && u->getExponent() == 3);
516     }
517   }
518   else
519   {
520     // should be any combination of litre/metre
521     unsigned int i = 0;
522     result = true;
523     while (result && i < ud->getNumUnits())
524     {
525       const Unit* u = ud->getUnit(i);
526       result = (  u->isLitre() || u->isMetre());
527 
528       i++;
529     }
530   }
531 
532   delete ud;
533   return result;
534 }
535 
536 
537 /*
538  * @return @c true if this UnitDefinition is a variant of dimensionless.
539  * i.e. dimensionless with only arbitrary variations in scale,
540  * or multiplier values, false otherwise.
541  */
542 bool
isVariantOfDimensionless(bool relaxed) const543 UnitDefinition::isVariantOfDimensionless (bool relaxed) const
544 {
545   bool result = false;
546 
547   // careful here if we have no units simplify will add dimensionless
548   if (getNumUnits() == 0)
549   {
550     return result;
551   }
552 
553   UnitDefinition *ud = static_cast<UnitDefinition*>(this->clone());
554   UnitDefinition::simplify(ud);
555 
556   if (!relaxed)
557   {
558     if (ud->getNumUnits() == 1)
559     {
560       const Unit* u = ud->getUnit(0);
561       result        = u->isDimensionless();
562     }
563   }
564   else
565   {
566     if (ud->getNumUnits() == 1)
567     {
568       const Unit* u = ud->getUnit(0);
569       result        = u->isDimensionless();
570     }
571   }
572 
573   delete ud;
574   return result;
575 }
576 
577 
578 /*
579  * @return @c true if this UnitDefinition is a variant of mass. ie gram or
580  * kilogram with only arbitrary variations in scale or multiplier
581  * values, false otherwise.
582  */
583 bool
isVariantOfMass(bool relaxed) const584 UnitDefinition::isVariantOfMass (bool relaxed) const
585 {
586   bool result = false;
587 
588   UnitDefinition *ud = static_cast<UnitDefinition*>(this->clone());
589   UnitDefinition::simplify(ud);
590 
591   if (!relaxed)
592   {
593     // should be gram/kilogram ^ 1
594     if (ud->getNumUnits() == 1)
595     {
596       const Unit* u = ud->getUnit(0);
597       result        = ((u->isGram() || u->isKilogram())
598                   && u->getExponent() == 1);
599     }
600   }
601   else
602   {
603     // should be any combination of kilogram/gram
604     unsigned int i = 0;
605     result = true;
606     while (result && i < ud->getNumUnits())
607     {
608       const Unit* u = ud->getUnit(i);
609       result = (  u->isGram() || u->isKilogram());
610 
611       i++;
612     }
613   }
614 
615   delete ud;
616   return result;
617 }
618 
619 
620 /*
621  * @return @c true if this UnitDefinition is a variant of the built-in type
622  * substance per time, false otherwise.
623  */
624 bool
isVariantOfSubstancePerTime(bool relaxed) const625 UnitDefinition::isVariantOfSubstancePerTime (bool relaxed) const
626 {
627   bool result = false;
628 
629   // this unitDefinition times second^1 should be a variant
630   // of substance
631   UnitDefinition *ud = static_cast<UnitDefinition*>(this->clone());
632   //Unit *u = new Unit(UNIT_KIND_SECOND);
633   Unit *u = new Unit(ud->getSBMLNamespaces());
634   u->setKind(UNIT_KIND_SECOND);
635   u->initDefaults();
636   ud->addUnit(u);
637 
638   UnitDefinition::simplify(ud);
639 
640   result = ud->isVariantOfSubstance(relaxed);
641 
642   delete ud;
643   delete u;
644   return result;
645 }
646 
647 
648 /*
649  * Adds a copy of the given Unit to this UnitDefinition.
650  */
651 int
addUnit(const Unit * u)652 UnitDefinition::addUnit (const Unit* u)
653 {
654   int returnValue = checkCompatibility(static_cast<const SBase *>(u));
655   if (returnValue != LIBSBML_OPERATION_SUCCESS)
656   {
657     return returnValue;
658   }
659   else if (u == NULL)
660   {
661     return LIBSBML_OPERATION_FAILED;
662   }
663   else if (u->hasRequiredAttributes() == false)
664   {
665     return LIBSBML_INVALID_OBJECT;
666   }
667   else if (getLevel() != u->getLevel())
668   {
669     return LIBSBML_LEVEL_MISMATCH;
670   }
671   else if (getVersion() != u->getVersion())
672   {
673     return LIBSBML_VERSION_MISMATCH;
674   }
675   else if (matchesRequiredSBMLNamespacesForAddition(static_cast<const
676     SBase*>(u)) == false)
677   {
678     return LIBSBML_NAMESPACES_MISMATCH;
679   }
680   else
681   {
682     return mUnits.append(u);
683   }
684 }
685 
686 
687 /*
688  * Creates a new Unit, adds it to this UnitDefinition's list of units and
689  * returns it.
690  */
691 Unit*
createUnit()692 UnitDefinition::createUnit ()
693 {
694   Unit* u = NULL;
695 
696   try
697   {
698     u = new Unit(getSBMLNamespaces());
699   }
700   catch (...)
701   {
702     /* here we do not create a default object as the level/version must
703      * match the parent object
704      *
705      * so do nothing
706      */
707     return NULL;
708   }
709 
710   if (u != NULL) mUnits.appendAndOwn(u);
711 
712   return u;
713 }
714 
715 
716 /*
717  * @return the list of Units for this UnitDefinition.
718  */
719 const ListOfUnits*
getListOfUnits() const720 UnitDefinition::getListOfUnits () const
721 {
722   return &mUnits;
723 }
724 
725 
726 /*
727  * @return the list of Units for this UnitDefinition.
728  */
729 ListOfUnits*
getListOfUnits()730 UnitDefinition::getListOfUnits ()
731 {
732   return &mUnits;
733 }
734 
735 
736 /*
737  * @return the nth Unit of this UnitDefinition
738  */
739 const Unit*
getUnit(unsigned int n) const740 UnitDefinition::getUnit (unsigned int n) const
741 {
742   return static_cast<const Unit*>( mUnits.get(n) );
743 }
744 
745 
746 /*
747  * @return the nth Unit of this UnitDefinition
748  */
749 Unit*
getUnit(unsigned int n)750 UnitDefinition::getUnit (unsigned int n)
751 {
752   return static_cast<Unit*>( mUnits.get(n) );
753 }
754 
755 
756 /*
757  * @return the number of Units in this UnitDefinition.
758  */
759 unsigned int
getNumUnits() const760 UnitDefinition::getNumUnits () const
761 {
762   return mUnits.size();
763 }
764 
765 
766 /**
767  * Removes the nth Unit object from this UnitDefinition object and
768  * returns a pointer to it.
769  */
770 Unit*
removeUnit(unsigned int n)771 UnitDefinition::removeUnit (unsigned int n)
772 {
773   return mUnits.remove(n);
774 }
775 
776 
777 /** @cond doxygenLibsbmlInternal */
778 /*
779  * Sets the parent SBMLDocument of this SBML object.
780  */
781 void
setSBMLDocument(SBMLDocument * d)782 UnitDefinition::setSBMLDocument (SBMLDocument* d)
783 {
784   SBase::setSBMLDocument(d);
785   mUnits.setSBMLDocument(d);
786 }
787 
788 
789 /*
790  * Sets this SBML object to child SBML objects (if any).
791  * (Creates a child-parent relationship by the parent)
792   */
793 void
connectToChild()794 UnitDefinition::connectToChild()
795 {
796   SBase::connectToChild();
797   mUnits.connectToParent(this);
798 }
799 
800 /**
801  * Enables/Disables the given package with this element and child
802  * elements (if any).
803  * (This is an internal implementation for enablePackage function)
804  */
805 void
enablePackageInternal(const std::string & pkgURI,const std::string & pkgPrefix,bool flag)806 UnitDefinition::enablePackageInternal(const std::string& pkgURI,
807                                       const std::string& pkgPrefix, bool flag)
808 {
809   SBase::enablePackageInternal(pkgURI,pkgPrefix,flag);
810 
811   mUnits.enablePackageInternal(pkgURI,pkgPrefix,flag);
812 }
813 
814 
815 void
updateSBMLNamespace(const std::string & pkg,unsigned int level,unsigned int version)816 UnitDefinition::updateSBMLNamespace(const std::string& pkg, unsigned int level,
817   unsigned int version)
818 {
819   SBase::updateSBMLNamespace(pkg, level, version);
820 
821   mUnits.updateSBMLNamespace(pkg, level, version);
822 }
823 /** @endcond */
824 
825 
826 /*
827  * @return the typecode (int) of this SBML object or SBML_UNKNOWN
828  * (default).
829  *
830  * @see getElementName()
831  */
832 int
getTypeCode() const833 UnitDefinition::getTypeCode () const
834 {
835   return SBML_UNIT_DEFINITION;
836 }
837 
838 
839 /*
840  * @return the name of this element ie "unitDefinition".
841  */
842 const string&
getElementName() const843 UnitDefinition::getElementName () const
844 {
845   static const string name = "unitDefinition";
846   return name;
847 
848 }
849 
850 bool
hasRequiredAttributes() const851 UnitDefinition::hasRequiredAttributes() const
852 {
853   bool allPresent = true;
854 
855   /* required attributes for unitDefinition: id (name in L1) */
856 
857   if (!isSetId())
858     allPresent = false;
859 
860   return allPresent;
861 }
862 
863 
864 bool
hasRequiredElements() const865 UnitDefinition::hasRequiredElements() const
866 {
867   bool allPresent = true;
868 
869   /* required attributes for unitDefinition: listOfUnits (L2 only) */
870 
871   if (getLevel() > 1 && getNumUnits() == 0)
872     allPresent = false;
873 
874   return allPresent;
875 }
876 
877 
878 /* utility functions originally in Utils_UnitDefinition
879  * declared as static
880  */
881 
882 void
simplify(UnitDefinition * ud)883 UnitDefinition::simplify(UnitDefinition * ud)
884 {
885   if (ud == NULL) return;
886 
887   unsigned int n, i;
888   ListOfUnits *  units = ud->getListOfUnits();
889   Unit * unit;
890   const char * unitKind;
891   int cancelFlag = 0;
892   bool dimensionlessPresent = false;
893 
894 
895   for (n = 0; n < ud->getNumUnits(); n++)
896   {
897     Unit* unit = ud->getUnit(n);
898     if (unit->getKind() == UNIT_KIND_DIMENSIONLESS)
899     {
900       dimensionlessPresent = true;
901     }
902   }
903 
904   double dimMultfactor = 1.0;
905   double dimMultfactorSaved = 1.0;
906 
907 
908   /* if only one unit cannot be simplified any further */
909   if (units->size() > 1)
910   {
911     if (dimensionlessPresent)
912     {
913       /* if contains a dimensionless unit and any others then
914         dimensionless is unecessary
915         unless it has a multiplier attached
916         */
917       unsigned int origNumUnits = units->size();
918       for (n = origNumUnits; n > 0; n--)
919       {
920         unit = (Unit *) units->get(n-1);
921         Unit::removeScale(unit);
922 
923         if (!strcmp(UnitKind_toString(unit->getKind()), "dimensionless"))
924         {
925           dimMultfactor = pow(unit->getMultiplier(), unit->getExponent());
926           if (util_isEqual(dimMultfactor, 1.0) == false)
927           {
928             cancelFlag = 1;
929             dimMultfactorSaved = dimMultfactorSaved * dimMultfactor;
930           }
931           delete units->remove(n-1);
932         }
933       }
934     }
935 
936     /* if it contains two units with same kind these must be combined */
937     for (n = 0; n < units->size(); n++)
938     {
939       unit = (Unit *)units->get(n);
940       unitKind = UnitKind_toString(unit->getKind());
941 
942       /* find other occurences and merge */
943       for (i = n+1; i < units->size();)
944       {
945         if (!strcmp(UnitKind_toString(((Unit *)units->get(i))->getKind()),
946           unitKind))
947         {
948           Unit::merge(unit, (Unit *)units->get(i));
949           delete units->remove(i);
950         }
951         else
952         {
953           i++;
954         }
955       }
956     }
957   }
958 
959   /* may have cancelled units - in which case exponent will be 0 */
960   // might need to propagate a multiplier though
961   double newMultiplier = dimMultfactorSaved;
962   unsigned int numUnits = units->size();
963   for (n = numUnits; n > 0; n--)
964   {
965     unit = (Unit *) units->get(n-1);
966     if (unit->isUnitChecking())
967     {
968       if (unit->getExponentUnitChecking() == 0)
969       {
970         newMultiplier = newMultiplier * unit->getMultiplier();
971         delete units->remove(n-1);
972         cancelFlag = 1;
973       }
974     }
975     else if (unit->getExponent() == 0)
976     {
977       newMultiplier = newMultiplier * unit->getMultiplier();
978       delete units->remove(n-1);
979       cancelFlag = 1;
980     }
981   }
982 
983   /* if all units have been cancelled need to add dimensionless */
984   /* or indeed if one or more have been cancelled need to
985    * propagate any remaining multiplier */
986   if (cancelFlag == 1 || (dimensionlessPresent && units->size() == 0))
987   {
988     if (units->size() == 0)
989     {
990       Unit tmpunit(ud->getSBMLNamespaces());
991       tmpunit.setKind(UNIT_KIND_DIMENSIONLESS);
992       tmpunit.initDefaults();
993       tmpunit.setMultiplier(newMultiplier);
994       ud->addUnit(&tmpunit);
995     }
996     else if (util_isEqual(newMultiplier, 1.0) == false)
997     {
998       unit = units->get(0);
999       unit->setMultiplier(unit->getMultiplier() *
1000         pow(newMultiplier, 1.0/unit->getExponentAsDouble()));
1001     }
1002   }
1003 
1004 }
1005 
1006 /** @cond doxygenLibsbmlInternal */
compareKinds(const void * u1,const void * u2)1007 int compareKinds(const void * u1, const void * u2)
1008 {
1009   return (*(int*)u1 - *(int*)u2);
1010 }
1011 /** @endcond */
1012 
1013 /*
1014  * Orders the listOfUnits within the UnitDefinition alphabetically.
1015  *
1016  * @param ud the UnitDefinition object to be ordered.
1017  */
1018 void
reorder(UnitDefinition * ud)1019 UnitDefinition::reorder(UnitDefinition *ud)
1020 {
1021   if (ud == NULL) return;
1022 
1023   unsigned int n, p;
1024   ListOfUnits * units = ud->getListOfUnits();
1025   Unit * unit;
1026   unsigned int numUnits = units->size();
1027 
1028   int *indexArray = NULL;
1029   indexArray = new int[units->size()];
1030 
1031   int *initialIndexArray = NULL;
1032   initialIndexArray = new int[units->size()];
1033 
1034   std::vector<unsigned int> used;
1035 
1036   for (n = 0; n < numUnits; n++)
1037   {
1038     unit = (Unit *)(units->get(n));
1039     int value = (int)(unit->getKind());
1040     indexArray[n] = value;
1041     initialIndexArray[n] = value;
1042   }
1043 
1044   qsort(indexArray, numUnits, sizeof(int), compareKinds);
1045 
1046   /* append units in correct order */
1047   for (n = 0; n < numUnits; n++)
1048   {
1049     for (p = 0; p < numUnits; p++)
1050     {
1051       if (indexArray[n] == initialIndexArray[p])
1052       {
1053         if (used.end() == std::find(used.begin(), used.end(), p))
1054         {
1055           unit = (Unit *) units->get(p);
1056           units->append(unit);
1057           used.push_back(p);
1058           break;
1059         }
1060       }
1061     }
1062   }
1063 
1064   /* remove originals */
1065   for (n = 0; n < numUnits; n++)
1066   {
1067     delete units->remove(0);
1068   }
1069 
1070   delete [] indexArray;
1071   delete [] initialIndexArray;
1072 }
1073 
1074 
1075 /*
1076  * Returns a UnitDefinition object which is the argument UnitDefinition
1077  * converted to the SI units.
1078  *
1079  * @param ud the UnitDefinition object to convert to SI.
1080  *
1081  * @return a UnitDefinition object converted to SI units.
1082  */
1083 UnitDefinition *
convertToSI(const UnitDefinition * ud)1084 UnitDefinition::convertToSI(const UnitDefinition * ud)
1085 {
1086   if (ud == NULL) return NULL;
1087 
1088   unsigned int n, p;
1089   UnitDefinition * newUd = new UnitDefinition(ud->getSBMLNamespaces());
1090   UnitDefinition * tempUd;
1091   Unit * tempUnit;
1092 
1093   newUd->setId(ud->getId());
1094   newUd->setName(ud->getName());
1095 
1096   for (n = 0; n < ud->getNumUnits(); n++)
1097   {
1098     tempUd = Unit::convertToSI(ud->getUnit(n));
1099     for (p = 0; p < tempUd->getNumUnits(); p++)
1100     {
1101       tempUnit = new Unit(ud->getSBMLNamespaces());
1102       tempUnit->setKind(tempUd->getUnit(p)->getKind());
1103       if (tempUd->getUnit(p)->isUnitChecking())
1104       {
1105         tempUnit->setExponentUnitChecking(tempUd->getUnit(p)->getExponentUnitChecking());
1106       }
1107       else
1108       {
1109         tempUnit->setExponent(tempUd->getUnit(p)->getExponent());
1110       }
1111       tempUnit->setScale(tempUd->getUnit(p)->getScale());
1112       tempUnit->setMultiplier(tempUd->getUnit(p)->getMultiplier());
1113       newUd->addUnit(tempUnit);
1114       delete tempUnit;
1115     }
1116     delete tempUd;
1117   }
1118 
1119   UnitDefinition::simplify(newUd);
1120   return newUd;
1121 }
1122 
1123 
1124 double
extractMultiplier(UnitDefinition * ud)1125 extractMultiplier(UnitDefinition * ud)
1126 {
1127   double multiplier = 1.0;
1128 
1129   unsigned int i = 0;
1130   while(i < ud->getNumUnits())
1131   {
1132     Unit::removeScale(ud->getUnit(i));
1133     multiplier = multiplier * pow(ud->getUnit(i)->getMultiplier(),
1134                                   ud->getUnit(i)->getExponentAsDouble());
1135     ud->getUnit(i)->setMultiplier(1.0);
1136     ud->getUnit(i)->setScale(0);
1137     i++;
1138   }
1139   return multiplier;
1140 }
1141 
1142 
1143 ///* slightly less restrictive version that util_isEqual
1144 // * I had issues with this when one of the multipliers
1145 // * had not been calculated and was just 1.0
1146 // */
1147 //bool
1148 //isEqual(double a, double b)
1149 //{
1150 //  double tol;
1151 //  if (a < b)
1152 //    tol = a * 1e-10;
1153 //  else
1154 //    tol = b * 1e-10;
1155 //  return (fabs(a-b) < sqrt(tol)) ? true : false;
1156 //}
1157 
1158 
1159 /*
1160  * Predicate returning @c true if
1161  * UnitDefinition objects are identical (all units are identical).
1162  *
1163  * @param ud1 the first UnitDefinition object to compare.
1164  * @param ud2 the second UnitDefinition object to compare.
1165  *
1166  * @return @c true if all the units of ud1 are identical
1167  * to the units of ud2, @c false otherwise.
1168  *
1169  * @note For the purposes of comparison two units can be "identical",
1170  * i.e. all attributes are an exact match, or "equivalent" i.e.
1171  * matching kind and exponent.
1172  *
1173  * @see areEquivalent();
1174  */
1175 bool
areIdentical(const UnitDefinition * ud1,const UnitDefinition * ud2)1176 UnitDefinition::areIdentical(const UnitDefinition * ud1,
1177                              const UnitDefinition * ud2)
1178 {
1179   bool identical = false;
1180 
1181   bool A = (ud1 == NULL);
1182   bool B = (ud2 == NULL);
1183 
1184   /* if one or other is NULL no need to check
1185    */
1186   if ((A || B) && !(A && B))
1187   {
1188     return identical;
1189   }
1190 
1191   /* if both NULL no need to check */
1192   if (A && B)
1193   {
1194     identical = true;
1195     return identical;
1196   }
1197 
1198   /* must be same level/version/ namespace
1199    */
1200   if ( (ud1->getLevel() != ud2->getLevel()) ||
1201        (ud1->getVersion() != ud2->getVersion()))
1202   {
1203     return identical;
1204   }
1205   unsigned int n;
1206 
1207   /* need to order the unitDefinitions so must make copies
1208    * since the arguments are const
1209    */
1210   UnitDefinition * ud1Temp = new UnitDefinition(ud1->getSBMLNamespaces());
1211   UnitDefinition * ud2Temp = new UnitDefinition(ud2->getSBMLNamespaces());
1212 
1213   for ( n = 0; n < ud1->getNumUnits(); n++)
1214     ud1Temp->addUnit(ud1->getUnit(n));
1215   for ( n = 0; n < ud2->getNumUnits(); n++)
1216     ud2Temp->addUnit(ud2->getUnit(n));
1217 
1218   UnitDefinition::simplify(ud1Temp);
1219   UnitDefinition::simplify(ud2Temp);
1220 
1221   if (ud1Temp->getNumUnits() == ud2Temp->getNumUnits())
1222   {
1223     UnitDefinition::reorder(ud1Temp);
1224     UnitDefinition::reorder(ud2Temp);
1225 
1226     if (ud1Temp->getNumUnits() > 1)
1227     {
1228       // different multipliers left on different units may not match
1229       // but overall they
1230       // e.g (2m)(sec) is tha same unit as (m)(2sec) but unit by unit
1231       // comparison will fail
1232       double multiplier1 = extractMultiplier(ud1Temp);
1233       double multiplier2 = extractMultiplier(ud2Temp);
1234 
1235       if (util_isEqual(multiplier1, multiplier2) == false)
1236       {
1237         return identical;
1238       }
1239     }
1240 
1241     n = 0;
1242     while (n < ud1Temp->getNumUnits())
1243     {
1244       if (!Unit::areIdentical(ud1Temp->getUnit(n), ud2Temp->getUnit(n)))
1245       {
1246         break;
1247       }
1248       else
1249       {
1250         n++;
1251       }
1252     }
1253     if (n == ud1Temp->getNumUnits())
1254     {
1255       identical = true;
1256     }
1257   }
1258 
1259   delete ud1Temp;
1260   delete ud2Temp;
1261 
1262   return identical;
1263 }
1264 
1265 
1266 /*
1267  * Predicate returning @c true if
1268  * UnitDefinition objects are equivalent (all units are equivalent).
1269  *
1270  * @param ud1 the first UnitDefinition object to compare.
1271  * @param ud2 the second UnitDefinition object to compare.
1272  *
1273  * @return @c true if all the units of ud1 are equivalent
1274  * to the units of ud2, @c false otherwise.
1275  *
1276  * @note For the purposes of comparison two units can be "identical",
1277  * i.e. all attributes are an exact match, or "equivalent" i.e.
1278  * matching kind and exponent.
1279  *
1280  * @see areIdentical();
1281  */
1282 bool
areEquivalent(const UnitDefinition * ud1,const UnitDefinition * ud2)1283 UnitDefinition::areEquivalent(const UnitDefinition * ud1, const UnitDefinition * ud2)
1284 {
1285   bool equivalent = false;
1286 
1287   bool A = (ud1 == NULL);
1288   bool B = (ud2 == NULL);
1289 
1290   /* if one or other is NULL no need to check
1291    */
1292   if ((A || B) && !(A && B))
1293   {
1294     return equivalent;
1295   }
1296 
1297   /* if both NULL no need to check */
1298   if (A && B)
1299   {
1300     equivalent = true;
1301     return equivalent;
1302   }
1303 
1304   unsigned int n;
1305 
1306   UnitDefinition * ud1Temp = UnitDefinition::convertToSI(ud1);
1307   UnitDefinition * ud2Temp = UnitDefinition::convertToSI(ud2);
1308 
1309   if (ud1Temp->getNumUnits() == ud2Temp->getNumUnits())
1310   {
1311     UnitDefinition::reorder(ud1Temp);
1312     UnitDefinition::reorder(ud2Temp);
1313 
1314     n = 0;
1315     while (n < ud1Temp->getNumUnits())
1316     {
1317       if (!Unit::areEquivalent(ud1Temp->getUnit(n), ud2Temp->getUnit(n)))
1318       {
1319         break;
1320       }
1321       else
1322       {
1323         n++;
1324       }
1325     }
1326     if (n == ud1Temp->getNumUnits())
1327     {
1328       equivalent = true;
1329     }
1330   }
1331 
1332   delete ud1Temp;
1333   delete ud2Temp;
1334 
1335   return equivalent;
1336 }
1337 
1338 /** @cond doxygenLibsbmlInternal */
1339 bool
areIdenticalSIUnits(const UnitDefinition * ud1,const UnitDefinition * ud2)1340 UnitDefinition::areIdenticalSIUnits(const UnitDefinition * ud1,
1341                                const UnitDefinition * ud2)
1342 {
1343   bool identical = false;
1344 
1345   bool A = (ud1 == NULL);
1346   bool B = (ud2 == NULL);
1347 
1348   /* if one or other is NULL no need to check
1349    */
1350   if ((A || B) && !(A && B))
1351   {
1352     return identical;
1353   }
1354 
1355   /* if both NULL no need to check */
1356   if (A && B)
1357   {
1358     identical = true;
1359     return identical;
1360   }
1361 
1362   unsigned int n;
1363 
1364   /* need to order the unitDefinitions so must make copies
1365    * since the arguments are const
1366    */
1367   UnitDefinition * ud1Temp = UnitDefinition::convertToSI(ud1);
1368   UnitDefinition * ud2Temp = UnitDefinition::convertToSI(ud2);
1369 
1370   if (ud1Temp->getNumUnits() == ud2Temp->getNumUnits())
1371   {
1372     UnitDefinition::reorder(ud1Temp);
1373     UnitDefinition::reorder(ud2Temp);
1374 
1375     if (ud1Temp->getNumUnits() > 1)
1376     {
1377       // different multipliers left on different units may not match
1378       // but overall they
1379       // e.g (2m)(sec) is tha same unit as (m)(2sec) but unit by unit
1380       // comparison will fail
1381       double multiplier1 = extractMultiplier(ud1Temp);
1382       double multiplier2 = extractMultiplier(ud2Temp);
1383 
1384       if (util_isEqual(multiplier1, multiplier2) == false)
1385       {
1386         delete ud1Temp;
1387         delete ud2Temp;
1388         return identical;
1389       }
1390     }
1391 
1392     n = 0;
1393     while (n < ud1Temp->getNumUnits())
1394     {
1395       Unit* u1 = ud1Temp->getUnit(n);
1396       Unit* u2 = ud2Temp->getUnit(n);
1397       // if the unit is dimensionless it does not matter
1398       // what numerical factors it has
1399       // but put this check here rather than in the unit areIdentical
1400       // so that Unit::areIdentical is trully a test for identical
1401       if (u1->getKind() == UNIT_KIND_DIMENSIONLESS)
1402       {
1403         if (u2->getKind() != UNIT_KIND_DIMENSIONLESS)
1404         {
1405           break;
1406         }
1407         else
1408         {
1409           n++;
1410         }
1411       }
1412       else
1413       {
1414         if (!Unit::areIdentical(u1, u2))
1415         {
1416           break;
1417         }
1418         else
1419         {
1420           n++;
1421         }
1422       }
1423     }
1424     if (n == ud1Temp->getNumUnits())
1425     {
1426       identical = true;
1427     }
1428   }
1429 
1430   delete ud1Temp;
1431   delete ud2Temp;
1432 
1433   return identical;
1434 }
1435 /** @endcond */
1436 
1437 /*
1438  * Combines two UnitDefinition objects into a single UnitDefinition object
1439  * which expresses the units of the two objects multiplied.
1440  *
1441  * @param ud1 the first UnitDefinition object into which the second is
1442  * combined.
1443  * @param ud2 the second UnitDefinition object.
1444  */
1445 UnitDefinition *
combine(UnitDefinition * ud1,UnitDefinition * ud2)1446 UnitDefinition::combine(UnitDefinition *ud1, UnitDefinition *ud2)
1447 {
1448   bool A = (ud1 == NULL);
1449   bool B = (ud2 == NULL);
1450 
1451   UnitDefinition * ud;
1452 
1453   if (A && B)
1454   {
1455     ud = NULL;
1456   }
1457   else if (A && !B)
1458   {
1459     ud = new UnitDefinition(*ud2);
1460   }
1461   else if (B && !A)
1462   {
1463     ud = new UnitDefinition(*ud1);
1464   }
1465   else  if ( (ud1->getLevel() != ud2->getLevel()) ||
1466        (ud1->getVersion() != ud2->getVersion()))
1467   {
1468     ud = NULL;
1469   }
1470   else
1471   {
1472     ud = new UnitDefinition(*ud1);
1473     for (unsigned int n = 0; n < ud2->getNumUnits(); n++)
1474     {
1475       ud->addUnit(ud2->getUnit(n));
1476     }
1477 
1478     UnitDefinition::simplify(ud);
1479   }
1480   return ud;
1481 }
1482 
1483 
1484 UnitDefinition *
divide(UnitDefinition * ud1,UnitDefinition * ud2)1485 UnitDefinition::divide(UnitDefinition *ud1, UnitDefinition *ud2)
1486 {
1487   bool A = (ud1 == NULL);
1488   bool B = (ud2 == NULL);
1489 
1490   UnitDefinition * ud = NULL;
1491 
1492   if (A && B)
1493   {
1494     ud = NULL;
1495   }
1496   else if (A && !B)
1497   {
1498     // no longer true
1499     ud = new UnitDefinition(*ud2);
1500     for (unsigned int i = 0; i < ud->getNumUnits(); i++)
1501     {
1502       ud->getUnit(i)->setExponent(ud->getUnit(i)->getExponent() * -1);
1503     }
1504   }
1505   else if (B && !A)
1506   {
1507     ud = new UnitDefinition(*ud1);
1508   }
1509   else  if ( (ud1->getLevel() != ud2->getLevel()) ||
1510        (ud1->getVersion() != ud2->getVersion()))
1511   {
1512     ud = NULL;
1513   }
1514   else
1515   {
1516     ud = new UnitDefinition(*ud1);
1517     for (unsigned int n = 0; n < ud2->getNumUnits(); n++)
1518     {
1519       Unit * u = new Unit(*(ud2->getUnit(n)));
1520       u->setExponent(u->getExponent() * -1);
1521       ud->addUnit(u);
1522       delete u;
1523     }
1524 
1525     UnitDefinition::simplify(ud);
1526   }
1527   return ud;
1528 }
1529 
1530 /*
1531  * Returns a string that expresses the units symbolised by the UnitDefinition.
1532  * For example printUnits applied to
1533  * @code
1534  * <unitDefinition>
1535  *  <listOfUnits>
1536  *    <unit kind="metre" exponent="1"/>
1537  *    <unit kind="second" exponent="-2"/>
1538  *  </listOfUnits>
1539  * <unitDefinition>
1540  * @endcode
1541  * returns the string 'metre (exponent = 1) second (exponent = -2)'
1542  *
1543  * @param ud the UnitDefinition object.
1544  *
1545  * @return a string expressing the units.
1546  */
1547 std::string
printUnits(const UnitDefinition * ud,bool compact)1548 UnitDefinition::printUnits(const UnitDefinition * ud, bool compact)
1549 {
1550   std::stringstream unitDef;
1551   if (ud == NULL || ud->getNumUnits() == 0)
1552   {
1553     unitDef << "indeterminable";
1554   }
1555   else
1556   {
1557     if (!compact)
1558     {
1559       for (unsigned int p = 0; p < ud->getNumUnits(); p++)
1560       {
1561         UnitKind_t kind = ud->getUnit(p)->getKind();
1562         double exp = 0;
1563         if (ud->getUnit(p)->isUnitChecking())
1564         {
1565           exp = ud->getUnit(p)->getExponentUnitChecking();
1566         }
1567         else
1568         {
1569           exp = ud->getUnit(p)->getExponentAsDouble();
1570         }
1571         int scale = ud->getUnit(p)->getScale();
1572         double mult = ud->getUnit(p)->getMultiplier();
1573 
1574         unitDef << UnitKind_toString(kind) << " (exponent = " << exp
1575             << ", multiplier = " << mult << ", scale = " << scale << ")";
1576 
1577         if (p + 1 < ud->getNumUnits())
1578         {
1579           unitDef << ", ";
1580         }
1581       }
1582     }
1583     else
1584     {
1585       for (unsigned int p = 0; p < ud->getNumUnits(); p++)
1586       {
1587         UnitKind_t kind = ud->getUnit(p)->getKind();
1588         double exp = ud->getUnit(p)->getExponentAsDouble();
1589         int scale = ud->getUnit(p)->getScale();
1590         double mult = ud->getUnit(p)->getMultiplier();
1591         mult = mult * pow(10.0, scale);
1592 
1593         unitDef << "(" << mult << " " << UnitKind_toString(kind) << ")^" << exp;
1594 
1595         if (p + 1 < ud->getNumUnits())
1596         {
1597           unitDef << ", ";
1598         }
1599       }
1600     }
1601   }
1602   return unitDef.str();
1603 }
1604 /** @cond doxygenLibsbmlInternal */
1605 
1606 /*
1607  * Returns the value of the "attributeName" attribute of this UnitDefinition.
1608  */
1609 int
getAttribute(const std::string & attributeName,bool & value) const1610 UnitDefinition::getAttribute(const std::string& attributeName,
1611                              bool& value) const
1612 {
1613   int return_value = SBase::getAttribute(attributeName, value);
1614 
1615   return return_value;
1616 }
1617 
1618 /** @endcond */
1619 
1620 
1621 
1622 /** @cond doxygenLibsbmlInternal */
1623 
1624 /*
1625  * Returns the value of the "attributeName" attribute of this UnitDefinition.
1626  */
1627 int
getAttribute(const std::string & attributeName,int & value) const1628 UnitDefinition::getAttribute(const std::string& attributeName,
1629                              int& value) const
1630 {
1631   int return_value = SBase::getAttribute(attributeName, value);
1632 
1633   return return_value;
1634 }
1635 
1636 /** @endcond */
1637 
1638 
1639 
1640 /** @cond doxygenLibsbmlInternal */
1641 
1642 /*
1643  * Returns the value of the "attributeName" attribute of this UnitDefinition.
1644  */
1645 int
getAttribute(const std::string & attributeName,double & value) const1646 UnitDefinition::getAttribute(const std::string& attributeName,
1647                              double& value) const
1648 {
1649   int return_value = SBase::getAttribute(attributeName, value);
1650 
1651   return return_value;
1652 }
1653 
1654 /** @endcond */
1655 
1656 
1657 
1658 /** @cond doxygenLibsbmlInternal */
1659 
1660 /*
1661  * Returns the value of the "attributeName" attribute of this UnitDefinition.
1662  */
1663 int
getAttribute(const std::string & attributeName,unsigned int & value) const1664 UnitDefinition::getAttribute(const std::string& attributeName,
1665                              unsigned int& value) const
1666 {
1667   int return_value = SBase::getAttribute(attributeName, value);
1668 
1669   return return_value;
1670 }
1671 
1672 /** @endcond */
1673 
1674 
1675 
1676 /** @cond doxygenLibsbmlInternal */
1677 
1678 /*
1679  * Returns the value of the "attributeName" attribute of this UnitDefinition.
1680  */
1681 int
getAttribute(const std::string & attributeName,std::string & value) const1682 UnitDefinition::getAttribute(const std::string& attributeName,
1683                              std::string& value) const
1684 {
1685   int return_value = SBase::getAttribute(attributeName, value);
1686 
1687   return return_value;
1688 }
1689 
1690 /** @endcond */
1691 
1692 
1693 
1694 /** @cond doxygenLibsbmlInternal */
1695 
1696 /*
1697  * Returns the value of the "attributeName" attribute of this UnitDefinition.
1698  */
1699 //int
1700 //UnitDefinition::getAttribute(const std::string& attributeName,
1701 //                             const char* value) const
1702 //{
1703 //  int return_value = SBase::getAttribute(attributeName, value);
1704 //
1705 //  return return_value;
1706 //}
1707 
1708 /** @endcond */
1709 
1710 
1711 
1712 /** @cond doxygenLibsbmlInternal */
1713 
1714 /*
1715  * Predicate returning @c true if this UnitDefinition's attribute
1716  * "attributeName" is set.
1717  */
1718 bool
isSetAttribute(const std::string & attributeName) const1719 UnitDefinition::isSetAttribute(const std::string& attributeName) const
1720 {
1721   bool value = SBase::isSetAttribute(attributeName);
1722 
1723   return value;
1724 }
1725 
1726 /** @endcond */
1727 
1728 
1729 
1730 /** @cond doxygenLibsbmlInternal */
1731 
1732 /*
1733  * Sets the value of the "attributeName" attribute of this UnitDefinition.
1734  */
1735 int
setAttribute(const std::string & attributeName,bool value)1736 UnitDefinition::setAttribute(const std::string& attributeName, bool value)
1737 {
1738   int return_value = SBase::setAttribute(attributeName, value);
1739 
1740   return return_value;
1741 }
1742 
1743 /** @endcond */
1744 
1745 
1746 
1747 /** @cond doxygenLibsbmlInternal */
1748 
1749 /*
1750  * Sets the value of the "attributeName" attribute of this UnitDefinition.
1751  */
1752 int
setAttribute(const std::string & attributeName,int value)1753 UnitDefinition::setAttribute(const std::string& attributeName, int value)
1754 {
1755   int return_value = SBase::setAttribute(attributeName, value);
1756 
1757   return return_value;
1758 }
1759 
1760 /** @endcond */
1761 
1762 
1763 
1764 /** @cond doxygenLibsbmlInternal */
1765 
1766 /*
1767  * Sets the value of the "attributeName" attribute of this UnitDefinition.
1768  */
1769 int
setAttribute(const std::string & attributeName,double value)1770 UnitDefinition::setAttribute(const std::string& attributeName, double value)
1771 {
1772   int return_value = SBase::setAttribute(attributeName, value);
1773 
1774   return return_value;
1775 }
1776 
1777 /** @endcond */
1778 
1779 
1780 
1781 /** @cond doxygenLibsbmlInternal */
1782 
1783 /*
1784  * Sets the value of the "attributeName" attribute of this UnitDefinition.
1785  */
1786 int
setAttribute(const std::string & attributeName,unsigned int value)1787 UnitDefinition::setAttribute(const std::string& attributeName,
1788                              unsigned int value)
1789 {
1790   int return_value = SBase::setAttribute(attributeName, value);
1791 
1792   return return_value;
1793 }
1794 
1795 /** @endcond */
1796 
1797 
1798 
1799 /** @cond doxygenLibsbmlInternal */
1800 
1801 /*
1802  * Sets the value of the "attributeName" attribute of this UnitDefinition.
1803  */
1804 int
setAttribute(const std::string & attributeName,const std::string & value)1805 UnitDefinition::setAttribute(const std::string& attributeName,
1806                              const std::string& value)
1807 {
1808   int return_value = SBase::setAttribute(attributeName, value);
1809 
1810   return return_value;
1811 }
1812 
1813 /** @endcond */
1814 
1815 
1816 
1817 /** @cond doxygenLibsbmlInternal */
1818 
1819 /*
1820  * Sets the value of the "attributeName" attribute of this UnitDefinition.
1821  */
1822 //int
1823 //UnitDefinition::setAttribute(const std::string& attributeName,
1824 //                             const char* value)
1825 //{
1826 //  int return_value = SBase::setAttribute(attributeName, value);
1827 //
1828 //  return return_value;
1829 //}
1830 //
1831 /** @endcond */
1832 
1833 
1834 
1835 /** @cond doxygenLibsbmlInternal */
1836 
1837 /*
1838  * Unsets the value of the "attributeName" attribute of this UnitDefinition.
1839  */
1840 int
unsetAttribute(const std::string & attributeName)1841 UnitDefinition::unsetAttribute(const std::string& attributeName)
1842 {
1843   int value = SBase::unsetAttribute(attributeName);
1844 
1845   return value;
1846 }
1847 /** @endcond */
1848 
1849 
1850 
1851 /** @cond doxygenLibsbmlInternal */
1852 /*
1853  * Creates and returns an new "elementName" object in this UnitDefinition.
1854  */
1855 SBase*
createChildObject(const std::string & elementName)1856 UnitDefinition::createChildObject(const std::string& elementName)
1857 {
1858   SBase* obj = NULL;
1859 
1860   if (elementName == "unit")
1861   {
1862     return createUnit();
1863   }
1864 
1865   return obj;
1866 }
1867 /** @endcond */
1868 
1869 /** @cond doxygenLibsbmlInternal */
1870 /*
1871  * Adds an new "elementName" object in this UnitDefinition.
1872  */
1873 int
addChildObject(const std::string & elementName,const SBase * element)1874 UnitDefinition::addChildObject(const std::string& elementName, const SBase* element)
1875 {
1876   if (elementName == "unit" && element->getTypeCode() == SBML_UNIT)
1877   {
1878     return addUnit((const Unit*)(element));
1879   }
1880 
1881   return LIBSBML_OPERATION_FAILED;
1882 }
1883 /** @endcond */
1884 
1885 
1886 /** @cond doxygenLibsbmlInternal */
1887 /*
1888  * Adds an new "elementName" object in this UnitDefinition.
1889  */
1890 SBase*
removeChildObject(const std::string & elementName,const std::string & id)1891 UnitDefinition::removeChildObject(const std::string& elementName, const std::string& id)
1892 {
1893 
1894   if (elementName == "unit")
1895   {
1896  //   return removeUnit(id);
1897   }
1898 
1899   return NULL;
1900 }
1901 
1902 /** @endcond */
1903 
1904 
1905 
1906 
1907 /** @cond doxygenLibsbmlInternal */
1908 
1909 /*
1910  * Returns the number of "elementName" in this UnitDefinition.
1911  */
1912 unsigned int
getNumObjects(const std::string & elementName)1913 UnitDefinition::getNumObjects(const std::string& elementName)
1914 {
1915   unsigned int n = 0;
1916 
1917   if (elementName == "unit")
1918   {
1919     return getNumUnits();
1920   }
1921 
1922   return n;
1923 }
1924 
1925 /** @endcond */
1926 
1927 
1928 
1929 /** @cond doxygenLibsbmlInternal */
1930 
1931 /*
1932  * Returns the nth object of "objectName" in this UnitDefinition.
1933  */
1934 SBase*
getObject(const std::string & elementName,unsigned int index)1935 UnitDefinition::getObject(const std::string& elementName, unsigned int index)
1936 {
1937   SBase* obj = NULL;
1938 
1939   if (elementName == "unit")
1940   {
1941     return getUnit(index);
1942   }
1943 
1944   return obj;
1945 }
1946 
1947 /** @endcond */
1948 
1949 
1950 
1951 /* @cond doxygenLibsbmlInternal */
1952 /*
1953  * @return the SBML object corresponding to next XMLToken in the
1954  * XMLInputStream or @c NULL if the token was not recognized.
1955  */
1956 SBase*
createObject(XMLInputStream & stream)1957 UnitDefinition::createObject (XMLInputStream& stream)
1958 {
1959   SBase* object = 0;
1960 
1961   const string& name = stream.peek().getName();
1962   if (name == "listOfUnits")
1963   {
1964     if (mUnits.size() != 0)
1965     {
1966       if (getLevel() < 3)
1967       {
1968         logError(NotSchemaConformant, getLevel(), getVersion(),
1969          "Only one <listOfUnits> elements is permitted in a "
1970          "given <unitDefinition>.");
1971       }
1972       else
1973       {
1974         logError(OneListOfUnitsPerUnitDef, getLevel(), getVersion());
1975       }
1976     }
1977     mUnits.setExplicitlyListed();
1978     object = &mUnits;
1979   }
1980 
1981   return object;
1982 }
1983 /** @endcond */
1984 
1985 
1986 /** @cond doxygenLibsbmlInternal */
1987 /*
1988  * Subclasses should override this method to get the list of
1989  * expected attributes.
1990  * This function is invoked from corresponding readAttributes()
1991  * function.
1992  */
1993 void
addExpectedAttributes(ExpectedAttributes & attributes)1994 UnitDefinition::addExpectedAttributes(ExpectedAttributes& attributes)
1995 {
1996   SBase::addExpectedAttributes(attributes);
1997 
1998   const unsigned int level   = getLevel  ();
1999 
2000   attributes.add("name");
2001 
2002   if (level > 1)
2003   {
2004     attributes.add("id");
2005   }
2006 }
2007 
2008 
2009 /*
2010  * Subclasses should override this method to read values from the given
2011  * XMLAttributes set into their specific fields.  Be sure to call your
2012  * parent's implementation of this method as well.
2013  */
2014 void
readAttributes(const XMLAttributes & attributes,const ExpectedAttributes & expectedAttributes)2015 UnitDefinition::readAttributes (const XMLAttributes& attributes,
2016                                 const ExpectedAttributes& expectedAttributes)
2017 {
2018   const unsigned int level   = getLevel  ();
2019 
2020   SBase::readAttributes(attributes, expectedAttributes);
2021 
2022   switch (level)
2023   {
2024   case 1:
2025     readL1Attributes(attributes);
2026     break;
2027   case 2:
2028     readL2Attributes(attributes);
2029     break;
2030   case 3:
2031   default:
2032     readL3Attributes(attributes);
2033     break;
2034   }
2035 }
2036 /** @endcond */
2037 
2038 
2039 /** @cond doxygenLibsbmlInternal */
2040 /*
2041  * Subclasses should override this method to read values from the given
2042  * XMLAttributes set into their specific fields.  Be sure to call your
2043  * parent's implementation of this method as well.
2044  */
2045 void
readL1Attributes(const XMLAttributes & attributes)2046 UnitDefinition::readL1Attributes (const XMLAttributes& attributes)
2047 {
2048   const unsigned int level = getLevel();
2049   const unsigned int version = getVersion();
2050 
2051   //
2052   // name: SName   { use="required" }  (L1v1, L1v2)
2053   //   id: SId     { use="required" }  (L2v1, L2v2)
2054   //
2055   bool assigned;
2056   assigned = attributes.readInto("name", mId, getErrorLog(), true, getLine(), getColumn());
2057   if (assigned && mId.size() == 0)
2058   {
2059     logEmptyString("name", level, version, "<unitDefinition>");
2060   }
2061   if (!SyntaxChecker::isValidInternalSId(mId))
2062     logError(InvalidIdSyntax, level, version, "The id '" + mId + "' does not conform to the syntax.");
2063 }
2064 /** @endcond */
2065 
2066 
2067 /** @cond doxygenLibsbmlInternal */
2068 /*
2069  * Subclasses should override this method to read values from the given
2070  * XMLAttributes set into their specific fields.  Be sure to call your
2071  * parent's implementation of this method as well.
2072  */
2073 void
readL2Attributes(const XMLAttributes & attributes)2074 UnitDefinition::readL2Attributes (const XMLAttributes& attributes)
2075 {
2076   const unsigned int level = getLevel();
2077   const unsigned int version = getVersion();
2078 
2079   //
2080   //   id: SId     { use="required" }  (L2v1, L2v2)
2081   //
2082   bool assigned;
2083   assigned = attributes.readInto("id", mId, getErrorLog(), true, getLine(), getColumn());
2084   if (assigned && mId.size() == 0)
2085   {
2086     logEmptyString("id", level, version, "<unitDefinition>");
2087   }
2088   if (!SyntaxChecker::isValidInternalSId(mId))
2089     logError(InvalidIdSyntax, level, version, "The id '" + mId + "' does not conform to the syntax.");
2090 
2091   //
2092   // name: string  { use="optional" }  (L2v1->)
2093   //
2094   attributes.readInto("name", mName, getErrorLog(), false, getLine(), getColumn());
2095 }
2096 /** @endcond */
2097 
2098 
2099 /** @cond doxygenLibsbmlInternal */
2100 /*
2101  * Subclasses should override this method to read values from the given
2102  * XMLAttributes set into their specific fields.  Be sure to call your
2103  * parent's implementation of this method as well.
2104  */
2105 void
readL3Attributes(const XMLAttributes & attributes)2106 UnitDefinition::readL3Attributes (const XMLAttributes& attributes)
2107 {
2108   const unsigned int level = getLevel();
2109   const unsigned int version = getVersion();
2110 
2111   //
2112   //   id: SId     { use="required" }  (L2v1, L2v2)
2113   //
2114   bool assigned;
2115   // for l3v2 sbase will read this as generically optional
2116   // we want to log errors relating to the specific object
2117   if (version == 1)
2118   {
2119     assigned = attributes.readInto("id", mId, getErrorLog(), false, getLine(), getColumn());
2120     if (!assigned)
2121     {
2122       logError(AllowedAttributesOnUnitDefinition, level, version,
2123                "The required attribute 'id' is missing.");
2124     }
2125     if (assigned && mId.size() == 0)
2126     {
2127       logEmptyString("id", level, version, "<unitDefinition>");
2128     }
2129     if (!SyntaxChecker::isValidInternalSId(mId))
2130       logError(InvalidIdSyntax, level, version, "The id '" + mId + "' does not conform to the syntax.");
2131   }
2132   else
2133   {
2134     // need to check that id was present
2135     // it has already been read and checked for syntax/emptyness
2136     if (attributes.hasAttribute("id") == false)
2137     {
2138       logError(AllowedAttributesOnUnitDefinition, level, version,
2139         "The required attribute 'id' is missing.");
2140     }
2141   }
2142 
2143   //
2144   // name: string  { use="optional" }  (L2v1->)
2145   //
2146   // for l3v2 sbase will read this
2147   if (version == 1)
2148   {
2149     attributes.readInto("name", mName, getErrorLog(), false,
2150                                        getLine(), getColumn());
2151   }
2152 }
2153 /** @endcond */
2154 
2155 
2156 /** @cond doxygenLibsbmlInternal */
2157 /*
2158  * Subclasses should override this method to write their XML attributes
2159  * to the XMLOutputStream.  Be sure to call your parent's implementation
2160  * of this method as well.
2161  */
2162 void
writeAttributes(XMLOutputStream & stream) const2163 UnitDefinition::writeAttributes (XMLOutputStream& stream) const
2164 {
2165   SBase::writeAttributes(stream);
2166 
2167   const unsigned int level = getLevel();
2168   unsigned int version = getVersion();
2169 
2170   // for L3V2 and above SBase will write this out
2171   if (level < 3 || (level == 3 && version == 1))
2172   {
2173     //
2174     // name: SName   { use="required" }  (L1v1, L1v2)
2175     //   id: SId     { use="required" }  (L2v1, L2v2)
2176     //
2177     const string id = (level == 1) ? "name" : "id";
2178     stream.writeAttribute(id, mId);
2179   }
2180 
2181   if (level > 1)
2182   {
2183     // for L3V2 and above SBase will write this out
2184     if (level < 3 || (level == 3 && version == 1))
2185     {
2186       //
2187       // name: string  { use="optional" }  (L2v1->)
2188       //
2189       stream.writeAttribute("name", mName);
2190     }
2191   }
2192 
2193   //
2194   // sboTerm: SBOTerm { use="optional" }  (L2v3->)
2195   // is written in SBase::writeAttributes()
2196   //
2197 
2198   //
2199   // (EXTENSION)
2200   //
2201   SBase::writeExtensionAttributes(stream);
2202 }
2203 /** @endcond */
2204 
2205 
2206 /** @cond doxygenLibsbmlInternal */
2207 /*
2208  * Subclasses should override this method to write out their contained
2209  * SBML objects as XML elements.  Be sure to call your parent's
2210  * implementation of this method as well.
2211  */
2212 void
writeElements(XMLOutputStream & stream) const2213 UnitDefinition::writeElements (XMLOutputStream& stream) const
2214 {
2215   SBase::writeElements(stream);
2216 
2217   if (getLevel() == 3 && getVersion() > 1)
2218   {
2219     if (mUnits.hasOptionalElements() == true ||
2220         mUnits.hasOptionalAttributes() == true ||
2221         mUnits.isExplicitlyListed())
2222     {
2223       mUnits.write(stream);
2224     }
2225   }
2226   else
2227   {
2228     // use original code
2229     if ( getNumUnits() > 0 ) mUnits.write(stream);
2230   }
2231 
2232   //
2233   // (EXTENSION)
2234   //
2235   SBase::writeExtensionElements(stream);
2236 }
2237 /** @endcond */
2238 
2239 
2240 /*
2241  * Creates a new ListOfUnitDefinitions items.
2242  */
ListOfUnitDefinitions(unsigned int level,unsigned int version)2243 ListOfUnitDefinitions::ListOfUnitDefinitions (unsigned int level, unsigned int version)
2244 : ListOf(level,version)
2245 {
2246 }
2247 
2248 
2249 /*
2250  * Creates a new ListOfUnitDefinitions items.
2251  */
ListOfUnitDefinitions(SBMLNamespaces * sbmlns)2252 ListOfUnitDefinitions::ListOfUnitDefinitions (SBMLNamespaces* sbmlns)
2253  : ListOf(sbmlns)
2254 {
2255   loadPlugins(sbmlns);
2256 }
2257 
2258 
2259 /*
2260  * @return a (deep) copy of this ListOfUnitDefinitions.
2261  */
2262 ListOfUnitDefinitions*
clone() const2263 ListOfUnitDefinitions::clone () const
2264 {
2265   return new ListOfUnitDefinitions(*this);
2266 }
2267 
2268 
2269 /*
2270  * @return the typecode (int) of SBML objects contained in this ListOf or
2271  * SBML_UNKNOWN (default).
2272  */
2273 int
getItemTypeCode() const2274 ListOfUnitDefinitions::getItemTypeCode () const
2275 {
2276   return SBML_UNIT_DEFINITION;
2277 }
2278 
2279 
2280 /*
2281  * @return the name of this element ie "listOfUnitDefinitions".
2282  */
2283 const string&
getElementName() const2284 ListOfUnitDefinitions::getElementName () const
2285 {
2286   static const string name = "listOfUnitDefinitions";
2287   return name;
2288 }
2289 
2290 
2291 /* return nth item in list */
2292 UnitDefinition *
get(unsigned int n)2293 ListOfUnitDefinitions::get(unsigned int n)
2294 {
2295   return static_cast<UnitDefinition*>(ListOf::get(n));
2296 }
2297 
2298 
2299 /* return nth item in list */
2300 const UnitDefinition *
get(unsigned int n) const2301 ListOfUnitDefinitions::get(unsigned int n) const
2302 {
2303   return static_cast<const UnitDefinition*>(ListOf::get(n));
2304 }
2305 
2306 
2307 /**
2308  * Used by ListOf::get() to lookup an SBase based by its id.
2309  */
2310 struct IdEqUD : public unary_function<SBase*, bool>
2311 {
2312   const string& mId;
2313 
IdEqUDIdEqUD2314   IdEqUD (const string& id) : mId(id) { }
operator ()IdEqUD2315   bool operator() (SBase* sb)
2316        { return static_cast <UnitDefinition *> (sb)->getId() == mId; }
2317 };
2318 
2319 
2320 /* return item by id */
2321 UnitDefinition*
get(const std::string & sid)2322 ListOfUnitDefinitions::get (const std::string& sid)
2323 {
2324   return const_cast<UnitDefinition*>(
2325     static_cast<const ListOfUnitDefinitions&>(*this).get(sid) );
2326 }
2327 
2328 
2329 /* return item by id */
2330 const UnitDefinition*
get(const std::string & sid) const2331 ListOfUnitDefinitions::get (const std::string& sid) const
2332 {
2333   vector<SBase*>::const_iterator result;
2334 
2335   result = find_if( mItems.begin(), mItems.end(), IdEqUD(sid) );
2336   return (result == mItems.end()) ? NULL :
2337                    static_cast <UnitDefinition*> (*result);
2338 }
2339 
2340 
2341 SBase*
getElementBySId(const std::string & id)2342 ListOfUnitDefinitions::getElementBySId(const std::string& id)
2343 {
2344   for (unsigned int i = 0; i < size(); i++)
2345   {
2346     SBase* obj = get(i);
2347     //Units are not in the SId namespace, so don't check 'getId'.  However, their children (through plugins) may have the element we are looking for, so we still need to check all of them.
2348     obj = obj->getElementBySId(id);
2349     if (obj != NULL) return obj;
2350   }
2351 
2352   return getElementFromPluginsBySId(id);
2353 }
2354 
2355 /* Removes the nth item from this list */
2356 UnitDefinition*
remove(unsigned int n)2357 ListOfUnitDefinitions::remove (unsigned int n)
2358 {
2359    return static_cast<UnitDefinition*>(ListOf::remove(n));
2360 }
2361 
2362 
2363 /* Removes item in this list by id */
2364 UnitDefinition*
remove(const std::string & sid)2365 ListOfUnitDefinitions::remove (const std::string& sid)
2366 {
2367   SBase* item = NULL;
2368   ListItemIter result;
2369 
2370   result = find_if( mItems.begin(), mItems.end(), IdEqUD(sid) );
2371 
2372   if (result != mItems.end())
2373   {
2374     item = *result;
2375     mItems.erase(result);
2376   }
2377 
2378   return static_cast <UnitDefinition*> (item);
2379 }
2380 
2381 
2382 /** @cond doxygenLibsbmlInternal */
2383 /*
2384  * @return the ordinal position of the element with respect to its siblings
2385  * or -1 (default) to indicate the position is not significant.
2386  */
2387 int
getElementPosition() const2388 ListOfUnitDefinitions::getElementPosition () const
2389 {
2390   return 2;
2391 }
2392 /** @endcond */
2393 
2394 
2395 /** @cond doxygenLibsbmlInternal */
2396 /*
2397  * @return the SBML object corresponding to next XMLToken in the
2398  * XMLInputStream or @c NULL if the token was not recognized.
2399  */
2400 SBase*
createObject(XMLInputStream & stream)2401 ListOfUnitDefinitions::createObject (XMLInputStream& stream)
2402 {
2403   const string& name   = stream.peek().getName();
2404   SBase*        object = NULL;
2405 
2406 
2407   if (name == "unitDefinition")
2408   {
2409     try
2410     {
2411       object = new UnitDefinition(getSBMLNamespaces());
2412     }
2413     catch (SBMLConstructorException*)
2414     {
2415       object = new UnitDefinition(SBMLDocument::getDefaultLevel(),
2416         SBMLDocument::getDefaultVersion());
2417     }
2418     catch ( ... )
2419     {
2420       object = new UnitDefinition(SBMLDocument::getDefaultLevel(),
2421         SBMLDocument::getDefaultVersion());
2422     }
2423 
2424     if (object != NULL) mItems.push_back(object);
2425   }
2426 
2427   return object;
2428 }
2429 /** @endcond */
2430 
2431 
2432 #endif /* __cplusplus */
2433 /** @cond doxygenIgnored */
2434 LIBSBML_EXTERN
2435 UnitDefinition_t *
UnitDefinition_create(unsigned int level,unsigned int version)2436 UnitDefinition_create (unsigned int level, unsigned int version)
2437 {
2438   try
2439   {
2440     UnitDefinition* obj = new UnitDefinition(level,version);
2441     return obj;
2442   }
2443   catch (SBMLConstructorException)
2444   {
2445     return NULL;
2446   }
2447 }
2448 
2449 
2450 LIBSBML_EXTERN
2451 UnitDefinition_t *
UnitDefinition_createWithNS(SBMLNamespaces_t * sbmlns)2452 UnitDefinition_createWithNS (SBMLNamespaces_t* sbmlns)
2453 {
2454   try
2455   {
2456     UnitDefinition* obj = new UnitDefinition(sbmlns);
2457     return obj;
2458   }
2459   catch (SBMLConstructorException)
2460   {
2461     return NULL;
2462   }
2463 }
2464 
2465 
2466 LIBSBML_EXTERN
2467 void
UnitDefinition_free(UnitDefinition_t * ud)2468 UnitDefinition_free (UnitDefinition_t *ud)
2469 {
2470   delete ud;
2471 }
2472 
2473 
2474 LIBSBML_EXTERN
2475 UnitDefinition_t*
UnitDefinition_clone(const UnitDefinition_t * ud)2476 UnitDefinition_clone (const UnitDefinition_t *ud)
2477 {
2478   return (ud != NULL) ? static_cast<UnitDefinition_t*>( ud->clone() ) : NULL;
2479 }
2480 
2481 
2482 LIBSBML_EXTERN
2483 const XMLNamespaces_t *
UnitDefinition_getNamespaces(UnitDefinition_t * ud)2484 UnitDefinition_getNamespaces(UnitDefinition_t *ud)
2485 {
2486   return (ud != NULL) ? ud->getNamespaces() : NULL;
2487 }
2488 
2489 LIBSBML_EXTERN
2490 const char *
UnitDefinition_getId(const UnitDefinition_t * ud)2491 UnitDefinition_getId (const UnitDefinition_t *ud)
2492 {
2493   return (ud != NULL && ud->isSetId()) ? ud->getId().c_str() : NULL;
2494 }
2495 
2496 
2497 LIBSBML_EXTERN
2498 const char *
UnitDefinition_getName(const UnitDefinition_t * ud)2499 UnitDefinition_getName (const UnitDefinition_t *ud)
2500 {
2501   return (ud != NULL && ud->isSetName()) ? ud->getName().c_str() : NULL;
2502 }
2503 
2504 
2505 LIBSBML_EXTERN
2506 int
UnitDefinition_isSetId(const UnitDefinition_t * ud)2507 UnitDefinition_isSetId (const UnitDefinition_t *ud)
2508 {
2509   return (ud != NULL) ? static_cast<int>( ud->isSetId() ) : 0;
2510 }
2511 
2512 
2513 LIBSBML_EXTERN
2514 int
UnitDefinition_isSetName(const UnitDefinition_t * ud)2515 UnitDefinition_isSetName (const UnitDefinition_t *ud)
2516 {
2517   return (ud != NULL) ? static_cast<int>( ud->isSetName() ) : 0;
2518 }
2519 
2520 
2521 LIBSBML_EXTERN
2522 int
UnitDefinition_isVariantOfArea(const UnitDefinition_t * ud)2523 UnitDefinition_isVariantOfArea (const UnitDefinition_t *ud)
2524 {
2525   return (ud != NULL) ? static_cast<int>( ud->isVariantOfArea() ) : 0;
2526 }
2527 
2528 
2529 LIBSBML_EXTERN
2530 int
UnitDefinition_isVariantOfLength(const UnitDefinition_t * ud)2531 UnitDefinition_isVariantOfLength (const UnitDefinition_t *ud)
2532 {
2533   return (ud != NULL) ? static_cast<int>( ud->isVariantOfLength() ) : 0;
2534 }
2535 
2536 
2537 LIBSBML_EXTERN
2538 int
UnitDefinition_isVariantOfSubstance(const UnitDefinition_t * ud)2539 UnitDefinition_isVariantOfSubstance (const UnitDefinition_t *ud)
2540 {
2541   return (ud != NULL) ? static_cast<int>( ud->isVariantOfSubstance() ) : 0;
2542 }
2543 
2544 
2545 LIBSBML_EXTERN
2546 int
UnitDefinition_isVariantOfTime(const UnitDefinition_t * ud)2547 UnitDefinition_isVariantOfTime (const UnitDefinition_t *ud)
2548 {
2549   return (ud != NULL) ? static_cast<int>( ud->isVariantOfTime() ) : 0;
2550 }
2551 
2552 
2553 LIBSBML_EXTERN
2554 int
UnitDefinition_isVariantOfVolume(const UnitDefinition_t * ud)2555 UnitDefinition_isVariantOfVolume (const UnitDefinition_t *ud)
2556 {
2557   return (ud != NULL) ? static_cast<int>( ud->isVariantOfVolume() ) : 0;
2558 }
2559 
2560 
2561 LIBSBML_EXTERN
2562 int
UnitDefinition_isVariantOfDimensionless(const UnitDefinition_t * ud)2563 UnitDefinition_isVariantOfDimensionless (const UnitDefinition_t *ud)
2564 {
2565   return (ud != NULL) ? static_cast<int>( ud->isVariantOfDimensionless() ) : 0;
2566 }
2567 
2568 
2569 LIBSBML_EXTERN
2570 int
UnitDefinition_isVariantOfMass(const UnitDefinition_t * ud)2571 UnitDefinition_isVariantOfMass (const UnitDefinition_t *ud)
2572 {
2573   return (ud != NULL) ? static_cast<int>( ud->isVariantOfMass() ) : 0;
2574 }
2575 
2576 
2577 LIBSBML_EXTERN
2578 int
UnitDefinition_isVariantOfSubstancePerTime(const UnitDefinition_t * ud)2579 UnitDefinition_isVariantOfSubstancePerTime (const UnitDefinition_t *ud)
2580 {
2581   return (ud != NULL) ?
2582     static_cast<int>( ud->isVariantOfSubstancePerTime() ) : 0;
2583 }
2584 
2585 
2586 LIBSBML_EXTERN
2587 int
UnitDefinition_setId(UnitDefinition_t * ud,const char * id)2588 UnitDefinition_setId (UnitDefinition_t *ud, const char *id)
2589 {
2590   if (ud != NULL)
2591     return (id == NULL) ? ud->setId("") : ud->setId(id);
2592   else
2593     return LIBSBML_INVALID_OBJECT;
2594 }
2595 
2596 
2597 LIBSBML_EXTERN
2598 int
UnitDefinition_setName(UnitDefinition_t * ud,const char * name)2599 UnitDefinition_setName (UnitDefinition_t *ud, const char *name)
2600 {
2601   if (ud != NULL)
2602     return (name == NULL) ? ud->unsetName() : ud->setName(name);
2603   else
2604     return LIBSBML_INVALID_OBJECT;
2605 }
2606 
2607 
2608 LIBSBML_EXTERN
2609 int
UnitDefinition_unsetName(UnitDefinition_t * ud)2610 UnitDefinition_unsetName (UnitDefinition_t *ud)
2611 {
2612   return (ud != NULL) ? ud->unsetName() : LIBSBML_INVALID_OBJECT;
2613 }
2614 
2615 
2616 LIBSBML_EXTERN
2617 int
UnitDefinition_addUnit(UnitDefinition_t * ud,const Unit_t * u)2618 UnitDefinition_addUnit (UnitDefinition_t *ud, const Unit_t *u)
2619 {
2620   return (ud != NULL) ? ud->addUnit(u) : LIBSBML_INVALID_OBJECT;
2621 }
2622 
2623 
2624 LIBSBML_EXTERN
2625 Unit_t *
UnitDefinition_createUnit(UnitDefinition_t * ud)2626 UnitDefinition_createUnit (UnitDefinition_t *ud)
2627 {
2628   return (ud != NULL) ? ud->createUnit() : NULL;
2629 }
2630 
2631 
2632 LIBSBML_EXTERN
2633 ListOf_t *
UnitDefinition_getListOfUnits(UnitDefinition_t * ud)2634 UnitDefinition_getListOfUnits (UnitDefinition_t *ud)
2635 {
2636   return (ud != NULL) ? ud->getListOfUnits() : NULL;
2637 }
2638 
2639 
2640 LIBSBML_EXTERN
2641 Unit_t *
UnitDefinition_getUnit(UnitDefinition_t * ud,unsigned int n)2642 UnitDefinition_getUnit (UnitDefinition_t *ud, unsigned int n)
2643 {
2644   return (ud != NULL) ? ud->getUnit(n) : NULL;
2645 }
2646 
2647 
2648 LIBSBML_EXTERN
2649 Unit_t *
UnitDefinition_removeUnit(UnitDefinition_t * ud,unsigned int n)2650 UnitDefinition_removeUnit (UnitDefinition_t *ud, unsigned int n)
2651 {
2652   if (ud != NULL)
2653     return ud->removeUnit(n);
2654   else
2655     return NULL;
2656 }
2657 
2658 
2659 LIBSBML_EXTERN
2660 unsigned int
UnitDefinition_getNumUnits(const UnitDefinition_t * ud)2661 UnitDefinition_getNumUnits (const UnitDefinition_t *ud)
2662 {
2663   return (ud != NULL) ? ud->getNumUnits() : SBML_INT_MAX;
2664 }
2665 
2666 
2667 LIBSBML_EXTERN
2668 void
UnitDefinition_simplify(UnitDefinition_t * ud)2669 UnitDefinition_simplify(UnitDefinition_t * ud)
2670 {
2671   if (ud != NULL)
2672     UnitDefinition::simplify(static_cast<UnitDefinition*>(ud));
2673 }
2674 
2675 LIBSBML_EXTERN
2676 void
UnitDefinition_reorder(UnitDefinition_t * ud)2677 UnitDefinition_reorder(UnitDefinition_t * ud)
2678 {
2679   if (ud != NULL)
2680     UnitDefinition::reorder(static_cast<UnitDefinition*>(ud));
2681 }
2682 
2683 LIBSBML_EXTERN
2684 UnitDefinition_t *
UnitDefinition_convertToSI(UnitDefinition_t * ud)2685 UnitDefinition_convertToSI(UnitDefinition_t * ud)
2686 {
2687   return (ud != NULL) ?
2688     UnitDefinition::convertToSI(static_cast<UnitDefinition*>(ud)) : NULL;
2689 }
2690 
2691 LIBSBML_EXTERN
2692 int
UnitDefinition_areIdentical(UnitDefinition_t * ud1,UnitDefinition_t * ud2)2693 UnitDefinition_areIdentical(UnitDefinition_t * ud1, UnitDefinition_t * ud2)
2694 {
2695   if (ud1 != NULL && ud2 != NULL)
2696     return static_cast<int>
2697          (UnitDefinition::areIdentical(static_cast<UnitDefinition*>(ud1),
2698                                        static_cast<UnitDefinition*>(ud2)));
2699   else
2700     return 0;
2701 }
2702 
2703 LIBSBML_EXTERN
2704 int
UnitDefinition_areEquivalent(UnitDefinition_t * ud1,UnitDefinition_t * ud2)2705 UnitDefinition_areEquivalent(UnitDefinition_t *ud1 , UnitDefinition_t * ud2)
2706 {
2707   if (ud1 != NULL && ud2 != NULL)
2708     return static_cast<int>(
2709          UnitDefinition::areEquivalent(static_cast<UnitDefinition*>(ud1),
2710                                        static_cast<UnitDefinition*>(ud2)));
2711   else
2712     return 0;
2713 }
2714 
2715 LIBSBML_EXTERN
2716 UnitDefinition_t *
UnitDefinition_combine(UnitDefinition_t * ud1,UnitDefinition_t * ud2)2717 UnitDefinition_combine(UnitDefinition_t * ud1, UnitDefinition_t * ud2)
2718 {
2719   return UnitDefinition::combine(static_cast<UnitDefinition*>(ud1),
2720                                        static_cast<UnitDefinition*>(ud2));
2721 }
2722 
2723 
2724 LIBSBML_EXTERN
2725 UnitDefinition_t *
UnitDefinition_divide(UnitDefinition_t * ud1,UnitDefinition_t * ud2)2726 UnitDefinition_divide(UnitDefinition_t * ud1, UnitDefinition_t * ud2)
2727 {
2728   return UnitDefinition::divide(static_cast<UnitDefinition*>(ud1),
2729                                        static_cast<UnitDefinition*>(ud2));
2730 }
2731 
2732 
2733 LIBSBML_EXTERN
2734 char *
UnitDefinition_printUnits(UnitDefinition_t * ud,int compact)2735 UnitDefinition_printUnits(UnitDefinition_t * ud, int compact)
2736 {
2737   return (ud != NULL) ?
2738     safe_strdup(UnitDefinition::printUnits(static_cast<UnitDefinition*>(ud)
2739     , compact).c_str()) : NULL;
2740 }
2741 
2742 LIBSBML_EXTERN
2743 UnitDefinition_t *
ListOfUnitDefinitions_getById(ListOf_t * lo,const char * sid)2744 ListOfUnitDefinitions_getById (ListOf_t *lo, const char *sid)
2745 {
2746   if (lo != NULL)
2747     return (sid != NULL) ?
2748       static_cast <ListOfUnitDefinitions *> (lo)->get(sid) : NULL;
2749   else
2750     return NULL;
2751 }
2752 
2753 
2754 LIBSBML_EXTERN
2755 UnitDefinition_t *
ListOfUnitDefinitions_removeById(ListOf_t * lo,const char * sid)2756 ListOfUnitDefinitions_removeById (ListOf_t *lo, const char *sid)
2757 {
2758   if (lo != NULL)
2759     return (sid != NULL) ?
2760       static_cast <ListOfUnitDefinitions *> (lo)->remove(sid) : NULL;
2761   else
2762     return NULL;
2763 }
2764 /** @endcond */
2765 
2766 LIBSBML_CPP_NAMESPACE_END
2767 
2768