Print

Print


Commit in lcio on MAIN
doc/versions.readme+5-11.52 -> 1.53
src/aid/EVENT/LCObject.aid+11.11 -> 1.12
src/cpp/include/LCRTRelations.h+466-3831.6 -> 1.7
               /lcio.h+9-11.25 -> 1.26
src/cpp/src/EXAMPLE/lcrtrelation.cc+240-481.2 -> 1.3
                   /recjob.cc+1-11.50 -> 1.51
+722-434
6 modified files
updated doc for runtime relations, put classes in namespace lcrtrel, created examples (lcrtrelation.cc)

lcio/doc
versions.readme 1.52 -> 1.53
diff -u -r1.52 -r1.53
--- versions.readme	13 Nov 2006 17:21:18 -0000	1.52
+++ versions.readme	1 Dec 2006 14:10:08 -0000	1.53
@@ -8,13 +8,17 @@
 
   - fixed bug with BitField64/CellIdDecoder
 
+  - introduced C++ runtime (user) extensions and relations
+    see LCRTRelation and lcrtrelation.cc for documentation and examples
+
 =====================
 v01-08-vtx               BETA-NON-PRODUCTION-RELEASE !!!!  
 =====================
 
    - test implementation new  of Vertex class 
 
-   - modified function UTIL:LCTOOLS:dumpEvent() for a more readable format 
+   - modified function UTIL:LCTOOLS:dumpEvent() for a more readable format
+     used e.g. in anajob.cc 
 
    - bug fixes:
 	+ in SIOReader::skipNEvents() (skipped only n-1 with readStream())

lcio/src/aid/EVENT
LCObject.aid 1.11 -> 1.12
diff -u -r1.11 -r1.12
--- LCObject.aid	27 Nov 2006 09:57:42 -0000	1.11
+++ LCObject.aid	1 Dec 2006 14:10:09 -0000	1.12
@@ -12,6 +12,7 @@
 class LCObject ;
 /**Vector of (pointers to) LCObjects.*/
 typedef std::vector<LCObject*> LCObjectVec ;
+using namespace lcrtrel ;
 }
 @endif
 

lcio/src/cpp/include
LCRTRelations.h 1.6 -> 1.7
diff -u -r1.6 -r1.7
--- LCRTRelations.h	30 Nov 2006 14:03:42 -0000	1.6
+++ LCRTRelations.h	1 Dec 2006 14:10:09 -0000	1.7
@@ -6,546 +6,629 @@
 #include <list>
 #include <map>
 
+namespace lcrtrel_helper{
 
+  //------------------ internal helper typdefs, function and classes ----------
 
-//------------------ internal helper typdefs, function and classes ----------
+  /** Function pointer for delete function */
+  typedef void (*DeleteFPtr)(void*) ;
 
-/** Function pointer for delete function */
-typedef void (*DeleteFPtr)(void*) ;
+  /** Simple init function for simple pointers */
+  struct SimplePtrInit{ static void* init() { return 0 ; } } ;
 
-/** Simple init function for simple pointers */
-struct SimplePtrInit{ static void* init() { return 0 ; } } ;
+  /** Empty delete function for pointers w/o ownership */
+  struct NoDelete{ static void clean(void *v) { /* no_op */ } } ;
 
-/** Empty delete function for pointers w/o ownership */
-struct NoDelete{ static void clean(void *v) { /* no_op */ } } ;
+  /** Factory for objects of type  T*/
+  template <class T>
+  struct CreationPtrInit{ static void* init() { return new T ; } } ;
 
-/** Factory for objects of type  T*/
-template <class T>
-struct CreationPtrInit{ static void* init() { return new T ; } } ;
+  /** Delete function for pointers w/ ownership.*/
+  template <class T>
+  struct DeletePtr{ static void clean(void *v) { delete (T*) v ; } } ;
 
-/** Delete function for pointers w/ ownership.*/
-template <class T>
-struct DeletePtr{ static void clean(void *v) { delete (T*) v ; } } ;
 
+  /** Delete function for containers of owned objects */
+  template <class T>
+  struct DeleteElements{
 
-/** Delete function for containers of owned objects */
-template <class T>
-struct DeleteElements{
+    static void clean(void *v) { 
+      T* vec = static_cast<T*>(v) ;
+      for( typename T::iterator it = vec->begin();it != vec->end(); ++it){
+	delete *it ;
+      }
+      delete vec  ;    
+    } 
+  };
 
-  static void clean(void *v) { 
-    T* vec = static_cast<T*>(v) ;
-    for( typename T::iterator it = vec->begin();it != vec->end(); ++it){
-      delete *it ;
-    }
-    delete vec  ;    
-  } 
-};
 
+  /** Map of pointers to extension obbjects*/
+  typedef std::map< unsigned , void * > PtrMap ;
 
-// typedef std::map< DeleteFPtr , void * > PtrMap ;
+  /** Vector of delete  functions */
+  typedef std::vector< DeleteFPtr > DPtrVec ;
 
-/** Vector of delete  functions */
-typedef std::vector< DeleteFPtr > DPtrVec ;
+  /** Vector of pointers to extension obbjects*/
+  //typedef std::vector< void * > PtrVec ;
 
-/** Vector of pointers to extension obbjects*/
-typedef std::vector< void * > PtrVec ;
 
-
-template <class U, class T , class I, class D, bool b>
-struct LCBaseTraits{
+  /** Base class for all extensions and relations */
+  template <class U, class T , class I, class D, bool b>
+  struct LCBaseTraits{
   
-  typedef T*  ptr ;  // base pointer type 
-  typedef U tag ;    // this ensures that a new class instance is created for every user extension
+    typedef T*  ptr ;  /**<base pointer type  */
+    typedef U tag ;    // this ensures that a new class instance is created for every user extension
   
-  static const int allowed_to_call_ext = b ;
+    static const int allowed_to_call_ext = b ;
   
-  static void clean(void *v) {
-    D::clean( v ) ;
-  }
-  static ptr init() {
-    return (ptr) I::init() ;
-  }
-  static DeleteFPtr deletePtr() { return  &clean ; }  ;
-};
-
-
-template <class U, class T , class I=SimplePtrInit, class D=NoDelete , bool b=1>
-struct LCBaseLinkTraits : public LCBaseTraits<U,T,I,D,b>{
-
-  typedef LCBaseTraits<U,T,I,D,b> base ;
+    static void clean(void *v) {
+      D::clean( v ) ;
+    }
+    static ptr init() {
+      return (ptr) I::init() ;
+    }
+    static DeleteFPtr deletePtr() { return  &clean ; }  ;
+  };
 
-  typedef T*& ext_type ;                 // return value of  ext<>()
-  typedef T*  rel_type ;                 // return value of  rel<>() 
-  typedef typename base::ptr obj_ptr ;   // pointer to object
 
-  static const bool is_container=false ;
-};
+  /** Base class for all extensions and relations of single objects */
+  template <class U, class T , class I=SimplePtrInit, class D=NoDelete , bool b=1>
+  struct LCBaseLinkTraits : public LCBaseTraits<U,T,I,D,b>{
 
-/** Special Extension that allows to write int extensions directly (not through a pointer !). */
-template <class U >
-struct LCIntExtension{  // FIXME: need to check on 64 bit architecture...
+    typedef LCBaseTraits<U,T,I,D,b> base ;
 
-  typedef int ptr ;  // base pointer type 
+    typedef T*& ext_type ;                 // return value of  ext<>()
+    typedef T*  rel_type ;                 // return value of  rel<>() 
+    typedef typename base::ptr obj_ptr ;   // pointer to object
 
-  typedef U tag ;     // this ensures that a new class instance is created for every user extension
+    static const bool is_container=false ;
+  };
 
-  static const int allowed_to_call_ext = 1 ;
+  /** Base class for all containers of extensions and relations, vectors, lists,... */
+  template <class U, class T , class I=CreationPtrInit<T>, class D=DeletePtr<T> , bool b=1>
+  struct LCBaseLinkContainerTraits : public LCBaseTraits<U,T,I,D,b>{
 
-  static void clean(void *v) { }
+    typedef LCBaseTraits<U,T,I,D,b> base ;
 
-  static ptr init() { 
-    return 0 ; 
-  }
-  static DeleteFPtr deletePtr() { return  &clean ; }  ;
+    typedef       T*  ext_type ;              // return value of  ext<>()
+    typedef const T*  rel_type ;              // return value of  rel<>() 
+    typedef typename T::value_type obj_ptr ;  // pointer to object
 
-  typedef int& ext_type ;                
-};
+    typedef typename T::iterator iterator ;
+    typedef typename T::const_iterator const_iterator ;
 
+    static const bool is_container=true ;
+  };
 
-/** Special Extension that allows to write float extensions directly (not through a pointer !). */
-template <class U >
 
-struct LCFloatExtension{// FIXME: need to check on 64 bit architecture...
-
-  typedef float  ptr ;  // base pointer type 
-  typedef U tag ;     // this ensures that a new class instance is created for every user extension
+  /** Helper class for relations */
+  template <class U, class T> 
+  struct RelationOneSide  : 
+    public LCBaseLinkTraits<U,T,SimplePtrInit,NoDelete,false> {};
   
-  static const int allowed_to_call_ext = 1 ;
   
-  static void clean(void *v) { }
-
-  static ptr init() { return 0 ; }
-
-  static DeleteFPtr deletePtr() { return  &clean ; }  ;
-
-  typedef float& ext_type ;                 // return value of  ext<>()
-};
-
-
-template <class U, class T , class I=CreationPtrInit<T>, class D=DeletePtr<T> , bool b=1>
-struct LCBaseLinkContainerTraits : public LCBaseTraits<U,T,I,D,b>{
+  /** Helper class for relations */
+  template <class U, class T> 
+  struct RelationManySide :
+    public LCBaseLinkContainerTraits< U, std::list<T*>,
+				      CreationPtrInit< std::list<T*> > , 
+				      DeletePtr<std::list<T*> > ,false  > {};
+  
+  /** Helper class for relations */
+  template <class U> struct FromRelation{} ;
+  
+  /** Helper class for relations */
+  template <class U> struct ToRelation{} ;
+  
+  
+  /** Helper class for biderectional relations provides the to and from type*/
+  template <class From, class To>
+  struct BiDirectional{
+    typedef From from  ;
+    typedef To   to  ;
+  } ;
+  
+  
+  /** Helper functions that treat single objects and containers */ 
+  template <bool is_container>
+  struct objorcont{
 
-  typedef LCBaseTraits<U,T,I,D,b> base ;
+    template <class T, class S>
+    inline static void add( T t, S s) { t->push_back( s )  ; }
 
-  typedef       T*  ext_type ;              // return value of  ext<>()
-  typedef const T*  rel_type ;              // return value of  rel<>() 
-  typedef typename T::value_type obj_ptr ;  // pointer to object
+    template <class T, class S>
+    inline static void remove( T t, S s) { t->remove( s )  ; }
+  };
 
-  typedef typename T::iterator iterator ;
-  typedef typename T::const_iterator const_iterator ;
 
-  static const bool is_container=true ;
-};
+  /** Helper functions specialization for single objects*/ 
+  template <>
+  struct objorcont<false>{
 
-//-----------end of  internal helper typdefs, function and classes ----------
+    template <class T, class S> 
+    inline static void add( T& t, S s) { t = s ; }
 
-/** Simple Extension -  pointer to an object of type T. 
- *  The class U needs to be the subclass  type, e.g.<br>
- *  struct MyAttributes : public LCExtension<MyAttributes,Attributes> {} ; <br>
- */
-template <class U, typename T> 
-struct LCExtension : public LCBaseLinkTraits< U, T > {};
+    template <class T, class S>
+    inline static void remove( T& t, S s) { t = 0 ; }
+  };
 
-/** Simple Extension -  pointer to an object of type T where the ownership is taken over
- *  by the object holding the extension, i.e. it deletes the object when itself is deleted. 
- *  The class U needs to be the subclass  type, e.g.<br>
- *  struct MyAttributes : public LCExtension<MyAttributes,Attributes> {} ; <br>
- */
-template <class U, typename T> 
-class LCOwnedExtension : public LCBaseLinkTraits< U, T , SimplePtrInit , DeletePtr<T> > {};
+  //-----------end of  internal helper typdefs, function and classes ----------
 
 
-/** Extension vector holding pointers to objects of type T - no ownership of the objects is taken. */
-template <class U, class T> 
-class LCExtensionVector :
-  public LCBaseLinkContainerTraits< U, std::vector<T*>,
-				    CreationPtrInit< std::vector<T*> > , 
-				    DeletePtr<std::vector<T*> > > {};
+} // end namespace lcrtrel_helper
 
+namespace lcrtrel{
 
-/** Extension vector holding pointers to objects of type T - ownership of the objects is taken, i.e.
- *  all objects pointed to in the vector are deleted when the object itself is deleted.
- */
-template <class U, class T> 
-class LCOwnedExtensionVector : 
-  public LCBaseLinkContainerTraits< U, std::vector<T*>,
-				    CreationPtrInit< std::vector<T*> > , 
-				    DeleteElements< std::vector<T*> > > {};
+  using namespace lcrtrel_helper ;
 
+  /** Simple Extension -  pointer to an object of type T. 
+   *  The class U needs to be the subclass  type, e.g.<br>
+   *  struct MyAttributes : public LCExtension<MyAttributes,Attributes> {} ; <br>
+   */
+  template <class U, typename T> 
+  struct LCExtension : public LCBaseLinkTraits< U, T > {};
 
-/** Extension list holding pointers to objects of type T - no ownership of the objects is taken. */
-template <class U, class T> 
-class LCExtensionList :
-  public LCBaseLinkContainerTraits< U, std::list<T*>,
-				    CreationPtrInit< std::list<T*> > , 
-				    DeletePtr<std::list<T*> > > {};
+  /** Simple Extension -  pointer to an object of type T where the ownership is taken over
+   *  by the object holding the extension, i.e. it deletes the object when itself is deleted. 
+   *  The class U needs to be the subclass  type, e.g.<br>
+   *  struct MyAttributes : public LCExtension<MyAttributes,Attributes> {} ; <br>
+   */
+  template <class U, typename T> 
+  class LCOwnedExtension : public LCBaseLinkTraits< U, T , SimplePtrInit , DeletePtr<T> > {};
 
-/** Extension list holding pointers to objects of type T - ownership of the objects is taken, i.e.
- *  all objects pointed to in the vector are deleted when the object itself is deleted.
- */
-template <class U, class T> 
-class LCOwnedExtensionList : 
-  public LCBaseLinkContainerTraits< U, std::list<T*>,
-				    CreationPtrInit< std::list<T*> > , 
-				    DeleteElements<  std::list<T*> > > {};
 
+  /** Extension vector holding pointers to objects of type T - no ownership of the objects is taken. */
+  template <class U, class T> 
+  class LCExtensionVector :
+    public LCBaseLinkContainerTraits< U, std::vector<T*>,
+				      CreationPtrInit< std::vector<T*> > , 
+				      DeletePtr<std::vector<T*> > > {};
 
 
-/** Helper class for relations */
-template <class U, class T> 
-struct RelationOneSide  : 
-  public LCBaseLinkTraits<U,T,SimplePtrInit,NoDelete,false> {};
+  /** Extension vector holding pointers to objects of type T - ownership of the objects is taken, i.e.
+   *  all objects pointed to in the vector are deleted when the object itself is deleted.
+   */
+  template <class U, class T> 
+  class LCOwnedExtensionVector : 
+    public LCBaseLinkContainerTraits< U, std::vector<T*>,
+				      CreationPtrInit< std::vector<T*> > , 
+				      DeleteElements< std::vector<T*> > > {};
+
+
+  /** Extension list holding pointers to objects of type T - no ownership of the objects is taken. */
+  template <class U, class T> 
+  class LCExtensionList :
+    public LCBaseLinkContainerTraits< U, std::list<T*>,
+				      CreationPtrInit< std::list<T*> > , 
+				      DeletePtr<std::list<T*> > > {};
 
+  /** Extension list holding pointers to objects of type T - ownership of the objects is taken, i.e.
+   *  all objects pointed to in the vector are deleted when the object itself is deleted.
+   */
+  template <class U, class T> 
+  class LCOwnedExtensionList : 
+    public LCBaseLinkContainerTraits< U, std::list<T*>,
+				      CreationPtrInit< std::list<T*> > , 
+				      DeleteElements<  std::list<T*> > > {};
 
-/** Helper class for relations */
-template <class U, class T> 
-struct RelationManySide :
-  public LCBaseLinkContainerTraits< U, std::list<T*>,
-				    CreationPtrInit< std::list<T*> > , 
-				    DeletePtr<std::list<T*> > ,false  > {};
 
-/** Helper class for relations */
-template <class U> struct FromRelation{} ;
+  /** One to one relation between two objects of type From and To */
+  template <class U, class From, class To>
+  struct LC1To1Relation : 
+    public BiDirectional<RelationOneSide<FromRelation<U>,From>,
+			 RelationOneSide<ToRelation<U>,To> > {
 
-/** Helper class for relations */
-template <class U> struct ToRelation{} ;
+  } ; 
 
+  /** One to many relation between one object of type From to many objects of type To */
+  template <class U, class From, class To>
+  struct LC1ToNRelation : 
+    public BiDirectional<RelationOneSide<FromRelation<U>,From>,
+			 RelationManySide<ToRelation<U>,To> > {
+  } ; 
 
-/** Helper class for biderectional relations provides the to and from type*/
-template <class From, class To>
-struct BiDirectional{
-  typedef From from  ;
-  typedef To   to  ;
-} ;
+  /** Many to many relation between objects of type From to objects of type To */
+  template <class U, class From, class To>
+  struct LCNToNRelation : 
+    public BiDirectional<RelationManySide<FromRelation<U>,From>,
+			 RelationManySide<ToRelation<U>,To> > {
+  } ; 
 
 
+  /** Special Extension that allows to write int extensions directly (not through a pointer !). */
+  template <class U >
+  struct LCIntExtension{  // FIXME: need to check on 64 bit architecture...
+    
+    typedef int ptr ;  // base pointer type 
+    
+    typedef U tag ;     // this ensures that a new class instance is created for every user extension
+    
+    static const int allowed_to_call_ext = 1 ;
+    
+    static void clean(void *v) { }
 
-/** One to one relation between two objects of type From and To */
-template <class U, class From, class To>
-struct LC1To1Relation : 
-  public BiDirectional<RelationOneSide<FromRelation<U>,From>,
-			  RelationOneSide<ToRelation<U>,To> > {
+    static ptr init() { 
+      return 0 ; 
+    }
+    static DeleteFPtr deletePtr() { return  &clean ; }  ;
 
-} ; 
+    typedef int& ext_type ;                
+  };
 
-/** One to many relation between one object of type From to many objects of type To */
-template <class U, class From, class To>
-struct LC1ToNRelation : 
-  public BiDirectional<RelationOneSide<FromRelation<U>,From>,
-			  RelationManySide<ToRelation<U>,To> > {
-} ; 
 
-/** Many to many relation between objects of type From to objects of type To */
-template <class U, class From, class To>
-struct LCNToNRelation : 
-  public BiDirectional<RelationManySide<FromRelation<U>,From>,
-			  RelationManySide<ToRelation<U>,To> > {
-} ; 
+  /** Special Extension that allows to write float extensions directly (not through a pointer !). */
+  template <class U >
 
+  struct LCFloatExtension{// FIXME: need to check on 64 bit architecture...
 
-//--------------------------------------------------------------------
+    typedef float  ptr ;  // base pointer type 
+    typedef U tag ;     // this ensures that a new class instance is created for every user extension
+    typedef float& ext_type ;     // return value of  ext<>()
+  
+    static const int allowed_to_call_ext = 1 ;
+    static void clean(void *v) { }
+    static ptr init() { return 0 ; }
+    static DeleteFPtr deletePtr() { return  &clean ; }  ;
+  };
 
 
+  //--------------------------------------------------------------------
 
-class LCRTRelations ;
 
-/** Set the 1-to-1 relation between two objects - prexisting inconsistent relations 
-    involving the two objects are deleted to enforce a coinsistent set of from-to relations. */
-template <class R> 
-void set_relation( typename R::from::obj_ptr f, 
-		   typename R::to::obj_ptr t) ;
 
-/** Unset the 1-to-1 relation from f */
-template <class R> 
-void unset_relation(typename R::from::obj_ptr f );
+  class LCRTRelations ;
 
+  /** Set the 1-to-1 relation between two objects - prexisting inconsistent relations 
+      involving the two objects are deleted to enforce a consistent set of from-to relations. */
+  template <class R> 
+  void set_relation( typename R::from::obj_ptr f, 
+		     typename R::to::obj_ptr t) ;
 
-/** Add a link from f to t to an N-to-N relation ship  */
-template <class R> 
-void add_relation( typename R::from::obj_ptr f, 
-		   typename R::to::obj_ptr t) ;
+  /** Unset the 1-to-1 relation from f */
+  template <class R> 
+  void unset_relation(typename R::from::obj_ptr f );
 
 
-/** Remove the link from from f to t from the N-to-N relation ship  */
-template <class R> 
-void remove_relation( typename R::from::obj_ptr f, 
-		      typename R::to::obj_ptr t) ;
+  /** Add a link from f to t to an N-to-N relation ship  */
+  template <class R> 
+  void add_relation( typename R::from::obj_ptr f, 
+		     typename R::to::obj_ptr t) ;
 
 
-/** Removes all relations from the given object */
-template <class R> 
-void remove_relations(typename R::from::obj_ptr f );
+  /** Remove the link from from f to t from the N-to-N relation ship  */
+  template <class R> 
+  void remove_relation( typename R::from::obj_ptr f, 
+			typename R::to::obj_ptr t) ;
 
 
-/** Merge the relations from f2 to f1 - after this call f1 will hold all 
- *  the relations and f2 will be empty. 
- */
-template <class R> 
-void merge_relations( typename R::from::obj_ptr f1, 
-		      typename R::from::obj_ptr f2) ;
+  /** Removes all relations from the given object */
+  template <class R> 
+  void remove_relations(typename R::from::obj_ptr f );
 
 
+  /** Merge the relations from f2 to f1 - after this call f1 will hold all 
+   *  the relations and f2 will be empty. 
+   */
+  template <class R> 
+  void merge_relations( typename R::from::obj_ptr f1, 
+			typename R::from::obj_ptr f2) ;
 
-/** Base class for run time extensions to and relation between objects */
 
-class LCRTRelations{
-  
-  // declare functions for relation handling as friends
-  template <class R> 
-  friend void set_relation( typename R::from::obj_ptr f, 
-			    typename R::to::obj_ptr t);
-  template <class R> 
-  friend void unset_relation(typename R::from::obj_ptr f );
 
-  template <class R> 
-  friend void add_relation( typename R::from::obj_ptr f, 
-		     typename R::to::obj_ptr t) ;
-  template <class R> 
-  friend void remove_relation( typename R::from::obj_ptr f, 
-			       typename R::to::obj_ptr t) ;
-  template <class R> 
-  friend void remove_relations(typename R::from::obj_ptr f );
+  /** Base class that provides run time (user) extensions and relation between objects. 
+   * Every subclass object of LCRTRelations (and thus LCObbject) will automatically have 
+   * the following functionality:<br>
+   * <ul>
+   * <li>extension of the object with arbitrary (even non-LCObject) classes</li>
+   * <li>extension of single objects or vectors, lists of objects</li>
+   * <li>optionally ownership is taken for extension objects (memory management)</li>
+   * <li>relations to other subclasses of LCRTRelations:
+   *  <ul>
+   *  <li>one to one</li>
+   *  <li>one to many</li>
+   *  <li>many to many</li>
+   *  </li></ul>
+   * </ul>
+   * 
+   * The described functionality is provided through the two templated member functions:<br>
+   * ext<class V>() <br>
+   * rel<class V>() <br>
+   * the class V is a user defined so called traits class, that uniquely tags the 
+   * extension/relationship and defines the types of the objects involved. <br>
+   * For extensions users have to subclass one of the following classes:<br>
+   * LCExtension, LCOwnedExtension, LCIntExtension, LCFloatExtension,<br>
+   * LCExtensionVector, LCExtensionList, LCOwnedExtensionVector, LCOwnedExtensionList. <br>
+   * For example 
+   * the following defines a user extension of a vector of strings that are owned by the 
+   * object (i.e. deleted when the object is deleted):<br>
+   * <p><b>
+   * struct ParticleIDs : LCOwnedExtensionVector<ParticleIDs, std::string> {};<br>
+   * </b>
+   * &nbsp;&nbsp;&nbsp;(note: the first template parameter has to be the class itself !)
+   * <p>
+   * This extension can then be used  anywhere in the following code for all LCObjects, e.g.:<br>
+   * <p><b>
+   *   MCParticle*  mcp = dynamic_cast<MCParticle*>( mcpcol->getElementAt(i) ) ;<br>
+   * 	mcp->ext<ParticleIDs>()->push_back( new std::string("charged")  )  ;<br>
+   * 	mcp->ext<ParticleIDs>()->push_back( new std::string("hadron")  )  ;<br>
+   * 	mcp->ext<ParticleIDs>()->push_back( new std::string("pion")  )  ;<br>
+   * </b><p>
+   * and be read out again: <br>
+   * <p><b>
+   *	ParticleIDs::ext_type pidv =  mcp->ext<ParticleIDs>() ;<br>
+   *	for( ParticleIDs::const_iterator ipid = pidv->begin() ; ipid != pidv->end(); ++ipid){<br>
+   *	 &nbsp;&nbsp; std::cout << **ipid << ", " ;<br>
+   *	}<br>
+   *</b><p>
+   * <p>
+   * Similarily the following defines a one to many relationship between Tracks and Clusters:<br>
+   * <p><b>
+   * struct TrkCluLink : LC1ToNRelation<TrkCluLink,Track,Cluster> {} ; <br>
+   * </b><p>
+   * Relations are allways biderectional, i.e. there is a <b>from</b> and a <b>to</b> side.
+   * They can then be set and modified with the following functions:<br>
+   * set_relation(), unset_relation(), add_relation(), <br>
+   * remove_relation(), remove_relations(),
+   * merge_relations(). <br>
+   * For example:<br>
+   * <p>
+   * <b>
+   *	Track*   trk = dynamic_cast<Track*>   ( trkcol->getElementAt(j) ) ; <br>
+   *    //... <br>
+   *	Cluster* clu = dynamic_cast<Cluster*> ( clucol->getElementAt(k) ) ; <br>
+   *	add_relation<TrkCluLink>( trk ,clu ); <br>
+   *</b><p>
+   * The many side can then  be read out with a const_iterator and the one side with a 
+   * normal pointer:<br>
+   * <p><b>
+   *	Track* trk =  clu->rel<TrkCluLink::from>() ; <br>
+   *    //...<br>
+	TrkCluLink::to::rel_type clulist =  trk->rel<TrkCluLink::to>() ; <br>
+	for( TrkCluLink::to::const_iterator iclu = clulist->begin() ; iclu != clulist->end() ; ++iclu ){ <br>
+	  &nbsp;&nbsp;Cluster* clu = *iclu ;  // iterator is of type pointer to container element <br>
+	  &nbsp;&nbsp;std::cout <<  "   assigned cluster with E = " << clu->getEnergy() << std::endl ;  <br>
+	}
+   *</b>
+   * <p>
+   * More examples can be found in <b>$LCIO/src/cpp/src/EXAMPLES/lcrtrelations.cc</b>.
+   */
 
-  template <class R> 
-  friend void merge_relations( typename R::from::obj_ptr f1, 
-			       typename R::from::obj_ptr f2) ;
+  class LCRTRelations{
   
-public:
-  
-  /** Provides access to an extension object - the type and ownership is defined 
-   *  by the class V which should be a subtype of LCExtension, LCOwnedExtension,
-   *  LCExtensionVector, LCExtensionList,...
-   */
-  template <class V>
-  inline typename V::ext_type  ext() { 
+    // declare functions for relation handling as friends
+    template <class R> 
+    friend void set_relation( typename R::from::obj_ptr f, 
+			      typename R::to::obj_ptr t);
+    template <class R> 
+    friend void unset_relation(typename R::from::obj_ptr f );
+
+    template <class R> 
+    friend void add_relation( typename R::from::obj_ptr f, 
+			      typename R::to::obj_ptr t) ;
+    template <class R> 
+    friend void remove_relation( typename R::from::obj_ptr f, 
+				 typename R::to::obj_ptr t) ;
+    template <class R> 
+    friend void remove_relations(typename R::from::obj_ptr f );
+
+    template <class R> 
+    friend void merge_relations( typename R::from::obj_ptr f1, 
+				 typename R::from::obj_ptr f2) ;
+  
+  public:
+  
+    /** Provides access to an extension object - the type and ownership is defined 
+     *  by the class V which should be a subtype of LCExtension, LCOwnedExtension,
+     *  LCExtensionVector, LCExtensionList,...
+     */
+    template <class V>
+    inline typename V::ext_type  ext() { 
 
-    static char check[ V::allowed_to_call_ext] ;
+      static char check[ V::allowed_to_call_ext] ;
 
-    return  ptr<V>() ;
-  }
+      return  ptr<V>() ;
+    }
   
 
-  /** Provides read access to relations - the object types and their connectivity 
-   *  are defined by the class V which has to be a subtype of either 
-   *  LC1To1Relation, LC1ToNRelation or LCNToNRelation.
-   */
-  template <class V>
-  inline typename V::rel_type rel() {
+    /** Provides read access to relations - the object types and their connectivity 
+     *  are defined by the class V which has to be a subtype of either 
+     *  LC1To1Relation, LC1ToNRelation or LCNToNRelation.
+     */
+    template <class V>
+    inline typename V::rel_type rel() {
     
-    return  ptr<V>() ;
-  }
+      return  ptr<V>() ;
+    }
   
   
 
-  LCRTRelations() { 
-    _vec = new PtrVec( 32  ) ; // initialize to prevent from to many resizes
-  }
+    //   LCRTRelations() { 
+    //     _vec = new PtrVec( 32  ) ; // initialize to prevent from to many resizes
+    //   }
+    //   ~LCRTRelations() {
+    //    for( unsigned i=0 ; i< cleaners().size() ; ++i){
+    //      cleaners()[i]( _vec->operator[](i)  ) ;  // call the delete function
+    //    }
+    //    delete _vec ;
+    //   }
 
-  ~LCRTRelations() {
 
-   for( unsigned i=0 ; i< cleaners().size() ; ++i){
 
-     cleaners()[i]( _vec->operator[](i)  ) ;  // call the delete function
-     
-   }
-   delete _vec ;
-  }
-
-//   ~LCRTRelations() {
-//     for( PtrMap::iterator it = _map.begin() ;
-// 	 it != _map.end() ; ++it ){
-//       it->first( it->second ) ;  // call the delete function
-//     }
-//   }
-
-//   void print(){
-//     std::cout << " ---- LCRTRelations -- : " << std::endl ;
-//     typedef std::map< void * , void*  > MyPtrMap ;
-//     MyPtrMap& map = *(MyPtrMap*) &_map ;
-//     for( MyPtrMap::iterator it = map.begin() ;
-// 	 it != map.end() ; ++it ){
-//       std::cout << "      ----   key : " << &(it->first) << " value " 
-// 		<<  (void*)it->second  << std::endl ;
-//     }
-//   }
+    ~LCRTRelations() {
+      for( PtrMap::iterator it = _map.begin() ; it != _map.end() ; ++it ){
+	cleaners()[ it->first ] ( it->second ) ;  // call the delete function
+      }
+    }
+  
+    //   void print(){
+    //     std::cout << " ---- LCRTRelations -- : " << std::endl ;
+    //     typedef std::map< void * , void*  > MyPtrMap ;
+    //     MyPtrMap& map = *(MyPtrMap*) &_map ;
+    //     for( MyPtrMap::iterator it = map.begin() ;
+    // 	 it != map.end() ; ++it ){
+    //       std::cout << "      ----   key : " << &(it->first) << " value " 
+    // 		<<  (void*)it->second  << std::endl ;
+    //     }
+    //   }
 
 
-protected:
+  protected:
 
-  /** Returns the reference to the pointer to the extension/relation object */
-  template <class V>
-  inline typename V::ptr & ptr() {
+    //   /** Returns the reference to the pointer to the extension/relation object */
+    //   template <class V>
+    //   inline typename V::ptr & ptr() {
     
-    typedef std::vector< typename V::ptr  > MyPtrVec ;
-    MyPtrVec* vec = (MyPtrVec*) _vec ;
+    //     typedef std::vector< typename V::ptr  > MyPtrVec ;
+    //     MyPtrVec* vec = (MyPtrVec*) _vec ;
 
-    unsigned id =  typeID<V>()  ;
+    //     unsigned id =  typeID<V>()  ;
 
-    if( ! (vec->size() > id )  ) {
-      vec->resize( id + 1 ) ;
-    }
+    //     if( ! (vec->size() > id )  ) {
+    //       vec->resize( id + 1 ) ;
+    //     }
 
-    typename V::ptr& p =  vec->operator[](id) ;
+    //     typename V::ptr& p =  vec->operator[](id) ;
 
-    if( p == 0 ) 
-      p = V::init() ;
+    //     if( p == 0 ) 
+    //       p = V::init() ;
 
-    return  p ;
-  }
+    //     return  p ;
+    //   }
   
-//   /** Returns the reference to the pointer to the extension/relation object */
-//   template <class V>
-//   typename V::ptr & ptr() {
+
+
+    /** Returns the reference to the pointer to the extension/relation object */
+    template <class V>
+    typename V::ptr & ptr() {
     
-//     typedef std::map< DeleteFPtr , typename V::ptr  > MyPtrMap ;
+      typedef std::map< unsigned , typename V::ptr  > MyPtrMap ;
     
-//     MyPtrMap& map = *(MyPtrMap*) &_map ;
+      MyPtrMap* map = (MyPtrMap*) &_map ;
     
-//     typename MyPtrMap::iterator it = map.find( V::deletePtr() ) ;
+      typename MyPtrMap::iterator it = map->find( typeID<V>() ) ;
     
-//     if( it == map.end() )
-//       it = map.insert( map.begin(), 
-// 		       std::make_pair( V::deletePtr(), V::init() )) ;
+      if( it == map->end() )
+	it = map->insert( map->begin(), 
+			  std::make_pair(  typeID<V>() , V::init() )) ;
     
-//     return  it->second  ;
-//   }
+      return  it->second  ;
+    }
 
-private:
+  private:
   
-  static DPtrVec& cleaners(){
-    static DPtrVec v ;
-    return v ;
-  }
+    static DPtrVec& cleaners(){
+      static DPtrVec v ;
+      return v ;
+    }
   
-  inline unsigned nextID(DeleteFPtr cp){
-    static unsigned id(0) ;
+    inline unsigned nextID(DeleteFPtr cp){
+      static unsigned id(0) ;
 
-//     std::cout << " ---- nextID " << id+1  << " - delete Ptr  " 
-    // <<  cp << std::endl ;
+      //     std::cout << " ---- nextID " << id+1  << " - delete Ptr  " 
+      // <<  cp << std::endl ;
       
-    cleaners().push_back( cp ) ;
+      cleaners().push_back( cp ) ;
 
-    return id++ ;
-  }
+      return id++ ;
+    }
   
-  template <class T>
-  inline unsigned typeID(){
-    static const unsigned uid  = nextID( T::deletePtr() ) ;
+    template <class T>
+    inline unsigned typeID(){
+      static const unsigned uid  = nextID( T::deletePtr() ) ;
 
-    return uid ;
-  } ;
-  
-  //   PtrMap _map ;
+      return uid ;
+    } ;
   
   
-  PtrVec* _vec ; 
+    //   PtrVec* _vec ; 
+    PtrMap _map ;
   
-} ;
+  } ;
   
 
-//----------------------- relation function definitions -----------------------------------
+  //----------------------- relation function definitions -----------------------------------
 
 
-template <class R> 
-void unset_relation(typename R::from::obj_ptr f){
+  template <class R> 
+  void unset_relation(typename R::from::obj_ptr f){
   
-  if( f != 0 ){
+    if( f != 0 ){
     
-    LCRTRelations* t = f->LCRTRelations::rel<typename R::to>() ;
+      LCRTRelations* t = f->LCRTRelations::rel<typename R::to>() ;
     
-    if( t != 0 ) 
-      t->LCRTRelations::ptr<typename R::from>() = 0 ;
+      if( t != 0 ) 
+	t->LCRTRelations::ptr<typename R::from>() = 0 ;
     
-    f->LCRTRelations::ptr<typename R::to>() = 0 ;
+      f->LCRTRelations::ptr<typename R::to>() = 0 ;
+    }
   }
-}
 
-template <class R> 
-void set_relation(typename R::from::obj_ptr f, typename R::to::obj_ptr t){
+  template <class R> 
+  void set_relation(typename R::from::obj_ptr f, typename R::to::obj_ptr t){
   
-  // clear old relations first
-  unset_relation<R>( f ) ;
-  unset_relation<R>(t->LCRTRelations::rel<typename R::from>() ) ; 
+    // clear old relations first
+    unset_relation<R>( f ) ;
+    unset_relation<R>(t->LCRTRelations::rel<typename R::from>() ) ; 
   
-  f->LCRTRelations::ptr<typename R::to>() =  t ;
-  t->LCRTRelations::ptr<typename R::from>() =  f ;
-}
-
-
-
-template <bool is_container>
-struct helper{
-
-  template <class T, class S>
-  inline static void add( T t, S s) { t->push_back( s )  ; }
-
-  template <class T, class S>
-  inline static void remove( T t, S s) { t->remove( s )  ; }
-};
+    f->LCRTRelations::ptr<typename R::to>() =  t ;
+    t->LCRTRelations::ptr<typename R::from>() =  f ;
+  }
 
-template <>
-struct helper<false>{
 
-  template <class T, class S> 
-  inline static void add( T& t, S s) { t = s ; }
 
-  template <class T, class S>
-  inline static void remove( T& t, S s) { t = 0 ; }
-};
 
-template <class R> 
-void add_relation(  typename R::from::obj_ptr f, 
-		    typename R::to::obj_ptr t){
+  template <class R> 
+  void add_relation(  typename R::from::obj_ptr f, 
+		      typename R::to::obj_ptr t){
 
-  f->LCRTRelations::ptr<typename R::to>()->push_back( t ) ;
+    f->LCRTRelations::ptr<typename R::to>()->push_back( t ) ;
 
-//   std::cout << " ask to assign " << f << " to " << t << std::endl ;
-  helper<R::from::is_container>::add( t->LCRTRelations::ptr<typename R::from>() , f ) ; 
-}
+    //   std::cout << " ask to assign " << f << " to " << t << std::endl ;
+    objorcont<R::from::is_container>::add( t->LCRTRelations::ptr<typename R::from>() , f ) ; 
+  }
 
 
 
 
-template <class R> 
-void remove_relation( typename R::from::obj_ptr f, 
-		      typename R::to::obj_ptr t ) {
+  template <class R> 
+  void remove_relation( typename R::from::obj_ptr f, 
+			typename R::to::obj_ptr t ) {
   
-  f->LCRTRelations::ptr<typename R::to>()->remove( t ) ;
+    f->LCRTRelations::ptr<typename R::to>()->remove( t ) ;
 
-  helper<R::from::is_container>::remove( t->LCRTRelations::ptr<typename R::from>() , f ) ; 
-}
+    objorcont<R::from::is_container>::remove( t->LCRTRelations::ptr<typename R::from>() , f ) ; 
+  }
 
 
-template <class R> 
-void remove_relations( typename R::from::obj_ptr f ) {
+  template <class R> 
+  void remove_relations( typename R::from::obj_ptr f ) {
   
-  typename R::to::ptr cl = f->LCRTRelations::ptr<typename R::to>() ;
+    typename R::to::ptr cl = f->LCRTRelations::ptr<typename R::to>() ;
   
-  for( typename R::to::iterator it = cl->begin(); it!=cl->end(); ++it){
+    for( typename R::to::iterator it = cl->begin(); it!=cl->end(); ++it){
     
+      objorcont<R::from::is_container>::remove((*it)->LCRTRelations::ptr<typename R::from>(), f ) ; 
 
-//     (*it)->LCRTRelations::ptr<typename R::from>().remove( f ) ;
-
-    helper<R::from::is_container>::remove((*it)->LCRTRelations::ptr<typename R::from>() , f ) ; 
-
+    }
+    cl->clear() ;
   }
-  cl->clear() ;
-}
 
-template <class R> 
-void merge_relations(typename R::from::obj_ptr f1, 
-		     typename R::from::obj_ptr f2 ) {
+  template <class R> 
+  void merge_relations(typename R::from::obj_ptr f1, 
+		       typename R::from::obj_ptr f2 ) {
   
-  typename R::to::ptr  lt2 = f2->LCRTRelations::ptr<typename R::to>() ;
+    typename R::to::ptr  lt2 = f2->LCRTRelations::ptr<typename R::to>() ;
   
-  for( typename R::to::iterator it = lt2->begin() ;it !=  lt2->end() ; it++ ){
+    for( typename R::to::iterator it = lt2->begin() ;it !=  lt2->end() ; it++ ){
[truncated at 1000 lines; 16 more skipped]

lcio/src/cpp/include
lcio.h 1.25 -> 1.26
diff -u -r1.25 -r1.26
--- lcio.h	21 Sep 2006 06:10:36 -0000	1.25
+++ lcio.h	1 Dec 2006 14:10:09 -0000	1.26
@@ -7,7 +7,7 @@
  * documentation with doxygen. 
  * 
  * @author gaede
- * @version $Id: lcio.h,v 1.25 2006/09/21 06:10:36 gaede Exp $ 
+ * @version $Id: lcio.h,v 1.26 2006/12/01 14:10:09 gaede Exp $ 
  * @see LCEvent
  */
 #include "EVENT/LCIO.h"
@@ -50,6 +50,12 @@
 namespace UTIL{}
 
 
+/** The namespace lcrtrel holds classes and functions for runtime extensions and relations
+ *  see LCRTRelations for more detailed documentation.
+ * 
+ */
+namespace lcrtrel{}
+
 
 /** The LCIO namespace combines EVENT, IO, IMPL and UTIL for user convenience. 
  */
@@ -63,6 +69,8 @@
 
   using namespace UTIL ;
 
+  using namespace lcrtrel ;
+
   using IOIMPL::LCFactory ;
 
 }

lcio/src/cpp/src/EXAMPLE
lcrtrelation.cc 1.2 -> 1.3
diff -u -r1.2 -r1.3
--- lcrtrelation.cc	30 Nov 2006 11:05:01 -0000	1.2
+++ lcrtrelation.cc	1 Dec 2006 14:10:10 -0000	1.3
@@ -6,69 +6,121 @@
 #include "EVENT/Track.h" 
 #include "EVENT/Cluster.h" 
 
-//static const char* FILEN = "recjob.slcio" ; // default file name 
-static std::vector<std::string> FILEN ; 
-
 using namespace std ;
 using namespace lcio ;
 
 
 
-struct TrkCluLink : LCNToNRelation<TrkCluLink,Track,Cluster> {} ;
+// ------  define some structs for extensions and relations:-----------
+
+// NB: the first template argument of the parent class has to the class itself !
+
+// a simple int extension 
+struct Index : LCIntExtension<Index> {} ;
+
+// a vector of strings (pointers) that are owned by the object that is extended 
+struct ParticleIDs : LCOwnedExtensionVector<ParticleIDs,std::string> {};
+
+
+// note extensions can be attched to any LCObject and be of any type, i.e. in particular
+// of user defined types:
+struct UserClass{
+  int someInt ;
+  float aFloat ;
+};
+struct MyUserExtension : LCOwnedExtension<MyUserExtension,UserClass> {} ;
+
+
+// relations have to specify the type of the objects from and to which they relate: 
 
-struct Index : LCOwnedExtension<Index,int> {} ;
+// example:   a one to many relationship between tracks and clusters:
+struct TrkCluLink : LC1ToNRelation<TrkCluLink,Track,Cluster> {} ;
 
 
-/** Example/test program for new LCIO runtime relations.
+// a many to many relationship between MCParticles
+struct ParentDaughter : LCNToNRelation<ParentDaughter,MCParticle,MCParticle> {} ;
+
+
+//-----------------------------------------------------------------------------------------
+
+/** Example/test program for new runtime extensions and relations
+ *  requires recjob.slcio (from simjob/recjob).
  */
 
 int main(int argc, char** argv ){
 
-  // read file names from command line (only argument) 
-  if( argc < 2) {
-    cout << " usage:  anajob <input-file1> [[input-file2],...]" << endl ;
-    exit(1) ;
-  }
-  for(int i=1 ; i < argc ; i++){
-      FILEN.push_back( argv[i] )  ;
-  }
-  int nFiles = argc-1 ;
-  
-  LCReader* lcReader = LCFactory::getInstance()->createLCReader() ;
-  
-  cout << " will open and read from files: " << endl ;  
-  for(int i=0 ; i < nFiles ; i++){
-    cout  << "     "  << FILEN[i] << endl ; 
-  }  
 
-  //  loop over the file  and dump event data
+  LCReader* lcReader = LCFactory::getInstance()->createLCReader() ;
 
-  lcReader->open( FILEN ) ;
+  lcReader->open( "recjob.slcio" ) ;
 
   LCEvent* evt ;
   int nEvents = 0 ;
   
 
   //----------- the event loop -----------
-  while( (evt = lcReader->readNextEvent()) != 0 && nEvents<10 ) {
+  while( (evt = lcReader->readNextEvent()) != 0 && nEvents < 1 ) {
     
-//     LCTOOLS::dumpEvent( evt ) ;
 
-    const StringVec* names = evt->getCollectionNames() ;
+    LCCollection* mcpcol = evt->getCollection("MCParticle" ) ;
+    
+    int nmcp = mcpcol->getNumberOfElements() ;
 
-    LCCollection* trkcol = 0  ;
-    LCCollection* clucol = 0  ;
+    for(int i=0 ; i< nmcp  ; i++ ){
 
-    for(unsigned int i=0;i< names->size() ;++i){
+      MCParticle*  mcp = dynamic_cast<MCParticle*>( mcpcol->getElementAt(i) ) ;
+	
+
+      // ints can be assigned directly - w/o pointer !
+      // make every particle know it's index in the collection 
+      mcp->ext<Index>() = i ;   
+
+
+      // assign a user object to each particle:
+
+      mcp->ext<MyUserExtension>() = new UserClass ;
+
+      mcp->ext<MyUserExtension>()->someInt = i*42 ;
+      mcp->ext<MyUserExtension>()->aFloat = i*3.1415 ;
+
+      // assign some pid strings - note ownership is taken by particle 
+
+      if( ! (i % 2) )
+
+	mcp->ext<ParticleIDs>()->push_back( new std::string("charged")  )  ;
+
+      else
+
+	mcp->ext<ParticleIDs>()->push_back( new std::string("neutral")  )  ;
       
-      LCCollection* col = evt->getCollection( (*names)[i] ) ;
+      if( ! (i % 3) )
+
+	mcp->ext<ParticleIDs>()->push_back( new std::string("hadron")  )  ;
+
+      else if( ! ((i+1) % 3) )
+
+	mcp->ext<ParticleIDs>()->push_back( new std::string("photon")  )  ;
+
+      else if( ! ((i+2) % 3) )
+
+	mcp->ext<ParticleIDs>()->push_back( new std::string("electron")  )  ;
+
+
+      // copy the parent - daughter relationship:
+
+      const MCParticleVec& daughters = mcp->getDaughters() ;
+
+      for(unsigned j=0 ; j< daughters.size()   ; j++ ){
+
+	add_relation<ParentDaughter>( mcp, daughters[j] ) ;
+      }
       
-      if(  col->getTypeName() == LCIO::TRACK ) 
-	trkcol = col ;
       
-      if(  col->getTypeName() == LCIO::CLUSTER ) 
-	clucol = col ;
     }
+    
+
+    LCCollection* trkcol = evt->getCollection("SomeTracks" ) ;
+    LCCollection* clucol = evt->getCollection("SomeClusters" ) ;
 
     if( trkcol && clucol ) {
 
@@ -80,43 +132,187 @@
 	
 	Track*   trk = dynamic_cast<Track*>   ( trkcol->getElementAt(j) ) ;
 	
-	trk->ext<Index>() = new int(j) ;
+	// ints can be assigned directly - w/o pointer !
+	// make every track know it's index in the collection 
+	trk->ext<Index>() = j ;   
 	
 	for(int k=0 ; k< nclu ; k++ ){
 	  
 	  Cluster* clu = dynamic_cast<Cluster*> ( clucol->getElementAt(k) ) ;
 	  
+	  // make every cluster know it's index in the collection 
  	  if( j == 0 )
-	    clu->ext<Index>() = new int(k) ;
-	  
-  	  add_relation<TrkCluLink>( trk ,clu );
+	    clu->ext<Index>() = k ;
 	  
-	}
+	  if( j % 2  && ( k == j || k == j-1 ) )  
 
+	    add_relation<TrkCluLink>( trk ,clu );
+	}
       }
       
       
-      // --- now print the relation:
+      // --- now print the relations:
 
+      std::cout << "   ---- tracks assigned to clusters: " << std::endl ;
       for(int j=0 ; j< ntrk ; j++ ){
 
-	std::cout << " track " << j << " cluster relations:   " ; 
 
 	Track*   trk = dynamic_cast<Track*>   ( trkcol->getElementAt(j) ) ;
 
+	std::cout << " track " << trk->ext<Index>()  << " assigned to clusters :   " ; 
+
 	TrkCluLink::to::rel_type clulist =  trk->rel<TrkCluLink::to>() ;
 
 	for( TrkCluLink::to::const_iterator iclu = clulist->begin() ;
 	     iclu != clulist->end() ; ++iclu ){
 	  
-	  Cluster* clu = *iclu ;
+	  Cluster* clu = *iclu ; // iterator is of type pointer to container element
 
-	  std::cout << * clu->ext<Index>() << ", " ; 
+	  std::cout <<  clu->ext<Index>() << ", " ; 
 	}
 	std::cout << std::endl ; 
       }
+
+      std::cout << "   ----- now the inverse relation : " << std::endl ;
+
+      for(int k=0 ; k< nclu ; k++ ){
+	  
+	Cluster* clu = dynamic_cast<Cluster*> ( clucol->getElementAt(k) ) ;
+
+
+	Track* trk =  clu->rel<TrkCluLink::from>() ;
+	
+	std::cout << " cluster " 
+		  << clu->ext<Index>() << " assigned from track:   " 
+		  << trk->ext<Index>() << std::endl ; 
+      }
+
+      std::cout << std::endl ; 
+
+
+      // print MCParticle extensions and relations:
+
+      std::cout << "   ----- MCParticles in event : : " << std::endl ;
       
+      nmcp = ( nmcp < 10 ? nmcp : 10 ) ;
+
+      for(int i=0 ; i<nmcp  ; i++ ){
+	
+	MCParticle*  mcp = dynamic_cast<MCParticle*>( mcpcol->getElementAt(i) ) ;
+
+	MCParticle*  mcp0 ;   // keep the first particle
+	if( i == 0 ) mcp0 = mcp  ;
+	
+	ParticleIDs::ext_type pidv =  mcp->ext<ParticleIDs>() ;
+	
+	std::cout <<  "   --- particle " << mcp->ext<Index>()  << " found to be : " ;  
+	
+	for( ParticleIDs::const_iterator ipid = pidv->begin() ; ipid != pidv->end(); ++ipid){
+	  
+	  std::cout << **ipid << ", " ;
+	}
+	
+	if( ( *(*pidv)[0] == "charged" && *(*pidv)[1] == "photon"  ) ||
+	    ( *(*pidv)[0] == "neutral" && *(*pidv)[1] == "electron")   )
+
+	  std::cout << " --- ooops ! " ;
+	
+	std::cout << std::endl ; 
+	
+
+
+	std::cout <<  "   --- particle " << mcp->ext<Index>()   <<  " user extension : " 
+		  << " someInt: " << mcp->ext<MyUserExtension>()->someInt
+		  << " aFloat:  " << mcp->ext<MyUserExtension>()->aFloat
+		  << std::endl ;
+
+
+	// now check that the runtime relation for daughters:
+
+	const MCParticleVec& daughters = mcp->getDaughters() ;
+
+	std::cout <<  "   --- particle " << mcp->ext<Index>()   <<  " daughters: " 
+		  << std::endl ;  
+
+	std::cout <<  "      --- from MCParticle:  " ; 
+
+	for(MCParticleVec::const_iterator idau = daughters.begin() ; 
+	    idau != daughters.end() ; ++idau){
+	  
+	  std::cout << (*idau)->ext<Index>() << ", " ; 
+	}
+	std::cout << std::endl ; 
+	
+
+	std::cout <<  "      --- from runtime rel: " ; 
+
+
+	ParentDaughter::to::rel_type daulist =  mcp->rel<ParentDaughter::to>() ;
+	
+	for( ParentDaughter::to::const_iterator idau = daulist->begin(); 
+	     idau != daulist->end(); ++idau){
+	  
+	  std::cout << (*idau)->ext<Index>() << ", " ;
+	}
+	std::cout << std::endl ; 
+	
+
+	std::cout <<  "   --- particle " << mcp->ext<Index>()   <<  " parents: " 
+		  << std::endl ;  
+
+	std::cout <<  "      --- from MCParticle:  " ; 
+
+
+	const MCParticleVec& parents = mcp->getParents() ;
+
+	for(MCParticleVec::const_iterator ipar = parents.begin() ; 
+	    ipar != parents.end() ; ++ipar){
+	  
+	  std::cout << (*ipar)->ext<Index>() << ", " ; 
+	}
+	std::cout << std::endl ; 
+	
+
+	std::cout <<  "      --- from runtime rel: " ; 
+
+
+	ParentDaughter::from::rel_type parlist =  mcp->rel<ParentDaughter::from>() ;
+	
+	for( ParentDaughter::from::const_iterator ipar = parlist->begin(); 
+	     ipar != parlist->end(); ++ipar){
+	  
+	  std::cout << (*ipar)->ext<Index>() << ", " ;
+	}
+	std::cout << std::endl ; 
+
+
+	// for demonstration we can rearange the daughter relationships:
+	if(i>0) 
+
+	  merge_relations<ParentDaughter>( mcp0 , mcp ) ;
+      }
       
+
+      for(int i=0 ; i<nmcp  ; i++ ){
+	
+	MCParticle*  mcp = dynamic_cast<MCParticle*>( mcpcol->getElementAt(i) ) ;
+
+	std::cout <<  "   --- particle " << mcp->ext<Index>()   
+		  <<  " daughters after merging : " ;
+
+
+	ParentDaughter::to::rel_type daulist =  mcp->rel<ParentDaughter::to>() ;
+	
+	for( ParentDaughter::to::const_iterator idau = daulist->begin(); 
+	     idau != daulist->end(); ++idau){
+	  
+	  std::cout << (*idau)->ext<Index>() << ", " ;
+	}
+	std::cout << std::endl ; 
+
+      }
+
+
     } else {
       std::cout << " couldn't find Track and Cluster collection in event !" << std::endl ;
     }
@@ -125,10 +321,6 @@
   } 
   // -------- end of event loop -----------
   
-  cout << endl <<  "  " <<  nEvents << " events read from files: " << endl  ;
-  for(int i=0 ; i < nFiles ; i++){
-    cout  << "     "  << FILEN[i] << endl ; 
-  }  
 
   lcReader->close() ;
   delete lcReader ;

lcio/src/cpp/src/EXAMPLE
recjob.cc 1.50 -> 1.51
diff -u -r1.50 -r1.51
--- recjob.cc	21 Sep 2006 06:10:41 -0000	1.50
+++ recjob.cc	1 Dec 2006 14:10:10 -0000	1.51
@@ -178,7 +178,7 @@
     trkVec->setFlag( trkFlag.getFlag()  ) ;
     
 
-    int nTrk = 10 ;
+    int nTrk = 5 ;
     for( int i=0; i < nTrk ; i ++ ){
       
       TrackImpl* trk = new TrackImpl ;
CVSspam 0.2.8