1 /*
2 * ****************************************************************************
3 * This file is part of libNUML.  Please visit http://code.google.com/p/numl/for more
4 * information about NUML, and the latest version of libNUML.
5 * Copyright (c) 2013 The University of Manchester.
6 *
7 * This library is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published
9 * by the Free Software Foundation.  A copy of the license agreement is
10 * provided in the file named "LICENSE.txt" included with this software
11 * distribution and also available online as http://www.gnu.org/licenses/lgpl.html
12 *
13 * Contributors:
14 * Joseph O. Dada, The University of Manchester - initial API and implementation
15 * ****************************************************************************
16 **/
17 
18 #include <algorithm>
19 #include <functional>
20 
21 #include <numl/NUMLVisitor.h>
22 #include <numl/NUMLList.h>
23 
24 using namespace std;
25 
26 LIBNUML_CPP_NAMESPACE_BEGIN
27 
NUMLList(unsigned int level,unsigned int version)28 NUMLList::NUMLList (unsigned int level, unsigned int version) :
29    NMBase ( level, version )
30 {
31   if (!hasValidLevelVersionNamespaceCombination())
32     throw NUMLConstructorException();
33 }
34 
NUMLList(NUMLNamespaces * numlns)35 NUMLList::NUMLList (NUMLNamespaces *numlns) :
36     NMBase                   ( numlns )
37 {
38   if (!hasValidLevelVersionNamespaceCombination())
39     throw NUMLConstructorException();
40 }
41 
42 /*
43  * Creates a new NUMLList items.
44  */
NUMLList()45 NUMLList::NUMLList ()
46 {
47 }
48 
49 
50 /**
51  * Used by the Destructor to delete each item in mItems.
52  */
53 struct Delete
54 {
operator ()Delete55   void operator() (NMBase* sb) { delete sb; }
56 };
57 
58 
59 /*
60  * Destroys the given NUMLList and its constituent items.
61  */
~NUMLList()62 NUMLList::~NUMLList ()
63 {
64   for_each( mItems.begin(), mItems.end(), Delete() );
65 }
66 
67 
68 /**
69  * Used by the Copy Constructor to clone each item in mItems.
70  */
71 struct Clone
72 {
operator ()Clone73   NMBase* operator() (NMBase* sb) { return sb->clone(); }
74 };
75 
76 
77 /*
78  * Copy constructor. Creates a copy of this NUMLList items.
79  */
NUMLList(const NUMLList & orig)80 NUMLList::NUMLList (const NUMLList& orig) : NMBase(orig)
81 {
82   mItems.resize( orig.size() );
83   transform( orig.mItems.begin(), orig.mItems.end(), mItems.begin(), Clone() );
84 }
85 
86 
87 /*
88  * Assignment operator
89  */
operator =(const NUMLList & rhs)90 NUMLList& NUMLList::operator=(const NUMLList& rhs)
91 {
92   if(&rhs!=this)
93   {
94     this->NMBase::operator =(rhs);
95     // Deletes existing items
96     for_each( mItems.begin(), mItems.end(), Delete() );
97     mItems.resize( rhs.size() );
98     transform( rhs.mItems.begin(), rhs.mItems.end(), mItems.begin(), Clone() );
99   }
100 
101   return *this;
102 }
103 
104 /*
105  * Accepts the given NUMLVisitor.
106  */
107 bool
accept(NUMLVisitor & v) const108 NUMLList::accept (NUMLVisitor& v) const
109 {
110   v.visit(*this, getItemTypeCode() );
111   for (unsigned int n = 0 ; n < mItems.size() && mItems[n]->accept(v); ++n) ;
112   v.leave(*this, getItemTypeCode() );
113 
114   return true;
115 }
116 
117 
118 /*
119  * @return a (deep) copy of this NUMLList items.
120  */
121 NMBase*
clone() const122 NUMLList::clone () const
123 {
124   return new NUMLList(*this);
125 }
126 
127 
128 /*
129  * Adds item to the end of this NUMLList items.  This NUMLList items assumes
130  * ownership of item and will delete it.
131  */
132 void
append(const NMBase * item)133 NUMLList::append (const NMBase* item)
134 {
135   appendAndOwn( item->clone() );
136 }
137 
138 
139 /*
140  * Adds item to the end of this NUMLList items.  This NUMLList items assumes
141  * ownership of item and will delete it.
142  */
143 void
appendAndOwn(NMBase * item)144 NUMLList::appendAndOwn (NMBase* item)
145 {
146   mItems.push_back( item );
147   item->setNUMLDocument(mNUML);
148   item->setParentNUMLObject(this);
149 }
150 
151 
152 /*
153  * @return the nth item in this NUMLList items.
154  */
155 const NMBase*
get(unsigned int n) const156 NUMLList::get (unsigned int n) const
157 {
158   return (n < mItems.size()) ? mItems[n] : 0;
159 }
160 
161 
162 /*
163  * @return the nth item in this NUMLList items.
164  */
165 NMBase*
get(unsigned int n)166 NUMLList::get (unsigned int n)
167 {
168   return const_cast<NMBase*>( static_cast<const NUMLList&>(*this).get(n) );
169 }
170 
171 
172 /**
173  * Used by NUMLList::get() to lookup an NMBase based by its id.
174  */
175 //struct IdEq
176 //{
177 //  const string& id;
178 //
179 //  IdEq (const string& id) : id(id) { }
180 //  bool operator() (NMBase* sb) { return sb->getId() == id; }
181 //};
182 
183 
184 /*
185  * @return item in this NUMLList items with the given id or NULL if no such
186  * item exists.
187  */
188 //const NMBase*
189 //NUMLList::get (const std::string& sid) const
190 //{
191 //  vector<NMBase*>::const_iterator result;
192 //
193 //  result = find_if( mItems.begin(), mItems.end(), IdEq(sid) );
194 //  return (result == mItems.end()) ? 0 : *result;
195 //}
196 
197 
198 /*
199  * @return item in this NUMLList items with the given id or NULL if no such
200  * item exists.
201  */
202 //NMBase*
203 //NUMLList::get (const std::string& sid)
204 //{
205 //  return const_cast<NMBase*>( static_cast<const NUMLList&>(*this).get(sid) );
206 //}
207 
208 
209 /*
210  * Removes all items in this NUMLList object.
211  *
212  * If doDelete is true (default), all items in this NUMLList object are deleted
213  * and cleared, and thus the caller doesn't have to delete those items.
214  * Otherwise, all items are just cleared from this NUMLList object and the caller
215  * is responsible for deleting all items (In this case, pointers to all items
216  * should be stored elsewhere before calling this function by the caller).
217  */
218 void
clear(bool doDelete)219 NUMLList::clear (bool doDelete)
220 {
221   if (doDelete)
222     for_each( mItems.begin(), mItems.end(), Delete() );
223   mItems.clear();
224 }
225 
226 
227 /*
228  * Removes the nth item from this NUMLList items and returns a pointer to
229  * it.  The caller owns the returned item and is responsible for deleting
230  * it.
231  */
232 NMBase*
remove(unsigned int n)233 NUMLList::remove (unsigned int n)
234 {
235   NMBase* item = get(n);
236   if (item) mItems.erase( mItems.begin() + n );
237   return item;
238 }
239 
240 
241 /*
242  * Removes item in this NUMLList items with the given id or NULL if no such
243  * item exists.  The caller owns the returned item and is repsonsible for
244  * deleting it.
245  */
246 //NMBase*
247 //NUMLList::remove (const std::string& sid)
248 //{
249 //  NMBase* item = 0;
250 //  vector<NMBase*>::iterator result;
251 //
252 //  result = find_if( mItems.begin(), mItems.end(), IdEq(sid) );
253 //
254 //  if (result != mItems.end())
255 //  {
256 //    item = *result;
257 //    mItems.erase(result);
258 //  }
259 //
260 //  return item;
261 //}
262 //
263 
264 /*
265  * @return the number of items in this NUMLList items.
266  */
267 unsigned int
size() const268 NUMLList::size () const
269 {
270   return mItems.size();
271 }
272 
273 
274 /**
275  * Used by NUMLList::setNUMLDocument().
276  */
277 struct SetNUMLDocument
278 {
279   NUMLDocument* d;
280 
SetNUMLDocumentSetNUMLDocument281   SetNUMLDocument (NUMLDocument* d) : d(d) { }
operator ()SetNUMLDocument282   void operator() (NMBase* sbase) { sbase->setNUMLDocument(d); }
283 };
284 
285 
286 /**
287  * Used by NUMLList::setParentNUMLObject().
288  */
289 struct SetParentNUMLObject
290 {
291   NMBase* sb;
292 
SetParentNUMLObjectSetParentNUMLObject293   SetParentNUMLObject (NMBase *sb) : sb(sb) { }
operator ()SetParentNUMLObject294   void operator() (NMBase* sbase) { sbase->setParentNUMLObject(sb); }
295 };
296 
297 
298 /*
299  * Sets the parent NUMLDocument of this NUML object.
300  */
301 void
setNUMLDocument(NUMLDocument * d)302 NUMLList::setNUMLDocument (NUMLDocument* d)
303 {
304   mNUML = d;
305   for_each( mItems.begin(), mItems.end(), SetNUMLDocument(d) );
306 }
307 
308 
309 /*
310  * Sets the parent NUML object of this NUML object.
311  */
312 void
setParentNUMLObject(NMBase * sb)313 NUMLList::setParentNUMLObject (NMBase* sb)
314 {
315   mParentNUMLObject = sb;
316   for_each( mItems.begin(), mItems.end(), SetParentNUMLObject(this) );
317 }
318 
319 
320 /*
321  * @return the typecode (int) of this NUML object or NUML_UNKNOWN
322  * (default).
323  */
324 /*int
325 NUMLList::getTypeCode () const
326 {
327   return NUML_NUMLLIST;
328 }
329 */
330 
331 /*
332  * @return the typecode (int) of NUML objects contained in this NUMList or
333  * NUML_UNKNOWN (default).
334  */
335 /*int
336 NUMLList::getItemTypeCode () const
337 {
338   return NUML_UNKNOWN;
339 }*/
340 
341 
342 
343 
344 
345 /*
346  * @return the NUMLTypeCode_t of this NUML object or NUML_UNKNOWN
347  * (default).
348  */
349 NUMLTypeCode_t
getTypeCode() const350 NUMLList::getTypeCode () const
351 {
352   return NUML_NUMLLIST;
353 }
354 
355 
356 /*
357  * @return the NUMLTypeCode_t of NUML objects contained in this NUMLList or
358  * NUML_UNKNOWN (default).
359  */
360 NUMLTypeCode_t
getItemTypeCode() const361 NUMLList::getItemTypeCode () const
362 {
363   return NUML_UNKNOWN;
364 }
365 
366 
367 /*
368  * @return the name of this element ie "listOf".
369 
370  */
371 const string&
getElementName() const372 NUMLList::getElementName () const
373 {
374   static const string name = "NUMLList";
375   return name;
376 }
377 
378 
379 /**
380  * Used by NUMLList::writeElements().
381  */
382 struct Write
383 {
384   LIBSBML_CPP_NAMESPACE_QUALIFIER XMLOutputStream& stream;
385 
WriteWrite386   Write (LIBSBML_CPP_NAMESPACE_QUALIFIER XMLOutputStream& s) : stream(s) { }
operator ()Write387   void operator() (NMBase* sbrbase) { sbrbase->write(stream); }
388 };
389 
390 
391 /*
392  * Subclasses should override this method to write out their contained
393  * NUML objects as XML elements.  Be sure to call your parents
394  * implementation of this method as well.
395  */
396 void
writeElements(LIBSBML_CPP_NAMESPACE_QUALIFIER XMLOutputStream & stream) const397 NUMLList::writeElements (LIBSBML_CPP_NAMESPACE_QUALIFIER  XMLOutputStream& stream) const
398 {
399   NMBase::writeElements(stream);
400   for_each( mItems.begin(), mItems.end(), Write(stream) );
401 }
402 
403 
404 /*
405  * Subclasses should override this method to read values from the given
406  * XMLAttributes set into their specific fields.  Be sure to call your
407  * parents implementation of this method as well.
408  */
409 void
readAttributes(const LIBSBML_CPP_NAMESPACE_QUALIFIER XMLAttributes & attributes)410 NUMLList::readAttributes (const LIBSBML_CPP_NAMESPACE_QUALIFIER  XMLAttributes& attributes)
411 {
412   NMBase::readAttributes(attributes);
413 
414   //const unsigned int level   = getLevel  ();
415   //const unsigned int version = getVersion();
416 
417   std::vector<std::string> expectedAttributes;
418   expectedAttributes.clear();
419 
420     expectedAttributes.push_back("metaid");
421 
422 
423 
424   //TODO
425   // check that all attributes are expected
426 /*  for (int i = 0; i < attributes.getLength(); i++)
427   {
428     std::vector<std::string>::const_iterator end = expectedAttributes.end();
429     std::vector<std::string>::const_iterator begin = expectedAttributes.begin();
430     std::string name = attributes.getName(i);
431     if (std::find(begin, end, name) == end)
432     {
433       std::string component = "<" + getElementName() + ">";
434       logUnknownAttribute(name, level, version, component);
435     }
436   }
437 */
438 }
439 
440 void
writeAttributes(LIBSBML_CPP_NAMESPACE_QUALIFIER XMLOutputStream & stream) const441 NUMLList::writeAttributes (LIBSBML_CPP_NAMESPACE_QUALIFIER  XMLOutputStream& stream) const
442 {
443   NMBase::writeAttributes(stream);
444 
445   //const unsigned int level   = getLevel  ();
446   //const unsigned int version = getVersion();
447 
448 }
449 
450 /**
451  * Creates a new NUMLList.
452  *
453  * @return a pointer to created NUMLList.
454  */
455 LIBNUML_EXTERN
456 NUMLList_t *
NUMLList_create()457 NUMLList_create ()
458 {
459   return new(nothrow) NUMLList;
460 }
461 
462 
463 /**
464  * Frees the given NUMLList and its constituent items.
465  *
466  * This function assumes each item in the list is derived from NMBase.
467  */
468 LIBNUML_EXTERN
469 void
NUMLList_free(NUMLList_t * lo)470 NUMLList_free (NUMLList_t *lo)
471 {
472   delete lo;
473 }
474 
475 
476 /**
477  * @return a (deep) copy of this NUMLList items.
478  */
479 LIBNUML_EXTERN
480 NUMLList_t *
NUMLList_clone(const NUMLList_t * lo)481 NUMLList_clone (const NUMLList_t *lo)
482 {
483   return static_cast<NUMLList_t*>( lo->clone() );
484 }
485 
486 
487 /**
488  * Adds a copy of item to the end of this NUMLList items.
489  */
490 LIBNUML_EXTERN
491 void
NUMLList_append(NUMLList_t * lo,const NMBase * item)492 NUMLList_append (NUMLList_t *lo, const NMBase *item)
493 {
494   lo->append(item);
495 }
496 
497 
498 /**
499  * Adds the given item to the end of this NUMLList items.
500  */
501 LIBNUML_EXTERN
502 void
NUMLList_appendAndOwn(NUMLList_t * lo,NMBase_t * item)503 NUMLList_appendAndOwn (NUMLList_t *lo, NMBase_t *item)
504 {
505   lo->appendAndOwn(item);
506 }
507 
508 
509 /**
510  * Returns the nth item in this NUMLList items.
511  */
512 LIBNUML_EXTERN
513 NMBase *
NUMLList_get(NUMLList_t * lo,unsigned int n)514 NUMLList_get (NUMLList_t *lo, unsigned int n)
515 {
516   return lo->get(n);
517 }
518 
519 
520 /*
521  * @return item in this NUMLList items with the given id or NULL if no such
522  * item exists.
523  */
524 //LIBNUML_EXTERN
525 //NMBase *
526 //NUMLList_getById (NUMLList_t *lo, const char *sid)
527 //{
528 //  return (sid != NULL) ? lo->get(sid) : NULL;
529 //}
530 //
531 
532 /**
533  * Removes all items in this NUMLList object.
534  *
535  * If doDelete is true (non-zero), all items in this NUMLList object are deleted
536  * and cleared, and thus the caller doesn't have to delete those items.
537  * Otherwise (zero), all items are just cleared from this NUMLList object and the
538  * caller is responsible for deleting all items (In this case, pointers to all
539  * items should be stored elsewhere before calling this function by the caller).
540  */
541 LIBNUML_EXTERN
542 void
NUMLList_clear(NUMLList_t * lo,int doDelete)543 NUMLList_clear (NUMLList_t *lo, int doDelete)
544 {
545   lo->clear(doDelete);
546 }
547 
548 
549 /**
550  * Removes the nth item from this NUMLList items and returns a pointer to
551  * it.  The caller owns the returned item and is responsible for deleting
552  * it.
553  */
554 LIBNUML_EXTERN
555 NMBase *
NUMLList_remove(NUMLList_t * lo,unsigned int n)556 NUMLList_remove (NUMLList_t *lo, unsigned int n)
557 {
558   return lo->remove(n);
559 }
560 
561 
562 /*
563  * Removes item in this NUMLList items with the given id or NULL if no such
564  * item exists.  The caller owns the returned item and is repsonsible for
565  * deleting it.
566  */
567 //LIBNUML_EXTERN
568 //NMBase *
569 //NUMLList_removeById (NUMLList_t *lo, const char *sid)
570 //{
571 //  return (sid != NULL) ? lo->remove(sid) : NULL;
572 //}
573 
574 
575 /**
576  * Returns the number of items in this NUMLList items.
577  */
578 LIBNUML_EXTERN
579 unsigned int
NUMLList_size(const NUMLList_t * lo)580 NUMLList_size (const NUMLList_t *lo)
581 {
582   return lo->size();
583 }
584 
585 
586 /**
587  * @return the NUMLTypeCode_t of NUML objects contained in this NUMLList or
588  * NUML_UNKNOWN (default).
589  */
590 LIBNUML_EXTERN
591 NUMLTypeCode_t
NUMLList_getItemTypeCode(const NUMLList_t * lo)592 NUMLList_getItemTypeCode (const NUMLList_t *lo)
593 {
594   return lo->getItemTypeCode();
595 }
596 
597 
598 
599 
600 LIBNUML_CPP_NAMESPACE_END
601