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