COPASI API  4.16.103
CCellDesignerImporter.cpp
Go to the documentation of this file.
1 // Copyright (C) 2011 - 2013 by Pedro Mendes, Virginia Tech Intellectual
2 // Properties, Inc., University of Heidelberg, and The University
3 // of Manchester.
4 // All rights reserved.
5 
6 #ifdef _WIN32
7 # define _USE_MATH_DEFINES // without the following define, M_PI will not be declared under windows
8 #endif // _WIN32
9 
10 #include <algorithm>
11 #include <assert.h>
12 #include <ctype.h>
13 #include <limits>
14 #include <cmath>
15 #include <sstream>
16 #include <stdlib.h> // for strtod
17 
18 #define USE_LAYOUT 1
19 #define USE_RENDER 1
20 
21 // SBML classes
22 #include <sbml/Compartment.h>
23 #include <sbml/Model.h>
24 #include <sbml/SBase.h>
25 #include <sbml/SBMLDocument.h>
26 #include <sbml/Species.h>
27 #include <sbml/xml/XMLNode.h>
28 #include <sbml/xml/XMLNamespaces.h>
29 #include <sbml/xml/XMLAttributes.h>
30 // layout classes
31 #include <sbml/packages/layout/sbml/CompartmentGlyph.h>
32 #include <sbml/packages/layout/sbml/CubicBezier.h>
33 #include <sbml/packages/layout/sbml/Curve.h>
34 #include <sbml/packages/layout/sbml/GraphicalObject.h>
35 #include <sbml/packages/layout/sbml/Layout.h>
36 #include <sbml/packages/layout/sbml/LineSegment.h>
37 #include <sbml/packages/layout/sbml/ReactionGlyph.h>
38 #include <sbml/packages/layout/sbml/SpeciesGlyph.h>
39 #include <sbml/packages/layout/sbml/SpeciesReferenceGlyph.h>
40 #include <sbml/packages/layout/sbml/SpeciesReferenceRole.h>
41 #include <sbml/packages/layout/sbml/TextGlyph.h>
42 
43 #include <sbml/packages/layout/extension/LayoutModelPlugin.h>
44 
45 // render classes
46 #include <sbml/packages/render/sbml/ColorDefinition.h>
47 #include <sbml/packages/render/sbml/Ellipse.h>
48 #include <sbml/packages/render/sbml/RenderGroup.h>
49 #include <sbml/packages/render/sbml/LocalRenderInformation.h>
50 #include <sbml/packages/render/sbml/LocalStyle.h>
51 #include <sbml/packages/render/sbml/Polygon.h>
52 #include <sbml/packages/render/sbml/Rectangle.h>
53 #include <sbml/packages/render/sbml/RelAbsVector.h>
54 #include <sbml/packages/render/sbml/RenderCurve.h>
55 #include <sbml/packages/render/sbml/RenderPoint.h>
56 
57 #include <sbml/packages/render/extension/RenderLayoutPlugin.h>
58 
59 #include "CCellDesignerImporter.h"
60 
61 #include "SBMLUtils.h"
62 
63 // TODO modifications are not imported yet
64 
65 // TODO set the role on species reference glyphs where possible, this is done on substrates and products already
66 
67 // TODO modifiers are missing
68 
69 // TODO deal with missing linkAnchor in a nicer way, e.g. find the closest
70 // TODO connection point
71 
72 // TODO import render information, e.g. start with color and font size
73 // TODO since these should be easy
74 
75 // TODO label positions on compartments are not handled
76 
77 /**
78  * Constructor that takes a pointer to an
79  * SBMLDocument.
80  * The SBMLDocument will not be copied and it will not be
81  * owned by the importer.
82  * If the pointer is not NULL, the class will try
83  * to directly convert the CellDesigner layout if there is one.
84  */
86  mpDocument(pDocument),
87  mpLayout(NULL),
88  mpLocalRenderInfo(NULL)
89 {
90  setlocale(LC_ALL, "C");
91  if (this->mpDocument != NULL &&
92  this->mpDocument->getModel() != NULL &&
93  this->mpDocument->getModel()->getAnnotation() != NULL)
94  {
95  const XMLNode* pAnnotation = this->findCellDesignerAnnotation(this->mpDocument, this->mpDocument->getModel()->getAnnotation());
96 
97  if (pAnnotation != NULL)
98  {
99  this->convertCellDesignerLayout(pAnnotation);
100  }
101  }
102 }
103 
104 /**
105  * Method to set the SBMLDocument.
106  * If the pointer is not NULL, the class will try
107  * to directly convert the CellDesigner layout if there is one.
108  */
109 void CCellDesignerImporter::setSBMLDocument(SBMLDocument* pDocument)
110 {
111  if (pDocument != this->mpDocument)
112  {
113  this->mpDocument = pDocument;
114 
115  if (this->mpDocument != NULL &&
116  this->mpDocument->getModel() != NULL &&
117  this->mpDocument->getModel()->getAnnotation() != NULL)
118  {
119  const XMLNode* pAnnotation = this->findCellDesignerAnnotation(this->mpDocument, this->mpDocument->getModel()->getAnnotation());
120 
121  if (pAnnotation != NULL)
122  {
123  this->convertCellDesignerLayout(pAnnotation);
124  }
125  }
126  else
127  {
128  if (this->mpLayout != NULL)
129  {
130  if (this->mpDocument && this->mpDocument->getModel())
131  {
132 
133  LayoutModelPlugin* lmPlugin = (LayoutModelPlugin*)this->mpDocument->getModel()->getPlugin("layout");
134 
135  if (lmPlugin != NULL)
136  {
137 
138  unsigned int i, iMax = lmPlugin->getListOfLayouts()->size();
139 
140  for (i = 0; i < iMax; ++i)
141  {
142  if (lmPlugin->getLayout(i) == this->mpLayout)
143  {
144  lmPlugin->removeLayout(i);
145  break;
146  }
147  }
148  }
149  }
150 
151  delete this->mpLayout;
152  this->mpLayout = NULL;
153  }
154  }
155  }
156 }
157 
158 /**
159  * Method to return a const poiner to the SBMLDocument.
160  */
161 const SBMLDocument* CCellDesignerImporter::getSBMLDocument() const
162 {
163  return this->mpDocument;
164 }
165 
166 /**
167  * Method to return the layout object.
168  * Since the laoyut object is owned by the importer,
169  * the caller should make a copy of the layout.
170  */
171 const Layout* CCellDesignerImporter::getLayout() const
172 {
173  return this->mpLayout;
174 }
175 
176 /**
177  * Goes through the SBMLDocument and tries to find a CellDesigner
178  * annotation.
179  * If one is found, a const pointer to the corresponding XMLNode
180  * is returned.
181  * If the current SBMLDocument is NULL or if no CellDesigner annotation
182  * is found, ULL is returned.
183  */
184 const XMLNode* CCellDesignerImporter::findCellDesignerAnnotation(SBMLDocument* pDocument, const XMLNode* pAnnotation)
185 {
186  const XMLNode* pNode = NULL;
187 
188  if (pDocument != NULL && pAnnotation != NULL)
189  {
190  const Model* pModel = pDocument->getModel();
191  std::pair<bool, std::string> celldesigner_ns_found = CCellDesignerImporter::findCellDesignerNamespace(pDocument);
192 
193  if (celldesigner_ns_found.first == true && pModel != NULL)
194  {
195  const XMLNamespaces* pNamespaces = NULL;
196  const std::string uri("http://www.sbml.org/2001/ns/celldesigner");
197  const XMLNode* pAnnoChild = NULL;
198 
199  if (pAnnotation != NULL)
200  {
201  unsigned int i, iMax = pAnnotation->getNumChildren();
202 
203  // we only search until we found the first element that fits
204  std::string ns_prefix;
205 
206  if (pAnnotation->getNamespaces().hasURI(uri))
207  {
208  ns_prefix = pAnnotation->getNamespaces().getPrefix(uri);
209  }
210  else if (pDocument->getNamespaces()->hasURI(uri))
211  {
212  ns_prefix = pDocument->getNamespaces()->getPrefix(uri);
213  }
214 
215  for (i = 0; i < iMax && pNode == NULL; ++i)
216  {
217  pAnnoChild = &pAnnotation->getChild(i);
218 
219  // check if the child has the celldesigner namespace
220  // or if the child has the celldesigner prefix
221  if (pAnnoChild != NULL)
222  {
223  // if the prefix is redefined here, it should take precedence
224  pNamespaces = &pAnnoChild->getNamespaces();
225 
226  if (pNamespaces->hasURI(uri))
227  {
228  ns_prefix = pNamespaces->getPrefix(uri);
229  }
230 
231  if (!ns_prefix.empty() && ns_prefix == pAnnoChild->getPrefix() && pAnnoChild->getName() == "extension")
232  {
233  // we have found the first cell designer annotation
234  // element
235  // check if it really is the top level cell designer anotation
236  pNode = pAnnoChild;
237  }
238  }
239  }
240  }
241  }
242  }
243 
244  return pNode;
245 }
246 
247 /**
248  * This method searches for the CellDesigner namespace in the annotation to the model
249  * as well as the annotation to the document.
250  * The method returns a pair of bool and string. The bool determines if the namespace was
251  * found and the string specifies the prefix for the namespace.
252  */
253 std::pair<bool, std::string> CCellDesignerImporter::findCellDesignerNamespace(const SBMLDocument* pDocument)
254 {
255  std::pair<bool, std::string> result(false, "");
256 
257  if (pDocument != NULL)
258  {
259  // first we look for the CellDesigner namespace in the SBMLDocument
260  // and in the model and in all children of the models annotation
261  const XMLNamespaces* pNamespaces = pDocument->getNamespaces();
262  const std::string uri("http://www.sbml.org/2001/ns/celldesigner");
263  const Model* pModel = pDocument->getModel();
264 
265  if (pNamespaces && pNamespaces->hasURI(uri))
266  {
267  result.first = true;
268  result.second = pNamespaces->getPrefix(uri);
269  }
270  else
271  {
272  if (pModel != NULL)
273  {
274  pNamespaces = pModel->getNamespaces();
275 
276  if (pNamespaces != NULL && pNamespaces->hasURI(uri))
277  {
278  result.first = true;
279  result.second = pNamespaces->getPrefix(uri);
280  }
281  else
282  {
283  // check the annotation and all its top level children
284  const XMLNode* pAnnotation = const_cast<Model*>(pModel)->getAnnotation();
285 
286  if (pAnnotation != NULL)
287  {
288  pNamespaces = &pAnnotation->getNamespaces();
289 
290  if (pNamespaces != NULL && pNamespaces->hasURI(uri))
291  {
292  result.first = true;
293  result.second = pNamespaces->getPrefix(uri);
294  }
295  else
296  {
297  unsigned int i, iMax = pAnnotation->getNumChildren();
298  const XMLNode* pChild = NULL;
299 
300  for (i = 0; i < iMax; ++i)
301  {
302  pChild = &pAnnotation->getChild(i);
303  assert(pChild != NULL);
304 
305  if (pChild != NULL)
306  {
307  pNamespaces = &pChild->getNamespaces();
308 
309  if (pNamespaces != NULL && pNamespaces->hasURI(uri))
310  {
311  result.first = true;
312  result.second = pNamespaces->getPrefix(uri);
313  break;
314  }
315  }
316  }
317  }
318  }
319  }
320  }
321  }
322  }
323 
324  return result;
325 }
326 
327 /**
328  * This method tries to convert the CellDesigner annotation to an SBML Layout.
329  * On success the method will return true and false otherwise.
330  */
331 bool CCellDesignerImporter::convertCellDesignerLayout(const XMLNode* pCellDesignerAnnotation)
332 {
333  bool result = true;
334 
335  // before we start, we make sure that all data structures
336  // are cleared
337  this->mCompartmentAliasMap.clear();
338  this->mSpeciesAliasMap.clear();
339  this->mColorStringMap.clear();
340  this->mIdMap.clear();
341  this->mCDIdToLayoutElement.clear();
342  this->mCDBounds.clear();
343  this->mSpeciesAnnotationMap.clear();
344  this->mCompartmentAnnotationMap.clear();
345  this->mSpeciesAliases.clear();
346  // actually we need to delete all nodes in the list
347  std::list<CCopasiNode<std::string>*>::iterator nit = this->mComplexDependencies.begin(), nendit = this->mComplexDependencies.end();
348 
349  while (nit != nendit)
350  {
351  delete *nit;
352  ++nit;
353  }
354 
355  this->mComplexDependencies.clear();
356  this->mModelIdToLayoutElement.clear();
357  this->mCompartmentNamePointMap.clear();
358  this->mProteinInformationMap.clear();
359  //this->mGeneNameMap.clear();
360  //this->mRNANameMap.clear();
361  //this->mASRNANameMap.clear();
362 
363  // check if we are in the top level cell designer element
364  if (pCellDesignerAnnotation != NULL &&
365  pCellDesignerAnnotation->getName() == "extension" &&
366  this->mpDocument != NULL &&
367  this->mpDocument->getModel() != NULL)
368  {
369  // we don't need the meta ids
370  std::map<std::string, const SBase*> metaids;
371  // delete all existing ids
372  SBMLUtils::collectIds(this->mpDocument->getModel(), this->mIdMap, metaids);
373 
374  LayoutModelPlugin* lmPlugin = (LayoutModelPlugin*)this->mpDocument->getModel()->getPlugin("layout");
375  assert(lmPlugin != NULL);
376  // create the layout
377  this->mpLayout = lmPlugin->createLayout();
378 
379  if (this->mpLayout != NULL)
380  {
381  // we need to find a unique id for the layout
382  std::string id = this->createUniqueId("Layout");
383  this->mpLayout->setId(id);
384  this->mpLayout->setName(id);
385  this->mIdMap.insert(std::pair<std::string, const SBase*>(id, this->mpLayout));
386 
387  // create the LocalRenderInformation
388  RenderLayoutPlugin* rlPlugin = (RenderLayoutPlugin*) this->mpLayout->getPlugin("render");
389  this->mpLocalRenderInfo = rlPlugin->createLocalRenderInformation();
390 
391  if (this->mpLocalRenderInfo != NULL)
392  {
393  // set the id of the render information
394  // set a name
395  // set a program name
396  // set the background color to white
397  this->mpLocalRenderInfo->setBackgroundColor("#FFFFFFFF");
398  this->mpLocalRenderInfo->setName("render info from celldesigner");
399  this->mpLocalRenderInfo->setProgramName("CellDesignerImporter");
400  this->mpLocalRenderInfo->setProgramVersion("0.0.1");
401  std::string render_id = this->createUniqueId("RenderInformation");
402  this->mpLocalRenderInfo->setId(id);
403  this->mIdMap.insert(std::pair<std::string, const SBase*>(render_id, this->mpLocalRenderInfo));
404  // since we use black for the edge of all objects, we create a color definition for that
405  std::string color_id = this->createUniqueId("black");
406  ColorDefinition* pBlack = this->mpLocalRenderInfo->createColorDefinition();
407 
408  if (pBlack != NULL)
409  {
410  pBlack->setId(color_id);
411  this->mIdMap.insert(std::pair<std::string, const SBase*>(color_id, pBlack));
412  pBlack->setRGBA(0, 0, 0, 255);
413  this->mColorStringMap.insert(std::pair<std::string, std::string>("#000000FF", color_id));
414  }
415  else
416  {
417  result = false;
418  }
419 
420  if (result == true)
421  {
422  // ReactionGlyphs and SpeciesReferenceGlyphs
423  result = this->createDefaultStyles();
424  }
425  }
426 
427  const XMLNode* pChild = NULL;
428 
429  double version = CCellDesignerImporter::determineVersion(pCellDesignerAnnotation);
430 
431  if (version < 4.0)
432  {
433  result = false;
434  }
435 
436  if (result == true)
437  {
438  // handle the modelDisplay element
439  pChild = CCellDesignerImporter::findChildNode(pCellDesignerAnnotation, pCellDesignerAnnotation->getPrefix(), "modelDisplay", false);
440  result = (pChild != NULL && CCellDesignerImporter::parseModelDisplay(pChild, *this->mpLayout->getDimensions()));
441  }
442 
443  if (result == true)
444  {
445  pChild = CCellDesignerImporter::findChildNode(pCellDesignerAnnotation, pCellDesignerAnnotation->getPrefix(), "listOfIncludedSpecies", false);
446 
447  if (pChild != NULL)
448  {
449  result = this->handleIncludedSpecies(pChild);
450  }
451  }
452 
453  if (result == true)
454  {
455  pChild = CCellDesignerImporter::findChildNode(pCellDesignerAnnotation, pCellDesignerAnnotation->getPrefix(), "listOfCompartmentAliases", false);
456 
457  if (pChild != NULL)
458  {
459  result = this->createCompartmentGlyphs(pChild);
460  }
461  }
462 
463  if (result == true)
464  {
465  pChild = CCellDesignerImporter::findChildNode(pCellDesignerAnnotation, pCellDesignerAnnotation->getPrefix(), "listOfSpeciesAliases", false);
466 
467  if (pChild != NULL)
468  {
469  result = this->createSpeciesGlyphs(pChild);
470  }
471  }
472 
473  if (result == true)
474  {
475  pChild = CCellDesignerImporter::findChildNode(pCellDesignerAnnotation, pCellDesignerAnnotation->getPrefix(), "listOfComplexSpeciesAliases", false);
476 
477  if (pChild != NULL)
478  {
479  result = this->createSpeciesGlyphs(pChild);
480  }
481  }
482 
483  /*
484  if(result == true)
485  {
486  pChild=CCellDesignerImporter::findChildNode(pCellDesignerAnnotation,pCellDesignerAnnotation->getPrefix(),"listOfGenes",false);
487  result = (pChild!=NULL && this->parseGeneNames(pChild));
488  }
489  if(result == true)
490  {
491  pChild=CCellDesignerImporter::findChildNode(pCellDesignerAnnotation,pCellDesignerAnnotation->getPrefix(),"listOfRNAs",false);
492  result = (pChild!=NULL && this->parseRNANames(pChild));
493  }
494  if(result == true)
495  {
496  pChild=CCellDesignerImporter::findChildNode(pCellDesignerAnnotation,pCellDesignerAnnotation->getPrefix(),"listOfAntisenseRNAs",false);
497  result = (pChild!=NULL && this->parseASRNANames(pChild));
498  }
499  */
500 
501  // go through the models reactions and find the cell designer annotations there
502  // so that we can create the edges of the graph
503  if (result)
504  {
505  result = this->convertReactionAnnotations();
506  }
507 
508  // go through the compartment annotations and create the text glyph for the names
509  if (result)
510  {
511  result = this->convertCompartmentAnnotations();
512  }
513 
514  // go through the species annotations and create the text glyph for the names
515  if (result)
516  {
517  result = this->convertSpeciesAnnotations();
518  }
519 
520  // now we need to find the correct way of drawing protein nodes
521  // for this we need the type on the protein elements
522  // this information is used when we create the styles for the species glyphs
523  // TODO the code below will only work if we know the mapping from protein reference id
524  // TODO to the corresponding species or CellDesigner species id
525  // TODO this information is stored in a proteinReference element of either the annotation
526  // TODO of the species or directly with the CellDesignerSpecies
527  if (result == true)
528  {
529  pChild = CCellDesignerImporter::findChildNode(pCellDesignerAnnotation, pCellDesignerAnnotation->getPrefix(), "listOfProteins", false);
530  result = (pChild != NULL && this->parseProteins(pChild));
531 
532  // // now we go through the protein map and set the correct type
533  // // on the SpeciesAlias for the corresponding species
534  // std::map<std::string,Protein>::const_iterator it=this->mProteinInformationMap.begin(),endit=this->mProteinInformationMap.end();
535  // std::map<std::string,SpeciesAnnotation>::iterator annoIt;
536  // std::cout << "num protein types:" << this->mProteinInformationMap.size() << std::endl;
537  // while(it != endit)
538  // {
539  // std::cout << "looking for annotation to " << it->first << std::endl;
540  // annoIt=this->mSpeciesAnnotationMap.find(it->first);
541  // if(annoIt != this->mSpeciesAnnotationMap.end())
542  // {
543  // annoIt->second.mIdentity.mSpeciesClass=it->second;
544  //}
545  // else
546  // {
547  // result=false;
548  //}
549  // ++it;
550  //}
551  }
552 
553  // go through all species glyphs and create a style for each one
554  if (result)
555  {
556  result = this->createSpeciesStyles();
557  }
558  }
559 
560  // clean up
561  if (!result && this->mpLayout != NULL)
562  {
563  if (this->mpDocument && this->mpDocument->getModel())
564  {
565  LayoutModelPlugin* lmPlugin = (LayoutModelPlugin*)this->mpDocument->getModel()->getPlugin("layout");
566 
567  if (lmPlugin != NULL)
568  {
569  unsigned int i, iMax = lmPlugin->getListOfLayouts()->size();
570 
571  for (i = 0; i < iMax; ++i)
572  {
573  if (lmPlugin->getLayout(i) == this->mpLayout)
574  {
575  lmPlugin->removeLayout(i);
576  break;
577  }
578  }
579  }
580  }
581 
582  delete this->mpLayout;
583  this->mpLayout = NULL;
584  }
585  }
586  else
587  {
588  result = false;
589  }
590 
591  return result;
592 }
593 
594 /**
595  * Creates the compartment glyphs from the given node
596  * that represents the listOfCompartmentAliases.
597  */
599 {
600  bool result = true;
601 
602  if (pLoCA != NULL && pLoCA->getName() == "listOfCompartmentAliases")
603  {
604  std::string prefix = pLoCA->getPrefix();
605  const XMLNode* pChild = NULL;
606  unsigned int i, iMax = pLoCA->getNumChildren();
607 
608  for (i = 0; i < iMax && result == true; ++i)
609  {
610  pChild = &pLoCA->getChild(i);
611 
612  if (pChild != NULL && pChild->getPrefix() == prefix && pChild->getName() == "compartmentAlias")
613  {
614  CompartmentAlias ca;
615  result = CCellDesignerImporter::parseCompartmentAlias(pChild, ca, *this->mpLayout->getDimensions());
616 
617  if (result == true)
618  {
619  result = this->createCompartmentGlyph(ca);
620  }
621  }
622  }
623  }
624  else
625  {
626  result = false;
627  }
628 
629  return result;
630 }
631 
632 /**
633  * Creates the species glyphs from the given node
634  * that represents the listOfSpeciesAliases.
635  */
637 {
638  bool result = true;
639 
640  if (pLoSA != NULL && (pLoSA->getName() == "listOfSpeciesAliases" || pLoSA->getName() == "listOfComplexSpeciesAliases"))
641  {
642  std::string prefix = pLoSA->getPrefix();
643  const XMLNode* pChild = NULL;
644  unsigned int i, iMax = pLoSA->getNumChildren();
645 
646  for (i = 0; i < iMax && result == true; ++i)
647  {
648  pChild = &pLoSA->getChild(i);
649 
650  if (pChild != NULL &&
651  pChild->getPrefix() == prefix &&
652  (pChild->getName() == "speciesAlias" || pChild->getName() == "complexSpeciesAlias"))
653  {
654  SpeciesAlias sa;
655  result = CCellDesignerImporter::parseSpeciesAlias(pChild, sa);
656 
657  if (result == true)
658  {
659  result = this->createSpeciesGlyph(sa);
660  }
661  }
662  }
663  }
664  else
665  {
666  result = false;
667  }
668 
669  return result;
670 }
671 
672 /**
673  * Creates the compartment glyph from the given
674  * compartmentAliase structure.
675  */
677 {
678  bool result = true;
679 
680  if (!ca.mId.empty())
681  {
682  CompartmentGlyph* pCGlyph = this->mpLayout->createCompartmentGlyph();
683 
684  if (pCGlyph != NULL)
685  {
686  this->mCDIdToLayoutElement.insert(std::pair<std::string, GraphicalObject*>(ca.mId, pCGlyph));
687  // create a unique id
688  std::string id = this->createUniqueId("CompartmentGlyph");
689  pCGlyph->setId(id);
690  this->mIdMap.insert(std::pair<std::string, const SBase*>(id, pCGlyph));
691 
692  // set the corresponding compartment
693  // check if a compartment with that id actually exists before making the link
694  if (!ca.mCompartment.empty() &&
695  this->mpDocument != NULL &&
696  this->mpDocument->getModel() != NULL &&
697  this->mpDocument->getModel()->getCompartment(ca.mCompartment) != NULL)
698  {
699  pCGlyph->setCompartmentId(ca.mCompartment);
700  this->mModelIdToLayoutElement.insert(std::pair<std::string, GraphicalObject*>(ca.mCompartment, pCGlyph));
701  assert(pCGlyph->getBoundingBox() != NULL);
702  pCGlyph->setBoundingBox(&ca.mBounds);
703  this->mCompartmentNamePointMap.insert(std::pair<const CompartmentGlyph*, Point>(pCGlyph, ca.mNamePoint));
704  }
705 
706  // create a style for the compartment glyph
707  result = this->createCompartmentStyle(ca, pCGlyph);
708 
709  if (result == true)
710  {
711  // store the compartment alias
712  this->mCompartmentAliasMap.insert(std::pair<const CompartmentGlyph*, CompartmentAlias>(pCGlyph, ca));
713  }
714  }
715  }
716  else
717  {
718  result = false;
719  }
720 
721  return result;
722 }
723 
724 /**
725  * Creates the species glyph from the given
726  * SpeciesAliases structure.
727  */
729 {
730  bool result = true;
731  // the speciesAlias node should
732  // have a bounds element with x,y,w and h
733  // attributes
734  SpeciesGlyph* pSGlyph = NULL;
735 
736  if (!sa.mId.empty())
737  {
738  if (sa.mComplexSpeciesAlias.empty())
739  {
740  pSGlyph = this->mpLayout->createSpeciesGlyph();
741 
742  if (pSGlyph != NULL)
743  {
744  // create unique id
745  std::string id = this->createUniqueId("SpeciesGlyph");
746  pSGlyph->setId(id);
747  this->mIdMap.insert(std::pair<std::string, const SBase*>(id, pSGlyph));
748  // set the bounds on the species glyph
749  pSGlyph->setBoundingBox(&sa.mBounds);
750  this->mCDIdToLayoutElement.insert(std::pair<std::string, GraphicalObject*>(sa.mId, pSGlyph));
751  // add the data to mCDBounds
752  this->mCDBounds.insert(std::pair<std::string, BoundingBox>(sa.mId, *pSGlyph->getBoundingBox()));
753 
754  // check if a compartment with that id actually exists before making the link
755  if (!sa.mSpecies.empty() &&
756  this->mpDocument != NULL &&
757  this->mpDocument->getModel() != NULL &&
758  this->mpDocument->getModel()->getSpecies(sa.mSpecies) != NULL)
759  {
760  pSGlyph->setSpeciesId(sa.mSpecies);
761  this->mModelIdToLayoutElement.insert(std::pair<std::string, GraphicalObject*>(sa.mSpecies, pSGlyph));
762  }
763 
764  if (result == true)
765  {
766  // store the species alias
767  this->mSpeciesAliasMap.insert(std::pair<const SpeciesGlyph*, SpeciesAlias>(pSGlyph, sa));
768  this->mSpeciesAliases.insert(std::pair<std::string, SpeciesAlias>(sa.mId, sa));
769  }
770 
771  // create a style for the object
772  //result=this->createSpeciesStyle(sa,pSGlyph->getId());
773  }
774  else
775  {
776  result = false;
777  }
778  }
779  else
780  {
781  this->addDependency(sa.mComplexSpeciesAlias, sa.mId);
782  // we need to parse the bounding box and store the information for it in
783  // mCDBounds
784  this->mCDBounds.insert(std::pair<std::string, BoundingBox>(sa.mId, sa.mBounds));
785  this->mSpeciesAliases.insert(std::pair<std::string, SpeciesAlias>(sa.mId, sa));
786  }
787  }
788  else
789  {
790  result = false;
791  }
792 
793  return result;
794 }
795 
796 /**
797  * Creates styles for all species glyphs.
798  */
800 {
801  bool result = true;
802 
803  if (this->mpLocalRenderInfo != NULL)
804  {
805  // we go through the top level species which we can get from the dependency tree
806  // for each glyph we create a primitive depending on the class of the alias
807  // for the first implementation, all classes will be represented as boxes
808  // then we will recurse into the dependency tree and create primitives for the
809  // children
810  std::map<const SpeciesGlyph*, SpeciesAlias>::const_iterator glyphs_it = this->mSpeciesAliasMap.begin(), glyphs_endit = this->mSpeciesAliasMap.end();
811  std::list<CCopasiNode<std::string>*>::const_iterator dependency_it, dependency_endit;
812 
813  while (glyphs_it != glyphs_endit)
814  {
815  std::map<std::string, SpeciesAnnotation>::const_iterator anno_pos = this->mSpeciesAnnotationMap.find(glyphs_it->second.mSpecies);
816 
817  if (anno_pos != this->mSpeciesAnnotationMap.end() && glyphs_it->first != NULL && glyphs_it->second.mComplexSpeciesAlias.empty())
818  {
819  // find the alias in the dependency map.
820  dependency_it = this->mComplexDependencies.begin();
821  dependency_endit = this->mComplexDependencies.end();
822 
823  while (dependency_it != dependency_endit)
824  {
825  if ((*dependency_it)->getData() == glyphs_it->second.mId)
826  {
827  break;
828  }
829 
830  ++dependency_it;
831  }
832 
833  if (dependency_it != dependency_endit)
834  {
835  // If we find it, we create a primitive and a text glyph
836  // and we create a style that contains all the children
837  const CCopasiNode<std::string>* pCurrent = *dependency_it;
838  assert(pCurrent != NULL);
839  std::string alias;
840  std::map<std::string, SpeciesAlias>::const_iterator alias_pos;
841  // create a style
842  std::string style_id = this->createUniqueId("ComplexSpeciesGlyphStyle");
843  LocalStyle* pStyle = this->mpLocalRenderInfo->createStyle(style_id);
844 
845  if (pStyle != NULL)
846  {
847  pStyle->setId(style_id);
848  this->mIdMap.insert(std::pair<std::string, const SBase*>(style_id, pStyle));
849  // apply the style to the glyph
850  pStyle->addId(glyphs_it->first->getId());
851  RenderGroup* pGroup = pStyle->getGroup();
852  assert(pGroup != NULL);
853  // since children of aliases should stay within the bounds of their
854  // parents, we add all children to the same group and assume
855  // that no overlap will occur
856  // this also allows us to traverse the tree depth first
857  // instead of level for level
858 
859  // all primitives we create should be relative to the glyphs bounding box
860  // sine the CellDesigner annotation contains absolute values for
861  // all coordinates, we need to subtract the species glyphs position
862  Point offset(new LayoutPkgNamespaces(), -glyphs_it->first->getBoundingBox()->getPosition()->x(), -glyphs_it->first->getBoundingBox()->getPosition()->y());
863 
864  while (pCurrent != NULL)
865  {
866  alias = pCurrent->getData();
867  assert(!alias.empty());
868  // find the corresponding SpeciesAlias entry
869  alias_pos = this->mSpeciesAliases.find(alias);
870  assert(alias_pos != this->mSpeciesAliases.end());
871  bool is_included = false;
872  std::map<std::string, std::pair<std::string, SpeciesIdentity> >::const_iterator nameMapPos;
873 
874  if (alias_pos != this->mSpeciesAliases.end())
875  {
876  SpeciesAlias sa = alias_pos->second;
877 
878  // find the corresponding SpeciesAnnotation
879  if (!sa.mSpecies.empty())
880  {
881  // create the primitive
882  std::string color_id;
883  result = this->findOrCreateColorDefinition(sa.mUView.mPaint.mColor, color_id);
884  // if we are not on the root node, we need to add a text
885  // element as well
886  std::string text;
887 
888  if (result == true && pCurrent != *dependency_it)
889  {
890  // find and add text
891  const Species* pSpecies = this->mpDocument->getModel()->getSpecies(sa.mSpecies);
892 
893  if (pSpecies == NULL)
894  {
895  // it is a CellDesignerSpecies
896  nameMapPos = this->mIncludedSpeciesNameMap.find(sa.mSpecies);
897  assert(nameMapPos != this->mIncludedSpeciesNameMap.end());
898 
899  if (nameMapPos != this->mIncludedSpeciesNameMap.end())
900  {
901  text = nameMapPos->second.first;
902  is_included = true;
903  }
904  }
905  else
906  {
907  text = pSpecies->getName();
908  }
909  }
910 
911  if (result == true)
912  {
913  if (is_included)
914  {
915  // the identity should be stored in the mIncludedSpeciesNameMap
916  result = CCellDesignerImporter::createPrimitive(pGroup, nameMapPos->second.second, alias_pos->second.mBounds, offset, 1.0, "#000000", color_id, text);
917  }
918  else
919  {
920  // the identity should be stored in the SpeciesAnnotationMap
921  // The mSpeciesAnnotationMap uses the id of an SBML species as the key
922  anno_pos = this->mSpeciesAnnotationMap.find(sa.mSpecies);
923  assert(anno_pos != this->mSpeciesAnnotationMap.end());
924 
925  if (anno_pos != this->mSpeciesAnnotationMap.end())
926  {
927  result = CCellDesignerImporter::createPrimitive(pGroup, anno_pos->second.mIdentity, alias_pos->second.mBounds, offset, 1.0, "#000000", color_id, text);
928  }
929  else
930  {
931  result = false;
932  }
933  }
934  }
935 
936  // TODO gradients are currently not considered
937  }
938  else
939  {
940  result = false;
941  }
942  }
943  else
944  {
945  result = false;
946  }
947 
948  pCurrent = pCurrent->getNext();
949  }
950  }
951  else
952  {
953  result = false;
954  }
955  }
956  else
957  {
958  // if it is not a root element in there, and if it
959  // does not have the mComplexSpeciesSpeciesAlias attribute set
960  // we assume it is a top level species and create a primitive
961  std::string style_id = this->createUniqueId("SpeciesGlyphStyle");
962  LocalStyle* pStyle = this->mpLocalRenderInfo->createStyle(style_id);
963  assert(pStyle != NULL);
964 
965  if (pStyle != NULL)
966  {
967  pStyle->setId(style_id);
968  // apply it to the glyph
969  pStyle->addId(glyphs_it->first->getId());
970  this->mIdMap.insert(std::pair<std::string, const SBase*>(style_id, pStyle));
971 
972  // find the identity for the species alias
973  if (!glyphs_it->second.mSpecies.empty())
974  {
975  std::map<std::string, SpeciesAnnotation>::const_iterator anno_pos = this->mSpeciesAnnotationMap.find(glyphs_it->second.mSpecies);
976 
977  if (anno_pos != this->mSpeciesAnnotationMap.end())
978  {
979  assert(pStyle->getGroup() != NULL);
980 
981  if (pStyle->getGroup() != NULL)
982  {
983  // all positions within the style should be relative
984  // to the glyphs bounding box, so we need to subtract
985  // the position of the glyphs bounding box from
986  // all coordinates in the style
987  std::string color_id;
988  result = this->findOrCreateColorDefinition(glyphs_it->second.mUView.mPaint.mColor, color_id);
989 
990  if (result == true)
991  {
992  result = CCellDesignerImporter::createPrimitive(pStyle->getGroup(), anno_pos->second.mIdentity, glyphs_it->second.mBounds, Point(new LayoutPkgNamespaces(), -glyphs_it->first->getBoundingBox()->getPosition()->x(), -glyphs_it->first->getBoundingBox()->getPosition()->y()), 1.0, "#000000", color_id);
993  }
994 
995  // TODO gradients are currently not considered
996  }
997  else
998  {
999  result = false;
1000  }
1001  }
1002  else
1003  {
1004  result = false;
1005  }
1006  }
1007  else
1008  {
1009  result = false;
1010  }
1011  }
1012  else
1013  {
1014  result = false;
1015  }
1016  }
1017  }
1018 
1019  ++glyphs_it;
1020  }
1021  }
1022  else
1023  {
1024  result = false;
1025  }
1026 
1027  return result;
1028 }
1029 
1030 /**
1031  * Create a primitive that corresponds to the given class
1032  * The promitive is created in the given group object.
1033  * The complete primitive is translated by the given offset.
1034  *
1035  * If creation of the primitive fails, false is returned.
1036  *
1037  */
1039  const SpeciesIdentity& si,
1040  const BoundingBox& bounds,
1041  const Point& offset,
1042  double stroke_width,
1043  const std::string& stroke_color,
1044  const std::string& fill_color,
1045  const std::string& text
1046  )
1047 {
1048  bool result = true;
1049 
1050  // maybe we should rule out all the SQUARE classes and the OVAL class
1051  // since they are probably only used for compartments
1052  // On the other hand, maybe we can use this method to create the primitives
1053  // for the compartments as well
1054  if (pGroup != NULL &&
1056  )
1057  {
1058  // if it is a protein, find the specific type
1060 
1061  if (si.mSpeciesClass == PROTEIN_CLASS && !si.mNameOrReference.empty())
1062  {
1063  std::map<std::string, Protein>::const_iterator pos = this->mProteinInformationMap.find(si.mNameOrReference);
1064 
1065  if (pos != this->mProteinInformationMap.end())
1066  {
1067  cl = pos->second.mType;
1068  }
1069  }
1070  else
1071  {
1072  cl = si.mSpeciesClass;
1073  }
1074 
1075  switch (cl)
1076  {
1077  case ION_CLASS:
1078  {
1079  double width = bounds.getDimensions()->getWidth();
1080  double height = bounds.getDimensions()->getHeight();
1081  double shortside = (width < height) ? width : height;
1082  Ellipse* pEllipse = pGroup->createEllipse();
1083  assert(pEllipse != NULL);
1084 
1085  if (pEllipse != NULL)
1086  {
1087  pEllipse->setCX(RelAbsVector(offset.x() + bounds.getPosition()->x() + width * 0.5, 0.0));
1088  pEllipse->setCY(RelAbsVector(offset.y() + bounds.getPosition()->y() + height * 0.5, 0.0));
1089  pEllipse->setRX(RelAbsVector(shortside * 0.5, 0.0));
1090  pEllipse->setRY(RelAbsVector(shortside * 0.5, 0.0));
1091  pEllipse->setStrokeWidth(stroke_width);
1092  pEllipse->setStroke(stroke_color);
1093  pEllipse->setFillColor(fill_color);
1094  }
1095  else
1096  {
1097  result = false;
1098  }
1099  }
1100  break;
1101 
1102  case UNKNOWN_CLASS:
1103  // unknown has no edge
1104  {
1105  Ellipse* pEllipse = pGroup->createEllipse();
1106  assert(pEllipse != NULL);
1107 
1108  if (pEllipse != NULL)
1109  {
1110  double width = bounds.getDimensions()->getWidth();
1111  double height = bounds.getDimensions()->getHeight();
1112  pEllipse->setCX(RelAbsVector(offset.x() + bounds.getPosition()->x() + width * 0.5, 0.0));
1113  pEllipse->setCY(RelAbsVector(offset.y() + bounds.getPosition()->y() + height * 0.5, 0.0));
1114  pEllipse->setRX(RelAbsVector(bounds.getDimensions()->getWidth() * 0.5, 0.0));
1115  pEllipse->setRY(RelAbsVector(bounds.getDimensions()->getHeight() * 0.5, 0.0));
1116  pEllipse->setFillColor(fill_color);
1117  }
1118  else
1119  {
1120  result = false;
1121  }
1122  }
1123  break;
1124 
1125  case DRUG_CLASS:
1126  // actually drug is a rectangle with rounded sides
1127  {
1128  // create two circles with radius height/2 at 10%,50% and 90%,50%
1129  // both have a fill and a black edge with stroke width 1
1130  double width = bounds.getDimensions()->getWidth();
1131  double height = bounds.getDimensions()->getHeight();
1132 
1133  // outer rectangle
1134  Rectangle* pRectangle = pGroup->createRectangle();
1135  assert(pRectangle != NULL);
1136 
1137  if (pRectangle != NULL)
1138  {
1139  pRectangle->setX(RelAbsVector(offset.x() + bounds.getPosition()->x(), 0.0));
1140  pRectangle->setY(RelAbsVector(offset.y() + bounds.getPosition()->y(), 0.0));
1141  pRectangle->setRadiusX(RelAbsVector(height * 0.5, 0.0));
1142  pRectangle->setRadiusY(RelAbsVector(height * 0.5, 0.0));
1143  pRectangle->setWidth(RelAbsVector(width, 0.0));
1144  pRectangle->setHeight(RelAbsVector(height, 0.0));
1145 
1146  pRectangle->setStrokeWidth(stroke_width);
1147  pRectangle->setStroke(stroke_color);
1148  pRectangle->setFillColor(fill_color);
1149  }
1150  else
1151  {
1152  result = false;
1153  }
1154 
1155  // inner rectangle
1156  pRectangle = pGroup->createRectangle();
1157  assert(pRectangle != NULL);
1158 
1159  if (pRectangle != NULL)
1160  {
1161  pRectangle->setX(RelAbsVector(offset.x() + bounds.getPosition()->x() + 5, 0.0));
1162  pRectangle->setY(RelAbsVector(offset.y() + bounds.getPosition()->y() + 5, 0.0));
1163  pRectangle->setRadiusX(RelAbsVector(height * 0.5 - 5, 0.0));
1164  pRectangle->setRadiusY(RelAbsVector(height * 0.5 - 5, 0.0));
1165  pRectangle->setWidth(RelAbsVector(width - 10, 0.0));
1166  pRectangle->setHeight(RelAbsVector(height - 10, 0.0));
1167 
1168  pRectangle->setStrokeWidth(stroke_width);
1169  pRectangle->setStroke(stroke_color);
1170  pRectangle->setFillColor(fill_color);
1171  }
1172  else
1173  {
1174  result = false;
1175  }
1176  }
1177  break;
1178 
1179  case SIMPLE_MOLECULE_CLASS:
1180  {
1181  Ellipse* pEllipse = pGroup->createEllipse();
1182  assert(pEllipse != NULL);
1183 
1184  if (pEllipse != NULL)
1185  {
1186  double width = bounds.getDimensions()->getWidth();
1187  double height = bounds.getDimensions()->getHeight();
1188  pEllipse->setCX(RelAbsVector(offset.x() + bounds.getPosition()->x() + width * 0.5, 0.0));
1189  pEllipse->setCY(RelAbsVector(offset.y() + bounds.getPosition()->y() + height * 0.5, 0.0));
1190  pEllipse->setRX(RelAbsVector(bounds.getDimensions()->getWidth() * 0.5, 0.0));
1191  pEllipse->setRY(RelAbsVector(bounds.getDimensions()->getHeight() * 0.5, 0.0));
1192  pEllipse->setStrokeWidth(stroke_width);
1193  pEllipse->setStroke(stroke_color);
1194  pEllipse->setFillColor(fill_color);
1195  }
1196  else
1197  {
1198  result = false;
1199  }
1200  }
1201  break;
1202 
1203  case DEGRADED_CLASS:
1204  {
1205  Ellipse* pEllipse = pGroup->createEllipse();
1206  assert(pEllipse != NULL);
1207 
1208  if (pEllipse != NULL)
1209  {
1210  double width = bounds.getDimensions()->getWidth();
1211  double height = bounds.getDimensions()->getHeight();
1212  pEllipse->setCX(RelAbsVector(offset.x() + bounds.getPosition()->x() + width * 0.5, 0.0));
1213  pEllipse->setCY(RelAbsVector(offset.y() + bounds.getPosition()->y() + height * 0.5, 0.0));
1214  double short_side = (width > height) ? height : width;
1215  pEllipse->setRX(RelAbsVector(short_side * 0.35, 0.0));
1216  pEllipse->setRY(RelAbsVector(short_side * 0.35, 0.0));
1217  pEllipse->setStrokeWidth(stroke_width);
1218  pEllipse->setStroke(stroke_color);
1219  pEllipse->setFillColor(fill_color);
1220  RenderCurve* pCurve = pGroup->createCurve();
1221  assert(pCurve != NULL);
1222 
1223  if (pCurve != NULL)
1224  {
1225  pCurve->setStrokeWidth(2.0);
1226  pCurve->setStroke("#000000FF");
1227  RenderPoint* pP = pCurve->createPoint();
1228  assert(pP != NULL);
1229 
1230  if (pP != NULL)
1231  {
1232  pP->setX((short_side - width) * 0.5);
1233  pP->setY((short_side - height) * 0.5 + short_side);
1234  pP = pCurve->createPoint();
1235  assert(pP != NULL);
1236 
1237  if (pP != NULL)
1238  {
1239  pP->setX((short_side - width) * 0.5 + short_side);
1240  pP->setY((short_side - height) * 0.5);
1241  }
1242  else
1243  {
1244  result = false;
1245  }
1246  }
1247  else
1248  {
1249  result = false;
1250  }
1251  }
1252  else
1253  {
1254  result = false;
1255  }
1256  }
1257  else
1258  {
1259  result = false;
1260  }
1261  }
1262  break;
1263 
1264  case TRUNCATED_CLASS:
1265  {
1266  // TODO the left corners should be rounded, but for now this is close enough
1267  double width = bounds.getDimensions()->getWidth();
1268  double height = bounds.getDimensions()->getHeight();
1269  // we take a fixed radius for the rounded corners
1270  double radius = 10.0;
1271  Polygon* pPoly = pGroup->createPolygon();
1272  assert(pPoly != NULL);
1273 
1274  if (pPoly != NULL)
1275  {
1276  pPoly->setStrokeWidth(stroke_width);
1277  pPoly->setStroke(stroke_color);
1278  pPoly->setFillColor(fill_color);
1279  RenderPoint* pP = pPoly->createPoint();
1280  RenderCubicBezier* pCB = NULL;
1281 
1282  if (pP != NULL)
1283  {
1284  pP->setX(RelAbsVector(radius, 0.0));
1285  pP->setY(RelAbsVector(0.0, 0.0));
1286  }
1287  else
1288  {
1289  result = false;
1290  }
1291 
1292  if (result == true)
1293  {
1294  pP = pPoly->createPoint();
1295 
1296  if (pP != NULL)
1297  {
1298  pP->setX(RelAbsVector(width, 0.0));
1299  pP->setY(RelAbsVector(0.0, 0.0));
1300  }
1301  else
1302  {
1303  result = false;
1304  }
1305  }
1306 
1307  if (result == true)
1308  {
1309  pP = pPoly->createPoint();
1310 
1311  if (pP != NULL)
1312  {
1313  pP->setX(RelAbsVector(width, 0.0));
1314  pP->setY(RelAbsVector(0.8 * height, 0.0));
1315  }
1316  else
1317  {
1318  result = false;
1319  }
1320  }
1321 
1322  if (result == true)
1323  {
1324  pP = pPoly->createPoint();
1325 
1326  if (pP != NULL)
1327  {
1328  pP->setX(RelAbsVector(0.8 * width, 0.0));
1329  pP->setY(RelAbsVector(0.5 * height, 0.0));
1330  }
1331  else
1332  {
1333  result = false;
1334  }
1335  }
1336 
1337  if (result == true)
1338  {
1339  pP = pPoly->createPoint();
1340 
1341  if (pP != NULL)
1342  {
1343  pP->setX(RelAbsVector(0.8 * width, 0.0));
1344  pP->setY(RelAbsVector(height, 0.0));
1345  }
1346  else
1347  {
1348  result = false;
1349  }
1350  }
1351 
1352  if (result == true)
1353  {
1354  pP = pPoly->createPoint();
1355 
1356  if (pP != NULL)
1357  {
1358  pP->setX(RelAbsVector(radius, 0.0));
1359  pP->setY(RelAbsVector(height, 0.0));
1360  }
1361  else
1362  {
1363  result = false;
1364  }
1365  }
1366 
1367  if (result == true)
1368  {
1369  pCB = pPoly->createCubicBezier();
1370 
1371  if (pCB != NULL)
1372  {
1373  pCB->setBasePoint1_X(RelAbsVector(0.0, 0.0));
1374  pCB->setBasePoint1_Y(RelAbsVector(height, 0.0));
1375  pCB->setBasePoint2_X(RelAbsVector(0.0, 0.0));
1376  pCB->setBasePoint2_Y(RelAbsVector(height, 0.0));
1377  pCB->setX(RelAbsVector(0.0, 0.0));
1378  pCB->setY(RelAbsVector(height - radius, 0.0));
1379  }
1380  else
1381  {
1382  result = false;
1383  }
1384  }
1385 
1386  if (result == true)
1387  {
1388  pP = pPoly->createPoint();
1389 
1390  if (pP != NULL)
1391  {
1392  pP->setX(RelAbsVector(0.0, 0.0));
1393  pP->setY(RelAbsVector(radius, 0.0));
1394  }
1395  else
1396  {
1397  result = false;
1398  }
1399  }
1400 
1401  if (result == true)
1402  {
1403  pCB = pPoly->createCubicBezier();
1404 
1405  if (pCB != NULL)
1406  {
1407  pCB->setBasePoint1_X(RelAbsVector(0.0, 0.0));
1408  pCB->setBasePoint1_Y(RelAbsVector(0.0, 0.0));
1409  pCB->setBasePoint2_X(RelAbsVector(0.0, 0.0));
1410  pCB->setBasePoint2_Y(RelAbsVector(0.0, 0.0));
1411  pCB->setX(RelAbsVector(radius, 0.0));
1412  pCB->setY(RelAbsVector(0.0, 0.0));
1413  }
1414  else
1415  {
1416  result = false;
1417  }
1418  }
1419  }
1420  else
1421  {
1422  result = false;
1423  }
1424  }
1425  break;
1426 
1427  case PROTEIN_CLASS:
1428  // make a rectangle with rounded edges
1429  {
1430  Rectangle* pRect = pGroup->createRectangle();
1431  assert(pRect != NULL);
1432 
1433  if (pRect != NULL)
1434  {
1435  pRect->setX(RelAbsVector(offset.x() + bounds.getPosition()->x(), 0.0));
1436  pRect->setY(RelAbsVector(offset.y() + bounds.getPosition()->y(), 0.0));
1437  pRect->setRadiusX(RelAbsVector(0.0, 10.0));
1438  pRect->setRadiusY(RelAbsVector(0.0, 10.0));
1439  pRect->setWidth(RelAbsVector(bounds.getDimensions()->getWidth(), 0.0));
1440  pRect->setHeight(RelAbsVector(bounds.getDimensions()->getHeight(), 0.0));
1441  pRect->setStrokeWidth(stroke_width);
1442  pRect->setStroke(stroke_color);
1443  pRect->setFillColor(fill_color);
1444  }
1445 
1446  else
1447  {
1448  result = false;
1449  }
1450 
1451  if (result == true)
1452  {
1453  // handle modifications
1454  std::vector<SpeciesModification>::const_iterator it = si.mState.mModifications.begin(), endit = si.mState.mModifications.end();
1455 
1456  while (it != endit)
1457  {
1458  result = this->createProteinModification(pGroup, *it, bounds, stroke_color);
1459  assert(result == true);
1460  ++it;
1461  }
1462  }
1463  }
1464  break;
1465 
1466  case PHENOTYPE_CLASS:
1467  {
1468  // we assume the width is larger
1469  Polygon* pPoly = pGroup->createPolygon();
1470  assert(pPoly != NULL);
1471 
1472  if (pPoly != NULL)
1473  {
1474  pPoly->setStrokeWidth(stroke_width);
1475  pPoly->setStroke(stroke_color);
1476  pPoly->setFillColor(fill_color);
1477  RenderPoint* pP = pPoly->createPoint();
1478 
1479  if (pP != NULL)
1480  {
1481  pP->setY(RelAbsVector(0.0, 0.0));
1482  pP->setY(RelAbsVector(0.0, 50.0));
1483  }
1484  else
1485  {
1486  result = false;
1487  }
1488 
1489  if (result == true)
1490  {
1491  pP = pPoly->createPoint();
1492 
1493  if (pP != NULL)
1494  {
1495  pP->setX(RelAbsVector(0.0, 15.0));
1496  pP->setY(RelAbsVector(0.0, 0.0));
1497  }
1498  else
1499  {
1500  result = false;
1501  }
1502  }
1503 
1504  if (result == true)
1505  {
1506  pP = pPoly->createPoint();
1507 
1508  if (pP != NULL)
1509  {
1510  pP->setX(RelAbsVector(0.0, 85.0));
1511  pP->setY(RelAbsVector(0.0, 0.0));
1512  }
1513  else
1514  {
1515  result = false;
1516  }
1517  }
1518 
1519  if (result == true)
1520  {
1521  pP = pPoly->createPoint();
1522 
1523  if (pP != NULL)
1524  {
1525  pP->setX(RelAbsVector(0.0, 100.0));
1526  pP->setY(RelAbsVector(0.0, 50.0));
1527  }
1528  else
1529  {
1530  result = false;
1531  }
1532  }
1533 
1534  if (result == true)
1535  {
1536  pP = pPoly->createPoint();
1537 
1538  if (pP != NULL)
1539  {
1540  pP->setX(RelAbsVector(0.0, 85.0));
1541  pP->setY(RelAbsVector(0.0, 100.0));
1542  }
1543  else
1544  {
1545  result = false;
1546  }
1547  }
1548 
1549  if (result == true)
1550  {
1551  pP = pPoly->createPoint();
1552 
1553  if (pP != NULL)
1554  {
1555  pP->setX(RelAbsVector(0.0, 15.0));
1556  pP->setY(RelAbsVector(0.0, 100.0));
1557  }
1558  else
1559  {
1560  result = false;
1561  }
1562  }
1563  }
1564  else
1565  {
1566  result = false;
1567  }
1568  }
1569  break;
1570 
1571  case RNA_CLASS:
1572  // make a trapezoid
1573  {
1574  // we assume the width is larger
1575  Polygon* pPoly = pGroup->createPolygon();
1576  assert(pPoly != NULL);
1577 
1578  if (pPoly != NULL)
1579  {
1580  pPoly->setStrokeWidth(stroke_width);
1581  pPoly->setStroke(stroke_color);
1582  pPoly->setFillColor(fill_color);
1583  RenderPoint* pP = pPoly->createPoint();
1584 
1585  if (pP != NULL)
1586  {
1587  pP->setX(RelAbsVector(0.0, 20.0));
1588  pP->setY(RelAbsVector(0.0, 0.0));
1589  }
1590  else
1591  {
1592  result = false;
1593  }
1594 
1595  if (result == true)
1596  {
1597  pP = pPoly->createPoint();
1598 
1599  if (pP != NULL)
1600  {
1601  pP->setX(RelAbsVector(0.0, 100.0));
1602  pP->setY(RelAbsVector(0.0, 0.0));
1603  }
1604  else
1605  {
1606  result = false;
1607  }
1608  }
1609 
1610  if (result == true)
1611  {
1612  pP = pPoly->createPoint();
1613 
1614  if (pP != NULL)
1615  {
1616  pP->setX(RelAbsVector(0.0, 80.0));
1617  pP->setY(RelAbsVector(0.0, 100.0));
1618  }
1619  else
1620  {
1621  result = false;
1622  }
1623  }
1624 
1625  if (result == true)
1626  {
1627  pP = pPoly->createPoint();
1628 
1629  if (pP != NULL)
1630  {
1631  pP->setX(RelAbsVector(0.0, 0.0));
1632  pP->setY(RelAbsVector(0.0, 100.0));
1633  }
1634  else
1635  {
1636  result = false;
1637  }
1638  }
1639  }
1640  else
1641  {
1642  result = false;
1643  }
1644  }
1645  break;
1646 
1647  case ANTISENSE_RNA_CLASS:
1648  // make a trapzoid
1649  {
1650  // we assume the width is larger
1651  Polygon* pPoly = pGroup->createPolygon();
1652  assert(pPoly != NULL);
1653 
1654  if (pPoly != NULL)
1655  {
1656  pPoly->setStrokeWidth(stroke_width);
1657  pPoly->setStroke(stroke_color);
1658  pPoly->setFillColor(fill_color);
1659  RenderPoint* pP = pPoly->createPoint();
1660 
1661  if (pP != NULL)
1662  {
1663  pP->setY(RelAbsVector(0.0, 0.0));
1664  pP->setY(RelAbsVector(0.0, 0.0));
1665  }
1666  else
1667  {
1668  result = false;
1669  }
1670 
1671  if (result == true)
1672  {
1673  pP = pPoly->createPoint();
1674 
1675  if (pP != NULL)
1676  {
1677  pP->setX(RelAbsVector(0.0, 80.0));
1678  pP->setY(RelAbsVector(0.0, 0.0));
1679  }
1680  else
1681  {
1682  result = false;
1683  }
1684  }
1685 
1686  if (result == true)
1687  {
1688  pP = pPoly->createPoint();
1689 
1690  if (pP != NULL)
1691  {
1692  pP->setX(RelAbsVector(0.0, 100.0));
1693  pP->setY(RelAbsVector(0.0, 100.0));
1694  }
1695  else
1696  {
1697  result = false;
1698  }
1699  }
1700 
1701  if (result == true)
1702  {
1703  pP = pPoly->createPoint();
1704 
1705  if (pP != NULL)
1706  {
1707  pP->setX(RelAbsVector(0.0, 20.0));
1708  pP->setY(RelAbsVector(0.0, 100.0));
1709  }
1710  else
1711  {
1712  result = false;
1713  }
1714  }
1715  }
1716  else
1717  {
1718  result = false;
1719  }
1720  }
1721  break;
1722 
1723  case COMPLEX_CLASS:
1724  // rectangle with cut edges
1725  {
1726  double width = bounds.getDimensions()->getWidth();
1727  double height = bounds.getDimensions()->getHeight();
1728  // we assume the width is larger
1729  double ratio = height / width;
1730  Polygon* pPoly = pGroup->createPolygon();
1731  assert(pPoly != NULL);
1732 
1733  if (pPoly != NULL)
1734  {
1735  pPoly->setStrokeWidth(stroke_width);
1736  pPoly->setStroke(stroke_color);
1737  pPoly->setFillColor(fill_color);
1738  RenderPoint* pP = pPoly->createPoint();
1739 
1740  if (pP != NULL)
1741  {
1742  pP->setX(RelAbsVector(0.0, 10.0 * ratio));
1743  pP->setY(RelAbsVector(0.0, 0.0));
1744  }
1745  else
1746  {
1747  result = false;
1748  }
1749 
1750  if (result == true)
1751  {
1752  pP = pPoly->createPoint();
1753 
1754  if (pP != NULL)
1755  {
1756  pP->setX(RelAbsVector(0.0, 100.0 - 10.0 * ratio));
1757  pP->setY(RelAbsVector(0.0, 0.0));
1758  }
1759  else
1760  {
1761  result = false;
1762  }
1763  }
1764 
1765  if (result == true)
1766  {
1767  pP = pPoly->createPoint();
1768 
1769  if (pP != NULL)
1770  {
1771  pP->setX(RelAbsVector(0.0, 100.0));
1772  pP->setY(RelAbsVector(0.0, 10.0));
1773  }
1774  else
1775  {
1776  result = false;
1777  }
1778  }
1779 
1780  if (result == true)
1781  {
1782  pP = pPoly->createPoint();
1783 
1784  if (pP != NULL)
1785  {
1786  pP->setX(RelAbsVector(0.0, 100.0));
1787  pP->setY(RelAbsVector(0.0, 90.0));
1788  }
1789  else
1790  {
1791  result = false;
1792  }
1793  }
1794 
1795  if (result == true)
1796  {
1797  pP = pPoly->createPoint();
1798 
1799  if (pP != NULL)
1800  {
1801  pP->setX(RelAbsVector(0.0, 100.0 - 10.0 * ratio));
1802  pP->setY(RelAbsVector(0.0, 100.0));
1803  }
1804  else
1805  {
1806  result = false;
1807  }
1808  }
1809 
1810  if (result == true)
1811  {
1812  pP = pPoly->createPoint();
1813 
1814  if (pP != NULL)
1815  {
1816  pP->setX(RelAbsVector(0.0, 10.0 * ratio));
1817  pP->setY(RelAbsVector(0.0, 100.0));
1818  }
1819  else
1820  {
1821  result = false;
1822  }
1823  }
1824 
1825  if (result == true)
1826  {
1827  pP = pPoly->createPoint();
1828 
1829  if (pP != NULL)
1830  {
1831  pP->setX(RelAbsVector(0.0, 0.0));
1832  pP->setY(RelAbsVector(0.0, 90.0));
1833  }
1834  else
1835  {
1836  result = false;
1837  }
1838  }
1839 
1840  if (result == true)
1841  {
1842  pP = pPoly->createPoint();
1843 
1844  if (pP != NULL)
1845  {
1846  pP->setX(RelAbsVector(0.0, 0.0));
1847  pP->setY(RelAbsVector(0.0, 10.0));
1848  }
1849  else
1850  {
1851  result = false;
1852  }
1853  }
1854  }
1855  else
1856  {
1857  result = false;
1858  }
1859  }
1860  break;
1861 
1862  case RECEPTOR_CLASS:
1863  {
1864  // we assume the width is larger
1865  Polygon* pPoly = pGroup->createPolygon();
1866  assert(pPoly != NULL);
1867 
1868  if (pPoly != NULL)
1869  {
1870  pPoly->setStrokeWidth(stroke_width);
1871  pPoly->setStroke(stroke_color);
1872  pPoly->setFillColor(fill_color);
1873  RenderPoint* pP = pPoly->createPoint();
1874 
1875  if (pP != NULL)
1876  {
1877  pP->setY(RelAbsVector(0.0, 0.0));
1878  pP->setY(RelAbsVector(0.0, 0.0));
1879  }
1880  else
1881  {
1882  result = false;
1883  }
1884 
1885  if (result == true)
1886  {
1887  pP = pPoly->createPoint();
1888 
1889  if (pP != NULL)
1890  {
1891  pP->setX(RelAbsVector(0.0, 50.0));
1892  pP->setY(RelAbsVector(0.0, 15.0));
1893  }
1894  else
1895  {
1896  result = false;
1897  }
1898  }
1899 
1900  if (result == true)
1901  {
1902  pP = pPoly->createPoint();
1903 
1904  if (pP != NULL)
1905  {
1906  pP->setX(RelAbsVector(0.0, 100.0));
1907  pP->setY(RelAbsVector(0.0, 0.0));
1908  }
1909  else
1910  {
1911  result = false;
1912  }
1913  }
1914 
1915  if (result == true)
1916  {
1917  pP = pPoly->createPoint();
1918 
1919  if (pP != NULL)
1920  {
1921  pP->setX(RelAbsVector(0.0, 100.0));
1922  pP->setY(RelAbsVector(0.0, 85.0));
1923  }
1924  else
1925  {
1926  result = false;
1927  }
1928  }
1929 
1930  if (result == true)
1931  {
1932  pP = pPoly->createPoint();
1933 
1934  if (pP != NULL)
1935  {
1936  pP->setX(RelAbsVector(0.0, 50.0));
1937  pP->setY(RelAbsVector(0.0, 100.0));
1938  }
1939  else
1940  {
1941  result = false;
1942  }
1943  }
1944 
1945  if (result == true)
1946  {
1947  pP = pPoly->createPoint();
1948 
1949  if (pP != NULL)
1950  {
1951  pP->setX(RelAbsVector(0.0, 0.0));
1952  pP->setY(RelAbsVector(0.0, 85.0));
1953  }
1954  else
1955  {
1956  result = false;
1957  }
1958  }
1959  }
1960  else
1961  {
1962  result = false;
1963  }
1964  }
1965  break;
1966 
1967  case CHANNEL_CLASS:
1968  // make two rectangles with rounded corners
1969  {
1970  double width = bounds.getDimensions()->getWidth();
1971  double height = bounds.getDimensions()->getHeight();
1972  Rectangle* pRect = pGroup->createRectangle();
1973  assert(pRect != NULL);
1974 
1975  if (pRect != NULL)
1976  {
1977  pRect->setX(RelAbsVector(offset.x() + bounds.getPosition()->x(), 0.0));
1978  pRect->setY(RelAbsVector(offset.y() + bounds.getPosition()->y(), 0.0));
1979  pRect->setRadiusX(RelAbsVector(6.0, 0.0));
1980  pRect->setRadiusY(RelAbsVector(6.0, 0.0));
1981  pRect->setWidth(RelAbsVector(width * 0.75, 0.0));
1982  pRect->setHeight(RelAbsVector(height, 0.0));
1983  pRect->setStrokeWidth(stroke_width);
1984  pRect->setStroke(stroke_color);
1985  pRect->setFillColor(fill_color);
1986  }
1987  else
1988  {
1989  result = false;
1990  }
1991 
1992  pRect = pGroup->createRectangle();
1993  assert(pRect != NULL);
1994 
1995  if (pRect != NULL)
1996  {
1997  pRect->setX(RelAbsVector(offset.x() + bounds.getPosition()->x() + width * 0.75, 0.0));
1998  pRect->setY(RelAbsVector(offset.y() + bounds.getPosition()->y(), 0.0));
1999  pRect->setWidth(RelAbsVector(width * 0.25, 0.0));
2000  pRect->setHeight(RelAbsVector(height, 0.0));
2001  pRect->setRadiusX(RelAbsVector(6.0, 0.0));
2002  pRect->setRadiusY(RelAbsVector(6.0, 0.0));
2003  pRect->setStrokeWidth(stroke_width);
2004  pRect->setStroke(stroke_color);
2005  pRect->setFillColor(fill_color);
2006  }
2007  else
2008  {
2009  result = false;
2010  }
2011  }
2012  break;
2013 
2014  case GENE_CLASS:
2015  {
2016  Rectangle* pRect = pGroup->createRectangle();
2017  assert(pRect != NULL);
2018 
2019  if (pRect != NULL)
2020  {
2021  pRect->setX(RelAbsVector(offset.x() + bounds.getPosition()->x(), 0.0));
2022  pRect->setY(RelAbsVector(offset.y() + bounds.getPosition()->y(), 0.0));
2023  pRect->setWidth(RelAbsVector(bounds.getDimensions()->getWidth(), 0.0));
2024  pRect->setHeight(RelAbsVector(bounds.getDimensions()->getHeight(), 0.0));
2025  pRect->setStrokeWidth(stroke_width);
2026  pRect->setStroke(stroke_color);
2027  pRect->setFillColor(fill_color);
2028  }
2029  else
2030  {
2031  result = false;
2032  }
2033  }
2034  break;
2035 
2036  default:
2037  result = false;
2038  break;
2039  }
2040 
2041  // create the text element
2042  if (result == true && !text.empty())
2043  {
2044  // place a text element in the box
2045  // specified by bounds
2046  Text* pText = pGroup->createText();
2047  assert(pText != NULL);
2048 
2049  if (pText != NULL)
2050  {
2051  pText->setTextAnchor(Text::ANCHOR_MIDDLE);
2052  pText->setVTextAnchor(Text::ANCHOR_MIDDLE);
2053  // middle of the box
2054  pText->setX(RelAbsVector(bounds.getPosition()->x() + offset.x() + 0.5 * bounds.getDimensions()->getWidth(), 0.0));
2055  // middle of the box
2056  pText->setY(RelAbsVector(bounds.getPosition()->y() + offset.y() + 0.5 * bounds.getDimensions()->getHeight(), 0.0));
2057  pText->setText(text);
2058  // TODO we need the font size and the font family
2059  // TODO for now we use a default
2060  pText->setFontFamily("serif");
2061  pText->setFontSize(RelAbsVector(10.0, 0.0));
2062  pText->setStroke("#000000");
2063  }
2064  else
2065  {
2066  result = false;
2067  }
2068  }
2069  }
2070  else
2071  {
2072  result = false;
2073  }
2074 
2075  return result;
2076 }
2077 
2078 /**
2079  * Takes a protein modification description and creates the corresponding primitive.
2080  */
2082  const SpeciesModification& smod,
2083  const BoundingBox& bounds,
2084  const std::string& stroke_color
2085  )
2086 {
2087  // TODO this method will place all modification in exactly the same spot, so
2088  // TODO if a protein has several modifications, they will sit on top of each other
2089  // TODO One would have to play around with CellDesigner to see how it is done there
2090  // TODO because there does not seem to be any stored information on where the
2091  // TODO modification symbol is supposed to be placed
2092  bool result = true;
2093  // this is a filled circle
2094  // the fill color is white
2095  Ellipse* pEllipse = pGroup->createEllipse();
2096  assert(pEllipse != NULL);
2097 
2098  if (pEllipse != NULL)
2099  {
2100  pEllipse->setCX(RelAbsVector(0.0, 0.0));
2101  pEllipse->setCY(RelAbsVector(0.0, 0.0));
2102  pEllipse->setRX(RelAbsVector(7.0, 0.0));
2103  pEllipse->setRY(RelAbsVector(7.0, 0.0));
2104  pEllipse->setStrokeWidth(1.0);
2105  pEllipse->setStroke(stroke_color);
2106  pEllipse->setFillColor("#FFFFFFFF");
2107  // depending on the type of modification, the string displayed in the circle varies
2108  std::string mod_string("");
2109 
2110  switch (smod.mType)
2111  {
2113  mod_string = "P";
2114  break;
2115 
2116  case ACETYLATED_MOD_TYPE:
2117  mod_string = "Ac";
2118  break;
2119 
2121  mod_string = "Ub";
2122  break;
2123 
2124  case METHYLATED_MOD_TYPE:
2125  mod_string = "Me";
2126  break;
2127 
2128  case HYDROXYLATED_MOD_TYPE:
2129  mod_string = "OH";
2130  break;
2131 
2132  case DONTCARE_MOD_TYPE:
2133  mod_string = "*";
2134  break;
2135 
2136  case UNKNOWN_MOD_TYPE:
2137  mod_string = "?";
2138  break;
2139 
2140  case GLYCOSYLATED_MOD_TYPE:
2141  mod_string = "G";
2142  break;
2143 
2145  mod_string = "My";
2146  break;
2147 
2149  mod_string = "Pa";
2150  break;
2151 
2152  case PRENYLATED_MOD_TYPE:
2153  mod_string = "Pr";
2154  break;
2155 
2156  case PROTONATED_MOD_TYPE:
2157  mod_string = "H";
2158  break;
2159 
2160  case SUFLATED_MOD_TYPE:
2161  mod_string = "S";
2162  break;
2163 
2164  default:
2165  break;
2166  }
2167 
2168  Text* pText = pGroup->createText();
2169  pText->setTextAnchor(Text::ANCHOR_MIDDLE);
2170  pText->setVTextAnchor(Text::ANCHOR_MIDDLE);
2171  pText->setX(RelAbsVector(0.0, 0.0));
2172  pText->setY(RelAbsVector(0.0, 0.0));
2173  pText->setText(mod_string);
2174  pText->setFontFamily("serif");
2175  pText->setFontSize(RelAbsVector(8.0, 0.0));
2176  pText->setStroke("#000000FF");
2177  }
2178  else
2179  {
2180  result = false;
2181  }
2182 
2183  return result;
2184 }
2185 
2186 /**
2187  * Creates a unique id with the given prefix.
2188  */
2189 std::string CCellDesignerImporter::createUniqueId(const std::string& prefix)
2190 {
2191  static std::ostringstream os;
2192  unsigned int index = 1;
2193  std::string id = prefix;
2194 
2195  while (this->mIdMap.find(id) != this->mIdMap.end())
2196  {
2197  os.str("");
2198  os << prefix;
2199  os << "_";
2200  os << index;
2201  id = os.str();
2202  ++index;
2203  }
2204 
2205  return id;
2206 }
2207 
2208 /**
2209  * Traverses the reactions of the model and looks for CellDesigner annotations.
2210  * These are used to create reaction glyphs.
2211  */
2213 {
2214  bool result = true;
2215 
2216  if (this->mpDocument != NULL)
2217  {
2218  Model* pModel = this->mpDocument->getModel();
2219 
2220  if (pModel != NULL)
2221  {
2222  unsigned int i, iMax = pModel->getNumReactions();
2223 
2224  for (i = 0; i < iMax && result == true; ++i)
2225  {
2226  result = this->convertReactionAnnotation(pModel->getReaction(i), pModel);
2227  }
2228  }
2229  else
2230  {
2231  result = false;
2232  }
2233  }
2234  else
2235  {
2236  result = false;
2237  }
2238 
2239  return result;
2240 }
2241 
2242 /**
2243  * Looks for CellDesigner annotation in the given reaction and ries to convert
2244  * the information in that annotation into a ReactionGlyph.
2245  */
2246 bool CCellDesignerImporter::convertReactionAnnotation(Reaction* pReaction, const Model* pModel)
2247 {
2248  bool result = true;
2249 
2250  if (pReaction != NULL && pModel != NULL && pReaction->getAnnotation() != NULL)
2251  {
2252  const XMLNode* pAnnotation = this->findCellDesignerAnnotation(this->mpDocument, pReaction->getAnnotation());
2253 
2254  if (pAnnotation != NULL && pAnnotation->getName() == "extension" && this->mpLayout != NULL)
2255  {
2256  // create a reaction glyph
2257  ReactionAnnotation ranno;
2258  result = this->parseReactionAnnotation(pAnnotation, ranno);
2259 
2260  if (result == true)
2261  {
2262  ReactionGlyph* pRGlyph = this->mpLayout->createReactionGlyph();
2263 
2264  if (pRGlyph != NULL)
2265  {
2266  std::string id = this->createUniqueId("ReactionGlyph");
2267  pRGlyph->setId(id);
2268  pRGlyph->setReactionId(pReaction->getId());
2269  this->mIdMap.insert(std::pair<std::string, const SBase*>(id, pRGlyph));
2270  // the reactionType element has a text element
2271  // that defines the type of reaction
2272 
2273  // the following reaction types have one reactant and one product
2274  // STATE_TRANSITION, KNOWN_TRANSITION_OMITTED, UNKNOWN_TRANSITION,
2275  // TRANSCRIPTION, TRANSLATION, TRANSPORT
2276  // I also have an example where an INHIBITION reaction has one substrate
2277  // and one product, so maybe we add some more like CATALYSIS, UNKNOWN_INHIBITION
2278  // UNKNOWN_CATALYSIS, TRANSCRITPTIONAL_INHIBITION, TRANSLATIONAL_INHIBITION,
2279  // TRANSLATIONAL_ACTIVATION, TRANSCRIPTIONAL_ACTIVATION
2280  // the following reactions have two reactants and one product
2281  // HETERODIMNER_ASSOCIATION
2282  // the following reactions have one substrate and two products:
2283  // DISSOCIATION, TRUNCATION
2284  switch (ranno.mType)
2285  {
2289  case TRANSCRIPTION_RTYPE:
2290  case TRANSLATION_RTYPE:
2291  case TRANSPORT_RTYPE:
2292  case CATALYSIS_RTYPE:
2294  case INHIBITION_RTYPE:
2300  {
2301  assert(ranno.mBaseReactants.size() == 1);
2302  assert(ranno.mBaseProducts.size() == 1);
2303  // check if both elements have a link anchor
2304  this->checkLinkAnchors(ranno.mBaseReactants[0], ranno.mBaseProducts[0]);
2305 
2306  if (ranno.mBaseReactants[0].mPosition != POSITION_UNDEFINED &&
2307  ranno.mBaseProducts[0].mPosition != POSITION_UNDEFINED &&
2308  !ranno.mBaseReactants[0].mAlias.empty() &&
2309  !ranno.mBaseProducts[0].mAlias.empty()
2310  )
2311  {
2312  // we should have a start and an end point now
2313  // and the reaction box lies in the middle between these two points
2314  std::map<std::string, BoundingBox>::const_iterator box_pos1 = this->mCDBounds.find(ranno.mBaseReactants[0].mAlias);
2315  std::map<std::string, BoundingBox>::const_iterator box_pos2 = this->mCDBounds.find(ranno.mBaseProducts[0].mAlias);
2316  assert(box_pos1 != this->mCDBounds.end());
2317  assert(box_pos2 != this->mCDBounds.end());
2318 
2319  if (box_pos1 != this->mCDBounds.end() && box_pos2 != this->mCDBounds.end())
2320  {
2321  // calculate the absolute values of all points
2322  // and put them in a vector
2323  // then we go through the vector and create
2324  // the line segments
2325  // add all edit points
2326  //
2327  // p1 stores the coordinates of the anchor point at the reactant
2328  Point p1 = CCellDesignerImporter::getPositionPoint(box_pos1->second, ranno.mBaseReactants[0].mPosition);
2329  // p2 stores the coordinates of the anchor point at the product
2330  Point p2 = CCellDesignerImporter::getPositionPoint(box_pos2->second, ranno.mBaseProducts[0].mPosition);
2331  Point v1(new LayoutPkgNamespaces(), p2.x() - p1.x(), p2.y() - p1.y());
2332  Point v2(new LayoutPkgNamespaces());
2333  result = CCellDesignerImporter::createOrthogonal(v1, v2);
2334 
2335  Point p3(new LayoutPkgNamespaces(), p1.x() + v2.x(), p1.y() + v2.y());
2336  std::vector<Point>::const_iterator pointIt = ranno.mEditPoints.mPoints.begin(), pointsEnd = ranno.mEditPoints.mPoints.end();
2337  Point p(new LayoutPkgNamespaces());
2338  std::vector<Point> points;
2339  // we add p1 and p2 to the points vector
2340  // then the values would be save and we could use the entries from the vector below
2341  // which would be save even if p1 and p2 got new values
2342  points.push_back(p1);
2343 
2344  while (pointIt != pointsEnd)
2345  {
2346  // create the absolute point
2347  p = CCellDesignerImporter::calculateAbsoluteValue(*pointIt, p1, p2, p3);
2348  points.push_back(p);
2349  ++pointIt;
2350  }
2351 
2352  points.push_back(p2);
2353 
2354  std::vector<Point> reactantPoints;
2355  pointIt = points.begin(), pointsEnd = points.end();
2356  reactantPoints.push_back(*pointIt);
2357  ++pointIt;
2358  std::vector<Point> productPoints;
2359  int index = 0;
2360  int rectangleIndex = ranno.mConnectScheme.mRectangleIndex;
2361 
2362  // rectangle index marks the segment that contains the "process symbol", i.e. the reaction glyph
2363  while (index < rectangleIndex)
2364  {
2365  reactantPoints.push_back(*pointIt);
2366  ++index;
2367  ++pointIt;
2368  }
2369 
2370  assert(pointIt != pointsEnd);
2371 
2372  if (pointIt != pointsEnd)
2373  {
2374  p2 = *pointIt;
2375  }
2376 
2377  // p2 now points to the end of the section that contains the reaction glyph
2378  // now we assing p3 to be the start of the segment that contains the reaction glyph
2379  // which is the last point we added to the reactants
2380  p3 = reactantPoints.back();
2381 
2382  double distance = CCellDesignerImporter::distance(p3, p2);
2383  Point v(new LayoutPkgNamespaces(), (p2.x() - p3.x()) / distance, (p2.y() - p3.y()) / distance);
2384  // create the curve for the reaction glyph
2385  // right now, the reaction glyph consists of a short
2386  // line segment
2387  // the curve should not be longer than 1/3 the distance
2388  distance /= 6.0;
2389 
2390  if (distance >= 7.5)
2391  {
2392  distance = 7.5;
2393  }
2394 
2395  Curve* pCurve = pRGlyph->getCurve();
2396  assert(pCurve != NULL);
2397  LineSegment* pLS = pCurve->createLineSegment();
2398  Point center(new LayoutPkgNamespaces(), (p3.x() + p2.x()) * 0.5, (p3.y() + p2.y()) * 0.5);
2399  pLS->setStart(center.x() - distance * v.x(), center.y() - distance * v.y());
2400  pLS->setEnd(center.x() + distance * v.x(), center.y() + distance * v.y());
2401  // add a new substrate point
2402  // the substrate points are in reverse order
2403  reactantPoints.push_back(*pLS->getStart());
2404  // add a new product point
2405  productPoints.push_back(*pLS->getEnd());
2406 
2407  if (pointIt == pointsEnd)
2408  {
2409  productPoints.push_back(p2);
2410  }
2411 
2412  while (pointIt != pointsEnd)
2413  {
2414  productPoints.push_back(*pointIt);
2415  ++pointIt;
2416  }
2417 
2418  // create the speciesReferenceGlyphs
2419  SpeciesReferenceGlyph* pSRefGlyph1 = pRGlyph->createSpeciesReferenceGlyph();
2420  SpeciesReferenceGlyph* pSRefGlyph2 = pRGlyph->createSpeciesReferenceGlyph();
2421  assert(pSRefGlyph1 != NULL);
2422  assert(pSRefGlyph2 != NULL);
2423 
2424  if (pSRefGlyph1 != NULL && pSRefGlyph2 != NULL)
2425  {
2426  // set the ids
2427  std::string id = this->createUniqueId("SpeciesReferenceGlyph");
2428  pSRefGlyph1->setId(id);
2429  this->mIdMap.insert(std::pair<std::string, const SBase*>(id, pSRefGlyph1));
2430  id = this->createUniqueId("SpeciesReferenceGlyph");
2431  pSRefGlyph2->setId(id);
2432  this->mIdMap.insert(std::pair<std::string, const SBase*>(id, pSRefGlyph2));
2433  // set the role
2434  pSRefGlyph1->setRole(SPECIES_ROLE_SUBSTRATE);
2435  pSRefGlyph2->setRole(SPECIES_ROLE_PRODUCT);
2436  // set the curve
2437  pCurve = pSRefGlyph1->getCurve();
2438  assert(pCurve != NULL);
2439 
2440  if (pCurve != NULL && result == true)
2441  {
2442  assert(reactantPoints.size() > 1);
2443  result = CCellDesignerImporter::createLineSegments(pCurve, reactantPoints.rbegin(), reactantPoints.rend());
2444  }
2445  else
2446  {
2447  result = false;
2448  }
2449 
2450  pCurve = pSRefGlyph2->getCurve();
2451  assert(pCurve != NULL);
2452 
2453  if (pCurve != NULL && result == true)
2454  {
2455  assert(productPoints.size() > 1);
2456  result = CCellDesignerImporter::createLineSegments(pCurve, productPoints.begin(), productPoints.end());
2457  }
2458 
2459  // make sure the role is set because setSpeciesReferenceId relies on it
2460  this->setSpeciesGlyphId(pSRefGlyph1, ranno.mBaseReactants[0]);
2461  this->setSpeciesReferenceId(pSRefGlyph1, ranno.mBaseReactants[0], pRGlyph->getReactionId());
2462  this->setSpeciesGlyphId(pSRefGlyph2, ranno.mBaseProducts[0]);
2463  this->setSpeciesReferenceId(pSRefGlyph2, ranno.mBaseProducts[0], pRGlyph->getReactionId());
2464  }
2465  else
2466  {
2467  result = false;
2468  }
2469  }
2470  else
2471  {
2472  result = false;
2473  }
2474  }
2475  else
2476  {
2477  result = false;
2478  }
2479  }
2480  break;
2481 
2482  case DISSOCIATION_RTYPE:
2483  case TRUNCATION_RTYPE:
2484  {
2485  assert(ranno.mBaseReactants.size() == 1);
2486  assert(ranno.mBaseProducts.size() == 2);
2487  // there must be some edit points
2488  assert(!ranno.mEditPoints.mPoints.empty());
2489  // there should be a tShapeIndex or an omittedShapeIndex element
2490  // that tells us, which of the points is the connection point
2491  // center_product1 - center_substrate_1)
2492  // if no tShapeIndex or omittedSHapeIndex is given, we assume it is 0
2493  Point connectionPoint(new LayoutPkgNamespaces());
2494 
2495  if (ranno.mEditPoints.mTShapeIndex < (int)ranno.mEditPoints.mPoints.size())
2496  {
2497  connectionPoint = ranno.mEditPoints.mPoints[ranno.mEditPoints.mTShapeIndex];
2498  }
2499  else if (ranno.mEditPoints.mOmittedShapeIndex < (int)ranno.mEditPoints.mPoints.size())
2500  {
2501  connectionPoint = ranno.mEditPoints.mPoints[ranno.mEditPoints.mOmittedShapeIndex];
2502  }
2503  else
2504  {
2505  connectionPoint = ranno.mEditPoints.mPoints[0];
2506  }
2507 
2508  // calculate the absolute position
2509  // the position for the relative points coordinates is calculated as
2510  // center_substrate1 + x*(center_substrate_2 - center_substrate_1)+y*(
2511  std::string alias1 = ranno.mBaseReactants[0].mAlias;
2512  assert(!alias1.empty());
2513  std::string alias2 = ranno.mBaseProducts[0].mAlias;
2514  assert(!alias2.empty());
2515  std::string alias3 = ranno.mBaseProducts[1].mAlias;
2516  assert(!alias3.empty());
2517  std::map<std::string, BoundingBox>::const_iterator pos1, pos2, pos3;
2518  pos1 = this->mCDBounds.find(alias1);
2519  assert(pos1 != this->mCDBounds.end());
2520  pos2 = this->mCDBounds.find(alias2);
2521  assert(pos2 != this->mCDBounds.end());
2522  pos3 = this->mCDBounds.find(alias3);
2523  assert(pos3 != this->mCDBounds.end());
2524 
2525  if (!alias1.empty() &&
2526  !alias3.empty() &&
2527  !alias3.empty() &&
2528  pos1 != this->mCDBounds.end() &&
2529  pos2 != this->mCDBounds.end() &&
2530  pos3 != this->mCDBounds.end())
2531  {
2532  Point p1(new LayoutPkgNamespaces(), pos1->second.getPosition()->x() + pos1->second.getDimensions()->getWidth() * 0.5, pos1->second.getPosition()->y() + pos1->second.getDimensions()->getHeight() * 0.5);
2533  Point p2(new LayoutPkgNamespaces(), pos2->second.getPosition()->x() + pos2->second.getDimensions()->getWidth() * 0.5, pos2->second.getPosition()->y() + pos2->second.getDimensions()->getHeight() * 0.5);
2534  Point p3(new LayoutPkgNamespaces(), pos3->second.getPosition()->x() + pos3->second.getDimensions()->getWidth() * 0.5, pos3->second.getPosition()->y() + pos3->second.getDimensions()->getHeight() * 0.5);
2535  Point v1(new LayoutPkgNamespaces(), p2.x() - p1.x(), p2.y() - p1.y());
2536  Point v2(new LayoutPkgNamespaces(), p3.x() - p1.x(), p3.y() - p1.y());
2537  Point p(new LayoutPkgNamespaces(), p1.x() + connectionPoint.x()*v1.x() + connectionPoint.y()*v2.x(), p1.y() + connectionPoint.x()*v1.y() + connectionPoint.y()*v2.y());
2538  // p is the start point of the reaction glyph
2539  // i.e. the point where the substrates connect
2540  // create the curve for the reaction glyph
2541  // the end point is a short distance further along the
2542  // path the the only product
2543 
2544  // first we have to check if we have linkAnchors for all
2545  // elements
2546  // if not, we create them based on the shortest distance to the
2547  // connection point
2548 
2552  assert(ranno.mBaseReactants[0].mPosition != POSITION_UNDEFINED);
2553  assert(ranno.mBaseProducts[0].mPosition != POSITION_UNDEFINED);
2554  assert(ranno.mBaseProducts[1].mPosition != POSITION_UNDEFINED);
2555 
2556  if (ranno.mBaseReactants[0].mPosition != POSITION_UNDEFINED &&
2557  ranno.mBaseProducts[0].mPosition != POSITION_UNDEFINED &&
2558  ranno.mBaseProducts[1].mPosition != POSITION_UNDEFINED)
2559  {
2560  // p is the end point of the reaction glyph
2561  // i.e. the point where the products connect
2562  // the start point is a short distance further along the
2563  // path the to the only substrate
2564  Curve* pCurve = pRGlyph->getCurve();
2565  assert(pCurve != NULL);
2566 
2567  if (pCurve != NULL)
2568  {
2569  LineSegment* pLS = pCurve->createLineSegment();
2570  assert(pLS != NULL);
2571 
2572  if (pLS != NULL)
2573  {
2574  pLS->setEnd(p.x(), p.y());
2575 
2576  Point p1 = CCellDesignerImporter::getPositionPoint(pos1->second, ranno.mBaseReactants[0].mPosition);
2577  double dist = CCellDesignerImporter::distance(p1, p);
2578  assert(dist != 0.0);
2579  Point v(new LayoutPkgNamespaces(), (p1.x() - p.x()) / dist, (p1.y() - p.y()) / dist);
2580  dist /= 3.0;
2581 
2582  if (dist > 15.0)
2583  {
2584  dist = 15.0;
2585  }
2586 
2587  pLS->setStart(p.x() + dist * v.x(), p.y() + dist * v.y());
2588 
2589  // create the species reference glyphs
2590  // since we already know the endpoint for the substrate, we start
2591  // with that
2592  SpeciesReferenceGlyph* pSRefGlyph = pRGlyph->createSpeciesReferenceGlyph();
2593  assert(pSRefGlyph != NULL);
2594 
2595  if (pSRefGlyph != NULL)
2596  {
2597  // set the curve
2598  pCurve = pSRefGlyph->getCurve();
2599 
2600  if (pCurve != NULL)
2601  {
2602  LineSegment* pLS2 = pCurve->createLineSegment();
2603  assert(pLS2 != NULL);
2604 
2605  if (pLS2 != NULL)
2606  {
2607  pLS2->setStart(pLS->getStart()->x(), pLS->getStart()->y());
2608  pLS2->setEnd(p1.x(), p1.y());
2609  }
2610  else
2611  {
2612  result = false;
2613  }
2614  }
2615  else
2616  {
2617  result = false;
2618  }
2619 
2620  // set an id
2621  std::string id = this->createUniqueId("SpeciesReferenceGlyph");
2622  pSRefGlyph->setId(id);
2623  this->mIdMap.insert(std::pair<std::string, const SBase*>(id, pSRefGlyph));
2624  // set the role
2625  pSRefGlyph->setRole(SPECIES_ROLE_SUBSTRATE);
2626  // set the species glyph id
2627  this->setSpeciesGlyphId(pSRefGlyph, ranno.mBaseReactants[0]);
2628  // set the species reference id
2629  this->setSpeciesReferenceId(pSRefGlyph, ranno.mBaseReactants[0], pRGlyph->getReactionId());
2630  }
2631  else
2632  {
2633  result = false;
2634  }
2635 
2636  // first product
2637  if (result == true)
2638  {
2639  p1 = CCellDesignerImporter::getPositionPoint(pos2->second, ranno.mBaseProducts[0].mPosition);
2640  pSRefGlyph = pRGlyph->createSpeciesReferenceGlyph();
2641  assert(pSRefGlyph != NULL);
2642 
2643  if (pSRefGlyph != NULL)
2644  {
2645  // set the curve
2646  pCurve = pSRefGlyph->getCurve();
2647 
2648  if (pCurve != NULL)
2649  {
2650  LineSegment* pLS2 = pCurve->createLineSegment();
2651  assert(pLS2 != NULL);
2652 
2653  if (pLS2 != NULL)
2654  {
2655  pLS2->setStart(pLS->getEnd()->x(), pLS->getEnd()->y());
2656  pLS2->setEnd(p1.x(), p1.y());
2657  }
2658  else
2659  {
2660  result = false;
2661  }
2662  }
2663  else
2664  {
2665  result = false;
2666  }
2667 
2668  // set an id
2669  std::string id = this->createUniqueId("SpeciesReferenceGlyph");
2670  pSRefGlyph->setId(id);
2671  this->mIdMap.insert(std::pair<std::string, const SBase*>(id, pSRefGlyph));
2672  // set the role
2673  pSRefGlyph->setRole(SPECIES_ROLE_PRODUCT);
2674  // set the species glyph id
2675  this->setSpeciesGlyphId(pSRefGlyph, ranno.mBaseProducts[0]);
2676  // set the species reference id
2677  this->setSpeciesReferenceId(pSRefGlyph, ranno.mBaseProducts[0], pRGlyph->getReactionId());
2678  }
2679  else
2680  {
2681  result = false;
2682  }
2683  }
2684 
2685  // second product
2686  if (result == true)
2687  {
2688  p1 = CCellDesignerImporter::getPositionPoint(pos3->second, ranno.mBaseProducts[1].mPosition);
2689  pSRefGlyph = pRGlyph->createSpeciesReferenceGlyph();
2690  assert(pSRefGlyph != NULL);
2691 
2692  if (pSRefGlyph != NULL)
2693  {
2694  // set the curve
2695  pCurve = pSRefGlyph->getCurve();
2696 
2697  if (pCurve != NULL)
2698  {
2699  LineSegment* pLS2 = pCurve->createLineSegment();
2700  assert(pLS2 != NULL);
2701 
2702  if (pLS2 != NULL)
2703  {
2704  pLS2->setStart(pLS->getEnd()->x(), pLS->getEnd()->y());
2705  pLS2->setEnd(p1.x(), p1.y());
2706  }
2707  else
2708  {
2709  result = false;
2710  }
2711  }
2712  else
2713  {
2714  result = false;
2715  }
2716 
2717  // set an id
2718  std::string id = this->createUniqueId("SpeciesReferenceGlyph");
2719  pSRefGlyph->setId(id);
2720  this->mIdMap.insert(std::pair<std::string, const SBase*>(id, pSRefGlyph));
2721  // set the role
2722  pSRefGlyph->setRole(SPECIES_ROLE_PRODUCT);
2723  // set the species glyph id
2724  this->setSpeciesGlyphId(pSRefGlyph, ranno.mBaseProducts[1]);
2725  // set the species reference id
2726  this->setSpeciesReferenceId(pSRefGlyph, ranno.mBaseProducts[1], pRGlyph->getReactionId());
2727  }
2728  else
2729  {
2730  result = false;
2731  }
2732  }
2733  }
2734  else
2735  {
2736  result = false;
2737  }
2738  }
2739  else
2740  {
2741  result = false;
2742  }
2743  }
2744  else
2745  {
2746  result = false;
2747  }
2748  }
2749  else
2750  {
2751  result = false;
2752  }
2753  }
2754  break;
2755 
2757  {
2758  assert(ranno.mBaseReactants.size() == 2);
2759  assert(ranno.mBaseProducts.size() == 1);
2760  // assert that all elements have a link anchor
2761  assert(!ranno.mEditPoints.mPoints.empty());
2762  // there should be a tShapeIndex or an omittedShapeIndex element
2763  // that tells us, which of the points is the connection point
2764  Point connectionPoint(new LayoutPkgNamespaces());
2765 
2766  if (ranno.mEditPoints.mTShapeIndex < (int)ranno.mEditPoints.mPoints.size())
2767  {
2768  connectionPoint = ranno.mEditPoints.mPoints[ranno.mEditPoints.mTShapeIndex];
2769  }
2770  else if (ranno.mEditPoints.mOmittedShapeIndex < (int)ranno.mEditPoints.mPoints.size())
2771  {
2772  connectionPoint = ranno.mEditPoints.mPoints[ranno.mEditPoints.mOmittedShapeIndex];
2773  }
2774  else
2775  {
2776  connectionPoint = ranno.mEditPoints.mPoints[0];
2777  }
2778 
2779  // calculate the absolute position
2780  // the position for the relative points coordinates is calculated as
2781  // center_substrat1 + x*(center_product1 - center_substrate_1)+y*(
2782  // center_product2 - center_substrate_1)
2783  // if no tShapeIndex or omittedShapeIndex is given, we assume it is 0
2784  std::string alias1 = ranno.mBaseReactants[0].mAlias;
2785  assert(!alias1.empty());
2786  std::string alias2 = ranno.mBaseReactants[1].mAlias;
2787  assert(!alias2.empty());
2788  std::string alias3 = ranno.mBaseProducts[0].mAlias;
2789  assert(!alias3.empty());
2790  std::map<std::string, BoundingBox>::const_iterator pos1, pos2, pos3;
2791  pos1 = this->mCDBounds.find(alias1);
2792  assert(pos1 != this->mCDBounds.end());
2793  pos2 = this->mCDBounds.find(alias2);
2794  assert(pos2 != this->mCDBounds.end());
2795  pos3 = this->mCDBounds.find(alias3);
2796  assert(pos3 != this->mCDBounds.end());
2797 
2798  if (!alias1.empty() &&
2799  !alias3.empty() &&
2800  !alias3.empty() &&
2801  pos1 != this->mCDBounds.end() &&
2802  pos2 != this->mCDBounds.end() &&
2803  pos3 != this->mCDBounds.end())
2804  {
2805  Point p1(new LayoutPkgNamespaces(), pos1->second.getPosition()->x() + pos1->second.getDimensions()->getWidth() * 0.5, pos1->second.getPosition()->y() + pos1->second.getDimensions()->getHeight() * 0.5);
2806  Point p2(new LayoutPkgNamespaces(), pos2->second.getPosition()->x() + pos2->second.getDimensions()->getWidth() * 0.5, pos2->second.getPosition()->y() + pos2->second.getDimensions()->getHeight() * 0.5);
2807  Point p3(new LayoutPkgNamespaces(), pos3->second.getPosition()->x() + pos3->second.getDimensions()->getWidth() * 0.5, pos3->second.getPosition()->y() + pos3->second.getDimensions()->getHeight() * 0.5);
2808 
2809  Point p = CCellDesignerImporter::calculateAbsoluteValue(connectionPoint, p1, p2, p3);
2810 
2811  // first we have to check if we have linkAnchors for all
2812  // elements
2813  // if not, we create them based on the shortest distance to the
2814  // connection point
2818  assert(ranno.mBaseReactants[0].mPosition != POSITION_UNDEFINED);
2819  assert(ranno.mBaseReactants[1].mPosition != POSITION_UNDEFINED);
2820  assert(ranno.mBaseProducts[0].mPosition != POSITION_UNDEFINED);
2821 
2822  if (ranno.mBaseReactants[0].mPosition != POSITION_UNDEFINED &&
2823  ranno.mBaseReactants[1].mPosition != POSITION_UNDEFINED &&
2824  ranno.mBaseProducts[0].mPosition != POSITION_UNDEFINED)
2825  {
2826  // p is the start point of the reaction glyph
2827  // i.e. the point where the substrates connect
2828  // create the curve for the reaction glyph
2829  // the end point is a short distance further along the
2830  // path the to the only product
2831  Curve* pCurve = pRGlyph->getCurve();
2832  assert(pCurve != NULL);
2833 
2834  if (pCurve != NULL)
2835  {
2836  LineSegment* pLS = pCurve->createLineSegment();
2837  assert(pLS != NULL);
2838 
2839  if (pLS != NULL)
2840  {
2841  pLS->setStart(p.x(), p.y());
2842 
2843  Point p3 = CCellDesignerImporter::getPositionPoint(pos3->second, ranno.mBaseProducts[0].mPosition);
2844  double dist = CCellDesignerImporter::distance(p3, p);
2845  assert(dist != 0.0);
2846  Point v(new LayoutPkgNamespaces(), (p3.x() - p.x()) / dist, (p3.y() - p.y()) / dist);
2847  dist /= 3.0;
2848 
2849  if (dist > 15.0)
2850  {
2851  dist = 15.0;
2852  }
2853 
2854  pLS->setEnd(p.x() + dist * v.x(), p.y() + dist * v.y());
2855 
2856  // create the species reference glyphs
2857  // since we already know the endpoint for the product, we start
2858  // with that
2859  SpeciesReferenceGlyph* pSRefGlyph = pRGlyph->createSpeciesReferenceGlyph();
2860  assert(pSRefGlyph != NULL);
2861 
2862  if (pSRefGlyph != NULL)
2863  {
2864  // set the curve
2865  pCurve = pSRefGlyph->getCurve();
2866 
2867  if (pCurve != NULL)
2868  {
2869  LineSegment* pLS2 = pCurve->createLineSegment();
2870  assert(pLS2 != NULL);
2871 
2872  if (pLS2 != NULL)
2873  {
2874  pLS2->setStart(p.x(), p.y());
2875  pLS2->setEnd(p3.x(), p3.y());
2876  }
2877  else
2878  {
2879  result = false;
2880  }
2881  }
2882  else
2883  {
2884  result = false;
2885  }
2886 
2887  // set an id
2888  std::string id = this->createUniqueId("SpeciesReferenceGlyph");
2889  pSRefGlyph->setId(id);
2890  this->mIdMap.insert(std::pair<std::string, const SBase*>(id, pSRefGlyph));
2891  // set the role
2892  pSRefGlyph->setRole(SPECIES_ROLE_PRODUCT);
2893  // set the species glyph id
2894  this->setSpeciesGlyphId(pSRefGlyph, ranno.mBaseProducts[0]);
2895  // set the species reference id
2896  this->setSpeciesReferenceId(pSRefGlyph, ranno.mBaseProducts[0], pRGlyph->getReactionId());
2897  }
2898  else
2899  {
2900  result = false;
2901  }
2902 
2903  // first substrate
2904  if (result == true)
2905  {
2906  p3 = CCellDesignerImporter::getPositionPoint(pos1->second, ranno.mBaseReactants[0].mPosition);
2907  pSRefGlyph = pRGlyph->createSpeciesReferenceGlyph();
2908  assert(pSRefGlyph != NULL);
2909 
2910  if (pSRefGlyph != NULL)
2911  {
2912  // set the curve
2913  pCurve = pSRefGlyph->getCurve();
2914 
2915  if (pCurve != NULL)
2916  {
2917  LineSegment* pLS2 = pCurve->createLineSegment();
2918  assert(pLS2 != NULL);
2919 
2920  if (pLS2 != NULL)
2921  {
2922  pLS2->setStart(pLS->getStart()->x(), pLS->getStart()->y());
2923  pLS2->setEnd(p3.x(), p3.y());
2924  }
2925  else
2926  {
2927  result = false;
2928  }
2929  }
2930  else
2931  {
2932  result = false;
2933  }
2934 
2935  // set an id
2936  std::string id = this->createUniqueId("SpeciesReferenceGlyph");
2937  pSRefGlyph->setId(id);
2938  this->mIdMap.insert(std::pair<std::string, const SBase*>(id, pSRefGlyph));
2939  // set the role
2940  pSRefGlyph->setRole(SPECIES_ROLE_SUBSTRATE);
2941  // set the species glyph id
2942  this->setSpeciesGlyphId(pSRefGlyph, ranno.mBaseReactants[0]);
2943  // set the species reference id
2944  this->setSpeciesReferenceId(pSRefGlyph, ranno.mBaseReactants[0], pRGlyph->getReactionId());
2945  }
2946  else
2947  {
2948  result = false;
2949  }
2950  }
2951 
2952  // second substrate
2953  if (result == true)
2954  {
2955  p3 = CCellDesignerImporter::getPositionPoint(pos2->second, ranno.mBaseReactants[1].mPosition);
2956  pSRefGlyph = pRGlyph->createSpeciesReferenceGlyph();
2957  assert(pSRefGlyph != NULL);
2958 
2959  if (pSRefGlyph != NULL)
2960  {
2961  // set the curve
2962  pCurve = pSRefGlyph->getCurve();
2963 
2964  if (pCurve != NULL)
2965  {
2966  LineSegment* pLS2 = pCurve->createLineSegment();
2967  assert(pLS2 != NULL);
2968 
2969  if (pLS2 != NULL)
2970  {
2971  pLS2->setStart(pLS->getStart()->x(), pLS->getStart()->y());
2972  pLS2->setEnd(p3.x(), p3.y());
2973  }
2974  else
2975  {
2976  result = false;
2977  }
2978  }
2979  else
2980  {
2981  result = false;
2982  }
2983 
2984  // set an id
2985  std::string id = this->createUniqueId("SpeciesReferenceGlyph");
2986  pSRefGlyph->setId(id);
2987  this->mIdMap.insert(std::pair<std::string, const SBase*>(id, pSRefGlyph));
2988  // set the role
2989  pSRefGlyph->setRole(SPECIES_ROLE_SUBSTRATE);
2990  // set the species glyph id
2991  this->setSpeciesGlyphId(pSRefGlyph, ranno.mBaseReactants[1]);
2992  // set the species reference id
2993  this->setSpeciesReferenceId(pSRefGlyph, ranno.mBaseReactants[1], pRGlyph->getReactionId());
2994  }
2995  else
2996  {
2997  result = false;
2998  }
2999  }
3000  }
3001  else
3002  {
3003  result = false;
3004  }
3005  }
3006  else
3007  {
3008  result = false;
3009  }
3010  }
3011  else
3012  {
3013  result = false;
3014  }
3015  }
3016  else
3017  {
3018  result = false;
3019  }
3020  }
3021  break;
3022 
3023  default:
3024  result = false;
3025  break;
3026  }
3027 
3028  // there might be additional substrates and reactants
3029  // in the listOfReactantLinks and the listOfProductLinks
3030  if (result == true)
3031  {
3032  result = this->handleExtraReactionElements(pRGlyph, ranno, true);
3033  }
3034 
3035  if (result == true)
3036  {
3037  result = this->handleExtraReactionElements(pRGlyph, ranno, false);
3038  }
3039 
3040  // now that the species reference glyphs are handled,
3041  // we should handle the modifiers
3042  if (result == true)
3043  {
3044  result = this->handleModificationLinks(pRGlyph, ranno);
3045  }
3046  }
3047  else
3048  {
3049  result = false;
3050  }
3051  }
3052  }
3053  }
3054  else
3055  {
3056  result = false;
3057  }
3058 
3059  return result;
3060 }
3061 
3062 /**
3063  * Takes a node that contains a number of baseReactants or baseProducts
3064  * and creates species reference glyphs for each one.
3065  */
3066 bool CCellDesignerImporter::createSpeciesReferenceGlyphs(ReactionGlyph* pRGlyph, const std::vector<LinkTarget>& links, std::map<SpeciesReferenceGlyph*, Point>& startsMap, bool reactants)
3067 {
3068  bool result = true;
3069  startsMap.clear();
3070 
3071  if (pRGlyph != NULL)
3072  {
3073  unsigned int i, iMax = links.size();
3074  const LinkTarget* pLink = NULL;
3075 
3076  for (i = 0; i < iMax && result == true; ++i)
3077  {
3078  pLink = &links[i];
3079 
3080  // a baseProduct or baseReactant node has an alias attribute
3081  if (!pLink->mAlias.empty())
3082  {
3083  // if the alias points to an element within a complexSpeciesReference,
3084  // we don't get a valid position here because we never created elements for this
3085  // aliases.
3086  // we need to store them and their size in another map so that we can determine where
3087  // the arrow is supposed to go
3088  std::map<std::string, BoundingBox>::const_iterator pos = this->mCDBounds.find(pLink->mAlias);
3089 
3090  if (pos != this->mCDBounds.end())
3091  {
3092  // now we have to find the layout element that corresponds to this alias
3093  // there are two posibilities
3094  // a) the alias belongs directly to the layout element
3095  // b) the alias is part of a complex and the complex root
3096  // represents the layout element
3097  std::map<std::string, GraphicalObject*>::const_iterator go_pos = this->mCDIdToLayoutElement.find(pLink->mAlias);
3098 
3099  if (go_pos == this->mCDIdToLayoutElement.end())
3100  {
3101  std::string alias = this->findRootElementId(pLink->mAlias);
3102  // make sure we found the dependency
3103  assert(!alias.empty());
3104 
3105  // nit should now point to the root of the tree
3106  // and the data of that root should correspond to the CD Id
3107  // of a layout object
3108  if (!alias.empty())
3109  {
3110  go_pos = this->mCDIdToLayoutElement.find(alias);
3111  assert(go_pos != this->mCDIdToLayoutElement.end());
3112 
3113  if (go_pos == this->mCDIdToLayoutElement.end())
3114  {
3115  result = false;
3116  }
3117  }
3118  }
3119 
3120  if (result == true)
3121  {
3122  SpeciesReferenceGlyph* pSRG = pRGlyph->createSpeciesReferenceGlyph();
3123 
3124  if (pSRG != NULL)
3125  {
3126  std::string id = this->createUniqueId("SpeciesReferenceGlyph");
3127  pSRG->setId(id);
3128  this->mIdMap.insert(std::pair<std::string, const SBase*>(id, pSRG));
3129  assert(go_pos->second != NULL);
3130  pSRG->setSpeciesGlyphId(go_pos->second->getId());
3131 
3132  // and a species attribute. The species attribute can be used to
3133  // determine the species reference the glyph belongs to
3134  if (!pLink->mSpecies.empty() &&
3135  !pRGlyph->getReactionId().empty() &&
3136  this->mpDocument != NULL &&
3137  this->mpDocument->getModel() != NULL)
3138  {
3139  Reaction* pReaction = this->mpDocument->getModel()->getReaction(pRGlyph->getReactionId());
3140 
3141  if (pReaction != NULL)
3142  {
3143  // check if we have a substrate or a product
3144  if (reactants == true)
3145  {
3146  pSRG->setRole("SUBSTRATE");
3147  // look for the species reference in the listOfReactants of the reaction
3148  id = pLink->mSpecies;
3149  // the id we get here can be the id of a cell designer species
3150  // in that case we can't associate the species reference glyph
3151  // with an SBML species reference
3152  unsigned int i, iMax = pReaction->getNumReactants();
3153 
3154  for (i = 0; i < iMax; ++i)
3155  {
3156  if (pReaction->getReactant(i)->getSpecies() == id)
3157  {
3158  break;
3159  }
3160  }
3161 
3162  if (i != iMax)
3163  {
3164  // check if the species reference has an id, if not, we create one
3165  if (!pReaction->getReactant(i)->isSetId())
3166  {
3167  id = this->createUniqueId("SpeciesReference");
3168  pReaction->getReactant(i)->setId(id);
3169  this->mIdMap.insert(std::pair<std::string, const SBase*>(id, pReaction->getReactant(i)));
3170  }
3171 
3172  id = pReaction->getReactant(i)->getId();
3173  pSRG->setSpeciesReferenceId(id);
3174  }
3175  }
3176  else
3177  {
3178  pSRG->setRole("PRODUCT");
3179  // look for the species reference in the listOfReactants of the reaction
3180  id = pLink->mSpecies;
3181  // the id we get here can be the id of a cell designer species
3182  // in that case we can't associate the species reference glyph
3183  // with an SBML species reference
3184  unsigned int i, iMax = pReaction->getNumProducts();
3185 
3186  for (i = 0; i < iMax; ++i)
3187  {
3188  if (pReaction->getProduct(i)->getSpecies() == id)
3189  {
3190  break;
3191  }
3192  }
3193 
3194  if (i != iMax)
3195  {
3196  // check if the species reference has an id, if not, we create one
3197  if (!pReaction->getProduct(i)->isSetId())
3198  {
3199  id = this->createUniqueId("SpeciesReference");
3200  pReaction->getProduct(i)->setId(id);
3201  this->mIdMap.insert(std::pair<std::string, const SBase*>(id, pReaction->getProduct(i)));
3202  }
3203 
3204  id = pReaction->getProduct(i)->getId();
3205  pSRG->setSpeciesReferenceId(id);
3206  }
3207  }
3208  }
3209  else
3210  {
3211  result = false;
3212  }
3213  }
3214 
3215  // the node has a child called linkAnchor with a position attribute
3216  // The attribute is an enum that can be converted to an angle or
3217  // a position on the bounding box of the associated species glyph
3218  if (result == true)
3219  {
3220  if (pLink->mPosition != POSITION_UNDEFINED)
3221  {
3222  // get the point on the boundingbox of the species glyph
3223  // that corresponds to position
3224  Point p = this->getPositionPoint(pos->second, pLink->mPosition);
3225  startsMap.insert(std::pair<SpeciesReferenceGlyph*, Point>(pSRG, p));
3226  }
3227  else
3228  {
3229  // there are actually elements that do not have the linkAnchor
3230  // since I currently don't know what to do with these, I just add the
3231  // origin as position
3232  startsMap.insert(std::pair<SpeciesReferenceGlyph*, Point>(pSRG, Point(new LayoutPkgNamespaces(), 0.0, 0.0)));
3233  }
3234  }
3235  }
3236  else
3237  {
3238  result = false;
3239  }
3240  }
3241  }
3242  else
3243  {
3244  result = false;
3245  }
3246  }
3247  else
3248  {
3249  result = false;
3250  }
3251  }
3252  }
3253  else
3254  {
3255  result = false;
3256  }
3257 
3258  return result;
3259 }
3260 
3261 /**
3262  * Takes a bounding box and a position string and retirns the position on the bounding box that corresponds
3263  * to the given position.
3264  */
3265 Point CCellDesignerImporter::getPositionPoint(const BoundingBox& box, POSITION position)
3266 {
3267  double x = std::numeric_limits<double>::quiet_NaN(), y = std::numeric_limits<double>::quiet_NaN();
3268  double bx = box.getPosition()->x();
3269  double by = box.getPosition()->y();
3270  double bw = box.getDimensions()->getWidth();
3271  double bh = box.getDimensions()->getHeight();
3272 
3273  switch (position)
3274  {
3275  case POSITION_N:
3276  // top
3277  x = bx + bw * 0.5;
3278  y = by;
3279  break;
3280 
3281  case POSITION_NNE:
3282  x = bx + bw * 0.75;
3283  y = by;
3284  break;
3285 
3286  case POSITION_NE:
3287  // top right
3288  x = bx + bw;
3289  y = by;
3290  break;
3291 
3292  case POSITION_ENE:
3293  x = bx + bw;
3294  y = by + 0.25 * bh;
3295  break;
3296 
3297  case POSITION_E:
3298  // right middle
3299  x = bx + bw;
3300  y = by + bh * 0.5;
3301  break;
3302 
3303  case POSITION_ESE:
3304  x = bx + bw;
3305  y = by + 0.75 * bh;
3306  break;
3307 
3308  case POSITION_SE:
3309  // right bottom
3310  x = bx + bw;
3311  y = by + bh;
3312  break;
3313 
3314  case POSITION_SSE:
3315  x = bx + 0.75 * bw;
3316  y = by + bh;
3317  break;
3318 
3319  case POSITION_S:
3320  // bottom
3321  x = bx + bw * 0.5;
3322  y = by + bh;
3323  break;
3324 
3325  case POSITION_SSW:
3326  x = bx + 0.25 * bw;
3327  y = by + bh;
3328  break;
3329 
3330  case POSITION_SW:
3331  // bottom left
3332  x = bx;
3333  y = by + bh;
3334  break;
3335 
3336  case POSITION_WSW:
3337  x = bx;
3338  y = by + 0.75 * bh;
3339  break;
3340 
3341  case POSITION_W:
3342  // left
3343  x = bx;
3344  y = by + bh * 0.5;
3345  break;
3346 
3347  case POSITION_WNW:
3348  x = bx;
3349  y = by + 0.25 * bh;
3350  break;
3351 
3352  case POSITION_NW:
3353  // top left
3354  x = bx;
3355  y = by;
3356  break;
3357 
3358  case POSITION_NNW:
3359  x = bx + 0.25 * bw;
3360  y = by;
3361  break;
3362 
3363  default:
3364  break;
3365  }
3366 
3367  return Point(new LayoutPkgNamespaces(), x, y);
3368 }
3369 
3370 /**
3371  * Traverses the compartments of the model and looks for CellDesigner annotations.
3372  * These are used to create text glyphs associated with compartments.
3373  */
3375 {
3376  bool result = true;
3377 
3378  if (this->mpDocument && this->mpDocument->getModel() && this->mpLayout)
3379  {
3380  Model* pModel = this->mpDocument->getModel();
3381  unsigned int i, iMax = pModel->getNumCompartments();
3382  Compartment* pCompartment = NULL;
3383  const XMLNode* pAnnotation = NULL;
3384 
3385  for (i = 0; i < iMax && result == true; ++i)
3386  {
3387  pCompartment = pModel->getCompartment(i);
3388 
3389  if (pCompartment->getAnnotation() != NULL)
3390  {
3391  pAnnotation = CCellDesignerImporter::findCellDesignerAnnotation(this->mpDocument, pCompartment->getAnnotation());
3392 
3393  // there should be a name element in there somewhere
3394  if (pAnnotation != NULL)
3395  {
3396  CompartmentAnnotation canno;
3397  result = CCellDesignerImporter::parseCompartmentAnnotation(pAnnotation, canno);
3398 
3399  if (result)
3400  {
3401  this->mCompartmentAnnotationMap.insert(std::pair<std::string, CompartmentAnnotation>(pCompartment->getId(), canno));
3402  // create the text glyph if there is a CompartmentGlyph
3403  std::multimap<std::string, GraphicalObject*>::const_iterator pos = this->mModelIdToLayoutElement.find(pCompartment->getId());
3404 
3405  if (pos != this->mModelIdToLayoutElement.end() && pos->second != NULL)
3406  {
3407  do
3408  {
3409  TextGlyph* pTGlyph = this->mpLayout->createTextGlyph();
3410  std::string id = this->createUniqueId("TextGlyph");
3411  pTGlyph->setId(id);
3412  this->mIdMap.insert(std::pair<std::string, const SBase*>(id, pTGlyph));
3413  // set the text and the associated layout element
3414  pTGlyph->setText(canno.mName);
3415  pTGlyph->setGraphicalObjectId(pos->second->getId());
3416  // set the position of the text relative to the layout element
3417  // from the mCompartmentNamePointMap
3418  const CompartmentGlyph* pCGlyph = dynamic_cast<const CompartmentGlyph*>(pos->second);
3419  assert(pCGlyph != NULL);
3420  std::map<const CompartmentGlyph*, Point>::const_iterator pos2 = this->mCompartmentNamePointMap.find(pCGlyph);
3421  Point p(new LayoutPkgNamespaces(), 0.0, 0.0);
3422 
3423  if (pos2 != this->mCompartmentNamePointMap.end())
3424  {
3425  p = pos2->second;
3426  }
3427 
3428  // set the position and dimensions of the text
3429  Point position = *pCGlyph->getBoundingBox()->getPosition();
3430  // add the name position to the position of the compartment
3431  position.setX(position.x() + p.x());
3432  position.setY(position.y() + p.y());
3433  Dimensions dim = *pCGlyph->getBoundingBox()->getDimensions();
3434  // subtract the name position from the dimensions of the compartment
3435  dim.setWidth(dim.getWidth() - p.x());
3436  dim.setHeight(dim.getHeight() - p.y());
3437  BoundingBox bb;
3438  bb.setPosition(&position);
3439  bb.setDimensions(&dim);
3440  pTGlyph->setBoundingBox(&bb);
3441  // create an appropriate style
3442  // first we need the style information for the CompartmentGlyph
3443  std::map<const CompartmentGlyph*, CompartmentAlias>::const_iterator compAliasPos = this->mCompartmentAliasMap.find(pCGlyph);
3444  assert(compAliasPos != this->mCompartmentAliasMap.end());
3445 
3446  if (compAliasPos != this->mCompartmentAliasMap.end())
3447  {
3448  this->createTextGlyphStyle(compAliasPos->second.mFontSize, Text::ANCHOR_START, Text::ANCHOR_BOTTOM, pTGlyph->getId());
3449  }
3450 
3451  ++pos;
3452  }
3453  while (pos != this->mModelIdToLayoutElement.end() && pos->first == pCompartment->getId());
3454  }
3455  else
3456  {
3457  // TODO this is OK as long as we only import compartments with bounds
3458  //result=false;
3459  }
3460  }
3461  else
3462  {
3463  result = false;
3464  }
3465  }
3466  }
3467  }
3468  }
3469  else
3470  {
3471  result = false;
3472  }
3473 
3474  return result;
3475 }
3476 
3477 /**
3478  * Traverses the species of the model and looks for CellDesigner annotations.
3479  * These are used to create text glyphs associated with species.
3480  */
3482 {
3483  bool result = true;
3484 
3485  if (this->mpDocument && this->mpDocument->getModel() && this->mpLayout)
3486  {
3487  Model* pModel = this->mpDocument->getModel();
3488  unsigned int i, iMax = pModel->getNumSpecies();
3489  Species* pSpecies = NULL;
3490  const XMLNode* pAnnotation = NULL;
3491 
3492  for (i = 0; i < iMax && result == true; ++i)
3493  {
3494  pSpecies = pModel->getSpecies(i);
3495 
3496  if (pSpecies->getAnnotation() != NULL)
3497  {
3498  pAnnotation = CCellDesignerImporter::findCellDesignerAnnotation(this->mpDocument, pSpecies->getAnnotation());
3499 
3500  // there should be a name element in there somewhere
3501  if (pAnnotation != NULL)
3502  {
3503 
3504  SpeciesAnnotation sanno;
3505  result = CCellDesignerImporter::parseSpeciesAnnotation(pAnnotation, sanno);
3506 
3507  if (result == true)
3508  {
3509  this->mSpeciesAnnotationMap.insert(std::pair<std::string, SpeciesAnnotation>(pSpecies->getId(), sanno));
3510  std::string name = pSpecies->getName();
3511 
3512  //result=this->findNameForSpeciesIdentity(sanno.mIdentity,name);
3513  if (result && !name.empty() && sanno.mIdentity.mSpeciesClass != DEGRADED_CLASS)
3514  {
3515  // create the text glyph if there is a SpeciesGlyph
3516  std::multimap<std::string, GraphicalObject*>::const_iterator pos = this->mModelIdToLayoutElement.find(pSpecies->getId());
3517  assert(pos != this->mModelIdToLayoutElement.end());
3518  assert(pos->second != NULL);
3519 
3520  if (pos != this->mModelIdToLayoutElement.end() && pos->second != NULL)
3521  {
3522  do
3523  {
3524  const SpeciesGlyph* pSGlyph = dynamic_cast<const SpeciesGlyph*>(pos->second);
3525  assert(pSGlyph != NULL);
3526 
3527  if (pSGlyph != NULL)
3528  {
3529  TextGlyph* pTGlyph = this->mpLayout->createTextGlyph();
3530  std::string id = this->createUniqueId("TextGlyph");
3531  pTGlyph->setId(id);
3532  this->mIdMap.insert(std::pair<std::string, const SBase*>(id, pTGlyph));
3533  // set the text and the associated layout element
3534  pTGlyph->setText(name);
3535  pTGlyph->setGraphicalObjectId(pSGlyph->getId());
3536  // set the position and dimensions of the text
3537  Point position = *pSGlyph->getBoundingBox()->getPosition();
3538  Dimensions dim = *pSGlyph->getBoundingBox()->getDimensions();
3539  BoundingBox bb;
3540  bb.setPosition(&position);
3541  bb.setDimensions(&dim);
3542  pTGlyph->setBoundingBox(&bb);
3543  // create an appropriate style
3544  // first we need the style information for the CompartmentGlyph
3545  std::map<const SpeciesGlyph*, SpeciesAlias>::const_iterator speciesAliasPos = this->mSpeciesAliasMap.find(pSGlyph);
3546  assert(speciesAliasPos != this->mSpeciesAliasMap.end());
3547 
3548  if (speciesAliasPos != this->mSpeciesAliasMap.end())
3549  {
3550  Text::TEXT_ANCHOR vAnchor = Text::ANCHOR_MIDDLE;
3551 
3552  if (speciesAliasPos->second.mComplex)
3553  {
3554  vAnchor = Text::ANCHOR_BOTTOM;
3555  }
3556 
3557  this->createTextGlyphStyle(speciesAliasPos->second.mFontSize, Text::ANCHOR_MIDDLE, vAnchor, pTGlyph->getId());
3558  }
3559  }
3560  else
3561  {
3562  result = false;
3563  }
3564 
3565  ++pos;
3566  }
3567  while (result == true && pos != this->mModelIdToLayoutElement.end() && pos->first == pSpecies->getId());
3568  }
3569  else
3570  {
3571  result = false;
3572  }
3573  }
3574  }
3575  else
3576  {
3577  result = false;
3578  }
3579  }
3580  }
3581  }
3582  }
3583  else
3584  {
3585  result = false;
3586  }
3587 
3588  return result;
3589 }
3590 
3591 /**
3592  * Adds a new entry to the dependency tree for complex species aliases.
3593  */
3594 void CCellDesignerImporter::addDependency(const std::string& parent, const std::string& child)
3595 {
3596  // check if the parent is already part of one of the trees
3597  CCopasiNode<std::string>* pChildNode = new CCopasiNode<std::string>(child);
3598  std::list<CCopasiNode<std::string>* >::iterator it = this->mComplexDependencies.begin(), endit = this->mComplexDependencies.end(), tree;
3599  CCopasiNode<std::string>* pCurrent;
3600 
3601  while (it != endit)
3602  {
3603  // iterate over the nodes in the tree
3604  // and try to find the parent
3605  pCurrent = *it;
3606 
3607  while (pCurrent != NULL)
3608  {
3609  if (pCurrent->getData() == parent)
3610  {
3611  pCurrent->addChild(pChildNode);
3612  break;
3613  }
3614 
3615  pCurrent = pCurrent->getNext();
3616  }
3617 
3618  if (pCurrent != NULL)
3619  {
3620  break;
3621  }
3622 
3623  ++it;
3624  }
3625 
3626  // if so add the child to that tree node
3627  // else create a new tree with parent as the root and child as the only child
3628  if (it == endit)
3629  {
3631  pRoot->setData(parent);
3632  pRoot->addChild(pChildNode);
3633  this->mComplexDependencies.push_back(pRoot);
3634  // update the iterator to the end
3635  endit = this->mComplexDependencies.end();
3636  }
3637 
3638  tree = this->mComplexDependencies.begin();
3639 
3640  // check if the child is already root to another tree, if so, we combine the two trees
3641  while (tree != endit)
3642  {
3643  // check if the root node is child
3644  if (tree != it && (*tree)->getData() == child)
3645  {
3646  // combine tree and it by adding all children from tree to it
3647  CCopasiNode<std::string>* pChild = (*tree)->getChild(), *pSibling = NULL;
3648 
3649  while (pChild != NULL)
3650  {
3651  // store the next node before we change the tree
3652  pSibling = pChild->getSibling();
3653  (*tree)->removeChild(pChild);
3654  pChildNode->addChild(pChild);
3655  pChild = pSibling;
3656  }
3657 
3658  // there can be only one I think, so we can stop here
3659  break;
3660  }
3661 
3662  ++tree;
3663  }
3664 }
3665 
3666 /**
3667  * Goes through the children of the given node which represents a list of protein definitions
3668  * and collects the names for them.
3669  * These names are converted to text glyphs for the proteins.
3670 bool CCellDesignerImporter::parseGeneNames(const XMLNode* pNode)
3671 {
3672  bool result=true;
3673  if(pNode != NULL && pNode->getName() == "listOfGenes")
3674  {
3675  std::string prefix=pNode->getPrefix();
3676  unsigned int i,iMax=pNode->getNumChildren();
3677  const XMLNode* pChild=NULL;
3678  for(i=0;i<iMax;++i)
3679  {
3680  pChild=&pNode->getChild(i);
3681  if(pChild != NULL &&
3682  pChild->getPrefix() == prefix &&
3683  pChild->getName() == "gene" &&
3684  pChild->getAttributes().hasAttribute("id") &&
3685  pChild->getAttributes().hasAttribute("name"))
3686  {
3687  std::string id=pChild->getAttributes().getValue("id");
3688  assert(!id.empty());
3689  std::string name=pChild->getAttributes().getValue("name");
3690  assert(!name.empty());
3691  this->mGeneNameMap.insert(std::pair<std::string,std::string>(id,name));
3692  }
3693  }
3694  }
3695  return result;
3696 }
3697  */
3698 
3699 /**
3700  * Goes through the children of the given node which represents a list of protein definitions
3701  * and collects the names for them.
3702  * These names are converted to text glyphs for the proteins.
3703 bool CCellDesignerImporter::parseRNANames(const XMLNode* pNode)
3704 {
3705  bool result=true;
3706  if(pNode != NULL && pNode->getName() == "listOfRNAs")
3707  {
3708  std::string prefix=pNode->getPrefix();
3709  unsigned int i,iMax=pNode->getNumChildren();
3710  const XMLNode* pChild=NULL;
3711  for(i=0;i<iMax;++i)
3712  {
3713  pChild=&pNode->getChild(i);
3714  if(pChild != NULL &&
3715  pChild->getPrefix() == prefix &&
3716  pChild->getName() == "RNA" &&
3717  pChild->getAttributes().hasAttribute("id") &&
3718  pChild->getAttributes().hasAttribute("name"))
3719  {
3720  std::string id=pChild->getAttributes().getValue("id");
3721  assert(!id.empty());
3722  std::string name=pChild->getAttributes().getValue("name");
3723  assert(!name.empty());
3724  this->mRNANameMap.insert(std::pair<std::string,std::string>(id,name));
3725  }
3726  }
3727  }
3728  return result;
3729 }
3730  */
3731 
3732 /**
3733  * Goes through the children of the given node which represents a list of protein definitions
3734  * and collects the names for them.
3735  * These names are converted to text glyphs for the proteins.
3736 bool CCellDesignerImporter::parseASRNANames(const XMLNode* pNode)
3737 {
3738  bool result=true;
3739  if(pNode != NULL && pNode->getName() == "listOfAntisenseRNAs")
3740  {
3741  std::string prefix=pNode->getPrefix();
3742  unsigned int i,iMax=pNode->getNumChildren();
3743  const XMLNode* pChild=NULL;
3744  for(i=0;i<iMax;++i)
3745  {
3746  pChild=&pNode->getChild(i);
3747  if(pChild != NULL &&
3748  pChild->getPrefix() == prefix &&
3749  pChild->getName() == "AntisenseRNA" &&
3750  pChild->getAttributes().hasAttribute("id") &&
3751  pChild->getAttributes().hasAttribute("name"))
3752  {
3753  std::string id=pChild->getAttributes().getValue("id");
3754  assert(!id.empty());
3755  std::string name=pChild->getAttributes().getValue("name");
3756  assert(!name.empty());
3757  this->mASRNANameMap.insert(std::pair<std::string,std::string>(id,name));
3758  }
3759  }
3760  }
3761  return result;
3762 }
3763  */
3764 
3765 /**
3766  * Goes through the children of the given node which represents a list of
3767  * protein definitions and check the types.
3768  * If the type is RECEPTOR, ION_CHANNEL or TRUNCATED, store that information.
3769  */
3770 bool CCellDesignerImporter::parseProteins(const XMLNode* pNode)
3771 {
3772  bool result = true;
3773 
3774  if (pNode != NULL && pNode->getName() == "listOfProteins")
3775  {
3776  std::string prefix = pNode->getPrefix();
3777  unsigned int i, iMax = pNode->getNumChildren();
3778  const XMLNode* pChild = NULL;
3779 
3780  for (i = 0; i < iMax; ++i)
3781  {
3782  pChild = &pNode->getChild(i);
3783 
3784  if (pChild != NULL &&
3785  pChild->getPrefix() == prefix &&
3786  pChild->getName() == "protein" &&
3787  pChild->getAttributes().hasAttribute("id") &&
3788  pChild->getAttributes().hasAttribute("name"))
3789  {
3790  Protein prot;
3791  // we are only interested in the id and the type
3792  prot.mId = pChild->getAttributes().getValue("id");
3793  assert(!prot.mId.empty());
3794  prot.mName = pChild->getAttributes().getValue("name");
3795  assert(!prot.mName.empty());
3796 
3797  if (pChild->getAttributes().hasAttribute("type"))
3798  {
3799  std::string type = pChild->getAttributes().getValue("type");
3800  assert(!type.empty());
3801  std::transform(type.begin(), type.end(), type.begin(), ::toupper);
3802 
3803  if (type != "GENERIC")
3804  {
3806 
3807  if (cl != UNDEFINED_CLASS)
3808  {
3809  prot.mType = cl;
3810  }
3811  else
3812  {
3813  result = false;
3814  }
3815  }
3816  }
3817 
3818  // parse the modifications
3819  const XMLNode* pModifications = CCellDesignerImporter::findChildNode(pChild, pChild->getPrefix(), "listOfModificationResidues", false);
3820 
3821  if (pModifications != NULL)
3822  {
3823  unsigned int j = 0, jMax = pModifications->getNumChildren();
3824  const XMLNode* pChild2 = NULL;
3825 
3826  while (j < jMax && result == true)
3827  {
3828  pChild2 = &pModifications->getChild(j);
3829  assert(pChild2 != NULL);
3830 
3831  if (pChild2 != NULL &&
3832  pChild2->getPrefix() == pModifications->getPrefix() &&
3833  pChild2->getName() == "modificationResidue")
3834  {
3835  ProteinModification mod;
3836  result = CCellDesignerImporter::parseProteinModification(pChild2, mod);
3837 
3838  if (result == true)
3839  {
3840  prot.mModifications.push_back(mod);
3841  }
3842  }
3843  else
3844  {
3845  result = false;
3846  }
3847 
3848  ++j;
3849  }
3850  }
3851 
3852  if (result == true)
3853  {
3854  this->mProteinInformationMap.insert(std::pair<std::string, Protein>(prot.mId, prot));
3855  }
3856  }
3857  }
3858  }
3859 
3860  return result;
3861 }
3862 
3863 /**
3864  * Tries to parse the protein modification in the given node and stores the data in the given
3865  * ProteinModification structure.
3866  * If parsing fails, false is returned.
3867  */
3869 {
3870  bool result = true;
3871 
3872  if (pNode != NULL &&
3873  pNode->getName() == "modificationResidue")
3874  {
3875  const XMLAttributes& attr = pNode->getAttributes();
3876 
3877  if (attr.hasAttribute("id"))
3878  {
3879  // has an id
3880  mod.mId = attr.getValue("id");
3881 
3882  // optional: name and angle
3883  if (attr.hasAttribute("name"))
3884  {
3885  mod.mName = attr.getValue("name");
3886  }
3887  else
3888  {
3889  mod.mName = "";
3890  }
3891 
3892  if (attr.hasAttribute("angle"))
3893  {
3894  char** err = NULL;
3895  double v;
3896  std::string s = attr.getValue("angle");
3897  assert(!s.empty());
3898  v = strtod(s.c_str(), err);
3899 
3900  if (err == NULL || *err != s.c_str())
3901  {
3902  mod.mAngle = v;
3903  }
3904  else
3905  {
3906  result = false;
3907  }
3908  }
3909  else
3910  {
3911  mod.mAngle = 0.0;
3912  }
3913  }
3914  else
3915  {
3916  result = false;
3917  }
3918  }
3919  else
3920  {
3921  result = false;
3922  }
3923 
3924  return result;
3925 }
3926 
3927 /**
3928  * Tries to parse the compartment annotation in the given node and stores the data in the given
3929  * CompartmentAnnotation structure.
3930  * If parsing fails, false is returned.
3931  */
3933 {
3934  bool result = true;
3935 
3936  if (pNode != NULL && pNode->getName() == "extension")
3937  {
3938  // as far as I can tell from the spec, there should only
3939  // be a name node
3940  const XMLNode* pNameNode = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "name", false);
3941 
3942  if (pNameNode != NULL && pNameNode->getNumChildren() == 1 && pNameNode->getChild(0).isText())
3943  {
3944  anno.mName = pNameNode->getChild(0).getCharacters();
3945  }
3946  else
3947  {
3948  result = false;
3949  }
3950  }
3951  else
3952  {
3953  result = false;
3954  }
3955 
3956  return result;
3957 }
3958 /**
3959  * Tries to parse the species annotation in the given node and stores the data in the given
3960  * SpeciesAnnotation structure.
3961  * If parsing fails, false is returned.
3962  */
3964 {
3965  bool result = true;
3966 
3967  if (pNode != NULL && pNode->getName() == "extension")
3968  {
3969  // the annotation should contain
3970  // either a positionToCompartment element
3971  // or a complexSpecies element
3972  // additionally it should contain a speciesIdentity element
3973  // and a listOfCatalyzedReactions element
3974  // TODO we currently don't use the last one or the first choice
3975  // we are only interested in the information stored in the identity
3976  const XMLNode* pIdentityNode = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "speciesIdentity", false);
3977 
3978  if (pIdentityNode != NULL)
3979  {
3980  result = CCellDesignerImporter::parseSpeciesIdentity(pIdentityNode, anno.mIdentity);
3981  }
3982  else
3983  {
3984  result = false;
3985  }
3986  }
3987  else
3988  {
3989  result = false;
3990  }
3991 
3992  return result;
3993 }
3994 
3995 /**
3996  * Parses the node which represents a speciesIdentity node and fills the given SpeciesIdentity
3997  * structure with the data.
3998  * If the parsinf fails, false is returned.
3999  */
4001 {
4002  bool result = true;
4003 
4004  if (pNode != NULL && pNode->getName() == "speciesIdentity")
4005  {
4006  // find the class element
4007  // this decides which futher element we expect
4008  const XMLNode* pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "class", false);
4009 
4010  if (pChild != NULL &&
4011  pChild->getNumChildren() == 1 &&
4012  pChild->getChild(0).isText())
4013  {
4014  std::string cl = pChild->getChild(0).getCharacters();
4015  assert(!cl.empty());
4017 
4018  switch (identity.mSpeciesClass)
4019  {
4020  case ION_CLASS:
4021  case SIMPLE_MOLECULE_CLASS:
4022  case COMPLEX_CLASS:
4023  // we expect a name
4024  {
4025  const XMLNode* pNameNode = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "name", false);
4026 
4027  if (pNameNode != NULL && pNameNode->getNumChildren() == 1 && pNameNode->getChild(0).isText())
4028  {
4029  identity.mNameOrReference = pNameNode->getChild(0).getCharacters();
4030  }
4031  else
4032  {
4033  result = false;
4034  }
4035  }
4036  break;
4037 
4038  case PROTEIN_CLASS:
4039  // we expect a protein reference
4040  {
4041  const XMLNode* pNameNode = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "proteinReference", false);
4042 
4043  if (pNameNode != NULL && pNameNode->getNumChildren() == 1 && pNameNode->getChild(0).isText())
4044  {
4045  identity.mNameOrReference = pNameNode->getChild(0).getCharacters();
4046  }
4047  else
4048  {
4049  result = false;
4050  }
4051  }
4052  break;
4053 
4054  default:
4055  // we don't handle all other cases
4056  // for now
4057  identity.mNameOrReference = "";
4058  break;
4059  }
4060  }
4061  else
4062  {
4063  result = false;
4064  }
4065 
4066  // handle state
4067  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "state", false);
4068 
4069  if (pChild != NULL)
4070  {
4071  result = CCellDesignerImporter::parseSpeciesState(pChild, identity.mState);
4072  }
4073  }
4074  else
4075  {
4076  result = false;
4077  }
4078 
4079  return result;
4080 }
4081 
4082 /**
4083  * Parses the node which represents the state in a speciesIdentity node and fills the given SpeciesState
4084  * structure with the data.
4085  * If the parsing fails, false is returned.
4086  */
4087 bool CCellDesignerImporter::parseSpeciesState(const XMLNode* pNode, SpeciesState& state)
4088 {
4089  bool result = true;
4090 
4091  if (pNode != NULL && pNode->getName() == "state")
4092  {
4093  // find the listOfModifications element
4094  const XMLNode* pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "listOfModifications", false);
4095 
4096  if (pChild != NULL)
4097  {
4098  unsigned int i = 0, iMax = pChild->getNumChildren();
4099  const XMLNode* pChild2 = NULL;
4100 
4101  while (i < iMax && result == true)
4102  {
4103  pChild2 = &pChild->getChild(i);
4104  assert(pChild2 != NULL);
4105 
4106  if (pChild2 != NULL)
4107  {
4108  SpeciesModification mod;
4109  result = CCellDesignerImporter::parseSpeciesModification(pChild2, mod);
4110 
4111  if (result == true)
4112  {
4113  state.mModifications.push_back(mod);
4114  }
4115  }
4116  else
4117  {
4118  result = false;
4119  }
4120 
4121  ++i;
4122  }
4123  }
4124  }
4125  else
4126  {
4127  result = false;
4128  }
4129 
4130  return result;
4131 }
4132 
4133 /**
4134  * Parses the node which represents a modification ion a species node and fills the given SpeciesModification
4135  * structure with the data.
4136  * If the parsing fails, false is returned.
4137  */
4139 {
4140  bool result = true;
4141 
4142  if (pNode != NULL &&
4143  pNode->getName() == "modification")
4144  {
4145  const XMLAttributes& attr = pNode->getAttributes();
4146 
4147  if (attr.hasAttribute("residue") &&
4148  attr.hasAttribute("state"))
4149  {
4150  mod.mResidue = attr.getValue("residue");
4151  assert(!mod.mResidue.empty());
4152  std::string s = attr.getValue("state");
4153  assert(!s.empty());
4155  assert(mod.mType != UNDEFINED_MOD_TYPE);
4156  }
4157  else
4158  {
4159  result = false;
4160  }
4161  }
4162  else
4163  {
4164  result = false;
4165  }
4166 
4167  return result;
4168 }
4169 
4170 /**
4171  * Searches for a child with a certain name and a certain prefix
4172  * in the tree based on pNode.
4173  * The first child that fits the name and the prefix or NULL is returned.
4174  * If recursive is true, the tree is searched recursively.
4175  */
4176 const XMLNode* CCellDesignerImporter::findChildNode(const XMLNode* pNode, const std::string& prefix, const std::string& name, bool recursive)
4177 {
4178  const XMLNode* pResult = NULL;
4179 
4180  if (pNode != NULL && !name.empty())
4181  {
4182  const XMLNode* pChild = NULL;
4183  unsigned int i, iMax = pNode->getNumChildren();
4184 
4185  for (i = 0; i < iMax && pResult == NULL; ++i)
4186  {
4187  pChild = &pNode->getChild(i);
4188 
4189  if (pChild != NULL && pChild->getPrefix() == prefix &&
4190  pChild->getName() == name)
4191  {
4192  pResult = pChild;
4193  break;
4194  }
4195 
4196  if (recursive && pChild != NULL && pChild->getNumChildren() > 0)
4197  {
4198  pResult = CCellDesignerImporter::findChildNode(pChild, prefix, name, recursive);
4199  }
4200  }
4201  }
4202 
4203  return pResult;
4204 }
4205 
4206 /**
4207  * Tries to parse the reaction annotation in the given node and stores the data in the given
4208  * ReactionAnnotation structure.
4209  * If parsing fails, false is returned.
4210  */
4212 {
4213  bool result = true;
4214 
4215  if (pNode != NULL)
4216  {
4217  const XMLNode* pChild = NULL;
4218 
4219  // now come the mandatory elements
4220  // type element
4221  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "reactionType");
4222 
4223  if (pChild != NULL)
4224  {
4225  if (pChild->getNumChildren() == 1 && pChild->getChild(0).isText())
4226  {
4227  std::string s = pChild->getChild(0).getCharacters();
4229 
4230  // baseReactants
4231  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "baseReactants");
4232 
4233  if (pChild != NULL)
4234  {
4236 
4237  if (result == true)
4238  {
4239  // baseProducts
4240  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "baseProducts");
4241 
4242  if (pChild != NULL)
4243  {
4245 
4246  if (result == true)
4247  {
4248  // connectScheme
4249  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "connectScheme");
4250 
4251  if (pChild != NULL)
4252  {
4254 
4255  if (result == true)
4256  {
4257  // line
4258  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "line");
4259 
4260  if (pChild != NULL)
4261  {
4262  result = CCellDesignerImporter::parseLine(pChild, ranno.mLine);
4263 
4264  if (result == true)
4265  {
4266  // now we read the optional elements
4267  // name element (optional)
4268  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "name");
4269 
4270  if (pChild != NULL)
4271  {
4272  if (pChild->getNumChildren() == 1 && pChild->getChild(0).isText())
4273  {
4274  ranno.mName = pChild->getChild(0).getCharacters();
4275  }
4276  }
4277 
4278  if (result == true)
4279  {
4280  // listOfReactantLinks (optional)
4281  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "listOfReactantLinks");
4282 
4283  if (pChild != NULL)
4284  {
4286  }
4287 
4288  if (result == true)
4289  {
4290  // listOfProductLinks (optional)
4291  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "listOfProductLinks");
4292 
4293  if (pChild != NULL)
4294  {
4295  result = CCellDesignerImporter::parseExtraLinks(pChild, ranno.mProductLinks);
4296  }
4297 
4298  if (result == true)
4299  {
4300  // offset (optional)
4301  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "offset");
4302 
4303  if (pChild != NULL)
4304  {
4305  // read the x and the y attribute
4306  if (pChild->getAttributes().hasAttribute("x") && pChild->getAttributes().hasAttribute("y"))
4307  {
4308  s = pChild->getAttributes().getValue("x");
4309  char** err = NULL;
4310  double v;
4311  v = strtod(s.c_str(), err);
4312 
4313  if (err == NULL || *err != s.c_str())
4314  {
4315  ranno.mOffset.setX(v);
4316  err = NULL;
4317  v = strtod(s.c_str(), err);
4318 
4319  if (err == NULL || *err != s.c_str())
4320  {
4321  ranno.mOffset.setY(v);
4322  }
4323  else
4324  {
4325  result = false;
4326  }
4327  }
4328  else
4329  {
4330  result = false;
4331  }
4332  }
4333  }
4334 
4335  if (result == true)
4336  {
4337  // editPoints (optional)
4338  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "editPoints");
4339 
4340  if (pChild != NULL)
4341  {
4342  result = CCellDesignerImporter::parseEditPoints(pChild, ranno.mEditPoints);
4343  }
4344 
4345  if (result == true)
4346  {
4347  // listOfModifications (optional)
4348  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "listOfModification");
4349 
4350  if (pChild != NULL)
4351  {
4353  }
4354  }
4355  }
4356  }
4357  }
4358  }
4359  }
4360  }
4361  else
4362  {
4363  result = false;
4364  }
4365  }
4366  }
4367  else
4368  {
4369  result = false;
4370  }
4371  }
4372  }
4373  else
4374  {
4375  result = false;
4376  }
4377  }
4378  }
4379  else
4380  {
4381  result = false;
4382  }
4383  }
4384  else
4385  {
4386  result = false;
4387  }
4388  }
4389  else
4390  {
4391  result = false;
4392  }
4393  }
4394  else
4395  {
4396  result = false;
4397  }
4398 
4399  return result;
4400 }
4401 
4402 /**
4403  * Converts the given reaction type string to the corresponding enum.
4404  * If there is no enum that corresponds to the string, UNDEFINED_RTYPE is returned.
4405  */
4407 {
4408  std::transform(s.begin(), s.end(), s.begin(), ::toupper);
4409  REACTION_TYPE result = UNDEFINED_RTYPE;
4410 
4411  if (s == "STATE_TRANSITION")
4412  {
4413  result = STATE_TRANSITION_RTYPE;
4414  }
4415  else if (s == "KNOWN_TRANSITION_OMITTED")
4416  {
4418  }
4419  else if (s == "UNKNOWN_TRANSITION")
4420  {
4421  result = UNKNOWN_TRANSITION_RTYPE;
4422  }
4423  else if (s == "CATALYSIS")
4424  {
4425  result = CATALYSIS_RTYPE;
4426  }
4427  else if (s == "UNKNOWN_CATALYSIS")
4428  {
4429  result = UNKNOWN_CATALYSIS_RTYPE;
4430  }
4431  else if (s == "INHIBITION")
4432  {
4433  result = INHIBITION_RTYPE;
4434  }
4435  else if (s == "UNKNOWN_INHIBITION")
4436  {
4437  result = UNKNOWN_INHIBITION_RTYPE;
4438  }
4439  else if (s == "TRANSPORT")
4440  {
4441  result = TRANSPORT_RTYPE;
4442  }
4443  else if (s == "HETERODIMER_ASSOCIATION")
4444  {
4446  }
4447  else if (s == "DISSOCIATION")
4448  {
4449  result = DISSOCIATION_RTYPE;
4450  }
4451  else if (s == "TRUNCATION")
4452  {
4453  result = TRUNCATION_RTYPE;
4454  }
4455  else if (s == "TRANSCRIPTIONAL_ACTIVATION")
4456  {
4458  }
4459  else if (s == "TRANSCRIPTIONAL_INHIBITION")
4460  {
4462  }
4463  else if (s == "TRANSLATIONAL_ACTIVATION")
4464  {
4466  }
4467  else if (s == "TRANSLATIONAL_INHIBITION")
4468  {
4470  }
4471  else if (s == "TRANSCRIPTION")
4472  {
4473  result = TRANSCRIPTION_RTYPE;
4474  }
4475  else if (s == "TRANSLATION")
4476  {
4477  result = TRANSLATION_RTYPE;
4478  }
4479 
4480  return result;
4481 }
4482 
4483 /**
4484  * Converts the given modification link type string to the corresponding enum.
4485  * If there is no enum that corresponds to the string, UNDEFINED_ML_TYPE is returned.
4486  */
4488 {
4489  std::transform(s.begin(), s.end(), s.begin(), ::toupper);
4491 
4492  if (s == "CATALYSIS")
4493  {
4494  result = CATALYSIS_ML_TYPE;
4495  }
4496  else if (s == "UNKNOWN_CATALYSIS")
4497  {
4498  result = UNKNOWN_CATALYSIS_ML_TYPE;
4499  }
4500  else if (s == "INHIBITION")
4501  {
4502  result = INHIBITION_ML_TYPE;
4503  }
4504  else if (s == "UNKNOWN_INHIBITION")
4505  {
4506  result = UNKNOWN_INHIBITION_ML_TYPE;
4507  }
4508  else if (s == "TRANSPORT")
4509  {
4510  result = TRANSPORT_ML_TYPE;
4511  }
4512  else if (s == "HETERODIMER_ASSOCIATION")
4513  {
4515  }
4516  else if (s == "TRANSCRIPTIONAL_ACTIVATION")
4517  {
4519  }
4520  else if (s == "TRANSCRIPTIONAL_INHIBITION")
4521  {
4523  }
4524  else if (s == "TRANSLATIONAL_ACTIVATION")
4525  {
4527  }
4528  else if (s == "TRANSLATIONAL_INHIBITION")
4529  {
4531  }
4532  else if (s == "PHYSICAL_STIMULATION")
4533  {
4535  }
4536  else if (s == "MODULATION")
4537  {
4538  result = MODULATION_ML_TYPE;
4539  }
4540  else if (s == "TRIGGER")
4541  {
4542  result = TRIGGER_ML_TYPE;
4543  }
4544  else if (s == "BOOLEAN_LOGIC_GATE_AND")
4545  {
4547  }
4548  else if (s == "BOOLEAN_LOGIC_GATE_OR")
4549  {
4551  }
4552  else if (s == "BOOLEAN_LOGIC_GATE_NOT")
4553  {
4555  }
4556  else if (s == "BOOLEAN_LOGIC_GATE_UNKNOWN")
4557  {
4559  }
4560 
4561  return result;
4562 }
4563 
4564 /**
4565  * Converts the given modification type string to the corresponding enum.
4566  * If there is no enum that corresponds to the string, UNDEFINED_MTYPE is returned.
4567  */
4569 {
4570  std::transform(s.begin(), s.end(), s.begin(), ::toupper);
4572 
4573  if (s == "CATALYSIS")
4574  {
4575  result = CATALYSIS_MTYPE;
4576  }
4577  else if (s == "UNKNOWN_CATALYSIS")
4578  {
4579  result = UNKNOWN_CATALYSIS_MTYPE;
4580  }
4581  else if (s == "INHIBITION")
4582  {
4583  result = INHIBITION_MTYPE;
4584  }
4585  else if (s == "UNKNOWN_INHIBITION")
4586  {
4587  result = UNKNOWN_INHIBITION_MTYPE;
4588  }
4589  else if (s == "TRANSPORT")
4590  {
4591  result = TRANSPORT_MTYPE;
4592  }
4593  else if (s == "HETERODIMER_ASSOCIATION")
4594  {
4596  }
4597  else if (s == "TRANSCRIPTIONAL_ACTIVATION")
4598  {
4600  }
4601  else if (s == "TRANSCRIPTIONAL_INHIBITION")
4602  {
4604  }
4605  else if (s == "TRANSLATIONAL_ACTIVATION")
4606  {
4608  }
4609  else if (s == "TRANSLATIONAL_INHIBITION")
4610  {
4612  }
4613  else if (s == "PHYSICAL_STIMULATION")
4614  {
4615  result = PHYSICAL_STIMULATION_MTYPE;
4616  }
4617  else if (s == "MODULATION")
4618  {
4619  result = MODULATION_MTYPE;
4620  }
4621 
4622  return result;
4623 }
4624 
4625 /**
4626  * Converts the given position to compartment string to the corresponding enum.
4627  * If there is no enum that corresponds to the string, UNDEFINED_POSITION is returned.
4628  */
4630 {
4631  std::transform(s.begin(), s.end(), s.begin(), ::toupper);
4633 
4634  if (s == "OUTER_SURFACE")
4635  {
4636  result = OUTER_SURFACE;
4637  }
4638  else if (s == "TRANSMEMBRANE")
4639  {
4640  result = TRANSMEMBRANE;
4641  }
4642  else if (s == "INNER_SURFACE")
4643  {
4644  result = INNER_SURFACE;
4645  }
4646  else if (s == "INSIDE")
4647  {
4648  result = INSIDE;
4649  }
4650  else if (s == "INSIDE_MEMBRANE")
4651  {
4652  result = INSIDE_MEMBRANE;
4653  }
4654 
4655  return result;
4656 }
4657 
4658 /**
4659  * Converts the given connection policy string to the corresponding enum.
4660  * If there is no enum that corresponds to the string, POLICY_UNDEFINED is returned.
4661  */
4663 {
4664  std::transform(s.begin(), s.end(), s.begin(), ::toupper);
4666 
4667  if (s == "DIRECT")
4668  {
4669  result = POLICY_DIRECT;
4670  }
4671  else if (s == "SQUARE")
4672  {
4673  result = POLICY_SQUARE;
4674  }
4675 
4676  return result;
4677 }
4678 
4679 /**
4680  * Converts the given direction string to the corresponding enum.
4681  * If there is no enum that corresponds to the string, DIRECTION_UNDEFINED is returned.
4682  */
4684 {
4685  std::transform(s.begin(), s.end(), s.begin(), ::toupper);
4687 
4688  if (s == "UNKNOWN")
4689  {
4690  result = DIRECTION_UNKNOWN;
4691  }
4692  else if (s == "HORIZONTAL")
4693  {
4694  result = DIRECTION_HORIZONTAL;
4695  }
4696  else if (s == "VERTICAL")
4697  {
4698  result = DIRECTION_VERTICAL;
4699  }
4700 
4701  return result;
4702 }
4703 
4704 /**
4705  * Converts the given position string to an enum.
4706  */
4708 {
4709  std::transform(pos.begin(), pos.end(), pos.begin(), ::toupper);
4710  POSITION position = POSITION_UNDEFINED;
4711 
4712  if (pos == "N")
4713  {
4714  position = POSITION_N;
4715  }
4716  else if (pos == "NNE")
4717  {
4718  position = POSITION_NNE;
4719  }
4720  else if (pos == "NE")
4721  {
4722  position = POSITION_NE;
4723  }
4724  else if (pos == "ENE")
4725  {
4726  position = POSITION_ENE;
4727  }
4728  else if (pos == "E")
4729  {
4730  position = POSITION_E;
4731  }
4732  else if (pos == "ESE")
4733  {
4734  position = POSITION_ESE;
4735  }
4736  else if (pos == "SE")
4737  {
4738  position = POSITION_SE;
4739  }
4740  else if (pos == "SSE")
4741  {
4742  position = POSITION_SSE;
4743  }
4744  else if (pos == "S")
4745  {
4746  position = POSITION_S;
4747  }
4748  else if (pos == "SSW")
4749  {
4750  position = POSITION_SSW;
4751  }
4752  else if (pos == "SW")
4753  {
4754  position = POSITION_SW;
4755  }
4756  else if (pos == "WSW")
4757  {
4758  position = POSITION_WSW;
4759  }
4760  else if (pos == "W")
4761  {
4762  position = POSITION_W;
4763  }
4764  else if (pos == "WNW")
4765  {
4766  position = POSITION_WNW;
4767  }
4768  else if (pos == "NW")
4769  {
4770  position = POSITION_NW;
4771  }
4772  else if (pos == "NNW")
4773  {
4774  position = POSITION_NNW;
4775  }
4776 
4777  return position;
4778 }
4779 
4780 /**
4781  * Converts the given paint scheme string to the correspnding PAINT_SCHEME enum value.
4782  * If no enum is found, PAINT_UNDEFINED is returned.
4783  */
4785 {
4786  PAINT_SCHEME result = PAINT_UNDEFINED;
4787  std::transform(s.begin(), s.end(), s.begin(), ::toupper);
4788 
4789  if (s == "COLOR")
4790  {
4791  result = PAINT_COLOR;
4792  }
4793  else if (s == "GRADIENT")
4794  {
4795  result = PAINT_GRADIENT;
4796  }
4797 
4798  return result;
4799 }
4800 
4801 /**
4802  * Converts the given class string to the correspnding SPECIES_CLASS enum value.
4803  * If no enum is found, UNDEFINED is returned.
4804  */
4806 {
4807  std::transform(cl.begin(), cl.end(), cl.begin(), ::toupper);
4808  SPECIES_CLASS result = UNDEFINED_CLASS;
4809 
4810  if (cl == "ION")
4811  {
4812  result = ION_CLASS;
4813  }
4814  else if (cl == "SIMPLE_MOLECULE")
4815  {
4816  result = SIMPLE_MOLECULE_CLASS;
4817  }
4818  else if (cl == "PROTEIN")
4819  {
4820  result = PROTEIN_CLASS;
4821  }
4822  else if (cl == "GENE")
4823  {
4824  result = GENE_CLASS;
4825  }
4826  else if (cl == "RNA")
4827  {
4828  result = RNA_CLASS;
4829  }
4830  else if (cl == "ANTISENSE_RNA")
4831  {
4832  result = ANTISENSE_RNA_CLASS;
4833  }
4834  else if (cl == "PHENOTYPE")
4835  {
4836  result = PHENOTYPE_CLASS;
4837  }
4838  else if (cl == "DRUG")
4839  {
4840  result = DRUG_CLASS;
4841  }
4842  else if (cl == "UNKNOWN")
4843  {
4844  result = UNKNOWN_CLASS;
4845  }
4846  else if (cl == "COMPLEX")
4847  {
4848  result = COMPLEX_CLASS;
4849  }
4850  else if (cl == "SQUARE")
4851  {
4852  result = SQUARE_CLASS;
4853  }
4854  else if (cl == "OVAL")
4855  {
4856  result = OVAL_CLASS;
4857  }
4858  else if (cl == "SQUARE_CLOSEUP_NORTHWEST")
4859  {
4860  result = SQUARE_NW_CLASS;
4861  }
4862  else if (cl == "SQUARE_CLOSEUP_NORTHEAST")
4863  {
4864  result = SQUARE_NE_CLASS;
4865  }
4866  else if (cl == "SQUARE_CLOSEUP_SOUTHWEST")
4867  {
4868  result = SQUARE_SW_CLASS;
4869  }
4870  else if (cl == "SQUARE_CLOSEUP_SOUTHEAST")
4871  {
4872  result = SQUARE_SE_CLASS;
4873  }
4874  else if (cl == "SQUARE_CLOSEUP_NORTH")
4875  {
4876  result = SQUARE_N_CLASS;
4877  }
4878  else if (cl == "SQUARE_CLOSEUP_EAST")
4879  {
4880  result = SQUARE_E_CLASS;
4881  }
4882  else if (cl == "SQUARE_CLOSEUP_WEST")
4883  {
4884  result = SQUARE_W_CLASS;
4885  }
4886  else if (cl == "SQUARE_CLOSEUP_SOUTH")
4887  {
4888  result = SQUARE_S_CLASS;
4889  }
4890  else if (cl == "DEGRADED")
4891  {
4892  result = DEGRADED_CLASS;
4893  }
4894  else if (cl == "RECEPTOR")
4895  {
4896  result = RECEPTOR_CLASS;
4897  }
4898  else if (cl == "TRUNCATED")
4899  {
4900  result = TRUNCATED_CLASS;
4901  }
4902  else if (cl == "ION_CHANNEL")
4903  {
4904  result = CHANNEL_CLASS;
4905  }
4906 
4907  return result;
4908 }
4909 
4910 /**
4911  * Tries to parse the reaction elements (baseReactants or baseProducts) in the given
4912  * node and stores the data in the given ReactionAnnotation structure.
4913  * If parsing fails, false is returned.
4914  */
4915 bool CCellDesignerImporter::parseReactionElements(const XMLNode* pNode, std::vector<LinkTarget>& elements)
4916 {
4917  bool result = true;
4918 
4919  if (pNode != NULL &&
4920  (pNode->getName() == "baseReactants" ||
4921  pNode->getName() == "baseProducts")
4922  )
4923  {
4924  // elements of either baseReactant or baseProduct
4925  // each element has the attributes alias and species
4926  // as well as a linkAnchor element (which sometimes is missing)
4927  unsigned int i, iMax = pNode->getNumChildren();
4928  const XMLNode* pChild = NULL;
4929  elements.clear();
4930 
4931  for (i = 0; i < iMax && result == true; ++i)
4932  {
4933  pChild = &pNode->getChild(i);
4934 
4935  if (pChild != NULL &&
4936  pChild->getPrefix() == pNode->getPrefix() &&
4937  (pChild->getName() == "baseReactant" ||
4938  pChild->getName() == "baseProduct")
4939  )
4940  {
4941  LinkTarget l;
4942  result = CCellDesignerImporter::parseLinkTarget(pChild, l);
4943  elements.push_back(l);
4944  }
4945  }
4946  }
4947  else
4948  {
4949  result = false;
4950  }
4951 
4952  return result;
4953 }
4954 
4955 /**
4956  * Tries to parse the connection scheme in the given node and stores the data in the given
4957  * ConnectionScheme structure.
4958  * If parsing fails, false is returned.
4959  */
4961 {
4962  bool result = true;
4963 
4964  if (pNode != NULL && pNode->getName() == "connectScheme")
4965  {
4966  // attributes
4967  // policy
4968  const XMLAttributes& attr = pNode->getAttributes();
4969 
4970  if (attr.hasAttribute("connectPolicy"))
4971  {
4972  std::string s = attr.getValue("connectPolicy");
4974 
4975  if (scheme.mPolicy != POLICY_UNDEFINED)
4976  {
4977  // reactangleIndex (optional)
4978  if (attr.hasAttribute("rectangleIndex"))
4979  {
4980  s = attr.getValue("rectangleIndex");
4981  char** err = NULL;
4982  long val = strtol(s.c_str(), err, 10);
4983 
4984  if (!err || *err != s.c_str())
4985  {
4986  scheme.mRectangleIndex = val;
4987  }
4988  else
4989  {
4990  result = false;
4991  }
4992  }
4993 
4994  // children
4995  const XMLNode* pDirections = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "listOfLineDirection");
4996 
4997  if (pDirections != NULL)
4998  {
4999  // list of lineDirectionElements
5000  unsigned int i, iMax = pDirections->getNumChildren();
5001  const XMLNode* pChild = NULL;
5002 
5003  for (i = 0; i < iMax && result == true; ++i)
5004  {
5005  pChild = &pDirections->getChild(i);
5006 
5007  if (pChild != NULL &&
5008  pChild->getPrefix() == pDirections->getPrefix() &&
5009  pChild->getName() == "lineDirection")
5010  {
5011  LineDirection l;
5012  result = CCellDesignerImporter::parseLineDirection(pChild, l);
5013  scheme.mLineDirections.push_back(l);
5014  }
5015  }
5016  }
5017  else
5018  {
5019  result = false;
5020  }
5021  }
5022  else
5023  {
5024  result = false;
5025  }
5026  }
5027  else
5028  {
5029  result = false;
5030  }
5031  }
5032  else
5033  {
5034  result = false;
5035  }
5036 
5037  return result;
5038 }
5039 
5040 /**
5041  * Tries to parse the line data in the given node and stores the data in the given
5042  * Line structure.
5043  * If parsing fails, false is returned.
5044  */
5045 bool CCellDesignerImporter::parseLine(const XMLNode* pNode, Line& line)
5046 {
5047  bool result = true;
5048 
5049  if (pNode != NULL && pNode->getName() == "line")
5050  {
5051  // the line element has two attributes
5052  // color and width
5053  const XMLAttributes& attr = pNode->getAttributes();
5054 
5055  if (attr.hasAttribute("color") && attr.hasAttribute("width"))
5056  {
5057  std::string s = attr.getValue("color");
5058  line.mColor = s;
5059  s = attr.getValue("width");
5060  char** err = NULL;
5061  double dbl = strtod(s.c_str(), err);
5062 
5063  if (!err || *err != s.c_str())
5064  {
5065  line.mWidth = dbl;
5066  }
5067  else
5068  {
5069  result = false;
5070  }
5071 
5072  // the lines with reactant and productLinks
5073  // might also have a type
5074  if (attr.hasAttribute("type"))
5075  {
5076  s = attr.getValue("type");
5077  std::transform(s.begin(), s.end(), s.begin(), ::toupper);
5078 
5079  if (s == "CURVE")
5080  {
5081  line.mCurve = true;
5082  }
5083  }
5084  }
5085  else
5086  {
5087  result = false;
5088  }
5089  }
5090  else
5091  {
5092  result = false;
5093  }
5094 
5095  return result;
5096 }
5097 
5098 /**
5099  * Tries to parse the extra reactant links in the given node and stores the data in the given
5100  * vector of ReactantLinks structure.
5101  * If parsing fails, false is returned.
5102  */
5103 bool CCellDesignerImporter::parseExtraLinks(const XMLNode* pNode, std::vector<ReactantLink>& rlinks)
5104 {
5105  bool result = true;
5106 
5107  if (pNode != NULL &&
5108  (pNode->getName() == "listOfReactantLinks" ||
5109  pNode->getName() == "listOfProductLinks")
5110  )
5111  {
5112  // each child is either a reactantLink or a productLink
5113  // which have the same structure
5114  unsigned int i, iMax = pNode->getNumChildren();
5115  const XMLNode* pChild = NULL;
5116  rlinks.clear();
5117 
5118  for (i = 0; i < iMax && result == true; ++i)
5119  {
5120  pChild = &pNode->getChild(i);
5121 
5122  if (pChild != NULL &&
5123  pChild->getPrefix() == pNode->getPrefix() &&
5124  (pChild->getName() == "reactantLink" ||
5125  pChild->getName() == "productLink")
5126  )
5127  {
5128  ReactantLink l;
5129  result = CCellDesignerImporter::parseExtraLink(pChild, l);
5130  rlinks.push_back(l);
5131  }
5132  }
5133  }
5134  else
5135  {
5136  result = false;
5137  }
5138 
5139  return result;
5140 }
5141 
5142 /**
5143  * Tries to parse the edit points in the given node and stores the data in the given
5144  * vector of Points.
5145  * If parsing fails, false is returned.
5146  */
5147 bool CCellDesignerImporter::parseEditPoints(const XMLNode* pNode, EditPoints& editpoints)
5148 {
5149  bool result = true;
5150 
5151  if (pNode != NULL && pNode->getName() == "editPoints")
5152  {
5153  // there can be attributes num0, num1 and num2
5154  // as well as tShapeIndex and omittedShapeIndex
5155  // all of these are optional
5156  if (pNode->getNumChildren() == 1 && pNode->getChild(0).isText())
5157  {
5158  std::string s = pNode->getChild(0).getCharacters();
5159  // the rest is a text child element that contains the string with the points
5160  result = CCellDesignerImporter::parsePointsString(s, editpoints.mPoints);
5161  char** err = NULL;
5162  const XMLAttributes& attr = pNode->getAttributes();
5163  long val = 0;
5164 
5165  if (result && attr.hasAttribute("num0"))
5166  {
5167  s = attr.getValue("num0");
5168  err = NULL;
5169  val = strtol(s.c_str(), err, 10);
5170 
5171  if (!err || *err != s.c_str())
5172  {
5173  editpoints.mNum0 = val;
5174  }
5175  else
5176  {
5177  result = false;
5178  }
5179  }
5180 
5181  if (result && attr.hasAttribute("num1"))
5182  {
5183  s = attr.getValue("num1");
5184  err = NULL;
5185  val = strtol(s.c_str(), err, 10);
5186 
5187  if (!err || *err != s.c_str())
5188  {
5189  editpoints.mNum1 = val;
5190  }
5191  else
5192  {
5193  result = false;
5194  }
5195  }
5196 
5197  if (result && attr.hasAttribute("num2"))
5198  {
5199  s = attr.getValue("num2");
5200  err = NULL;
5201  val = strtol(s.c_str(), err, 10);
5202 
5203  if (!err || *err != s.c_str())
5204  {
5205  editpoints.mNum2 = val;
5206  }
5207  else
5208  {
5209  result = false;
5210  }
5211  }
5212 
5213  if (result && attr.hasAttribute("tShapeIndex"))
5214  {
5215  s = attr.getValue("tShapeIndex");
5216  err = NULL;
5217  val = strtol(s.c_str(), err, 10);
5218 
5219  if (!err || *err != s.c_str())
5220  {
5221  editpoints.mTShapeIndex = val;
5222  }
5223  else
5224  {
5225  result = false;
5226  }
5227  }
5228 
5229  if (result && attr.hasAttribute("omittedShapeIndex"))
5230  {
5231  s = attr.getValue("omittedShapeIndex");
5232  err = NULL;
5233  val = strtol(s.c_str(), err, 10);
5234 
5235  if (!err || *err != s.c_str())
5236  {
5237  editpoints.mOmittedShapeIndex = val;
5238  }
5239  else
5240  {
5241  result = false;
5242  }
5243  }
5244  }
5245  else
5246  {
5247  result = false;
5248  }
5249  }
5250  else
5251  {
5252  result = false;
5253  }
5254 
5255  return result;
5256 }
5257 
5258 /**
5259  * Tries to parse the reaction modifications in the given node and stores the data in the given
5260  * vector of ReactionModifications.
5261  * If parsing fails, false is returned.
5262  */
5263 bool CCellDesignerImporter::parseReactionModifications(const XMLNode* pNode, std::vector<ReactionModification>& rmods)
5264 {
5265  bool result = true;
5266 
5267  if (pNode != NULL && pNode->getName() == "listOfModification")
5268  {
5269  unsigned int i, iMax = pNode->getNumChildren();
5270  const XMLNode* pChild = NULL;
5271 
5272  for (i = 0; i < iMax && result == true; ++i)
5273  {
5274  pChild = &pNode->getChild(i);
5275 
5276  if (pChild != NULL &&
5277  pChild->getPrefix() == pNode->getPrefix() &&
5278  pChild->getName() == "modification")
5279  {
5280  ReactionModification rmod;
5281  result = CCellDesignerImporter::parseReactionModification(pChild, rmod);
5282  rmods.push_back(rmod);
5283  }
5284  }
5285  }
5286  else
5287  {
5288  result = false;
5289  }
5290 
5291  return result;
5292 }
5293 
5294 /**
5295  * Tries to parse the link target in the given node and stores the data in the given
5296  * vector of LinkTarget structure.
5297  * If parsing fails, false is returned.
5298  */
5300 {
5301  bool result = true;
5302 
5303  if (pNode != NULL &&
5304  (pNode->getName() == "baseReactant" ||
5305  pNode->getName() == "baseProduct" ||
5306  pNode->getName() == "linkTarget")
5307  )
5308  {
5309  // alias and species attributes are mandatory
5310  // a linkAnchor child seems to be optional
5311  const XMLAttributes& attr = pNode->getAttributes();
5312 
5313  if (attr.hasAttribute("alias") && attr.hasAttribute("species"))
5314  {
5315  std::string s = attr.getValue("alias");
5316  l.mAlias = s;
5317  s = attr.getValue("species");
5318  l.mSpecies = s;
5319  const XMLNode* pAnchor = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "linkAnchor", false);
5320 
5321  if (pAnchor != NULL)
5322  {
5323  if (pAnchor->getAttributes().hasAttribute("position"))
5324  {
5325  s = pAnchor->getAttributes().getValue("position");
5327 
5328  if (l.mPosition == POSITION_UNDEFINED)
5329  {
5330  result = false;
5331  }
5332  }
5333  else
5334  {
5335  result = false;
5336  }
5337  }
5338  }
5339  else
5340  {
5341  result = false;
5342  }
5343  }
5344  else
5345  {
5346  result = false;
5347  }
5348 
5349  return result;
5350 }
5351 
5352 /**
5353  * Tries to parse the line direction in the given node and stores the data in the given
5354  * vector of LineDirection structure.
5355  * If parsing fails, false is returned.
5356  */
5358 {
5359  bool result = true;
5360 
5361  if (pNode != NULL &&
5362  pNode->getName() == "lineDirection")
5363  {
5364  // attributesd index and value are mandatory
5365  // attribute arm is optional
5366  const XMLAttributes& attr = pNode->getAttributes();
5367 
5368  if (attr.hasAttribute("index") && attr.hasAttribute("value"))
5369  {
5370  std::string s = attr.getValue("index");
5371  char** err = NULL;
5372  long val = strtol(s.c_str(), err, 10);
5373 
5374  if (!err || *err != s.c_str())
5375  {
5376  d.mIndex = val;
5377  err = NULL;
5378  s = attr.getValue("value");
5380 
5381  if (d.mValue != DIRECTION_UNDEFINED)
5382  {
5383  if (attr.hasAttribute("arm"))
5384  {
5385  s = attr.getValue("arm");
5386  err = NULL;
5387  val = strtol(s.c_str(), err, 10);
5388 
5389  if (!err || *err != s.c_str())
5390  {
5391  d.mArm = val;
5392  }
5393  else
5394  {
5395  result = false;
5396  }
5397  }
5398  }
5399  else
5400  {
5401  result = false;
5402  }
5403  }
5404  else
5405  {
5406  result = false;
5407  }
5408  }
5409  else
5410  {
5411  result = false;
5412  }
5413  }
5414 
5415  return result;
5416 }
5417 
5418 /**
5419  * Tries to parse the wreactant link in the given node and stores the data in the given
5420  * vector of ReactionLink structure.
5421  * If parsing fails, false is returned.
5422  */
5424 {
5425  bool result = true;
5426 
5427  if (pNode != NULL &&
5428  (pNode->getName() == "productLink" ||
5429  pNode->getName() == "reactantLink")
5430  )
5431  {
5432  // attributes alias , reactant and targetLineIndex are mandatory
5433  const XMLAttributes& attr = pNode->getAttributes();
5434 
5435  if (attr.hasAttribute("alias") &&
5436  (attr.hasAttribute("reactant") ||
5437  attr.hasAttribute("product")) &&
5438  attr.hasAttribute("targetLineIndex"))
5439  {
5440  std::string s = attr.getValue("alias");
5441  l.mAlias = s;
5442 
5443  if (attr.hasAttribute("reactant"))
5444  {
5445  s = attr.getValue("reactant");
5446  }
5447  else
5448  {
5449  s = attr.getValue("product");
5450  }
5451 
5452  l.mReactant = s;
5453  s = attr.getValue("targetLineIndex");
5454  std::vector<std::string> parts;
5455  // targetLineIndex has two number split by a ','
5456  result = CCellDesignerImporter::splitString(s, parts, ",");
5457 
5458  if (result && parts.size() == 2)
5459  {
5460  char** err = NULL;
5461  // we are only interested in the second value because for CellDesigner 4.0
5462  // and higher, the first value is always -1
5463  long val = strtol(parts[1].c_str(), err, 10);
5464 
5465  if (!err || *err != s.c_str())
5466  {
5467  l.mTargetLineIndex = val;
5468  // child element line is mandatory
5469  const XMLNode* pLineNode = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "line", false);
5470 
5471  if (pLineNode != NULL)
5472  {
5473  result = CCellDesignerImporter::parseLine(pLineNode, l.mLine);
5474 
5475  // child element linkAnchor is optional
5476  if (result == true)
5477  {
5478  pLineNode = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "linkAnchor", false);
5479 
5480  if (pLineNode != NULL && pLineNode->getAttributes().hasAttribute("position"))
5481  {
5482  l.mPosition = CCellDesignerImporter::positionToEnum(pLineNode->getAttributes().getValue("position"));
5483 
5484  if (l.mPosition == POSITION_UNDEFINED)
5485  {
5486  result = false;
5487  }
5488  }
5489  }
5490  }
5491  else
5492  {
5493  result = false;
5494  }
5495  }
5496  else
5497  {
5498  result = false;
5499  }
5500  }
5501  else
5502  {
5503  result = false;
5504  }
5505  }
5506  else
5507  {
5508  result = false;
5509  }
5510  }
5511  else
5512  {
5513  result = false;
5514  }
5515 
5516  return result;
5517 }
5518 
5519 /**
5520  * Tries to parse the reaction modification in the given node and stores the data in the given
5521  * ReactionModification structure.
5522  * If parsing fails, false is returned.
5523  */
5525 {
5526  bool result = true;
5527 
5528  if (pNode != NULL &&
5529  pNode->getName() == "modification")
5530  {
5531  // mandatory attributes: alias, modifiers, type, targetLineIndex
5532  // optional attributes: editPoints, num0, num1, num2, modificationType
5533  // offsetX,offsetY
5534  // optional children: connectScheme, linkTarget and line
5535 
5536  // first we handle the mandatory attributes
5537  const XMLAttributes& attr = pNode->getAttributes();
5538 
5539  if (attr.hasAttribute("aliases") &&
5540  attr.hasAttribute("modifiers") &&
5541  attr.hasAttribute("type") &&
5542  attr.hasAttribute("targetLineIndex"))
5543  {
5544  std::string s = attr.getValue("aliases");
5545  result = CCellDesignerImporter::splitString(s, mod.mAliases, ",");
5546 
5547  if (result == true)
5548  {
5549  s = attr.getValue("modifiers");
5550  result = CCellDesignerImporter::splitString(s, mod.mModifiers, ",");
5551 
5552  if (result == true)
5553  {
5554  s = attr.getValue("type");
5556 
5557  if (mod.mType != UNDEFINED_ML_TYPE)
5558  {
5559  s = attr.getValue("targetLineIndex");
5560  // the targetLineIndex attribute is a comma
5561  // separated list of two int values
5562  // for CellDesigner 4.0 and above the first
5563  // value is always -1, so we ignore it
5564  std::vector<std::string> tmp;
5565  result = CCellDesignerImporter::splitString(s, tmp, ",");
5566 
5567  if (result == true && tmp.size() == 2)
5568  {
5569  char** err = NULL;
5570  long val = strtol(tmp[1].c_str(), err, 10);
5571 
5572  if (!err || *err != tmp[1].c_str())
5573  {
5574  mod.mTargetLineIndex = val;
5575  }
5576  else
5577  {
5578  result = false;
5579  }
5580  }
5581  else
5582  {
5583  result = false;
5584  }
5585  }
5586  else
5587  {
5588  result = false;
5589  }
5590  }
5591  }
5592 
5593  if (result == true)
5594  {
5595  // optional attributes: editPoints, num0, num1, num2, modificationType
5596  // offsetX,offsetY
5597  char** err = NULL;
5598  long val;
5599  double dval;
5600 
5601  if (attr.hasAttribute("editPoints"))
5602  {
5603  s = attr.getValue("editPoints");
5605  }
5606 
5607  if (result == true && attr.hasAttribute("num0"))
5608  {
5609  s = attr.getValue("num0");
5610  err = NULL;
5611  val = strtol(s.c_str(), err, 10);
5612 
5613  if (!err || *err != s.c_str())
5614  {
5615  mod.mNum0 = val;
5616  }
5617  else
5618  {
5619  result = false;
5620  }
5621  }
5622 
5623  if (result == true && attr.hasAttribute("num1"))
5624  {
5625  s = attr.getValue("num1");
5626  err = NULL;
5627  val = strtol(s.c_str(), err, 10);
5628 
5629  if (!err || *err != s.c_str())
5630  {
5631  mod.mNum1 = val;
5632  }
5633  else
5634  {
5635  result = false;
5636  }
5637  }
5638 
5639  if (result == true && attr.hasAttribute("num2"))
5640  {
5641  s = attr.getValue("num2");
5642  err = NULL;
5643  val = strtol(s.c_str(), err, 10);
5644 
5645  if (!err || *err != s.c_str())
5646  {
5647  mod.mNum2 = val;
5648  }
5649  else
5650  {
5651  result = false;
5652  }
5653  }
5654 
5655  if (result == true && attr.hasAttribute("modificationType"))
5656  {
5657  s = attr.getValue("modificationType");
5659 
5660  if (mod.mModType == UNDEFINED_MTYPE)
5661  {
5662  result = false;
5663  }
5664  }
5665 
5666  if (result == true && attr.hasAttribute("offsetX"))
5667  {
5668  s = attr.getValue("offsetX");
5669  err = NULL;
5670  dval = strtod(s.c_str(), err);
5671 
5672  if (!err || *err != s.c_str())
5673  {
5674  mod.mOffset.setX(dval);
5675  }
5676  else
5677  {
5678  result = false;
5679  }
5680  }
5681 
5682  if (result == true && attr.hasAttribute("offsetY"))
5683  {
5684  s = attr.getValue("offsetY");
5685  err = NULL;
5686  dval = strtod(s.c_str(), err);
5687 
5688  if (!err || *err != s.c_str())
5689  {
5690  mod.mOffset.setY(dval);
5691  }
5692  else
5693  {
5694  result = false;
5695  }
5696  }
5697  }
5698 
5699  if (result == true)
5700  {
5701  // optional children: connectScheme, linkTarget and line
5702  const XMLNode* pNode2 = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "line", false);
5703 
5704  if (pNode2 != NULL)
5705  {
5706  result = CCellDesignerImporter::parseLine(pNode2, mod.mLine);
5707  }
5708 
5709  if (result == true)
5710  {
5711  pNode2 = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "connectScheme", false);
5712 
5713  if (pNode2 != NULL)
5714  {
5716  }
5717  }
5718 
5719  if (result == true)
5720  {
5721  // there can be several linkTarget elements
5722  unsigned int i, iMax = pNode->getNumChildren();
5723  mod.mLinkTargets.clear();
5724 
5725  for (i = 0; i < iMax && result == true; ++i)
5726  {
5727  pNode2 = &pNode->getChild(i);
5728 
5729  if (pNode2 != NULL &&
5730  pNode2->getPrefix() == pNode->getPrefix() &&
5731  pNode2->getName() == "linkTarget")
5732  {
5733  LinkTarget l;
5734  result = CCellDesignerImporter::parseLinkTarget(pNode2, l);
5735  mod.mLinkTargets.push_back(l);
5736  }
5737  }
5738  }
5739  }
5740  }
5741  else
5742  {
5743  result = false;
5744  }
5745  }
5746  else
5747  {
5748  result = false;
5749  }
5750 
5751  return result;
5752 }
5753 
5754 /**
5755  * Tries to parse the 2D points in the given string and stores the data in the given
5756  * vector of Points.
5757  * The points vector is cleared by the method.
5758  * If parsing fails, false is returned.
5759  */
5760 bool CCellDesignerImporter::parsePointsString(const std::string& s, std::vector<Point>& points)
5761 {
5762  bool result = true;
5763  // first we need to split the string at the whitespaces
5764  std::string splitChars = " \n\t\r";
5765  std::vector<std::string> parts;
5766  result = CCellDesignerImporter::splitString(s, parts, splitChars);
5767 
5768  if (result == true)
5769  {
5770  points.clear();
5771  std::vector<std::string>::const_iterator it = parts.begin(), endit = parts.end();
5772  std::vector<std::string> tmp;
5773  std::string splitter(",");
5774  char** err;
5775  double dbl;
5776  Point p(new LayoutPkgNamespaces());
5777 
5778  while (it != endit && result == true)
5779  {
5780  // now we have to split the string at the komma
5781  tmp.clear();
5782  result = CCellDesignerImporter::splitString(*it, tmp, splitter);
5783 
5784  if (result == true)
5785  {
5786  if (tmp.size() == 2)
5787  {
5788  err = NULL;
5789  dbl = strtod(tmp[0].c_str(), err);
5790 
5791  if (!err || *err != tmp[0].c_str())
5792  {
5793  p.setX(dbl);
5794  err = NULL;
5795  dbl = strtod(tmp[1].c_str(), err);
5796 
5797  if (!err || *err != tmp[0].c_str())
5798  {
5799  p.setY(dbl);
5800  points.push_back(p);
5801  }
5802  else
5803  {
5804  result = false;
5805  }
5806  }
5807  else
5808  {
5809  result = false;
5810  }
5811  }
5812  else
5813  {
5814  result = false;
5815  }
5816  }
5817 
5818  ++it;
5819  }
5820  }
5821 
5822  return result;
5823 }
5824 
5825 /**
5826  * Splits the given string at each character occurs in splitChars.
5827  * The parts generated are stored in the given vector.
5828  * The vector is cleared by the method.
5829  * If something goes wrong false is returned.
5830  */
5831 bool CCellDesignerImporter::splitString(const std::string& s, std::vector<std::string>& parts, const std::string& splitChars)
5832 {
5833  bool result = true;
5834  parts.clear();
5835 
5836  if (splitChars.empty())
5837  {
5838  parts.push_back(s);
5839  }
5840  else
5841  {
5842  size_t pos = 0;
5843  size_t next = s.find_first_of(splitChars, pos);
5844 
5845  while (next != std::string::npos)
5846  {
5847  // add the substring to parts
5848  parts.push_back(s.substr(pos, next - pos));
5849  pos = next;
5850 
5851  // step after the found character
5852  while (splitChars.find(s[pos]) != std::string::npos)
5853  {
5854  ++pos;
5855  }
5856 
5857  if (pos < s.size())
5858  {
5859  next = s.find_first_of(splitChars, pos);
5860  }
5861  else
5862  {
5863  next = std::string::npos;
5864  }
5865  }
5866 
5867  next = s.find_last_of(splitChars);
5868 
5869  if (next < pos || next == std::string::npos)
5870  {
5871  parts.push_back(s.substr(pos, s.size() - pos));
5872  }
5873  }
5874 
5875  return result;
5876 }
5877 
5878 /**
5879  * Parses the data in the given node which represents a compartment alias
5880  * and stores it in the given CompartmentAlias structure.
5881  * The last argument is the dimensions of the layout.
5882  * This is needed to calculate the bounds for compartments that only specify a point
5883  * and a class.
5884  * If parsing fails, false is returned.
5885  */
5886 bool CCellDesignerImporter::parseCompartmentAlias(const XMLNode* pNode, CompartmentAlias& ca, const Dimensions& ld)
5887 {
5888  bool result = true;
5889 
5890  if (pNode != NULL && pNode->getName() == "compartmentAlias")
5891  {
5892  // attributes are id, compartment
5893  const XMLAttributes& attr = pNode->getAttributes();
5894 
5895  if (attr.hasAttribute("id") && attr.hasAttribute("compartment"))
5896  {
5897  ca.mId = attr.getValue("id");
5898  ca.mCompartment = attr.getValue("compartment");
5899  }
5900  else
5901  {
5902  result = false;
5903  }
5904 
5905  if (result == true)
5906  {
5907  const XMLNode* pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "class", false);
5908 
5909  // we have the class element
5910  if (pChild != NULL && pChild->getNumChildren() == 1 && pChild->getChild(0).isText())
5911  {
5912  ca.mClass = CCellDesignerImporter::classToEnum(pChild->getChild(0).getCharacters());
5913 
5914  if (ca.mClass != UNDEFINED_CLASS)
5915  {
5916  // the bounds element or the point element
5917  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "bounds", false);
5918 
5919  if (pChild != NULL)
5920  {
5921  result = CCellDesignerImporter::parseBounds(pChild, ca.mBounds);
5922  }
5923  else
5924  {
5925  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "point", false);
5926 
5927  if (pChild != NULL)
5928  {
5929  if (pChild->getAttributes().hasAttribute("x") && pChild->getAttributes().hasAttribute("y"))
5930  {
5931  Point tmp(new LayoutPkgNamespaces());
5932  result = CCellDesignerImporter::parsePoint(pChild, tmp);
5933 
5934  if (result == true)
5935  {
5936  // we have to check the class of the compartment alias to calculate the correct bounds
5937  // we should actually do this when we parse the element
5938  switch (ca.mClass)
5939  {
5940  case SQUARE_NW_CLASS:
5941  // the point determines the north western point of the compartment
5942  // so the compartment fills the space from that point to the lower right
5943  // corner of the layout
5944  ca.mBounds.setX(tmp.x());
5945  ca.mBounds.setY(tmp.y());
5946  ca.mBounds.setWidth(ld.getWidth() - tmp.x());
5947  ca.mBounds.setHeight(ld.getHeight() - tmp.y());
5948  break;
5949 
5950  case SQUARE_NE_CLASS:
5951  // the point determines the north eastern point of the compartment
5952  // so the compartment fills the space from that point to the lower left
5953  // corner of the layout
5954  ca.mBounds.setX(0.0);
5955  ca.mBounds.setY(tmp.y());
5956  ca.mBounds.setWidth(tmp.x());
5957  ca.mBounds.setHeight(ld.getHeight() - tmp.y());
5958  break;
5959 
5960  case SQUARE_SW_CLASS:
5961  // the point determines the south western point of the compartment
5962  // so the compartment fills the space from that point to the upper right
5963  // corner of the layout
5964  ca.mBounds.setX(tmp.x());
5965  ca.mBounds.setY(0.0);
5966  ca.mBounds.setWidth(ld.getWidth() - tmp.x());
5967  ca.mBounds.setHeight(tmp.y());
5968  break;
5969 
5970  case SQUARE_SE_CLASS:
5971  // the point determines the southern eastern point of the compartment
5972  // so the compartment fills the space from that point to the upper left
5973  // corner of the layout
5974  ca.mBounds.setX(0.0);
5975  ca.mBounds.setY(0.0);
5976  ca.mBounds.setWidth(tmp.x());
5977  ca.mBounds.setHeight(tmp.y());
5978  break;
5979 
5980  case SQUARE_N_CLASS:
5981  // the compartment fills the lower part of the layout up to the
5982  // y value in the given point
5983  ca.mBounds.setX(0.0);
5984  ca.mBounds.setY(tmp.y());
5985  ca.mBounds.setWidth(ld.getWidth());
5986  ca.mBounds.setHeight(ld.getHeight() - tmp.y());
5987  break;
5988 
5989  case SQUARE_E_CLASS:
5990  // the compartment fills the left part of the layout up to the
5991  // y value in the given point
5992  ca.mBounds.setX(0.0);
5993  ca.mBounds.setY(0.0);
5994  ca.mBounds.setWidth(tmp.x());
5995  ca.mBounds.setHeight(ld.getHeight());
5996  break;
5997 
5998  case SQUARE_W_CLASS:
5999  // the compartment fills the right part of the layout up to the
6000  // y value in the given point
6001  ca.mBounds.setX(tmp.x());
6002  ca.mBounds.setY(0.0);
6003  ca.mBounds.setWidth(ld.getWidth() - tmp.x());
6004  ca.mBounds.setHeight(ld.getHeight());
6005  break;
6006 
6007  case SQUARE_S_CLASS:
6008  // the compartment fills the upper part of the layout up to the
6009  // y value in the given point
6010  ca.mBounds.setX(0.0);
6011  ca.mBounds.setY(0.0);
6012  ca.mBounds.setWidth(ld.getWidth());
6013  ca.mBounds.setHeight(tmp.y());
6014  break;
6015 
6016  default:
6017  result = false;
6018  break;
6019  }
6020  }
6021  }
6022  else
6023  {
6024  result = false;
6025  }
6026  }
6027  else
6028  {
6029  result = false;
6030  }
6031  }
6032 
6033  if (result == true)
6034  {
6035  // we have the namePoint
6036  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "namePoint", false);
6037 
6038  if (pChild != NULL)
6039  {
6040  result = CCellDesignerImporter::parsePoint(pChild, ca.mNamePoint);
6041  }
6042  else
6043  {
6044  result = false;
6045  }
6046 
6047  if (result == true)
6048  {
6049  // we have the double line
6050  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "doubleLine", false);
6051 
6052  if (pChild != NULL && CCellDesignerImporter::parseDoubleLine(pChild, ca.mDoubleLine) == true)
6053  {
6054  // we have the paint
6055  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "paint", false);
6056 
6057  if (pChild != NULL && CCellDesignerImporter::parsePaint(pChild, ca.mPaint) == true)
6058  {
6059  // and we might have a font element with a size attribute that is not describes in the spec
6060  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "font", false);
6061 
6062  if (pChild != NULL && pChild->getAttributes().hasAttribute("size"))
6063  {
6064  std::string s = pChild->getAttributes().getValue("size");
6065  char** err = NULL;
6066  double dbl = strtod(s.c_str(), err);
6067 
6068  if (!err || *err != s.c_str())
6069  {
6070  ca.mFontSize = dbl;
6071  }
6072  else
6073  {
6074  result = false;
6075  }
6076  }
6077  }
6078  else
6079  {
6080  result = false;
6081  }
6082  }
6083  else
6084  {
6085  result = false;
6086  }
6087  }
6088  }
6089  }
6090  else
6091  {
6092  result = false;
6093  }
6094  }
6095  else
6096  {
6097  result = false;
6098  }
6099  }
6100  }
6101  else
6102  {
6103  result = false;
6104  }
6105 
6106  return result;
6107 }
6108 
6109 /**
6110  * Parses the data in the given node which represents a species
6111  * (or ComplexSpecies) alias
6112  * and stores it in the given SpeciesAlias structure.
6113  * If parsing fails, false is returned.
6114  */
6116 {
6117  bool result = true;
6118 
6119  if (pNode != NULL &&
6120  (pNode->getName() == "speciesAlias" ||
6121  pNode->getName() == "complexSpeciesAlias")
6122  )
6123  {
6124  if (pNode->getName() == "complexSpeciesAlias")
6125  {
6126  sa.mComplex = true;
6127  }
6128 
6129  // attributes: id, species compartmentAlias or complesSpeciesAlias
6130  const XMLAttributes& attr = pNode->getAttributes();
6131 
6132  if (attr.hasAttribute("id") && attr.hasAttribute("species"))
6133  {
6134  sa.mId = attr.getValue("id");
6135  sa.mSpecies = attr.getValue("species");
6136 
6137  // complexSpeciesAlias and compartmentAlias attributes are optional
6138  if (attr.hasAttribute("complexSpeciesAlias"))
6139  {
6140  sa.mComplexSpeciesAlias = attr.getValue("complexSpeciesAlias");
6141  }
6142  else if (attr.hasAttribute("compartmentAlias"))
6143  {
6144  sa.mCompartmentAlias = attr.getValue("compartmentAlias");
6145  }
6146 
6147  // elements: font (optional), bounds, usualView
6148  const XMLNode* pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "font", false);
6149 
6150  if (pChild != NULL)
6151  {
6152  std::string s = pChild->getAttributes().getValue("size");
6153  char** err = NULL;
6154  double dbl = strtod(s.c_str(), err);
6155 
6156  if (!err || *err != s.c_str())
6157  {
6158  sa.mFontSize = dbl;
6159  }
6160  else
6161  {
6162  result = false;
6163  }
6164  }
6165 
6166  if (result == true)
6167  {
6168  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "bounds", false);
6169 
6170  if (pChild != NULL && CCellDesignerImporter::parseBounds(pChild, sa.mBounds) == true)
6171  {
6172  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "usualView", false);
6173 
6174  if (pChild != NULL)
6175  {
6176  result = CCellDesignerImporter::parseUsualView(pChild, sa.mUView);
6177  }
6178  }
6179  else
6180  {
6181  result = false;
6182  }
6183  }
6184  }
6185  else
6186  {
6187  result = false;
6188  }
6189  }
6190  else
6191  {
6192  result = false;
6193  }
6194 
6195  return result;
6196 }
6197 
6198 /**
6199  * Parse the data in the given node assuming that this is a node that represents a point
6200  * and therefore contains an "x" and a "y" attribute.
6201  * The data is stored in the given point object.
6202  * If parsing fails, false is returned.
6203  */
6204 bool CCellDesignerImporter::parsePoint(const XMLNode* pNode, Point& p)
6205 {
6206  bool result = true;
6207 
6208  if (pNode != NULL &&
6209  pNode->getAttributes().hasAttribute("x") &&
6210  pNode->getAttributes().hasAttribute("y"))
6211  {
6212  std::string s = pNode->getAttributes().getValue("x");
6213  char** err = NULL;
6214  double val = strtod(s.c_str(), err);
6215 
6216  if (!err || *err != s.c_str())
6217  {
6218  p.setX(val);
6219  s = pNode->getAttributes().getValue("y");
6220  err = NULL;
6221  val = strtod(s.c_str(), err);
6222 
6223  if (!err || *err != s.c_str())
6224  {
6225  p.setY(val);
6226  }
6227  else
6228  {
6229  result = false;
6230  }
6231  }
6232  else
6233  {
6234  result = false;
6235  }
6236  }
6237  else
6238  {
6239  result = false;
6240  }
6241 
6242  return result;
6243 }
6244 
6245 /**
6246  * Parse the data in the given node assuming that this is a node that represents a point
6247  * and therefore contains an "x" and a "y" attribute.
6248  * The data is stored in the given point object.
6249  * If parsing fails, false is returned.
6250  */
6251 bool CCellDesignerImporter::parseBounds(const XMLNode* pNode, BoundingBox& box)
6252 {
6253  bool result = true;
6254 
6255  if (pNode != NULL &&
6256  pNode->getAttributes().hasAttribute("x") &&
6257  pNode->getAttributes().hasAttribute("y") &&
6258  pNode->getAttributes().hasAttribute("w") &&
6259  pNode->getAttributes().hasAttribute("h"))
6260  {
6261  result = CCellDesignerImporter::parsePoint(pNode, *box.getPosition());
6262 
6263  if (result == true)
6264  {
6265  std::string s = pNode->getAttributes().getValue("w");
6266  char** err = NULL;
6267  double val = strtod(s.c_str(), err);
6268 
6269  if (!err || *err != s.c_str())
6270  {
6271  box.getDimensions()->setWidth(val);
6272  s = pNode->getAttributes().getValue("h");
6273  err = NULL;
6274  val = strtod(s.c_str(), err);
6275 
6276  if (!err || *err != s.c_str())
6277  {
6278  box.getDimensions()->setHeight(val);
6279  }
6280  else
6281  {
6282  result = false;
6283  }
6284  }
6285  else
6286  {
6287  result = false;
6288  }
6289  }
6290  }
6291  else
6292  {
6293  result = false;
6294  }
6295 
6296  return result;
6297 }
6298 
6299 /**
6300  * Parses the data in the given node which represents a UsualView object and stores
6301  * the parsed data in the given UsualView structure.
6302  * If parsinf fails, false is returned.
6303  */
6304 bool CCellDesignerImporter::parseUsualView(const XMLNode* pNode, UsualView& view)
6305 {
6306  bool result = true;
6307 
6308  if (pNode != NULL && pNode->getName() == "usualView")
6309  {
6310  // elements: innerPosition (optional)
6311  // boxSize
6312  // singleLine
6313  // paint
6314  const XMLNode* pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "innerPosition", false);
6315 
6316  if (pChild != NULL)
6317  {
6318  result = CCellDesignerImporter::parsePoint(pChild, view.mInnerPosition);
6319  }
6320 
6321  if (result == true)
6322  {
6323  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "boxSize", false);
6324 
6325  if (pChild != NULL && CCellDesignerImporter::parseBoxSize(pChild, view.mBoxSize) == true)
6326  {
6327  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "paint", false);
6328 
6329  if (pChild != NULL && CCellDesignerImporter::parsePaint(pChild, view.mPaint) == true)
6330  {
6331  pChild = CCellDesignerImporter::findChildNode(pNode, pNode->getPrefix(), "singleLine", false);
6332 
6333  if (pChild != NULL && pChild->getAttributes().hasAttribute("width"))
6334  {
6335  std::string s = pChild->getAttributes().getValue("width");
6336  char** err = NULL;
6337  double dbl = strtod(s.c_str(), err);
6338 
6339  if (!err || *err != s.c_str())
6340  {
6341  view.mLineWidth = dbl;
6342  }
6343  else
6344  {
6345  result = false;
6346  }
6347  }
6348  else
6349  {
6350  result = false;
6351  }
6352  }
6353  else
6354  {
6355  result = false;
6356  }
6357  }
6358  else
6359  {
6360  result = false;
6361  }
6362  }
6363  }
6364  else
6365  {
6366  result = false;
6367  }
6368 
6369  return result;
6370 }
6371 
6372 /**
6373  * Parses the given node and stored the information iín the width and height attribute
6374  * in the given dimensions object.
6375  * If parsinf fails, false is returned.
6376  */
6377 bool CCellDesignerImporter::parseModelDisplay(const XMLNode* pNode, Dimensions& d)
6378 {
6379  bool result = true;
6380 
6381  if (pNode != NULL &&
6382  pNode->getName() == "modelDisplay" &&
6383  pNode->getAttributes().hasAttribute("sizeX") &&
6384  pNode->getAttributes().hasAttribute("sizeY"))
6385  {
6386  std::string s = pNode->getAttributes().getValue("sizeX");
6387  char** err = NULL;
6388  double val = strtod(s.c_str(), err);
6389 
6390  if (!err || *err != s.c_str())
6391  {
6392  d.setWidth(val);
6393  s = pNode->getAttributes().getValue("sizeY");
6394  err = NULL;
6395  val = strtod(s.c_str(), err);
6396 
6397  if (!err || *err != s.c_str())
6398  {
6399  d.setHeight(val);
6400  }
6401  else
6402  {
6403  result = false;
6404  }
6405  }
6406  else
6407  {
6408  result = false;
6409  }
6410  }
6411  else
6412  {
6413  result = false;
6414  }
6415 
6416  return result;
6417 }
6418 
6419 /**
6420  * Parses the given node and stored the information iín the width and height attribute
6421  * in the given dimensions object.
6422  * If parsinf fails, false is returned.
6423  */
6424 bool CCellDesignerImporter::parseBoxSize(const XMLNode* pNode, Dimensions& d)
6425 {
6426  bool result = true;
6427 
6428  if (pNode != NULL &&
6429  pNode->getAttributes().hasAttribute("width") &&
6430  pNode->getAttributes().hasAttribute("height"))
6431  {
6432  std::string s = pNode->getAttributes().getValue("width");
6433  char** err = NULL;
6434  double val = strtod(s.c_str(), err);
6435 
6436  if (!err || *err != s.c_str())
6437  {
6438  d.setWidth(val);
6439  s = pNode->getAttributes().getValue("height");
6440  err = NULL;
6441  val = strtod(s.c_str(), err);
6442 
6443  if (!err || *err != s.c_str())
6444  {
6445  d.setHeight(val);
6446  }
6447  else
6448  {
6449  result = false;
6450  }
6451  }
6452  else
6453  {
6454  result = false;
6455  }
6456  }
6457  else
6458  {
6459  result = false;
6460  }
6461 
6462  return result;
6463 }
6464 
6465 /**
6466  * Parses the given XMLNode which represents a double line element.
6467  * The parsed data is stored in the given DoubleLine structure.
6468  * If parsing fails, false is returned.
6469  */
6471 {
6472  bool result = true;
6473 
6474  if (pNode != NULL &&
6475  pNode->getName() == "doubleLine")
6476  {
6477  const XMLAttributes& attr = pNode->getAttributes();
6478 
6479  if (attr.hasAttribute("innerWidth") &&
6480  attr.hasAttribute("outerWidth") &&
6481  attr.hasAttribute("thickness"))
6482  {
6483  std::string s = attr.getValue("innerWidth");
6484  char** err = NULL;
6485  double val = strtod(s.c_str(), err);
6486 
6487  if (!err || *err != s.c_str())
6488  {
6489  dl.mInnerWidth = val;
6490  s = attr.getValue("outerWidth");
6491  err = NULL;
6492  val = strtod(s.c_str(), err);
6493 
6494  if (!err || *err != s.c_str())
6495  {
6496  dl.mOuterWidth = val;
6497  s = attr.getValue("thickness");
6498  err = NULL;
6499  val = strtod(s.c_str(), err);
6500 
6501  if (!err || *err != s.c_str())
6502  {
6503  dl.mThickness = val;
6504  }
6505  else
6506  {
6507  result = false;
6508  }
6509  }
6510  else
6511  {
6512  result = false;
6513  }
6514  }
6515  else
6516  {
6517  result = false;
6518  }
6519  }
6520  else
6521  {
6522  result = false;
6523  }
6524  }
6525  else
6526  {
6527  result = false;
6528  }
6529 
6530  return result;
6531 }
6532 
6533 /**
6534  * Parses the paint data in the given XMLNode and stores the result in the
6535  * given Paint structure.
6536  * If parsing fails, false is returned.
6537  */
6538 bool CCellDesignerImporter::parsePaint(const XMLNode* pNode, Paint& p)
6539 {
6540  bool result = true;
6541 
6542  if (pNode != NULL && pNode->getName() == "paint")
6543  {
6544  const XMLAttributes& attr = pNode->getAttributes();
6545 
6546  if (attr.hasAttribute("color") &&
6547  attr.hasAttribute("scheme"))
6548  {
6549  p.mColor = attr.getValue("color");
6550  // we convert the string to upper
6551  // and add the # in front and we
6552  // convert the aRGB to RGBa
6553  std::transform(p.mColor.begin(), p.mColor.end(), p.mColor.begin(), ::toupper);
6554  p.mColor = "#" + p.mColor.substr(2) + p.mColor.substr(0, 2);
6555  p.mScheme = CCellDesignerImporter::paintSchemeToEnum(attr.getValue("scheme"));
6556 
6557  if (p.mScheme == PAINT_UNDEFINED)
6558  {
6559  result = false;
6560  }
6561  }
6562  else
6563  {
6564  result = false;
6565  }
6566  }
6567  else
6568  {
6569  result = false;
6570  }
6571 
6572  return result;
6573 }
6574 
6575 /**
6576  * This method creates a new local style based on the passed in CompartmentAlias object.
6577  * The style is associated with the object via the given id.
6578  * If Creating the style fails, false is returned.
6579  */
6580 bool CCellDesignerImporter::createCompartmentStyle(const CompartmentAlias& ca, const CompartmentGlyph* pCGlyph)
6581 {
6582  // TODO the GRADIENT flag is currently ignored
6583  bool result = true;
6584 
6585  if (this->mpLocalRenderInfo != NULL &&
6586  !ca.mPaint.mColor.empty() &&
6587  pCGlyph != NULL &&
6588  !pCGlyph->getId().empty())
6589  {
6590  std::string color_id;
6591  result = this->findOrCreateColorDefinition(ca.mPaint.mColor, color_id);
6592  // CellDesigner seems to use the paint color for the two edges
6593  // of the compartment representation
6594  // The inner area (between the two edges seems to be filled with the same color, but
6595  // with a opacity value of about 35 (23 hex).
6596  std::string inner_color_id, inner_color_string = ca.mPaint.mColor;
6597 
6598  if (inner_color_string.length() == 7)
6599  {
6600  inner_color_string += "23";
6601  result = this->findOrCreateColorDefinition(inner_color_string, inner_color_id);
6602  }
6603  else if (inner_color_string.length() == 9)
6604  {
6605  inner_color_string[7] = '2';
6606  inner_color_string[8] = '3';
6607  result = this->findOrCreateColorDefinition(inner_color_string, inner_color_id);
6608  }
6609  else
6610  {
6611  result = false;
6612  }
6613 
6614  if (result == true)
6615  {
6616  // create a new style for the object
6617  std::string style_id = this->createUniqueId("Style");
6618  LocalStyle* pStyle = this->mpLocalRenderInfo->createStyle(style_id);
6619 
6620  if (pStyle != NULL)
6621  {
6622  this->mIdMap.insert(std::pair<std::string, const SBase*>(style_id, pStyle));
6623  RenderGroup* pGroup = pStyle->getGroup();
6624  assert(pGroup != NULL);
6625 
6626  if (pGroup != NULL)
6627  {
6628  // set the font size
6629  pGroup->setFontSize(ca.m