From c68232f728af4a9ec6a2419adff33f5320e9e8c3 Mon Sep 17 00:00:00 2001
From: Markus Frank <Markus.Frank@cern.ch>
Date: Wed, 15 Mar 2017 14:32:58 +0100
Subject: [PATCH] Group common XML parsers (XMLParsers.h,XMLParsers.cpp).

---
 DDAlign/src/plugins/GlobalAlignmentParser.cpp | 117 +-------------
 .../plugins/ConditionsRepositoryParser.cpp    | 148 ++----------------
 DDCore/include/XML/XMLParsers.h               | 129 +++++++++++++++
 DDCore/src/OpaqueDataBinder.cpp               |   4 +-
 DDCore/src/XML/XMLParsers.cpp                 | 133 ++++++++++++++++
 .../AlignDet/compact/AlephTPC_alignment.xml   |  39 +++--
 6 files changed, 301 insertions(+), 269 deletions(-)
 create mode 100644 DDCore/include/XML/XMLParsers.h
 create mode 100644 DDCore/src/XML/XMLParsers.cpp

diff --git a/DDAlign/src/plugins/GlobalAlignmentParser.cpp b/DDAlign/src/plugins/GlobalAlignmentParser.cpp
index d3745b702..8758c0c7f 100644
--- a/DDAlign/src/plugins/GlobalAlignmentParser.cpp
+++ b/DDAlign/src/plugins/GlobalAlignmentParser.cpp
@@ -17,7 +17,7 @@
 #include "DD4hep/Mutex.h"
 #include "DD4hep/Printout.h"
 #include "XML/Conversions.h"
-#include "XML/XMLElements.h"
+#include "XML/XMLParsers.h"
 #include "XML/DocumentHandler.h"
 #include "DD4hep/DetectorTools.h"
 #include "DD4hep/DetFactoryHelper.h"
@@ -48,11 +48,6 @@ namespace DD4hep  {
 
   /// Forward declarations for all specialized converters
   template <> void Converter<debug>::operator()(xml_h seq)  const;
-  template <> void Converter<pivot>::operator()(xml_h seq)  const;
-  template <> void Converter<position>::operator()(xml_h seq)  const;
-  template <> void Converter<rotation>::operator()(xml_h seq)  const;
-  template <> void Converter<alignment_delta>::operator()(xml_h seq)  const;
-
   template <> void Converter<volume>::operator()(xml_h seq)  const;
   template <> void Converter<alignment>::operator()(xml_h seq)  const;
   template <> void Converter<detelement>::operator()(xml_h seq)  const;
@@ -62,8 +57,6 @@ namespace DD4hep  {
 using namespace std;
 using namespace DD4hep;
 using namespace DD4hep::Alignments;
-using DD4hep::Geometry::Position;
-using DD4hep::Geometry::Translation3D;
 
 /** Convert to enable/disable debugging.
  *
@@ -76,104 +69,6 @@ template <> void Converter<debug>::operator()(xml_h e) const {
   GlobalDetectorAlignment::debug(value);
 }
 
-/** Convert rotation objects
- *
- *    <rotation x="0.5" y="0"  z="0"/>
- *
- *  @author  M.Frank
- *  @version 1.0
- *  @date    01/04/2014
- */
-template <> void Converter<rotation>::operator()(xml_h e) const {
-  xml_comp_t r(e);
-  RotationZYX* v = (RotationZYX*)param;
-  v->SetComponents(r.z(), r.y(), r.x());
-  printout(INFO,"Alignment<rot>",
-           "  Rotation:   x=%9.3f y=%9.3f   z=%9.3f  phi=%7.4f psi=%7.4f theta=%7.4f",
-           r.x(), r.y(), r.z(), v->Phi(), v->Psi(), v->Theta());
-}
-
-/** Convert position objects
- *
- *    <position x="0.5" y="0"  z="0"/>
- *
- *  @author  M.Frank
- *  @version 1.0
- *  @date    01/04/2014
- */
-template <> void Converter<position>::operator()(xml_h e) const {
-  xml_comp_t p(e);
-  Position* v = (Position*)param;
-  v->SetXYZ(p.x(), p.y(), p.z());
-  printout(INFO,"Alignment<pos>","  Position:   x=%9.3f y=%9.3f   z=%9.3f",
-           v->X(), v->Y(), v->Z());
-}
-
-/** Convert pivot objects
- *
- *    <pivot x="0.5" y="0"  z="0"/>
- *
- *  @author  M.Frank
- *  @version 1.0
- *  @date    01/04/2014
- */
-template <> void Converter<pivot>::operator()(xml_h e) const {
-  xml_comp_t p(e);
-  double x,y,z;
-  Translation3D* v = (Translation3D*)param;
-  v->SetXYZ(x=p.x(), y=p.y(), z=p.z());
-  printout(INFO,"Alignment<piv>","     Pivot:      x=%9.3f y=%9.3f   z=%9.3f",x,y,z);
-}
-
-/** Convert delta objects
- *
- *     A generic alignment transformation is defined by
- *     - a translation in 3D space identified in XML as a
- *         <position/> element
- *       - a rotation in 3D space around a pivot point specified in XML by
- *         2 elements: the <rotation/> and the <pivot/> element.
- *       The specification of any of the elements is optional:
- *     - The absence of a translation implies the origine (0,0,0)
- *     - The absence of a pivot point implies the origine (0,0,0)
- *       - The absence of a rotation implies the identity rotation.
- *         Any supplied pivot point in this case is ignored.
- *
- *      <xx>
- *        <position x="0" y="0"  z="0.0001*mm"/>
- *        <rotation x="0" y="0"  z="0"/>
- *        <pivot    x="0" y="0"    z="100"/>
- *      </xx>
- *
- *  @author  M.Frank
- *  @version 1.0
- *  @date    01/04/2014
- */
-template <> void Converter<alignment_delta>::operator()(xml_h e) const {
-  Position pos;
-  RotationZYX rot;
-  Translation3D piv;
-  xml_h  child_rot, child_pos, child_piv;
-  Delta* delta = (Delta*)param;
-
-  if ( (child_pos=e.child(_U(position),false)) )
-    Converter<position>(lcdd,&delta->translation)(child_pos);
-  if ( (child_rot=e.child(_U(rotation),false)) )   {
-    Converter<rotation>(lcdd,&delta->rotation)(child_rot);
-    if ( (child_piv=e.child(_U(pivot),false)) )
-      Converter<pivot>(lcdd,&delta->pivot)(child_piv);
-  }
-  if ( child_rot && child_pos && child_piv )
-    delta->flags |= Delta::HAVE_ROTATION|Delta::HAVE_PIVOT|Delta::HAVE_TRANSLATION;
-  else if ( child_rot && child_pos )
-    delta->flags |= Delta::HAVE_ROTATION|Delta::HAVE_TRANSLATION;
-  else if ( child_rot && child_piv )
-    delta->flags |= Delta::HAVE_ROTATION|Delta::HAVE_PIVOT;
-  else if ( child_rot )
-    delta->flags |= Delta::HAVE_ROTATION;
-  else if ( child_pos )
-    delta->flags |= Delta::HAVE_TRANSLATION;
-}
-
 typedef GlobalAlignmentStack::StackEntry StackEntry;
 
 /** Convert volume objects
@@ -193,8 +88,8 @@ typedef GlobalAlignmentStack::StackEntry StackEntry;
  */
 template <> void Converter<volume>::operator()(xml_h e) const {
   Delta val;
-  pair<DetElement,string>* elt = (pair<DetElement,string>*)param;
-  GlobalAlignmentStack* stack = _option<GlobalAlignmentStack>();
+  GlobalAlignmentStack* stack  = _option<GlobalAlignmentStack>();
+  pair<DetElement,string>* elt = _param<pair<DetElement,string> >();
   string subpath    = e.attr<string>(_ALU(path));
   bool   reset      = e.hasAttr(_ALU(reset)) ? e.attr<bool>(_ALU(reset)) : true;
   bool   reset_dau  = e.hasAttr(_ALU(reset_children)) ? e.attr<bool>(_ALU(reset_children)) : true;
@@ -208,7 +103,7 @@ template <> void Converter<volume>::operator()(xml_h e) const {
   printout(INFO,"Alignment<vol>","    path:%s placement:%s reset:%s children:%s",
            subpath.c_str(), placement.c_str(), yes_no(reset), yes_no(reset_dau));
 
-  Converter<alignment_delta>(lcdd,&val)(e);
+  XML::parse(e,val);
   if ( val.flags ) val.flags |= GlobalAlignmentStack::MATRIX_DEFINED;
   if ( overlap   ) val.flags |= GlobalAlignmentStack::OVERLAP_DEFINED;
   if ( reset     ) val.flags |= GlobalAlignmentStack::RESET_VALUE;
@@ -231,7 +126,7 @@ template <> void Converter<volume>::operator()(xml_h e) const {
  *    <detelement path="/world/TPC/TPC_SideA/TPC_SideA_sector02">
  *      <position x="0"   y="0"  z="0"/>
  *      <rotation x="0.5" y="0"  z="0"/>
- *        <pivot    x="0" y="0"    z="100"/>
+ *      <pivot    x="0"   y="0"  z="100"/>
  *    </detelement>
  *
  *  @author  M.Frank
@@ -257,7 +152,7 @@ template <> void Converter<detelement>::operator()(xml_h e) const {
   }
 
   Delta delta;
-  Converter<alignment_delta>(lcdd,&delta)(e);
+  XML::parse(e, delta);
   if ( delta.flags )  {
     delta.flags |= GlobalAlignmentStack::MATRIX_DEFINED;
     reset = reset_dau = true;
diff --git a/DDCond/src/plugins/ConditionsRepositoryParser.cpp b/DDCond/src/plugins/ConditionsRepositoryParser.cpp
index 772b96ba0..436a2354f 100644
--- a/DDCond/src/plugins/ConditionsRepositoryParser.cpp
+++ b/DDCond/src/plugins/ConditionsRepositoryParser.cpp
@@ -14,7 +14,7 @@
 // Framework include files
 #include "DD4hep/LCDD.h"
 #include "XML/Conversions.h"
-#include "XML/XMLElements.h"
+#include "XML/XMLParsers.h"
 #include "XML/DocumentHandler.h"
 #include "DD4hep/Path.h"
 #include "DD4hep/Printout.h"
@@ -45,6 +45,7 @@ namespace DD4hep  {
     class detelement;
     class conditions;
     class arbitrary;
+
     /// Conditions types
     class value;
     class pressure;
@@ -52,18 +53,12 @@ namespace DD4hep  {
     class mapping;
     class sequence;
     class alignment;
-    class position;
-    class rotation;
-    class pivot;
   }
   /// Forward declarations for all specialized converters
   template <> void Converter<iov>::operator()(xml_h seq)  const;
   template <> void Converter<iov_type>::operator()(xml_h seq)  const;
   template <> void Converter<repository>::operator()(xml_h seq)  const;
   template <> void Converter<manager>::operator()(xml_h seq)  const;
-  template <> void Converter<rotation>::operator()(xml_h e) const;
-  template <> void Converter<position>::operator()(xml_h e) const;
-  template <> void Converter<pivot>::operator()(xml_h e) const;
   template <> void Converter<value>::operator()(xml_h e) const;
   template <> void Converter<pressure>::operator()(xml_h e) const;
   template <> void Converter<temperature>::operator()(xml_h e) const;
@@ -312,162 +307,43 @@ namespace DD4hep {
     arg->manager.registerUnlocked(arg->pool, con);
   }
 
-  /// Convert conditions sequence objects (unmapped containers)
+  /// Convert conditions sequence objects (unmapped containers). See XML/XMLParsers.h for details.
   /**
    *  \author  M.Frank
    *  \version 1.0
    *  \date    01/04/2014
    */
   template <> void Converter<sequence>::operator()(xml_h e) const {
-    xml_dim_t      elt(e);
-    Condition      con(0);
-    string         typ = elt.typeStr();
     ConversionArg* arg = _param<ConversionArg>();
-    size_t idx = typ.find('[');
-    size_t idq = typ.find(']');
-    string value_type = typ.substr(idx+1,idq-idx-1);
-    if ( typ.substr(0,6) == "vector" )
-      con = bind_condition(VectorBinder(), arg->detector, e, value_type);
-    else if ( typ.substr(0,4) == "list" )
-      con = bind_condition(ListBinder(), arg->detector, e, value_type);
-    else if ( typ.substr(0,3) == "set" )
-      con = bind_condition(SetBinder(), arg->detector, e, value_type);
-    else
-      except("XMLConditions",
-             "++ Failed to convert unknown sequence conditions type: %s",typ.c_str());
+    Condition      con = create_condition(arg->detector, e);
+    XML::parse_sequence(e, con->data);
     arg->manager.registerUnlocked(arg->pool, con);
   }
 
-  /// Convert conditions STL maps
+  /// Convert conditions STL maps. See XML/XMLParsers.h for details.
   /**
    *  \author  M.Frank
    *  \version 1.0
    *  \date    01/04/2014
    */
   template <> void Converter<mapping>::operator()(xml_h e) const {
-    xml_comp_t elt(e);
     ConversionArg* arg = _param<ConversionArg>();
-    string    key_type = e.attr<string>(_U(key));
-    string    val_type = e.attr<string>(_U(value));
     Condition      con = create_condition(arg->detector, e);
-    OpaqueDataBlock& b = con->data;
-    MapBinder binder;
-
-    OpaqueDataBinder::bind_map(binder, b, key_type, val_type);
-    for(xml_coll_t i(e,_U(item)); i; ++i)  {
-      // If explicit key, value data are present in attributes:
-      if ( i.hasAttr(_U(key)) && i.hasAttr(_U(value)) )  {
-        string key = i.attr<string>(_U(key));
-        string val = i.attr<string>(_U(value));
-        OpaqueDataBinder::insert_map(binder, b, key_type, key, val_type, val);
-        continue;
-      }
-      // Otherwise interprete the data directly from the data content
-      OpaqueDataBinder::insert_map(binder, b, key_type, val_type, i.text());
-    }
+    XML::parse_mapping(e, con->data);
     arg->manager.registerUnlocked(arg->pool, con);
   }
 
-  /// Convert rotation objects
-  /**
-   *    <rotation x="0.5" y="0"  z="0"/>
-   *
-   *  \author  M.Frank
-   *  \version 1.0
-   *  \date    01/04/2014
-   */
-  template <> void Converter<rotation>::operator()(xml_h e) const {
-    xml_comp_t r(e);
-    RotationZYX* v = (RotationZYX*)param;
-    v->SetComponents(r.z(), r.y(), r.x());
-    printout(s_parseLevel,"XMLConditions",
-             "++ Rotation:   x=%9.3f y=%9.3f   z=%9.3f  phi=%7.4f psi=%7.4f theta=%7.4f",
-             r.x(), r.y(), r.z(), v->Phi(), v->Psi(), v->Theta());
-  }
-
-  /// Convert position objects
+  /// Convert alignment delta objects. See XML/XMLParsers.h for details.
   /**
-   *    <position x="0.5" y="0"  z="0"/>
-   *
-   *  \author  M.Frank
-   *  \version 1.0
-   *  \date    01/04/2014
-   */
-  template <> void Converter<position>::operator()(xml_h e) const {
-    xml_comp_t p(e);
-    Position* v = (Position*)param;
-    v->SetXYZ(p.x(), p.y(), p.z());
-    printout(s_parseLevel,"XMLConditions","++ Position:   x=%9.3f y=%9.3f   z=%9.3f",
-             v->X(), v->Y(), v->Z());
-  }
-
-  /// Convert pivot objects
-  /**
-   *    <pivot x="0.5" y="0"  z="0"/>
-   *
-   *  \author  M.Frank
-   *  \version 1.0
-   *  \date    01/04/2014
-   */
-  template <> void Converter<pivot>::operator()(xml_h e) const {
-    xml_comp_t p(e);
-    double x,y,z;
-    Translation3D* v = (Translation3D*)param;
-    v->SetXYZ(x=p.x(), y=p.y(), z=p.z());
-    printout(s_parseLevel,"XMLConditions","++ Pivot:      x=%9.3f y=%9.3f   z=%9.3f",x,y,z);
-  }
-
-  /// Convert alignment delta objects
-  /**
-   *     A generic alignment transformation is defined by
-   *     - a translation in 3D space identified in XML as a
-   *         <position/> element
-   *       - a rotation in 3D space around a pivot point specified in XML by
-   *         2 elements: the <rotation/> and the <pivot/> element.
-   *       The specification of any of the elements is optional:
-   *     - The absence of a translation implies the origine (0,0,0)
-   *     - The absence of a pivot point implies the origine (0,0,0)
-   *       - The absence of a rotation implies the identity rotation.
-   *         Any supplied pivot point in this case is ignored.
-   *
-   *      <xx>
-   *        <position x="0" y="0"  z="0.0001*mm"/>
-   *        <rotation x="0" y="0"  z="0"/>
-   *        <pivot    x="0" y="0"  z="100"/>
-   *      </xx>
-   *
    *  \author  M.Frank
    *  \version 1.0
    *  \date    01/04/2014
    */
   template <> void Converter<alignment>::operator()(xml_h e) const {
-    using Alignments::Delta;
-    Position       pos;
-    RotationZYX    rot;
-    Translation3D  piv;
-    xml_h          child_rot, child_pos, child_piv;
-    ConversionArg* arg = _param<ConversionArg>();
-    Condition      con = create_condition(arg->detector, e);
-    Delta&         del = con.bind<Delta>();
-
-    if ( (child_pos=e.child(_U(position),false)) )
-      Converter<position>(lcdd,&del.translation)(child_pos);
-    if ( (child_rot=e.child(_U(rotation),false)) )   {
-      Converter<rotation>(lcdd,&del.rotation)(child_rot);
-      if ( (child_piv=e.child(_U(pivot),false)) )
-        Converter<pivot>(lcdd,&del.pivot)(child_piv);
-    }
-    if ( child_rot && child_pos && child_piv )
-      del.flags |= Delta::HAVE_ROTATION|Delta::HAVE_PIVOT|Delta::HAVE_TRANSLATION;
-    else if ( child_rot && child_pos )
-      del.flags |= Delta::HAVE_ROTATION|Delta::HAVE_TRANSLATION;
-    else if ( child_rot && child_piv )
-      del.flags |= Delta::HAVE_ROTATION|Delta::HAVE_PIVOT;
-    else if ( child_rot )
-      del.flags |= Delta::HAVE_ROTATION;
-    else if ( child_pos )
-      del.flags |= Delta::HAVE_TRANSLATION;
-
+    xml_h              child_rot, child_pos, child_piv;
+    ConversionArg*     arg = _param<ConversionArg>();
+    Condition          con = create_condition(arg->detector, e);
+    XML::parse_delta(e, con->data);
     con->setFlag(Condition::ALIGNMENT);
     arg->manager.registerUnlocked(arg->pool, con);
   }
diff --git a/DDCore/include/XML/XMLParsers.h b/DDCore/include/XML/XMLParsers.h
new file mode 100644
index 000000000..8eca92361
--- /dev/null
+++ b/DDCore/include/XML/XMLParsers.h
@@ -0,0 +1,129 @@
+//==========================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+//  \author   Markus Frank
+//  \date     2017-03-15
+//  \version  1.0
+//
+//==========================================================================
+#ifndef DDCORE_XML_XMLPARSERS_H
+#define DDCORE_XML_XMLPARSERS_H
+
+// Framework include files
+#include "DD4hep/AlignmentData.h"
+#include "XML/XMLElements.h"
+
+// C/C++ include files
+
+
+/// Namespace for the AIDA detector description toolkit
+namespace DD4hep {
+
+  // Forward declarations
+  class OpaqueDataBlock;
+  
+  /// Namespace for the AIDA detector description toolkit supporting XML utilities
+  namespace XML  {
+
+    /// Set debug print level for this module. Default is OFF
+    bool setXMLParserDebug(bool new_value);
+    
+    /// Convert rotation XML objects to DD4hep::Geometry::RotationZYX
+    /**    <rotation x="0.5" y="0"  z="0"/>  => DD4hep::Geometry::RotationZYX
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \date    01/04/2014
+     */
+    void parse(Handle_t e, Geometry::RotationZYX& rot);
+
+    /// Convert XML position objects to DD4hep::Geometry::Position
+    /**
+     *    <position x="0.5" y="0"  z="0"/>  => DD4hep::Geometry::Position
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \date    01/04/2014
+     */
+    void parse(Handle_t e, Geometry::Position& pos);
+
+    /// Convert XML pivot objects to DD4hep::Geometry::Translation3D objects
+    /**
+     *    <pivot x="0.5" y="0"  z="0"/>
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \date    01/04/2014
+     */
+    void parse(Handle_t e, Geometry::Translation3D& tr);
+    
+    /// Convert alignment delta objects to Alignments::Delta
+    /**
+     *     A generic alignment transformation is defined by
+     *     - a translation in 3D space identified in XML as a
+     *         <position/> element
+     *       - a rotation in 3D space around a pivot point specified in XML by
+     *         2 elements: the <rotation/> and the <pivot/> element.
+     *       The specification of any of the elements is optional:
+     *     - The absence of a translation implies the origine (0,0,0)
+     *     - The absence of a pivot point implies the origine (0,0,0)
+     *       - The absence of a rotation implies the identity rotation.
+     *         Any supplied pivot point in this case is ignored.
+     *
+     *      <xx>
+     *        <position x="0" y="0"  z="0.0001*mm"/>
+     *        <rotation x="0" y="0"  z="0"/>
+     *        <pivot    x="0" y="0"    z="100"/>
+     *      </xx>
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \date    01/04/2014
+     */
+    void parse(Handle_t e, Alignments::Delta& delta);
+
+    /// Parse delta into an opaque data block
+    /**
+     *  See void parse(Handle_t e, Alignments::Delta& delta) for details.
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \date    01/04/2014
+     */
+    void parse_delta(Handle_t e, OpaqueDataBlock& block);
+
+    /// Converts opaque maps to OpaqueDataBlock objects
+    /**
+     *  Opaque data mappings are formalized std::map objects (or std::hash_map etc.)
+     *  where the data source is parsed into the map using boost::spirit as a data
+     *  interpretation mechanism.
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \date    01/04/2014
+     */
+    void parse_mapping(Handle_t e, OpaqueDataBlock& block);
+
+    /// Converts linear STL containers from their string representation.
+    /**
+     *  Opaque data sequences are formalized linear STL container objects 
+     *  (std::vector, std::list, std::set, std::deque etc.)
+     *  where the data source is parsed into the map using boost::spirit as a data
+     *  interpretation mechanism.
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \date    01/04/2014
+     */
+    void parse_sequence(Handle_t e, OpaqueDataBlock& block);
+
+    
+  }    /*   End namespace XML            */
+}      /*   End namespace DD4hep         */
+#endif /*   End DDCORE_XML_XMLPARSERS_H  */
diff --git a/DDCore/src/OpaqueDataBinder.cpp b/DDCore/src/OpaqueDataBinder.cpp
index 10759fc86..45b9d224f 100644
--- a/DDCore/src/OpaqueDataBinder.cpp
+++ b/DDCore/src/OpaqueDataBinder.cpp
@@ -137,9 +137,9 @@ namespace DD4hep {
     string value_type = typ.substr(idx+1,idq-idx-1);
     if ( typ.substr(0,6) == "vector" )
       return bind(VectorBinder(), object, value_type, val);
-    else if ( typ.substr(0,6) == "list" )
+    else if ( typ.substr(0,4) == "list" )
       return bind(ListBinder(), object, value_type, val);
-    else if ( typ.substr(0,6) == "set" )
+    else if ( typ.substr(0,3) == "set" )
       return bind(SetBinder(), object, value_type, val);
     else if ( idx == string::npos && idq == string::npos )
       return bind(ValueBinder(), object, value_type, val);
diff --git a/DDCore/src/XML/XMLParsers.cpp b/DDCore/src/XML/XMLParsers.cpp
new file mode 100644
index 000000000..a65f7d3e4
--- /dev/null
+++ b/DDCore/src/XML/XMLParsers.cpp
@@ -0,0 +1,133 @@
+//==========================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+//  \author   Markus Frank
+//  \date     2017-03-15
+//  \version  1.0
+//
+//==========================================================================
+
+// Framework include files
+#include "DD4hep/Objects.h"
+#include "DD4hep/Printout.h"
+#include "DD4hep/OpaqueData.h"
+#include "DD4hep/OpaqueDataBinder.h"
+#include "XML/XMLParsers.h"
+#include "XML/XMLDimension.h"
+#include "XML/DocumentHandler.h"
+
+
+// C/C++ include files
+#include <stdexcept>
+
+using std::string;
+using namespace DD4hep;
+typedef DD4hep::XML::Handle_t  xml_h;
+typedef DD4hep::XML::Dimension xml_dim_t;
+typedef DD4hep::XML::Collection_t xml_coll_t;
+
+namespace {
+  PrintLevel s_print = DEBUG;
+}
+
+/// Set debug level for this module. Default is OFF
+bool DD4hep::XML::setXMLParserDebug(bool value)   {
+  bool old = s_print==ALWAYS;
+  s_print = value ? ALWAYS : DEBUG;
+  return old;
+}
+
+/// Convert rotation XML objects to DD4hep::Geometry::RotationZYX
+void DD4hep::XML::parse(xml_h e, Geometry::RotationZYX& rot)  {
+  xml_dim_t r(e);
+  rot.SetComponents(r.z(), r.y(), r.x());
+  printout(s_print,"Alignment<rot>",
+           "  Rotation:   x=%9.3f y=%9.3f   z=%9.3f  phi=%7.4f psi=%7.4f theta=%7.4f",
+           r.x(), r.y(), r.z(), rot.Phi(), rot.Psi(), rot.Theta());
+}
+
+/// Convert XML position objects to DD4hep::Geometry::Position
+void DD4hep::XML::parse(xml_h e, Geometry::Position& pos)  {
+  xml_dim_t p(e);
+  pos.SetXYZ(p.x(), p.y(), p.z());
+  printout(s_print,"Alignment<pos>","  Position:   x=%9.3f y=%9.3f   z=%9.3f",
+           pos.X(), pos.Y(), pos.Z());
+}
+
+/// Convert XML pivot objects to DD4hep::Geometry::Translation3D objects
+void DD4hep::XML::parse(xml_h e, Geometry::Translation3D& tr)   {
+  xml_dim_t p(e);
+  double x,y,z;
+  tr.SetXYZ(x=p.x(), y=p.y(), z=p.z());
+  printout(s_print,"<pivot>","     Pivot:      x=%9.3f y=%9.3f   z=%9.3f",x,y,z);
+}
+
+/// Convert alignment delta objects to Alignments::Delta
+void DD4hep::XML::parse(xml_h e, Alignments::Delta& delta)  {
+  using Alignments::Delta;
+  Geometry::Position pos;
+  Geometry::RotationZYX rot;
+  Geometry::Translation3D piv;
+  xml_h  child_rot, child_pos, child_piv;
+
+  if ( (child_pos=e.child(_U(position),false)) )
+    parse(child_pos, delta.translation);
+  if ( (child_rot=e.child(_U(rotation),false)) )   {
+    parse(child_rot, delta.rotation);
+    if ( (child_piv=e.child(_U(pivot),false)) )
+      parse(child_piv, delta.pivot);
+  }
+  if ( child_rot && child_pos && child_piv )
+    delta.flags |= Delta::HAVE_ROTATION|Delta::HAVE_PIVOT|Delta::HAVE_TRANSLATION;
+  else if ( child_rot && child_pos )
+    delta.flags |= Delta::HAVE_ROTATION|Delta::HAVE_TRANSLATION;
+  else if ( child_rot && child_piv )
+    delta.flags |= Delta::HAVE_ROTATION|Delta::HAVE_PIVOT;
+  else if ( child_rot )
+    delta.flags |= Delta::HAVE_ROTATION;
+  else if ( child_pos )
+    delta.flags |= Delta::HAVE_TRANSLATION;
+}
+
+/// Parse delta into an opaque data block
+void DD4hep::XML::parse_delta(Handle_t e, OpaqueDataBlock& block)   {
+  Alignments::Delta& delta = block.bind<Alignments::Delta>();
+  parse(e, delta);
+}
+
+/// Converts opaque maps to OpaqueDataBlock objects
+void DD4hep::XML::parse_mapping(xml_h e, OpaqueDataBlock& b)   {
+  string    val_type = e.attr<string>(_U(value));
+  string    key_type = e.attr<string>(_U(key));
+  MapBinder binder;
+
+  OpaqueDataBinder::bind_map(binder, b, key_type, val_type);
+  for(xml_coll_t i(e,_U(item)); i; ++i)  {
+    // If explicit key, value data are present in attributes:
+    if ( i.hasAttr(_U(key)) && i.hasAttr(_U(value)) )  {
+      string key = i.attr<string>(_U(key));
+      string val = i.attr<string>(_U(value));
+      OpaqueDataBinder::insert_map(binder, b, key_type, key, val_type, val);
+      continue;
+    }
+    // Otherwise interprete the data directly from the data content
+    OpaqueDataBinder::insert_map(binder, b, key_type, val_type, i.text());
+  }
+}
+
+/// Converts linear STL containers from their string representation.
+void DD4hep::XML::parse_sequence(xml_h e, OpaqueDataBlock& block)    {
+  xml_dim_t elt(e);
+  string typ = elt.typeStr();
+  string val = elt.hasAttr(_U(value)) ? elt.valueStr() : elt.text();
+  if ( !OpaqueDataBinder::bind_sequence(block, typ, val) )  {
+    except("XMLParsers",
+           "++ Failed to convert unknown sequence conditions type: %s",typ.c_str());
+  }
+}
diff --git a/examples/AlignDet/compact/AlephTPC_alignment.xml b/examples/AlignDet/compact/AlephTPC_alignment.xml
index d8bff42d4..9d829c6c9 100644
--- a/examples/AlignDet/compact/AlephTPC_alignment.xml
+++ b/examples/AlignDet/compact/AlephTPC_alignment.xml
@@ -7,30 +7,29 @@
 	Note: The subdetector name MUST be in the list of top level
 	detector elements attached to the LCDD structure.
 
-A generic alignment transformation is defined by
-- a translation in 3D space identified in XML as a
-<position/> element
-- a rotation in 3D space around a pivot point specified in XML by
-2 elements: the <rotation/> and the <pivot/> element.
-The specification of any of the elements is optional:
-- The absence of a translation implies the origin (0,0,0)
-- The absence of a pivot point implies the origin (0,0,0)
-- The absence of a rotation implies the identity rotation.
-Any supplied pivot point in this case is ignored.
+        A generic alignment transformation is defined by
+        - a translation in 3D space identified in XML as a <position/> element
+        - a rotation in 3D space around a pivot point specified in XML by
+          2 elements: the <rotation/> and the <pivot/> element.
+       The specification of any of the elements is optional:
+        - The absence of a translation implies the origin (0,0,0)
+        - The absence of a pivot point implies the origin (0,0,0)
+        - The absence of a rotation implies the identity rotation.
+        Any supplied pivot point in this case is ignored.
 
-<position x="30"   y="30"  z="80"/>
+        <position x="30"   y="30"  z="80"/>
 
     -->
 
     <detelement path="TPC" reset="true" reset_children="true">
       <comment ref="Move the entire TPC in the world volume."/>
-      <position x="0"   y="0"  z="0*mm"/>
-      <rotation x="0" y="0" z="0"/>     
+      <position x="0"       y="0"  z="0*mm"/>
+      <rotation x="0"       y="0" z="0"/>     
 
       <comment ref="Twist a bit the entire endcap A"/>
       <detelement path="/world/TPC/TPC_SideA" check_overlaps="false">
-	<position x="0"   y="0"  z="-500*mm"/>
-	<rotation x="-0.2" y="-0.2"  z="0"/>
+	<position x="0"     y="0"  z="-500*mm"/>
+	<rotation x="-0.2"  y="-0.2"  z="0"/>
 
 	<comment ref="A detector element relative to the parent"/>
 	<detelement path="TPC_SideA_sector02" check_overlaps="true">
@@ -40,12 +39,12 @@ Any supplied pivot point in this case is ignored.
       </detelement>
 
       <detelement path="TPC_SideA/TPC_SideA_sector03" check_overlaps="true">
-	<position x="0" y="0"    z="290.0*mm"/>
-	<rotation x="0" y="pi/2" z="0"/>     
-	<pivot    x="0" y="0"    z="100"/>     
+	<position x="0"     y="0"    z="290.0*mm"/>
+	<rotation x="0"     y="pi/2" z="0"/>     
+	<pivot    x="0"     y="0"    z="100"/>     
 	<volume path="TPC_sector_K_layer2_2">
-	  <position x="0" y="0"  z="0.0001*mm"/>
-	  <rotation x="0" y="0.5"  z="0"/>     
+	  <position x="0"   y="0"  z="0.0001*mm"/>
+	  <rotation x="0"   y="0.5"  z="0"/>     
 	</volume>
       </detelement>
 
-- 
GitLab