1 /**
2 * @file RenderLayoutPlugin.cpp
3 * @brief Implementation of RenderLayoutPlugin, the plugin class of
4 * the fbc package for the Model element.
5 * @author Frank T. Bergmann
6 *
7 *<!---------------------------------------------------------------------------
8 * This file is part of libSBML. Please visit http://sbml.org for more
9 * information about SBML, and the latest version of libSBML.
10 *
11 * Copyright (C) 2020 jointly by the following organizations:
12 * 1. California Institute of Technology, Pasadena, CA, USA
13 * 2. University of Heidelberg, Heidelberg, Germany
14 * 3. University College London, London, UK
15 *
16 * Copyright (C) 2019 jointly by the following organizations:
17 * 1. California Institute of Technology, Pasadena, CA, USA
18 * 2. University of Heidelberg, Heidelberg, Germany
19 *
20 * Copyright (C) 2013-2018 jointly by the following organizations:
21 * 1. California Institute of Technology, Pasadena, CA, USA
22 * 2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK
23 * 3. University of Heidelberg, Heidelberg, Germany
24 *
25 * Copyright (C) 2009-2013 jointly by the following organizations:
26 * 1. California Institute of Technology, Pasadena, CA, USA
27 * 2. EMBL European Bioinformatics Institute (EMBL-EBI), Hinxton, UK
28 *
29 * This library is free software; you can redistribute it and/or modify it
30 * under the terms of the GNU Lesser General Public License as published by
31 * the Free Software Foundation. A copy of the license agreement is provided
32 * in the file named "LICENSE.txt" included with this software distribution
33 * and also available online as http://sbml.org/software/libsbml/license.html
34 *------------------------------------------------------------------------- -->
35 */
36
37 #include <sbml/packages/render/extension/RenderExtension.h>
38 #include <sbml/packages/render/extension/RenderLayoutPlugin.h>
39 #include <sbml/packages/render/common/RenderExtensionTypes.h>
40 #include <sbml/packages/render/util/RenderUtilities.h>
41
42
43 #include <sbml/packages/layout/sbml/Layout.h>
44
45 #include <sbml/util/ElementFilter.h>
46
47 #include <iostream>
48 using namespace std;
49
50
51 #ifdef __cplusplus
52
53 LIBSBML_CPP_NAMESPACE_BEGIN
54
55
56
57 /*
58 * Constructor
59 */
RenderLayoutPlugin(const std::string & uri,const std::string & prefix,RenderPkgNamespaces * renderns)60 RenderLayoutPlugin::RenderLayoutPlugin (const std::string &uri,
61 const std::string &prefix,
62 RenderPkgNamespaces *renderns)
63 : SBasePlugin(uri,prefix, renderns)
64 , mLocalRenderInformation(renderns)
65 {
66 }
67
68
69 /*
70 * Copy constructor. Creates a copy of this SBase object.
71 */
RenderLayoutPlugin(const RenderLayoutPlugin & orig)72 RenderLayoutPlugin::RenderLayoutPlugin(const RenderLayoutPlugin& orig)
73 : SBasePlugin(orig)
74 , mLocalRenderInformation(orig.mLocalRenderInformation)
75 {
76 }
77
78
79 /*
80 * Destroy this object.
81 */
~RenderLayoutPlugin()82 RenderLayoutPlugin::~RenderLayoutPlugin () {}
83
84 /*
85 * Assignment operator for RenderLayoutPlugin.
86 */
87 RenderLayoutPlugin&
operator =(const RenderLayoutPlugin & orig)88 RenderLayoutPlugin::operator=(const RenderLayoutPlugin& orig)
89 {
90 if(&orig!=this)
91 {
92 this->SBasePlugin::operator =(orig);
93 }
94 return *this;
95 }
96
97
98 /*
99 * Creates and returns a deep copy of this RenderLayoutPlugin object.
100 *
101 * @return a (deep) copy of this RenderLayoutPlugin object
102 */
103 RenderLayoutPlugin*
clone() const104 RenderLayoutPlugin::clone () const
105 {
106 return new RenderLayoutPlugin(*this);
107 }
108
109
110 List*
getAllElements(ElementFilter * filter)111 RenderLayoutPlugin::getAllElements(ElementFilter* filter)
112 {
113 List* ret = new List();
114 List* sublist = NULL;
115
116 ADD_FILTERED_LIST(ret, sublist, mLocalRenderInformation, filter);
117
118 return ret;
119 }
120
121
122 /** @cond doxygenLibsbmlInternal */
123 SBase*
createObject(XMLInputStream & stream)124 RenderLayoutPlugin::createObject(XMLInputStream& stream)
125 {
126 SBase* object = 0;
127
128 const std::string& name = stream.peek().getName();
129 const XMLNamespaces& xmlns = stream.peek().getNamespaces();
130 const std::string& prefix = stream.peek().getPrefix();
131
132 const std::string& targetPrefix = (xmlns.hasURI(mURI)) ? xmlns.getPrefix(mURI) : mPrefix;
133
134 if (prefix == targetPrefix)
135 {
136 if ( name == "listOfRenderInformation" )
137 {
138 //cout << "[DEBUG] LayoutModelPlugin::createObject create listOfLayouts" << endl;
139 object = &mLocalRenderInformation;
140
141 if (targetPrefix.empty())
142 {
143 //
144 // prefix is empty when writing elements in layout extension.
145 //
146 mLocalRenderInformation.getSBMLDocument()->enableDefaultNS(mURI,true);
147 }
148 }
149 }
150
151 return object;
152 }
153 /** @endcond */
154
155 /** @cond doxygenLibsbmlInternal */
156 void
writeAttributes(XMLOutputStream & stream) const157 RenderLayoutPlugin::writeAttributes (XMLOutputStream& stream) const
158 {
159 //
160 // This function is used only for SBML Level 2.
161 //
162 if ( getURI() != RenderExtension::getXmlnsL2() ) return;
163
164 SBase *parent = const_cast<SBase*>(getParentSBMLObject());
165 if (parent == NULL)
166 return;
167
168 // when called this will serialize the annotation
169 parent->getAnnotation();
170 }
171 /** @endcond */
172
173 /** @cond doxygenLibsbmlInternal */
174 void
writeElements(XMLOutputStream & stream) const175 RenderLayoutPlugin::writeElements (XMLOutputStream& stream) const
176 {
177 if ( getURI() == RenderExtension::getXmlnsL2() ) return;
178 if (mLocalRenderInformation.size() > 0 || mLocalRenderInformation.isSetDefaultValues())
179 mLocalRenderInformation.write(stream);
180 }
181 /** @endcond */
182
183 /** @cond doxygenLibsbmlInternal */
184
185 /*
186 * Parse L2 annotation if supported
187 *
188 */
189 void
parseAnnotation(SBase * parentObject,XMLNode * annotation)190 RenderLayoutPlugin::parseAnnotation(SBase *parentObject, XMLNode *annotation)
191 {
192 mLocalRenderInformation.setSBMLDocument(mSBML);
193 parseLocalRenderAnnotation(annotation,(Layout*)parentObject);
194 }
195 /** @endcond */
196
197
198 /** @cond doxygenLibsbmlInternal */
199 /*
200 * Synchronizes the annotation of this SBML object.
201 */
202 void
syncAnnotation(SBase * parentObject,XMLNode * pAnnotation)203 RenderLayoutPlugin::syncAnnotation (SBase *parentObject, XMLNode *pAnnotation)
204 {
205 if(pAnnotation && pAnnotation->getNumChildren() > 0)
206 {
207 parentObject->removeTopLevelAnnotationElement("listOfRenderInformation", "", false);
208 }
209
210 // only do this for L1 and L2 documents
211 if(getLevel() >= 3)
212 return;
213
214
215 if (mLocalRenderInformation.size() == 0)
216 return;
217
218 XMLNode * render = parseLocalRenderInformation((Layout*)parentObject);
219 if (render == NULL)
220 return;
221
222
223 if (pAnnotation == NULL)
224 {
225 // cannot happen, as syncAnnotation is called with a valid Annotation
226 // (possibly empty)
227 return;
228 }
229 else
230 {
231 if (pAnnotation->isEnd())
232 {
233 pAnnotation->unsetEnd();
234 }
235 pAnnotation->addChild(render->getChild(0));
236 delete render;
237 }
238
239
240
241 }
242 /** @endcond */
243
244
245 /** @cond doxygenLibsbmlInternal */
246 /*
247 * Subclasses should override this method to read (and store) XHTML,
248 * MathML, etc. directly from the XMLInputStream.
249 *
250 * @return @c true if the subclass read from the stream, false otherwise.
251 */
252 bool
readOtherXML(SBase * parentObject,XMLInputStream & stream)253 RenderLayoutPlugin::readOtherXML (SBase* parentObject, XMLInputStream& stream)
254 {
255 // L2 render parsed by the annotation API
256 // @see parseAnnotation / syncAnnotation
257 return false;
258 }
259 /** @endcond */
260
261
262 /** @cond doxygenLibsbmlInternal */
263 /* default for components that have no required elements */
264 bool
hasRequiredElements() const265 RenderLayoutPlugin::hasRequiredElements() const
266 {
267 bool allPresent = true;
268
269 return allPresent;
270 }
271 /** @endcond */
272
273
274
275 /*
276 *
277 * (EXTENSION) Additional public functions
278 *
279 */
280
281
282
283 /** @cond doxygenLibsbmlInternal */
284 /*
285 * Sets the parent SBMLDocument of this SBML object.
286 *
287 * @param d the SBMLDocument object to use
288 */
289 void
setSBMLDocument(SBMLDocument * d)290 RenderLayoutPlugin::setSBMLDocument (SBMLDocument* d)
291 {
292 SBasePlugin::setSBMLDocument(d);
293 mLocalRenderInformation.setSBMLDocument(d);
294 if (mLocalRenderInformation.isSetDefaultValues())
295 {
296 mLocalRenderInformation.getDefaultValues()->setSBMLDocument(d);
297 }
298 }
299 /** @endcond */
300
301
302 /** @cond doxygenLibsbmlInternal */
303 /*
304 * Sets the parent SBML object of this plugin object to
305 * this object and child elements (if any).
306 * (Creates a child-parent relationship by this plugin object)
307 */
308 void
connectToParent(SBase * sbase)309 RenderLayoutPlugin::connectToParent (SBase* sbase)
310 {
311 SBasePlugin::connectToParent(sbase);
312 mLocalRenderInformation.connectToParent(sbase);
313 }
314 /** @endcond */
315
316
317 /** @cond doxygenLibsbmlInternal */
318 /*
319 * Enables/Disables the given package with child elements in this plugin
320 * object (if any).
321 */
322 void
enablePackageInternal(const std::string & pkgURI,const std::string & pkgPrefix,bool flag)323 RenderLayoutPlugin::enablePackageInternal(const std::string& pkgURI,
324 const std::string& pkgPrefix, bool flag)
325 {
326 mLocalRenderInformation.enablePackageInternal(pkgURI, pkgPrefix, flag);
327 }
328 /** @endcond */
329
330
331 /*
332 * Returns a pointer to the list object that contains local render information.
333 */
getListOfLocalRenderInformation()334 ListOfLocalRenderInformation* RenderLayoutPlugin::getListOfLocalRenderInformation()
335 {
336 return &mLocalRenderInformation;
337 }
338
339 /*
340 * Returns a const pointer to the list object that contains local render information.
341 */
getListOfLocalRenderInformation() const342 const ListOfLocalRenderInformation* RenderLayoutPlugin::getListOfLocalRenderInformation() const
343 {
344 return &mLocalRenderInformation;
345 }
346
347
348 /*
349 * Returns the number of local render information objects.
350 */
getNumLocalRenderInformationObjects() const351 unsigned int RenderLayoutPlugin::getNumLocalRenderInformationObjects() const
352 {
353 return mLocalRenderInformation.size();
354 }
355
356 /*
357 * Returns a pointer to the local render information object with the given
358 * index.
359 * If the index is invalid, @c NULL is returned.
360 */
getRenderInformation(unsigned int index)361 LocalRenderInformation* RenderLayoutPlugin::getRenderInformation(unsigned int index)
362 {
363 if(index < mLocalRenderInformation.size())
364 {
365 return static_cast<LocalRenderInformation*>(mLocalRenderInformation.get(index));
366 }
367 else
368 {
369 return NULL;
370 }
371 }
372
373 /*
374 * Returns a const pointer to the local render information object with the given
375 * index.
376 * If the index is invalid, @c NULL is returned.
377 */
getRenderInformation(unsigned int index) const378 const LocalRenderInformation* RenderLayoutPlugin::getRenderInformation(unsigned int index) const
379 {
380 if(index < mLocalRenderInformation.size())
381 {
382 return static_cast<const LocalRenderInformation*>(mLocalRenderInformation.get(index));
383 }
384 else
385 {
386 return NULL;
387 }
388 }
389
390 /*
391 * Returns a pointer to the local render information object with the given
392 * id.
393 * If no object with the given @p id exists, @c NULL is returned.
394 */
getRenderInformation(const std::string & id)395 LocalRenderInformation* RenderLayoutPlugin::getRenderInformation(const std::string& id)
396 {
397 LocalRenderInformation* pResult=NULL;
398 unsigned int i=0,iMax=mLocalRenderInformation.size();
399 while(i<iMax)
400 {
401 if(mLocalRenderInformation.get(i)->getId()==id)
402 {
403 pResult=static_cast<LocalRenderInformation*>(mLocalRenderInformation.get(i));
404 break;
405 }
406 ++i;
407 }
408 return pResult;
409 }
410
411 /*
412 * Returns a const pointer to the local render information object with the given
413 * id.
414 * If no object with the given @p id exists, @c NULL is returned.
415 */
getRenderInformation(const std::string & id) const416 const LocalRenderInformation* RenderLayoutPlugin::getRenderInformation(const std::string& id) const
417 {
418 const LocalRenderInformation* pResult=NULL;
419 unsigned int i=0,iMax=mLocalRenderInformation.size();
420 while(i<iMax)
421 {
422 if(mLocalRenderInformation.get(i)->getId()==id)
423 {
424 pResult=static_cast<const LocalRenderInformation*>(mLocalRenderInformation.get(i));
425 break;
426 }
427 ++i;
428 }
429 return pResult;
430 }
431
432 /*
433 * Adds a copy of the given local render information object to the list of
434 * local render information objects.
435 */
addLocalRenderInformation(const LocalRenderInformation * pLRI)436 void RenderLayoutPlugin::addLocalRenderInformation(const LocalRenderInformation* pLRI)
437 {
438
439 mLocalRenderInformation.appendAndOwn(new LocalRenderInformation(*pLRI));
440 }
441
442 /*
443 * Creates a new local render information object and adds it to the list.
444 * The created object does not have a id and it is the responsibility of
445 * the calling code to ensure that it gets one.
446 * For constraints on the id, please consult the render information document.
447 */
createLocalRenderInformation()448 LocalRenderInformation* RenderLayoutPlugin::createLocalRenderInformation()
449 {
450 RENDER_CREATE_NS(renderns, getSBMLNamespaces());
451 LocalRenderInformation* pGRI=new LocalRenderInformation(renderns);
452
453 mLocalRenderInformation.appendAndOwn(pGRI);
454 delete renderns;
455 return pGRI;
456 }
457
458 /*
459 * Removed the render information with the given index from the list.
460 * The removed object is returned. It is the responsibility of the calling
461 * code to delete the object.
462 * If the index is not valid, @c NULL is returned.
463 */
removeLocalRenderInformation(unsigned int index)464 LocalRenderInformation* RenderLayoutPlugin::removeLocalRenderInformation(unsigned int index)
465 {
466 if(index < mLocalRenderInformation.size())
467 {
468 return static_cast<LocalRenderInformation*>(mLocalRenderInformation.remove(index));
469 }
470 else
471 {
472 return NULL;
473 }
474 }
475
476 /*
477 * Removed the render information with the given @p id from the list.
478 * The removed object is returned. It is the responsibility of the calling
479 * code to delete the object.
480 * If an object with the given @p id does not exist, @c NULL is returned.
481 */
removeLocalRenderInformation(const std::string & id)482 LocalRenderInformation* RenderLayoutPlugin::removeLocalRenderInformation(const std::string& id)
483 {
484 unsigned int i=0,iMax=mLocalRenderInformation.size();
485 while(i<iMax)
486 {
487 if(mLocalRenderInformation.get(i)->isSetId() && mLocalRenderInformation.get(i)->getId()==id)
488 {
489 break;
490 }
491 ++i;
492 }
493 if(i!=iMax)
494 {
495 return removeLocalRenderInformation(i);
496 }
497 else
498 {
499 return NULL;
500 }
501 }
502
503 /** @cond doxygenLibsbmlInternal */
504
505 bool
accept(SBMLVisitor & v) const506 RenderLayoutPlugin::accept (SBMLVisitor& v) const
507 {
508 return true;
509 }
510
511 /** @endcond */
512
513
514
515
516 #ifdef ANNOTATION
517
518 /** @cond doxygenLibsbmlInternal */
519 /*
520 * Subclasses should override this method to read (and store) XHTML,
521 * MathML, etc. directly from the XMLInputStream.
522 *
523 * @return @c true if the subclass read from the stream, false otherwise.
524 */
525 bool
readOtherXML(XMLInputStream & stream)526 RenderLayoutPlugin::readOtherXML (XMLInputStream& stream)
527 {
528 bool read = false;
529 const std::string& name = stream.peek().getName();
530
531 // This has to do additional work for reading annotations, so the code
532
533 if (name == "annotation")
534 {
535 if (mAnnotation)
536 {
537 if (getLevel() < 3)
538 {
539 logError(NotSchemaConformant, getLevel(), getVersion(),
540 "Only one <annotation> element is permitted inside a "
541 "particular containing element.");
542 }
543 else
544 {
545 logError(MultipleAnnotations, getLevel(), getVersion());
546 }
547 }
548
549 delete mAnnotation;
550 mAnnotation = new XMLNode(stream);
551 checkAnnotation();
552 // only parse layout from annotations for Level 2 and below
553 if(getLevel() < 3)
554 {
555 mLocalRenderInformation.setSBMLDocument(mSBML);
556 parseLocalRenderAnnotation(mAnnotation,this);
557 }
558
559 read = true;
560 }
561
562 return read;
563 }
564 /** @endcond */
565
566 /*
567 * Sets the annotation of this SBML object to a copy of annotation.
568 */
569 int
setAnnotation(const XMLNode * annotation)570 RenderLayoutPlugin::setAnnotation (const XMLNode* annotation)
571 {
572 int success = SBase::setAnnotation(annotation);
573 if(success == LIBSBML_OPERATION_SUCCESS && getLevel() < 3)
574 {
575 for(unsigned int i=0; i < mLocalRenderInformation.size(); i++)
576 {
577 LocalRenderInformation* lr = static_cast<LocalRenderInformation*>(mLocalRenderInformation.remove(0));
578 delete lr;
579 }
580
581 if(mAnnotation)
582 {
583 // parse mAnnotation (if any) and set mLayouts
584 mLocalRenderInformation.setSBMLDocument(mSBML);
585 parseLocalRenderAnnotation(mAnnotation,this);
586 }
587 }
588 return success;
589 }
590
591
592 /*
593 * Appends annotation to the existing annotations.
594 * This allows other annotations to be preserved whilst
595 * adding additional information.
596 */
597 int
appendAnnotation(const XMLNode * annotation)598 RenderLayoutPlugin::appendAnnotation (const XMLNode* annotation)
599 {
600 int success = LIBSBML_OPERATION_FAILED;
601 if(!annotation) return LIBSBML_OPERATION_SUCCESS;
602
603 XMLNode* new_annotation = NULL;
604 const std::string& name = annotation->getName();
605
606 // check for annotation tags and add if necessary
607 if (name != "annotation")
608 {
609 XMLToken ann_t = XMLToken(XMLTriple("annotation", "", ""), XMLAttributes());
610 new_annotation = new XMLNode(ann_t);
611 new_annotation->addChild(*annotation);
612 }
613 else
614 {
615 new_annotation = annotation->clone();
616 }
617
618 if(getLevel() < 3)
619 {
620 // parse new_annotation and add mLayouts
621 mLocalRenderInformation.setSBMLDocument(mSBML);
622 parseLocalRenderAnnotation(new_annotation,this);
623
624 }
625
626 success = SBase::appendAnnotation(new_annotation);
627 delete new_annotation;
628
629 return success;
630 }
631
632
633 /** @cond doxygenLibsbmlInternal */
634 /*
635 * Synchronizes the annotation of this SBML object.
636 */
637 void
syncAnnotation()638 RenderLayoutPlugin::syncAnnotation ()
639 {
640 SBase::syncAnnotation();
641 // only write the render information to an annotation
642 // if we are in a L1 or L2 document
643 if(getLevel() < 3)
644 {
645 if(mAnnotation)
646 {
647 XMLNode* new_annotation = deleteLocalRenderAnnotation(mAnnotation);
648 delete mAnnotation;
649 mAnnotation = new_annotation;
650 }
651 if (getListOfLocalRenderInformation()->size()!=0)
652 {
653 XMLNode * render = parseLocalRenderInformation(this);
654
655 if (render)
656 {
657 if (!mAnnotation)
658 {
659 mAnnotation = render;
660 }
661 else
662 {
663 if (mAnnotation->isEnd())
664 {
665 mAnnotation->unsetEnd();
666 }
667 mAnnotation->addChild(render->getChild(0));
668 delete render;
669 }
670 }
671 }
672 }
673 }
674 /** @endcond */
675 #endif
676
677 LIBSBML_CPP_NAMESPACE_END
678
679 #endif /* __cplusplus */
680