Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-01-18 09:14:52

0001 //==========================================================================
0002 //  AIDA Detector description implementation 
0003 //--------------------------------------------------------------------------
0004 // Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
0005 // All rights reserved.
0006 //
0007 // For the licensing terms see $DD4hepINSTALL/LICENSE.
0008 // For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
0009 //
0010 // Author     : M.Frank
0011 //
0012 //==========================================================================
0013 //
0014 // DDDB is a detector description convention developed by the LHCb experiment.
0015 // For further information concerning the DTD, please see:
0016 // http://lhcb-comp.web.cern.ch/lhcb-comp/Frameworks/DetDesc/Documents/lhcbDtd.pdf
0017 //
0018 //==========================================================================
0019 
0020 // Framework includes
0021 #include "DD4hep/Path.h"
0022 #include "DD4hep/Alignments.h"
0023 #include "DD4hep/OpaqueDataBinder.h"
0024 #include "DD4hep/detail/ConditionsInterna.h"
0025 #include "DDDB/DDDBTags.h"
0026 #include "DDDB/DDDBHelper.h"
0027 #include "DDDB/DDDBReader.h"
0028 #include "DDDB/DDDBDimension.h"
0029 #include "DDDB/DDDBConversion.h"
0030 #include "DDDBConfig.h"
0031 
0032 #include "Math/Polar2D.h"
0033 
0034 // C/C++ include files
0035 #include <climits>
0036 
0037 using namespace std;
0038 using namespace dd4hep;
0039 using namespace dd4hep::DDDB;
0040 
0041 #ifdef __GNUC__    // Disable some diagnostics.
0042 #pragma GCC diagnostic ignored "-Wunused-function"
0043 #endif
0044 
0045 /// Namespace for the AIDA detector description toolkit
0046 namespace dd4hep {
0047 
0048   /// Keep all in here anonymous. Does not have to be visible outside.
0049   namespace {
0050 
0051     using cond::AbstractMap;
0052 
0053     typedef AbstractMap::Params ConditionParams;
0054     struct PositionRPhiZ {};
0055     struct DDDBLogVolRef {};
0056     struct DDDBElementRef  {};
0057     struct DDDBMaterialRef  {};
0058     struct DDDBCatalogRef  {};
0059     struct DDDBConditionRef  {};
0060     struct DDDBTabPropertyRef  {};
0061     struct DDDBDetElemRef  {};
0062 
0063     struct DDDBConditionInfo  {};
0064     struct DDDBDetElem  {};
0065     struct DDDBParam {};
0066     struct DDDBBlock {};
0067     struct DDDBConfig {};
0068     struct DDDBParameter  {};
0069     struct DDDBGeometryInfo  {};
0070     struct DDDBConditionParam {};
0071     struct DDDBConditionParamMap {};
0072     struct DDDBConditionParamVector {};
0073     struct DDDBConditionParamSpecific {};
0074 
0075     /// C++ version to convert a string to lower case
0076     std::string str_lower(const std::string& str) {
0077       std::string res = str.c_str();
0078       for(char* p=(char*)res.c_str(); *p; ++p) *p = ::tolower(*p);
0079       return res;
0080     }
0081 
0082     /// C++ version to convert a string to upper case
0083     std::string str_upper(const std::string& str) {
0084       std::string res = str.c_str();
0085       for(char* p=(char*)res.c_str(); *p; ++p) *p = ::toupper(*p);
0086       return res;
0087     }
0088     
0089     /// Main processing context
0090     /**   \ingroup DD4HEP_DDDB
0091      */
0092     class DDDBContext  {
0093 
0094     private:
0095       template <typename T,typename Q> 
0096       void collect_id(Q& container, const string& id, T* object)  const {
0097         typename Q::const_iterator i=container.find(id);
0098         if ( i != container.end() )  {
0099           if ( object == (*i).second ) return;
0100           printout(ERROR,"collect","++ Duplicate ID: %s  %p <-> %p",
0101                    id.c_str(), object, (*i).second);
0102         }
0103         object->id = id;
0104         container[id] = object->addRef();
0105         print(object);
0106       }
0107       template <typename T,typename Q> 
0108       void collect_p(Q& container, const string& path, T* object)   const {
0109         typename Q::const_iterator i=container.find(path);
0110         if ( i != container.end() )  {
0111           if ( object == (*i).second ) return;
0112           printout(ERROR,"collectPath","++ Duplicate ID: %s  %p <-> %p",
0113                    path.c_str(), object, (*i).second);
0114         }
0115         container[path] = object->addRef();
0116       }
0117 
0118     public:
0119 
0120       /// Local processing environment
0121       /**   \ingroup DD4HEP_DDDB
0122        */
0123       class Locals  {
0124       public:
0125         string obj_path;
0126         DDDBDocument* xml_doc = 0;
0127         Locals() = default;
0128         Locals(const Locals& c) = default;
0129         Locals& operator=(const Locals& c) = default;
0130       };
0131 
0132       /// Helper class to preserve local processing environment
0133       /**   \ingroup DD4HEP_DDDB
0134        */
0135       class PreservedLocals : public Locals {
0136       public:
0137         DDDBContext* context;
0138 #ifdef __DEBUG_LOCALS
0139         void print(const char* opt, bool inc)  const  {
0140           static int preserv_level = 0;
0141           int level = inc ? preserv_level++ : --preserv_level;
0142           if ( xml_doc )
0143             printout(INFO,"Locals","%s[%d]: %s [%s]", opt, level, obj_path.c_str(), xml_doc->id.c_str());
0144           else
0145             printout(INFO,"Locals","%s[%d]: %s ", opt, level, obj_path.c_str());
0146         }
0147 #else
0148         inline void print(const char*, bool) const {}
0149 #endif
0150         PreservedLocals(DDDBContext* c) : Locals(c->locals), context(c) {
0151           print("PUSH", true);
0152         }
0153         ~PreservedLocals()           {
0154           print("POP ", false);
0155           context->locals = *this; 
0156         }
0157       };
0158 
0159     public:
0160       Locals      locals;
0161       Detector*   description         = 0;
0162       xml::UriReader* resolver        = 0;
0163       dddb*       geo                 = 0;
0164       bool        check               = true;
0165       /// Debug flags: can be set by parsing specialized XML
0166       CondDB2Objects::PrintConfig printConfig;
0167       /// Default constructor
0168       DDDBContext() = default;
0169       /// Initializing constructor
0170       DDDBContext(Detector* d);
0171 
0172       /** Printout helpers                                                                             */
0173       void print(const DDDBIsotope* obj)   const               { if ( printConfig.materials ) dddb_print(obj);    }
0174       void print(const DDDBElement* obj)   const               { if ( printConfig.materials ) dddb_print(obj);    }
0175       void print(const DDDBMaterial* obj)  const               { if ( printConfig.materials ) dddb_print(obj);    }
0176       void print(const DDDBShape* obj)     const               { if ( printConfig.shapes )    dddb_print(obj);    }
0177       void print(const DDDBPhysVol* obj)   const               { if ( printConfig.physvol )   dddb_print(obj);    }
0178       void print(const DDDBLogVol* obj)    const               { if ( printConfig.logvol )    dddb_print(obj);    }
0179       void print(const DDDBCatalog* obj)   const               { if ( printConfig.catalog )   dddb_print(obj);    }
0180       void print(const DDDBTabProperty* obj)  const            { if ( printConfig.tabprop )   dddb_print(obj);    }
0181       void print(const DDDBDocument* obj)  const               { if ( printConfig.docs )      dddb_print(obj);    }
0182       
0183       /** Data collection helpers for indexing by object identifier                                    */
0184       void collect(const string& id, DDDBCatalog* obj)         { collect_id(geo->catalogs, id, obj);        }
0185       void collect(const string& id, DDDBShape* obj)           { collect_id(geo->shapes, id, obj);          }
0186       void collect(const string& id, DDDBPhysVol* obj)         { collect_id(geo->placements, id, obj);      }
0187       void collect(const string& id, DDDBLogVol* obj)          { collect_id(geo->volumes, id, obj);         }
0188       void collect(const string& id, DDDBIsotope* obj)         { collect_id(geo->isotopes, id, obj);        }
0189       void collect(const string& id, DDDBElement* obj)         { collect_id(geo->elements, id, obj);        }
0190       void collect(const string& id, DDDBMaterial* obj)        { collect_id(geo->materials, id, obj);       }
0191       void collect(const string& id, DDDBTabProperty* obj)     { collect_id(geo->tabproperties, id, obj);   }
0192       void collect(const string& id, Condition& object)  {
0193         dddb::Conditions::const_iterator i=geo->conditions.find(id);
0194         if ( i != geo->conditions.end() )  {
0195           if ( object.ptr() == (*i).second ) return;
0196           printout(ERROR,"collect","++ Duplicate ID: %s  %p <-> %p",
0197                    id.c_str(), object.ptr(), (*i).second);
0198         }
0199         geo->conditions[id] = object.ptr();
0200       }
0201 
0202       /** Data collection helpers for indexing by path                                                 */
0203       void collectPath(const string& path, DDDBElement*   obj) { collect_p(geo->elementPaths,   path, obj); }
0204       void collectPath(const string& path, DDDBMaterial*  obj) { collect_p(geo->materialPaths,  path, obj); }
0205       void collectPath(const string& path, DDDBPhysVol*   obj) { collect_p(geo->placementPaths, path, obj); }
0206       void collectPath(const string& path, DDDBLogVol*    obj) { collect_p(geo->volumePaths,    path, obj); }
0207       void collectPath(const string& path, DDDBTabProperty* obj) { collect_p(geo->tabpropertyPaths, path, obj); }
0208       void collectPath(const string& path, DDDBCatalog*   obj) { collect_p(geo->catalogPaths,   path, obj); }
0209       void collectPath(const string& path, Condition& object) {
0210         dddb::Conditions::const_iterator i=geo->conditionPaths.find(path);
0211         if ( i != geo->conditionPaths.end() )  {
0212           if ( object.ptr() == (*i).second ) return;
0213           printout(ERROR,"collectPath","++ Duplicate ID: %s  %p <-> %p",
0214                    path.c_str(), object.ptr(), (*i).second);
0215         }
0216         geo->conditionPaths[path] = object.ptr();
0217       }
0218     } s_config;
0219 
0220     /// Initializing constructor
0221     DDDBContext::DDDBContext(Detector* d)   {
0222       *this = s_config;
0223       description = d;
0224     }
0225 
0226     
0227     /// Converter to incept processing exceptions
0228     /**   \ingroup DD4HEP_DDDB
0229      */
0230     template <typename T> struct Conv : protected Converter<T> {
0231     public:
0232       /// Initializing constructor of the functor with initialization of the user parameter
0233       Conv(Detector& l, void* p, void* o=0) : Converter<T>(l,p,o) {}
0234       void convert(xml::Handle_t element) const;
0235       void fill(xml::Handle_t, T*) const {}
0236       void operator()(xml::Handle_t element) const  {
0237         Increment<T> incr;
0238         try  {
0239           convert(element);
0240         }
0241         catch(const exception& e)  {
0242       bool eval_err = ::strstr(e.what(),"error during expression evaluation");
0243       if ( !eval_err ) eval_err = ::strstr(e.what(),"Evaluator : unknown variable");
0244       if ( !eval_err || (eval_err && s_config.printConfig.eval_error) )
0245         printout(INFO,typeName(typeid(T)),"Failed to convert XML object: %s", e.what());
0246       if ( s_config.printConfig.tree_on_error ) xml::dump_tree(element.parent());
0247         }
0248         catch(...)   {
0249           printout(INFO,typeName(typeid(T)),"Failed to convert XML object.");
0250       if ( s_config.printConfig.tree_on_error ) xml::dump_tree(element.parent());
0251         }
0252       }
0253     };
0254 
0255     /// Special shape converter with inception of processing exceptions
0256     /**   \ingroup DD4HEP_DDDB
0257      */
0258     template <typename T> struct ShapeConv : private Converter<T> {
0259     public:
0260       /// Initializing constructor of the functor with initialization of the user parameter
0261       ShapeConv(Detector& l, void* p) : Converter<T>(l,p,0) {}
0262       void operator()(xml::Handle_t element, DDDBShape*& ptr_shape) const  {
0263         Increment<T> incr;
0264         try  {
0265           convert(element, ptr_shape);
0266         }
0267         catch(const exception& e)  {
0268           printout(INFO,typeName(typeid(T)),"Failed to convert object: %s",e.what());
0269           //xml::dump_tree(element.parent());
0270         }
0271         catch(...)   {
0272           printout(INFO,typeName(typeid(T)),"Failed to convert object.");
0273           //xml::dump_tree(element.parent());
0274         }
0275       }
0276       void convert(xml::Handle_t element, DDDBShape*& ptr_shape) const;
0277     };
0278 
0279     /// Explicit template instantiations
0280     template <> void ShapeConv<DDDBShape>::convert(xml_h element, DDDBShape*& s) const;
0281     template <> void ShapeConv<DDDBAssembly>::convert(xml_h , DDDBShape*& s) const;
0282     template <> void ShapeConv<DDDBBox>::convert(xml_h element, DDDBShape*& s) const;
0283     template <> void ShapeConv<DDDBCons>::convert(xml_h element, DDDBShape*& s) const;
0284     template <> void ShapeConv<DDDBConeSegment>::convert(xml_h element, DDDBShape*& s) const;
0285     template <> void ShapeConv<DDDBTubs>::convert(xml_h element, DDDBShape*& s) const;
0286     template <> void ShapeConv<DDDBTrap>::convert(xml_h element, DDDBShape*& s) const;
0287     template <> void ShapeConv<DDDBPolycone>::convert(xml_h element, DDDBShape*& s) const;
0288     template <> void ShapeConv<DDDBPolygon>::convert(xml_h element, DDDBShape*& s) const;
0289     template <> void ShapeConv<DDDBEllipticalTube>::convert(xml_h element, DDDBShape*& s) const;
0290     template <> void ShapeConv<DDDBTRD>::convert(xml_h element, DDDBShape*& s) const;
0291     template <> void ShapeConv<DDDBSphere>::convert(xml_h element, DDDBShape*& s) const;
0292     template <> void ShapeConv<DDDBBooleanShape>::convert(xml_h element, DDDBShape*& s) const;
0293     template <> void ShapeConv<DDDBBooleanUnion>::convert(xml_h element, DDDBShape*& s) const;
0294     template <> void ShapeConv<DDDBBooleanIntersection>::convert(xml_h element, DDDBShape*& s) const;
0295     template <> void ShapeConv<DDDBBooleanSubtraction>::convert(xml_h element, DDDBShape*& s) const;
0296     template <> void ShapeConv<DDDBBooleanOperation>::convert(xml_h element, DDDBShape*& ptr_shape) const;
0297 
0298     template <> void Conv<DDDBZPlane>::convert(xml_h element) const;
0299     template <> void Conv<dddb>::convert(xml_h element) const;
0300     template <> void Conv<DDDBLogVol>::convert(xml_h element) const;
0301     template <> void Conv<DDDBBlock>::convert(xml_h element) const;
0302     template <> void Conv<DDDBConfig>::convert(xml_h element) const;
0303     template <> void Conv<DDDBLogVolRef>::convert(xml_h element) const;
0304     template <> void Conv<DDDBPhysVol>::convert(xml_h element) const;
0305     template <> void Conv<DDDBParamPhysVol>::convert(xml_h element) const;
0306     template <> void Conv<DDDBParamPhysVol2D>::convert(xml_h element) const;
0307     template <> void Conv<DDDBParamPhysVol3D>::convert(xml_h element) const;
0308     template <> void Conv<DDDBConditionParam>::convert(xml_h element) const;
0309     template <> void Conv<Delta>::convert(xml_h element) const;
0310 
0311     template <> void Conv<Position>::convert(xml_h element) const;
0312     template <> void Conv<PositionRPhiZ>::convert(xml_h element) const;
0313     template <> void Conv<RotationZYX>::convert(xml_h element) const;
0314     template <> void Conv<Transform3D>::convert(xml_h element) const;
0315 
0316     void extract_transformation(Detector& description, void* context, xml_coll_t& collection, Transform3D& tr, int which=-1);
0317     void build_transformation(Detector& description, void* context, xml_h element, Transform3D& tr, int which=-1)   {
0318       xml_coll_t p(element,_U(star));
0319       extract_transformation(description,context,p,tr,which);
0320     }
0321     string reference_href(xml_h element, const string& ref);
0322 
0323     xml_h find_local_element(xml_elt_t element, const string& ref, const xml_tag_t& tag)  {
0324       size_t hash = ref.find("#");
0325       if ( hash == 0 )  {
0326         string name = ref.substr(1);
0327         xml_h  root = element.document().root();
0328         for(xml_coll_t coll(root,tag); coll; ++coll )  {
0329           string entry = coll.attr<string>(_U(name));
0330           if ( entry == name )  {
0331             return std::move(coll);
0332           }
0333         }
0334       }
0335       return xml_h(0);
0336     }
0337 
0338     string object_path(DDDBContext* context, const string& ref)  {
0339       size_t hash = ref.rfind("#");
0340       Path path = hash==0 ? ref.substr(1) : ref;
0341       if ( ref[0] != '/' )  {
0342         path = context->locals.obj_path;
0343         path /= (hash==0 ? ref.substr(1) : ref.substr(hash+1));
0344       }
0345       return path.normalize().native();
0346     }
0347     string object_href(xml_h element, const string& ref)   {
0348       string p = xml::DocumentHandler::system_path(element);
0349       Path path = p;
0350       p = path.normalize().native();
0351       p += '#';
0352       p += ref;
0353       return p;
0354     }
0355     string reference_path(DDDBContext* context, const string& ref)   {
0356       size_t hash = ref.rfind("#");
0357       size_t idx  = ref.find(":");
0358       size_t idq  = ref.find("/");
0359       Path path = hash==0 ? ref.substr(1) : ref;
0360       if ( (idx == string::npos || idq < idx) && ref[0] != '/' )  {
0361         path = context->locals.xml_doc->id;
0362         if ( hash != 0 ) path = path.parent_path();
0363         path /= ref.substr(0,hash);
0364       }
0365       return path.normalize().native();
0366     }
0367     void print_ref(const char* desc, DDDBContext* context, xml_h element, const string& ref, const string& opt="")  {
0368       size_t hash = ref.find("#");
0369       string path = reference_path(context,ref);
0370       string obj  = hash == string::npos ? ref : ref.substr(hash+1);
0371       string id1  = object_path(context,ref);
0372       string id2  = reference_href(element,ref);
0373       printout(INFO, desc, "** %s --> %s  path: %s # %s  %s", 
0374                id1.c_str(), id2.c_str(), path.c_str(), obj.c_str(), opt.c_str());
0375     }
0376 
0377     template <typename ACTION=dddb>
0378     void load_dddb_entity(DDDBContext*        context,
0379                           DDDBCatalog*    catalog,
0380                           xml_h           element,
0381                           const string&   ref,
0382                           bool            print=false);
0383 
0384     /// Helper to locate objects in a map using string identifiers
0385     template <typename Q> bool _find(const string& id, const Q& container)  {
0386       return container.find(id) != container.end();
0387     }
0388 
0389     bool checkParents(DDDBContext* context, DDDBCatalog* det)  {
0390       dddb* geo = context->geo;
0391       if ( det == geo->top )  {
0392         return true;
0393       }
0394       else if ( det )   {
0395         DDDBCatalog* par = 0;
0396         string parent_id  = det->support;
0397         dddb::Catalogs::const_iterator k = geo->catalogPaths.find(parent_id);
0398         if ( k != geo->catalogPaths.end() )  {
0399           par = (*k).second;
0400           par->catalogrefs[det->id] = det;
0401           return checkParents(context, par);
0402         }
0403         Path p(det->path);
0404         parent_id  = p.parent_path().native();
0405         if ( parent_id == "/" )  {
0406           return true;
0407         }
0408         k = geo->catalogPaths.find(parent_id);
0409         if ( k != geo->catalogPaths.end() )  {
0410           par = (*k).second;
0411           par->catalogrefs[det->id] = det;
0412           return checkParents(context, par);
0413         }
0414         printout(ERROR,"checkParents", "++ %s: NO PARENT Detector: '%s'!",
0415                  det->path.c_str(), parent_id.c_str());
0416       }
0417       return false;
0418     }
0419 
0420     void checkParents(DDDBContext* context)  {
0421       dddb* geo = context->geo;
0422       if ( context->check )  {
0423         for(dddb::Catalogs::iterator i=geo->catalogs.begin(); i!=geo->catalogs.end(); ++i)  {
0424           DDDBCatalog* det = (*i).second;
0425           checkParents(context,det);
0426         }
0427       }
0428     }
0429 
0430     void fixCatalogs(DDDBContext* context)  {
0431       dddb*       geo = context->geo;
0432       xml::UriReader* rdr = context->resolver;
0433       for(dddb::Catalogs::iterator i=geo->catalogs.begin(); i!=geo->catalogs.end(); ++i)  {
0434         DDDBCatalog* det = (*i).second;
0435         for(dddb::Catalogs::iterator j=det->catalogrefs.begin(); j!=det->catalogrefs.end(); ++j)  {
0436           const string& child_id = (*j).first;
0437           dddb::Catalogs::const_iterator k = geo->catalogs.find(child_id);
0438           if ( k == geo->catalogs.end() )   {
0439             if ( !rdr->isBlocked(child_id) )  {
0440               printout(ERROR,"fixCatalogs","++  MISSING ID: %s child:%s",det->id.c_str(),child_id.c_str());
0441             }
0442             continue;
0443           }
0444           DDDBCatalog* c = (*k).second;
0445           det->catalogs[c->name] = c;
0446           if ( 0 == (*j).second )  {
0447             (*j).second = c;
0448           }
0449         }
0450         for(dddb::Volumes::iterator j=det->logvolrefs.begin(); j!=det->logvolrefs.end(); ++j)  {
0451           DDDBLogVol* c = (*j).second;
0452           if ( !c )  {
0453             if ( !rdr->isBlocked(det->id) )  {
0454               printout(ERROR,"fixCatalogs","++  MISSING Volume: %s child:%s",det->id.c_str(),(*j).first.c_str());
0455             }
0456             continue;
0457           }
0458           dddb::Volumes::const_iterator k = geo->volumes.find(c->id);
0459           if ( k == geo->volumes.end() )   {
0460             if ( !rdr->isBlocked(det->id) )  {
0461               printout(ERROR,"fixCatalogs","++  MISSING VolID: %s child:%s",det->id.c_str(),c->id.c_str());
0462             }
0463           }
0464           det->logvols[c->name] = c;
0465           if ( 0 == (*j).second )  {
0466             (*j).second = c;
0467           }
0468         }
0469       }
0470     }
0471     string clean_cond_data(char pre, const string& data, char post)  {
0472       string d = pre+data+" ";
0473       size_t idx, idq;
0474       for(idx = d.find_first_not_of(' ',1); idx != string::npos;)  {
0475         if ( ::isspace(d[idx]) ) d[idx] = ' ';
0476         idx = d.find_first_not_of(' ',++idx);
0477       }
0478       for(idx = d.find_first_not_of(' ',1); idx != string::npos; ++idx)  {
0479         if ( d[idx] != ' ' && ::isspace(d[idx]) ) d[idx] = ' ';
0480         idq = d.find_first_of(' ',idx);
0481         if ( idq != string::npos )  {
0482           idx = d.find_first_not_of(' ',idq);
0483           if ( idx == string::npos ) break;
0484           if ( d[idx] != ' ' && ::isspace(d[idx]) ) d[idx] = ' ';
0485           d[idq] = ',';
0486           continue;
0487         }
0488         break;
0489       }
0490       d[d.length()-1] = post;
0491       return d;
0492     }
0493 
0494     /// Specialized conversion of <param/> entities
0495     template <> void Conv<DDDBConditionParam>::convert(xml_h element) const {
0496       string          nam = element.attr<string>(_U(name));
0497       string          typ = element.hasAttr(_U(type)) ? element.attr<string>(_U(type)) : string("int");
0498       string         data = element.text();
0499       pair<string,OpaqueDataBlock> block;
0500       block.first = nam;
0501       try {
0502         detail::OpaqueDataBinder::bind(detail::ValueBinder(), block.second, typ, data);
0503       }
0504       catch(...)  {
0505         pair<string,OpaqueDataBlock> block1;
0506         detail::OpaqueDataBinder::bind(detail::ValueBinder(), block1.second, typ, data);
0507       }
0508       ConditionParams* par = _option<ConditionParams>();
0509       pair<ConditionParams::iterator,bool> res = par->insert(block);
0510       if ( !res.second )  {
0511         printout(INFO,"ParamVector","++ Failed to insert condition parameter:%s",nam.c_str());
0512       }
0513     }
0514 
0515     /// Specialized conversion of <paramVector> entities
0516     template <> void Conv<DDDBConditionParamVector>::convert(xml_h element) const {
0517       string  nam = element.attr<string>(_U(name));
0518       string  typ = element.hasAttr(_U(type)) ? element.attr<string>(_U(type)) : string("int");
0519       string data = clean_cond_data('[',element.text(),']');
0520       ConditionParams* par = _option<ConditionParams>();
0521       pair<string,OpaqueDataBlock> block;
0522 
0523       block.first = nam;
0524       detail::OpaqueDataBinder::bind(detail::VectorBinder(), block.second, typ, data);
0525       pair<ConditionParams::iterator,bool> res = par->insert(block);
0526       if ( !res.second )  {
0527         printout(INFO,"ParamVector","++ Failed to insert condition parameter:%s",nam.c_str());
0528       }
0529     }
0530 
0531     /// Specialized conversion of <map/> conditions entities
0532     template <> void Conv<DDDBConditionParamMap>::convert(xml_h element) const {
0533       dddb_dim_t e = element;
0534       string nam = element.attr<string>(_U(name));
0535       string key_type = e.attr<string>(_LBU(keytype));
0536       string val_type = e.attr<string>(_LBU(valuetype));
0537       pair<string,OpaqueDataBlock> block;
0538       detail::MapBinder binder;
0539 
0540       block.first = nam;
0541       detail::OpaqueDataBinder::bind_map(binder,block.second, key_type, val_type);
0542       for(xml_coll_t i(e,_LBU(item)); i; ++i)  {
0543         string key = i.attr<string>(_LBU(key));
0544         string val = i.attr<string>(_LBU(value));
0545         detail::OpaqueDataBinder::insert_map(binder,block.second, key_type, key, val_type, val);
0546       }
0547       ConditionParams* par = _option<ConditionParams>();
0548       pair<ConditionParams::iterator,bool> res = par->insert(block);
0549       if ( !res.second )
0550         printout(INFO,"ParamMap","++ Failed to insert map-condition:%s",nam.c_str());
0551     }
0552 
0553     /// Specialized conversion of <specific/> conditions entities
0554     template <> void Conv<DDDBConditionParamSpecific>::convert(xml_h element) const {
0555       string nam = element.parent().attr<string>(_U(name));
0556       pair<string,OpaqueDataBlock> block;
0557       stringstream str;
0558 
0559       xml::dump_tree(element, str);
0560       block.second.bind<string>(str.str());
0561       block.first = nam;
0562 
0563       ConditionParams* par = _option<ConditionParams>();
0564       pair<ConditionParams::iterator,bool> res = par->insert(block);
0565       if ( !res.second )  {
0566         printout(INFO,"ParamVector","++ Failed to insert condition entry:%s of type <specific/>",nam.c_str());
0567       }
0568     }
0569 
0570     /// Specialized conversion of <param/> and <paramVector> entities in alignments
0571     template <> void Conv<Delta>::convert(xml_h element) const {
0572       string        nam = element.attr<string>(_U(name));
0573       string       data = clean_cond_data('(',element.text(),')');
0574       Delta* a = _option<Delta>();
0575       Position pos;
0576       const BasicGrammar& g = BasicGrammar::instance<Position>();
0577 
0578       if ( !g.fromString(&pos,data) ) g.invalidConversion(data, g.type());
0579       if ( nam == "dPosXYZ" )  {
0580         a->translation = pos/10.0;
0581         a->flags |= Delta::HAVE_TRANSLATION;
0582       }
0583       else if ( nam == "dRotXYZ" )   {
0584         a->rotation = RotationZYX(pos.z(),pos.y(),pos.x());
0585         a->flags |= Delta::HAVE_ROTATION;
0586       }
0587       else if ( nam == "pivotXYZ" )   {
0588         a->pivot = Translation3D(pos.x(),pos.y(),pos.z());
0589         a->flags |= Delta::HAVE_PIVOT;
0590       }
0591       else   {
0592         printout(ERROR,"Delta","++ Unknown alignment conditions tag: %s",nam.c_str());
0593       }
0594     }
0595 
0596     /// Specialized conversion of <condition/> entities
0597     template <> void Conv<Condition>::convert(xml_h element) const {
0598       DDDBContext*   context = _param<DDDBContext>();
0599       string     name    = element.attr<string>(_U(name));
0600       string     id      = object_href(element,name);
0601       if ( !_find(id, context->geo->conditions) )  {
0602         DDDBCatalog*   catalog = _option<DDDBCatalog>();
0603         DDDBDocument*  doc     = context->locals.xml_doc;
0604         string     path    = object_path(context,name);
0605         static int num_param=0, num_vector=0, num_map=0, num_spec=0, num_align=0;
0606         Condition cond(path,"DDDB");
0607         cond->address  = doc->name+"@"+id;
0608         cond->value    = path; // doc->name;
0609         cond->validity = "";
0610         cond->hash     = detail::hash64(path);
0611         if ( element.hasAttr(_U(comment)) )  {
0612           cond->comment = element.attr<string>(_U(comment));
0613         }
0614 #if 0
0615         if ( str_upper(path).find("/VP/") != string::npos )   {
0616           printout(ALWAYS,"Conditions","Loading condition: %s", path.c_str());
0617         }
0618 #endif
0619         
0620         int cls_id = -1;
0621         if ( element.hasAttr(_LBU(classID)) )  {
0622           cls_id = element.attr<int>(_LBU(classID));
0623         }
0624 #if 0
0625         if ( cls_id == AbstractMap::ALIGNMENT )   {
0626           Conv<Delta> conv(description,context,&cond.bind<Delta>());
0627           xml_coll_t(element,_LBU(paramVector)).for_each(conv);
0628           cond->setFlag(Condition::ALIGNMENT_DELTA);
0629           ++num_align;
0630         }
0631 #endif
0632         if ( cls_id == AbstractMap::ALIGNMENT || cls_id == 1008106 )   {
0633           AbstractMap& d = cond.bind<AbstractMap>();
0634           pair<string,OpaqueDataBlock>  block;
0635           Delta&  align = block.second.bind<Delta>();
0636           d.clientData = doc->addRef();
0637           d.classID    = cls_id;
0638           block.first  = align::Keys::deltaName;
0639 
0640           Conv<Delta> conv(description,context,&align);
0641           xml_coll_t(element,_LBU(paramVector)).for_each(conv);
0642           cond.setFlag(Condition::ALIGNMENT_DELTA);
0643           pair<ConditionParams::iterator,bool> res = d.params.insert(block);
0644           if ( !res.second )  {
0645             printout(INFO,"Condition",
0646                      "++ Failed to insert condition parameter:%s",
0647                      name.c_str());
0648           }
0649           if ( d.size() > 1 )  {
0650             printout(WARNING,"Condition",
0651                      "++ Found ALIGNMENT condition block with MULTIPLE entries [%d]: %s",
0652                      int(d.size()), name.c_str());
0653           }
0654           ++num_align;
0655         }
0656         else
0657         {
0658           AbstractMap& d = cond.bind<AbstractMap>();
0659           d.clientData = doc->addRef();
0660           d.classID    = cls_id;
0661 
0662           Conv<DDDBConditionParam>         object_cnv(description,context,&d.params);
0663           xml_coll_t(element,_U(param)).for_each(object_cnv);
0664 
0665           Conv<DDDBConditionParamVector>   vector_cnv(description,context,&d.params);
0666           xml_coll_t(element,_LBU(paramVector)).for_each(vector_cnv);
0667 
0668           Conv<DDDBConditionParamMap>      map_cnv(description,context,&d.params);
0669           xml_coll_t(element,_LBU(map)).for_each(map_cnv);
0670 
0671           Conv<DDDBConditionParamSpecific> specific_cnv(description,context,&d.params);
0672           xml_coll_t(element,_LBU(specific)).for_each(specific_cnv);
0673           for(xml_coll_t iter(element,_U(star)); iter; ++iter)  {
0674             string tag = iter.tag();
0675             string nam = iter.hasAttr(_U(name)) ? iter.attr<string>(_U(name)) : string();
0676             if ( context->printConfig.condition )  {
0677               printout(INFO,"ParamMap","++ Condition:%s -> %s",path.c_str(),nam.c_str());
0678             }
0679             if ( d.classID == AbstractMap::ALIGNMENT ) { continue; }
0680             if ( tag == "param"       )  { ++num_param;  continue; }
0681             if ( tag == "paramVector" )  { ++num_vector; continue; }
0682             if ( tag == "map"         )  { ++num_map;    continue; }
0683             if ( tag == "specific"    )  { ++num_spec;   continue; }
0684             printout(INFO,"Condition","++ Unknown conditions tag:%s obj:%s id:%s",
0685                      tag.c_str(), path.c_str(), id.c_str());
0686           }
0687           num_param += int(d.params.size());
0688         }
0689         context->collect(id, cond);
0690         if ( catalog )  {
0691           context->collectPath(path, cond);
0692         }
0693         if ( (context->geo->conditions.size()%500) == 0 )  {
0694           printout(INFO,"Condition","++ Processed %d conditions....last:%s Number of Params: %d Vec:%d Map:%d Spec:%d Align:%d", 
0695                    int(context->geo->conditions.size()), path.c_str(), num_param, num_vector, num_map, num_spec, num_align);
0696         }
0697       }
0698     }
0699 
0700     /// Specialized conversion of <conditionref/> entities
0701     template <> void Conv<DDDBConditionRef>::convert(xml_h element) const {
0702       DDDBContext* context = _param<DDDBContext>();
0703       DDDBCatalog* catalog = _option<DDDBCatalog>();
0704       string      href = element.attr<string>(_LBU(href));
0705       string     refid = reference_href(element,href);
0706       string      path;
0707 
0708       xml_h target = find_local_element(element, href, _LBU(condition));
0709       if ( target )
0710         Conv<Condition>(description,context,catalog)(target);
0711       else
0712         load_dddb_entity(context, catalog, element, href);
0713       dddb::Conditions::const_iterator i=context->geo->conditions.find(refid);
0714       if ( i == context->geo->conditions.end() )  {
0715         printout(ERROR,"ConditionRef","++  MISSING ID: %s Failed to convert ref:%s cat:%s",
0716                  refid.c_str(),path.c_str(), catalog ? catalog->path.c_str() : "???");
0717         if ( context->printConfig.condition_ref )  {
0718           print_ref("ConditionRef", context, element, href, "Path:----");
0719         }
0720         return;
0721       }
0722       Condition cond((*i).second);
0723       path = object_path(context,cond->name);
0724       context->collectPath(path, cond);
0725       if ( context->printConfig.condition_ref )  {
0726         print_ref("ConditionRef", context, element, href, "Path:"+path);
0727       }
0728     }
0729 
0730     /// Specialized conversion of <author/> entities
0731     template <> void Conv<DDDBAuthor>::convert(xml_h element) const {
0732       string* context = _option<string>();
0733       if ( element.hasAttr(_U(author)) ) *context = element.attr<string>(_U(author));
0734     }
0735 
0736     /// Specialized conversion of <version/> entities
0737     template <> void Conv<DDDBVersion>::convert(xml_h element) const {
0738       string* context = _option<string>();
0739       if ( element.hasAttr(_U(version)) ) *context = element.attr<string>(_U(version));
0740     }
0741 
0742     /// Specialized conversion of <param/> entities
0743     template <> void Conv<DDDBParam>::convert(xml_h element) const {
0744       DDDBCatalog* det   = _option<DDDBCatalog>();
0745       string   name  = element.attr<string>(_U(name));
0746       string   type  = element.hasAttr(_U(type)) ? element.attr<string>(_U(type)) : string("int");
0747       string   value = element.text();
0748       det->params[name] = make_pair(type,value);
0749     }
0750 
0751     /// Specialized conversion of <param/> entities
0752     template <> void Conv<DDDBBlock>::convert(xml_h element) const {
0753       DDDBContext* context = _param<DDDBContext>();
0754       context->resolver->blockPath(element.attr<string>(_U(name)));
0755     }
0756 
0757     /// Specialized conversion of <param/> entities
0758     template <> void Conv<DDDBConfig>::convert(xml_h element) const {
0759       xml_dim_t e = element;
0760       if ( e.hasAttr(_U(type)) && e.attr<string>(_U(type)) != "CondDB2DDDB" )   {
0761         return;
0762       }
0763       if ( !e.hasAttr(_U(type)) || e.attr<string>(_U(type)) != "CondDB2DDDB" )   {
0764         CondDB2Objects::PrintConfig& cfg = s_config.printConfig; //_param<DDDBContext>();
0765         for(xml_coll_t c(element,_U(param)); c; ++c)   {
0766           xml_dim_t p = c;
0767           if ( p.nameStr() == "print_file_load" )
0768             cfg.file_load = p.attr<bool>(_U(value));
0769           else if ( p.nameStr() == "print_xml" )
0770             cfg.xml = p.attr<bool>(_U(value));
0771           else if ( p.nameStr() == "print_docs" )
0772             cfg.docs = p.attr<bool>(_U(value));
0773           else if ( p.nameStr() == "print_materials" )
0774             cfg.materials = p.attr<bool>(_U(value));
0775           else if ( p.nameStr() == "print_logvol" )
0776             cfg.logvol = p.attr<bool>(_U(value));
0777           else if ( p.nameStr() == "print_shapes" )
0778             cfg.shapes = p.attr<bool>(_U(value));
0779           else if ( p.nameStr() == "print_physvol" )
0780             cfg.physvol = p.attr<bool>(_U(value));
0781           else if ( p.nameStr() == "print_params" )
0782             cfg.params = p.attr<bool>(_U(value));
0783           else if ( p.nameStr() == "print_detelem" )
0784             cfg.detelem = p.attr<bool>(_U(value));
0785           else if ( p.nameStr() == "print_detelem_ref" )
0786             cfg.detelem_ref = p.attr<bool>(_U(value));
0787           else if ( p.nameStr() == "print_detelem_xml" )
0788             cfg.detelem_xml = p.attr<bool>(_U(value));
0789           else if ( p.nameStr() == "print_condition" )
0790             cfg.condition = p.attr<bool>(_U(value));
0791           else if ( p.nameStr() == "print_condition_ref" )
0792             cfg.condition_ref = p.attr<bool>(_U(value));
0793           else if ( p.nameStr() == "print_catalog" )
0794             cfg.catalog = p.attr<bool>(_U(value));
0795           else if ( p.nameStr() == "print_catalog_ref" )
0796             cfg.catalog_ref = p.attr<bool>(_U(value));
0797           else if ( p.nameStr() == "print_tabprop" )
0798             cfg.tabprop = p.attr<bool>(_U(value));
0799           else if ( p.nameStr() == "print_tree_on_error" )
0800             cfg.tree_on_error = p.attr<bool>(_U(value));
0801           else if ( p.nameStr() == "print_eval_error" )
0802             cfg.eval_error = p.attr<bool>(_U(value));
0803         }
0804       }
0805       else if ( e.attr<string>(_U(type)) != "DDDB2Objects" )   {
0806         DDDB2Objects::PrintConfig& cfg = DDDB2Objects::PrintConfig::instance();
0807         for(xml_coll_t c(element,_U(param)); c; ++c)   {
0808           xml_dim_t p = c;
0809           if ( p.nameStr() == "print_materials" )
0810             cfg.materials = p.attr<bool>(_U(value));
0811           else if ( p.nameStr() == "print_logvol" )
0812             cfg.logvol = p.attr<bool>(_U(value));
0813           else if ( p.nameStr() == "print_shapes" )
0814             cfg.shapes = p.attr<bool>(_U(value));
0815           else if ( p.nameStr() == "print_physvol" )
0816             cfg.physvol = p.attr<bool>(_U(value));
0817           else if ( p.nameStr() == "print_params" )
0818             cfg.params = p.attr<bool>(_U(value));
0819           else if ( p.nameStr() == "print_detelem" )
0820             cfg.detelem = p.attr<bool>(_U(value));
0821           else if ( p.nameStr() == "print_condition" )
0822             cfg.condition = p.attr<bool>(_U(value));
0823           else if ( p.nameStr() == "print_vis" )
0824             cfg.vis = p.attr<bool>(_U(value));
0825           else if ( p.nameStr() == "max_volume_depth" )
0826             cfg.max_volume_depth = p.attr<int>(_U(value));
0827         }
0828       }
0829     }
0830     
0831     /// Specialized conversion of <ConditionInfo/> entities
0832     template <> void Conv<DDDBConditionInfo>::convert(xml_h element) const {
0833       DDDBCatalog* det  = _option<DDDBCatalog>();
0834       string   name = element.attr<string>(_U(name));
0835       string   cond = element.attr<string>(_LBU(condition));
0836       det->conditioninfo[name] = cond;
0837     }
0838 
0839     /// Specialized conversion of <isotope/> entities
0840     template <> void Conv<DDDBIsotope>::convert(xml_h element) const {
0841       DDDBContext* context = _param<DDDBContext>();
0842       dddb_dim_t x_i = element;
0843       string name = x_i.nameStr();
0844       string id = object_path(context,name);
0845       if ( !_find(id, context->geo->isotopes) )  {
0846         DDDBIsotope* i = new DDDBIsotope();
0847         i->name       = name;
0848         i->A          = x_i.A(-1.0);
0849         i->Z          = x_i.Z(-1.0);
0850         i->density    = x_i.density(-1.0);
0851         context->collect(id, i);
0852         i->setDocument(context->locals.xml_doc);
0853       }
0854     }
0855 
0856     /// Specialized conversion of <elementref/> entities
0857     template <> void Conv<DDDBElementRef>::convert(xml_h element) const {
0858       DDDBContext* context = _param<DDDBContext>();
0859       DDDBCatalog* catalog = _option<DDDBCatalog>();
0860       string      href = element.attr<string>(_LBU(href));
0861       string     refid = reference_href(element,href);
0862       load_dddb_entity(context, catalog, element, href);
0863       dddb::Elements::const_iterator i=context->geo->elements.find(refid);
0864       if ( i == context->geo->elements.end() )  {
0865         printout(ERROR,"ElementRef","++  MISSING ID: %s Failed to convert ref:%s",refid.c_str(),href.c_str());
0866       }
0867       DDDBElement* e = (*i).second;
0868       string path = object_path(context,e->name);
0869       context->collectPath(path, e);
0870     }
0871 
0872     /// Specialized conversion of <element/> entities
0873     template <> void Conv<DDDBElement>::convert(xml_h element) const {
0874       DDDBContext* context = _param<DDDBContext>();
0875       dddb_dim_t x_elem = element;
0876       string       name = x_elem.nameStr();
0877       string         id = object_href(element, name);
0878       if ( !_find(id, context->geo->elements) )  {
0879         DDDBElement* e = new DDDBElement();
0880         dddb_dim_t atom = x_elem.child(_U(atom),false);
0881         e->id         = id;
0882         e->name       = name;
0883         e->path       = object_path(context,name);
0884         e->density    = x_elem.density(-1.0);
0885         e->ionization = x_elem.I(-1.0);
0886         e->symbol     = x_elem.symbol(e->name);
0887         e->atom.A     = atom ? atom.attr<double>(_U(A)) : -1.0;
0888         e->atom.Zeff  = atom ? atom.attr<double>(_U(Zeff)) : -1.0;
0889         string st = x_elem.state();
0890         if      ( st == "solid"  ) e->state = DDDBElement::SOLID;
0891         else if ( st == "liquid" ) e->state = DDDBElement::LIQUID;
0892         else if ( st == "gas"    ) e->state = DDDBElement::GAS;
0893         else                       e->state = DDDBElement::UNKNOWN;
0894 
0895         for(xml_coll_t p(x_elem,_LBU(isotoperef)); p; ++p)   {
0896           dddb_dim_t isotope = p;
0897           double frac   = isotope.fractionmass(1.0);
0898           string iso_id = object_path(context,isotope.href());
0899           e->isotopes.push_back(make_pair(iso_id,frac));
0900         }
0901         context->collect(e->id, e);
0902         context->collectPath(e->path, e);
0903         e->setDocument(context->locals.xml_doc);
0904       }
0905     }
0906 
0907     /// Specialized conversion of <material><component/></material> entities
0908     template <> void Conv<DDDBMaterialComponent>::convert(xml_h element) const {
0909       DDDBMaterial* m = _option<DDDBMaterial>();
0910       dddb_dim_t x_mat = element;
0911       m->components.push_back(DDDBMaterialComponent());
0912       DDDBMaterialComponent& c = m->components.back();
0913       c.name = x_mat.nameStr();
0914       c.natoms = x_mat.natoms(1);
0915       c.fractionmass = x_mat.fractionmass(1.0);
0916     }
0917 
0918     /// Specialized conversion of <materialref/> entities
0919     template <> void Conv<DDDBMaterialRef>::convert(xml_h element) const {
0920       DDDBContext*  context = _param<DDDBContext>();
0921       DDDBCatalog*  catalog = _option<DDDBCatalog>();
0922       string       href = element.attr<string>(_LBU(href));
0923       string      refid = reference_href(element,href);
0924       load_dddb_entity(context, catalog, element, href);
0925       dddb::Materials::const_iterator i=context->geo->materials.find(refid);
0926       if ( i == context->geo->materials.end() )  {
0927         printout(ERROR,"MaterialRef","++  MISSING ID: %s Failed to convert ref:%s",refid.c_str(),href.c_str());
0928       }
0929       else if ( catalog )  {
0930         DDDBMaterial* m = (*i).second;
0931         string path = object_path(context,m->name);
0932         context->collectPath(path, m);
0933       }
0934     }
0935 
0936     /// Specialized conversion of <material/> entities
0937     template <> void Conv<DDDBMaterial>::convert(xml_h element) const {
0938       DDDBContext* context = _param<DDDBContext>();
0939       DDDBCatalog* catalog = _option<DDDBCatalog>();
0940       dddb_dim_t x_mat = element;
0941       string      name = x_mat.nameStr();
0942       string        id = object_href(element, name);
0943       if ( !_find(id, context->geo->materials) )  {
0944         DDDBMaterial* m    = new DDDBMaterial();
0945         m->name        = name;
0946         m->id          = id;
0947         m->path        = object_path(context,name);
0948         m->density     = x_mat.density(-1.0);
0949         m->pressure    = x_mat.pressure(-1.0);
0950         m->temperature = x_mat.temperature(-1.0);
0951         m->radlen      = x_mat.radlen(-1.0);
0952         m->lambda      = x_mat.lambda(-1.0);
0953         for(xml_coll_t p(element,_LBU(tabprops)); p; ++p)
0954           m->properties.push_back(p.attr<string>(_LBU(address)));
0955 
0956         xml_coll_t(element, _U(component)).for_each(Conv<DDDBMaterialComponent>(description,context,m));
0957         context->collect(m->id, m); // We collect materials by NAME!!!
0958         context->collect(m->name, m);
0959         m->setDocument(context->locals.xml_doc);
0960         if ( catalog ) context->collectPath(m->path, m);
0961       }
0962     }
0963 
0964     /// Specialized conversion of <geometryinfo/> entities
0965     template <> void Conv<DDDBGeometryInfo>::convert(xml_h element) const {
0966       DDDBCatalog* context = _option<DDDBCatalog>();
0967       context->logvol   = element.attr<string>(_LBU(lvname));
0968       if ( element.hasAttr(_LBU(npath)) ) context->npath = element.attr<string>(_LBU(npath));
0969       if ( element.hasAttr(_LBU(support)) ) context->support = element.attr<string>(_LBU(support));
0970       if ( element.hasAttr(_LBU(condition)) ) context->condition = element.attr<string>(_LBU(condition));
0971     }
0972 
0973     /// Specialized conversion of <posXYZ/> entities
0974     template <> void Conv<Position>::convert(xml_h element) const {
0975       dddb_dim_t dim = element;
0976       Position*  pos = _option<Position>();
0977       pos->SetXYZ(dim.x(0.0), dim.y(0.0), dim.z(0.0));
0978       //dddb_print(p);
0979     }
0980 
0981     /// Specialized conversion of <posRPhiZ/> entities
0982     template <> void Conv<PositionRPhiZ>::convert(xml_h element) const {
0983       dddb_dim_t dim = element;
0984       ROOT::Math::Polar2D<double> dim2(dim.r(0.0), dim.phi(0.0));
0985       Position*  pos = _option<Position>();
0986       pos->SetXYZ(dim2.X(), dim2.Y(), dim.z(0.0));
0987       //dddb_print(p);
0988     }
0989 
0990     /// Specialized conversion of <rotXYZ/> entities
0991     template <> void Conv<RotationZYX>::convert(xml_h element) const {
0992       dddb_dim_t   dim = element;
0993       RotationZYX* rot = _option<RotationZYX>();
0994       rot->SetComponents(dim.rotZ(0.0), dim.rotY(0.0), dim.rotX(0.0));
0995       //dddb_print(p);
0996     }
0997 
0998     /// Specialized conversion of <transformation/> entities
0999     template <> void Conv<Transform3D>::convert(xml_h element) const {
1000       Transform3D* tr = _option<Transform3D>();
1001       build_transformation(description, param, element, *tr);
1002       //dddb_print(tr);
1003     }
1004 
1005     /// Specialized conversion of <zplane/> entities
1006     template <> void Conv<DDDBZPlane>::convert(xml_h element) const {
1007       DDDBShape* s = _param<DDDBShape>();
1008       dddb_dim_t dim = element;
1009       DDDBZPlane plane;
1010       plane.innerRadius = dim.innerRadius(0.0);
1011       plane.outerRadius = dim.outerRadius(0.0);
1012       plane.z = dim.z(0.0);
1013       s->zplanes.push_back(plane);
1014     }
1015 
1016     /// Specialized common shape conversion
1017     template <> void ShapeConv<DDDBShape>::convert(xml_h element, DDDBShape*& s) const {
1018       DDDBContext* context = _param<DDDBContext>();
1019       xml_dim_t dim = element;
1020       s = new DDDBShape;
1021       s->name = dim.nameStr();
1022       s->path = object_path(context, s->name);
1023     }
1024 
1025     /// Specialized conversion of assemblies (logical volumes without shapes)
1026     template <> void ShapeConv<DDDBAssembly>::convert(xml_h , DDDBShape*& s) const {
1027       s = new DDDBShape();
1028       s->name = "assembly";
1029       s->type = to_type::type();
1030     }
1031 
1032     /// Specialized conversion of Box shapes
1033     template <> void ShapeConv<DDDBBox>::convert(xml_h element, DDDBShape*& s) const {
1034       ShapeConv<DDDBShape>(description,param)(element,s);
1035       dddb_dim_t dim = element;
1036       s->type = to_type::type();
1037       s->s.box.x = dim.sizeX(0.0)/2e0;
1038       s->s.box.y = dim.sizeY(0.0)/2e0;
1039       s->s.box.z = dim.sizeZ(0.0)/2e0;
1040     }
1041 
1042     /// Specialized conversion of Cons shapes
1043     template <> void ShapeConv<DDDBCons>::convert(xml_h element, DDDBShape*& s) const {
1044       dddb_dim_t dim = element;
1045       ShapeConv<DDDBShape>(description,param)(element,s);
1046       s->type = to_type::type();
1047       s->s.cons.innerRadiusMZ = dim.innerRadiusMZ(0.0);
1048       s->s.cons.innerRadiusPZ = dim.innerRadiusPZ(0.0);
1049       s->s.cons.outerRadiusMZ = dim.outerRadiusMZ(0.0);
1050       s->s.cons.outerRadiusPZ = dim.outerRadiusPZ(0.0);
1051       s->s.cons.sizeZ         = dim.sizeZ(0.0)/2e0;
1052     }
1053 
1054     /// Specialized conversion of ConeSegment shapes
1055     template <> void ShapeConv<DDDBConeSegment>::convert(xml_h element, DDDBShape*& s) const {
1056       dddb_dim_t dim = element;
1057       ShapeConv<DDDBShape>(description,param)(element,s);
1058       s->type = to_type::type();
1059       s->s.coneSegment.start         = dim.startPhiAngle(0.0);
1060       s->s.coneSegment.delta         = dim.deltaPhiAngle(2.0*M_PI);
1061       s->s.coneSegment.innerRadiusMZ = dim.innerRadiusMZ(0.0);
1062       s->s.coneSegment.innerRadiusPZ = dim.innerRadiusPZ(0.0);
1063       s->s.coneSegment.outerRadiusMZ = dim.outerRadiusMZ(0.0);
1064       s->s.coneSegment.outerRadiusPZ = dim.outerRadiusPZ(0.0);
1065       s->s.coneSegment.sizeZ = dim.sizeZ(0.0)/2e0;
1066     }
1067 
1068     /// Specialized conversion of Tubs shapes
1069     template <> void ShapeConv<DDDBTubs>::convert(xml_h element, DDDBShape*& s) const {
1070       dddb_dim_t dim = element;
1071       ShapeConv<DDDBShape>(description,param)(element,s);
1072       s->type = to_type::type();
1073       s->s.tubs.start       = dim.startPhiAngle(0.0);
1074       s->s.tubs.delta       = dim.deltaPhiAngle(2.0*M_PI);
1075       s->s.tubs.innerRadius = dim.innerRadius(0.0);
1076       s->s.tubs.outerRadius = dim.outerRadius(0.0);
1077       s->s.tubs.sizeZ       = dim.sizeZ(0.0)/2e0;
1078     }
1079 
1080     /// Specialized conversion of Trap shapes
1081     template <> void ShapeConv<DDDBTrap>::convert(xml_h element, DDDBShape*& s) const {
1082       dddb_dim_t dim = element;
1083       ShapeConv<DDDBShape>(description,param)(element,s);
1084       if ( s->name == "Cut_out_right" )  {
1085         s->type = to_type::type();
1086       }
1087       s->type = to_type::type();
1088       s->s.trap.dz     = dim.sizeZ()/2e0;
1089       s->s.trap.phi    = dim.phiAngle(0);
1090       s->s.trap.theta  = dim.thetaAngle(0);
1091       s->s.trap.h1     = dim.sizeY1(0)/2e0;
1092       s->s.trap.bl1    = dim.sizeX1(0)/2e0;
1093       s->s.trap.tl1    = dim.sizeX2(0)/2e0;
1094       s->s.trap.alpha1 = dim.alp1(0);
1095       s->s.trap.h2     = dim.sizeY2(0)/2e0;
1096       s->s.trap.bl2    = dim.sizeX3(0)/2e0;
1097       s->s.trap.tl2    = dim.sizeX4(0)/2e0;
1098       s->s.trap.alpha2 = dim.alp2(0);
1099     }
1100 
1101     /// Specialized conversion of Polycone shapes
1102     template <> void ShapeConv<DDDBPolycone>::convert(xml_h element, DDDBShape*& s) const {
1103       dddb_dim_t dim = element;
1104       ShapeConv<DDDBShape>(description,param)(element,s);
1105       s->type = to_type::type();
1106       s->s.polycone.start = dim.startPhiAngle(0.0);
1107       s->s.polycone.delta = dim.deltaPhiAngle(2.0*M_PI);
1108       xml_coll_t(element, _U(zplane)).for_each(Conv<DDDBZPlane>(description,s));
1109     }
1110 
1111     /// Specialized conversion of Polygon shapes
1112     template <> void ShapeConv<DDDBPolygon>::convert(xml_h element, DDDBShape*& s) const {
1113       dddb_dim_t dim = element;
1114       ShapeConv<DDDBShape>(description,param)(element,s);
1115       s->type = to_type::type();
1116       s->s.polygon.z      = dim.z();
1117       s->s.polygon.start  = dim.start(0.0);
1118       s->s.polygon.nsides = dim.nsides();
1119       s->s.polygon.innerRadius = dim.innerRadius(0.0);
1120       s->s.polygon.outerRadius = dim.outerRadius(0.0);
1121       xml_coll_t(element, _U(zplane)).for_each(Conv<DDDBZPlane>(description,s));
1122     }
1123 
1124     /// Specialized conversion of EllipticalTube shapes
1125     template <> void ShapeConv<DDDBEllipticalTube>::convert(xml_h element, DDDBShape*& s) const {
1126       dddb_dim_t dim = element;
1127       ShapeConv<DDDBShape>(description,param)(element,s);
1128       s->type = to_type::type();
1129       s->s.ellipticalTube.a  = dim.a();
1130       s->s.ellipticalTube.b  = dim.b();
1131       s->s.ellipticalTube.dz = dim.dz();
1132     }
1133 
1134     /// Specialized conversion of EllipticalTube shapes
1135     template <> void ShapeConv<DDDBTRD>::convert(xml_h element, DDDBShape*& s) const {
1136       dddb_dim_t dim = element;
1137       ShapeConv<DDDBShape>(description,param)(element,s);
1138       s->type = to_type::type();
1139       s->s.trd.x1 = dim.sizeX1()/2e0;
1140       s->s.trd.x2 = dim.sizeX2()/2e0;
1141       s->s.trd.y1 = dim.sizeY1()/2e0;
1142       s->s.trd.y2 = dim.sizeY2()/2e0;
1143       s->s.trd.z  = dim.sizeZ()/2e0;
1144     }
1145 
1146     /// Specialized conversion of EllipticalTube shapes
1147     template <> void ShapeConv<DDDBSphere>::convert(xml_h element, DDDBShape*& s) const {
1148       dddb_dim_t dim = element;
1149       ShapeConv<DDDBShape>(description,param)(element,s);
1150       s->type = to_type::type();
1151       s->s.sphere.rmin        = dim.innerRadius(0);
1152       s->s.sphere.rmax        = dim.outerRadius(0);
1153       s->s.sphere.theta       = dim.startThetaAngle(0);
1154       s->s.sphere.delta_theta = dim.deltaThetaAngle(2.0*M_PI);
1155       s->s.sphere.phi         = dim.startPhiAngle(0);
1156       s->s.sphere.delta_phi   = dim.deltaPhiAngle(2.0*M_PI);
1157     }
1158 
1159     /// Specialized common conversion of boolean shapes
1160     template <> void ShapeConv<DDDBBooleanShape>::convert(xml_h element, DDDBShape*& s) const {
1161       ShapeConv<DDDBShape>(description,param)(element,s);
1162       DDDBContext* context = _param<DDDBContext>();
1163       string        id = object_path(context,s->name);
1164       DDDBContext::PreservedLocals locals(context);
1165       context->locals.obj_path = id;
1166       s->s.boolean.first = 0;
1167       for(xml_coll_t p(element,_U(star)); p; ++p)  {
1168         if ( p.parent() == element ) { // Only next level is processed here
1169           if ( 0 == s->s.boolean.first )  {
1170             ShapeConv<DDDBBooleanOperation>(description,context)(p,s->s.boolean.first);
1171             s->s.boolean.first->id = id + "/" + s->s.boolean.first->name;
1172             ++p;
1173           }
1174           DDDBBooleanOperation op;
1175           ShapeConv<DDDBBooleanOperation>(description,context)(p,op.shape);
1176           if ( 0 == op.shape )  {
1177             // Error. What to do? 
1178             // Anyhow: ShapeConv<BooleanOperation> throws exception if the
1179             //         shape is unknown. We never get here.
1180             printout(ERROR,"ShapeConv","++ Invalid boolean shape operation. [Invalid operand]");
1181             continue;
1182           }
1183           op.shape->id = id + "/" + op.shape->name;
1184           ++p;
1185           extract_transformation(description, param, p, op.trafo);
1186           s->boolean_ops.push_back(op);
1187         }
1188       }
1189     }
1190 
1191     /// Specialized conversion of boolean union shapes
1192     template <> void ShapeConv<DDDBBooleanUnion>::convert(xml_h element, DDDBShape*& s) const {
1193       ShapeConv<DDDBBooleanShape>(description,param)(element,s);
1194       s->type = to_type::type();
1195     }
1196 
1197     /// Specialized conversion of boolean intersection shapes
1198     template <> void ShapeConv<DDDBBooleanIntersection>::convert(xml_h element, DDDBShape*& s) const {
1199       ShapeConv<DDDBBooleanShape>(description,param)(element,s);
1200       s->type = to_type::type();
1201     }
1202 
1203     /// Specialized conversion of boolean subtraction shapes
1204     template <> void ShapeConv<DDDBBooleanSubtraction>::convert(xml_h element, DDDBShape*& s) const {
1205       ShapeConv<DDDBBooleanShape>(description,param)(element,s);
1206       s->type = to_type::type();
1207     }
1208 
1209     /// Specialized conversion of boolean operations
1210     template <> void ShapeConv<DDDBBooleanOperation>::convert(xml_h element, DDDBShape*& s) const {
1211       xml_h elt = element;
1212       string tag = element.tag();
1213       DDDBContext* context = _param<DDDBContext>();
1214 
1215       // Now convert all possible / supported shapes
1216       if ( tag == "box" )
1217         ShapeConv<DDDBBox>(description,context)(elt,s);
1218       else if ( tag == "cons" )
1219         ShapeConv<DDDBCons>(description,context)(elt,s);
1220       else if ( tag == "tubs" )
1221         ShapeConv<DDDBTubs>(description,context)(elt,s);
1222       else if ( tag == "trap" )
1223         ShapeConv<DDDBTrap>(description,context)(elt,s);
1224       else if ( tag == "polycone" )
1225         ShapeConv<DDDBPolycone>(description,context)(elt,s);
1226       else if ( tag == "polygon" )
1227         ShapeConv<DDDBPolygon>(description,context)(elt,s);
1228       else if ( tag == "trd" )
1229         ShapeConv<DDDBTRD>(description,context)(elt,s);
1230       else if ( tag == "eltu" )
1231         ShapeConv<DDDBEllipticalTube>(description,context)(elt,s);
1232       else if ( tag == "sphere" )
1233         ShapeConv<DDDBSphere>(description,context)(elt,s);
1234       else if ( tag == "union" )
1235         ShapeConv<DDDBBooleanUnion>(description,context)(elt,s);
1236       else if ( tag == "subtraction" )
1237         ShapeConv<DDDBBooleanSubtraction>(description,context)(elt,s);
1238       else if ( tag == "intersection" )
1239         ShapeConv<DDDBBooleanIntersection>(description,context)(elt,s);
1240       else   {
1241         xml::dump_tree(element.parent());
1242         except("BooleanOperation","Unknown shape conversion requested:"+tag);
1243       }
1244     }
1245 
1246     /// Specialized conversion of <logvolref/> entities
1247     template <> void Conv<DDDBLogVolRef>::convert(xml_h element) const {
1248       DDDBContext* context = _param<DDDBContext>();
1249       DDDBCatalog* catalog = _option<DDDBCatalog>();
1250       string      href = element.attr<string>(_LBU(href));
1251       string     refid = reference_href(element,href);
1252 
1253       load_dddb_entity(context, catalog, element, href);
1254       dddb::Volumes::const_iterator i=context->geo->volumes.find(refid);
1255       if ( i == context->geo->volumes.end() )  {
1256         string r = reference_href(element,href);
1257         printout(ERROR,"LogVolRef","++  MISSING ID: %s Failed to convert ref:%s",refid.c_str(),href.c_str());
1258       }
1259       DDDBLogVol* vol = (*i).second;
1260       catalog->logvolrefs[vol->id] = vol;
1261       string path = object_path(context,vol->name);
1262       context->collectPath(path, vol);
1263       if ( context->printConfig.logvol )  {
1264         print_ref("LogVolRef", context, element, href, "Path:"+path);
1265       }
1266     }
1267 
1268     /// Specialized conversion of <logvol/> entities
1269     template <> void Conv<DDDBLogVol>::convert(xml_h element) const {
1270       DDDBContext* context = _param<DDDBContext>();
1271       string   name    = element.attr<string>(_U(name));
1272       string   id      = object_href(element, name);
1273       if ( !_find(id, context->geo->volumes) )  {
1274         DDDBCatalog* catalog = _option<DDDBCatalog>();
1275         string   material;
1276         DDDBLogVol* vol = new DDDBLogVol;
1277         xml_h elt;
1278         vol->name = name;
1279         vol->path = object_path(context,name);
1280         if ( element.hasAttr(_U(material)) )  {
1281           vol->material = element.attr<string>(_U(material));
1282         }
1283         DDDBShape* s = 0;
1284         // Now convert all possible / supported shapes
1285         if ( (elt=element.child(_U(box),false)) )
1286           ShapeConv<DDDBBox>(description,context)(elt,s);
1287         else if ( (elt=element.child(_U(cons),false)) )
1288           ShapeConv<DDDBCons>(description,context)(elt,s);
1289         else if ( (elt=element.child(_U(tubs),false)) )
1290           ShapeConv<DDDBTubs>(description,context)(elt,s);
1291         else if ( (elt=element.child(_U(trap),false)) )
1292           ShapeConv<DDDBTrap>(description,context)(elt,s);
1293         else if ( (elt=element.child(_U(trd),false)) )
1294           ShapeConv<DDDBTRD>(description,context)(elt,s);
1295         else if ( (elt=element.child(_U(polycone),false)) )
1296           ShapeConv<DDDBPolycone>(description,context)(elt,s);
1297         else if ( (elt=element.child(_U(sphere),false)) )
1298           ShapeConv<DDDBSphere>(description,context)(elt,s);
1299         else if ( (elt=element.child(_U(union),false)) )
1300           ShapeConv<DDDBBooleanUnion>(description,context)(elt,s);
1301         else if ( (elt=element.child(_U(subtraction),false)) )
1302           ShapeConv<DDDBBooleanSubtraction>(description,context)(elt,s);
1303         else if ( (elt=element.child(_U(intersection),false)) )
1304           ShapeConv<DDDBBooleanIntersection>(description,context)(elt,s);
1305         else  {
1306           ShapeConv<DDDBAssembly>(description,context)(elt,s);
1307           // Dump element if not known and processed....
1308           for(xml_coll_t p(element,_U(star)); p; ++p)  {
1309             if ( p.parent() == element )  {
1310               string tag = p.tag();
1311               if ( tag == "physvol" ) continue;
1312               if ( tag == "paramphysvol" ) continue;
1313               if ( tag == "paramphysvol2D" ) continue;
1314               if ( tag == "paramphysvol3D" ) continue;
1315               printout(WARNING,"LogVol","++ Unknown and not processed tag found: %s",tag.c_str());
1316               xml::dump_tree(element);
1317               break;
1318             }
1319           }
1320         }
1321         // Now collect the information
1322         vol->shape = id;
1323         s->setDocument(context->locals.xml_doc);
1324         vol->setDocument(context->locals.xml_doc);
1325         context->collect(id, s);
1326         context->collect(id, vol);
1327         if ( catalog ) context->collectPath(vol->path, vol);
1328         {
1329           DDDBContext::PreservedLocals locals(context);
1330           context->locals.obj_path = id;
1331           xml_coll_t(element, _U(physvol)).for_each(Conv<DDDBPhysVol>(description,context,vol));
1332           xml_coll_t(element, _LBU(paramphysvol)).for_each(Conv<DDDBParamPhysVol>(description,context,vol));
1333           xml_coll_t(element, _LBU(paramphysvol2D)).for_each(Conv<DDDBParamPhysVol2D>(description,context,vol));
1334           xml_coll_t(element, _LBU(paramphysvol3D)).for_each(Conv<DDDBParamPhysVol3D>(description,context,vol));
1335         }
1336       }
1337     }
1338 
1339     /// Specialized conversion of <physvol/> entities
1340     template <> void Conv<DDDBPhysVol>::fill(xml_h element, DDDBPhysVol* pv) const {
1341       xml_h      elt;
1342       dddb_dim_t x_vol   = element;
1343       string     name    = x_vol.nameStr();
1344       DDDBContext*   context = _param<DDDBContext>();
1345 
1346       pv->name   = name;
1347       pv->logvol = x_vol.logvol();
1348       pv->path   = object_path(context,name);
1349       build_transformation(description, param, element, pv->trafo, -1);
1350     }
1351     template <> void Conv<DDDBPhysVol>::convert(xml_h element) const {
1352       DDDBContext* context = _param<DDDBContext>();
1353       dddb_dim_t x_vol = element;
1354       string   name    = x_vol.nameStr();
1355       string   id      = object_href(element, name);
1356       if ( !_find(id, context->geo->placements) )  {
1357         DDDBPhysVol* vol = new DDDBPhysVol();
1358         this->fill(element, vol);
1359         context->collect(id, vol);
1360         context->collectPath(vol->path,vol);
1361         vol->setDocument(context->locals.xml_doc);
1362         if ( optional )  {
1363           _option<DDDBLogVol>()->physvols.push_back(vol);
1364         }
1365       }
1366     }
1367 
1368     /// Specialized conversion of EllipticalTube shapes
1369     template <> void Conv<DDDBParamPhysVol>::fill(xml_h element, DDDBParamPhysVol* pv) const {
1370       dddb_dim_t x_pv = element.child(_U(physvol));
1371       dddb_dim_t elt = element;
1372       Conv<DDDBPhysVol>(description,param).fill(x_pv, pv);
1373       pv->number1 = elt.number(0);
1374       build_transformation(description, param, element, pv->trafo1, 0);
1375     }
1376     template <> void Conv<DDDBParamPhysVol>::convert(xml_h element) const {
1377       DDDBParamPhysVol* pv = new DDDBParamPhysVol();
1378       this->fill(element, pv);
1379       _option<DDDBLogVol>()->physvols.push_back(pv);
1380     }
1381 
1382     /// Specialized conversion of EllipticalTube shapes
1383     template <> void Conv<DDDBParamPhysVol2D>::fill(xml_h element, DDDBParamPhysVol2D* pv) const {
1384       dddb_dim_t elt = element;
1385       Conv<DDDBParamPhysVol>(description,param).fill(element, pv);
1386       pv->number1 = elt.number1();
1387       pv->number2 = elt.number2();
1388       build_transformation(description, param, element, pv->trafo2, 1);
1389     }
1390     template <> void Conv<DDDBParamPhysVol2D>::convert(xml_h element) const {
1391       DDDBParamPhysVol2D* pv = new DDDBParamPhysVol2D();
1392       this->fill(element,pv);
1393       _option<DDDBLogVol>()->physvols.push_back(pv);
1394     }
1395 
1396     /// Specialized conversion of EllipticalTube shapes
1397     template <> void Conv<DDDBParamPhysVol3D>::fill(xml_h element, DDDBParamPhysVol3D* pv) const {
1398       dddb_dim_t elt = element;
1399       Conv<DDDBParamPhysVol2D>(description,param).fill(element, pv);
1400       pv->number3 = elt.number3();
1401       build_transformation(description, param, element, pv->trafo3, 2);
1402     }
1403     template <> void Conv<DDDBParamPhysVol3D>::convert(xml_h element) const {
1404       DDDBParamPhysVol3D* pv = new DDDBParamPhysVol3D();
1405       this->fill(element,pv);
1406       _option<DDDBLogVol>()->physvols.push_back(pv);
1407     }
1408 
1409     /// Specialized conversion of <geometryinfo/> entities
1410     template <> void Conv<DDDBTabProperty>::convert(xml_h element) const {
1411       DDDBContext*   context = _param<DDDBContext>();
1412       dddb_dim_t x_dim   = element;
1413       string     name    = x_dim.nameStr();
1414       string     id      = object_href(element, name);
1415       if ( !_find(id, context->geo->tabproperties) )  {
1416         DDDBTabProperty* p = new DDDBTabProperty();
1417         p->name        = name;
1418         p->path        = object_path(context,name);
1419         if ( element.hasAttr(_U(type))    ) p->type = element.attr<string>(_U(type));
1420         if ( element.hasAttr(_LBU(xunit)) ) p->xunit = element.attr<string>(_LBU(xunit));
1421         if ( element.hasAttr(_LBU(yunit)) ) p->yunit = element.attr<string>(_LBU(yunit));
1422         if ( element.hasAttr(_LBU(xaxis)) ) p->xaxis = element.attr<string>(_LBU(xaxis));
1423         if ( element.hasAttr(_LBU(yaxis)) ) p->yaxis = element.attr<string>(_LBU(yaxis));
1424         context->collect(id, p);
1425         context->collectPath(p->path, p);
1426         p->setDocument(context->locals.xml_doc);
1427       }
1428     }
1429 
1430     /// Specialized conversion of <tabpropertyref/> entities
1431     template <> void Conv<DDDBTabPropertyRef>::convert(xml_h element) const {
1432       DDDBContext* context = _param<DDDBContext>();
1433       DDDBCatalog* catalog = _option<DDDBCatalog>();
1434       string      href = element.attr<string>(_LBU(href));
1435       string     refid = reference_href(element,href);
1436 
1437       load_dddb_entity(context, catalog, element, href);
1438       dddb::TabProperties::const_iterator i=context->geo->tabproperties.find(refid);
1439       if ( i == context->geo->tabproperties.end() )  {
1440         string r = reference_href(element,href);
1441         printout(ERROR,"TabPropertyRef","++  MISSING ID: %s Failed to convert ref:%s",refid.c_str(),href.c_str());
1442         return;
1443       }
1444       DDDBTabProperty* p = (*i).second;
1445       catalog->tabpropertyrefs[p->id] = p;
1446       string path = object_path(context,p->name);
1447       context->collectPath(path, p);
1448       if ( context->printConfig.tabprop )  {
1449         print_ref("TabPropertyRef", context, element, href, "Path:"+path);
1450       }
1451     }
1452 
1453     /// Specialized conversion of <parameter/> entities
1454     template <> void Conv<DDDBParameter>::convert(xml_h element) const {
1455       DDDBContext* context  = _param<DDDBContext>();
1456       string name  = element.attr<string>(_U(name));
1457       string value = element.attr<string>(_U(value));
1458       if ( context->printConfig.params )  {
1459         printout(INFO,"Parameter","++  %s = %s",name.c_str(),value.c_str());
1460       }
1461       try  {
1462     _toDictionary(name,value);
1463       }
1464       catch(const exception& e)  {
1465     if ( context->printConfig.eval_error )  {
1466       printout(ERROR,"DDDBParameter","++  FAILED  %s = %s [%s]",name.c_str(),value.c_str(),e.what());
1467     }
1468     throw;
1469       }
1470     }
1471 
1472     /// Specialized conversion of <detelemref/> entities
1473     template <> void Conv<DDDBDetElemRef>::convert(xml_h element) const {
1474       DDDBContext* context = _param<DDDBContext>();
1475       DDDBCatalog* catalog = _option<DDDBCatalog>();
1476       string   href    = element.attr<string>(_LBU(href));
1477       string   refid   = reference_href(element, href);
1478 
1479       xml_h target = find_local_element(element, href, _LBU(detelem));
1480       if ( target )
1481         Conv<DDDBDetElem>(description,context,catalog)(target);
1482       else
1483         load_dddb_entity(context, catalog, element, href);
1484       dddb::Catalogs::const_iterator i=context->geo->catalogs.find(refid);
1485       catalog->catalogrefs[refid] = (i==context->geo->catalogs.end()) ? 0 : (*i).second;
1486       if ( context->printConfig.detelem_ref )   {
1487         print_ref("DetElemRef", context, element, href);
1488       }
1489     }
1490 
1491     /// Specialized conversion of <detelem/> entities
1492     template <> void Conv<DDDBDetElem>::convert(xml_h element) const {
1493       DDDBContext*   context = _param<DDDBContext>();
1494       dddb*      geo     = context->geo;
1495       dddb_dim_t x_det   = element;
1496       string     name    = x_det.nameStr();
1497       string     id      = object_href(element, name);
1498 
1499       dddb::Catalogs::iterator idet = geo->catalogs.find(id);
1500       if ( idet == geo->catalogs.end() ) {
1501         xml_h      elt;
1502         string     path   = object_path(context, name);
1503         Path p(path);
1504         string     parent = p.parent_path().native();
1505         DDDBCatalog* det  = new DDDBCatalog();
1506         det->typeID   = 1;
1507         det->name     = name;
1508         det->type     = x_det.typeStr();
1509         det->path     = path;
1510         det->id       = id;
1511         det->support  = parent;
1512         det->setDocument(context->locals.xml_doc);
1513         if ( context->printConfig.detelem )   {
1514           printout(INFO,"DetElem","  xml:%s id=%s  [%s/%s] doc:%s obj:%s / %s",
1515                    element.parent().tag().c_str(), 
1516                    det->id.c_str(),
1517                    det->name.c_str(),
1518                    det->type.c_str(),
1519                    context->locals.xml_doc->id.c_str(),
1520                    context->locals.obj_path.c_str(),
1521                    det->name.c_str()
1522                    );
1523         }
1524         if ( x_det.hasAttr(_LBU(classID)) )  {
1525           det->classID = element.attr<int>(_LBU(classID));
1526         }
1527         // Now extract all availible information from the xml
1528         if ( (elt=x_det.child(_U(author),false)) )
1529           Conv<DDDBAuthor>(description,context,&det->author)(elt);
1530         if ( (elt=x_det.child(_U(version),false)) )
1531           Conv<DDDBVersion>(description,context,&det->version)(elt);
1532         xml_coll_t(element, _U(param)).for_each(Conv<DDDBParam>(description,context,det));
1533         xml_coll_t(element, _LBU(userParameter)).for_each(Conv<DDDBParam>(description,context,det));
1534         xml_coll_t(element, _LBU(conditioninfo)).for_each(Conv<DDDBConditionInfo>(description,context,det));
1535         {
1536           DDDBContext::PreservedLocals locals(context);
1537           context->locals.obj_path = det->path;
1538           xml_coll_t(element, _LBU(geometryinfo)).for_each(Conv<DDDBGeometryInfo>(description,context,det));
1539           xml_coll_t(element, _LBU(detelem)).for_each(Conv<DDDBDetElem>(description,context,det));
1540           xml_coll_t(element, _LBU(detelemref)).for_each(Conv<DDDBDetElemRef>(description,context,det));
1541         }
1542         det->path = det->support + "/" + det->name;
1543         context->collect(det->id, det);
1544         context->collectPath(det->path, det);
1545         context->print(det);
1546         return;
1547       }
1548       printout(DEBUG,"DetElem","ALREADY PROCESSED: xid:%s -> %s",id.c_str(),(*idet).second->path.c_str());
1549     }
1550 
1551     /// Specialized conversion of references to catalogs
1552     template <> void Conv<DDDBCatalogRef>::convert(xml_h element) const {
1553       DDDBContext* context = _param<DDDBContext>();
1554       DDDBCatalog* catalog = _option<DDDBCatalog>();
1555       string   href    = element.attr<string>(_LBU(href));
1556       string   refid   = reference_href(element,href);
1557 #if 0
1558       if ( href.find("@ChamAlign.xml#") != string::npos )  {
1559         print_ref("CatalogRef", context, element, href);
1560       }
1561 #endif
1562       xml_h target = find_local_element(element, href,_LBU(catalog));
1563       if ( target )  {
1564         Conv<DDDBCatalog>(description,context,catalog)(target);
1565       }
1566       else  {
1567         load_dddb_entity(context, catalog, element, href);
1568       }
1569       dddb::Catalogs::const_iterator i=context->geo->catalogs.find(refid);
1570       catalog->catalogrefs[refid] = (i == context->geo->catalogs.end()) ? 0 : (*i).second;
1571       if ( context->printConfig.catalog_ref )  {
1572         print_ref("CatalogRef", context, element, href);
1573       }
1574     }
1575 
1576     /// Specialized conversion of <catalog/> entities
1577     template <> void Conv<DDDBCatalog>::convert(xml_h e) const {
1578       DDDBContext* context = _param<DDDBContext>();
1579       string   name    = e.attr<string>(_U(name));
1580       string   id      = object_href(e,name);
1581       dddb::Catalogs::const_iterator icat = context->geo->catalogs.find(id);
1582 
1583       if ( icat == context->geo->catalogs.end() )  {
1584         DDDBCatalog* catalog = new DDDBCatalog();
1585         catalog->name          = name;
1586         catalog->path          = object_path(context,name);
1587         printout(DEBUG,"Catalog","PROCESSING:        xid:%s -> %s",id.c_str(),catalog->path.c_str());
1588         catalog->level         = Increment<DDDBCatalog>::counter();
1589         catalog->type          = "Logical";
1590         catalog->support       = "";
1591         catalog->setDocument(context->locals.xml_doc);
1592         context->collect(id, catalog);
1593         context->collectPath(catalog->path, catalog);
1594         if ( catalog->path == "/dd" )  {
1595           catalog->type    = "World";
1596           context->geo->top = catalog;
1597         }
1598         else if ( catalog->path == "/dd/Structure" )  {
1599           catalog->type    = "Structure";
1600           context->geo->structure = catalog;
1601         }
1602         else if ( catalog->path == "/dd/Geometry" )  {
1603           catalog->type    = "Geometry";
1604           context->geo->geometry  = catalog;
1605         }
1606         {
1607           DDDBContext::PreservedLocals locals(context);
1608           context->locals.obj_path = catalog->path;
1609           xml_coll_t(e, _U(parameter)).for_each(Conv<DDDBParameter>(description,context,catalog));
1610           xml_coll_t(e, _U(isotope)).for_each(Conv<DDDBIsotope>(description,context,catalog));
1611           xml_coll_t(e, _U(element)).for_each(Conv<DDDBElement>(description,context,catalog));
1612           xml_coll_t(e, _U(material)).for_each(Conv<DDDBMaterial>(description,context,catalog));
1613           xml_coll_t(e, _U(logvol)).for_each(Conv<DDDBLogVol>(description,context,catalog));
1614 
1615           xml_coll_t(e, _LBU(tabproperty)).for_each(Conv<DDDBTabProperty>(description,context,catalog));
1616 
1617           //xml_coll_t(e, _LBU(condition)).for_each(Conv<DDDBCondition>(description,context,catalog));
1618           //xml_coll_t(e, _LBU(detelem)).for_each(Conv<DDDBDetElem>(description,context,catalog));
1619           //xml_coll_t(e, _LBU(catalog)).for_each(Conv<DDDBCatalog>(description,context,catalog));
1620 
1621           xml_coll_t(e, _LBU(elementref)).for_each(Conv<DDDBElementRef>(description,context,catalog));
1622           xml_coll_t(e, _LBU(materialref)).for_each(Conv<DDDBMaterialRef>(description,context,catalog));
1623           xml_coll_t(e, _LBU(logvolref)).for_each(Conv<DDDBLogVolRef>(description,context,catalog));
1624           xml_coll_t(e, _LBU(tabpropertyref)).for_each(Conv<DDDBTabPropertyRef>(description,context,catalog));
1625 
1626           xml_coll_t(e, _LBU(conditionref)).for_each(Conv<DDDBConditionRef>(description,context,catalog));
1627           xml_coll_t(e, _LBU(catalogref)).for_each(Conv<DDDBCatalogRef>(description,context,catalog));
1628           xml_coll_t(e, _LBU(detelemref)).for_each(Conv<DDDBDetElemRef>(description,context,catalog));
1629 
1630           xml_coll_t(e, _LBU(catalog)).for_each(Conv<DDDBCatalog>(description,context,catalog));
1631           xml_coll_t(e, _LBU(detelem)).for_each(Conv<DDDBDetElem>(description,context,catalog));
1632           xml_coll_t(e, _LBU(condition)).for_each(Conv<Condition>(description,context,catalog));
1633         }
1634         return;
1635       }
1636       printout(DEBUG,"Catalog","ALREADY PROCESSED: xid:%s -> %s",id.c_str(),(*icat).second->path.c_str());
1637     }
1638 
1639     /// Specialized conversion of <DDDB/> entities
1640     template <> void Conv<dddb>::convert(xml_h e) const {
1641       DDDBCatalog* catalog = 0;
1642       DDDBContext* context = _param<DDDBContext>();
1643       xml_coll_t(e, _LBU(block)).for_each(Conv<DDDBBlock>(description,context,catalog));
1644       xml_coll_t(e, _U(config)).for_each(Conv<DDDBConfig>(description,&s_config,catalog));
1645       xml_coll_t(e, _U(config)).for_each(Conv<DDDBConfig>(description,context,catalog));
1646       xml_coll_t(e, _U(parameter)).for_each(Conv<DDDBParameter>(description,context,catalog));
1647       xml_coll_t(e, _U(isotope)).for_each(Conv<DDDBIsotope>(description,context,catalog));
1648       xml_coll_t(e, _U(element)).for_each(Conv<DDDBElement>(description,context,catalog));
1649       xml_coll_t(e, _U(material)).for_each(Conv<DDDBMaterial>(description,context,catalog));
1650       xml_coll_t(e, _U(logvol)).for_each(Conv<DDDBLogVol>(description,context,catalog));
1651       xml_coll_t(e, _LBU(tabproperty)).for_each(Conv<DDDBTabProperty>(description,context,catalog));
1652 
1653       //xml_coll_t(e, _LBU(condition)).for_each(Conv<Condition>(description,context,catalog));
1654       //xml_coll_t(e, _LBU(detelem)).for_each(Conv<DDDBDetElem>(description,context,catalog));
1655       //xml_coll_t(e, _LBU(catalog)).for_each(Conv<DDDBCatalog>(description,context,catalog));
1656 
1657       xml_coll_t(e, _LBU(elementref)).for_each(Conv<DDDBElementRef>(description,context,catalog));
1658       xml_coll_t(e, _LBU(materialref)).for_each(Conv<DDDBMaterialRef>(description,context,catalog));
1659       xml_coll_t(e, _LBU(logvolref)).for_each(Conv<DDDBLogVolRef>(description,context,catalog));
1660       xml_coll_t(e, _LBU(tabpropertyref)).for_each(Conv<DDDBTabPropertyRef>(description,context,catalog));
1661 
1662       xml_coll_t(e, _LBU(conditionref)).for_each(Conv<DDDBConditionRef>(description,context,catalog));
1663       xml_coll_t(e, _LBU(catalogref)).for_each(Conv<DDDBCatalogRef>(description,context,catalog));
1664       xml_coll_t(e, _LBU(detelemref)).for_each(Conv<DDDBDetElemRef>(description,context,catalog));
1665 
1666       xml_coll_t(e, _LBU(detelem)).for_each(Conv<DDDBDetElem>(description,context,catalog));
1667       // First handle the catalog. It may refer to local conditions!
1668       xml_coll_t(e, _LBU(catalog)).for_each(Conv<DDDBCatalog>(description,context,catalog));
1669       xml_coll_t(e, _LBU(condition)).for_each(Conv<Condition>(description,context,catalog));
1670     }
1671 
1672     /// Specialized conversion of <DDDB/> entities
1673     template <> void Conv<dddb_conditions>::convert(xml_h e) const {
1674       DDDBCatalog* catalog = 0;
1675       DDDBContext* context = _param<DDDBContext>();
1676       context->check = false;
1677       xml_coll_t(e, _LBU(conditionref)).for_each(Conv<DDDBConditionRef>(description,context,catalog));
1678       xml_coll_t(e, _LBU(catalogref)).for_each(Conv<DDDBCatalogRef>(description,context,catalog));
1679       {
1680         DDDBContext::PreservedLocals locals(context);
1681         // First handle the catalog. It may refer to local conditions!
1682         xml_coll_t(e, _LBU(catalog)).for_each(Conv<DDDBCatalog>(description,context,catalog));
1683         xml_coll_t(e, _LBU(condition)).for_each(Conv<Condition>(description,context,catalog));
1684       }
1685     }
1686 
1687     void apply_trafo(int apply, Position& pos, RotationZYX& rot, Transform3D& trafo, Transform3D& tr)  {
1688       switch(apply)   {
1689       case 99:   {
1690         tr *= trafo;
1691         trafo = Transform3D();
1692         pos = Position();
1693         rot = RotationZYX();
1694         break;
1695       }
1696       case 2:  {
1697         Transform3D r(rot);
1698         trafo = Transform3D(pos);
1699         trafo = trafo * r;
1700         tr = trafo * tr;
1701         trafo = Transform3D();
1702         pos = Position();
1703         rot = RotationZYX();
1704         break;
1705       }
1706       case 1:  {
1707         /// Is this really correct ?
1708         double xx, xy, xz, dx, yx, yy, yz, dy, zx, zy, zz, dz;
1709         tr.GetComponents(xx, xy, xz, dx, yx, yy, yz, dy, zx, zy, zz, dz);
1710         dx += pos.X();
1711         dy += pos.Y();
1712         dz += pos.Z();
1713         tr.SetComponents(xx, xy, xz, dx, yx, yy, yz, dy, zx, zy, zz, dz);
1714 #if 0
1715         trafo = Transform3D(pos);
1716         tr *= trafo;
1717 #endif
1718         trafo = Transform3D();
1719         pos = Position();
1720         rot = RotationZYX();
1721         break;
1722       }
1723       case 0:
1724       default:
1725         break;
1726       }
1727     }
1728 
1729     void extract_transformation(Detector& description, void* context, xml_coll_t& p, Transform3D& tr, int which)   {
1730       int count = 0;
1731       int apply = 0;
1732       Position pos;
1733       RotationZYX rot;
1734       Transform3D trafo;
1735       for(xml_h element = p.parent(); p; ++p )  {
1736         if ( p.parent() == element ) { // Only next level is processed here
1737           dddb_dim_t dim = p;
1738           string tag = p.tag();
1739           if ( tag == "transformation" && (which<0 || count == which) )  {
1740             apply_trafo(apply, pos, rot, trafo, tr);
1741             Conv<Transform3D>(description,context,&trafo)(p);
1742             apply = 99;
1743           }
1744           else if ( tag == "posXYZ" && (which<0 || count == which) )   {
1745             apply_trafo(apply, pos, rot, trafo, tr);
1746             pos.SetXYZ(dim.x(0.0), dim.y(0.0), dim.z(0.0));
1747             apply = 1;
1748             ++count;
1749           }
1750           else if ( tag == "posRPhiZ" && (which<0 || count == which) )   {
1751             ROOT::Math::Polar2D<double> dim2(dim.r(0.0), dim.phi(0.0));
1752             apply_trafo(apply, pos, rot, trafo, tr);
1753             pos.SetXYZ(dim2.X(), dim2.Y(), dim.z(0.0));
1754             apply = 1;
1755             ++count;
1756           }
1757           else if ( tag == "rotXYZ" && (which<0 || count == (which+1)) )  {
1758             rot.SetComponents(dim.rotZ(0.0), dim.rotY(0.0), dim.rotX(0.0));
1759             apply = 2;
1760           }
1761           else  {
1762             --p;
1763             apply_trafo(apply, pos, rot, trafo, tr);
1764             return;
1765           }
1766           if ( apply > 1 )  {
1767             apply_trafo(apply, pos, rot, trafo, tr);
1768             apply = 0;
1769           }
1770         }
1771       }
1772       if ( apply > 0 ) {
1773         apply_trafo(apply, pos, rot, trafo, tr);
1774       }
1775     }
1776     string reference_href(xml_h element, const string& ref)  {
1777       size_t hash = ref.rfind("#");
1778       size_t idx = ref.find(":");
1779       size_t idq = ref.find("/");
1780 
1781       if ( idx != string::npos && idx < idq )  {
1782         if ( hash == string::npos && idq != string::npos )   {
1783           if ( (idq=ref.rfind("/")) != string::npos )
1784             return ref + '#' + ref.substr(idq+1);
1785         }
1786         return ref;
1787       }
1788       // Resolve relative path
1789       string p = xml::DocumentHandler::system_path(element);
1790       if ( hash == 0 )  { // This is a local object. Take the element's path
1791         p += ref;
1792         Path path = p;  // Remote object. Parent + local path
1793         p = path.normalize().native();      
1794         return p;
1795       }
1796       Path path = p;  // Remote object. Parent + local path
1797       path  = path.parent_path();
1798       path /= ref;
1799       p  = path.normalize().native();      
1800       /// Hacky: If no reference object is given, the object name 
1801       /// is the same as the last item of the path (???)
1802       /// ==> Local fix for online consitions, which are referenced using:
1803       /// conddb:/Conditions/Online/L0MUON/Q1/FOI instead of:
1804       /// conddb:/Conditions/Online/L0MUON/Q1/FOI#FOI ...
1805       if ( hash == string::npos )   {
1806         if ( (idq=p.rfind("/")) != string::npos )
1807           p += '#' + p.substr(idq+1);
1808         else if ( (idx=p.find(":")) != string::npos )
1809           p += '#' + p.substr(idx+1);
1810         else
1811           p += '#' + ref;
1812       }
1813       return p;
1814     }
1815 
1816     template <typename ACTION>
1817     void load_dddb_entity(DDDBContext*      context,
1818                           DDDBCatalog*      catalog, 
1819                           xml_h         element,
1820                           const string& ref,
1821                           bool prt)
1822     {
1823       size_t hash = ref.find("#");
1824       if ( hash != 0 )  {
1825         try {
1826           xml::UriReader*        rdr       = context->resolver;
1827           DDDBReaderContext* ctx       = (DDDBReaderContext*)rdr->context();
1828           string doc_path = element.ptr() ? reference_href(element,ref) : ref;
1829           if ( ref == ctx->match+"/Conditions/Online" )
1830             doc_path = reference_href(element,ref);
1831           hash = doc_path.find('#');
1832           if ( hash != string::npos ) doc_path = doc_path.substr(0,hash);
1833 #if 0
1834           if ( doc_path.find("conddb:/Rich") != string::npos )  {
1835             printout(INFO, "load_dddb", "SKIPPING DOC %s", doc_path.c_str());
1836             return;
1837           }
1838 #endif
1839           dddb::Documents& docs = context->geo->documents;
1840           if ( _find(doc_path,docs) )
1841             return;
1842 
1843           size_t idx = doc_path.find('[');
1844           size_t idq = doc_path.find(']');
1845           string key, fp = doc_path;
1846           if ( idq != string::npos && idx != string::npos )  {
1847             key = doc_path.substr(idx+1,idq-idx-1);
1848             fp = doc_path.substr(0,idx);
1849           }
1850           DDDBDocument*      xml_doc   = new DDDBDocument();
1851           xml_doc->id                  = doc_path;
1852           xml_doc->name                = context->locals.obj_path;
1853           xml_doc->context.doc         = xml_doc->id;
1854           xml_doc->context.event_time  = ctx->event_time;
1855           xml_doc->context.valid_since = 0;//ctx->valid_since;
1856           xml_doc->context.valid_until = LONG_MAX;//ctx->valid_until;
1857           docs.insert(make_pair(doc_path,xml_doc->addRef()));
1858 
1859           if ( !rdr->isBlocked(doc_path) )   {
1860             xml::UriContextReader reader(rdr, &xml_doc->context);
1861             xml_doc_holder_t doc(xml_handler_t().load(fp, &reader));
1862             xml_h e = doc.root();
1863             context->print(xml_doc);
1864             printout(context->printConfig.file_load ? INFO : DEBUG,
1865                      "load_dddb","Loaded document: %s IOV: %ld [%ld,%ld]",
1866                      xml_doc->id.c_str(), 
1867                      xml_doc->context.event_time,
1868                      xml_doc->context.valid_since,
1869                      xml_doc->context.valid_until);
1870 
1871             if ( e )   {
1872               if ( !key.empty() )  {
1873                 stringstream str;
1874                 xml::dump_tree(e, str);
1875                 string buffer = str.str();
1876                 while( (idx=buffer.find("-KEY-")) != string::npos )
1877                   buffer.replace(idx,5,key);
1878                 doc.assign(xml_handler_t().parse(buffer.c_str(),
1879                                                  buffer.length(),
1880                                                  doc_path.c_str(),
1881                                                  &reader));
1882                 e = doc.root();
1883               }
1884               DDDBContext::PreservedLocals locals(context);
1885               context->locals.xml_doc  = xml_doc;
1886               Conv<ACTION> converter(*context->description, context, catalog);
1887               context->printConfig.condition = prt;
1888               if ( prt || context->printConfig.xml )  xml::dump_tree(e);
1889               converter(e);
1890           return;
1891             }
1892             return;
1893           }
1894           printout(context->printConfig.file_load ? INFO : DEBUG,
1895                    "load_dddb","Ignore BLOCKED load %s",ref.c_str());
1896         }
1897         catch(const exception& e)  {
1898           printout(INFO,"load_dddb","Failed to load %s [%s]",ref.c_str(),e.what()); 
1899        }
1900         catch(...)   {
1901           printout(INFO,"load_dddb","Failed to load %s",ref.c_str());
1902         }
1903       }
1904     }
1905 
1906     void config_context(DDDBContext& context, 
1907                         DDDBHelper*  hlp, 
1908                         const std::string& doc_path,
1909                         const std::string& obj_path)  {
1910       xml::UriReader*     rdr     = hlp->reader<xml::UriReader>();
1911       DDDBReaderContext*  ctx     = (DDDBReaderContext*)rdr->context();
1912       DDDBDocument*       doc     = new DDDBDocument();
1913       doc->name                   = obj_path;
1914       doc->id                     = doc_path;
1915       doc->context.event_time     = ctx->event_time;
1916       doc->context.valid_since    = ctx->valid_since;
1917       doc->context.valid_until    = ctx->valid_until;
1918       context.resolver            = rdr;
1919       context.geo                 = new dddb();
1920       context.locals.obj_path     = obj_path;
1921       context.locals.xml_doc      = doc;
1922       context.geo->documents.insert(make_pair("Initial_dummy_doc",doc->addRef()));
1923     }
1924 
1925     /// Plugin entry point.
1926     template <typename ACTION>
1927     long load_dddb_objects(Detector& description, int argc, char** argv) {
1928       DDDBHelper* hlp = description.extension<DDDBHelper>(false);
1929       if ( hlp )   {
1930         xml::UriReader*    rdr = hlp->xmlReader();
1931         DDDBReaderContext* ctx = (DDDBReaderContext*)rdr->context();
1932         DDDBContext ctxt(&description);
1933         string sys_id = ctx->match+"//lhcb.xml";
1934         string obj_path = "/";
1935         if ( argc == 0 )   {
1936           return 0;
1937         }
1938         if ( argc >= 1 && argv[0] != 0 )  {
1939           rdr = (xml::UriReader*)argv[0];
1940         }
1941         if ( argc >= 2 && argv[1] != 0 )  {
1942           sys_id = argv[1];
1943         }
1944         if ( argc >= 3 && argv[2] != 0 )  {
1945           obj_path = argv[2];
1946         }
1947         if ( argc == 4 && argv[3] != 0 )  {
1948           long long int evt_time = *(long long int*)argv[3];
1949           ctx->event_time  = evt_time;
1950         }
1951         if ( argc == 5 && argv[3] != 0 && argv[4] != 0)  {
1952           long long int iov_start = *(long long int*)argv[3];
1953           long long int iov_end   = *(long long int*)argv[4];
1954           ctx->event_time  = (iov_start+iov_end)/2;
1955           ctx->valid_since = iov_start;
1956           ctx->valid_until = iov_end;
1957         }
1958         config_context(ctxt, hlp, sys_id, obj_path);
1959         load_dddb_entity<ACTION>(&ctxt,0,0,ctxt.locals.xml_doc->id);
1960         checkParents( &ctxt );
1961         fixCatalogs( &ctxt );
1962         /// Transfer ownership from local context to the helper
1963         hlp->setDetectorDescription( ctxt.geo );
1964         ctxt.geo = 0;
1965         return 1;
1966       }
1967       except("DDDB","+++ Failed to access cool. No DDDBHelper object defined. Run plugin DDDBInstallHelper.");
1968       return 0;
1969     }
1970   }
1971 
1972   /// Access global instance for xml configuration
1973   CondDB2Objects::PrintConfig& CondDB2Objects::PrintConfig::instance()   {
1974     return s_config.printConfig;
1975   }
1976   
1977   namespace DDDB  {
1978     long load_dddb_from_uri(Detector& description, int argc, char** argv) {
1979       return load_dddb_objects<dddb>(description,argc,argv);
1980     }
1981     long load_dddb_conditions_from_uri(Detector& description, int argc, char** argv) {
1982       return load_dddb_objects<dddb_conditions>(description,argc,argv);
1983     }
1984     /// Plugin entry point.
1985     long load_dddb_from_handle(Detector& description, xml_h element) {
1986       DDDBHelper* helper = description.extension<DDDBHelper>(false);
1987       if ( helper )   {
1988         DDDBContext context(&description);
1989         xml::UriReader* rdr = helper->xmlReader();
1990         DDDBReaderContext*  ctx = (DDDBReaderContext*)rdr->context();
1991         config_context(context, helper, ctx->match+"//lhcb.xml", "/");
1992         /// Convert the XML information
1993         Conv<dddb> converter(description, &context);
1994         converter( element );
1995         checkParents( &context );
1996         fixCatalogs( &context );
1997         /// Transfer ownership from local context to the helper
1998         helper->setDetectorDescription( context.geo );
1999         context.geo = 0;
2000         return 1;
2001       }
2002       except("DDDB","+++ Failed to access cool. No DDDBHelper object defined. Run plugin DDDBInstallHelper.");
2003       return 0;
2004     }
2005   }
2006 }
2007 DECLARE_XML_DOC_READER(DDDB,load_dddb_from_handle)
2008 DECLARE_APPLY(DDDB_Loader,load_dddb_from_uri)
2009 DECLARE_APPLY(DDDB_ConditionsLoader,load_dddb_conditions_from_uri)
2010 
2011 /// Plugin entry point.
2012 static long install_helper(Detector& description, int argc, char** argv) {
2013   DDDBHelper* helper = description.extension<DDDBHelper>(false);
2014   if ( !helper )   {
2015     helper = new DDDBHelper(description);
2016     if ( argc > 0 )   {
2017       helper->setXmlReader((xml::UriReader*)argv[0]);
2018     }
2019     description.addExtension<DDDBHelper,DDDBHelper>(helper);
2020   }
2021   return 1;
2022 }
2023 DECLARE_APPLY(DDDB_InstallHelper,install_helper)