1 /**
2  * @cond doxygenLibsbmlInternal
3  *
4  * @file    UniqueIdsInModel.cpp
5  * @brief   Ensures the appropriate ids within a Model are unique
6  * @author  Ben Bornstein
7  *
8  * <!--------------------------------------------------------------------------
9  * This file is part of libSBML.  Please visit http://sbml.org for more
10  * information about SBML, and the latest version of libSBML.
11  *
12  * Copyright (C) 2020 jointly by the following organizations:
13  *     1. California Institute of Technology, Pasadena, CA, USA
14  *     2. University of Heidelberg, Heidelberg, Germany
15  *     3. University College London, London, UK
16  *
17  * Copyright (C) 2019 jointly by the following organizations:
18  *     1. California Institute of Technology, Pasadena, CA, USA
19  *     2. University of Heidelberg, Heidelberg, Germany
20  *
21  * Copyright (C) 2013-2018 jointly by the following organizations:
22  *     1. California Institute of Technology, Pasadena, CA, USA
23  *     2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK
24  *     3. University of Heidelberg, Heidelberg, Germany
25  *
26  * Copyright (C) 2009-2013 jointly by the following organizations:
27  *     1. California Institute of Technology, Pasadena, CA, USA
28  *     2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK
29  *
30  * Copyright (C) 2006-2008 by the California Institute of Technology,
31  *     Pasadena, CA, USA
32  *
33  * Copyright (C) 2002-2005 jointly by the following organizations:
34  *     1. California Institute of Technology, Pasadena, CA, USA
35  *     2. Japan Science and Technology Agency, Japan
36  *
37  * This library is free software; you can redistribute it and/or modify it
38  * under the terms of the GNU Lesser General Public License as published by
39  * the Free Software Foundation.  A copy of the license agreement is provided
40  * in the file named "LICENSE.txt" included with this software distribution
41  * and also available online as http://sbml.org/software/libsbml/license.html
42  * ---------------------------------------------------------------------- -->*/
43 
44 #include <sbml/Model.h>
45 #include <sbml/ModifierSpeciesReference.h>
46 #include "UniqueIdsInModel.h"
47 
48 /** @cond doxygenIgnored */
49 using namespace std;
50 /** @endcond */
51 
52 LIBSBML_CPP_NAMESPACE_BEGIN
53 
54 static const char* PREAMBLE =
55     "The value of the 'id' field on every instance of the following type of "
56     "object in a model must be unique: <model>, <functionDefinition>, "
57     "<compartmentType>, <compartment>, <speciesType>, <species>, <reaction>, "
58     "<speciesReference>, <modifierSpeciesReference>, <event>, and model-wide "
59     "<parameter>s. Note that <unitDefinition> and parameters defined inside "
60     "a reaction are treated separately. (References: L2V1 Section 3.5; L2V2 "
61     "Section 3.4; L2V3 Section 3.3.)";
62 
63 
64 /*
65  * Creates a new Constraint with the given constraint id.
66  */
UniqueIdsInModel(unsigned int id,Validator & v)67 UniqueIdsInModel::UniqueIdsInModel (unsigned int id, Validator& v) :
68   UniqueIdBase(id, v)
69 {
70 }
71 
72 
73 /*
74  * Destroys this Constraint.
75  */
~UniqueIdsInModel()76 UniqueIdsInModel::~UniqueIdsInModel ()
77 {
78 }
79 
80 
81 /*
82  * @return the preamble to use when logging constraint violations.
83  */
84 const char*
getPreamble()85 UniqueIdsInModel::getPreamble ()
86 {
87   return PREAMBLE;
88 }
89 
90 
91 /*
92  * Checks that all ids on the following Model objects are unique:
93  * FunctionDefinitions, Species, Compartments, global Parameters,
94  * Reactions, and Events.
95  */
96 void
doCheck(const Model & m)97 UniqueIdsInModel::doCheck (const Model& m)
98 {
99   // from l3v2 all sbase objects may have an id
100   if (m.getLevel() == 3 && m.getVersion() > 1)
101   {
102     doAllIdCheck(m);
103   }
104   else
105   {
106     unsigned int n, size, sr, sr_size;
107 
108     checkId( m );
109 
110     size = m.getNumFunctionDefinitions();
111     for (n = 0; n < size; ++n) checkId( *m.getFunctionDefinition(n) );
112 
113     size = m.getNumCompartments();
114     for (n = 0; n < size; ++n) checkId( *m.getCompartment(n) );
115 
116     size = m.getNumSpecies();
117     for (n = 0; n < size; ++n) checkId( *m.getSpecies(n) );
118 
119     size = m.getNumParameters();
120     for (n = 0; n < size; ++n) checkId( *m.getParameter(n) );
121 
122     size = m.getNumReactions();
123     for (n = 0; n < size; ++n)
124     {
125       checkId( *m.getReaction(n) );
126 
127       sr_size = m.getReaction(n)->getNumReactants();
128       for (sr = 0; sr < sr_size; sr++)
129       {
130         checkId(*m.getReaction(n)->getReactant(sr));
131       }
132 
133       sr_size = m.getReaction(n)->getNumProducts();
134       for (sr = 0; sr < sr_size; sr++)
135       {
136         checkId(*m.getReaction(n)->getProduct(sr));
137       }
138 
139       sr_size = m.getReaction(n)->getNumModifiers();
140       for (sr = 0; sr < sr_size; sr++)
141       {
142         checkId(*m.getReaction(n)->getModifier(sr));
143       }
144 
145     }
146 
147     size = m.getNumEvents();
148     for (n = 0; n < size; ++n) checkId( *m.getEvent(n) );
149 
150     size = m.getNumCompartmentTypes();
151     for (n = 0; n < size; ++n) checkId( *m.getCompartmentType(n) );
152 
153     size = m.getNumSpeciesTypes();
154     for (n = 0; n < size; ++n) checkId( *m.getSpeciesType(n) );
155 
156   }
157   reset();
158 }
159 
160 void
doAllIdCheck(const Model & m)161 UniqueIdsInModel::doAllIdCheck (const Model& m)
162 {
163   unsigned int n, size, j, num;
164 
165   /* check any id on the sbml container */
166   doCheckId((SBase&)(*m.getSBMLDocument()));
167 
168   doCheckId( m );
169 
170   size = m.getNumFunctionDefinitions();
171   doCheckId(*m.getListOfFunctionDefinitions());
172   for (n = 0; n < size; ++n) doCheckId( *m.getFunctionDefinition(n) );
173 
174   size = m.getNumUnitDefinitions();
175   doCheckId(*m.getListOfUnitDefinitions());
176   for (n = 0; n < size; ++n)
177   {
178     // unitDefinitions have their own rule
179     const UnitDefinition *ud = m.getUnitDefinition(n);
180     //doCheckId( *ud );
181     num = ud->getNumUnits();
182     doCheckId(*ud->getListOfUnits());
183     for (j = 0; j < num; j++)
184     {
185       doCheckId(*ud->getUnit(j));
186     }
187   }
188 
189   size = m.getNumCompartments();
190   doCheckId(*m.getListOfCompartments());
191   for (n = 0; n < size; ++n) doCheckId( *m.getCompartment(n) );
192 
193   size = m.getNumSpecies();
194   doCheckId(*m.getListOfSpecies());
195   for (n = 0; n < size; ++n) doCheckId( *m.getSpecies(n) );
196 
197   size = m.getNumParameters();
198   doCheckId(*m.getListOfParameters());
199   for (n = 0; n < size; ++n) doCheckId( *m.getParameter(n) );
200 
201   size = m.getNumInitialAssignments();
202   doCheckId(*m.getListOfInitialAssignments());
203   for (n = 0; n < size; ++n) doCheckId( *m.getInitialAssignment(n) );
204 
205   size = m.getNumRules();
206   doCheckId(*m.getListOfRules());
207   for (n = 0; n < size; ++n) doCheckId( *m.getRule(n) );
208 
209   size = m.getNumConstraints();
210   doCheckId(*m.getListOfConstraints());
211   for (n = 0; n < size; ++n) doCheckId( *m.getConstraint(n) );
212 
213   size = m.getNumReactions();
214   doCheckId(*m.getListOfReactions());
215   for (n = 0; n < size; ++n)
216   {
217     const Reaction *r = m.getReaction(n);
218     doCheckId( *r );
219 
220     if (r->isSetKineticLaw())
221     {
222       doCheckId(*r->getKineticLaw());
223       // local parameters do not apply
224       num = r->getKineticLaw()->getNumParameters();
225       doCheckId(*r->getKineticLaw()->getListOfParameters());
226       //for (j = 0; j < num; j++)
227       //{
228       //  doCheckId(*r->getKineticLaw()->getParameter(j));
229       //}
230     }
231 
232     num = r->getNumReactants();
233     doCheckId(*r->getListOfReactants());
234     for (j = 0; j < num; j++)
235     {
236       doCheckId(*r->getReactant(j));
237     }
238 
239     num = r->getNumProducts();
240     doCheckId(*r->getListOfProducts());
241     for (j = 0; j < num; j++)
242     {
243       doCheckId(*r->getProduct(j));
244     }
245 
246     num = r->getNumModifiers();
247     doCheckId(*r->getListOfModifiers());
248     for (j = 0; j < num; j++)
249     {
250       doCheckId(*r->getModifier(j));
251     }
252   }
253   size = m.getNumEvents();
254   doCheckId(*m.getListOfEvents());
255   for (n = 0; n < size; ++n)
256   {
257     const Event *e = m.getEvent(n);
258     doCheckId( *e );
259 
260     if (e->isSetTrigger())
261     {
262       doCheckId( *e->getTrigger());
263     }
264 
265     if (e->isSetDelay())
266     {
267       doCheckId( *e->getDelay());
268     }
269 
270     if (e->isSetPriority())
271     {
272       doCheckId( *e->getPriority());
273     }
274 
275     num = e->getNumEventAssignments();
276     doCheckId(*e->getListOfEventAssignments());
277     for (j = 0; j < num; j++)
278     {
279       doCheckId(*e->getEventAssignment(j));
280     }
281   }
282 
283 }
284 
285 LIBSBML_CPP_NAMESPACE_END
286 /** @endcond */
287