1 /*****************************************************************************/
2 /*                                    XDMF                                   */
3 /*                       eXtensible Data Model and Format                    */
4 /*                                                                           */
5 /*  Id : XdmfItem.hpp                                                        */
6 /*                                                                           */
7 /*  Author:                                                                  */
8 /*     Kenneth Leiter                                                        */
9 /*     kenneth.leiter@arl.army.mil                                           */
10 /*     US Army Research Laboratory                                           */
11 /*     Aberdeen Proving Ground, MD                                           */
12 /*                                                                           */
13 /*     Copyright @ 2011 US Army Research Laboratory                          */
14 /*     All Rights Reserved                                                   */
15 /*     See Copyright.txt for details                                         */
16 /*                                                                           */
17 /*     This software is distributed WITHOUT ANY WARRANTY; without            */
18 /*     even the implied warranty of MERCHANTABILITY or FITNESS               */
19 /*     FOR A PARTICULAR PURPOSE.  See the above copyright notice             */
20 /*     for more information.                                                 */
21 /*                                                                           */
22 /*****************************************************************************/
23 
24 #ifndef XDMFITEM_HPP_
25 #define XDMFITEM_HPP_
26 
27 // C Compatible Includes
28 #include "XdmfCore.hpp"
29 #include "XdmfVisitor.hpp"
30 
31 #ifdef __cplusplus
32 
33 // Forward Declarations
34 class XdmfCoreReader;
35 class XdmfInformation;
36 class XdmfVisitor;
37 
38 // Includes
39 #include <loki/Visitor.h>
40 #define vtk_libxml2_reference reference // Reversing VTK name mangling
41 #include <libxml/xmlexports.h>
42 #include <libxml/tree.h>
43 #include <libxml/uri.h>
44 #include <libxml/xpointer.h>
45 #include <libxml/xmlreader.h>
46 #include <map>
47 #include <set>
48 #include <string>
49 #include <vector>
50 #include "XdmfSharedPtr.hpp"
51 
52 
53 // Macro that allows children XdmfItems to be attached to a parent XdmfItem.
54 // -- For Header File
55 #define XDMF_CHILDREN(ParentClass, ChildClass, ChildName, SearchName)         \
56                                                                               \
57 public:                                                                       \
58                                                                               \
59   /** Get a ChildClass attached to this item by index.<br>
60       Example of use:<br>
61       C++<br>
62       //Assume that exampleItem is a shared pointer to the ParentClass object<br>
63       //Using an XdmfInformation as an example because all XdmfItems have XdmfInformation as a child class<br>
64       unsigned int getIndex = 0;<br>
65       shared_ptr<XdmfInformation> exampleChild = exampleItem->getInformation(getIndex);<br>
66       Python<br>
67       '''<br>
68       Assume that exampleItem is a shared pointer to the ParentClass object<br>
69       Using an XdmfInformation as an example because all XdmfItems have XdmfInformation as a child class<br>
70       '''<br>
71       getIndex = 0<br>
72       exampleChild = exampleItem.getInformation(getIndex)<br>
73       @return requested ChildClass. If no ChildClass##s exist at the index,
74       a NULL pointer is returned.
75   */                                                                          \
76   virtual shared_ptr<ChildClass>                                              \
77   get##ChildName(const unsigned int index);                                   \
78                                                                               \
79   /** Get a ChildClass attached to this item by index (const version).<br>
80       Example of use:<br>
81       C++<br>
82       //Assume that exampleItem is a shared pointer to the ParentClass object<br>
83       //Using an XdmfInformation as an example because all XdmfItems have XdmfInformation as a child class<br>
84       unsigned int getIndex = 0;<br>
85       shared_ptr<const XdmfInformation> exampleChildConst = exampleItem->getInformation(getIndex);<br>
86       Python: does not support a constant version of this function
87       @param index of the ChildClass to retrieve.
88       @return requested ChildClass. If no ChildClass##s exist at the index, a
89       NULL pointer is returned.
90   */                                                                          \
91   virtual shared_ptr<const ChildClass>                                        \
92   get##ChildName(const unsigned int index) const;                             \
93                                                                               \
94   /** Get a ChildClass attached to this item by SearchName.<br>
95       Example of use:<br>
96       C++<br>
97       //Assume that exampleItem is a shared pointer to the ParentClass object<br>
98       //Using an XdmfInformation as an example because all XdmfItems have XdmfInformation as a child class<br>
99       std::string findingInfo = "Find this";<br>
100       shared_ptr<XdmfInformation> exampleStringChild = exampleItem->getInformation(findingInfo);<br>
101       Python<br>
102       '''<br>
103       Assume that exampleItem is a shared pointer to the ParentClass object<br>
104       Using an XdmfInformation as an example because all XdmfItems have XdmfInformation as a child class<br>
105       '''<br>
106       findingInfo = "Find this"<br>
107       exampleStringChild = exampleItem.getInformation(findingInfo)<br>
108       @param SearchName of the ChildClass to retrieve.
109       @return requested ChildClass. If no ChildClass##s are found with the
110       correct SearchName, a NULL pointer is returned.
111   */                                                                          \
112   virtual shared_ptr<ChildClass>                                              \
113   get##ChildName(const std::string & SearchName);                             \
114                                                                               \
115   /** Get a ChildClass attached to this item by SearchName (const version).<br>
116       Example of use:<br>
117       C++<br>
118       //Assume that exampleItem is a shared pointer to the ParentClass object<br>
119       //Using an XdmfInformation as an example because all XdmfItems have XdmfInformation as a child class<br>
120       std::string findingInfo = "Find this";<br>
121       shared_ptr<const XdmfInformation> exampleStringChildConst = exampleItem->getInformation(findingInfo);<br>
122       Python: does not support a constant version of this function
123       @param SearchName of the ChildClass to retrieve.
124       @return requested ChildClass  If no ChildClass##s are found with the
125       correct SearchName, a NULL pointer is returned.
126   */                                                                          \
127   virtual shared_ptr<const ChildClass>                                        \
128   get##ChildName(const std::string & SearchName) const;                       \
129                                                                               \
130   /** Get the number of ChildClass##s attached to this item.<br>
131       Example of use:<br>
132       C++<br>
133       //Assume that exampleItem is a shared pointer to the ParentClass object<br>
134       //Using an XdmfInformation as an example because all XdmfItems have XdmfInformation as a child class<br>
135       unsigned int exampleSize = exampleItem->getNumberInformations();<br>
136       Python<br>
137       '''<br>
138       Assume that exampleItem is a shared pointer to the ParentClass object<br>
139       Using an XdmfInformation as an example because all XdmfItems have XdmfInformation as a child class<br>
140       '''<br>
141       exampleSize = exampleItem.getNumberInformations()<br>
142       @return number of ChildClass##s attached to this item.
143   */                                                                          \
144   virtual unsigned int getNumber##ChildName##s() const;                       \
145                                                                               \
146   /** Insert a ChildClass into to this item.<br>
147       Example of use:<br>
148       C++<br>
149       shared_ptr<XdmfInformation> exampleItem = XdmfInformation::New("Parent", "This is a parent information");<br>
150       shared_ptr<XdmfInformation> addChild = XdmfInformation::New("Child", "This is a child information");<br>
151       exampleItem->insert(addChild);<br>
152       Python<br>
153       exampleItem = XdmfInformation.New("Parent", "This is a parent information")<br>
154       addChild = XdmfInformation.New("Child", "This is a child information")<br>
155       exampleItem.insert(addChild)<br>
156       @param ChildName to attach to this item.
157   */                                                                          \
158   virtual void insert(const shared_ptr<ChildClass> ChildName);                \
159                                                                               \
160   /** Remove a ChildClass from this item by index. If no object exists
161       at the index, nothing is removed.<br>
162       Example of use:<br>
163       C++<br>
164       //Assume that exampleItem is a shared pointer to the ParentClass object<br>
165       //Using an XdmfInformation as an example because all XdmfItems have XdmfInformation as a child class<br>
166       unsigned int removeIndex = 0;<br>
167       exampleItem->removeInformation(removeIndex);<br>
168       Python<br>
169       '''<br>
170       Assume that exampleItem is a shared pointer to the ParentClass object<br>
171       Using an XdmfInformation as an example because all XdmfItems have XdmfInformation as a child class<br>
172       '''<br>
173       removeIndex = 0<br>
174       exampleItem.removeInformation(removeIndex)
175       @param index of the ChildClass to remove.
176   */                                                                          \
177   virtual void remove##ChildName(const unsigned int index);                   \
178                                                                               \
179   /** Remove a ChildClass from this item by SearchName. If no ChildClass##s
180       have the correct SearchName, nothing is removed.<br>
181       Example of use:<br>
182       C++<br>
183       //Assume that exampleItem is a shared pointer to the ParentClass object<br>
184       //Using an XdmfInformation as an example because all XdmfItems have XdmfInformation as a child class<br>
185       std::string removeInfo = "Remove this";<br>
186       exampleItem->removeInformation(removeInfo);<br>
187       Python<br>
188       '''<br>
189       Assume that exampleItem is a shared pointer to the ParentClass object<br>
190       Using an XdmfInformation as an example because all XdmfItems have XdmfInformation as a child class<br>
191       '''<br>
192       removeInfo = "Remove this"<br>
193       exampleItem.removeInformation(removeInfo)<br>
194       @param SearchName of the ChildClass to remove.
195   */                                                                          \
196   virtual void remove##ChildName(const std::string & SearchName);             \
197                                                                               \
198 protected :                                                                   \
199                                                                               \
200   std::vector<shared_ptr<ChildClass> > m##ChildName##s;                       \
201                                                                               \
202 public :
203 
204 // Macro that allows children XdmfItems to be attached to a parent XdmfItem.
205 // -- For Implementation File
206 #define XDMF_CHILDREN_IMPLEMENTATION(ParentClass,                             \
207                                      ChildClass,                              \
208                                      ChildName,                               \
209                                      SearchName)                              \
210                                                                               \
211   shared_ptr<ChildClass>                                                      \
212   ParentClass::get##ChildName(const unsigned int index)                       \
213   {                                                                           \
214     return boost::const_pointer_cast<ChildClass>                              \
215       (static_cast<const ParentClass &>(*this).get##ChildName(index));        \
216   }                                                                           \
217                                                                               \
218   shared_ptr<const ChildClass>                                                \
219   ParentClass::get##ChildName(const unsigned int index) const                 \
220   {                                                                           \
221     if(index < m##ChildName##s.size()) {                                      \
222       return m##ChildName##s[index];                                          \
223     }                                                                         \
224     return shared_ptr<ChildClass>();                                          \
225   }                                                                           \
226                                                                               \
227   shared_ptr<ChildClass>                                                      \
228   ParentClass::get##ChildName(const std::string & SearchName)                 \
229   {                                                                           \
230     return boost::const_pointer_cast<ChildClass>                              \
231       (static_cast<const ParentClass &>(*this).get##ChildName(SearchName));   \
232   }                                                                           \
233                                                                               \
234   shared_ptr<const ChildClass>                                                \
235   ParentClass::get##ChildName(const std::string & SearchName) const           \
236   {                                                                           \
237     for(std::vector<shared_ptr<ChildClass> >::const_iterator iter =           \
238           m##ChildName##s.begin();                                            \
239         iter != m##ChildName##s.end();                                        \
240         ++iter) {                                                             \
241       if((*iter)->get##SearchName().compare(SearchName) == 0) {               \
242         return *iter;                                                         \
243       }                                                                       \
244     }                                                                         \
245     return shared_ptr<ChildClass>();                                          \
246   }                                                                           \
247                                                                               \
248   unsigned int                                                                \
249   ParentClass::getNumber##ChildName##s() const                                \
250   {                                                                           \
251     return m##ChildName##s.size();                                            \
252   }                                                                           \
253                                                                               \
254   void                                                                        \
255   ParentClass::insert(const shared_ptr<ChildClass> ChildName)                 \
256   {                                                                           \
257     m##ChildName##s.push_back(ChildName);                                     \
258     this->setIsChanged(true);                                                 \
259   }                                                                           \
260                                                                               \
261   void                                                                        \
262   ParentClass::remove##ChildName(const unsigned int index)                    \
263   {                                                                           \
264     if(index < m##ChildName##s.size()) {                                      \
265       m##ChildName##s.erase(m##ChildName##s.begin() + index);                 \
266     }                                                                         \
267     this->setIsChanged(true);                                                 \
268   }                                                                           \
269                                                                               \
270   void                                                                        \
271   ParentClass::remove##ChildName(const std::string & SearchName)              \
272   {                                                                           \
273     for(std::vector<shared_ptr<ChildClass> >::iterator iter =                 \
274           m##ChildName##s.begin();                                            \
275         iter != m##ChildName##s.end();                                        \
276         ++iter) {                                                             \
277         if((*iter)->get##SearchName().compare(SearchName) == 0) {             \
278           m##ChildName##s.erase(iter);                                        \
279           return;                                                             \
280         }                                                                     \
281     }                                                                         \
282     this->setIsChanged(true);                                                 \
283   }
284 
285 /**
286  * @brief Base class of any object that is able to be added to an Xdmf
287  * structure.
288  *
289  * XdmfItem is an abstract base class. An XdmfItem is a structure that
290  * can be visited and traversed by an XdmfVisitor and have its
291  * contents written to an Xdmf file.
292  */
293 
294 class XDMFCORE_EXPORT XdmfItem : public Loki::BaseVisitable<void> {
295 
296 public:
297 
298   virtual ~XdmfItem() = 0;
299 
300   LOKI_DEFINE_VISITABLE_BASE()
301   XDMF_CHILDREN(XdmfItem, XdmfInformation, Information, Key)
302   friend class XdmfCoreReader;
303   friend class XdmfWriter;
304   friend class XdmfHeavyDataWriter;
305   friend class XdmfHDF5Writer;
306 
307   /**
308    * Get the tag for this item.  This is equivalent to tags in XML
309    * parlance.
310    *
311    * Example of use:
312    *
313    * C++
314    *
315    * @dontinclude ExampleXdmfItem.cpp
316    * @skipline //#initialization
317    * @until //#initialization
318    * @skipline //#getItemTag
319    * @until //#getItemTag
320    *
321    * Python
322    *
323    * @dontinclude XdmfExampleItem.py
324    * @skipline #//initialization
325    * @until #//initialization
326    * @skipline #//getItemTag
327    * @until #//getItemTag
328    *
329    * @return    The tag for this XdmfItem.
330    */
331   virtual std::string getItemTag() const = 0;
332 
333   /**
334    * Get the key/value property pairs for this item. These are
335    * equivalent to attributes in XML parlance.
336    *
337    * Example of use:
338    *
339    * C++
340    *
341    * @dontinclude ExampleXdmfItem.cpp
342    * @skipline //#initialization
343    * @until //#initialization
344    * @skipline //#getItemProperties
345    * @until //#getItemProperties
346    *
347    * Python
348    *
349    * @dontinclude XdmfExampleItem.py
350    * @skipline #//initialization
351    * @until #//initialization
352    * @skipline #//getItemProperties
353    * @until #//getItemProperties
354    *
355    * @return    A map of key/value properties associated with this XdmfItem.
356    */
357   virtual std::map<std::string, std::string> getItemProperties() const = 0;
358 
359   /**
360    * Traverse this item by passing the visitor to child items.
361    *
362    * Example of use:
363    *
364    * C++
365    *
366    * @dontinclude ExampleXdmfItem.cpp
367    * @skipline //#initialization
368    * @until //#initialization
369    * @skipline //#traverse
370    * @until //#traverse
371    *
372    * Python
373    *
374    * @dontinclude XdmfExampleItem.py
375    * @skipline #//initialization
376    * @until #//initialization
377    * @skipline #//traverse
378    * @until #//traverse
379    *
380    * @param     visitor         The visitor to pass to child items.
381    */
382   virtual void traverse(const shared_ptr<XdmfBaseVisitor> visitor);
383 
384   XdmfItem(const XdmfItem &);
385 
386 protected:
387 
388   XdmfItem();
389 
390   /**
391    * Populates an item using a map of key/value property pairs and a
392    * vector of its child items. This is used to support generic
393    * reading of XdmfItems from disk.
394    *
395    * @param itemProperties a map of key/value properties associated with
396    * this item.
397    * @param childItems a vector of child items to be added to this item.
398    * @param reader the current XdmfCoreReader being used to populate Xdmf
399    * structures.
400    */
401   virtual void
402   populateItem(const std::map<std::string, std::string> & itemProperties,
403                const std::vector<shared_ptr<XdmfItem > > & childItems,
404                const XdmfCoreReader * const reader);
405 
406   bool
407   getIsChanged();
408 
409   void
410   setIsChanged(bool status);
411 
412   std::set<XdmfItem *> mParents;
413 
414   bool mIsChanged;
415 
416 private:
417 
418 //  XdmfItem(const XdmfItem &);  // It is implemented for C wrappers.
419   void operator=(const XdmfItem &);  // Not implemented.
420 
421 };
422 
423 #endif
424 
425 #ifdef __cplusplus
426 extern "C" {
427 #endif
428 
429 // C wrappers go here
430 
431 struct XDMFITEM; // Simply as a typedef to ensure correct typing
432 typedef struct XDMFITEM XDMFITEM;
433 
434 #ifndef XDMFINFORMATIONCDEFINE
435 #define XDMFINFORMATIONCDEFINE
436 struct XDMFINFORMATION; // Simply as a typedef to ensure correct typing
437 typedef struct XDMFINFORMATION XDMFINFORMATION;
438 #endif
439 
440 XDMFCORE_EXPORT void XdmfItemAccept(XDMFITEM * item, XDMFVISITOR * visitor, int * status);
441 
442 XDMFCORE_EXPORT void XdmfItemFree(void * item);
443 
444 XDMFCORE_EXPORT XDMFINFORMATION * XdmfItemGetInformation(XDMFITEM * item, unsigned int index);
445 
446 XDMFCORE_EXPORT XDMFINFORMATION * XdmfItemGetInformationByKey(XDMFITEM * item, char * key);
447 
448 XDMFCORE_EXPORT unsigned int XdmfItemGetNumberInformations(XDMFITEM * item);
449 
450 XDMFCORE_EXPORT void XdmfItemInsertInformation(XDMFITEM * item, XDMFINFORMATION * information, int passControl);
451 
452 XDMFCORE_EXPORT void XdmfItemRemoveInformation(XDMFITEM * item, unsigned int index);
453 
454 XDMFCORE_EXPORT void XdmfItemRemoveInformationByKey(XDMFITEM * item, char * key);
455 
456 XDMFCORE_EXPORT char * XdmfItemGetItemTag(XDMFITEM * item);
457 
458 #define XDMF_ITEM_C_CHILD_DECLARE(ClassName, CClassName, Level)                                                       \
459                                                                                                                       \
460 Level##_EXPORT void ClassName##Accept ( CClassName * item, XDMFVISITOR * visitor, int * status);                      \
461 Level##_EXPORT CClassName * ClassName##Cast ( XDMFITEM * item);                                                       \
462 Level##_EXPORT void ClassName##Free(void * item);                                                                    \
463 Level##_EXPORT XDMFINFORMATION * ClassName##GetInformation( CClassName * item, unsigned int index);                   \
464 Level##_EXPORT XDMFINFORMATION * ClassName##GetInformationByKey( CClassName * item, char * key);                      \
465 Level##_EXPORT unsigned int ClassName##GetNumberInformations( CClassName * item);                                     \
466 Level##_EXPORT void ClassName##InsertInformation( CClassName * item, XDMFINFORMATION * information, int passControl); \
467 Level##_EXPORT void ClassName##RemoveInformation( CClassName * item, unsigned int index);                             \
468 Level##_EXPORT void ClassName##RemoveInformationByKey( CClassName * item, char * key);                                \
469 Level##_EXPORT char * ClassName##GetItemTag( CClassName * item);
470 
471 
472 #define XDMF_ITEM_C_CHILD_WRAPPER(ClassName, CClassName)                                                    \
473 void ClassName##Accept( CClassName * item, XDMFVISITOR * visitor, int * status)                             \
474 {                                                                                                           \
475   XdmfItemAccept(((XDMFITEM *)item), visitor, status);                                                      \
476 }                                                                                                           \
477                                                                                                             \
478 void ClassName##Free(void * item)                                                                           \
479 {                                                                                                           \
480   XdmfItemFree(item);                                                                                       \
481 }                                                                                                           \
482                                                                                                             \
483 XDMFINFORMATION * ClassName##GetInformation( CClassName * item, unsigned int index)                         \
484 {                                                                                                           \
485   return XdmfItemGetInformation(((XDMFITEM *)item), index);                                                 \
486 }                                                                                                           \
487                                                                                                             \
488 XDMFINFORMATION * ClassName##GetInformationByKey( CClassName * item, char * key)                            \
489 {                                                                                                           \
490   return XdmfItemGetInformationByKey(((XDMFITEM *)item), key);                                              \
491 }                                                                                                           \
492                                                                                                             \
493 unsigned int ClassName##GetNumberInformations( CClassName * item)                                           \
494 {                                                                                                           \
495   return XdmfItemGetNumberInformations(((XDMFITEM *)item));                                                 \
496 }                                                                                                           \
497                                                                                                             \
498 void ClassName##InsertInformation( CClassName * item, XDMFINFORMATION * information, int passControl)       \
499 {                                                                                                           \
500   XdmfItemInsertInformation(((XDMFITEM *)item), information, passControl);                                  \
501 }                                                                                                           \
502                                                                                                             \
503 void ClassName##RemoveInformation( CClassName * item, unsigned int index)                                   \
504 {                                                                                                           \
505   XdmfItemRemoveInformation(((XDMFITEM *)item), index);                                                     \
506 }                                                                                                           \
507                                                                                                             \
508 void ClassName##RemoveInformationByKey( CClassName * item, char * key)                                      \
509 {                                                                                                           \
510   XdmfItemRemoveInformationByKey(((XDMFITEM *)item), key);                                                  \
511 }                                                                                                           \
512                                                                                                             \
513 char * ClassName##GetItemTag( CClassName * item)                                                            \
514 {                                                                                                           \
515   return XdmfItemGetItemTag(((XDMFITEM *)item));                                                            \
516 }
517 
518 #ifdef __cplusplus
519 }
520 #endif
521 
522 #endif /* XDMFITEM_HPP_ */
523