Main Page   Namespace List   Class Hierarchy   Compound List   File List   Compound Members   File Members  

Persistence.h

Go to the documentation of this file.
00001 // $Id: Persistence.h,v 1.8 2001/01/26 20:57:14 jrb Exp $
00002 // Implementation of the persistence design pattern
00003 
00004 #ifndef XMLPERSISTENCE_H
00005 #define XMLPERSISTENCE_H
00006 
00007 
00008 // #include "xml/Element.h"
00009 #include "facilities/error.h" // for FATAL
00010 #include <dom/DOM_Element.hpp>
00011 #include "xml/Dom.h"
00012 #include <string>
00013 #include <iostream>
00014 #include <iterator>
00015 #include <vector>
00016 #include <map>
00017 
00018 
00019 // PersistentObject - class declaration
00020 
00021 /* The base class supports XML persistence (std::ostream persistence
00022 removed as of September, 2000). Other
00023 types of persistence may be implemented by declaring other static
00024 createPersistence( _Persistence ) methods, where _Persistence
00025 represents the data type being used. Then, a container defined with a
00026 value_type parameter of only those subclasses is defined and a
00027 persist_iterator< _Container, _Persistence > is declared. This can
00028 then be used to assign classes from the _Persistence type into the
00029 container. Note that the new 'base persistence class' in this scheme
00030 (whatever defines the new persistence type) must write and read ALL
00031 persistence information.  */
00032 
00033 class DOM_Element;
00034 
00035 namespace xml {
00036   class PersistentObject {      // implements a set of persistent objects.
00037   public:
00038     // type declarations
00039     typedef     std::string     _PersistKey;
00040     class _Factory {
00041     public:
00042       virtual PersistentObject* create(const DOM_Element&);
00043     };
00044     
00045     // ctor
00046     PersistentObject() {}
00047     
00048     // public access to persistence
00049     static PersistentObject* createPersistence (const DOM_Element&);
00050     
00051     static bool addPersistence(const _PersistKey&, 
00052                                class PersistentObject::_Factory* );
00053     
00054     static void killPersistence ();
00055     
00056     // equality
00057     bool operator==(const PersistentObject&) { return true; }
00058     
00059     // persist - write persistence information to a persistence stream
00060     // BY DEFINITION: calling createPersistence with an istream at the
00061     // same position as called for persist will instantiate an copy of 
00062     // this object
00063     
00064     virtual DOM_Element persist(DOM_Element& parent) const;
00065     
00066   protected:    
00067     
00068     PersistentObject(DOM_Element&);                     
00069     
00070     // subclasses must define a persistence key as a unique ID
00071     virtual const _PersistKey&  persistKey() const = 0;
00072     
00073     // friends
00074     friend class PersistentObject::_Factory;
00075     
00076   private:
00077     static std::map<_PersistKey, class _Factory*>*      s_persist_table;
00078   };
00079   
00080   // PersistentContainter<_Cont> - wraps any container which provides 
00081   // begin, end, size to persistence
00082   //    !! it is important to note that PersistentContainers are not 
00083   //    !! incorporated  into the overall PersistentObject
00084   //    !! hierarchy - they are not inserted into any PersistentObject 
00085   //    !! scheme other than that they provide generic persist( )
00086   //    !! methods and persistence constructors. The value_type of the 
00087   //    !!  container must also be a PersistentObject
00088   //    !! or at least supply a persist method.
00089   
00090   template <class _Cont> class PersistentContainer {    
00091   public:
00092     // constructors
00093     PersistentContainer() {} // default
00094     
00095     PersistentContainer(const DOM_Element&);
00096     // destructor
00097     virtual ~PersistentContainer() {}
00098     // type declarations/synonyms       
00099     typedef     _Cont    container;
00100     typedef typename container::iterator                iterator;
00101     typedef     typename container::const_iterator      const_iterator;
00102     typedef typename container::reverse_iterator    reverse_iterator;
00103     typedef typename container::const_reverse_iterator const_reverse_iterator;
00104     typedef typename container::value_type              value_type;
00105     
00106     // access to container
00107     iterator            begin () { return m_container.begin(); }
00108     iterator            end () { return m_container.end(); }
00109     const_iterator      begin () const { return m_container.begin(); }
00110     const_iterator      end () const { return m_container.end(); }
00111     reverse_iterator        rbegin () { return m_container.rbegin(); }
00112     reverse_iterator        rend () { return m_container.rend(); }
00113     const_reverse_iterator  rbegin () const { return m_container.rbegin(); }
00114     const_reverse_iterator  rend () const { return m_container.rend(); }
00115     container&  operator() (void) { return m_container; }
00116     const container& operator() (void) const { return m_container; }
00117     unsigned int        size () const { return m_container.size(); }
00118     bool                empty () const { return m_container.empty(); }
00119     
00120     // public methods
00121     iterator insert ( iterator& i, value_type& v ) 
00122       { return m_container.insert(i,v); }
00123     
00126     void           load (const DOM_Element&);
00127     
00128     
00131     virtual void persist(DOM_Element& parent) const;
00132     
00133   protected:
00134     
00135   private:
00136         container       m_container;
00137   };
00138   
00139   // persist_iterator - used to make persistence construction generic
00140   // _Iterator should be an input_iterator into some container, _Persistence
00141   // is a valid persistence data type
00142   template <class _Iterator, class _Persistence>
00143     class persist_iterator {
00144     public:
00145     // type declarations
00146     typedef _Iterator iterator;
00147     typedef typename iterator::value_type       value_type;
00148     typedef _Persistence persistence;
00149     
00150     explicit persist_iterator ( iterator& it );
00151     
00152     persist_iterator&   operator=(persistence& p);
00153     
00154     persist_iterator&   operator* ();
00155     persist_iterator&   operator++ ();
00156     persist_iterator&   operator ++ (int);
00157     
00158     private:
00159     iterator&   m_iter;
00160   };
00161   
00162   // PersistentObject inline implementation
00163   
00164   // createPersistence
00165   // - creates a persistent object (+ children) from an XML element
00166     inline PersistentObject*
00167     PersistentObject::createPersistence(const DOM_Element& elem) {
00168       std::string temp_string(Dom::transToChar(elem.getTagName()));
00169      _PersistKey key(temp_string);
00170     if (!s_persist_table) FATAL("Persistence information not initialized.");
00171     
00172     
00173     std::map<_PersistKey, _Factory*>::iterator mit =
00174       s_persist_table->find(key); 
00175     
00176     if (mit != s_persist_table->end()) {
00177       return (*mit).second->create(elem);
00178     }
00179     else   return 0;
00180   }
00181   
00182   
00183   // killPersistence
00184   // - deletes all of the PersistenceKey-factory pairs
00185   inline void PersistentObject::killPersistence() {
00186     if (!s_persist_table) return;
00187     for (std::map<_PersistKey, _Factory*>::iterator it = 
00188            s_persist_table->begin(); it != s_persist_table->end();   ++it) {
00189       delete (*it).second;
00190     }
00191   }
00192   
00193   // PersistentContainer - inline implementations
00194   template <class _Cont>
00195     inline void PersistentContainer<_Cont>::persist(DOM_Element& parent) const
00196     {
00197       // note that this occurs in reverse order such that
00198       // the contents are read back in in the same order... 
00199       for (const_reverse_iterator it = rbegin(); it != rend(); ++it) {
00200         (*it)->persist(parent);    
00201       }
00202     }
00203   
00204   template <class _Cont>
00205     inline void PersistentContainer<_Cont>::load(const DOM_Element& elem) {
00206     DOM_NodeList children = elem.getChildNodes();
00207     int          len = children.getLength();
00208     int          iChild;
00209     iterator     thisIt = begin();
00210     
00211     for (iChild = 0; iChild < len; iChild++) {
00212       if (children.item(iChild).getNodeType() == DOM_Node::ELEMENT_NODE) {
00213         DOM_Node    child_tmp = children.item(iChild);
00214         DOM_Element child = DOM_Element(static_cast<DOM_Element&>(child_tmp));
00215         // value_type is, e.g. GlastDetector* 
00216         value_type newObj = 
00217           static_cast<value_type> (PersistentObject::createPersistence(child));
00218         if (newObj) thisIt = insert(thisIt, newObj);
00219       }
00220     }
00221   }
00222   
00223   // persist_iterator implementation
00224   template <class _Iterator, class _Persistence>
00225     inline persist_iterator<_Iterator, _Persistence>::persist_iterator 
00226     (persist_iterator<_Iterator, _Persistence>::iterator& it)
00227     : m_iter(it) {}
00228   
00229   template <class _Iterator, class _Persistence>
00230     inline persist_iterator<_Iterator, _Persistence>&
00231     persist_iterator<_Iterator, _Persistence>::operator=
00232     (persist_iterator<_Iterator, _Persistence>::persistence& p) {
00233       value_type* o = value_type::createPersistence(p);
00234       if (o != 0) {
00235         *m_iter = o;
00236         ++m_iter;
00237       }
00238       return *this;
00239     }
00240   
00241   template <class _Iterator, class _Persistence>
00242     inline persist_iterator<_Iterator, _Persistence>&
00243     persist_iterator<_Iterator, _Persistence>::operator* () {
00244     return *this;
00245   }
00246   
00247   template <class _Iterator, class _Persistence>
00248     inline persist_iterator<_Iterator, _Persistence>&
00249     persist_iterator<_Iterator, _Persistence>::operator++ () {
00250     return *this;
00251   }
00252   
00253   template <class _Iterator, class _Persistence>
00254     inline persist_iterator<_Iterator, _Persistence>&
00255     persist_iterator<_Iterator, _Persistence>::operator++ (int) {
00256     return *this;
00257   }
00258 }         // end namespace xml
00259 #endif  // _H_PERSISTENCEHEADER

Generated at Wed Nov 21 12:22:26 2001 by doxygen1.2.3 written by Dimitri van Heesch, © 1997-2000