COPASI API  4.16.103
CCopasiXMLParser.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010 - 2015 by Pedro Mendes, Virginia Tech Intellectual
2 // Properties, Inc., University of Heidelberg, and The University
3 // of Manchester.
4 // All rights reserved.
5 
6 // Copyright (C) 2008 - 2009 by Pedro Mendes, Virginia Tech Intellectual
7 // Properties, Inc., EML Research, gGmbH, University of Heidelberg,
8 // and The University of Manchester.
9 // All rights reserved.
10 
11 // Copyright (C) 2003 - 2007 by Pedro Mendes, Virginia Tech Intellectual
12 // Properties, Inc. and EML Research, gGmbH.
13 // All rights reserved.
14 
15 /**
16  * CCopasiXMLParser class.
17  * This class parses a COPASI XML file.
18  *
19  * Created for COPASI by Stefan Hoops 2003
20  * Copyright Stefan Hoops
21  */
22 
23 #include "copasi.h"
24 
25 #include "CExpat.h"
26 
27 #include "CCopasiXMLParser.h"
28 #include "CCopasiXMLInterface.h"
30 #include "function/CFunction.h"
31 #include "function/CExpression.h"
32 #include "model/CModel.h"
34 #include "report/CKeyFactory.h"
37 
38 #include "utilities/CVersion.h"
41 #include "utilities/CSlider.h"
43 #include "steadystate/CMCATask.h"
44 #include "lna/CLNATask.h"
45 #include "tssanalysis/CTSSATask.h"
46 #include "scan/CScanTask.h"
48 #include "optimization/COptTask.h"
51 #include "lyap/CLyapTask.h"
53 #include "moieties/CMoietiesTask.h"
57 #include "plot/CPlotItem.h"
59 #include "layout/CListOfLayouts.h"
61 
71 #include "copasi/layout/CLImage.h"
72 #include "copasi/layout/CLText.h"
82 
83 #define START_ELEMENT -1
84 #define UNKNOWN_ELEMENT -2
85 
86 #ifdef COPASI_TEMPLATE
87 CCopasiXMLParser::TEMPLATEElement::TEMPLATEElement(CCopasiXMLParser & parser,
88  SCopasiXMLParserCommon & common):
90 {}
91 
92 CCopasiXMLParser::TEMPLATEElement::~TEMPLATEElement()
93 {
94  pdelete(mpetcElement);
95 }
96 
97 void CCopasiXMLParser::TEMPLATEElement::start(const XML_Char *pszName,
98  const XML_Char **papszAttrs)
99 {
100  mpCurrentHandler = NULL;
101  mCurrentElement = mLastKnownElement;
102 
103  while (mpCurrentHandler == NULL)
104  {
105  mCurrentElement++; /* We should always be on the next element */
106 
107  switch (mCurrentElement)
108  {
109  case TEMPLATE:
110 
111  if (strcmp(pszName, "TEMPLATE"))
113  pszName, "TEMPLATE", mParser.getCurrentLineNumber());
114 
115  mLastKnownElement = TEMPLATE;
116 
117  // Element specific code.
118  return;
119 
120  case etc:
121 
122  if (!strcmp(pszName, "etc"))
123  {
124  /* If we do not have an etc element handler we create one. */
125  if (!mpetcElement)
126  mpetcElement = new etcElement(mParser, mCommon);
127 
128  mpCurrentHandler = mpetcElement;
129  }
130  // Optional
131  else
132  {
134  pszName, "etc", mParser.getCurrentLineNumber());
135  }
136 
137  break;
138 
139  default:
140  mCurrentElement = UNKNOWN_ELEMENT;
141  mpCurrentHandler = &mParser.mUnknownElement;
142  break;
143  }
144  }
145 
146  mParser.pushElementHandler(mpCurrentHandler);
147 
148  if (mpCurrentHandler != &mParser.mUnknownElement)
149  {
150  mLastKnownElement = mCurrentElement;
151  }
152 
153  mParser.onStartElement(pszName, papszAttrs);
154 
155  return;
156 }
157 
158 void CCopasiXMLParser::TEMPLATEElement::end(const XML_Char *pszName)
159 {
160  switch (mCurrentElement)
161  {
162  case TEMPLATE:
163 
164  if (strcmp(pszName, "TEMPLATE"))
166  pszName, "TEMPLATE", mParser.getCurrentLineNumber());
167 
168  mParser.popElementHandler();
169  mLastKnownElement = START_ELEMENT;
170 
171  /* Tell the parent element we are done. */
172  mParser.onEndElement(pszName);
173  break;
174 
175  case etc:
176 
177  if (strcmp(pszName, "etc"))
179  pszName, "etc", mParser.getCurrentLineNumber());
180 
181  // Element specific code
182 
183  break;
184 
185  case UNKNOWN_ELEMENT:
186  break;
187 
188  default:
190  pszName, "???", mParser.getCurrentLineNumber());
191  break;
192  }
193 
194  mCurrentElement = TEMPLATE;
195  return;
196 }
197 
198 #endif // COPASI_TEMPLATE
199 
201  CExpat(),
202  mCommon(),
203  mCharacterData(),
204  mCharacterDataEncoding(CCopasiXMLInterface::none),
205  mElementHandlerStack(),
206  mUnknownElement(*this, this->mCommon),
207  mCharacterDataElement(*this, this->mCommon),
208  mListOfUnsupportedAnnotationsElement(*this, this->mCommon),
209  mCommentElement(*this, this->mCommon),
210  mMiriamAnnotationElement(*this, this->mCommon)
211  // Attributes
212 {
213  create();
214 
215  mElementHandlerStack.push(new COPASIElement(*this, mCommon));
216 
217  // mCommon.pParser = this;
218  mCommon.pVersion = & version;
219  mCommon.pModel = NULL;
220  mCommon.pFunctionList = NULL;
221  mCommon.pFunction = NULL;
222  mCommon.pTaskList = NULL;
223  mCommon.pReportList = NULL;
224  mCommon.pReport = NULL;
226  mCommon.pGUI = NULL;
227 
228  mCommon.pPlotList = NULL;
230 
231  mCommon.pLayoutList = NULL;
232  mCommon.pCurrentLayout = NULL;
233  mCommon.pCompartmentGlyph = NULL;
234  mCommon.pMetaboliteGlyph = NULL;
235  mCommon.pReactionGlyph = NULL;
236  mCommon.pTextGlyph = NULL;
237  //mCommon.pAdditionalGO = NULL;
238  mCommon.pGeneralGlyph = NULL;
239  mCommon.pCurve = NULL;
240  mCommon.pLineSegment = NULL;
243  mCommon.pGradient = NULL;
244  mCommon.pLineEnding = NULL;
245  mCommon.pStyle = NULL;
246  mCommon.pGroup = NULL;
247  mCommon.pText = NULL;
249 
250  enableElementHandler(true);
251 }
252 
254 {
255  // We need to destruct the top most element on the stack since it has been
256  // allocated in the constructor.
257  if (mElementHandlerStack.empty())
258  return;
259 
260  while (mElementHandlerStack.size() > 1)
261  mElementHandlerStack.pop();
262 
263  delete mElementHandlerStack.top();
264 }
265 
266 void CCopasiXMLParser::onStartElement(const XML_Char *pszName,
267  const XML_Char **papszAttrs)
268 {
269  assert(mElementHandlerStack.size() != 0);
270  mElementHandlerStack.top()->start(pszName, papszAttrs);
271 }
272 
273 void CCopasiXMLParser::onEndElement(const XML_Char *pszName)
274 {
275  if (mElementHandlerStack.size() != 0)
276  mElementHandlerStack.top()->end(pszName);
277  else
278  return;
279 }
280 
281 #ifdef XXXX
283 {
284  long i = mParser.getCurrentByteIndex();
285 }
286 
288 {
289  long i = mParser.getCurrentByteIndex();
290 }
291 #endif // XXXX
292 
293 /**
294  * Skipped entity handler
295  * This is called in two situations:
296  * 1) An entity reference is encountered for which no declaration
297  * has been read *and* this is not an error.
298  * 2) An internal entity reference is read, but not expanded, because
299  * XML_SetDefaultHandler has been called.
300  * Note: skipped parameter entities in declarations and skipped general
301  * entities in attribute values cannot be reported, because
302  * the event would be out of sync with the reporting of the
303  * declarations or attribute values
304  * @param const XML_Char *entityName
305  * @param int is_parameter_entity
306  */
307 void CCopasiXMLParser::onSkippedEntityHandler(const XML_Char * entityName,
308  int is_parameter_entity)
309 {
310  mCharacterData += "&";
311  mCharacterData += entityName;
312  mCharacterData += ";";
313 
314  return;
315 }
316 
318 {
319  mCharacterData.erase();
321 }
322 
323 void CCopasiXMLParser::onCharacterData(const XML_Char *pszData,
324  int nLength)
325 {
326  std::string Data;
327  Data.append(pszData, nLength);
328 
330 }
331 
332 std::string CCopasiXMLParser::getCharacterData(const std::string & toBeStripped,
333  const std::string & join)
334 {
335  std::string tmp(mCharacterData);
336 
337  enableCharacterDataHandler(false); /* Resetting for future calls. */
338 
339  if (toBeStripped == "") return tmp;
340 
341  std::string::size_type Start = tmp.find_first_of(toBeStripped);
342  std::string::size_type End = 0;
343 
344  while (Start != std::string::npos)
345  {
346  End = tmp.find_first_not_of(toBeStripped, Start);
347 
348  tmp.erase(Start, End - Start);
349 
350  if (Start && End != std::string::npos)
351  {
352  tmp.insert(Start, join);
353  Start += join.length();
354  }
355 
356  Start = tmp.find_first_of(toBeStripped, Start);
357  }
358 
359  return tmp;
360 }
361 
363 {mElementHandlerStack.push(elementHandler);}
364 
366 {mElementHandlerStack.pop();}
367 
369 {mCommon.pFunctionList = pFunctionList;}
370 
372 {return mCommon.pModel;}
373 
375 {return mCommon.pReportList;}
376 
378 {return mCommon.pTaskList;}
379 
381 {return mCommon.pPlotList;}
382 
384 {mCommon.pGUI = pGUI;}
385 
387 {mCommon.pLayoutList = pLayoutList;}
388 
390 {return mCommon.pLayoutList;}
391 
393 {return dynamic_cast< const CCopasiParameterGroup * >(mCommon.pCurrentParameter);}
394 
395 const CCopasiObject * CCopasiXMLParser::getObjectFromName(const std::string & cn) const
396 {
397  const CObjectInterface * pObject = NULL;
399 
400  if (mCommon.pModel &&
401  (pObject = mCommon.pModel->getObject(CN)))
402  return static_cast< const CCopasiObject * >(pObject);
403 
404  if (mCommon.pTaskList &&
405  (pObject = mCommon.pTaskList->getObject(CN)))
406  return static_cast< const CCopasiObject * >(pObject);
407 
408  if (mCommon.pFunctionList &&
409  (pObject = mCommon.pFunctionList->getObject(CN)))
410  return static_cast< const CCopasiObject * >(pObject);
411 
412  return NULL;
413 }
414 
416  SCopasiXMLParserCommon & common):
418  mLineNumber(0)
419 {}
420 
422 {
423  deleteCurrentHandler();
424 }
425 
426 void CCopasiXMLParser::UnknownElement::start(const XML_Char * /*pszName*/ ,
427  const XML_Char ** /* papszAttrs */)
428 {
429  /* We count the level of subelements of the Unknown Element */
430  mCurrentElement++;
431 
432  if (mCurrentElement == Unknown)
433  {
434  mLineNumber = mParser.getCurrentLineNumber();
435  }
436 
437  return;
438 }
439 
440 void CCopasiXMLParser::UnknownElement::end(const XML_Char *pszName)
441 {
442  switch (mCurrentElement)
443  {
444  case Unknown:
445  mParser.popElementHandler();
446  mCurrentElement = START_ELEMENT;
447  {
449  pszName, mLineNumber);
450  }
451 
452  /* Tell the parent element we are done. */
453  mParser.onEndElement(pszName);
454  break;
455 
456  default:
457  mCurrentElement--;
458  break;
459  }
460 
461  return;
462 }
463 
465  SCopasiXMLParserCommon & common):
467 {}
468 
470 
471 void CCopasiXMLParser::COPASIElement::start(const XML_Char *pszName,
472  const XML_Char **papszAttrs)
473 {
474  mCurrentElement++; /* We should always be on the next element */
475  mpCurrentHandler = NULL;
476 
477  const char * versionMajor;
478  C_INT32 VersionMajor;
479  const char * versionMinor;
480  C_INT32 VersionMinor;
481  const char * versionDevel;
482  C_INT32 VersionDevel;
483  bool CopasiSourcesModified = true;
484 
485  switch (mCurrentElement)
486  {
487  case COPASI:
488 
489  if (!strcmp(pszName, "COPASI"))
490  {
491  versionMajor = mParser.getAttributeValue("versionMajor", papszAttrs, "0");
492  VersionMajor = strToInt(versionMajor);
493  versionMinor = mParser.getAttributeValue("versionMinor", papszAttrs, "0");
494  VersionMinor = strToInt(versionMinor);
495  versionDevel = mParser.getAttributeValue("versionDevel", papszAttrs, "0");
496  VersionDevel = strToInt(versionDevel);
497  CopasiSourcesModified = mParser.toBool(mParser.getAttributeValue("copasiSourcesModified", papszAttrs, "true"));
498 
499  mCommon.pVersion->setVersion(VersionMajor, VersionMinor, VersionDevel, CopasiSourcesModified);
500 
501  return;
502  }
503  // We may have a configuration file which starts with a parameter group
504  else if (!strcmp(pszName, "ParameterGroup"))
505  {
506  mpCurrentHandler = new ParameterGroupElement(mParser, mCommon);
507  }
508  else
509  {
510  mpCurrentHandler = &mParser.mUnknownElement;
511 
513  pszName, "COPASI", mParser.getCurrentLineNumber());
514  }
515 
516  break;
517 
518  case ListOfFunctions:
519 
520  if (!strcmp(pszName, "ListOfFunctions"))
521  mpCurrentHandler = new ListOfFunctionsElement(mParser, mCommon);
522 
523  break;
524 
525  case Model:
526 
527  if (!strcmp(pszName, "Model"))
528  mpCurrentHandler = new ModelElement(mParser, mCommon);
529 
530  break;
531 
532  case ListOfTasks:
533 
534  if (!strcmp(pszName, "ListOfTasks"))
535  mpCurrentHandler = new ListOfTasksElement(mParser, mCommon);
536 
537  break;
538 
539  case ListOfReports:
540 
541  if (!strcmp(pszName, "ListOfReports"))
542  mpCurrentHandler = new ListOfReportsElement(mParser, mCommon);
543 
544  break;
545 
546  case ListOfPlots:
547 
548  if (!strcmp(pszName, "ListOfPlots"))
549  mpCurrentHandler = new ListOfPlotsElement(mParser, mCommon);
550 
551  break;
552 
553  case GUI:
554 
555  if (!strcmp(pszName, "GUI"))
556  {
557  if (mCommon.pGUI)
558  mpCurrentHandler = new GUIElement(mParser, mCommon);
559  else
560  mpCurrentHandler = &mParser.mUnknownElement;
561  }
562 
563  break;
564 
565  case ListOfLayouts:
566 
567  if (!strcmp(pszName, "ListOfLayouts"))
568  mpCurrentHandler = new ListOfLayoutsElement(mParser, mCommon);
569 
570  break;
571 
572  case SBMLReference:
573 
574  if (!strcmp(pszName, "SBMLReference"))
575  mpCurrentHandler = new SBMLReferenceElement(mParser, mCommon);
576 
577  break;
578 
579  default:
580  mpCurrentHandler = &mParser.mUnknownElement;
581  break;
582  }
583 
584  if (mpCurrentHandler)
585  mParser.pushElementHandler(mpCurrentHandler);
586 
587  mParser.onStartElement(pszName, papszAttrs);
588 
589  return;
590 }
591 
592 void CCopasiXMLParser::COPASIElement::end(const XML_Char * pszName)
593 {
594  if (!strcmp(pszName, "COPASI"))
595  {
596  mCurrentElement = START_ELEMENT;
597 
598  // We need to handle the unmapped parameters of type key.
599  std::vector< std::string >::iterator it = mCommon.UnmappedKeyParameters.begin();
600  std::vector< std::string >::iterator end = mCommon.UnmappedKeyParameters.end();
601 
602  for (; it != end; ++it)
603  {
604  CCopasiParameter * pParameter =
605  dynamic_cast< CCopasiParameter * >(CCopasiRootContainer::getKeyFactory()->get(*it));
606 
607  if (pParameter != NULL &&
608  pParameter->getType() == CCopasiParameter::KEY)
609  {
610  CCopasiObject * pObject =
611  mCommon.KeyMap.get(*pParameter->getValue().pKEY);
612 
613  if (pObject != NULL)
614  pParameter->setValue(pObject->getKey());
615  else
616  pParameter->setValue(std::string(""));
617  }
618  }
619 
620  // We need to remove the no longer needed expression "Objective Function" from the function list.
621  if (mCommon.pFunctionList != NULL &&
622  mCommon.pFunctionList->getIndex("Objective Function") != C_INVALID_INDEX)
623  {
624  mCommon.pFunctionList->remove("Objective Function");
625  }
626 
627  return;
628  }
629 
630  if (!strcmp(pszName, "ParameterGroup"))
631  {
632  mCurrentElement = START_ELEMENT;
633  }
634  else if (!strcmp(pszName, "GUI") && mCommon.pGUI == NULL)
635  {
637  }
638 
639  deleteCurrentHandler();
640 
641  //TODO why no case statement with error checking (like in other elements)?
642 
643  return;
644 }
645 
647  SCopasiXMLParserCommon & common):
649 {}
650 
652 {
653  deleteCurrentHandler();
654 }
655 
657  const XML_Char **papszAttrs)
658 {
659  mCurrentElement++; /* We should always be on the next element */
660 
661  switch (mCurrentElement)
662  {
663  case ListOfFunctions:
664 
665  if (strcmp(pszName, "ListOfFunctions"))
667  pszName, "ListOfFunctions", mParser.getCurrentLineNumber());
668 
669  if (!mCommon.pFunctionList)
671 
672  break;
673 
674  case Function:
675 
676  if (strcmp(pszName, "Function"))
678  pszName, "Function", mParser.getCurrentLineNumber());
679 
680  /* If we do not have a function element handler we create one. */
681  if (!mpCurrentHandler)
682  mpCurrentHandler = new FunctionElement(mParser, mCommon);
683 
684  /* Push the Function element handler on the stack and call it. */
685  mParser.pushElementHandler(mpCurrentHandler);
686  mpCurrentHandler->start(pszName, papszAttrs);
687  break;
688 
689  default:
690  mLastKnownElement = mCurrentElement - 1;
691  mCurrentElement = UNKNOWN_ELEMENT;
692  mParser.pushElementHandler(&mParser.mUnknownElement);
693  mParser.onStartElement(pszName, papszAttrs);
694  break;
695  }
696 
697  return;
698 }
699 
701 {
702  switch (mCurrentElement)
703  {
704  case ListOfFunctions:
705 
706  if (strcmp(pszName, "ListOfFunctions"))
708  pszName, "ListOfFunctions", mParser.getCurrentLineNumber());
709 
710  mParser.popElementHandler();
711  mCurrentElement = START_ELEMENT;
712  {
713  size_t i, imax = mCommon.pFunctionList->size();
714 
715  for (i = imax - 1; i != C_INVALID_INDEX; i--)
716  {
717  CFunction * pFunction =
718  dynamic_cast<CFunction *>((*mCommon.pFunctionList)[i]);
719 
720  if (pFunction && !pFunction->compile())
721  {
723  pFunction->getObjectName().c_str(),
724  mParser.getCurrentLineNumber());
725  // We can keep the function as the compile is later checked again.
726  // mCommon.pFunctionList->CCopasiVector< CEvaluationTree >::remove(i);
727  }
728  }
729  }
730 
731  /* Tell the parent element we are done. */
732  mParser.onEndElement(pszName);
733  break;
734 
735  case Function:
736 
737  if (strcmp(pszName, "Function"))
739  pszName, "Function", mParser.getCurrentLineNumber());
740 
741  mCurrentElement = ListOfFunctions;
742  break;
743 
744  case UNKNOWN_ELEMENT:
745  mCurrentElement = mLastKnownElement;
746  break;
747 
748  default:
750  pszName, "???", mParser.getCurrentLineNumber());
751  break;
752  }
753 
754  return;
755 }
756 
758  SCopasiXMLParserCommon & common):
760  mpMathMLElement(NULL),
761  mpListOfParameterDescriptionsElement(NULL)
762 {}
763 
765 {
766  pdelete(mpMathMLElement);
767  pdelete(mpListOfParameterDescriptionsElement);
768 }
769 
770 void CCopasiXMLParser::FunctionElement::start(const XML_Char *pszName,
771  const XML_Char **papszAttrs)
772 {
773  const char * type;
775  const char * Name;
776  const char * Reversible;
777  size_t Index;
778 
779  mpCurrentHandler = NULL;
780  mCurrentElement = mLastKnownElement;
781 
782  while (mpCurrentHandler == NULL)
783  {
784  mCurrentElement++; /* We should always be on the next element */
785  CEvaluationTree* pEvaluationTree = NULL;
786 
787  switch (mCurrentElement)
788  {
789  case Function:
790 
791  if (strcmp(pszName, "Function"))
793  pszName, "Function", mParser.getCurrentLineNumber());
794 
795  mKey = mParser.getAttributeValue("key", papszAttrs);
796  Name = mParser.getAttributeValue("name", papszAttrs);
797  type = mParser.getAttributeValue("type", papszAttrs);
799 
800  Reversible = mParser.getAttributeValue("reversible", papszAttrs, false);
801 
802  if (!Reversible) // We may have an old file format using positive
803  Reversible = mParser.getAttributeValue("positive", papszAttrs, "unspecified");
804 
805  mLastKnownElement = Function;
806 
809  mExistingFunctionIndex.clear();
810 
811  pEvaluationTree = CEvaluationTree::create(Type);
812 
813  if (Type == CEvaluationTree::Expression)
814  {
815  mCommon.pFunction = NULL;
816 
817  mCommon.mpExpression = static_cast< CExpression * >(pEvaluationTree);
819  }
820  else
821  {
822  mCommon.mpExpression = NULL;
823 
824  mCommon.pFunction = static_cast<CFunction *>(pEvaluationTree);
826 
827  if (!strcmp(Reversible, "true"))
829  else if (!strcmp(Reversible, "false"))
831  else
833 
834  Index = mCommon.pFunctionList->getIndex(Name);
835 
836  if (Index != C_INVALID_INDEX) // A function with that name exists.
837  {
838  mExistingFunctionIndex.insert(Index);
839 
840  switch ((*mCommon.pFunctionList)[Index]->getType())
841  {
843 
844  if (Type == CEvaluationTree::MassAction)
845  {
849  }
850  else
851  {
852  size_t Counter = 0;
853  std::string NewName;
854 
855  while (true)
856  {
857  Counter++;
858  std::ostringstream ss;
859  ss << Name << " [" << Counter << "]";
860  NewName = ss.str();
861  Index = mCommon.pFunctionList->getIndex(NewName);
862 
863  if (Index == C_INVALID_INDEX)
864  break;
865 
866  mExistingFunctionIndex.insert(Index);
867  }
868 
869  mCommon.pFunction->setObjectName(NewName);
870  }
871 
872  break;
873 
875 
876  if (Type == CEvaluationTree::PreDefined)
877  {
881  }
882  else
883  {
884  size_t Counter = 0;
885  std::string NewName;
886 
887  while (true)
888  {
889  Counter++;
890  std::ostringstream ss;
891  ss << Name << " [" << Counter << "]";
892  NewName = ss.str();
893  Index = mCommon.pFunctionList->getIndex(NewName);
894 
895  if (Index == C_INVALID_INDEX)
896  break;
897 
898  mExistingFunctionIndex.insert(Index);
899  }
900 
901  mCommon.pFunction->setObjectName(NewName);
902  }
903 
904  break;
905 
908  // Create a unique name
909  {
910  size_t Counter = 0;
911  std::string NewName;
912 
913  while (true)
914  {
915  Counter++;
916  std::ostringstream ss;
917  ss << Name << " [" << Counter << "]";
918  NewName = ss.str();
919  Index = mCommon.pFunctionList->getIndex(NewName);
920 
921  if (Index == C_INVALID_INDEX)
922  break;
923 
924  mExistingFunctionIndex.insert(Index);
925  }
926 
927  mCommon.pFunction->setObjectName(NewName);
928  }
929 
930  break;
931 
932  default:
933  break;
934  }
935  }
936  }
937 
938  return;
939 
940  case MiriamAnnotation:
941 
942  if (!strcmp(pszName, "MiriamAnnotation"))
943  mpCurrentHandler = &mParser.mMiriamAnnotationElement;
944 
945  break;
946 
947  case Comment:
948 
949  if (!strcmp(pszName, "Comment"))
950  mpCurrentHandler = &mParser.mCommentElement;
951 
952  break;
953 
954  case ListOfUnsupportedAnnotations:
955 
956  if (!strcmp(pszName, "ListOfUnsupportedAnnotations"))
957  mpCurrentHandler = &mParser.mListOfUnsupportedAnnotationsElement;
958 
959  break;
960 
961  case Expression:
962 
963  if (!strcmp(pszName, "Expression"))
964  mpCurrentHandler = &mParser.mCharacterDataElement;
965  else if (!strcmp(pszName, "MathML"))
966  {
967  /* If we do not have a MathML element handler we create one. */
968  if (!mpMathMLElement)
969  mpMathMLElement = new MathMLElement(mParser, mCommon);
970 
971  mCurrentElement = MathML;
972  mpCurrentHandler = mpMathMLElement;
973  }
974  else
976  pszName, "Expression", mParser.getCurrentLineNumber());
977 
978  break;
979 
980  case ListOfParameterDescriptions:
981 
982  if (strcmp(pszName, "ListOfParameterDescriptions"))
984  pszName, "ListOfParameterDescriptions", mParser.getCurrentLineNumber());
985 
986  /* If we do not have a ListOfParameterDescriptions element handler we create one. */
987  if (!mpListOfParameterDescriptionsElement)
988  mpListOfParameterDescriptionsElement = new ListOfParameterDescriptionsElement(mParser, mCommon);
989 
990  /* Push the ListOfParameterDescriptions element handler on the stack and call it. */
991  mpCurrentHandler = mpListOfParameterDescriptionsElement;
992  break;
993 
994  default:
995  mCurrentElement = UNKNOWN_ELEMENT;
996  mpCurrentHandler = &mParser.mUnknownElement;
997  break;
998  }
999  }
1000 
1001  mParser.pushElementHandler(mpCurrentHandler);
1002 
1003  if (mpCurrentHandler != &mParser.mUnknownElement)
1004  {
1005  mLastKnownElement = mCurrentElement;
1006  }
1007 
1008  mParser.onStartElement(pszName, papszAttrs);
1009 }
1010 
1011 void CCopasiXMLParser::FunctionElement::end(const XML_Char *pszName)
1012 {
1013  switch (mCurrentElement)
1014  {
1015  case Function:
1016 
1017  if (strcmp(pszName, "Function"))
1019  pszName, "Function", mParser.getCurrentLineNumber());
1020 
1021  mLastKnownElement = START_ELEMENT;
1022  mParser.popElementHandler();
1023 
1024  /* Tell the parent element we are done. */
1025  mParser.onEndElement(pszName);
1026 
1027  if (mCommon.pFunction != NULL)
1028  {
1030  {
1031  // TODOWe need to check whether any existing function with the same
1032  // name is identical
1033 
1034  std::set< size_t >::const_iterator it = mExistingFunctionIndex.begin();
1035  std::set< size_t >::const_iterator end = mExistingFunctionIndex.end();
1036 
1037  for (; it != end; ++it)
1038  {
1039  CFunction * pFunction = (*mCommon.pFunctionList)[*it];
1040 
1041  if (*pFunction == *mCommon.pFunction)
1042  {
1045 
1046  break;
1047  }
1048  }
1049 
1050  /* We have a new function and add it to the list */
1051  if (it == end)
1052  {
1054  }
1055  }
1056 
1057  addFix(mKey , mCommon.pFunction);
1058 
1059  std::map< size_t, std::string >::const_iterator it = mCommon.mFunctionParameterKeyMap.begin();
1060  std::map< size_t, std::string >::const_iterator end = mCommon.mFunctionParameterKeyMap.end();
1061 
1062  for (; it != end; ++it)
1063  {
1064  addFix(it->second, mCommon.pFunction->getVariables()[it->first]);
1065  }
1066  }
1067 
1068  break;
1069 
1070  case MiriamAnnotation:
1071 
1072  if (strcmp(pszName, "MiriamAnnotation"))
1074  pszName, "MiriamAnnotation", mParser.getCurrentLineNumber());
1075 
1076  if (mCommon.pFunction != NULL)
1077  {
1079  mCommon.CharacterData = "";
1080  }
1081 
1082  break;
1083 
1084  case Comment:
1085 
1086  if (strcmp(pszName, "Comment"))
1088  pszName, "Comment", mParser.getCurrentLineNumber());
1089 
1090  if (mCommon.pFunction != NULL)
1091  {
1093  mCommon.CharacterData = "";
1094  }
1095 
1096  break;
1097 
1098  case ListOfUnsupportedAnnotations:
1099 
1100  if (strcmp(pszName, "ListOfUnsupportedAnnotations"))
1102  pszName, "ListOfUnsupportedAnnotations", mParser.getCurrentLineNumber());
1103 
1104  if (mCommon.pFunction != NULL)
1105  {
1106  mCommon.pFunction->getUnsupportedAnnotations() = mParser.mListOfUnsupportedAnnotationsElement.getUnsupportedAnnotations();
1107  }
1108 
1109  break;
1110 
1111  case Expression:
1112 
1113  if (strcmp(pszName, "Expression"))
1115  pszName, "Expression", mParser.getCurrentLineNumber());
1116 
1117  if (mCommon.pFunction != NULL)
1118  {
1120  {
1121  // do not yet compile the function as it might depend on elements not
1122  // read yet
1124  }
1125  }
1126  else if (mCommon.mpExpression != NULL)
1127  {
1129  }
1130 
1131  break;
1132 
1133  case ListOfParameterDescriptions:
1134 
1135  if (strcmp(pszName, "ListOfParameterDescriptions"))
1137  pszName, "ListOfParameterDescriptions", mParser.getCurrentLineNumber());
1138 
1139  break;
1140 
1141  case MathML:
1142 
1143  if (strcmp(pszName, "MathML"))
1145  pszName, "MathML", mParser.getCurrentLineNumber());
1146 
1147  if (mCommon.pFunction != NULL)
1148  {
1151  }
1152  else if (mCommon.mpExpression != NULL)
1153  {
1155  }
1156 
1157  // MathML is in place of Expression in old CopasiML files.
1158  mLastKnownElement = Expression;
1159  break;
1160 
1161  case UNKNOWN_ELEMENT:
1162  break;
1163 
1164  default:
1166  pszName, "???", mParser.getCurrentLineNumber());
1167  break;
1168  }
1169 
1170  mCurrentElement = Function;
1171 
1172  return;
1173 }
1174 
1176  SCopasiXMLParserCommon & common):
1178 {}
1179 
1181 {
1182  deleteCurrentHandler();
1183 }
1184 
1185 void CCopasiXMLParser::MathMLElement::start(const XML_Char *pszName,
1186  const XML_Char **papszAttrs)
1187 {
1188  mCurrentElement++; /* We should always be on the next element */
1189 
1190  switch (mCurrentElement)
1191  {
1192  case MathML:
1193 
1194  if (strcmp(pszName, "MathML"))
1196  pszName, "MathML", mParser.getCurrentLineNumber());
1197 
1198  break;
1199 
1200  case Text:
1201 
1202  if (strcmp(pszName, "Text"))
1204  pszName, "Text", mParser.getCurrentLineNumber());
1205 
1206  /* If we do not have a function element handler we create one. */
1207  if (!mpCurrentHandler)
1208  mpCurrentHandler = new CharacterDataElement(mParser, mCommon);
1209 
1210  /* Push the Function element handler on the stack and call it. */
1211  mParser.pushElementHandler(mpCurrentHandler);
1212  mpCurrentHandler->start(pszName, papszAttrs);
1213  break;
1214 
1215  default:
1216  mLastKnownElement = mCurrentElement - 1;
1217  mCurrentElement = UNKNOWN_ELEMENT;
1218  mParser.pushElementHandler(&mParser.mUnknownElement);
1219  mParser.onStartElement(pszName, papszAttrs);
1220  break;
1221  }
1222 
1223  return;
1224 }
1225 
1226 void CCopasiXMLParser::MathMLElement::end(const XML_Char *pszName)
1227 {
1228  switch (mCurrentElement)
1229  {
1230  case MathML:
1231 
1232  if (strcmp(pszName, "MathML"))
1234  pszName, "MathML", mParser.getCurrentLineNumber());
1235 
1236  mParser.popElementHandler();
1237  mCurrentElement = START_ELEMENT;
1238 
1239  /* Tell the parent element we are done. */
1240  mParser.onEndElement(pszName);
1241  break;
1242 
1243  case Text:
1244 
1245  if (strcmp(pszName, "Text"))
1247  pszName, "Text", mParser.getCurrentLineNumber());
1248 
1249  mCurrentElement = MathML;
1250 
1251  break;
1252 
1253  case UNKNOWN_ELEMENT:
1254  mCurrentElement = mLastKnownElement;
1255  break;
1256 
1257  default:
1259  pszName, "???", mParser.getCurrentLineNumber());
1260  break;
1261  }
1262 }
1263 
1265  SCopasiXMLParserCommon & common):
1267 {}
1268 
1270 {}
1271 
1273  const XML_Char ** papszAttrs)
1274 {
1275  mCurrentElement++; /* We should always be on the next element */
1276 
1277  switch (mCurrentElement)
1278  {
1279  case CharacterData:
1280  mCurrentElementName = pszName;
1281  mParser.enableCharacterDataHandler(true);
1282  break;
1283 
1284  default:
1285  mLastKnownElement = mCurrentElement - 1;
1286  mCurrentElement = UNKNOWN_ELEMENT;
1287  mParser.pushElementHandler(&mParser.mUnknownElement);
1288  mParser.onStartElement(pszName, papszAttrs);
1289  break;
1290  }
1291 
1292  return;
1293 }
1294 
1295 void CCopasiXMLParser::CharacterDataElement::end(const XML_Char *pszName)
1296 {
1297  switch (mCurrentElement)
1298  {
1299  case CharacterData:
1300 
1301  if (strcmp(pszName, mCurrentElementName.c_str()))
1303  pszName, mCurrentElementName.c_str(), mParser.getCurrentLineNumber());
1304 
1305  mParser.popElementHandler();
1306  mCurrentElement = START_ELEMENT;
1307  mCommon.CharacterData = mParser.getCharacterData("\x0a\x0d\t", "");
1308  {
1309  std::string::size_type Start = mCommon.CharacterData.find_first_not_of(" ");
1310 
1311  if (Start == std::string::npos)
1312  mCommon.CharacterData = "";
1313  else
1314  {
1315  std::string::size_type End = mCommon.CharacterData.find_last_not_of(" ");
1316 
1317  if (End == std::string::npos)
1318  mCommon.CharacterData = mCommon.CharacterData.substr(Start);
1319  else
1320  mCommon.CharacterData = mCommon.CharacterData.substr(Start, End - Start + 1);
1321  }
1322  }
1323  /* Tell the parent element we are done. */
1324  mParser.onEndElement(pszName);
1325  break;
1326 
1327  case UNKNOWN_ELEMENT:
1328  mCurrentElement = mLastKnownElement;
1329  break;
1330 
1331  default:
1333  pszName, "???", mParser.getCurrentLineNumber());
1334  break;
1335  }
1336 }
1337 
1339  SCopasiXMLParserCommon & common):
1341 {}
1342 
1344 {
1345  deleteCurrentHandler();
1346 }
1347 
1349  const XML_Char **papszAttrs)
1350 {
1351  mCurrentElement++; /* We should always be on the next element */
1352 
1353  switch (mCurrentElement)
1354  {
1355  case ListOfParameterDescriptions:
1356 
1358 
1359  if (strcmp(pszName, "ListOfParameterDescriptions"))
1361  pszName, "ListOfParameterDescriptions", mParser.getCurrentLineNumber());
1362 
1363  if (mpCurrentHandler) mpCurrentHandler->reset();
1364 
1365  break;
1366 
1367  case ParameterDescription:
1368 
1369  if (strcmp(pszName, "ParameterDescription"))
1371  pszName, "ParameterDescription", mParser.getCurrentLineNumber());
1372 
1373  /* If we do not have a ParameterDescription element handler we create one. */
1374  if (!mpCurrentHandler)
1375  mpCurrentHandler = new ParameterDescriptionElement(mParser, mCommon);
1376 
1377  /* Push the ParameterDescription element handler on the stack and call it. */
1378  mParser.pushElementHandler(mpCurrentHandler);
1379  mpCurrentHandler->start(pszName, papszAttrs);
1380  break;
1381 
1382  default:
1383  mLastKnownElement = mCurrentElement - 1;
1384  mCurrentElement = UNKNOWN_ELEMENT;
1385  mParser.pushElementHandler(&mParser.mUnknownElement);
1386  mParser.onStartElement(pszName, papszAttrs);
1387  break;
1388  }
1389 
1390  return;
1391 }
1392 
1394 {
1395  switch (mCurrentElement)
1396  {
1397  case ListOfParameterDescriptions:
1398 
1399  if (strcmp(pszName, "ListOfParameterDescriptions"))
1401  pszName, "ListOfParameterDescriptions", mParser.getCurrentLineNumber());
1402 
1403  mParser.popElementHandler();
1404  mCurrentElement = START_ELEMENT;
1405 
1406  // We need to remove all parameters which have been temporarily added to the list of variables
1407  {
1408  CFunction * pFunction = dynamic_cast<CFunction *>(mCommon.pFunction);
1409 
1410  if (pFunction)
1411  {
1412  CFunctionParameters & Variables = pFunction->getVariables();
1413  size_t i = Variables.size() - 1;
1414 
1415  for (; i != C_INVALID_INDEX && Variables[i]->getUsage() == CFunctionParameter::TEMPORARY; i--)
1416  Variables.remove(Variables[i]->getObjectName());
1417  }
1418  }
1419  /* Tell the parent element we are done. */
1420  mParser.onEndElement(pszName);
1421  break;
1422 
1423  case ParameterDescription:
1424 
1425  if (strcmp(pszName, "ParameterDescription"))
1427  pszName, "ParameterDescription", mParser.getCurrentLineNumber());
1428 
1429  mCurrentElement = ListOfParameterDescriptions;
1430  break;
1431 
1432  case UNKNOWN_ELEMENT:
1433  mCurrentElement = mLastKnownElement;
1434  break;
1435 
1436  default:
1438  pszName, "???", mParser.getCurrentLineNumber());
1439  break;
1440  }
1441 
1442  return;
1443 }
1444 
1446  SCopasiXMLParserCommon & common):
1448  mOrder(0)
1449 {}
1450 
1452 {
1453  deleteCurrentHandler();
1454 }
1455 
1457  const XML_Char **papszAttrs)
1458 {
1459  const char * Key;
1460  const char * Name;
1461  const char * order;
1462  unsigned C_INT32 Order;
1463  const char * role; /*substrate, product, modifier, constant, other*/
1465  const char * minOccurs;
1466  unsigned C_INT32 MinOccurs;
1467  const char * maxOccurs;
1468  unsigned C_INT32 MaxOccurs;
1469 
1470  mCurrentElement++; /* We should always be on the next element */
1471 
1472  //std::string Usage[] = {"SUBSTRATE", "PRODUCT", "MODIFIER", "PARAMETER"};
1473  CFunctionParameter * pParm = NULL;
1474  CFunction * pFunction = dynamic_cast<CFunction *>(mCommon.pFunction);
1475 
1476  if (!pFunction) mCurrentElement++;
1477 
1478  switch (mCurrentElement)
1479  {
1480  case ParameterDescription:
1481 
1482  if (strcmp(pszName, "ParameterDescription"))
1484  pszName, "ParameterDescription", mParser.getCurrentLineNumber());
1485 
1486  Key = mParser.getAttributeValue("key", papszAttrs);
1487  Name = mParser.getAttributeValue("name", papszAttrs);
1488 
1489  order = mParser.getAttributeValue("order", papszAttrs);
1490  Order = (unsigned C_INT32) atoi(order);
1491 
1492  role = mParser.getAttributeValue("role", papszAttrs);
1493  Role = CFunctionParameter::xmlRole2Enum(role);
1494  //if (Role == "") fatalError();
1495 
1496  minOccurs = mParser.getAttributeValue("minOccurs", papszAttrs, "1");
1497  MinOccurs = strToUnsignedInt(minOccurs);
1498 
1499  maxOccurs = mParser.getAttributeValue("maxOccurs", papszAttrs , "1");
1500 
1501  if (std::string("unbounded") == std::string(maxOccurs))
1502  MaxOccurs = (unsigned C_INT32) - 1;
1503  else
1504  MaxOccurs = strToUnsignedInt(maxOccurs);
1505 
1507  {
1508  addFix(Key, pFunction->getVariables()[Name]);
1509  }
1510  else
1511  {
1512  // If we are here we have a user defined function.
1513  // We need to check whether the variable exists within the function.
1515  size_t Index =
1516  pFunction->getVariables().findParameterByName(Name, DataType);
1517 
1518  bool isUsed = true;
1519 
1520  if (Index == C_INVALID_INDEX)
1521  {
1522  // We add the missing parameter and mark it as unused.
1523  pFunction->getVariables().add(Name,
1525  Role);
1526 
1527  Index = pFunction->getVariables().findParameterByName(Name, DataType);
1528  isUsed = false;
1529  }
1530 
1531  // Make sure that we have enough parameter to swap
1532  size_t Counter = 0;
1533 
1534  while (Order >= pFunction->getVariables().size())
1535  {
1536  std::string NewName = StringPrint("TMP_%d", Counter++);
1537 
1538  while (!pFunction->getVariables().add(NewName,
1541 
1542  NewName = StringPrint("TMP_%d", Counter++);
1543  }
1544 
1545  // Assure that the order is correct
1546  if (Order != Index)
1547  pFunction->getVariables().swap(Order, Index);
1548 
1549  pParm = pFunction->getVariables()[Order];
1550  pParm->setObjectName(Name);
1551  pParm->setUsage(Role);
1552  pParm->setIsUsed(isUsed);
1553 
1554  if (MaxOccurs == 1 && MinOccurs == 1)
1556  else
1558 
1559  mCommon.mFunctionParameterKeyMap[Order] = Key;
1560  }
1561 
1562  break;
1563 
1564  default:
1565  mLastKnownElement = mCurrentElement - 1;
1566  mCurrentElement = UNKNOWN_ELEMENT;
1567  mParser.pushElementHandler(&mParser.mUnknownElement);
1568  mParser.onStartElement(pszName, papszAttrs);
1569  break;
1570  }
1571 
1572  return;
1573 }
1574 
1576 {
1577  switch (mCurrentElement)
1578  {
1579  case ParameterDescription:
1580 
1581  if (strcmp(pszName, "ParameterDescription"))
1583  pszName, "ParameterDescription", mParser.getCurrentLineNumber());
1584 
1585  mParser.popElementHandler();
1586  mCurrentElement = START_ELEMENT;
1587 
1588  /* Tell the parent element we are done. */
1589  mParser.onEndElement(pszName);
1590  break;
1591 
1592  case UNKNOWN_ELEMENT:
1593  mCurrentElement = mLastKnownElement;
1594  break;
1595 
1596  default:
1598  pszName, "???", mParser.getCurrentLineNumber());
1599  break;
1600  }
1601 
1602  return;
1603 }
1604 
1606 {mOrder = 0;}
1607 
1609  SCopasiXMLParserCommon & common):
1611 {}
1612 
1614 {
1615  deleteCurrentHandler();
1616 }
1617 
1618 void CCopasiXMLParser::ModelElement::start(const XML_Char *pszName,
1619  const XML_Char **papszAttrs)
1620 {
1621  const char * Name;
1622  const char * timeUnit;
1623  CModel::TimeUnit TimeUnit;
1624  const char * volumeUnit;
1625  CModel::VolumeUnit VolumeUnit;
1626  const char * areaUnit;
1627  CModel::AreaUnit AreaUnit;
1628  const char * lengthUnit;
1629  CModel::LengthUnit LengthUnit;
1630  const char * quantityUnit;
1631  CModel::QuantityUnit QuantityUnit;
1632  CModel::ModelType ModelType;
1633  C_FLOAT64 Avogadro;
1634 
1635  mpCurrentHandler = NULL;
1636  mCurrentElement++; /* We should always be on the next element */
1637 
1638  switch (mCurrentElement)
1639  {
1640  case Model:
1641 
1642  if (strcmp(pszName, "Model"))
1644  pszName, "Model", mParser.getCurrentLineNumber());
1645 
1646  mKey = mParser.getAttributeValue("key", papszAttrs);
1647  Name = mParser.getAttributeValue("name", papszAttrs);
1648 
1649  timeUnit = mParser.getAttributeValue("timeUnit", papszAttrs);
1650  TimeUnit = toEnum(timeUnit, CModel::TimeUnitNames, CModel::OldMinute);
1651 
1652  if (TimeUnit == CModel::OldMinute)
1653  {
1654  if (strcmp(timeUnit, "m"))
1655  TimeUnit = CModel::s;
1656  else
1657  TimeUnit = CModel::min;
1658  }
1659 
1660  volumeUnit = mParser.getAttributeValue("volumeUnit", papszAttrs);
1661  VolumeUnit = toEnum(volumeUnit, CModel::VolumeUnitNames, CModel::ml);
1662 
1663  //the next 2 attributes are introduced in Build 31, they have a default for
1664  //reading older cps files
1665  areaUnit = mParser.getAttributeValue("areaUnit", papszAttrs, "m\xc2\xb2");
1666  AreaUnit = toEnum(areaUnit, CModel::AreaUnitNames, CModel::m2);
1667 
1668  lengthUnit = mParser.getAttributeValue("lengthUnit", papszAttrs, "m");
1669  LengthUnit = toEnum(lengthUnit, CModel::LengthUnitNames, CModel::m);
1670 
1671  quantityUnit = mParser.getAttributeValue("quantityUnit", papszAttrs);
1672  QuantityUnit = toEnum(quantityUnit, CModel::QuantityUnitNames, CModel::OldXML);
1673 
1674  if (QuantityUnit == CModel::OldXML)
1675  QuantityUnit = toEnum(quantityUnit, CModel::QuantityUnitOldXMLNames, CModel::mMol);
1676 
1677  ModelType = toEnum(mParser.getAttributeValue("type", papszAttrs, "deterministic"),
1679 
1680  Avogadro = CCopasiXMLInterface::DBL(mParser.getAttributeValue("avogadroConstant", papszAttrs, "6.0221415e23"));
1681 
1683 
1684  // We remove the default parameter set:
1685  mCommon.pModel->getModelParameterSets().CCopasiVector< CModelParameterSet >::remove((size_t) 0);
1686 
1687  addFix(mKey, mCommon.pModel);
1688  mCommon.pModel->setObjectName(Name);
1689  mCommon.pModel->setTimeUnit(TimeUnit);
1690  mCommon.pModel->setVolumeUnit(VolumeUnit);
1691  mCommon.pModel->setAreaUnit(AreaUnit);
1692  mCommon.pModel->setLengthUnit(LengthUnit);
1693  mCommon.pModel->setQuantityUnit(QuantityUnit);
1694  mCommon.pModel->setModelType(ModelType);
1695  mCommon.pModel->setAvogadro(Avogadro);
1696 
1697  return;
1698  break;
1699 
1700  case MiriamAnnotation:
1701 
1702  if (!strcmp(pszName, "MiriamAnnotation"))
1703  {
1704  mpCurrentHandler = &mParser.mMiriamAnnotationElement;
1705  mLastKnownElement = mCurrentElement;
1706  }
1707 
1708  break;
1709 
1710  case Comment:
1711 
1712  if (!strcmp(pszName, "Comment"))
1713  {
1714  mpCurrentHandler = &mParser.mCommentElement;
1715  mLastKnownElement = mCurrentElement;
1716  }
1717 
1718  break;
1719 
1720  case ListOfUnsupportedAnnotations:
1721 
1722  if (!strcmp(pszName, "ListOfUnsupportedAnnotations"))
1723  {
1724  mpCurrentHandler = &mParser.mListOfUnsupportedAnnotationsElement;
1725  mLastKnownElement = mCurrentElement;
1726  }
1727 
1728  break;
1729 
1730  case InitialExpression:
1731 
1732  if (!strcmp(pszName, "InitialExpression"))
1733  {
1734  mpCurrentHandler = &mParser.mCharacterDataElement;
1735  mLastKnownElement = mCurrentElement;
1736  }
1737 
1738  break;
1739 
1740  case ListOfCompartments:
1741 
1742  if (!strcmp(pszName, "ListOfCompartments"))
1743  {
1744  mpCurrentHandler = new ListOfCompartmentsElement(mParser, mCommon);
1745  mLastKnownElement = mCurrentElement;
1746  }
1747 
1748  break;
1749 
1750  case ListOfMetabolites:
1751 
1752  if (!strcmp(pszName, "ListOfMetabolites"))
1753  {
1754  mpCurrentHandler = new ListOfMetabolitesElement(mParser, mCommon);
1755  mLastKnownElement = mCurrentElement;
1756  }
1757 
1758  break;
1759 
1760  case ListOfModelValues:
1761 
1762  if (!strcmp(pszName, "ListOfModelValues"))
1763  {
1764  mpCurrentHandler = new ListOfModelValuesElement(mParser, mCommon);
1765  mLastKnownElement = mCurrentElement;
1766  }
1767 
1768  break;
1769 
1770  case ListOfReactions:
1771 
1772  if (!strcmp(pszName, "ListOfReactions"))
1773  {
1774  mpCurrentHandler = new ListOfReactionsElement(mParser, mCommon);
1775  mLastKnownElement = mCurrentElement;
1776  }
1777 
1778  break;
1779 
1780  case ListOfEvents:
1781 
1782  if (!strcmp(pszName, "ListOfEvents"))
1783  {
1784  mpCurrentHandler = new ListOfEventsElement(mParser, mCommon);
1785  mLastKnownElement = mCurrentElement;
1786  }
1787 
1788  break;
1789 
1790  case ListOfModelParameterSets:
1791 
1792  if (!strcmp(pszName, "ListOfModelParameterSets"))
1793  {
1794  mpCurrentHandler = new ListOfModelParameterSetsElement(mParser, mCommon);
1795  mLastKnownElement = mCurrentElement;
1796  }
1797 
1798  break;
1799 
1800  case StateTemplate:
1801 
1802  if (!strcmp(pszName, "StateTemplate"))
1803  {
1804  mpCurrentHandler = new StateTemplateElement(mParser, mCommon);
1805  mLastKnownElement = mCurrentElement;
1806  }
1807 
1808  break;
1809 
1810  case InitialState:
1811 
1812  if (!strcmp(pszName, "InitialState"))
1813  {
1814  mpCurrentHandler = new InitialStateElement(mParser, mCommon);
1815  mLastKnownElement = mCurrentElement;
1816  }
1817 
1818  break;
1819 
1820  default:
1821  mCurrentElement = UNKNOWN_ELEMENT;
1822  mpCurrentHandler = &mParser.mUnknownElement;
1823  break;
1824  }
1825 
1826  if (mpCurrentHandler)
1827  mParser.pushElementHandler(mpCurrentHandler);
1828 
1829  mParser.onStartElement(pszName, papszAttrs);
1830 
1831  return;
1832 }
1833 
1834 void CCopasiXMLParser::ModelElement::end(const XML_Char *pszName)
1835 {
1836  switch (mCurrentElement)
1837  {
1838  case Model:
1839 
1840  if (strcmp(pszName, "Model"))
1842  pszName, "Model", mParser.getCurrentLineNumber());
1843 
1844  mCommon.pModel->setCompileFlag(true);
1845 
1846  mParser.popElementHandler();
1847  mCurrentElement = START_ELEMENT;
1848 
1849  /* Tell the parent element we are done. */
1850  mParser.onEndElement(pszName);
1851  break;
1852 
1853  case MiriamAnnotation:
1854 
1855  if (strcmp(pszName, "MiriamAnnotation"))
1857  pszName, "MiriamAnnotation", mParser.getCurrentLineNumber());
1858 
1860  mCommon.CharacterData = "";
1861  break;
1862 
1863  case Comment:
1864 
1865  if (strcmp(pszName, "Comment"))
1867  pszName, "Comment", mParser.getCurrentLineNumber());
1868 
1870  mCommon.CharacterData = "";
1871  break;
1872 
1873  case ListOfUnsupportedAnnotations:
1874 
1875  if (strcmp(pszName, "ListOfUnsupportedAnnotations"))
1877  pszName, "ListOfUnsupportedAnnotations", mParser.getCurrentLineNumber());
1878 
1879  mCommon.pModel->getUnsupportedAnnotations() = mParser.mListOfUnsupportedAnnotationsElement.getUnsupportedAnnotations();
1880  break;
1881 
1882  case InitialExpression:
1883 
1884  if (strcmp(pszName, "InitialExpression"))
1886  pszName, "InitialExpression", mParser.getCurrentLineNumber());
1887 
1888  {
1889  size_t Size = CCopasiMessage::size();
1890 
1892 
1893  // Remove error messages created by setExpression as this may fail
1894  // due to incomplete model specification at this time.
1895  while (CCopasiMessage::size() > Size)
1897  }
1898 
1899  // Old CopasiML files have the incorrect order and the comment may appear after
1900  // the initial expression. Therefore, we reset to MiriamAnnotation.
1901  mCurrentElement = MiriamAnnotation;
1902  break;
1903 
1904  case ListOfCompartments:
1905 
1906  if (strcmp(pszName, "ListOfCompartments"))
1908  pszName, "ListOfCompartments", mParser.getCurrentLineNumber());
1909 
1910  deleteCurrentHandler();
1911  break;
1912 
1913  case ListOfMetabolites:
1914 
1915  if (strcmp(pszName, "ListOfMetabolites"))
1917  pszName, "ListOfMetabolites", mParser.getCurrentLineNumber());
1918 
1919  deleteCurrentHandler();
1920  break;
1921 
1922  case ListOfModelValues:
1923 
1924  if (strcmp(pszName, "ListOfModelValues"))
1926  pszName, "ListOfModelValues", mParser.getCurrentLineNumber());
1927 
1928  deleteCurrentHandler();
1929  break;
1930 
1931  case ListOfReactions:
1932 
1933  if (strcmp(pszName, "ListOfReactions"))
1935  pszName, "ListOfReactions", mParser.getCurrentLineNumber());
1936 
1937  deleteCurrentHandler();
1938  break;
1939 
1940  case ListOfEvents:
1941 
1942  if (strcmp(pszName, "ListOfEvents"))
1944  pszName, "ListOfEvents", mParser.getCurrentLineNumber());
1945 
1946  deleteCurrentHandler();
1947  break;
1948 
1949  case ListOfModelParameterSets:
1950 
1951  if (strcmp(pszName, "ListOfModelParameterSets"))
1953  pszName, "ListOfModelParameterSets", mParser.getCurrentLineNumber());
1954 
1955  deleteCurrentHandler();
1956  mCurrentElement = Model; // This is possibly the last element.
1957  break;
1958 
1959  case StateTemplate:
1960 
1961  if (strcmp(pszName, "StateTemplate"))
1963  pszName, "StateTemplate", mParser.getCurrentLineNumber());
1964 
1965  deleteCurrentHandler();
1966  break;
1967 
1968  case InitialState:
1969 
1970  if (strcmp(pszName, "InitialState"))
1972  pszName, "InitialState", mParser.getCurrentLineNumber());
1973 
1974  deleteCurrentHandler();
1975  mCurrentElement = Model; // This is possibly the last element.
1976  break;
1977 
1978  case UNKNOWN_ELEMENT:
1979  mCurrentElement = mLastKnownElement;
1980  mCurrentElement = Model; // This is possibly the last element.
1981  break;
1982 
1983  default:
1985  pszName, "???", mParser.getCurrentLineNumber());
1986  break;
1987  }
1988 
1989  return;
1990 }
1991 
1993  SCopasiXMLParserCommon & common):
1995  mXhtml(),
1996  mLevel(0)
1997 {}
1998 
2000 {
2001  deleteCurrentHandler();
2002 }
2003 
2004 void CCopasiXMLParser::CommentElement::start(const XML_Char *pszName,
2005  const XML_Char ** papszAttrs)
2006 {
2007  mCurrentElement++; /* We should always be on the next element */
2008  const XML_Char ** ppAttrs;
2009 
2010  if (mLevel) mCurrentElement = xhtml;
2011 
2012  switch (mCurrentElement)
2013  {
2014  case Comment:
2015 
2016  if (strcmp(pszName, "Comment"))
2018  pszName, "Comment", mParser.getCurrentLineNumber());
2019 
2020  mXhtml.str("");
2021  mLevel = 0;
2022  mParser.enableCharacterDataHandler();
2023  mParser.enableSkippedEntityHandler();
2024  mParser.mCharacterDataEncoding = CCopasiXMLInterface::standard;
2025 
2026  mElementEmpty.push(false);
2027  break;
2028 
2029  case xhtml:
2030 
2031  if (mElementEmpty.top() == true)
2032  {
2033  mXhtml << ">";
2034  mElementEmpty.top() = false;
2035  }
2036 
2037  mXhtml << CCopasiXMLInterface::encode(mParser.getCharacterData());
2038  mXhtml << "<" << pszName;
2039 
2040  for (ppAttrs = papszAttrs; *ppAttrs && **ppAttrs; ppAttrs += 2)
2041  mXhtml << " " << *ppAttrs << "=\""
2042  << CCopasiXMLInterface::encode(*(ppAttrs + 1), CCopasiXMLInterface::attribute) << "\"";
2043 
2044  mLevel++;
2045  mElementEmpty.push(true);
2046 
2047  mParser.enableCharacterDataHandler();
2048  break;
2049 
2050  default:
2051  mLastKnownElement = mCurrentElement - 1;
2052  mCurrentElement = UNKNOWN_ELEMENT;
2053  mParser.pushElementHandler(&mParser.mUnknownElement);
2054  mParser.onStartElement(pszName, papszAttrs);
2055  break;
2056  }
2057 
2058  return;
2059 }
2060 
2061 void CCopasiXMLParser::CommentElement::end(const XML_Char *pszName)
2062 {
2063  std::string Xhtml;
2064 
2065  switch (mCurrentElement)
2066  {
2067  case Comment:
2068 
2069  if (strcmp(pszName, "Comment"))
2071  pszName, "Comment", mParser.getCurrentLineNumber());
2072 
2073  mXhtml << mParser.getCharacterData();
2074 
2075  mCommon.CharacterData = mXhtml.str();
2076 
2077  {
2078  // remove leading whitepsaces
2079  std::string::size_type pos = mCommon.CharacterData.find_first_not_of("\x0a\x0d\t ");
2080 
2081  if (pos != 0) mCommon.CharacterData.erase(0, pos);
2082 
2083  // remove trailing whitepsace
2084  pos = mCommon.CharacterData.find_last_not_of("\x0a\x0d\t ");
2085 
2086  if (pos < mCommon.CharacterData.length())
2087  mCommon.CharacterData = mCommon.CharacterData.substr(0, pos + 1);
2088  }
2089 
2090  mParser.enableSkippedEntityHandler(false);
2091  mParser.mCharacterDataEncoding = CCopasiXMLInterface::none;
2092 
2093  mParser.popElementHandler();
2094  mCurrentElement = START_ELEMENT;
2095  mElementEmpty.pop();
2096 
2097  deleteCurrentHandler();
2098 
2099  /* Tell the parent element we are done. */
2100  mParser.onEndElement(pszName);
2101  break;
2102 
2103  case xhtml:
2104  Xhtml = mParser.getCharacterData();
2105 
2106  // Check whether and how we need to close the attribute
2107  if (mElementEmpty.top() == true)
2108  {
2109  if (Xhtml != "")
2110  {
2111  mElementEmpty.top() = false;
2112  mXhtml << ">";
2113  }
2114  else
2115  mXhtml << " />";
2116  }
2117 
2118  mXhtml << Xhtml;
2119 
2120  if (mElementEmpty.top() == false)
2121  mXhtml << "</" << pszName << ">";
2122 
2123  mElementEmpty.pop();
2124  mElementEmpty.top() = false;
2125  mLevel--;
2126 
2127  if (!mLevel) mCurrentElement = Comment;
2128 
2129  mParser.enableCharacterDataHandler();
2130  break;
2131 
2132  case UNKNOWN_ELEMENT:
2133  mCurrentElement = mLastKnownElement;
2134  break;
2135 
2136  default:
2138  pszName, "???", mParser.getCurrentLineNumber());
2139  break;
2140  }
2141 
2142  return;
2143 }
2144 
2146  SCopasiXMLParserCommon & common):
2148 {}
2149 
2151 {
2152  deleteCurrentHandler();
2153 }
2154 
2156  const XML_Char **papszAttrs)
2157 {
2158  mCurrentElement++; /* We should always be on the next element */
2159 
2160  switch (mCurrentElement)
2161  {
2162  case ListOfCompartments:
2163 
2164  if (strcmp(pszName, "ListOfCompartments"))
2166  pszName, "ListOfCompartments", mParser.getCurrentLineNumber());
2167 
2169  break;
2170 
2171  case Compartment:
2172 
2173  if (strcmp(pszName, "Compartment"))
2175  pszName, "Compartment", mParser.getCurrentLineNumber());
2176 
2177  /* If we do not have a function element handler we create one. */
2178  if (!mpCurrentHandler)
2179  mpCurrentHandler = new CompartmentElement(mParser, mCommon);
2180 
2181  /* Push the Compartment element handler on the stack and call it. */
2182  mParser.pushElementHandler(mpCurrentHandler);
2183  mpCurrentHandler->start(pszName, papszAttrs);
2184  break;
2185 
2186  default:
2187  mLastKnownElement = mCurrentElement - 1;
2188  mCurrentElement = UNKNOWN_ELEMENT;
2189  mParser.pushElementHandler(&mParser.mUnknownElement);
2190  mParser.onStartElement(pszName, papszAttrs);
2191  break;
2192  }
2193 
2194  return;
2195 }
2196 
2198 {
2199  switch (mCurrentElement)
2200  {
2201  case ListOfCompartments:
2202 
2203  if (strcmp(pszName, "ListOfCompartments"))
2205  pszName, "ListOfCompartments", mParser.getCurrentLineNumber());
2206 
2207  mParser.popElementHandler();
2208  mCurrentElement = START_ELEMENT;
2209 
2210  /* Tell the parent element we are done. */
2211  mParser.onEndElement(pszName);
2212  break;
2213 
2214  case Compartment:
2215 
2216  if (strcmp(pszName, "Compartment"))
2218  pszName, "Compartment", mParser.getCurrentLineNumber());
2219 
2220  mCurrentElement = ListOfCompartments;
2221  break;
2222 
2223  case UNKNOWN_ELEMENT:
2224  mCurrentElement = mLastKnownElement;
2225  break;
2226 
2227  default:
2229  pszName, "???", mParser.getCurrentLineNumber());
2230  break;
2231  }
2232 
2233  return;
2234 }
2235 
2237  SCopasiXMLParserCommon & common):
2239  mpCompartment(NULL)
2240 {}
2241 
2243 {}
2244 
2245 void CCopasiXMLParser::CompartmentElement::start(const XML_Char *pszName,
2246  const XML_Char **papszAttrs)
2247 {
2248  const char * Name;
2249  const char * simulationType;
2250  const char * Dimensionality;
2251  CModelEntity::Status SimulationType;
2252 
2253  mpCurrentHandler = NULL;
2254  mCurrentElement = mLastKnownElement;
2255 
2256  while (mpCurrentHandler == NULL)
2257  {
2258  mCurrentElement++; /* We should always be on the next element */
2259 
2260  switch (mCurrentElement)
2261  {
2262  case Compartment:
2263 
2264  if (strcmp(pszName, "Compartment"))
2266  pszName, "Compartment", mParser.getCurrentLineNumber());
2267 
2268  mKey = mParser.getAttributeValue("key", papszAttrs);
2269  Name = mParser.getAttributeValue("name", papszAttrs);
2270  simulationType = mParser.getAttributeValue("simulationType", papszAttrs, "fixed");
2271  SimulationType = toEnum(simulationType, CModelEntity::XMLStatus, CModel::FIXED);
2272  Dimensionality = mParser.getAttributeValue("dimensionality", papszAttrs, "3");
2273 
2274  mpCompartment = new CCompartment();
2275  addFix(mKey, mpCompartment);
2276 
2277  mpCompartment->setObjectName(Name);
2278  mpCompartment->setStatus(SimulationType);
2279  mpCompartment->setDimensionality(strToUnsignedInt(Dimensionality));
2280 
2281  mCommon.pModel->getCompartments().add(mpCompartment, true);
2282  mLastKnownElement = Compartment;
2283  return;
2284 
2285  case MiriamAnnotation:
2286 
2287  if (!strcmp(pszName, "MiriamAnnotation"))
2288  mpCurrentHandler = &mParser.mMiriamAnnotationElement;
2289 
2290  break;
2291 
2292  case Comment:
2293 
2294  if (!strcmp(pszName, "Comment"))
2295  mpCurrentHandler = &mParser.mCommentElement;
2296 
2297  break;
2298 
2299  case ListOfUnsupportedAnnotations:
2300 
2301  if (!strcmp(pszName, "ListOfUnsupportedAnnotations"))
2302  mpCurrentHandler = &mParser.mListOfUnsupportedAnnotationsElement;
2303 
2304  break;
2305 
2306  case Expression:
2307 
2308  if (!strcmp(pszName, "Expression"))
2309  mpCurrentHandler = &mParser.mCharacterDataElement;
2310 
2311  break;
2312 
2313  case InitialExpression:
2314 
2315  if (!strcmp(pszName, "InitialExpression"))
2316  mpCurrentHandler = &mParser.mCharacterDataElement;
2317 
2318  break;
2319 
2320  default:
2321  mCurrentElement = UNKNOWN_ELEMENT;
2322  mpCurrentHandler = &mParser.mUnknownElement;
2323  break;
2324  }
2325  }
2326 
2327  mParser.pushElementHandler(mpCurrentHandler);
2328 
2329  if (mpCurrentHandler != &mParser.mUnknownElement)
2330  {
2331  mLastKnownElement = mCurrentElement;
2332  }
2333 
2334  mParser.onStartElement(pszName, papszAttrs);
2335 
2336  return;
2337 }
2338 
2339 void CCopasiXMLParser::CompartmentElement::end(const XML_Char *pszName)
2340 {
2341  switch (mCurrentElement)
2342  {
2343  case Compartment:
2344 
2345  if (strcmp(pszName, "Compartment"))
2347  pszName, "Compartment", mParser.getCurrentLineNumber());
2348 
2349  mParser.popElementHandler();
2350  mLastKnownElement = START_ELEMENT;
2351 
2352  /* Tell the parent element we are done. */
2353  mParser.onEndElement(pszName);
2354  break;
2355 
2356  case MiriamAnnotation:
2357 
2358  if (strcmp(pszName, "MiriamAnnotation"))
2360  pszName, "MiriamAnnotation", mParser.getCurrentLineNumber());
2361 
2362  mpCompartment->setMiriamAnnotation(mCommon.CharacterData, mpCompartment->getKey(), mKey);
2363  mCommon.CharacterData = "";
2364  break;
2365 
2366  case Comment:
2367 
2368  if (strcmp(pszName, "Comment"))
2370  pszName, "Comment", mParser.getCurrentLineNumber());
2371 
2372  mpCompartment->setNotes(mCommon.CharacterData);
2373  mCommon.CharacterData = "";
2374  break;
2375 
2376  case ListOfUnsupportedAnnotations:
2377 
2378  if (strcmp(pszName, "ListOfUnsupportedAnnotations"))
2380  pszName, "ListOfUnsupportedAnnotations", mParser.getCurrentLineNumber());
2381 
2382  mpCompartment->getUnsupportedAnnotations() = mParser.mListOfUnsupportedAnnotationsElement.getUnsupportedAnnotations();
2383 
2384  break;
2385 
2386  case Expression:
2387 
2388  if (strcmp(pszName, "Expression"))
2390  pszName, "Expression", mParser.getCurrentLineNumber());
2391 
2392  {
2393  size_t Size = CCopasiMessage::size();
2394 
2395  mpCompartment->setExpression(mCommon.CharacterData);
2396 
2397  // Remove error messages created by setExpression as this may fail
2398  // due to incomplete model specification at this time.
2399  while (CCopasiMessage::size() > Size)
2401  }
2402  break;
2403 
2404  case InitialExpression:
2405 
2406  if (strcmp(pszName, "InitialExpression"))
2408  pszName, "InitialExpression", mParser.getCurrentLineNumber());
2409 
2410  {
2411  size_t Size = CCopasiMessage::size();
2412 
2413  mpCompartment->setInitialExpression(mCommon.CharacterData);
2414 
2415  // Remove error messages created by setExpression as this may fail
2416  // due to incomplete model specification at this time.
2417  while (CCopasiMessage::size() > Size)
2419  }
2420 
2421  break;
2422 
2423  case UNKNOWN_ELEMENT:
2424  break;
2425 
2426  default:
2428  pszName, "???", mParser.getCurrentLineNumber());
2429  break;
2430  }
2431 
2432  mCurrentElement = Compartment;
2433  return;
2434 }
2435 
2437  SCopasiXMLParserCommon & common):
2439 {}
2440 
2442 {
2443  deleteCurrentHandler();
2444 }
2445 
2447  const XML_Char **papszAttrs)
2448 {
2449  mCurrentElement++; /* We should always be on the next element */
2450 
2451  switch (mCurrentElement)
2452  {
2453  case ListOfMetabolites:
2454 
2455  if (strcmp(pszName, "ListOfMetabolites"))
2457  pszName, "ListOfMetabolites", mParser.getCurrentLineNumber());
2458 
2459  break;
2460 
2461  case Metabolite:
2462 
2463  if (strcmp(pszName, "Metabolite"))
2465  pszName, "Metabolite", mParser.getCurrentLineNumber());
2466 
2467  /* If we do not have a function element handler we create one. */
2468  if (!mpCurrentHandler)
2469  mpCurrentHandler = new MetaboliteElement(mParser, mCommon);
2470 
2471  /* Push the Metabolite element handler on the stack and call it. */
2472  mParser.pushElementHandler(mpCurrentHandler);
2473  mpCurrentHandler->start(pszName, papszAttrs);
2474  break;
2475 
2476  default:
2477  mLastKnownElement = mCurrentElement - 1;
2478  mCurrentElement = UNKNOWN_ELEMENT;
2479  mParser.pushElementHandler(&mParser.mUnknownElement);
2480  mParser.onStartElement(pszName, papszAttrs);
2481  break;
2482  }
2483 
2484  return;
2485 }
2486 
2488 {
2489  switch (mCurrentElement)
2490  {
2491  case ListOfMetabolites:
2492 
2493  if (strcmp(pszName, "ListOfMetabolites"))
2495  pszName, "ListOfMetabolites", mParser.getCurrentLineNumber());
2496 
2497  mParser.popElementHandler();
2498  mCurrentElement = START_ELEMENT;
2499 
2500  /* Tell the parent element we are done. */
2501  mParser.onEndElement(pszName);
2502  break;
2503 
2504  case Metabolite:
2505 
2506  if (strcmp(pszName, "Metabolite"))
2508  pszName, "Metabolite", mParser.getCurrentLineNumber());
2509 
2510  mCurrentElement = ListOfMetabolites;
2511  break;
2512 
2513  case UNKNOWN_ELEMENT:
2514  mCurrentElement = mLastKnownElement;
2515  break;
2516 
2517  default:
2519  pszName, "???", mParser.getCurrentLineNumber());
2520  break;
2521  }
2522 
2523  return;
2524 }
2525 
2527  SCopasiXMLParserCommon & common):
2529  mpMetabolite(NULL)
2530 {}
2531 
2533 {}
2534 
2535 void CCopasiXMLParser::MetaboliteElement::start(const XML_Char *pszName,
2536  const XML_Char **papszAttrs)
2537 {
2538  CCompartment * pCompartment = NULL;
2539  const char * Name;
2540  const char * simulationType;
2541  CModelEntity::Status SimulationType;
2542  const char reactions[] = "reactions";
2543  const char * Compartment;
2544 
2545  mpCurrentHandler = NULL;
2546  mCurrentElement = mLastKnownElement;
2547 
2548  while (mpCurrentHandler == NULL)
2549  {
2550  mCurrentElement++; /* We should always be on the next element */
2551 
2552  switch (mCurrentElement)
2553  {
2554  case Metabolite:
2555 
2556  if (strcmp(pszName, "Metabolite"))
2558  pszName, "Metabolite", mParser.getCurrentLineNumber());
2559 
2560  mKey = mParser.getAttributeValue("key", papszAttrs);
2561  Name = mParser.getAttributeValue("name", papszAttrs);
2562 
2563  simulationType = mParser.getAttributeValue("simulationType", papszAttrs, false);
2564 
2565  // We need to handle old files which used the attribute status.
2566  if (!simulationType)
2567  {
2568  simulationType = mParser.getAttributeValue("status", papszAttrs, false);
2569 
2570  if (!simulationType) // status and simulationType are both missing
2571  simulationType = mParser.getAttributeValue("simulationType", papszAttrs);
2572  else if (!strcmp(simulationType, "variable")) // reactions was named variable
2573  simulationType = reactions;
2574  }
2575 
2576  SimulationType = toEnum(simulationType, CModelEntity::XMLStatus, CModelEntity::REACTIONS);
2577  Compartment = mParser.getAttributeValue("compartment", papszAttrs);
2578 
2579  mpMetabolite = new CMetab();
2580  addFix(mKey, mpMetabolite);
2581  mpMetabolite->setObjectName(Name);
2582  mpMetabolite->setStatus(SimulationType);
2583 
2584  pCompartment =
2585  dynamic_cast< CCompartment* >(mCommon.KeyMap.get(Compartment));
2586 
2587  if (!pCompartment) fatalError();
2588 
2589  pCompartment->addMetabolite(mpMetabolite);
2590  mCommon.pModel->getMetabolites().add(mpMetabolite);
2591 
2592  mLastKnownElement = mCurrentElement;
2593  return;
2594 
2595  case MiriamAnnotation:
2596 
2597  if (!strcmp(pszName, "MiriamAnnotation"))
2598  mpCurrentHandler = &mParser.mMiriamAnnotationElement;
2599 
2600  break;
2601 
2602  case Comment:
2603 
2604  if (!strcmp(pszName, "Comment"))
2605  {
2606  mpCurrentHandler = &mParser.mCommentElement;
2607  mLastKnownElement = mCurrentElement;
2608  }
2609 
2610  break;
2611 
2612  case ListOfUnsupportedAnnotations:
2613 
2614  if (!strcmp(pszName, "ListOfUnsupportedAnnotations"))
2615  mpCurrentHandler = &mParser.mListOfUnsupportedAnnotationsElement;
2616 
2617  break;
2618 
2619  case Expression:
2620 
2621  if (!strcmp(pszName, "Expression"))
2622  mpCurrentHandler = &mParser.mCharacterDataElement;
2623 
2624  break;
2625 
2626  case InitialExpression:
2627 
2628  if (!strcmp(pszName, "InitialExpression"))
2629  mpCurrentHandler = &mParser.mCharacterDataElement;
2630 
2631  break;
2632 
2633  default:
2634  mCurrentElement = UNKNOWN_ELEMENT;
2635  mpCurrentHandler = &mParser.mUnknownElement;
2636  break;
2637  }
2638  }
2639 
2640  mParser.pushElementHandler(mpCurrentHandler);
2641 
2642  if (mpCurrentHandler != &mParser.mUnknownElement)
2643  {
2644  mLastKnownElement = mCurrentElement;
2645  }
2646 
2647  mParser.onStartElement(pszName, papszAttrs);
2648 
2649  return;
2650 }
2651 
2652 void CCopasiXMLParser::MetaboliteElement::end(const XML_Char *pszName)
2653 {
2654  switch (mCurrentElement)
2655  {
2656  case Metabolite:
2657 
2658  if (strcmp(pszName, "Metabolite"))
2660  pszName, "Metabolite", mParser.getCurrentLineNumber());
2661 
2662  mParser.popElementHandler();
2663  mLastKnownElement = START_ELEMENT;
2664 
2665  /* Tell the parent element we are done. */
2666  mParser.onEndElement(pszName);
2667  break;
2668 
2669  case MiriamAnnotation:
2670 
2671  if (strcmp(pszName, "MiriamAnnotation"))
2673  pszName, "MiriamAnnotation", mParser.getCurrentLineNumber());
2674 
2675  mpMetabolite->setMiriamAnnotation(mCommon.CharacterData, mpMetabolite->getKey(), mKey);
2676  mCommon.CharacterData = "";
2677  break;
2678 
2679  case Comment:
2680 
2681  if (strcmp(pszName, "Comment"))
2683  pszName, "Comment", mParser.getCurrentLineNumber());
2684 
2685  mpMetabolite->setNotes(mCommon.CharacterData);
2686  mCommon.CharacterData = "";
2687  break;
2688 
2689  case ListOfUnsupportedAnnotations:
2690 
2691  if (strcmp(pszName, "ListOfUnsupportedAnnotations"))
2693  pszName, "ListOfUnsupportedAnnotations", mParser.getCurrentLineNumber());
2694 
2695  mpMetabolite->getUnsupportedAnnotations() = mParser.mListOfUnsupportedAnnotationsElement.getUnsupportedAnnotations();
2696 
2697  break;
2698 
2699  case Expression:
2700 
2701  if (strcmp(pszName, "Expression"))
2703  pszName, "Expression", mParser.getCurrentLineNumber());
2704 
2705  {
2706  size_t Size = CCopasiMessage::size();
2707 
2708  mpMetabolite->setExpression(mCommon.CharacterData);
2709 
2710  // Remove error messages created by setExpression as this may fail
2711  // due to incomplete model specification at this time.
2712  while (CCopasiMessage::size() > Size)
2714  }
2715 
2716  break;
2717 
2718  case InitialExpression:
2719 
2720  if (strcmp(pszName, "InitialExpression"))
2722  pszName, "InitialExpression", mParser.getCurrentLineNumber());
2723 
2724  {
2725  size_t Size = CCopasiMessage::size();
2726 
2727  mpMetabolite->setInitialExpression(mCommon.CharacterData);
2728 
2729  // Remove error messages created by setExpression as this may fail
2730  // due to incomplete model specification at this time.
2731  while (CCopasiMessage::size() > Size)
2733  }
2734 
2735  break;
2736 
2737  case UNKNOWN_ELEMENT:
2738  break;
2739 
2740  default:
2742  pszName, "???", mParser.getCurrentLineNumber());
2743  break;
2744  }
2745 
2746  mCurrentElement = Metabolite;
2747  return;
2748 }
2749 
2750 //****** TODO: ModelValues
2751 
2753  SCopasiXMLParserCommon & common):
2755 {}
2756 
2758 {
2759  deleteCurrentHandler();
2760 }
2761 
2763  const XML_Char **papszAttrs)
2764 {
2765  mCurrentElement++; /* We should always be on the next element */
2766 
2767  switch (mCurrentElement)
2768  {
2769  case ListOfModelValues:
2770 
2771  if (strcmp(pszName, "ListOfModelValues"))
2773  pszName, "ListOfModelValues", mParser.getCurrentLineNumber());
2774 
2775  break;
2776 
2777  case ModelValue:
2778 
2779  if (strcmp(pszName, "ModelValue"))
2781  pszName, "ModelValue", mParser.getCurrentLineNumber());
2782 
2783  /* If we do not have a function element handler we create one. */
2784  if (!mpCurrentHandler)
2785  mpCurrentHandler = new ModelValueElement(mParser, mCommon);
2786 
2787  /* Push the Metabolite element handler on the stack and call it. */
2788  mParser.pushElementHandler(mpCurrentHandler);
2789  mpCurrentHandler->start(pszName, papszAttrs);
2790  break;
2791 
2792  default:
2793  mLastKnownElement = mCurrentElement - 1;
2794  mCurrentElement = UNKNOWN_ELEMENT;
2795  mParser.pushElementHandler(&mParser.mUnknownElement);
2796  mParser.onStartElement(pszName, papszAttrs);
2797  break;
2798  }
2799 
2800  return;
2801 }
2802 
2804 {
2805  switch (mCurrentElement)
2806  {
2807  case ListOfModelValues:
2808 
2809  if (strcmp(pszName, "ListOfModelValues"))
2811  pszName, "ListOfModelValues", mParser.getCurrentLineNumber());
2812 
2813  mParser.popElementHandler();
2814  mCurrentElement = START_ELEMENT;
2815 
2816  /* Tell the parent element we are done. */
2817  mParser.onEndElement(pszName);
2818  break;
2819 
2820  case ModelValue:
2821 
2822  if (strcmp(pszName, "ModelValue"))
2824  pszName, "ModelValue", mParser.getCurrentLineNumber());
2825 
2826  mCurrentElement = ListOfModelValues;
2827  break;
2828 
2829  case UNKNOWN_ELEMENT:
2830  mCurrentElement = mLastKnownElement;
2831  break;
2832 
2833  default:
2835  pszName, "???", mParser.getCurrentLineNumber());
2836  break;
2837  }
2838 
2839  return;
2840 }
2841 
2843  SCopasiXMLParserCommon & common):
2845  mpMV(NULL),
2846  mpMathMLElement(NULL),
2847  mKey("")
2848 {}
2849 
2851 {
2852  pdelete(mpMathMLElement);
2853 }
2854 
2855 void CCopasiXMLParser::ModelValueElement::start(const XML_Char *pszName,
2856  const XML_Char **papszAttrs)
2857 {
2858  const char * Name;
2859  const char * simulationType;
2860  CModelEntity::Status SimulationType;
2861 
2862  mpCurrentHandler = NULL;
2863  mCurrentElement = mLastKnownElement;
2864 
2865  while (mpCurrentHandler == NULL)
2866  {
2867  mCurrentElement++; /* We should always be on the next element */
2868 
2869  switch (mCurrentElement)
2870  {
2871  case ModelValue:
2872 
2873  if (strcmp(pszName, "ModelValue"))
2875  pszName, "ModelValue", mParser.getCurrentLineNumber());
2876 
2877  mKey = mParser.getAttributeValue("key", papszAttrs);
2878  Name = mParser.getAttributeValue("name", papszAttrs);
2879  simulationType = mParser.getAttributeValue("simulationType", papszAttrs, false);
2880 
2881  // We need to handle old files which used the attribute status.
2882  if (!simulationType)
2883  {
2884  simulationType = mParser.getAttributeValue("status", papszAttrs, false);
2885 
2886  if (!simulationType) // status and simulationType are both missing
2887  simulationType = mParser.getAttributeValue("simulationType", papszAttrs);
2888  }
2889 
2890  SimulationType = toEnum(simulationType, CModelEntity::XMLStatus, CModelEntity::FIXED);
2891 
2892  mpMV = new CModelValue();
2893  addFix(mKey, mpMV);
2894  mpMV->setObjectName(Name);
2895  mpMV->setStatus(SimulationType);
2896 
2897  mCommon.pModel->getModelValues().add(mpMV, true);
2898  mLastKnownElement = mCurrentElement;
2899 
2900  return;
2901 
2902  case MiriamAnnotation:
2903 
2904  if (!strcmp(pszName, "MiriamAnnotation"))
2905  mpCurrentHandler = &mParser.mMiriamAnnotationElement;
2906 
2907  break;
2908 
2909  case Comment:
2910 
2911  if (!strcmp(pszName, "Comment"))
2912  mpCurrentHandler = &mParser.mCommentElement;
2913 
2914  break;
2915 
2916  case ListOfUnsupportedAnnotations:
2917 
2918  if (!strcmp(pszName, "ListOfUnsupportedAnnotations"))
2919  mpCurrentHandler = &mParser.mListOfUnsupportedAnnotationsElement;
2920 
2921  break;
2922 
2923  case Expression:
2924 
2925  if (!strcmp(pszName, "Expression"))
2926  mpCurrentHandler = &mParser.mCharacterDataElement;
2927 
2928  break;
2929 
2930  case InitialExpression:
2931 
2932  if (!strcmp(pszName, "InitialExpression"))
2933  mpCurrentHandler = &mParser.mCharacterDataElement;
2934 
2935  break;
2936 
2937  case MathML: // Old file format support
2938 
2939  if (!strcmp(pszName, "MathML"))
2940  {
2941  /* If we do not have a MathML element handler we create one. */
2942  if (!mpMathMLElement)
2943  mpMathMLElement = new MathMLElement(mParser, mCommon);
2944 
2945  mpCurrentHandler = mpMathMLElement;
2946  }
2947 
2948  break;
2949 
2950  default:
2951  mCurrentElement = UNKNOWN_ELEMENT;
2952  mpCurrentHandler = &mParser.mUnknownElement;
2953  break;
2954  }
2955  }
2956 
2957  mParser.pushElementHandler(mpCurrentHandler);
2958 
2959  if (mpCurrentHandler != &mParser.mUnknownElement)
2960  {
2961  mLastKnownElement = mCurrentElement;
2962  }
2963 
2964  mParser.onStartElement(pszName, papszAttrs);
2965 
2966  return;
2967 }
2968 
2969 void CCopasiXMLParser::ModelValueElement::end(const XML_Char *pszName)
2970 {
2971  switch (mCurrentElement)
2972  {
2973  case ModelValue:
2974 
2975  if (strcmp(pszName, "ModelValue"))
2977  pszName, "ModelValue", mParser.getCurrentLineNumber());
2978 
2979  mParser.popElementHandler();
2980  mLastKnownElement = START_ELEMENT;
2981 
2982  /* Tell the parent element we are done. */
2983  mParser.onEndElement(pszName);
2984  break;
2985 
2986  case MiriamAnnotation:
2987 
2988  if (strcmp(pszName, "MiriamAnnotation"))
2990  pszName, "MiriamAnnotation", mParser.getCurrentLineNumber());
2991 
2992  mpMV->setMiriamAnnotation(mCommon.CharacterData, mpMV->getKey(), mKey);
2993  mCommon.CharacterData = "";
2994  break;
2995 
2996  case Comment:
2997 
2998  if (strcmp(pszName, "Comment"))
3000  pszName, "Comment", mParser.getCurrentLineNumber());
3001 
3002  mpMV->setNotes(mCommon.CharacterData);
3003  mCommon.CharacterData = "";
3004  break;
3005 
3006  case ListOfUnsupportedAnnotations:
3007 
3008  if (strcmp(pszName, "ListOfUnsupportedAnnotations"))
3010  pszName, "ListOfUnsupportedAnnotations", mParser.getCurrentLineNumber());
3011 
3012  mpMV->getUnsupportedAnnotations() = mParser.mListOfUnsupportedAnnotationsElement.getUnsupportedAnnotations();
3013 
3014  break;
3015 
3016  case Expression:
3017 
3018  if (strcmp(pszName, "Expression"))
3020  pszName, "Expression", mParser.getCurrentLineNumber());
3021 
3022  {
3023  size_t Size = CCopasiMessage::size();
3024 
3025  mpMV->setExpression(mCommon.CharacterData);
3026 
3027  // Remove error messages created by setExpression as this may fail
3028  // due to incomplete model specification at this time.
3029 
3030  while (CCopasiMessage::size() > Size)
3032  }
3033 
3034  break;
3035 
3036  case InitialExpression:
3037 
3038  if (strcmp(pszName, "InitialExpression"))
3040  pszName, "InitialExpression", mParser.getCurrentLineNumber());
3041 
3042  {
3043  size_t Size = CCopasiMessage::size();
3044 
3045  mpMV->setInitialExpression(mCommon.CharacterData);
3046 
3047  // Remove error messages created by setExpression as this may fail
3048  // due to incomplete model specification at this time.
3049  while (CCopasiMessage::size() > Size)
3051  }
3052 
3053  break;
3054 
3055  case MathML: // Old file format support
3056 
3057  if (strcmp(pszName, "MathML"))
3059  pszName, "MathML", mParser.getCurrentLineNumber());
3060 
3061  {
3062  size_t Size = CCopasiMessage::size();
3063 
3064  mpMV->setExpression(mCommon.CharacterData);
3065 
3066  // Remove error messages created by setExpression as this may fail
3067  // due to incomplete model specification at this time.
3068 
3069  while (CCopasiMessage::size() > Size)
3071  }
3072 
3073  break;
3074 
3075  case UNKNOWN_ELEMENT:
3076  break;
3077 
3078  default:
3080  pszName, "???", mParser.getCurrentLineNumber());
3081  break;
3082  }
3083 
3084  mCurrentElement = ModelValue;
3085  return;
3086 }
3087 
3088 //****** TODO: Event
3089 
3091  SCopasiXMLParserCommon & common):
3093 {}
3094 
3096 {
3097  deleteCurrentHandler();
3098 }
3099 
3101  const XML_Char **papszAttrs)
3102 {
3103  mCurrentElement++; /* We should always be on the next element */
3104 
3105  switch (mCurrentElement)
3106  {
3107  case ListOfEvents:
3108 
3109  if (strcmp(pszName, "ListOfEvents"))
3111  pszName, "ListOfEvents", mParser.getCurrentLineNumber());
3112 
3113  mEventOrders.clear();
3114  break;
3115 
3116  case Event:
3117 
3118  if (strcmp(pszName, "Event"))
3120  pszName, "Event", mParser.getCurrentLineNumber());
3121 
3122  /* If we do not have a function element handler we create one. */
3123  if (!mpCurrentHandler)
3124  mpCurrentHandler = new EventElement(mParser, mCommon);
3125 
3126  /* Push the Metabolite element handler on the stack and call it. */
3127  mParser.pushElementHandler(mpCurrentHandler);
3128  mpCurrentHandler->start(pszName, papszAttrs);
3129  break;
3130 
3131  default:
3132  mLastKnownElement = mCurrentElement - 1;
3133  mCurrentElement = UNKNOWN_ELEMENT;
3134  mParser.pushElementHandler(&mParser.mUnknownElement);
3135  mParser.onStartElement(pszName, papszAttrs);
3136  break;
3137  }
3138 
3139  return;
3140 }
3141 
3142 void CCopasiXMLParser::ListOfEventsElement::end(const XML_Char *pszName)
3143 {
3144  switch (mCurrentElement)
3145  {
3146  case ListOfEvents:
3147 
3148  if (strcmp(pszName, "ListOfEvents"))
3150  pszName, "ListOfEvents", mParser.getCurrentLineNumber());
3151 
3152  mParser.popElementHandler();
3153  mCurrentElement = START_ELEMENT;
3154 
3155  /* Tell the parent element we are done. */
3156  mParser.onEndElement(pszName);
3157  break;
3158 
3159  case Event:
3160 
3161  if (strcmp(pszName, "Event"))
3163  pszName, "Event", mParser.getCurrentLineNumber());
3164 
3165  mCurrentElement = ListOfEvents;
3166  break;
3167 
3168  case UNKNOWN_ELEMENT:
3169  mCurrentElement = mLastKnownElement;
3170  break;
3171 
3172  default:
3174  pszName, "???", mParser.getCurrentLineNumber());
3175  break;
3176  }
3177 
3178  return;
3179 }
3180 
3182  SCopasiXMLParserCommon & common):
3184  mpListOfAssignmentsElementHandler(NULL)
3185 {}
3186 
3188 {
3189  pdelete(mpListOfAssignmentsElementHandler);
3190 }
3191 
3192 void CCopasiXMLParser::EventElement::start(const XML_Char *pszName,
3193  const XML_Char **papszAttrs)
3194 {
3195  const char * Name;
3196  bool DelayAssignment;
3197  bool FireAtInitialTime;
3198  bool PersistentTrigger;
3199 
3200  mpCurrentHandler = NULL;
3201  mCurrentElement = mLastKnownElement;
3202 
3203  while (mpCurrentHandler == NULL)
3204  {
3205  mCurrentElement++; /* We should always be on the next element */
3206 
3207  switch (mCurrentElement)
3208  {
3209  case Event:
3210 
3211  if (strcmp(pszName, "Event"))
3213  pszName, "Event", mParser.getCurrentLineNumber());
3214 
3215  mKey = mParser.getAttributeValue("key", papszAttrs);
3216  Name = mParser.getAttributeValue("name", papszAttrs);
3217  DelayAssignment =
3218  mParser.toBool(mParser.getAttributeValue("delayAssignment", papszAttrs, false));
3219  FireAtInitialTime =
3220  mParser.toBool(mParser.getAttributeValue("fireAtInitialTime", papszAttrs, false));
3221 
3222  if (mCommon.pVersion->getVersionDevel() <= 90)
3223  {
3224  PersistentTrigger = true;
3225  }
3226  else
3227  {
3228  PersistentTrigger = mParser.toBool(mParser.getAttributeValue("persistentTrigger", papszAttrs, true));
3229  }
3230 
3231  mCommon.pEvent = new CEvent();
3232  addFix(mKey, mCommon.pEvent);
3233  mCommon.pEvent->setObjectName(Name);
3234  mCommon.pEvent->setDelayAssignment(DelayAssignment);
3235  mCommon.pEvent->setFireAtInitialTime(FireAtInitialTime);
3236  mCommon.pEvent->setPersistentTrigger(PersistentTrigger);
3237 
3238  mCommon.pModel->getEvents().add(mCommon. pEvent, true);
3239 
3240  mLastKnownElement = Event;
3241  return;
3242 
3243  case MiriamAnnotation:
3244 
3245  if (!strcmp(pszName, "MiriamAnnotation"))
3246  mpCurrentHandler = &mParser.mMiriamAnnotationElement;
3247 
3248  break;
3249 
3250  case Comment:
3251 
3252  if (!strcmp(pszName, "Comment"))
3253  mpCurrentHandler = &mParser.mCommentElement;
3254 
3255  break;
3256 
3257  case ListOfUnsupportedAnnotations:
3258 
3259  if (!strcmp(pszName, "ListOfUnsupportedAnnotations"))
3260  mpCurrentHandler = &mParser.mListOfUnsupportedAnnotationsElement;
3261 
3262  break;
3263 
3264  case TriggerExpression:
3265 
3266  if (!strcmp(pszName, "TriggerExpression"))
3267  mpCurrentHandler = &mParser.mCharacterDataElement;
3268 
3269  break;
3270 
3271  case DelayExpression:
3272 
3273  if (!strcmp(pszName, "DelayExpression"))
3274  mpCurrentHandler = &mParser.mCharacterDataElement;
3275 
3276  break;
3277 
3278  case ListOfAssignments:
3279 
3280  if (!strcmp(pszName, "ListOfAssignments"))
3281  {
3282  if (!mpListOfAssignmentsElementHandler)
3283  {
3284  mpListOfAssignmentsElementHandler =
3286 
3287  mCommon.mAssignments.reserve(100);
3288  mCommon.mAssignments.resize(0);
3289  }
3290 
3291  mpCurrentHandler = mpListOfAssignmentsElementHandler;
3292  }
3293 
3294  break;
3295 
3296  default:
3297  mCurrentElement = UNKNOWN_ELEMENT;
3298  mpCurrentHandler = &mParser.mUnknownElement;
3299  break;
3300  }
3301  }
3302 
3303  mParser.pushElementHandler(mpCurrentHandler);
3304 
3305  if (mpCurrentHandler != &mParser.mUnknownElement)
3306  {
3307  mLastKnownElement = mCurrentElement;
3308  }
3309 
3310  mParser.onStartElement(pszName, papszAttrs);
3311 
3312  return;
3313 }
3314 
3315 void CCopasiXMLParser::EventElement::end(const XML_Char *pszName)
3316 {
3317  switch (mCurrentElement)
3318  {
3319  case Event:
3320 
3321  if (strcmp(pszName, "Event"))
3323  pszName, "Event", mParser.getCurrentLineNumber());
3324 
3325  mParser.popElementHandler();
3326  mLastKnownElement = START_ELEMENT;
3327 
3328  /* Tell the parent element we are done. */
3329  mParser.onEndElement(pszName);
3330  break;
3331 
3332  case MiriamAnnotation:
3333 
3334  if (strcmp(pszName, "MiriamAnnotation"))
3336  pszName, "MiriamAnnotation", mParser.getCurrentLineNumber());
3337 
3339  mCommon.CharacterData = "";
3340  break;
3341 
3342  case Comment:
3343 
3344  if (strcmp(pszName, "Comment"))
3346  pszName, "Comment", mParser.getCurrentLineNumber());
3347 
3349  mCommon.CharacterData = "";
3350  break;
3351 
3352  case ListOfUnsupportedAnnotations:
3353 
3354  if (strcmp(pszName, "ListOfUnsupportedAnnotations"))
3356  pszName, "ListOfUnsupportedAnnotations", mParser.getCurrentLineNumber());
3357 
3358  mCommon.pEvent->getUnsupportedAnnotations() = mParser.mListOfUnsupportedAnnotationsElement.getUnsupportedAnnotations();
3359 
3360  break;
3361 
3362  case TriggerExpression:
3363 
3364  if (strcmp(pszName, "TriggerExpression"))
3365  {
3367  pszName, "TriggerExpression", mParser.getCurrentLineNumber());
3368  }
3369 
3370  {
3371  size_t Size = CCopasiMessage::size();
3372 
3374 
3375  // Remove error messages created by setExpression as this may fail
3376  // due to incomplete model specification at this time.
3377  while (CCopasiMessage::size() > Size)
3378  {
3380  }
3381  }
3382 
3383  break;
3384 
3385  case DelayExpression:
3386 
3387  if (strcmp(pszName, "DelayExpression"))
3388  {
3390  pszName, "DelayExpression", mParser.getCurrentLineNumber());
3391  }
3392 
3393  {
3394  size_t Size = CCopasiMessage::size();
3395 
3397 
3398  // Remove error messages created by setExpression as this may fail
3399  // due to incomplete model specification at this time.
3400  while (CCopasiMessage::size() > Size)
3401  {
3403  }
3404  }
3405 
3406  break;
3407 
3408  case ListOfAssignments:
3409  break;
3410 
3411  case UNKNOWN_ELEMENT:
3412  break;
3413 
3414  default:
3416  pszName, "???", mParser.getCurrentLineNumber());
3417  break;
3418  }
3419 
3420  mCurrentElement = Event;
3421  return;
3422 }
3423 
3424 //****** TODO: Assignments
3425 
3427  SCopasiXMLParserCommon & common):
3429 {}
3430 
3432 {deleteCurrentHandler();}
3433 
3435  const XML_Char **papszAttrs)
3436 {
3437  mCurrentElement++; /* We should always be on the next element */
3438 
3439  switch (mCurrentElement)
3440  {
3441  case ListOfAssignments:
3442 
3443  if (strcmp(pszName, "ListOfAssignments"))
3445  pszName, "ListOfAssignments", mParser.getCurrentLineNumber());
3446 
3447  break;
3448 
3449  case Assignment:
3450 
3451  if (strcmp(pszName, "Assignment"))
3453  pszName, "Assignment", mParser.getCurrentLineNumber());
3454 
3455  /* If we do not have a function element handler we create one. */
3456  if (!mpCurrentHandler)
3457  {
3458  mpCurrentHandler = new AssignmentElement(mParser, mCommon);
3459  }
3460 
3461  /* Push the Metabolite element handler on the stack and call it. */
3462  mParser.pushElementHandler(mpCurrentHandler);
3463  mpCurrentHandler->start(pszName, papszAttrs);
3464  break;
3465 
3466  default:
3467  mLastKnownElement = mCurrentElement - 1;
3468  mCurrentElement = UNKNOWN_ELEMENT;
3469  mParser.pushElementHandler(&mParser.mUnknownElement);
3470  mParser.onStartElement(pszName, papszAttrs);
3471  break;
3472  }
3473 
3474  return;
3475 }
3476 
3478 {
3479  switch (mCurrentElement)
3480  {
3481  case ListOfAssignments:
3482 
3483  if (strcmp(pszName, "ListOfAssignments"))
3485  pszName, "ListOfAssignments", mParser.getCurrentLineNumber());
3486 
3487  mParser.popElementHandler();
3488  mCurrentElement = START_ELEMENT;
3489 
3490  /* Tell the parent element we are done. */
3491  mParser.onEndElement(pszName);
3492  break;
3493 
3494  case Assignment:
3495 
3496  if (strcmp(pszName, "Assignment"))
3498  pszName, "Assignment", mParser.getCurrentLineNumber());
3499 
3500  mCurrentElement = ListOfAssignments;
3501  break;
3502 
3503  case UNKNOWN_ELEMENT:
3504  mCurrentElement = mLastKnownElement;
3505  break;
3506 
3507  default:
3509  pszName, "???", mParser.getCurrentLineNumber());
3510  break;
3511  }
3512 
3513  return;
3514 }
3515 
3517  SCopasiXMLParserCommon & common):
3519 {}
3520 
3522 {deleteCurrentHandler();}
3523 
3524 void CCopasiXMLParser::AssignmentElement::start(const XML_Char *pszName,
3525  const XML_Char **papszAttrs)
3526 {
3527  mpCurrentHandler = NULL;
3528  mCurrentElement++; /* We should always be on the next element */
3529 
3530  const CModelEntity* pME = NULL;
3531 
3532  switch (mCurrentElement)
3533  {
3534  case Assignment:
3535 
3536  if (strcmp(pszName, "Assignment"))
3538  pszName, "Assignment", mParser.getCurrentLineNumber());
3539 
3540  mCommon.pEventAssignment = NULL;
3541  mKey = mParser.getAttributeValue("targetKey", papszAttrs);
3542  pME = dynamic_cast<const CModelEntity *>(mCommon.KeyMap.get(mKey));
3543 
3544  if (pME != NULL &&
3546  {
3549  }
3550 
3551  return;
3552 
3553  case Expression:
3554 
3555  if (!strcmp(pszName, "Expression"))
3556  {
3557  mpCurrentHandler = &mParser.mCharacterDataElement;
3558  }
3559 
3560  break;
3561 
3562  default:
3563  mLastKnownElement = mCurrentElement - 1;
3564  mCurrentElement = UNKNOWN_ELEMENT;
3565  mpCurrentHandler = &mParser.mUnknownElement;
3566  break;
3567  }
3568 
3569  if (mpCurrentHandler)
3570  mParser.pushElementHandler(mpCurrentHandler);
3571 
3572  mParser.onStartElement(pszName, papszAttrs);
3573 
3574  return;
3575 }
3576 
3577 void CCopasiXMLParser::AssignmentElement::end(const XML_Char *pszName)
3578 {
3579  switch (mCurrentElement)
3580  {
3581  case Assignment:
3582 
3583  if (strcmp(pszName, "Assignment"))
3585  pszName, "Assignment", mParser.getCurrentLineNumber());
3586 
3587  mParser.popElementHandler();
3588  mCurrentElement = START_ELEMENT;
3589 
3590  /* Tell the parent element we are done. */
3591  mParser.onEndElement(pszName);
3592  break;
3593 
3594  case Expression:
3595 
3596  if (strcmp(pszName, "Expression"))
3598  pszName, "Expression", mParser.getCurrentLineNumber());
3599 
3600  {
3601  size_t Size = CCopasiMessage::size();
3602 
3603  if (mCommon.pEventAssignment != NULL)
3605 
3607 
3608  // Remove error messages created by setExpression as this may fail
3609  // due to incomplete model specification at this time.
3610  while (CCopasiMessage::size() > Size)
3611  {
3613  }
3614  }
3615 
3616  mCurrentElement = Assignment;
3617  break;
3618 
3619  case UNKNOWN_ELEMENT:
3620  mCurrentElement = mLastKnownElement;
3621  break;
3622 
3623  default:
3625  pszName, "???", mParser.getCurrentLineNumber());
3626  break;
3627  }
3628 
3629  return;
3630 }
3631 
3632 //******
3633 
3635  SCopasiXMLParserCommon & common):
3637 {}
3638 
3640 {
3641  deleteCurrentHandler();
3642 }
3643 
3645  const XML_Char **papszAttrs)
3646 {
3647  mCurrentElement++; /* We should always be on the next element */
3648 
3649  switch (mCurrentElement)
3650  {
3651  case ListOfReactions:
3652 
3653  if (strcmp(pszName, "ListOfReactions"))
3655  pszName, "ListOfReactions", mParser.getCurrentLineNumber());
3656 
3658  break;
3659 
3660  case Reaction:
3661 
3662  if (strcmp(pszName, "Reaction"))
3664  pszName, "Reaction", mParser.getCurrentLineNumber());
3665 
3666  /* If we do not have a Reaction element handler we create one. */
3667  if (!mpCurrentHandler)
3668  mpCurrentHandler = new ReactionElement(mParser, mCommon);
3669 
3670  /* Push the Reaction element handler on the stack and call it. */
3671  mParser.pushElementHandler(mpCurrentHandler);
3672  mpCurrentHandler->start(pszName, papszAttrs);
3673  break;
3674 
3675  default:
3676  mLastKnownElement = mCurrentElement - 1;
3677  mCurrentElement = UNKNOWN_ELEMENT;
3678  mParser.pushElementHandler(&mParser.mUnknownElement);
3679  mParser.onStartElement(pszName, papszAttrs);
3680  break;
3681  }
3682 
3683  return;
3684 }
3685 
3687 {
3688  switch (mCurrentElement)
3689  {
3690  case ListOfReactions:
3691 
3692  if (strcmp(pszName, "ListOfReactions"))
3694  pszName, "ListOfReactions", mParser.getCurrentLineNumber());
3695 
3696  mParser.popElementHandler();
3697  mCurrentElement = START_ELEMENT;
3698 
3699  /* Tell the parent element we are done. */
3700  mParser.onEndElement(pszName);
3701  break;
3702 
3703  case Reaction:
3704 
3705  if (strcmp(pszName, "Reaction"))
3707  pszName, "Reaction", mParser.getCurrentLineNumber());
3708 
3709  mCurrentElement = ListOfReactions;
3710  break;
3711 
3712  case UNKNOWN_ELEMENT:
3713  mCurrentElement = mLastKnownElement;
3714  break;
3715 
3716  default:
3718  pszName, "???", mParser.getCurrentLineNumber());
3719  break;
3720  }
3721 
3722  return;
3723 }
3724 
3726  SCopasiXMLParserCommon & common):
3728  mpListOfSubstratesElement(NULL),
3729  mpListOfProductsElement(NULL),
3730  mpListOfModifiersElement(NULL),
3731  mpListOfConstantsElement(NULL),
3732  mpKineticLawElement(NULL)
3733 {}
3734 
3736 {
3737  pdelete(mpListOfSubstratesElement);
3738  pdelete(mpListOfProductsElement);
3739  pdelete(mpListOfModifiersElement);
3740  pdelete(mpListOfConstantsElement);
3741  pdelete(mpKineticLawElement);
3742 }
3743 
3744 void CCopasiXMLParser::ReactionElement::start(const XML_Char *pszName,
3745  const XML_Char **papszAttrs)
3746 {
3747  CCompartment * pCompartment;
3748  const char * Name;
3749  const char * Compartment; // Default Compartment_00
3750  const char * reversible;
3751  bool Reversible;
3752  const char * fast;
3753  bool Fast;
3754  const char * SBMLId;
3755 
3756  mCurrentElement = mLastKnownElement;
3757  mpCurrentHandler = NULL;
3758 
3759  while (mpCurrentHandler == NULL)
3760  {
3761  mCurrentElement++; /* We should always be on the next element */
3762 
3763  switch (mCurrentElement)
3764  {
3765  case Reaction:
3766 
3767  if (strcmp(pszName, "Reaction"))
3769  pszName, "Reaction", mParser.getCurrentLineNumber());
3770 
3771  mKey = mParser.getAttributeValue("key", papszAttrs);
3772  Name = mParser.getAttributeValue("name", papszAttrs);
3773  Compartment = mParser.getAttributeValue("compartment", papszAttrs,
3774  "Compartment_00");
3775 
3776  reversible = mParser.getAttributeValue("reversible", papszAttrs);
3777  Reversible = mParser.toBool(reversible);
3778 
3779  fast = mParser.getAttributeValue("fast", papszAttrs, "false");
3780  Fast = mParser.toBool(fast);
3781 
3782  mCommon.pReaction = new CReaction();
3783  addFix(mKey, mCommon.pReaction);
3785  mCommon.pReaction->setReversible(Reversible);
3786  mCommon.pReaction->setFast(Fast);
3787  SBMLId = mParser.getAttributeValue("sbmlid", papszAttrs, "");
3788 
3789  if (std::string(SBMLId) != std::string(""))
3790  {
3791  mCommon.pReaction->setSBMLId(SBMLId);
3792  }
3793 
3794  if (strcmp(Compartment, "Compartment_00")) //TODO necessary?
3795  {
3796  pCompartment =
3797  dynamic_cast< CCompartment* >(mCommon.KeyMap.get(Compartment));
3798 
3799  if (!pCompartment) fatalError();
3800 
3801  //mCommon.pReaction->setCompartment(pCompartment);
3802  }
3803 
3805 
3806  mLastKnownElement = Reaction;
3807  return;
3808  break;
3809 
3810  case MiriamAnnotation:
3811 
3812  if (!strcmp(pszName, "MiriamAnnotation"))
3813  mpCurrentHandler = &mParser.mMiriamAnnotationElement;
3814 
3815  break;
3816 
3817  case Comment:
3818 
3819  if (!strcmp(pszName, "Comment"))
3820  {
3821  mpCurrentHandler = &mParser.mCommentElement;
3822  mLastKnownElement = mCurrentElement;
3823  }
3824 
3825  break;
3826 
3827  case ListOfUnsupportedAnnotations:
3828 
3829  if (!strcmp(pszName, "ListOfUnsupportedAnnotations"))
3830  mpCurrentHandler = &mParser.mListOfUnsupportedAnnotationsElement;
3831 
3832  break;
3833 
3834  case ListOfSubstrates:
3835 
3836  if (!strcmp(pszName, "ListOfSubstrates"))
3837  {
3838  /* If we do not have a function element handler we create one. */
3839  if (!mpListOfSubstratesElement)
3840  mpListOfSubstratesElement =
3842 
3843  mpCurrentHandler = mpListOfSubstratesElement;
3844  }
3845 
3846  break;
3847 
3848  case ListOfProducts:
3849 
3850  if (!strcmp(pszName, "ListOfProducts"))
3851  {
3852  if (!mpListOfProductsElement)
3853  mpListOfProductsElement =
3855 
3856  mpCurrentHandler = mpListOfProductsElement;
3857  }
3858 
3859  break;
3860 
3861  case ListOfModifiers:
3862 
3863  if (!strcmp(pszName, "ListOfModifiers"))
3864  {
3865  if (!mpListOfModifiersElement)
3866  mpListOfModifiersElement =
3868 
3869  mpCurrentHandler = mpListOfModifiersElement;
3870  }
3871 
3872  break;
3873 
3874  case ListOfConstants:
3875 
3876  if (!strcmp(pszName, "ListOfConstants"))
3877  {
3878  if (!mpListOfConstantsElement)
3879  mpListOfConstantsElement =
3881 
3882  mpCurrentHandler = mpListOfConstantsElement;
3883  }
3884 
3885  break;
3886 
3887  case KineticLaw:
3888 
3889  if (!strcmp(pszName, "KineticLaw"))
3890  {
3891  if (!mpKineticLawElement)
3892  mpKineticLawElement = new KineticLawElement(mParser, mCommon);
3893 
3894  mpCurrentHandler = mpKineticLawElement;
3895  }
3896 
3897  break;
3898 
3899  default:
3900  mCurrentElement = UNKNOWN_ELEMENT;
3901  mpCurrentHandler = &mParser.mUnknownElement;
3902  break;
3903  }
3904  }
3905 
3906  mParser.pushElementHandler(mpCurrentHandler);
3907 
3908  if (mpCurrentHandler != &mParser.mUnknownElement)
3909  {
3910  mLastKnownElement = mCurrentElement;
3911  }
3912 
3913  mParser.onStartElement(pszName, papszAttrs);
3914 
3915  return;
3916 }
3917 
3918 void CCopasiXMLParser::ReactionElement::end(const XML_Char *pszName)
3919 {
3920  switch (mCurrentElement)
3921  {
3922  case Reaction:
3923 
3924  if (strcmp(pszName, "Reaction"))
3926  pszName, "Reaction", mParser.getCurrentLineNumber());
3927 
3928  mParser.popElementHandler();
3929  mLastKnownElement = START_ELEMENT;
3930 
3931  /* Tell the parent element we are done. */
3932  mParser.onEndElement(pszName);
3933  break;
3934 
3935  case MiriamAnnotation:
3936 
3937  if (strcmp(pszName, "MiriamAnnotation"))
3939  pszName, "MiriamAnnotation", mParser.getCurrentLineNumber());
3940 
3942  mCommon.CharacterData = "";
3943  break;
3944 
3945  case Comment:
3946 
3947  if (strcmp(pszName, "Comment"))
3949  pszName, "Comment", mParser.getCurrentLineNumber());
3950 
3952  mCommon.CharacterData = "";
3953  break;
3954 
3955  case ListOfUnsupportedAnnotations:
3956 
3957  if (strcmp(pszName, "ListOfUnsupportedAnnotations"))
3959  pszName, "ListOfUnsupportedAnnotations", mParser.getCurrentLineNumber());
3960 
3961  mCommon.pReaction->getUnsupportedAnnotations() = mParser.mListOfUnsupportedAnnotationsElement.getUnsupportedAnnotations();
3962 
3963  break;
3964 
3965  case ListOfSubstrates:
3966 
3967  if (strcmp(pszName, "ListOfSubstrates"))
3969  pszName, "ListOfSubstrates", mParser.getCurrentLineNumber());
3970 
3971  break;
3972 
3973  case ListOfProducts:
3974 
3975  if (strcmp(pszName, "ListOfProducts"))
3977  pszName, "ListOfProducts", mParser.getCurrentLineNumber());
3978 
3979  break;
3980 
3981  case ListOfModifiers:
3982 
3983  if (strcmp(pszName, "ListOfModifiers"))
3985  pszName, "ListOfModifiers", mParser.getCurrentLineNumber());
3986 
3987  break;
3988 
3989  case ListOfConstants:
3990 
3991  if (strcmp(pszName, "ListOfConstants"))
3993  pszName, "ListOfConstants", mParser.getCurrentLineNumber());
3994 
3995  break;
3996 
3997  case KineticLaw:
3998 
3999  if (strcmp(pszName, "KineticLaw"))
4001  pszName, "KineticLaw", mParser.getCurrentLineNumber());
4002 
4003  break;
4004 
4005  case UNKNOWN_ELEMENT:
4006  break;
4007 
4008  default:
4010  pszName, "???", mParser.getCurrentLineNumber());
4011  break;
4012  }
4013 
4014  mCurrentElement = Reaction;
4015 
4016  return;
4017 }
4018 
4020  SCopasiXMLParserCommon & common):
4022 {}
4023 
4025 {
4026  deleteCurrentHandler();
4027 }
4028 
4030  const XML_Char **papszAttrs)
4031 {
4032  mCurrentElement++; /* We should always be on the next element */
4033 
4034  switch (mCurrentElement)
4035  {
4036  case ListOfSubstrates:
4037 
4038  if (strcmp(pszName, "ListOfSubstrates"))
4040  pszName, "ListOfSubstrates", mParser.getCurrentLineNumber());
4041 
4042  break;
4043 
4044  case Substrate:
4045 
4046  if (strcmp(pszName, "Substrate"))
4048  pszName, "Substrate", mParser.getCurrentLineNumber());
4049 
4050  /* If we do not have a Substrate element handler we create one. */
4051  if (!mpCurrentHandler)
4052  mpCurrentHandler = new SubstrateElement(mParser, mCommon);
4053 
4054  /* Push the Substrate element handler on the stack and call it. */
4055  mParser.pushElementHandler(mpCurrentHandler);
4056  mpCurrentHandler->start(pszName, papszAttrs);
4057  break;
4058 
4059  default:
4060  mLastKnownElement = mCurrentElement - 1;
4061  mCurrentElement = UNKNOWN_ELEMENT;
4062  mParser.pushElementHandler(&mParser.mUnknownElement);
4063  mParser.onStartElement(pszName, papszAttrs);
4064  break;
4065  }
4066 
4067  return;
4068 }
4069 
4071 {
4072  switch (mCurrentElement)
4073  {
4074  case ListOfSubstrates:
4075 
4076  if (strcmp(pszName, "ListOfSubstrates"))
4078  pszName, "ListOfSubstrates", mParser.getCurrentLineNumber());
4079 
4080  mParser.popElementHandler();
4081  mCurrentElement = START_ELEMENT;
4082 
4083  /* Tell the parent element we are done. */
4084  mParser.onEndElement(pszName);
4085  break;
4086 
4087  case Substrate:
4088 
4089  if (strcmp(pszName, "Substrate"))
4091  pszName, "Substrate", mParser.getCurrentLineNumber());
4092 
4093  mCurrentElement = ListOfSubstrates;
4094  break;
4095 
4096  case UNKNOWN_ELEMENT:
4097  mCurrentElement = mLastKnownElement;
4098  break;
4099 
4100  default:
4102  pszName, "???", mParser.getCurrentLineNumber());
4103  break;
4104  }
4105 
4106  return;
4107 }
4108 
4110  SCopasiXMLParserCommon & common):
4112 {}
4113 
4115 {
4116  deleteCurrentHandler();
4117 }
4118 
4119 void CCopasiXMLParser::SubstrateElement::start(const XML_Char *pszName,
4120  const XML_Char **papszAttrs)
4121 {
4122  const char * Metabolite;
4123  CMetab * pMetabolite;
4124 
4125  const char * Stoichiometry;
4126 
4127  mCurrentElement++; /* We should always be on the next element */
4128 
4129  switch (mCurrentElement)
4130  {
4131  case Substrate:
4132 
4133  if (strcmp(pszName, "Substrate"))
4135  pszName, "Substrate", mParser.getCurrentLineNumber());
4136 
4137  Metabolite = mParser.getAttributeValue("metabolite", papszAttrs);
4138  Stoichiometry = mParser.getAttributeValue("stoichiometry", papszAttrs);
4139 
4140  pMetabolite = dynamic_cast< CMetab * >(mCommon.KeyMap.get(Metabolite));
4141 
4142  if (!pMetabolite) fatalError();
4143 
4144  mCommon.pReaction->addSubstrate(pMetabolite->getKey(),
4145  CCopasiXMLInterface::DBL(Stoichiometry));
4146  break;
4147 
4148  default:
4149  mLastKnownElement = mCurrentElement - 1;
4150  mCurrentElement = UNKNOWN_ELEMENT;
4151  mParser.pushElementHandler(&mParser.mUnknownElement);
4152  mParser.onStartElement(pszName, papszAttrs);
4153  break;
4154  }
4155 
4156  return;
4157 }
4158 
4159 void CCopasiXMLParser::SubstrateElement::end(const XML_Char *pszName)
4160 {
4161  switch (mCurrentElement)
4162  {
4163  case Substrate:
4164 
4165  if (strcmp(pszName, "Substrate"))
4167  pszName, "Substrate", mParser.getCurrentLineNumber());
4168 
4169  mParser.popElementHandler();
4170  mCurrentElement = START_ELEMENT;
4171 
4172  /* Tell the parent element we are done. */
4173  mParser.onEndElement(pszName);
4174  break;
4175 
4176  case UNKNOWN_ELEMENT:
4177  mCurrentElement = mLastKnownElement;
4178  break;
4179 
4180  default:
4182  pszName, "???", mParser.getCurrentLineNumber());
4183  break;
4184  }
4185 
4186  return;
4187 }
4188 
4190  SCopasiXMLParserCommon & common):
4192 {}
4193 
4195 {
4196  deleteCurrentHandler();
4197 }
4198 
4200  const XML_Char **papszAttrs)
4201 {
4202  mCurrentElement++; /* We should always be on the next element */
4203 
4204  switch (mCurrentElement)
4205  {
4206  case ListOfProducts:
4207 
4208  if (strcmp(pszName, "ListOfProducts"))
4210  pszName, "ListOfProducts", mParser.getCurrentLineNumber());
4211 
4212  break;
4213 
4214  case Product:
4215 
4216  if (strcmp(pszName, "Product"))
4218  pszName, "Product", mParser.getCurrentLineNumber());
4219 
4220  /* If we do not have a Product element handler we create one. */
4221  if (!mpCurrentHandler)
4222  mpCurrentHandler = new ProductElement(mParser, mCommon);
4223 
4224  /* Push the Product element handler on the stack and call it. */
4225  mParser.pushElementHandler(mpCurrentHandler);
4226  mpCurrentHandler->start(pszName, papszAttrs);
4227  break;
4228 
4229  default:
4230  mLastKnownElement = mCurrentElement - 1;
4231  mCurrentElement = UNKNOWN_ELEMENT;
4232  mParser.pushElementHandler(&mParser.mUnknownElement);
4233  mParser.onStartElement(pszName, papszAttrs);
4234  break;
4235  }
4236 
4237  return;
4238 }
4239 
4241 {
4242  switch (mCurrentElement)
4243  {
4244  case ListOfProducts:
4245 
4246  if (strcmp(pszName, "ListOfProducts"))
4248  pszName, "ListOfProducts", mParser.getCurrentLineNumber());
4249 
4250  mParser.popElementHandler();
4251  mCurrentElement = START_ELEMENT;
4252 
4253  /* Tell the parent element we are done. */
4254  mParser.onEndElement(pszName);
4255  break;
4256 
4257  case Product:
4258 
4259  if (strcmp(pszName, "Product"))
4261  pszName, "Product", mParser.getCurrentLineNumber());
4262 
4263  mCurrentElement = ListOfProducts;
4264  break;
4265 
4266  case UNKNOWN_ELEMENT:
4267  mCurrentElement = mLastKnownElement;
4268  break;
4269 
4270  default:
4272  pszName, "???", mParser.getCurrentLineNumber());
4273  break;
4274  }
4275 
4276  return;
4277 }
4278 
4280  SCopasiXMLParserCommon & common):
4282 {}
4283 
4285 {
4286  deleteCurrentHandler();
4287 }
4288 
4289 void CCopasiXMLParser::ProductElement::start(const XML_Char *pszName,
4290  const XML_Char **papszAttrs)
4291 {
4292  const char * Metabolite;
4293  CMetab * pMetabolite;
4294 
4295  const char * Stoichiometry;
4296 
4297  mCurrentElement++; /* We should always be on the next element */
4298 
4299  switch (mCurrentElement)
4300  {
4301  case Product:
4302 
4303  if (strcmp(pszName, "Product"))
4305  pszName, "Product", mParser.getCurrentLineNumber());
4306 
4307  Metabolite = mParser.getAttributeValue("metabolite", papszAttrs);
4308  Stoichiometry = mParser.getAttributeValue("stoichiometry", papszAttrs);
4309 
4310  pMetabolite = dynamic_cast< CMetab * >(mCommon.KeyMap.get(Metabolite));
4311 
4312  if (!pMetabolite) fatalError();
4313 
4314  mCommon.pReaction->addProduct(pMetabolite->getKey(),
4315  CCopasiXMLInterface::DBL(Stoichiometry));
4316  break;
4317 
4318  default:
4319  mLastKnownElement = mCurrentElement - 1;
4320  mCurrentElement = UNKNOWN_ELEMENT;
4321  mParser.pushElementHandler(&mParser.mUnknownElement);
4322  mParser.onStartElement(pszName, papszAttrs);
4323  break;
4324  }
4325 
4326  return;
4327 }
4328 
4329 void CCopasiXMLParser::ProductElement::end(const XML_Char *pszName)
4330 {
4331  switch (mCurrentElement)
4332  {
4333  case Product:
4334 
4335  if (strcmp(pszName, "Product"))
4337  pszName, "Product", mParser.getCurrentLineNumber());
4338 
4339  mParser.popElementHandler();
4340  mCurrentElement = START_ELEMENT;
4341 
4342  /* Tell the parent element we are done. */
4343  mParser.onEndElement(pszName);
4344  break;
4345 
4346  case UNKNOWN_ELEMENT:
4347  mCurrentElement = mLastKnownElement;
4348  break;
4349 
4350  default:
4352  pszName, "???", mParser.getCurrentLineNumber());
4353  break;
4354  }
4355 
4356  return;
4357 }
4358 
4360  SCopasiXMLParserCommon & common):
4362 {}
4363 
4365 {
4366  deleteCurrentHandler();
4367 }
4368 
4370  const XML_Char **papszAttrs)
4371 {
4372  mCurrentElement++; /* We should always be on the next element */
4373 
4374  switch (mCurrentElement)
4375  {
4376  case ListOfModifiers:
4377 
4378  if (strcmp(pszName, "ListOfModifiers"))
4380  pszName, "ListOfModifiers", mParser.getCurrentLineNumber());
4381 
4382  break;
4383 
4384  case Modifier:
4385 
4386  if (strcmp(pszName, "Modifier"))
4388  pszName, "Modifier", mParser.getCurrentLineNumber());
4389 
4390  /* If we do not have a Modifier element handler we create one. */
4391  if (!mpCurrentHandler)
4392  mpCurrentHandler = new ModifierElement(mParser, mCommon);
4393 
4394  /* Push the Modifier element handler on the stack and call it. */
4395  mParser.pushElementHandler(mpCurrentHandler);
4396  mpCurrentHandler->start(pszName, papszAttrs);
4397  break;
4398 
4399  default:
4400  mLastKnownElement = mCurrentElement - 1;
4401  mCurrentElement = UNKNOWN_ELEMENT;
4402  mParser.pushElementHandler(&mParser.mUnknownElement);
4403  mParser.onStartElement(pszName, papszAttrs);
4404  break;
4405  }
4406 
4407  return;
4408 }
4409 
4411 {
4412  switch (mCurrentElement)
4413  {
4414  case ListOfModifiers:
4415 
4416  if (strcmp(pszName, "ListOfModifiers"))
4418  pszName, "ListOfModifiers", mParser.getCurrentLineNumber());
4419 
4420  mParser.popElementHandler();
4421  mCurrentElement = START_ELEMENT;
4422 
4423  /* Tell the parent element we are done. */
4424  mParser.onEndElement(pszName);
4425  break;
4426 
4427  case Modifier:
4428 
4429  if (strcmp(pszName, "Modifier"))
4431  pszName, "Modifier", mParser.getCurrentLineNumber());
4432 
4433  mCurrentElement = ListOfModifiers;
4434  break;
4435 
4436  case UNKNOWN_ELEMENT:
4437  mCurrentElement = mLastKnownElement;
4438  break;
4439 
4440  default:
4442  pszName, "???", mParser.getCurrentLineNumber());
4443  break;
4444  }
4445 
4446  return;
4447 }
4448 
4450  SCopasiXMLParserCommon & common):
4452 {}
4453 
4455 {
4456  deleteCurrentHandler();
4457 }
4458 
4459 void CCopasiXMLParser::ModifierElement::start(const XML_Char *pszName,
4460  const XML_Char **papszAttrs)
4461 {
4462  const char * Metabolite;
4463  CMetab * pMetabolite;
4464 
4465  const char * Stoichiometry;
4466 
4467  mCurrentElement++; /* We should always be on the next element */
4468 
4469  switch (mCurrentElement)
4470  {
4471  case Modifier:
4472 
4473  if (strcmp(pszName, "Modifier"))
4475  pszName, "Modifier", mParser.getCurrentLineNumber());
4476 
4477  Metabolite = mParser.getAttributeValue("metabolite", papszAttrs);
4478  Stoichiometry = mParser.getAttributeValue("stoichiometry", papszAttrs);
4479 
4480  pMetabolite = dynamic_cast< CMetab * >(mCommon.KeyMap.get(Metabolite));
4481 
4482  if (!pMetabolite) fatalError();
4483 
4484  mCommon.pReaction->addModifier(pMetabolite->getKey(),
4485  CCopasiXMLInterface::DBL(Stoichiometry));
4486  break;
4487 
4488  default:
4489  mLastKnownElement = mCurrentElement - 1;
4490  mCurrentElement = UNKNOWN_ELEMENT;
4491  mParser.pushElementHandler(&mParser.mUnknownElement);
4492  mParser.onStartElement(pszName, papszAttrs);
4493  break;
4494  }
4495 
4496  return;
4497 }
4498 
4499 void CCopasiXMLParser::ModifierElement::end(const XML_Char *pszName)
4500 {
4501  switch (mCurrentElement)
4502  {
4503  case Modifier:
4504 
4505  if (strcmp(pszName, "Modifier"))
4507  pszName, "Modifier", mParser.getCurrentLineNumber());
4508 
4509  mParser.popElementHandler();
4510  mCurrentElement = START_ELEMENT;
4511 
4512  /* Tell the parent element we are done. */
4513  mParser.onEndElement(pszName);
4514  break;
4515 
4516  case UNKNOWN_ELEMENT:
4517  mCurrentElement = mLastKnownElement;
4518  break;
4519 
4520  default:
4522  pszName, "???", mParser.getCurrentLineNumber());
4523  break;
4524  }
4525 
4526  return;
4527 }
4528 
4530  SCopasiXMLParserCommon & common):
4532 {}
4533 
4535 {
4536  deleteCurrentHandler();
4537 }
4538 
4540  const XML_Char **papszAttrs)
4541 {
4542  mCurrentElement++; /* We should always be on the next element */
4543 
4544  switch (mCurrentElement)
4545  {
4546  case ListOfConstants:
4547 
4548  if (strcmp(pszName, "ListOfConstants"))
4550  pszName, "ListOfConstants", mParser.getCurrentLineNumber());
4551 
4553  break;
4554 
4555  case Constant:
4556 
4557  if (strcmp(pszName, "Constant"))
4559  pszName, "Constant", mParser.getCurrentLineNumber());
4560 
4561  /* If we do not have a Constant element handler we create one. */
4562  if (!mpCurrentHandler)
4563  mpCurrentHandler = new ConstantElement(mParser, mCommon);
4564 
4565  /* Push the Constant element handler on the stack and call it. */
4566  mParser.pushElementHandler(mpCurrentHandler);
4567  mpCurrentHandler->start(pszName, papszAttrs);
4568  break;
4569 
4570  default:
4571  mLastKnownElement = mCurrentElement - 1;
4572  mCurrentElement = UNKNOWN_ELEMENT;
4573  mParser.pushElementHandler(&mParser.mUnknownElement);
4574  mParser.onStartElement(pszName, papszAttrs);
4575  break;
4576  }
4577 
4578  return;
4579 }
4580 
4582 {
4583  switch (mCurrentElement)
4584  {
4585  case ListOfConstants:
4586 
4587  if (strcmp(pszName, "ListOfConstants"))
4589  pszName, "ListOfConstants", mParser.getCurrentLineNumber());
4590 
4591  mParser.popElementHandler();
4592  mCurrentElement = START_ELEMENT;
4593 
4594  /* Tell the parent element we are done. */
4595  mParser.onEndElement(pszName);
4596  break;
4597 
4598  case Constant:
4599 
4600  if (strcmp(pszName, "Constant"))
4602  pszName, "Constant", mParser.getCurrentLineNumber());
4603 
4604  mCurrentElement = ListOfConstants;
4605  break;
4606 
4607  case UNKNOWN_ELEMENT:
4608  mCurrentElement = mLastKnownElement;
4609  break;
4610 
4611  default:
4613  pszName, "???", mParser.getCurrentLineNumber());
4614  break;
4615  }
4616 
4617  return;
4618 }
4619 
4621  SCopasiXMLParserCommon & common):
4623 {}
4624 
4626 {
4627  deleteCurrentHandler();
4628 }
4629 
4630 void CCopasiXMLParser::ConstantElement::start(const XML_Char *pszName,
4631  const XML_Char **papszAttrs)
4632 {
4633  const char * Key;
4634  const char * Name;
4635  const char * Value;
4636 
4637  mCurrentElement++; /* We should always be on the next element */
4638 
4639  switch (mCurrentElement)
4640  {
4641  case Constant:
4642 
4643  if (strcmp(pszName, "Constant"))
4645  pszName, "Constant", mParser.getCurrentLineNumber());
4646 
4647  Key = mParser.getAttributeValue("key", papszAttrs);
4648  Name = mParser.getAttributeValue("name", papszAttrs);
4649  Value = mParser.getAttributeValue("value", papszAttrs);
4650 
4651  mCommon.pReaction->
4652  getParameters().addParameter(Name,
4655 
4656  addFix(Key,
4658 
4659  break;
4660 
4661  default:
4662  mLastKnownElement = mCurrentElement - 1;
4663  mCurrentElement = UNKNOWN_ELEMENT;
4664  mParser.pushElementHandler(&mParser.mUnknownElement);
4665  mParser.onStartElement(pszName, papszAttrs);
4666  break;
4667  }
4668 
4669  return;
4670 }
4671 
4672 void CCopasiXMLParser::ConstantElement::end(const XML_Char *pszName)
4673 {
4674  switch (mCurrentElement)
4675  {
4676  case Constant:
4677 
4678  if (strcmp(pszName, "Constant"))
4680  pszName, "Constant", mParser.getCurrentLineNumber());
4681 
4682  mParser.popElementHandler();
4683  mCurrentElement = START_ELEMENT;
4684 
4685  /* Tell the parent element we are done. */
4686  mParser.onEndElement(pszName);
4687  break;
4688 
4689  case UNKNOWN_ELEMENT:
4690  mCurrentElement = mLastKnownElement;
4691  break;
4692 
4693  default:
4695  pszName, "???", mParser.getCurrentLineNumber());
4696  break;
4697  }
4698 
4699  return;
4700 }
4701 
4703  SCopasiXMLParserCommon & common):
4705 {}
4706 
4708 {
4709  deleteCurrentHandler();
4710 }
4711 
4712 void CCopasiXMLParser::KineticLawElement::start(const XML_Char *pszName,
4713  const XML_Char **papszAttrs)
4714 {
4715  const char * Function;
4716 
4717  mCurrentElement++; /* We should always be on the next element */
4718 
4719  switch (mCurrentElement)
4720  {
4721  case KineticLaw:
4722 
4723  if (strcmp(pszName, "KineticLaw"))
4725  pszName, "KineticLaw", mParser.getCurrentLineNumber());
4726 
4727  Function = mParser.getAttributeValue("function", papszAttrs);
4728 
4729  mCommon.pFunction =
4730  dynamic_cast< CFunction* >(mCommon.KeyMap.get(Function));
4731 
4732  if (!mCommon.pFunction)
4733  {
4734  CCopasiMessage(CCopasiMessage::RAW, MCXML + 7, Function,
4735  mCommon.pReaction->getObjectName().c_str(),
4736  mParser.getCurrentLineNumber());
4738  }
4739 
4740  // This must be deferred till the end since we need to check for consistency
4741  // of the parameters first (Bug 832)
4742  // mCommon.pReaction->setFunction(pFunction);
4743  break;
4744 
4745  case ListOfCallParameters:
4746 
4747  if (strcmp(pszName, "ListOfCallParameters"))
4749  pszName, "ListOfCallParameters", mParser.getCurrentLineNumber());
4750 
4752  mParser.onStartElement(pszName, papszAttrs);
4753 
4754  /* If we do not have a etc element handler we create one. */
4755  if (!mpCurrentHandler)
4756  mpCurrentHandler = new ListOfCallParametersElement(mParser, mCommon);
4757 
4758  /* Push the etc element handler on the stack and call it. */
4759  mParser.pushElementHandler(mpCurrentHandler);
4760  mpCurrentHandler->start(pszName, papszAttrs);
4761  break;
4762 
4763  default:
4764  mLastKnownElement = mCurrentElement - 1;
4765  mCurrentElement = UNKNOWN_ELEMENT;
4766  mParser.pushElementHandler(&mParser.mUnknownElement);
4767  mParser.onStartElement(pszName, papszAttrs);
4768  break;
4769  }
4770 
4771  return;
4772 }
4773 
4774 void CCopasiXMLParser::KineticLawElement::end(const XML_Char *pszName)
4775 {
4776  switch (mCurrentElement)
4777  {
4778  case KineticLaw:
4779 
4780  if (strcmp(pszName, "KineticLaw"))
4782  pszName, "KineticLaw", mParser.getCurrentLineNumber());
4783 
4784  mCommon.pReaction->setFunction(dynamic_cast< CFunction * >(mCommon.pFunction));
4785 
4786  {
4787  std::map< std::string, std::vector< std::string > >::const_iterator it
4788  = mCommon.SourceParameterKeys.begin();
4789  std::map< std::string, std::vector< std::string > >::const_iterator end
4790  = mCommon.SourceParameterKeys.end();
4791 
4792  for (; it != end; ++it)
4793  if (it->second.size() > 0)
4794  mCommon.pReaction->setParameterMappingVector(it->first, it->second);
4795  }
4796  mCommon.SourceParameterKeys.clear();
4797 
4798  mParser.popElementHandler();
4799  mCurrentElement = START_ELEMENT;
4800 
4801  /* Tell the parent element we are done. */
4802  mParser.onEndElement(pszName);
4803  break;
4804 
4805  case ListOfCallParameters:
4806 
4807  if (strcmp(pszName, "ListOfCallParameters"))
4809  pszName, "ListOfCallParameters", mParser.getCurrentLineNumber());
4810 
4811  mCurrentElement = KineticLaw;
4812  break;
4813 
4814  case UNKNOWN_ELEMENT:
4815 
4817  mCurrentElement = KineticLaw;
4818  else
4819  mCurrentElement = mLastKnownElement;
4820 
4821  break;
4822 
4823  default:
4825  pszName, "???", mParser.getCurrentLineNumber());
4826  break;
4827  }
4828 
4829  return;
4830 }
4831 
4833  SCopasiXMLParserCommon & common):
4835 {}
4836 
4838 {
4839  deleteCurrentHandler();
4840 }
4841 
4843  const XML_Char **papszAttrs)
4844 {
4845  mCurrentElement++; /* We should always be on the next element */
4846 
4847  switch (mCurrentElement)
4848  {
4849  case ListOfCallParameters:
4850 
4851  if (strcmp(pszName, "ListOfCallParameters"))
4853  pszName, "ListOfCallParameters", mParser.getCurrentLineNumber());
4854 
4855  break;
4856 
4857  case CallParameter:
4858 
4859  if (strcmp(pszName, "CallParameter"))
4861  pszName, "CallParameter", mParser.getCurrentLineNumber());
4862 
4863  /* If we do not have a CallParameter element handler we create one. */
4864  if (!mpCurrentHandler)
4865  mpCurrentHandler = new CallParameterElement(mParser, mCommon);
4866 
4867  /* Push the CallParameter element handler on the stack and call it. */
4868  mParser.pushElementHandler(mpCurrentHandler);
4869  mpCurrentHandler->start(pszName, papszAttrs);
4870  break;
4871 
4872  default:
4873  mLastKnownElement = mCurrentElement - 1;
4874  mCurrentElement = UNKNOWN_ELEMENT;
4875  mParser.pushElementHandler(&mParser.mUnknownElement);
4876  mParser.onStartElement(pszName, papszAttrs);
4877  break;
4878  }
4879 
4880  return;
4881 }
4882 
4884 {
4885  switch (mCurrentElement)
4886  {
4887  case ListOfCallParameters:
4888 
4889  if (strcmp(pszName, "ListOfCallParameters"))
4891  pszName, "ListOfCallParameters", mParser.getCurrentLineNumber());
4892 
4893  mParser.popElementHandler();
4894  mCurrentElement = START_ELEMENT;
4895 
4896  /* Tell the parent element we are done. */
4897  mParser.onEndElement(pszName);
4898  break;
4899 
4900  case CallParameter:
4901 
4902  if (strcmp(pszName, "CallParameter"))
4904  pszName, "CallParameter", mParser.getCurrentLineNumber());
4905 
4906  mCurrentElement = ListOfCallParameters;
4907  break;
4908 
4909  case UNKNOWN_ELEMENT:
4910  mCurrentElement = mLastKnownElement;
4911  break;
4912 
4913  default:
4915  pszName, "???", mParser.getCurrentLineNumber());
4916  break;
4917  }
4918 
4919  return;
4920 }
4921 
4923  SCopasiXMLParserCommon & common):
4925 {}
4926 
4928 {
4929  deleteCurrentHandler();
4930 }
4931 
4933  const XML_Char **papszAttrs)
4934 {
4935  const char * FunctionParameter;
4936 
4937  mCurrentElement++; /* We should always be on the next element */
4938 
4939  switch (mCurrentElement)
4940  {
4941  case CallParameter:
4942 
4943  if (strcmp(pszName, "CallParameter"))
4945  pszName, "CallParameter", mParser.getCurrentLineNumber());
4946 
4947  FunctionParameter =
4948  mParser.getAttributeValue("functionParameter", papszAttrs);
4949 
4951  dynamic_cast< CFunctionParameter* >(mCommon.KeyMap.get(FunctionParameter));
4952 
4954  {
4955  fatalError();
4956  }
4957 
4958  break;
4959 
4960  case SourceParameter:
4961 
4962  if (strcmp(pszName, "SourceParameter"))
4964  pszName, "SourceParameter", mParser.getCurrentLineNumber());
4965 
4966  /* If we do not have a SourceParameter element handler we create one. */
4967  if (!mpCurrentHandler)
4968  mpCurrentHandler = new SourceParameterElement(mParser, mCommon);
4969 
4970  /* Push the SourceParameter element handler on the stack and call it. */
4971  mParser.pushElementHandler(mpCurrentHandler);
4972  mpCurrentHandler->start(pszName, papszAttrs);
4973  break;
4974 
4975  default:
4976  mLastKnownElement = mCurrentElement - 1;
4977  mCurrentElement = UNKNOWN_ELEMENT;
4978  mParser.pushElementHandler(&mParser.mUnknownElement);
4979  mParser.onStartElement(pszName, papszAttrs);
4980  break;
4981  }
4982 
4983  return;
4984 }
4985 
4986 void CCopasiXMLParser::CallParameterElement::end(const XML_Char *pszName)
4987 {
4988  switch (mCurrentElement)
4989  {
4990  case CallParameter:
4991 
4992  if (strcmp(pszName, "CallParameter"))
4994  pszName, "CallParameter", mParser.getCurrentLineNumber());
4995 
4996  mParser.popElementHandler();
4997  mCurrentElement = START_ELEMENT;
4998 
4999  /* Tell the parent element we are done. */
5000  mParser.onEndElement(pszName);
5001  break;
5002 
5003  case SourceParameter:
5004 
5005  if (strcmp(pszName, "SourceParameter"))
5007  pszName, "SourceParameter", mParser.getCurrentLineNumber());
5008 
5009  mCurrentElement = CallParameter;
5010  break;
5011 
5012  case UNKNOWN_ELEMENT:
5013  mCurrentElement = mLastKnownElement;
5014  break;
5015 
5016  default:
5018  pszName, "???", mParser.getCurrentLineNumber());
5019  break;
5020  }
5021 
5022  return;
5023 }
5024 
5026  SCopasiXMLParserCommon & common):
5028 {}
5029 
5031 {
5032  deleteCurrentHandler();
5033 }
5034 
5036  const XML_Char **papszAttrs)
5037 {
5038  mCurrentElement++; /* We should always be on the next element */
5039 
5040  const char * Reference;
5041  CCopasiObject * pObject;
5042  CCopasiParameter * pParameter;
5043  CModelEntity * pME;
5044 
5045  switch (mCurrentElement)
5046  {
5047  case SourceParameter:
5048 
5049  if (strcmp(pszName, "SourceParameter"))
5051  pszName, "SourceParameter", mParser.getCurrentLineNumber());
5052 
5053  Reference =
5054  mParser.getAttributeValue("reference", papszAttrs);
5055 
5056  pObject = mCommon.KeyMap.get(Reference);
5057 
5058  if ((pParameter = dynamic_cast< CCopasiParameter * >(pObject)))
5059  {
5060  // We need to assure that the parameter name for variables which are not
5061  // of type vector match.
5064 
5066  }
5067  else if ((pME = dynamic_cast<CModelEntity*>(pObject)))
5069  else
5071 
5072  break;
5073 
5074  default:
5075  mLastKnownElement = mCurrentElement - 1;
5076  mCurrentElement = UNKNOWN_ELEMENT;
5077  mParser.pushElementHandler(&mParser.mUnknownElement);
5078  mParser.onStartElement(pszName, papszAttrs);
5079  break;
5080  }
5081 
5082  return;
5083 }
5084 
5086 {
5087  switch (mCurrentElement)
5088  {
5089  case SourceParameter:
5090 
5091  if (strcmp(pszName, "SourceParameter"))
5093  pszName, "SourceParameter", mParser.getCurrentLineNumber());
5094 
5095  mParser.popElementHandler();
5096  mCurrentElement = START_ELEMENT;
5097 
5098  /* Tell the parent element we are done. */
5099  mParser.onEndElement(pszName);
5100  break;
5101 
5102  case UNKNOWN_ELEMENT:
5103  mCurrentElement = mLastKnownElement;
5104  break;
5105 
5106  default:
5108  pszName, "???", mParser.getCurrentLineNumber());
5109  break;
5110  }
5111 
5112  return;
5113 }
5114 
5116  SCopasiXMLParserCommon & common):
5118 {}
5119 
5121 {
5122  deleteCurrentHandler();
5123 }
5124 
5126  const XML_Char **papszAttrs)
5127 {
5128  mCurrentElement++; /* We should always be on the next element */
5129 
5130  switch (mCurrentElement)
5131  {
5132  case StateTemplate:
5133 
5134  if (strcmp(pszName, "StateTemplate"))
5136  pszName, "StateTemplate", mParser.getCurrentLineNumber());
5137 
5138  mCommon.StateVariableList.clear();
5139  break;
5140 
5141  case StateTemplateVariable:
5142 
5143  if (strcmp(pszName, "StateTemplateVariable"))
5145  pszName, "StateTemplateVariable", mParser.getCurrentLineNumber());
5146 
5147  /* If we do not have a StateTemplateVariable element handler we create one. */
5148  if (!mpCurrentHandler)
5149  mpCurrentHandler = new StateTemplateVariableElement(mParser, mCommon);
5150 
5151  /* Push the StateTemplateVariable element handler on the stack and call it. */
5152  mParser.pushElementHandler(mpCurrentHandler);
5153  mpCurrentHandler->start(pszName, papszAttrs);
5154  break;
5155 
5156  default:
5157  mLastKnownElement = mCurrentElement - 1;
5158  mCurrentElement = UNKNOWN_ELEMENT;
5159  mParser.pushElementHandler(&mParser.mUnknownElement);
5160  mParser.onStartElement(pszName, papszAttrs);
5161  break;
5162  }
5163 
5164  return;
5165 }
5166 
5167 void CCopasiXMLParser::StateTemplateElement::end(const XML_Char *pszName)
5168 {
5169  switch (mCurrentElement)
5170  {
5171  case StateTemplate:
5172 
5173  if (strcmp(pszName, "StateTemplate"))
5175  pszName, "StateTemplate", mParser.getCurrentLineNumber());
5176 
5177  mParser.popElementHandler();
5178  mCurrentElement = START_ELEMENT;
5179 
5180  /* Tell the parent element we are done. */
5181  mParser.onEndElement(pszName);
5182  break;
5183 
5184  case StateTemplateVariable:
5185 
5186  if (strcmp(pszName, "StateTemplateVariable"))
5188  pszName, "StateTemplateVariable", mParser.getCurrentLineNumber());
5189 
5190  mCurrentElement = StateTemplate;
5191  break;
5192 
5193  case UNKNOWN_ELEMENT:
5194  mCurrentElement = mLastKnownElement;
5195  break;
5196 
5197  default:
5199  pszName, "???", mParser.getCurrentLineNumber());
5200  break;
5201  }
5202 
5203  return;
5204 }
5205 
5207  SCopasiXMLParserCommon & common):
5209 {}
5210 
5212 {
5213  deleteCurrentHandler();
5214 }
5215 
5217  const XML_Char **papszAttrs)
5218 {
5219  const char * ObjectReference;
5220  CModelEntity * pME;
5221 
5222  mCurrentElement++; /* We should always be on the next element */
5223 
5224  switch (mCurrentElement)
5225  {
5226  case StateTemplateVariable:
5227 
5228  if (strcmp(pszName, "StateTemplateVariable"))
5230  pszName, "StateTemplateVariable", mParser.getCurrentLineNumber());
5231 
5232  ObjectReference = mParser.getAttributeValue("objectReference",
5233  papszAttrs);
5234  pME = dynamic_cast< CModelEntity * >(mCommon.KeyMap.get(ObjectReference));
5235 
5236  if (pME != NULL)
5237  mCommon.StateVariableList.push_back(pME);
5238  else
5239  fatalError();
5240 
5241  break;
5242 
5243  default:
5244  mLastKnownElement = mCurrentElement - 1;
5245  mCurrentElement = UNKNOWN_ELEMENT;
5246  mParser.pushElementHandler(&mParser.mUnknownElement);
5247  mParser.onStartElement(pszName, papszAttrs);
5248  break;
5249  }
5250 
5251  return;
5252 }
5253 
5255 {
5256  switch (mCurrentElement)
5257  {
5258  case StateTemplateVariable:
5259 
5260  if (strcmp(pszName, "StateTemplateVariable"))
5262  pszName, "StateTemplateVariable", mParser.getCurrentLineNumber());
5263 
5264  mParser.popElementHandler();
5265  mCurrentElement = START_ELEMENT;
5266 
5267  /* Tell the parent element we are done. */
5268  mParser.onEndElement(pszName);
5269  break;
5270 
5271  case UNKNOWN_ELEMENT:
5272  mCurrentElement = mLastKnownElement;
5273  break;
5274 
5275  default:
5277  pszName, "???", mParser.getCurrentLineNumber());
5278  break;
5279  }
5280 
5281  return;
5282 }
5283 
5285  SCopasiXMLParserCommon & common):
5287 {}
5288 
5290 {
5291  deleteCurrentHandler();
5292 }
5293 
5295  const XML_Char **papszAttrs)
5296 {
5297  const char * Type;
5298 
5299  mCurrentElement++; /* We should always be on the next element */
5300 
5301  switch (mCurrentElement)
5302  {
5303  case InitialState:
5304 
5305  if (strcmp(pszName, "InitialState"))
5307  pszName, "InitialState", mParser.getCurrentLineNumber());
5308 
5309  Type = mParser.getAttributeValue("type", papszAttrs, "initialState");
5310 
5311  if (strcmp(Type, "initialState")) fatalError();
5312 
5313  mParser.enableCharacterDataHandler();
5314  break;
5315 
5316  default:
5317  mLastKnownElement = mCurrentElement - 1;
5318  mCurrentElement = UNKNOWN_ELEMENT;
5319  mParser.pushElementHandler(&mParser.mUnknownElement);
5320  mParser.onStartElement(pszName, papszAttrs);
5321  break;
5322  }
5323 
5324  return;
5325 }
5326 
5327 void CCopasiXMLParser::InitialStateElement::end(const XML_Char *pszName)
5328 {
5329  std::istringstream Values;
5330  std::string StringValue;
5331  std::vector< CModelEntity * >::iterator it;
5332  std::vector< CModelEntity * >::iterator end;
5333  double Value;
5334 
5335  const CStateTemplate & Template = mCommon.pModel->getStateTemplate();
5336  CState IState = mCommon.pModel->getInitialState();
5337  C_FLOAT64 * pValues = IState.beginIndependent() - 1;
5338  size_t Index;
5339 
5340  switch (mCurrentElement)
5341  {
5342  case InitialState:
5343 
5344  if (strcmp(pszName, "InitialState"))
5346  pszName, "InitialState", mParser.getCurrentLineNumber());
5347 
5348  Values.str(mParser.getCharacterData("\x0a\x0d\t ", " "));
5349 
5350  it = mCommon.StateVariableList.begin();
5351  end = mCommon.StateVariableList.end();
5352 
5353  for (Values >> StringValue; it != end; ++it, Values >> StringValue)
5354  {
5355  if (Values.fail()) break;
5356 
5357  Value = CCopasiXMLInterface::DBL(StringValue.c_str());
5358 
5359  Index = Template.getIndex(*it);
5360 
5361  if (Index != C_INVALID_INDEX)
5362  {
5363  pValues[Index] = Value;
5364  continue;
5365  }
5366 
5367  fatalError();
5368  }
5369 
5370  if (it != end || !Values.fail() || !Values.eof())
5371  {
5372  CCopasiMessage(CCopasiMessage::EXCEPTION, MCXML + 17, mParser.getCurrentLineNumber());
5373  }
5374 
5375  mCommon.pModel->setInitialState(IState);
5376 
5377  mParser.popElementHandler();
5378  mCurrentElement = START_ELEMENT;
5379 
5380  /* Tell the parent element we are done. */
5381  mParser.onEndElement(pszName);
5382  break;
5383 
5384  case UNKNOWN_ELEMENT:
5385  mCurrentElement = mLastKnownElement;
5386  break;
5387 
5388  default:
5390  pszName, "???", mParser.getCurrentLineNumber());
5391  break;
5392  }
5393 
5394  return;
5395 }
5396 
5398  SCopasiXMLParserCommon & common):
5400 {}
5401 
5403 {
5404  deleteCurrentHandler();
5405 }
5406 
5408  const XML_Char ** papszAttrs)
5409 {
5410  mCurrentElement++; /* We should always be on the next element */
5411 
5412  switch (mCurrentElement)
5413  {
5414  case ListOfPlotItems:
5415 
5416  if (strcmp(pszName, "ListOfPlotItems"))
5418  pszName, "ListOfPlotItems", mParser.getCurrentLineNumber());
5419 
5420  break;
5421 
5422  case PlotItem:
5423 
5424  if (strcmp(pszName, "PlotItem"))
5426  pszName, "PlotItem", mParser.getCurrentLineNumber());
5427 
5428  // If we do not have a plot specification element handler, we create one
5429  if (!mpCurrentHandler)
5430  {
5431  mpCurrentHandler = new PlotItemElement(mParser, mCommon);
5432  }
5433 
5434  mParser.pushElementHandler(mpCurrentHandler);
5435  mpCurrentHandler->start(pszName, papszAttrs);
5436  break;
5437 
5438  default:
5439  mLastKnownElement = mCurrentElement - 1;
5440  mCurrentElement = UNKNOWN_ELEMENT;
5441  mParser.pushElementHandler(&mParser.mUnknownElement);
5442  mParser.onStartElement(pszName, papszAttrs);
5443  break;
5444  }
5445 
5446  return;
5447 }
5448 
5450 {
5451  switch (mCurrentElement)
5452  {
5453  case ListOfPlotItems:
5454 
5455  if (strcmp(pszName, "ListOfPlotItems"))
5457  pszName, "ListOfPlotItems", mParser.getCurrentLineNumber());
5458 
5459  mParser.popElementHandler();
5460  mCurrentElement = START_ELEMENT;
5461  mParser.onEndElement(pszName);
5462  break;
5463 
5464  case PlotItem:
5465 
5466  if (strcmp(pszName, "PlotItem"))
5468  pszName, "PlotItem", mParser.getCurrentLineNumber());
5469 
5471  mCurrentElement = ListOfPlotItems;
5472  break;
5473 
5474  case UNKNOWN_ELEMENT:
5475  mCurrentElement = mLastKnownElement;
5476  break;
5477 
5478  default:
5480  pszName, "???", mParser.getCurrentLineNumber());
5481  break;
5482  }
5483 
5484  return;
5485 }
5486 
5488  SCopasiXMLParserCommon & common):
5490 {}
5491 
5493 {
5494  deleteCurrentHandler();
5495 }
5496 
5498  const XML_Char ** papszAttrs)
5499 {
5500  mCurrentElement++; /* We should always be on the next element */
5501 
5502  switch (mCurrentElement)
5503  {
5504  case ListOfChannels:
5505 
5506  if (strcmp(pszName, "ListOfChannels"))
5508  pszName, "ListOfChannels", mParser.getCurrentLineNumber());
5509 
5510  break;
5511 
5512  case ChannelSpec:
5513 
5514  if (strcmp(pszName, "ChannelSpec"))
5516  pszName, "ChannelSpec", mParser.getCurrentLineNumber());
5517 
5518  if (!mpCurrentHandler)
5519  {
5520  mpCurrentHandler = new ChannelSpecElement(mParser, mCommon);
5521  }
5522 
5523  mParser.pushElementHandler(mpCurrentHandler);
5524  mpCurrentHandler->start(pszName, papszAttrs);
5525  break;
5526 
5527  default:
5528  mLastKnownElement = mCurrentElement - 1;
5529  mCurrentElement = UNKNOWN_ELEMENT;
5530  mParser.pushElementHandler(&mParser.mUnknownElement);
5531  mParser.onStartElement(pszName, papszAttrs);
5532  break;
5533  }
5534 
5535  return;
5536 }
5537 
5538 void CCopasiXMLParser::ListOfChannelsElement::end(const XML_Char * pszName)
5539 {
5540  switch (mCurrentElement)
5541  {
5542  case ListOfChannels:
5543 
5544  if (strcmp(pszName, "ListOfChannels"))
5546  pszName, "ListOfChannels", mParser.getCurrentLineNumber());
5547 
5548  mParser.popElementHandler();
5549  mCurrentElement = START_ELEMENT;
5550  mParser.onEndElement(pszName);
5551  break;
5552 
5553  case ChannelSpec:
5554 
5555  if (strcmp(pszName, "ChannelSpec"))
5557  pszName, "ChannelSpec", mParser.getCurrentLineNumber());
5558 
5560 
5563  mCurrentElement = ListOfChannels;
5564  break;
5565 
5566  case UNKNOWN_ELEMENT:
5567  mCurrentElement = mLastKnownElement;
5568  break;
5569 
5570  default:
5572  pszName, "???", mParser.getCurrentLineNumber());
5573  break;
5574  }
5575 
5576  return;
5577 }
5578 
5580  SCopasiXMLParserCommon & common):
5582 {}
5583 
5585 {
5586  deleteCurrentHandler();
5587 }
5588 
5589 void CCopasiXMLParser::ListOfPlotsElement::start(const XML_Char * pszName,
5590  const XML_Char ** papszAttrs)
5591 {
5592  mCurrentElement++; /* We should always be on the next element */
5593 
5594  switch (mCurrentElement)
5595  {
5596  case ListOfPlots:
5597 
5598  if (strcmp(pszName, "ListOfPlots"))
5600  pszName, "ListOfPlots", mParser.getCurrentLineNumber());
5601 
5602  if (!mCommon.pPlotList)
5603  {
5605  }
5606 
5607  break;
5608 
5609  case PlotSpecification:
5610 
5611  if (strcmp(pszName, "PlotSpecification"))
5613  pszName, "PlotSpecification", mParser.getCurrentLineNumber());
5614 
5615  // If we do not have a plot specification element handler, we create one
5616  if (!mpCurrentHandler)
5617  {
5618  mpCurrentHandler = new PlotSpecificationElement(mParser, mCommon);
5619  }
5620 
5621  mParser.pushElementHandler(mpCurrentHandler);
5622  mpCurrentHandler->start(pszName, papszAttrs);
5623  break;
5624 
5625  default:
5626  mLastKnownElement = mCurrentElement - 1;
5627  mCurrentElement = UNKNOWN_ELEMENT;
5628  mParser.pushElementHandler(&mParser.mUnknownElement);
5629  mParser.onStartElement(pszName, papszAttrs);
5630  break;
5631  }
5632 
5633  return;
5634 }
5635 
5636 void CCopasiXMLParser::ListOfPlotsElement::end(const XML_Char * pszName)
5637 {
5638  switch (mCurrentElement)
5639  {
5640  case ListOfPlots:
5641 
5642  if (strcmp(pszName, "ListOfPlots"))
5644  pszName, "ListOfPlots", mParser.getCurrentLineNumber());
5645 
5646  mParser.popElementHandler();
5647  mCurrentElement = START_ELEMENT;
5648  mParser.onEndElement(pszName);
5649  break;
5650&#