From 202bd291b163360ffd18818592710dc893f068b8 Mon Sep 17 00:00:00 2001
From: Markus Frank <markus.frank@cern.ch>
Date: Thu, 11 Dec 2014 19:56:37 +0000
Subject: [PATCH] Allow for string constants in lcdd define section

---
 DDCore/include/DD4hep/BasicGrammar.h          |   7 +
 DDCore/include/DD4hep/Callback.h              | 133 +++++++++++++++---
 DDCore/include/DD4hep/Dictionary.h            |   7 +
 DDCore/include/DD4hep/GeoHandler.h            |   2 +-
 DDCore/include/DD4hep/Handle.h                |  19 ++-
 DDCore/include/DD4hep/Objects.h               |  20 ++-
 DDCore/include/DD4hep/Plugins.h               |   7 +-
 DDCore/include/DD4hep/Primitives.h            |  27 ++--
 DDCore/include/DD4hep/Readout.h               |   2 +-
 DDCore/include/DD4hep/Segmentations.h         |   2 +-
 DDCore/include/DD4hep/Shapes.h                |   8 ++
 DDCore/include/DD4hep/ToStream.h              |   2 +-
 DDCore/include/DD4hep/VolumeManager.h         |   2 +-
 .../include/DD4hep/objects/ObjectsInterna.h   |  22 +++
 DDCore/include/XML/Evaluator.h                |  14 ++
 DDCore/include/XML/XMLElements.h              |   2 +
 DDCore/src/BasicGrammar.cpp                   |  17 +--
 DDCore/src/Evaluator/Evaluator.cpp            |  40 +++++-
 DDCore/src/GeometryTreeDump.h                 |   3 +-
 DDCore/src/Handle.cpp                         |  43 +++---
 DDCore/src/ObjectExtensions.cpp               |  25 ++--
 DDCore/src/Objects.cpp                        |  18 ++-
 DDCore/src/ObjectsInterna.cpp                 |  14 ++
 DDCore/src/Primitives.cpp                     |  33 ++---
 DDCore/src/Shapes.cpp                         | 107 ++++++++++++++
 DDCore/src/SimpleGDMLWriter.h                 |   4 +-
 DDCore/src/SurfaceInstaller.cpp               |  34 +++--
 DDCore/src/ToStream.cpp                       |  21 ++-
 DDCore/src/XML/DocumentHandler.cpp            |   7 +-
 DDCore/src/XML/XMLElements.cpp                |  43 +++++-
 DDCore/src/plugins/Compact2Objects.cpp        |  15 +-
 DDCore/src/plugins/LCDDConverter.h            |   6 +-
 DDCore/src/plugins/StandardPlugins.cpp        |   3 +
 33 files changed, 556 insertions(+), 153 deletions(-)

diff --git a/DDCore/include/DD4hep/BasicGrammar.h b/DDCore/include/DD4hep/BasicGrammar.h
index 0aae6ca5f..d52e1b6c7 100644
--- a/DDCore/include/DD4hep/BasicGrammar.h
+++ b/DDCore/include/DD4hep/BasicGrammar.h
@@ -18,6 +18,13 @@ namespace DD4hep {
 
   /// Base class describing string evaluation to C++ objects using boost::spirit
   /** 
+   *   Grammar object handle the boost::spirit conversion between strings and numeric
+   *   values/objects. Numeric objects could be atomic (int, long, float, double, etc)
+   *   or complex (vector<int>, vector<float>...). This way e.g. a vector<int> may 
+   *   be converted into a list<double>. The conversion though requires an intermediate
+   *   string representation. For this reason the conversion mechanism is relatively 
+   *   slow and hence should not be used inside number-crunching algorithms.
+   *
    *   \author  M.Frank
    *   \version 1.0
    *   \date    13.08.2013
diff --git a/DDCore/include/DD4hep/Callback.h b/DDCore/include/DD4hep/Callback.h
index 2b1aa2765..9c383609d 100644
--- a/DDCore/include/DD4hep/Callback.h
+++ b/DDCore/include/DD4hep/Callback.h
@@ -22,6 +22,12 @@ namespace DD4hep {
   
   /// Definition of the generic callback structure for member functions
   /**
+   *  The callback structure allows to wrap any member function with up to 
+   *  3 arguments into an abstract objects, which could later be called 
+   *  using the argument list. The pointer to the hosting objects is stored
+   *  in the callback object. The callback objects in this sense behaves 
+   *  very similar to a static function.
+   *
    *  \author  M.Frank
    *  \date    01/03/2013
    *  \version 1.0
@@ -39,36 +45,43 @@ namespace DD4hep {
     void* par;
     func_t call;
     mfunc_t func;
+
     /// Default constructor
     Callback()
         : par(0), call(0) {
       func.first = func.second = 0;
     }
+    /// Constructor with object initialization
     Callback(void* p)
         : par(p), call(0) {
       func.first = func.second = 0;
     }
+    /// Initializing constructor
     Callback(void* p, void* mf, func_t c)
         : par(p), call(c) {
       func = *(mfunc_t*) mf;
     }
-
+    /// Check validity of the callback object
     operator bool() const {
       return (call && par && func.first);
     }
+    /// Execute the callback with the required number of user parameters
     unsigned long execute(const void* user_param[]) const {
       return (*this) ? call(par, &func, user_param) : 0;
     }
-
+    /// Template cast function used internally by the wrapper for type conversion to the object's type
     template <typename T> static T* cast(void* p) {
       return (T*) p;
-    }
+    }    
+    /// Template const cast function used internally by the wrapper for type conversion to the object's type
     template <typename T> static const T* c_cast(const void* p) {
       return (const T*) p;
     }
 
     /// Wrapper around a C++ member function pointer
     /**
+     *  Generic wrapper around a object member function.
+     *
      *  \author  M.Frank
      *  \date    01/03/2013
      *  \version 1.0
@@ -93,15 +106,16 @@ namespace DD4hep {
         return func.ptr;
       }
     };
-    //
-    // Callback with no arguments
-    //
+
+    /** Callback setup with no arguments  */
+    /// Callback setup function for Callbacks with member functions taking no arguments
     template <typename T> const Callback& _make(ulong (*fptr)(void* o, const void* f, const void* u[]), T pmf) {
       typename Wrapper<T>::Functor f(pmf);
       func = f.ptr;
       call = fptr;
       return *this;
     }
+    /// Callback setup function for Callbacks with member functions with explicit return type taking no arguments
     template <typename R, typename T> const Callback& make(R (T::*pmf)()) {
       typedef R (T::*pfunc_t)();
       struct _Wrapper : public Wrapper<pfunc_t> {
@@ -111,6 +125,7 @@ namespace DD4hep {
       };
       return _make(_Wrapper::call, pmf);
     }
+    /// Callback setup function for Callbacks with const member functions with explicit return type taking no arguments
     template <typename R, typename T> const Callback& make(R (T::*pmf)() const) {
       typedef R (T::*pfunc_t)() const;
       struct _Wrapper : public Wrapper<pfunc_t> {
@@ -120,6 +135,7 @@ namespace DD4hep {
       };
       return _make(_Wrapper::call, pmf);
     }
+    /// Callback setup function for Callbacks with void member functions taking no arguments
     template <typename T> const Callback& make(void (T::*pmf)()) {
       typedef void (T::*pfunc_t)() const;
       struct _Wrapper : public Wrapper<pfunc_t> {
@@ -130,6 +146,7 @@ namespace DD4hep {
       };
       return _make(_Wrapper::call, pmf);
     }
+    /// Callback setup function for Callbacks with const void member functions taking no arguments
     template <typename T> const Callback& make(void (T::*pmf)() const) {
       typedef void (T::*pfunc_t)() const;
       struct _Wrapper : public Wrapper<pfunc_t> {
@@ -140,9 +157,9 @@ namespace DD4hep {
       };
       return _make(_Wrapper::call, pmf);
     }
-    //
-    // Callback with 1 argument
-    //
+
+    /** Callbacks with 1 argument  */
+    /// Callback setup function for Callbacks with member functions with explicit return type taking 1 argument
     template <typename R, typename T, typename A> const Callback& make(R (T::*pmf)(A)) {
       typedef R (T::*pfunc_t)(A);
       struct _Wrapper : public Wrapper<pfunc_t> {
@@ -152,6 +169,7 @@ namespace DD4hep {
       };
       return _make(_Wrapper::call, pmf);
     }
+    /// Callback setup function for Callbacks with const member functions with explicit return type taking 1 argument
     template <typename R, typename T, typename A> const Callback& make(R (T::*pmf)(A) const) {
       typedef R (T::*pfunc_t)(A) const;
       struct _Wrapper : public Wrapper<pfunc_t> {
@@ -161,6 +179,7 @@ namespace DD4hep {
       };
       return _make(_Wrapper::call, pmf);
     }
+    /// Callback setup function for Callbacks with void member functions taking 1 argument
     template <typename T, typename A> const Callback& make(void (T::*pmf)(A)) {
       typedef void (T::*pfunc_t)(const A);
       struct _Wrapper : public Wrapper<pfunc_t> {
@@ -171,6 +190,7 @@ namespace DD4hep {
       };
       return _make(_Wrapper::call, pmf);
     }
+    /// Callback setup function for Callbacks with const void member functions taking 1 argument
     template <typename T, typename A> const Callback& make(void (T::*pmf)(A) const) {
       typedef void (T::*pfunc_t)(const A) const;
       struct _Wrapper : public Wrapper<pfunc_t> {
@@ -181,9 +201,10 @@ namespace DD4hep {
       };
       return _make(_Wrapper::call, pmf);
     }
-    //
-    // Callback with 2 arguments
-    //
+
+    /** Callback with 2 arguments     */
+
+    /// Callback setup function for Callbacks with member functions with explicit return type taking 2 arguments
     template <typename R, typename T, typename A0, typename A1> const Callback& make(R (T::*pmf)(A0, A1)) {
       typedef R (T::*pfunc_t)(A0, A1);
       typedef Wrapper<pfunc_t> _W;
@@ -194,6 +215,7 @@ namespace DD4hep {
       };
       return _make(_Wrapper::call, pmf);
     }
+    /// Callback setup function for Callbacks with const member functions with explicit return type taking 2 arguments
     template <typename R, typename T, typename A0, typename A1> const Callback& make(R (T::*pmf)(A0, A1) const) {
       typedef R (T::*pfunc_t)(A0, A1);
       typedef Wrapper<pfunc_t> _W;
@@ -204,6 +226,7 @@ namespace DD4hep {
       };
       return _make(_Wrapper::call, pmf);
     }
+    /// Callback setup function for Callbacks with const void member functions taking 2 arguments
     template <typename T, typename A0, typename A1> const Callback& make(void (T::*pmf)(A0, A1)) {
       typedef void (T::*pfunc_t)(A0, A1);
       typedef Wrapper<pfunc_t> _W;
@@ -215,6 +238,7 @@ namespace DD4hep {
       };
       return _make(_Wrapper::call, pmf);
     }
+    /// Callback setup function for Callbacks with const void member functions taking 2 arguments
     template <typename T, typename A0, typename A1> const Callback& make(void (T::*pmf)(A0, A1) const) {
       typedef void (T::*pfunc_t)(A0, A1);
       typedef Wrapper<pfunc_t> _W;
@@ -226,9 +250,10 @@ namespace DD4hep {
       };
       return _make(_Wrapper::call, pmf);
     }
-    //
-    // Callback with 3 arguments
-    //
+
+    /** Callback setup for callbacks with 3 arguments  */
+
+    /// Callback setup function for Callbacks with member functions with explicit return type taking 3 arguments
     template <typename R, typename T, typename A0, typename A1, typename A2> const Callback& make(R (T::*pmf)(A0, A1, A2)) {
       typedef R (T::*pfunc_t)(A0, A1, A2);
       typedef Wrapper<pfunc_t> _W;
@@ -239,6 +264,7 @@ namespace DD4hep {
       };
       return _make(_Wrapper::call, pmf);
     }
+    /// Callback setup function for Callbacks with const member functions with explicit return type taking 3 arguments
     template <typename R, typename T, typename A0, typename A1, typename A2> const Callback& make(
         R (T::*pmf)(A0, A1, A2) const) {
       typedef R (T::*pfunc_t)(A0, A1, A2);
@@ -250,6 +276,7 @@ namespace DD4hep {
       };
       return _make(_Wrapper::call, pmf);
     }
+    /// Callback setup function for Callbacks with const void member functions taking 3 arguments
     template <typename T, typename A0, typename A1, typename A2> const Callback& make(void (T::*pmf)(A0, A1, A2)) {
       typedef void (T::*pfunc_t)(A0, A1, A2);
       typedef Wrapper<pfunc_t> _W;
@@ -261,6 +288,7 @@ namespace DD4hep {
       };
       return _make(_Wrapper::call, pmf);
     }
+    /// Callback setup function for Callbacks with const void member functions taking 3 arguments
     template <typename T, typename A0, typename A1, typename A2> const Callback& make(void (T::*pmf)(A0, A1, A2) const) {
       typedef void (T::*pfunc_t)(A0, A1, A2);
       typedef Wrapper<pfunc_t> _W;
@@ -294,9 +322,13 @@ namespace DD4hep {
 
   /// Definition of an actor on sequences of callbacks
   /**
-   * @author  M.Frank
-   * @date    01/03/2013
-   * @version 0.1
+   *  A callback sequence is a set of callbacks with identical signature, so that
+   *  the can be called consecutively using the same arguments.
+   *
+   *  \author  M.Frank
+   *  \date    01/03/2013
+   *  \version 0.1
+   *  \ingroup DD4HEP
    */
   struct CallbackSequence {
     typedef std::vector<Callback> Callbacks;
@@ -321,9 +353,11 @@ namespace DD4hep {
     bool empty() const {
       return callbacks.empty();
     }
+    /// Clear the sequence and remove all callbacks
     void clear() {
       callbacks.clear();
     }
+    /// Generically Add a new callback to the sequence depending on the location arguments
     void add(const Callback& cb,Location where) {
       if ( where == CallbackSequence::FRONT )
 	callbacks.insert(callbacks.begin(),cb);
@@ -341,21 +375,84 @@ namespace DD4hep {
     /// Check the compatibility of two typed objects. The test is the result of a dynamic_cast
     static void checkTypes(const std::type_info& typ1, const std::type_info& typ2, void* test);
 
+    /** Callback setup for callbacks with no arguments  */
+    /// Add a new callback to a member function with explicit return type and no arguments
     template <typename TYPE, typename R, typename OBJECT>
       void add(TYPE* pointer, R (OBJECT::*pmf)(),Location where=CallbackSequence::END) {
       checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
       add(Callback(pointer).make(pmf),where);
     }
+    /// Add a new callback to a const member function with explicit return type and no arguments
+    template <typename TYPE, typename R, typename OBJECT>
+      void add(TYPE* pointer, R (OBJECT::*pmf)() const,Location where=CallbackSequence::END) {
+      checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
+      add(Callback(pointer).make(pmf),where);
+    }
+    /// Add a new callback to a void member function with no arguments
+    template <typename TYPE, typename OBJECT>
+      void add(TYPE* pointer, void (OBJECT::*pmf)(),Location where=CallbackSequence::END) {
+      checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
+      add(Callback(pointer).make(pmf),where);
+    }
+    /// Add a new callback to a const void member function and no arguments
+    template <typename TYPE, typename OBJECT>
+      void add(TYPE* pointer, void (OBJECT::*pmf)() const,Location where=CallbackSequence::END) {
+      checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
+      add(Callback(pointer).make(pmf),where);
+    }
+
+    /** Callback setup for callbacks with 1 argument  */
+    /// Add a new callback to a member function with explicit return type and 1 argument
     template <typename TYPE, typename R, typename OBJECT, typename A>
     void add(TYPE* pointer, R (OBJECT::*pmf)(A),Location where=CallbackSequence::END) {
       checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
       add(Callback(pointer).make(pmf),where);
     }
+    /// Add a new callback to a void member function and 1 argument
+    template <typename TYPE, typename OBJECT, typename A>
+    void add(TYPE* pointer, void (OBJECT::*pmf)(A),Location where=CallbackSequence::END) {
+      checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
+      add(Callback(pointer).make(pmf),where);
+    }
+    /// Add a new callback to a const member function with explicit return type and 1 argument
+    template <typename TYPE, typename R, typename OBJECT, typename A>
+    void add(TYPE* pointer, R (OBJECT::*pmf)(A) const,Location where=CallbackSequence::END) {
+      checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
+      add(Callback(pointer).make(pmf),where);
+    }
+    /// Add a new callback to a const void member function and 1 argument
+    template <typename TYPE, typename OBJECT, typename A>
+    void add(TYPE* pointer, void (OBJECT::*pmf)(A) const,Location where=CallbackSequence::END) {
+      checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
+      add(Callback(pointer).make(pmf),where);
+    }
+
+
+    /** Callback setup for callbacks with 2 arguments  */
+    /// Add a new callback to a member function with explicit return type and 2 arguments
     template <typename TYPE, typename R, typename OBJECT, typename A1, typename A2>
     void add(TYPE* pointer, R (OBJECT::*pmf)(A1, A2),Location where=CallbackSequence::END) {
       checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
       add(Callback(pointer).make(pmf),where);
     }
+    /// Add a new callback to a const member function with explicit return type and 2 arguments
+    template <typename TYPE, typename R, typename OBJECT, typename A1, typename A2>
+    void add(TYPE* pointer, R (OBJECT::*pmf)(A1, A2) const,Location where=CallbackSequence::END) {
+      checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
+      add(Callback(pointer).make(pmf),where);
+    }
+    /// Add a new callback to a void member function with 2 arguments
+    template <typename TYPE, typename OBJECT, typename A1, typename A2>
+    void add(TYPE* pointer, void (OBJECT::*pmf)(A1, A2),Location where=CallbackSequence::END) {
+      checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
+      add(Callback(pointer).make(pmf),where);
+    }
+    /// Add a new callback to a const void member function with 2 arguments
+    template <typename TYPE, typename OBJECT, typename A1, typename A2>
+    void add(TYPE* pointer, void (OBJECT::*pmf)(A1, A2) const,Location where=CallbackSequence::END) {
+      checkTypes(typeid(TYPE), typeid(OBJECT), dynamic_cast<OBJECT*>(pointer));
+      add(Callback(pointer).make(pmf),where);
+    }
   };
 
   /// Execution overload for callbacks with no arguments
diff --git a/DDCore/include/DD4hep/Dictionary.h b/DDCore/include/DD4hep/Dictionary.h
index a5d85ac53..b87d76304 100644
--- a/DDCore/include/DD4hep/Dictionary.h
+++ b/DDCore/include/DD4hep/Dictionary.h
@@ -110,22 +110,29 @@ template class DD4hep::Geometry::Handle<TNamed>;
 // Objects.h
 #pragma link C++ class DD4hep::Geometry::Author+;
 #pragma link C++ class vector<DD4hep::Geometry::Author>+;
+
 #pragma link C++ class DD4hep::Geometry::Header+;
 #pragma link C++ class DD4hep::Geometry::HeaderObject+;
 #pragma link C++ class DD4hep::Geometry::Handle<DD4hep::Geometry::HeaderObject>+;
 
 #pragma link C++ class DD4hep::Geometry::Constant+;
+#pragma link C++ class DD4hep::Geometry::ConstantObject+;
+#pragma link C++ class DD4hep::Geometry::Handle<DD4hep::Geometry::ConstantObject>+;
 #pragma link C++ class vector<DD4hep::Geometry::Constant>+;
+
 #pragma link C++ class DD4hep::Geometry::Atom+;
 #pragma link C++ class vector<DD4hep::Geometry::Atom>+;
 #pragma link C++ class DD4hep::Geometry::Handle<TGeoElement>+;
+
 #pragma link C++ class DD4hep::Geometry::Material+;
 #pragma link C++ class vector<DD4hep::Geometry::Material>+;
 #pragma link C++ class DD4hep::Geometry::Handle<TGeoMedium>+;
+
 #pragma link C++ class DD4hep::Geometry::VisAttr+;
 #pragma link C++ class vector<DD4hep::Geometry::VisAttr>+;
 #pragma link C++ class DD4hep::Geometry::VisAttrObject+;
 #pragma link C++ class DD4hep::Geometry::Handle<DD4hep::Geometry::VisAttrObject>+;
+
 #pragma link C++ class DD4hep::Geometry::AlignmentEntry+;
 #pragma link C++ class DD4hep::Geometry::Limit+;
 #pragma link C++ class set<DD4hep::Geometry::Limit>+;
diff --git a/DDCore/include/DD4hep/GeoHandler.h b/DDCore/include/DD4hep/GeoHandler.h
index db870c0f4..d930734ce 100644
--- a/DDCore/include/DD4hep/GeoHandler.h
+++ b/DDCore/include/DD4hep/GeoHandler.h
@@ -136,7 +136,7 @@ namespace DD4hep {
      *  \version 1.0
      *  \ingroup DD4HEP_GEOMETRY
      */
-    struct GeoScan {
+    class GeoScan {
     protected:
       /// Data holder
       GeoHandler::Data* m_data;
diff --git a/DDCore/include/DD4hep/Handle.h b/DDCore/include/DD4hep/Handle.h
index 579a8281c..a2354f142 100644
--- a/DDCore/include/DD4hep/Handle.h
+++ b/DDCore/include/DD4hep/Handle.h
@@ -143,8 +143,10 @@ namespace DD4hep {
       return left * _toDouble(right);
     }
 
-    /// Enter name value pair to the dictionary. \"valye\" must be a numerical expression, which is evaluated  \ingroup DD4HEP_GEOMETRY
+    /// Enter name value pair to the dictionary. \"value\" must be a numerical expression, which is evaluated  \ingroup DD4HEP_GEOMETRY
     void _toDictionary(const std::string& name, const std::string& value);
+    /// Enter name value pair to the dictionary.  \ingroup DD4HEP_GEOMETRY
+    void _toDictionary(const std::string& name, const std::string& value, const std::string& typ);
 
     long num_object_validations();
     void increment_object_validations();
@@ -186,9 +188,13 @@ namespace DD4hep {
      */
     template <typename T> class Handle {
     public:
+      /** Type definitions and class specific abbreviations and forward declarations */
+      /// Extern accessible definition of the contained element type
       typedef T Implementation;
+      /// Declaration of 'self'
       typedef Handle<Implementation> handle_t;
-      /// Reference to the actual element.
+
+      /// Single and only data member: Reference to the actual element.
       T* m_element;
       /// Defaulot constructor
       Handle()
@@ -293,19 +299,22 @@ namespace DD4hep {
       releasePtr(h.m_element);
     }
     /// Functor to destroy handles and delete the cached object  \ingroup DD4HEP_GEOMETRY
-    template <typename T> struct DestroyHandle {
+    template <typename T> class DestroyHandle {
+    public:
       void operator()(T p) const {
         destroyHandle(p);
       }
     };
     /// Functor to destroy handles and delete the cached object  \ingroup DD4HEP_GEOMETRY
-    template <typename T> struct ReleaseHandle {
+    template <typename T> class ReleaseHandle {
+    public:
       void operator()(T p) const {
         releaseHandle(p);
       }
     };
     /// map Functor to destroy handles and delete the cached object  \ingroup DD4HEP_GEOMETRY
-    template <typename M> struct DestroyHandles {
+    template <typename M> class DestroyHandles {
+    public:
       M& object;
       DestroyHandles(M& m)
           : object(m) {
diff --git a/DDCore/include/DD4hep/Objects.h b/DDCore/include/DD4hep/Objects.h
index 7ca2cc283..117d0c5ee 100644
--- a/DDCore/include/DD4hep/Objects.h
+++ b/DDCore/include/DD4hep/Objects.h
@@ -14,6 +14,7 @@
 #include "DD4hep/Handle.h"
 #include "DD4hep/NamedObject.h"
 
+// Forward declarations
 class TMap;
 class TGeoElement;
 class TGeoMaterial;
@@ -23,6 +24,8 @@ class TGeoRotation;
 class TGeoTranslation;
 class TGeoPhysicalNode;
 class TGeoIdentity;
+
+// ROOT include files
 #include "TGeoPhysicalNode.h"
 #include "Math/Vector3D.h"
 #include "Math/Transform3D.h"
@@ -57,13 +60,14 @@ namespace DD4hep {
     class IDDescriptor;
     class VisAttrObject;
     class HeaderObject;
+    class ConstantObject;
     class RegionObject;
     class LimitSetObject;
 
     /** Access to identity transformation  */
     TGeoIdentity* identityTransform();
 
-    /// Handle class describing an author identity
+    /// Handle class describing an author entity
     /** 
      *  \author  M.Frank
      *  \version 1.0
@@ -176,27 +180,29 @@ namespace DD4hep {
      *  \version 1.0
      *  \ingroup DD4HEP_GEOMETRY
      */
-    class Constant: public Ref_t {
+    class Constant: public Handle<ConstantObject> {
     public:
       /// Definition of the implementation type
-      typedef NamedObject Object;
+      typedef ConstantObject Object;
       /// Default constructor
       Constant()
-          : Ref_t() {
+          : Handle<ConstantObject> () {
       }
       /// Constructorto be used for assignment from a handle
       Constant(const Constant& e)
-          : Ref_t(e) {
+          : Handle<ConstantObject> (e) {
       }
       /// Constructor to be used when reading the already parsed DOM tree
       template <typename Q>
       Constant(const Handle<Q>& e)
-          : Ref_t(e) {
+          : Handle<ConstantObject> (e) {
       }
       /// Constructor to be used when creating a new DOM tree
       Constant(const std::string& name);
       /// Constructor to be used when creating a new DOM tree
-      Constant(const std::string& name, const std::string& val);
+      Constant(const std::string& name, const std::string& val, const std::string& typ="number");
+      /// Access the constant
+      std::string type() const;
       /// String representation of this object
       std::string toString() const;
     };
diff --git a/DDCore/include/DD4hep/Plugins.h b/DDCore/include/DD4hep/Plugins.h
index 54df4f337..72dd8bf20 100644
--- a/DDCore/include/DD4hep/Plugins.h
+++ b/DDCore/include/DD4hep/Plugins.h
@@ -16,6 +16,7 @@
 /// Namespace for the AIDA detector description toolkit
 namespace DD4hep {
 
+  // Forward declarations
   typedef ROOT::Reflex::PluginService PluginService;
 
   /// Helper to debug plugin manager calls
@@ -38,7 +39,7 @@ namespace DD4hep {
     std::string missingFactory(const std::string& name) const;
   };
 
-} /* End namespace DD4hep    */
-#endif
+} /* End namespace DD4hep      */
 
-#endif    /* DD4HEP_PLUGINS_H        */
+#endif    /* __CINT__          */
+#endif    /* DD4HEP_PLUGINS_H  */
diff --git a/DDCore/include/DD4hep/Primitives.h b/DDCore/include/DD4hep/Primitives.h
index ecebfac5a..1dbc74efc 100644
--- a/DDCore/include/DD4hep/Primitives.h
+++ b/DDCore/include/DD4hep/Primitives.h
@@ -143,14 +143,16 @@ namespace DD4hep {
     deletePtr(p);
   }
   /// Functor to delete objects from heap and reset the pointer
-  template <typename T> struct DestroyObject {
+  template <typename T> class DestroyObject {
+  public:
     void operator()(T& p) const {
       destroyObject(p);
     }
   };
 
   /// Operator to select second element of a pair
-  template <typename T> struct Select2nd  {
+  template <typename T> class Select2nd  {
+  public:
     typedef T arg_t;
     typedef typename T::second_type result_t;
     /// Operator function
@@ -161,7 +163,8 @@ namespace DD4hep {
     { return Select2nd<typename T::value_type>(); }
 
   /// Operator to select the first element of a pair
-  template <typename T> struct Select1st  {
+  template <typename T> class Select1st  {
+  public:
     typedef T arg_t;
     typedef typename T::first_type result_t;
     /// Operator function
@@ -173,7 +176,8 @@ namespace DD4hep {
 
 
   /// map Functor to delete objects from heap
-  template <typename M> struct DestroyObjects {
+  template <typename M> class DestroyObjects {
+  public:
     M& object;
     DestroyObjects(M& m)
         : object(m) {
@@ -196,7 +200,8 @@ namespace DD4hep {
   }
 
   /// map Functor to delete objects from heap
-  template <typename M> struct DestroyFirst {
+  template <typename M> class DestroyFirst {
+  public:
     M& object;
     DestroyFirst(M& m)
         : object(m) {
@@ -226,13 +231,15 @@ namespace DD4hep {
   }
 
   /// Functor to release objects from heap and reset the pointer
-  template <typename T> struct ReleaseObject {
+  template <typename T> class ReleaseObject {
+  public:
     void operator()(T& p) const {
       releasePtr(p);
     }
   };
   /// Map Functor to release objects from heap
-  template <typename M> struct ReleaseObjects {
+  template <typename M> class ReleaseObjects {
+  public:
     M& object;
     ReleaseObjects(M& m)
         : object(m) {
@@ -258,7 +265,8 @@ namespace DD4hep {
   }
 
   /// Functor to delete objects from heap and reset the pointer
-  template <typename T> struct ReferenceObject {
+  template <typename T> class ReferenceObject {
+  public:
     typedef T arg_t;
     T operator()(T p) const {
       if ( p ) p->addRef();
@@ -266,7 +274,8 @@ namespace DD4hep {
     }
   };
   /// Functor to delete objects from heap and reset the pointer
-  template <typename M> struct ReferenceObjects {
+  template <typename M> class ReferenceObjects {
+  public:
     typedef typename M::second_type result_t;
     result_t operator()(const M& p) const {
       return ReferenceObject<result_t>()(p.second);
diff --git a/DDCore/include/DD4hep/Readout.h b/DDCore/include/DD4hep/Readout.h
index bdd515c51..dc2f183fe 100644
--- a/DDCore/include/DD4hep/Readout.h
+++ b/DDCore/include/DD4hep/Readout.h
@@ -35,7 +35,7 @@ namespace DD4hep {
      *   \version 1.0
      *   \ingroup DD4HEP_GEOMETRY
      */
-    struct Readout: public Handle<ReadoutObject> {
+    class Readout: public Handle<ReadoutObject> {
     public:
       /// Implementation type
       typedef ReadoutObject Object;
diff --git a/DDCore/include/DD4hep/Segmentations.h b/DDCore/include/DD4hep/Segmentations.h
index db4b59946..361cc5516 100644
--- a/DDCore/include/DD4hep/Segmentations.h
+++ b/DDCore/include/DD4hep/Segmentations.h
@@ -82,7 +82,7 @@ namespace DD4hep {
      *   \version 1.0
      *   \ingroup DD4HEP_GEOMETRY
      */
-    struct Segmentation: public Handle<SegmentationObject> {
+    class Segmentation: public Handle<SegmentationObject> {
     public:
       typedef SegmentationObject Object;
       typedef DDSegmentation::Segmentation BaseSegmentation;
diff --git a/DDCore/include/DD4hep/Shapes.h b/DDCore/include/DD4hep/Shapes.h
index 7659b4e94..9192acf94 100644
--- a/DDCore/include/DD4hep/Shapes.h
+++ b/DDCore/include/DD4hep/Shapes.h
@@ -37,6 +37,9 @@ namespace DD4hep {
 
     // Forward declarations
 
+    /// Pretty print of solid attributes
+    std::string toStringSolid(const TGeoShape* shape, int precision=2);
+
     ///  Base class for Solid (shape) objects
     /**
      *   Generic handle holding an object of base TGeoShape.
@@ -89,6 +92,11 @@ namespace DD4hep {
       T* operator->() const {
         return this->m_element;
       }
+
+      /// Conversion to string for pretty print
+      std::string toString(int precision=2) const   {
+	return toStringSolid(this->m_element,precision);
+      }
     };
     typedef Solid_type<TGeoShape> Solid;
 
diff --git a/DDCore/include/DD4hep/ToStream.h b/DDCore/include/DD4hep/ToStream.h
index d690f2875..a584152f5 100644
--- a/DDCore/include/DD4hep/ToStream.h
+++ b/DDCore/include/DD4hep/ToStream.h
@@ -22,7 +22,7 @@
 #include "Math/Vector4D.h"
 
 // ============================================================================
-/** @file DD4hepKernel/ToStream.h
+/** @file DD4hep/ToStream.h
  *  implemenattiono fvarioud functions for streaming.
  *  this functionality is essenital for usag eof varuodu types as property for
  *  the various DD4hep components
diff --git a/DDCore/include/DD4hep/VolumeManager.h b/DDCore/include/DD4hep/VolumeManager.h
index a023fd51a..f5c643745 100644
--- a/DDCore/include/DD4hep/VolumeManager.h
+++ b/DDCore/include/DD4hep/VolumeManager.h
@@ -62,7 +62,7 @@ namespace DD4hep {
      *   \version 1.0
      *   \ingroup DD4HEP_GEOMETRY
      */
-    struct VolumeManager: public Handle<VolumeManagerObject> {
+    class VolumeManager: public Handle<VolumeManagerObject> {
     public:
       typedef DD4hep::VolumeID VolumeID;
       typedef VolumeID VolIdentifier;
diff --git a/DDCore/include/DD4hep/objects/ObjectsInterna.h b/DDCore/include/DD4hep/objects/ObjectsInterna.h
index 28667566e..2b57bea93 100644
--- a/DDCore/include/DD4hep/objects/ObjectsInterna.h
+++ b/DDCore/include/DD4hep/objects/ObjectsInterna.h
@@ -52,6 +52,28 @@ namespace DD4hep {
       HeaderObject& operator=(const HeaderObject&) { return *this; }
     };
 
+    /// Concrete object implementation for the Constant handle
+    /**
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_GEOMETRY
+     */
+    class ConstantObject: public NamedObject {
+    public:
+      /// Constant type
+      std::string m_type;
+      /// Standard constructor
+      ConstantObject(const std::string& nam, const std::string& val, const std::string& typ);
+      /// Default destructor
+      virtual ~ConstantObject();
+    private:
+      /// Private copy constructor
+      ConstantObject(const ConstantObject&) : NamedObject() {}
+      /// Private assignment operator
+      ConstantObject& operator=(const ConstantObject&) { return *this; }
+    };
+
     /// Concrete object implementation of the VisAttr Handle
     /**
      *
diff --git a/DDCore/include/XML/Evaluator.h b/DDCore/include/XML/Evaluator.h
index cd24242bd..8260759c0 100644
--- a/DDCore/include/XML/Evaluator.h
+++ b/DDCore/include/XML/Evaluator.h
@@ -91,6 +91,20 @@ namespace XmlTools {
      */
     void print_error() const;
 
+    /**
+     * Adds to the dictionary a string constant
+     *
+     * @param name name of the variable.
+     * @param value value assigned to the variable.
+     */
+    void setEnviron(const char* name, const char* value);
+    /**
+     * Lookup the dictionary for a string constant
+     *
+     * @param name name of the variable.
+     * @param value value assigned to the variable.
+     */
+    const char* getEnviron(const char* name);
     /**
      * Adds to the dictionary a variable with given value.
      * If a variable with such a name already exist in the dictionary,
diff --git a/DDCore/include/XML/XMLElements.h b/DDCore/include/XML/XMLElements.h
index 3ac19a1da..34693e07d 100644
--- a/DDCore/include/XML/XMLElements.h
+++ b/DDCore/include/XML/XMLElements.h
@@ -124,6 +124,8 @@ namespace DD4hep {
     void _toDictionary(const XmlChar* name, float  value);
     /// Helper function to populate the evaluator dictionary  \ingroup DD4HEP_XML
     void _toDictionary(const XmlChar* name, double value);
+    /// Helper function to lookup environment from the expression evaluator
+    std::string getEnviron(const std::string& env);
 
     /// Conversion function from raw unicode string to bool  \ingroup DD4HEP_XML
     bool _toBool(const XmlChar* value);
diff --git a/DDCore/src/BasicGrammar.cpp b/DDCore/src/BasicGrammar.cpp
index 2e481dd7b..1ba3a9cec 100644
--- a/DDCore/src/BasicGrammar.cpp
+++ b/DDCore/src/BasicGrammar.cpp
@@ -15,28 +15,25 @@
 // C/C++ include files
 #include <stdexcept>
 
-using namespace std;
-using namespace DD4hep;
-
 /// Default constructor
-BasicGrammar::BasicGrammar()  {
+DD4hep::BasicGrammar::BasicGrammar()  {
 }
 
 /// Default destructor
-BasicGrammar::~BasicGrammar()   {
+DD4hep::BasicGrammar::~BasicGrammar()   {
 }
 
 /// Error callback on invalid conversion
-void BasicGrammar::invalidConversion(const string& value, const type_info& to) {
-  string to_name = typeName(to);
+void DD4hep::BasicGrammar::invalidConversion(const std::string& value, const std::type_info& to) {
+  std::string to_name = typeName(to);
   throw unrelated_value_error(to,
       "The Property data conversion of '" + value + "' to type " + to_name + " is not defined.");
 }
 
 /// Error callback on invalid conversion
-void BasicGrammar::invalidConversion(const type_info& from, const type_info& to) {
-  string to_name = typeName(to);
-  string from_name = typeName(from);
+void DD4hep::BasicGrammar::invalidConversion(const std::type_info& from, const std::type_info& to) {
+  std::string to_name = typeName(to);
+  std::string from_name = typeName(from);
   throw unrelated_type_error(from, to,
       "The Property data conversion from type " + from_name + " to " + to_name + " is not implemented.");
 }
diff --git a/DDCore/src/Evaluator/Evaluator.cpp b/DDCore/src/Evaluator/Evaluator.cpp
index 34fc22f0a..6b4cbf29e 100644
--- a/DDCore/src/Evaluator/Evaluator.cpp
+++ b/DDCore/src/Evaluator/Evaluator.cpp
@@ -16,7 +16,7 @@
 
 //---------------------------------------------------------------------------
 struct Item {
-  enum { UNKNOWN, VARIABLE, EXPRESSION, FUNCTION } what;
+  enum { UNKNOWN, VARIABLE, EXPRESSION, FUNCTION, STRING } what;
   double variable;
   string expression;
   void   *function;
@@ -665,6 +665,44 @@ void Evaluator::print_error() const {
   }
 }
 
+//---------------------------------------------------------------------------
+void Evaluator::setEnviron(const char* name, const char* value)  {
+  Struct* s = (Struct *)p;
+  string prefix = "${";
+  string item_name = prefix + string(name) + string("}");
+  dic_type::iterator iter = (s->theDictionary).find(item_name);
+  Item item;
+  item.what = Item::STRING;
+  item.expression = value;
+  item.function = 0;
+  item.variable = 0;
+  //std::cout << " ++++++++++++++++++++++++++++ Saving env:" << name << " = " << value << std::endl;
+  if (iter != (s->theDictionary).end()) {
+    iter->second = item;
+    if (item_name == name) {
+      s->theStatus = EVAL::WARNING_EXISTING_VARIABLE;
+    }else{
+      s->theStatus = EVAL::WARNING_EXISTING_FUNCTION;
+    }
+  }else{
+    (s->theDictionary)[item_name] = item;
+    s->theStatus = EVAL::OK;
+  }
+}
+//---------------------------------------------------------------------------
+const char* Evaluator::getEnviron(const char* name)  {
+  Struct* s = (Struct *)p;
+  string item_name = name;
+  //std::cout << " ++++++++++++++++++++++++++++ Try to resolve env:" << name << std::endl;
+  dic_type::iterator iter = (s->theDictionary).find(item_name);
+  if (iter == (s->theDictionary).end()) {
+    s->theStatus = EVAL::ERROR_UNKNOWN_VARIABLE;
+    return 0;
+  }
+  s->theStatus = EVAL::OK;
+  return iter->second.expression.c_str();
+}
+
 //---------------------------------------------------------------------------
 void Evaluator::setVariable(const char * name, double value)
 { setItem("", name, Item(value), (Struct *)p); }
diff --git a/DDCore/src/GeometryTreeDump.h b/DDCore/src/GeometryTreeDump.h
index 399b4f0a6..e833949df 100644
--- a/DDCore/src/GeometryTreeDump.h
+++ b/DDCore/src/GeometryTreeDump.h
@@ -29,7 +29,8 @@ namespace DD4hep {
      *  \version 1.0
      *  \ingroup DD4HEP_GEOMETRY
      */
-    struct GeometryTreeDump: public GeoHandler {
+    class GeometryTreeDump: public GeoHandler {
+    public:
       GeometryTreeDump() {
       }
       /// Standard destructor
diff --git a/DDCore/src/Handle.cpp b/DDCore/src/Handle.cpp
index 1fc3ea21a..7b39fa7b7 100644
--- a/DDCore/src/Handle.cpp
+++ b/DDCore/src/Handle.cpp
@@ -64,7 +64,7 @@ long DD4hep::Geometry::_toLong(const string& value) {
 }
 
 bool DD4hep::Geometry::_toBool(const string& value) {
-  return value == "true";
+  return value == "true" || value == "yes";
 }
 
 float DD4hep::Geometry::_toFloat(const string& value) {
@@ -104,22 +104,33 @@ template <> double DD4hep::Geometry::_multiply<double>(const string& left, const
 }
 
 void DD4hep::Geometry::_toDictionary(const string& name, const string& value) {
-  string n = name, v = value;
-  size_t idx = v.find("(int)");
-  if (idx != string::npos)
-    v.erase(idx, 5);
-  idx = v.find("(float)");
-  if (idx != string::npos)
-    v.erase(idx, 7);
-  while (v[0] == ' ')
-    v.erase(0, 1);
-  double result = eval.evaluate(v.c_str());
-  if (eval.status() != XmlTools::Evaluator::OK) {
-    cerr << value << ": ";
-    eval.print_error();
-    throw runtime_error("DD4hep: Severe error during expression evaluation " + name + "=" + value);
+  _toDictionary(name, value, "number");
+}
+
+/// Enter name value pair to the dictionary.  \ingroup DD4HEP_GEOMETRY
+void DD4hep::Geometry::_toDictionary(const std::string& name, const std::string& value, const std::string& typ)   {
+  if ( typ == "string" )  {
+    eval.setEnviron(name.c_str(),value.c_str());
+    return;
+  }
+  else  {
+    string n = name, v = value;
+    size_t idx = v.find("(int)");
+    if (idx != string::npos)
+      v.erase(idx, 5);
+    idx = v.find("(float)");
+    if (idx != string::npos)
+      v.erase(idx, 7);
+    while (v[0] == ' ')
+      v.erase(0, 1);
+    double result = eval.evaluate(v.c_str());
+    if (eval.status() != XmlTools::Evaluator::OK) {
+      cerr << value << ": ";
+      eval.print_error();
+      throw runtime_error("DD4hep: Severe error during expression evaluation " + name + "=" + value);
+    }
+    eval.setVariable(n.c_str(), result);
   }
-  eval.setVariable(n.c_str(), result);
 }
 
 template <typename T> static inline string __to_string(T value, const char* fmt) {
diff --git a/DDCore/src/ObjectExtensions.cpp b/DDCore/src/ObjectExtensions.cpp
index ed2e187fc..0eefb3a88 100644
--- a/DDCore/src/ObjectExtensions.cpp
+++ b/DDCore/src/ObjectExtensions.cpp
@@ -15,19 +15,18 @@
 // C/C++ include files
 #include <stdexcept>
 
-using namespace std;
 using namespace DD4hep;
 
 namespace {
   static int s_extensionID = 0;
-  ObjectExtensions::ExtensionMap* extensionContainer(const type_info& typ) {
-    static map<const type_info*, ObjectExtensions::ExtensionMap> s_map;
+  ObjectExtensions::ExtensionMap* extensionContainer(const std::type_info& typ) {
+    static std::map<const std::type_info*, ObjectExtensions::ExtensionMap> s_map;
     return &s_map[&typ];
   }
 }
 
 /// Default constructor
-ObjectExtensions::ObjectExtensions(const type_info& parent_type)    {
+ObjectExtensions::ObjectExtensions(const std::type_info& parent_type)    {
   extensionMap = extensionContainer(parent_type);
   InstanceCount::increment(this);
 }
@@ -57,7 +56,7 @@ void ObjectExtensions::clear(bool destroy) {
 /// Copy object extensions from another object
 void ObjectExtensions::copyFrom(const Extensions& ext, void* arg)  {
   for (Extensions::const_iterator i = ext.begin(); i != ext.end(); ++i) {
-    const type_info* info = (*i).first;
+    const std::type_info* info = (*i).first;
     ExtensionMap::const_iterator j = extensionMap->find(info);
     const Entry& e = (*j).second;
     extensions[info] = (*(e.copy))((*i).second, arg);
@@ -65,12 +64,12 @@ void ObjectExtensions::copyFrom(const Extensions& ext, void* arg)  {
 }
 
 /// Add an extension object to the detector element
-void* ObjectExtensions::addExtension(void* ptr, const type_info& info, destruct_t dtor)  {
+void* ObjectExtensions::addExtension(void* ptr, const std::type_info& info, destruct_t dtor)  {
   return addExtension(ptr, info, 0, dtor);
 }
 
 /// Add an extension object to the detector element
-void* ObjectExtensions::addExtension(void* ptr, const type_info& info, copy_t ctor, destruct_t dtor)  {
+void* ObjectExtensions::addExtension(void* ptr, const std::type_info& info, copy_t ctor, destruct_t dtor)  {
   Extensions::iterator j = extensions.find(&info);
   if (j == extensions.end()) {
     ExtensionMap::iterator i = extensionMap->find(&info);
@@ -84,7 +83,7 @@ void* ObjectExtensions::addExtension(void* ptr, const type_info& info, copy_t ct
     }
     return extensions[&info] = ptr;
   }
-  throw runtime_error("DD4hep: addExtension: Object already has an extension of type:" + typeName(info) + ".");
+  throw std::runtime_error("DD4hep: addExtension: Object already has an extension of type:" + typeName(info) + ".");
 }
 
 /// Remove an existing extension object from the instance
@@ -103,26 +102,26 @@ void* ObjectExtensions::removeExtension(const std::type_info& info, bool destroy
     extensions.erase(j);
     return ptr;
   }
-  throw runtime_error("DD4hep: removeExtension: The object of type " + typeName(info) + " is not present.");
+  throw std::runtime_error("DD4hep: removeExtension: The object of type " + typeName(info) + " is not present.");
 }
 
 /// Access an existing extension object from the detector element
-void* ObjectExtensions::extension(const type_info& info) const {
+void* ObjectExtensions::extension(const std::type_info& info) const {
   Extensions::const_iterator j = extensions.find(&info);
   if (j != extensions.end()) {
     return (*j).second;
   }
-  throw runtime_error("DD4hep: extension: Object has no extension of type:" + typeName(info) + ".");
+  throw std::runtime_error("DD4hep: extension: Object has no extension of type:" + typeName(info) + ".");
 }
 
 /// Access an existing extension object from the detector element
-void* ObjectExtensions::extension(const type_info& info, bool alert) const {
+void* ObjectExtensions::extension(const std::type_info& info, bool alert) const {
   Extensions::const_iterator j = extensions.find(&info);
   if (j != extensions.end()) {
     return (*j).second;
   }
   else if ( !alert ) 
     return 0;
-  throw runtime_error("DD4hep: extension: Object has no extension of type:" + typeName(info) + ".");
+  throw std::runtime_error("DD4hep: extension: Object has no extension of type:" + typeName(info) + ".");
 }
 
diff --git a/DDCore/src/Objects.cpp b/DDCore/src/Objects.cpp
index 3e7bc4a1b..322660107 100644
--- a/DDCore/src/Objects.cpp
+++ b/DDCore/src/Objects.cpp
@@ -132,19 +132,29 @@ void Header::setComment(const std::string& new_comment) {
 }
 
 /// Constructor to be used when creating a new DOM tree
-Constant::Constant(const string& nam, const string& val) {
-  m_element = new NamedObject(nam.c_str(), val.c_str());
+Constant::Constant(const string& nam, const string& val, const string& typ) {
+  m_element = new Object(nam, val, typ);
 }
 
 /// Constructor to be used when creating a new DOM tree
 Constant::Constant(const string& name) {
-  m_element = new NamedObject(name.c_str(), "");
+  m_element = new Object(name.c_str(), "", "number");
+}
+
+/// Access the constant
+string Constant::type() const   {
+  if ( isValid() )  {
+    return m_element->type;
+  }
+  throw runtime_error("DD4hep: Attempt to access internals from invalid Constant handle!");
 }
 
 /// String representation of this object
 string Constant::toString() const {
   stringstream os;
-  os << m_element->GetName() << "  \"" << m_element->GetTitle() << "\"  Value:" << _toDouble(m_element->GetTitle());
+  os << m_element->GetName() << "  \"" << m_element->GetTitle() << "\"  ";
+  if ( m_element->m_type == "string" ) os << "Value:" << m_element->GetTitle();
+  else os << "Value:" << _toDouble(m_element->GetTitle());
   return os.str();
 }
 
diff --git a/DDCore/src/ObjectsInterna.cpp b/DDCore/src/ObjectsInterna.cpp
index 3c10d405b..68b0d2057 100644
--- a/DDCore/src/ObjectsInterna.cpp
+++ b/DDCore/src/ObjectsInterna.cpp
@@ -41,6 +41,20 @@ HeaderObject::~HeaderObject() {
   InstanceCount::decrement(this);
 }
 
+DD4HEP_INSTANTIATE_HANDLE_NAMED(ConstantObject);
+
+/// Standard constructor
+ConstantObject::ConstantObject(const string& nam, const string& val, const string& typ)
+  : NamedObject(nam.c_str(), val.c_str()) {
+  m_type = typ;
+  InstanceCount::increment(this);
+}
+
+/// Default destructor
+ConstantObject::~ConstantObject() {
+  InstanceCount::decrement(this);
+}
+
 DD4HEP_INSTANTIATE_HANDLE_NAMED(RegionObject);
 
 /// Standard constructor
diff --git a/DDCore/src/Primitives.cpp b/DDCore/src/Primitives.cpp
index 803c5f6c0..7ef516706 100644
--- a/DDCore/src/Primitives.cpp
+++ b/DDCore/src/Primitives.cpp
@@ -25,14 +25,11 @@ using   abi::__dynamic_cast;
 #endif
 #endif
 
-using namespace std;
-using namespace DD4hep;
-
 static const std::string __typeinfoName(const std::type_info& tinfo) {
   const char* class_name = tinfo.name();
   std::string result;
 #ifdef WIN32
-  size_t off = 0;
+  std::size_t off = 0;
   if ( ::strncmp(class_name, "class ", 6) == 0 ) {
     // The returned name is prefixed with "class "
     off = 6;
@@ -135,7 +132,7 @@ static const std::string __typeinfoName(const std::type_info& tinfo) {
   }
   else {
     char buff[16 * 1024];
-    size_t len = sizeof(buff);
+    std::size_t len = sizeof(buff);
     int status = 0;
     result = __cxxabiv1::__cxa_demangle(class_name, buff, &len, &status);
   }
@@ -146,27 +143,27 @@ static const std::string __typeinfoName(const std::type_info& tinfo) {
   return result;
 }
 
-string DD4hep::typeName(const type_info& typ) {
+std::string DD4hep::typeName(const std::type_info& typ) {
   return __typeinfoName(typ);
 }
 
-void DD4hep::invalidHandleError(const type_info& type)   {
-  throw runtime_error("Attempt to access invalid object of type "+typeName(type)+" [Invalid Handle]");
+void DD4hep::invalidHandleError(const std::type_info& type)   {
+  throw std::runtime_error("Attempt to access invalid object of type "+typeName(type)+" [Invalid Handle]");
 }
 
-void DD4hep::invalidHandleAssignmentError(const type_info& from, const type_info& to)  {
-  string msg = "Wrong assingment from ";
+void DD4hep::invalidHandleAssignmentError(const std::type_info& from, const std::type_info& to)  {
+  std::string msg = "Wrong assingment from ";
   msg += typeName(from);
   msg += " to ";
   msg += typeName(to);
   msg += " not possible!!";
-  throw runtime_error(msg);
+  throw std::runtime_error(msg);
 }
 
 /// Throw exception when handles are check for validity
 void DD4hep::notImplemented(const std::string& msg)   {
-  string m = "The requested feature " + msg + " is not implemented!";
-  throw runtime_error(m);
+  std::string m = "The requested feature " + msg + " is not implemented!";
+  throw std::runtime_error(m);
 }
 
 void DD4hep::typeinfoCheck(const std::type_info& typ1, const std::type_info& typ2, const std::string& text) {
@@ -176,7 +173,7 @@ void DD4hep::typeinfoCheck(const std::type_info& typ1, const std::type_info& typ
 }
 
 /// Initializing Constructor
-ComponentCast::ComponentCast(const std::type_info& t, destroy_t d, cast_t c)
+DD4hep::ComponentCast::ComponentCast(const std::type_info& t, destroy_t d, cast_t c)
   : type(t), destroy(d), cast(c) {
 #ifdef __APPLE__
   abi_class = 0;
@@ -189,7 +186,7 @@ ComponentCast::ComponentCast(const std::type_info& t, destroy_t d, cast_t c)
 }
 
 /// Defautl destructor
-ComponentCast::~ComponentCast() {
+DD4hep::ComponentCast::~ComponentCast() {
 }
 
 #if 0
@@ -218,7 +215,7 @@ static inline void* cast_wrap(const void* p,
 #endif
 
 /// Apply cast using typeinfo instead of dynamic_cast
-void* ComponentCast::apply_dynCast(const ComponentCast& to, const void* ptr) const {
+void* DD4hep::ComponentCast::apply_dynCast(const ComponentCast& to, const void* ptr) const {
   if (&to == this) {
     return (void*) ptr;
   }
@@ -256,7 +253,7 @@ void* ComponentCast::apply_dynCast(const ComponentCast& to, const void* ptr) con
 }
 
 /// Apply cast using typeinfo instead of dynamic_cast
-void* ComponentCast::apply_upCast(const ComponentCast& to, const void* ptr) const {
+void* DD4hep::ComponentCast::apply_upCast(const ComponentCast& to, const void* ptr) const {
   if (&to == this) {
     return (void*) ptr;
   }
@@ -264,7 +261,7 @@ void* ComponentCast::apply_upCast(const ComponentCast& to, const void* ptr) cons
 }
 
 /// Apply cast using typeinfo instead of dynamic_cast
-void* ComponentCast::apply_downCast(const ComponentCast& to, const void* ptr) const {
+void* DD4hep::ComponentCast::apply_downCast(const ComponentCast& to, const void* ptr) const {
   if (&to == this) {
     return (void*) ptr;
   }
diff --git a/DDCore/src/Shapes.cpp b/DDCore/src/Shapes.cpp
index 6f3613c88..8e480c79d 100644
--- a/DDCore/src/Shapes.cpp
+++ b/DDCore/src/Shapes.cpp
@@ -15,7 +15,9 @@
 #include <stdexcept>
 
 // ROOT includes
+#include "TClass.h"
 #include "TGeoShape.h"
+#include "TGeoHype.h"
 #include "TGeoPcon.h"
 #include "TGeoPgon.h"
 #include "TGeoTube.h"
@@ -33,6 +35,111 @@
 using namespace std;
 using namespace DD4hep::Geometry;
 
+/// Pretty print of solid attributes
+std::string DD4hep::Geometry::toStringSolid(const TGeoShape* shape, int precision)   {
+  stringstream log;
+
+  if ( !shape )  {
+    return "[Invalid shape]";
+  }
+
+  TClass* cl = shape->IsA();
+  int prec = log.precision();
+  log.setf(ios::fixed,ios::floatfield);
+  log << setprecision(precision);
+  log << cl->GetName();
+  if ( cl == TGeoBBox::Class() )   {
+    TGeoBBox* s = (TGeoBBox*) shape;
+    log << " x:" << s->GetDX() 
+	<< " y:" << s->GetDY()
+	<< " z:" << s->GetDZ();
+  }
+  else if (cl == TGeoTube::Class()) {
+    const TGeoTube* s = (const TGeoTube*) shape;
+    log << " rmin:" << s->GetRmin() << " rmax:" << s->GetRmax() << " dz:" << s->GetDz();
+  }
+  else if (cl == TGeoTubeSeg::Class()) {
+    const TGeoTubeSeg* s = (const TGeoTubeSeg*) shape;
+    log << " rmin:" << s->GetRmin() << " rmax:" << s->GetRmax() << " dz:" << s->GetDz() 
+	<< " Phi1:" << s->GetPhi1() << " Phi2:" << s->GetPhi2();
+  }
+  else if (cl == TGeoTrd1::Class()) {
+    const TGeoTrd1* s = (const TGeoTrd1*) shape;
+    log << " x1:" << s->GetDx1() << " x2:" << s->GetDx2() << " y:" << s->GetDy() << " z:" << s->GetDz();
+  }
+  else if (cl == TGeoTrd2::Class()) {
+    const TGeoTrd2* s = (const TGeoTrd2*) shape;
+    log << " x1:" << s->GetDx1() << " x2:" << s->GetDx2() 
+	<< " y1:" << s->GetDy1() << " y2:" << s->GetDy2() << " z:" << s->GetDz();
+  }
+  else if (cl == TGeoHype::Class()) {
+    const TGeoHype* s = (const TGeoHype*) shape;
+    log << " rmin:" << s->GetRmin() << " rmax:"  << s->GetRmax() << " dz:" << s->GetDz() 
+	<< " StIn:" << s->GetStIn() << " StOut:" << s->GetStOut();
+  }
+  else if (cl == TGeoPgon::Class()) {
+    const TGeoPgon* s = (const TGeoPgon*) shape;
+    log << " Phi1:"   << s->GetPhi1()   << " dPhi:" << s->GetDphi() 
+	<< " NEdges:" << s->GetNedges() << " Nz:" << s->GetNz();
+    for(int i=0, n=s->GetNz(); i<n; ++i)  {
+      log << " i=" << i << " z:" << s->GetZ(i) 
+	  << " r:[" << s->GetRmin(i) << "," << s->GetRmax(i) << "]";
+    }
+  }
+  else if (cl == TGeoPcon::Class()) {
+    const TGeoPcon* s = (const TGeoPcon*) shape;
+    log << " Phi1:" << s->GetPhi1() << " dPhi:" << s->GetDphi() << " Nz:" << s->GetNz();
+    for(int i=0, n=s->GetNz(); i<n; ++i)  {
+      log << " i=" << i << " z:" << s->GetZ(i) 
+	  << " r:[" << s->GetRmin(i) << "," << s->GetRmax(i) << "]";
+    }
+  }
+  else if (cl == TGeoConeSeg::Class()) {
+    const TGeoConeSeg* s = (const TGeoConeSeg*) shape;
+    log << " rmin1:" << s->GetRmin1() << " rmax1:" << s->GetRmax1()
+	<< " rmin2:" << s->GetRmin2() << " rmax2:" << s->GetRmax2()
+	<< " dz:"    << s->GetDz() 
+	<< " Phi1:"  << s->GetPhi1() << " Phi2:" << s->GetPhi2();
+  }
+  else if (cl == TGeoParaboloid::Class()) {
+    const TGeoParaboloid* s = (const TGeoParaboloid*) shape;
+    log << " dz:" << s->GetDz() << " RLo:" << s->GetRlo() << " Rhi:" << s->GetRhi();
+  }
+  else if (cl == TGeoSphere::Class()) {
+    const TGeoSphere* s = (const TGeoSphere*) shape;
+    log << " rmin:" << s->GetRmin() << " rmax:" << s->GetRmax()
+	<< " Phi1:" << s->GetPhi1() << " Phi2:" << s->GetPhi2()
+	<< " Theta1:" << s->GetTheta1() << " Theta2:" << s->GetTheta2();
+  }
+  else if (cl == TGeoTorus::Class()) {
+    const TGeoTorus* s = (const TGeoTorus*) shape;
+    log << " rmin:" << s->GetRmin() << " rmax:" << s->GetRmax() << " r:" << s->GetR()
+	<< " Phi1:" << s->GetPhi1() << " dPhi:" << s->GetDphi();
+  }
+  else if (cl == TGeoTrap::Class()) {
+    const TGeoTrap* s = (const TGeoTrap*) shape;
+    log << " dz:" << s->GetDz() << " Theta:" << s->GetTheta() << " Phi:" << s->GetPhi()
+	<< " H1:" << s->GetH1() << " Bl1:"   << s->GetBl1()   << " Tl1:" << s->GetTl1() << " Alpha1:" << s->GetAlpha1()
+	<< " H2:" << s->GetH2() << " Bl2:"   << s->GetBl2()   << " Tl2:" << s->GetTl2() << " Alpha2:" << s->GetAlpha2();
+  }
+  else if (shape->IsA() == TGeoCompositeShape::Class()) {
+    const TGeoCompositeShape* s = (const TGeoCompositeShape*) shape;
+    const TGeoBoolNode* boolean = s->GetBoolNode();
+    const TGeoShape* left = boolean->GetLeftShape();
+    const TGeoShape* right = boolean->GetRightShape();
+    TGeoBoolNode::EGeoBoolType oper = boolean->GetBooleanOperator();
+    if (oper == TGeoBoolNode::kGeoSubtraction)
+      log << "Subtraction: ";
+    else if (oper == TGeoBoolNode::kGeoUnion)
+      log << "Union: ";
+    else if (oper == TGeoBoolNode::kGeoIntersection)
+      log << "Intersection: ";
+    log << " Left:" << toStringSolid(left) << " Right:" << toStringSolid(right);
+  }
+  log << setprecision(prec);
+  return log.str();
+}
+
 template <typename T> void Solid_type<T>::_setDimensions(double* param) {
   this->ptr()->SetDimensions(param);
   this->ptr()->ComputeBBox();
diff --git a/DDCore/src/SimpleGDMLWriter.h b/DDCore/src/SimpleGDMLWriter.h
index 27816abb1..10106331e 100644
--- a/DDCore/src/SimpleGDMLWriter.h
+++ b/DDCore/src/SimpleGDMLWriter.h
@@ -29,8 +29,8 @@ namespace DD4hep {
      *  \version 1.0
      *  \ingroup DD4HEP_GEOMETRY
      */
-    struct SimpleGDMLWriter: public GeoHandler {
-
+    class SimpleGDMLWriter: public GeoHandler {
+    public:
       /// Reference to output stream
       std::ostream& m_output;
 
diff --git a/DDCore/src/SurfaceInstaller.cpp b/DDCore/src/SurfaceInstaller.cpp
index 29de01640..bc13fbb10 100644
--- a/DDCore/src/SurfaceInstaller.cpp
+++ b/DDCore/src/SurfaceInstaller.cpp
@@ -6,11 +6,13 @@
 //  Author     : M.Frank
 //
 //====================================================================
+#include "DD4hep/Shapes.h"
 #include "DD4hep/Printout.h"
 #include "DD4hep/SurfaceInstaller.h"
 
 // C/C++ include files
 #include <stdexcept>
+// ROOT includes
 #include "TClass.h"
 
 using namespace std;
@@ -79,26 +81,30 @@ void SurfaceInstaller::install(DetElement component, PlacedVolume pv)   {
     printout(INFO,m_det.name(),log.str());
     log.str("");
     log << "       " << " Matrices[" <<  all_nodes.size()  << "]: ";
-    log << pv->GetVolume()->GetShape()->IsA()->GetName() << " ";
     for(PlacementPath::const_reverse_iterator i=all_nodes.rbegin(); i!=all_nodes.rend(); ++i)  {
-      log << (void*)((*i)->GetMatrix()) << "  ";
-      if ( i+1 == all_nodes.rend() ) log << "( -> " << (*i)->GetName() << ")";
+      PlacedVolume placed = *i;
+      log << (void*)(placed->GetMatrix()) << " ";
+      if ( placed->GetUserExtension() )  {
+	const PlacedVolume::VolIDs& vid = placed.volIDs();
+	for(PlacedVolume::VolIDs::const_iterator j=vid.begin(); j!=vid.end(); ++j)  {
+	  log << (*j).first << ":" << (*j).second << " ";
+	}
+      }
+      log << " ";
+      if ( i+1 == all_nodes.rend() ) log << "( -> " << placed->GetName() << ")";
     }
     // Get the module element:
-    TClass* cl = pv->GetVolume()->GetShape()->IsA();
     printout(INFO,m_det.name(),log.str());
     log.str("");
+    Volume vol = pv.volume();
     log << "       "
-	<< " Sensitive:" << (pv.volume().isSensitive() ? "YES" : "NO ") 
-	<< " Shape: " << cl->GetName();
-    TGeoBBox* box = (TGeoBBox*)pv.volume()->GetShape();
-    if ( cl == TGeoBBox::Class() )   {
-      log << " ["  << (void*)box << "]"
-	  << " x:" << box->GetDX() 
-	  << " y:" << box->GetDY()
-	  << " z:" << box->GetDZ();
-    }
+	<< " Sensitive:   " << (vol.isSensitive() ? "YES" : "NO ") 
+	<< " Volume: " << (void*)vol.ptr() << " "
+	<< " Shape: "  << vol.solid().toString();
+    printout(INFO,m_det.name(),log.str());
+    return;
   }
+  cout << component.name() << ": " << pv.name() << endl;
 }
 
 /// Scan through tree of volume placements
@@ -114,5 +120,3 @@ void SurfaceInstaller::scan()  {
   scan(m_det);
 }
 
-typedef DD4hep::SurfaceInstaller TestSurfacesPlugin;
-DECLARE_SURFACE_INSTALLER(TestSurfaces,TestSurfacesPlugin)
diff --git a/DDCore/src/ToStream.cpp b/DDCore/src/ToStream.cpp
index 99dbdfd3f..a48fa7495 100644
--- a/DDCore/src/ToStream.cpp
+++ b/DDCore/src/ToStream.cpp
@@ -21,28 +21,27 @@ namespace {
   XmlTools::Evaluator& eval(DD4hep::g4Evaluator());
 }
 
-using namespace std;
 //==============================================================================
 namespace DD4hep {  namespace Parsers {
-    template <typename T> T evaluate_string(const string& /* value */)   {
+    template <typename T> T evaluate_string(const std::string& /* value */)   {
       throw "Bad undefined call";
     }
 
-    template <> double evaluate_string<double>(const string& value)   {
+    template <> double evaluate_string<double>(const std::string& value)   {
       double result = eval.evaluate(value.c_str());
       if (eval.status() != XmlTools::Evaluator::OK) {
-	cerr << value << ": ";
+	std::cerr << value << ": ";
 	eval.print_error();
-	throw runtime_error("DD4hep::Properties: Severe error during expression evaluation of " + value);
+	throw std::runtime_error("DD4hep::Properties: Severe error during expression evaluation of " + value);
       }
       return result;
     }
-    template <> float evaluate_string<float>(const string& value)   {
+    template <> float evaluate_string<float>(const std::string& value)   {
       double result = eval.evaluate(value.c_str());
       if (eval.status() != XmlTools::Evaluator::OK) {
-	cerr << value << ": ";
+	std::cerr << value << ": ";
 	eval.print_error();
-	throw runtime_error("DD4hep::Properties: Severe error during expression evaluation of " + value);
+	throw std::runtime_error("DD4hep::Properties: Severe error during expression evaluation of " + value);
       }
       return (float) result;
     }
@@ -51,7 +50,7 @@ namespace DD4hep {  namespace Parsers {
 
 // ============================================================================
 // print XYZ-point
-ostream& DD4hep::Utils::toStream(const ROOT::Math::XYZPoint&  obj, ostream& s)  {
+std::ostream& DD4hep::Utils::toStream(const ROOT::Math::XYZPoint&  obj, std::ostream& s)  {
   s << "( ";
   toStream(obj.X () , s );
   s << " , ";
@@ -63,7 +62,7 @@ ostream& DD4hep::Utils::toStream(const ROOT::Math::XYZPoint&  obj, ostream& s)
 }
 // ============================================================================
 // print XYZ-vector
-ostream& DD4hep::Utils::toStream(const ROOT::Math::XYZVector& obj, ostream& s)  {
+std::ostream& DD4hep::Utils::toStream(const ROOT::Math::XYZVector& obj, std::ostream& s)  {
   s << "( ";
   toStream(obj.X () , s );
   s << " , ";
@@ -75,7 +74,7 @@ ostream& DD4hep::Utils::toStream(const ROOT::Math::XYZVector& obj, ostream& s)
 }
 // ============================================================================
 // print LorentzVector
-ostream& DD4hep::Utils::toStream(const ROOT::Math::PxPyPzEVector& obj, ostream& s){
+std::ostream& DD4hep::Utils::toStream(const ROOT::Math::PxPyPzEVector& obj, std::ostream& s){
   s << "( ";
   toStream(obj.Px () , s , 12 );
   s << " , ";
diff --git a/DDCore/src/XML/DocumentHandler.cpp b/DDCore/src/XML/DocumentHandler.cpp
index 83b7a0152..59e91bede 100644
--- a/DDCore/src/XML/DocumentHandler.cpp
+++ b/DDCore/src/XML/DocumentHandler.cpp
@@ -167,7 +167,8 @@ DocumentHandler::~DocumentHandler() {
 static string uri(Handle_t base, const XMLCh* fname)   {
   xercesc::DOMElement* e = (xercesc::DOMElement*) base.ptr();
   xercesc::XMLURL base_url(e->getBaseURI());
-  xercesc::XMLURL ref_url(base_url, fname);
+  string bbb = _toString(fname);
+  xercesc::XMLURL ref_url(base_url, Strng_t(bbb));
   return _toString(ref_url.getURLText());
 }
 
@@ -176,7 +177,7 @@ Document DocumentHandler::load(Handle_t base, const XMLCh* fname) const {
   return load(path);
 }
 
-Document DocumentHandler::load(const string& fname) const {
+Document DocumentHandler::load(const std::string& fname) const {
   printout(DEBUG,"DocumentHandler","+++ Loading document URI: %s",fname.c_str());
   XMLURL xerurl = (const XMLCh*) Strng_t(fname);
   string path = _toString(xerurl.getPath());
@@ -307,7 +308,7 @@ Document DocumentHandler::load(Handle_t base, const XmlChar* fname) const {
   return load(fname);
 }
 
-Document DocumentHandler::load(const string& fname) const {
+Document DocumentHandler::load(const std::string& fname) const {
   printout(INFO,"DocumentHandler","+++ Loading document URI: %s",fname.c_str());
   TiXmlDocument* doc = new TiXmlDocument(_clean_fname(fname).c_str());
   bool result = false;
diff --git a/DDCore/src/XML/XMLElements.cpp b/DDCore/src/XML/XMLElements.cpp
index 681d3ba3b..00d9da8ef 100644
--- a/DDCore/src/XML/XMLElements.cpp
+++ b/DDCore/src/XML/XMLElements.cpp
@@ -29,6 +29,10 @@ namespace DD4hep {
 // Static storage
 namespace {
   XmlTools::Evaluator& eval(DD4hep::evaluator());
+  string _checkEnviron(const string& env)  {
+    string r = getEnviron(env);
+    return r.empty() ? env : r;
+  }
 }
 
 // Shortcuts
@@ -81,8 +85,8 @@ namespace {
   }
 }
 XmlChar* DD4hep::XML::XmlString::replicate(const XmlChar* c) {return c ? ::strdup(c) : 0;}
-XmlChar* DD4hep::XML::XmlString::transcode(const char* c) {return c ? ::strdup(c) : 0;}
-void DD4hep::XML::XmlString::release(char** p) {if(p && *p) {::free(*p); *p=0;}}
+XmlChar* DD4hep::XML::XmlString::transcode(const char* c)    {return c ? ::strdup(c) : 0;}
+void DD4hep::XML::XmlString::release(char** p) {if(p && *p)  {::free(*p); *p=0;}}
 
 #else
 #include "xercesc/util/XMLString.hpp"
@@ -156,10 +160,14 @@ namespace {
     return 0;
   }
 }
+
 string DD4hep::XML::_toString(const XmlChar *toTranscode) {
   char *buff = XmlString::transcode(toTranscode);
   string tmp(buff == 0 ? "" : buff);
   XmlString::release(&buff);
+  if ( tmp.length()<3 ) return tmp;
+  if ( !(tmp[0] == '$' && tmp[1] == '{') ) return tmp;
+  tmp = _checkEnviron(tmp);
   return tmp;
 }
 #endif
@@ -191,12 +199,16 @@ template <typename T> static inline string __to_string(T value, const char* fmt)
 
 /// Do-nothing version. Present for completeness and argument interchangeability
 std::string DD4hep::XML::_toString(const char* s) {
-  return string(s ? s : "");
+  if ( !s || *s == 0 ) return "";
+  else if ( !(*s == '$' && *(s+1) == '{') ) return s;
+  return _checkEnviron(s);
 }
 
 /// Do-nothing version. Present for completeness and argument interchangeability
 std::string DD4hep::XML::_toString(const std::string& s) {
-  return s;
+  if ( s.length() < 3 || s[0] != '$' ) return s;
+  else if ( !(s[0] == '$' && s[1] == '{') ) return s;
+  return _checkEnviron(s);
 }
 
 /// Format unsigned long integer to string with atrbitrary format
@@ -312,6 +324,7 @@ void DD4hep::XML::_toDictionary(const XmlChar* name, T value)   {
   const XmlChar* item_value = item;
   _toDictionary(name, item_value);
 }
+
 #ifndef DD4HEP_USE_TINYXML
 template void DD4hep::XML::_toDictionary(const XmlChar* name, const char* value);
 #endif
@@ -325,6 +338,28 @@ template void DD4hep::XML::_toDictionary(const XmlChar* name, short value);
 template void DD4hep::XML::_toDictionary(const XmlChar* name, float value);
 template void DD4hep::XML::_toDictionary(const XmlChar* name, double value);
 
+/// Evaluate string constant using environment stored in the evaluator
+string DD4hep::XML::getEnviron(const string& env)   {
+  size_t id1 = env.find("${");
+  size_t id2 = env.rfind("}");
+  if ( id1 == string::npos || id2 == string::npos )   {
+    return "";
+  }
+  else  {
+    string v = env.substr(0,id2+1);
+    const char* ret = eval.getEnviron(v.c_str());
+    if (eval.status() != XmlTools::Evaluator::OK) {
+      cerr << env << ": ";
+      eval.print_error();
+      throw runtime_error("DD4hep: Severe error during environment lookup of " + env);
+    }
+    v = env.substr(0,id1);
+    v += ret;
+    v += env.substr(id2+1);
+    return v;
+  }
+}
+
 template <typename B>
 static inline string i_add(const string& a, B b) {
   string r = a;
diff --git a/DDCore/src/plugins/Compact2Objects.cpp b/DDCore/src/plugins/Compact2Objects.cpp
index 86e467395..95e63a2df 100644
--- a/DDCore/src/plugins/Compact2Objects.cpp
+++ b/DDCore/src/plugins/Compact2Objects.cpp
@@ -247,10 +247,12 @@ template <> void Converter<Plugin>::operator()(xml_h e) const {
  */
 template <> void Converter<Constant>::operator()(xml_h e) const {
   xml_ref_t constant(e);
-  NamedObject* obj = new NamedObject(constant.attr < string > (_U(name)).c_str(), constant.attr < string > (_U(value)).c_str());
-  Ref_t cons(obj);
-  _toDictionary(obj->GetName(), obj->GetTitle());
-  lcdd.addConstant(cons);
+  string nam = constant.attr < string > (_U(name));
+  string val = constant.attr < string > (_U(value));
+  string typ = constant.hasAttr(_U(type)) ? constant.attr<string>(_U(type)) : "number";
+  Constant c(nam, val, typ);
+  _toDictionary(nam, val, typ);
+  lcdd.addConstant(c);
 }
 /** Convert compact constant objects (defines)
  *
@@ -864,13 +866,14 @@ template <> void Converter<Compact>::operator()(xml_h element) const {
 
   ++num_calls;
   xml_elt_t compact(element);
+
+  xml_coll_t(compact, _U(define)).for_each(_U(include), Converter < DetElementInclude > (lcdd));
+  xml_coll_t(compact, _U(define)).for_each(_U(constant), Converter < Constant > (lcdd));
   xml_coll_t(compact, _U(includes)).for_each(_U(gdmlFile), Converter < GdmlFile > (lcdd));
 
   if (element.hasChild(_U(info)))
     (Converter < Header > (lcdd))(xml_h(compact.child(_U(info))));
 
-  xml_coll_t(compact, _U(define)).for_each(_U(include), Converter < DetElementInclude > (lcdd));
-  xml_coll_t(compact, _U(define)).for_each(_U(constant), Converter < Constant > (lcdd));
   xml_coll_t(compact, _U(materials)).for_each(_U(element), Converter < Atom > (lcdd));
   xml_coll_t(compact, _U(materials)).for_each(_U(material), Converter < Material > (lcdd));
   xml_coll_t(compact, _U(properties)).for_each(_U(attributes), Converter < Property > (lcdd));
diff --git a/DDCore/src/plugins/LCDDConverter.h b/DDCore/src/plugins/LCDDConverter.h
index 6976b4726..fdf96d5ce 100644
--- a/DDCore/src/plugins/LCDDConverter.h
+++ b/DDCore/src/plugins/LCDDConverter.h
@@ -42,7 +42,8 @@ namespace DD4hep {
      *  \version 1.0
      *  \ingroup DD4HEP_GEOMETRY
      */
-    struct LCDDConverter: public GeoHandler {
+    class LCDDConverter: public GeoHandler {
+    public:
       typedef XML::XmlElement XmlElement;
       typedef std::map<Atom,              XmlElement*> ElementMap;
       typedef std::map<Material,          XmlElement*> MaterialMap;
@@ -62,7 +63,8 @@ namespace DD4hep {
        *  \version 1.0
        *  \ingroup DD4HEP_GEOMETRY
        */
-      struct GeometryInfo: public GeoHandler::GeometryInfo {
+      class GeometryInfo: public GeoHandler::GeometryInfo {
+      public:
         ElementMap xmlElements;
         MaterialMap xmlMaterials;
         SolidMap xmlSolids;
diff --git a/DDCore/src/plugins/StandardPlugins.cpp b/DDCore/src/plugins/StandardPlugins.cpp
index 940650a81..8217c9c9e 100644
--- a/DDCore/src/plugins/StandardPlugins.cpp
+++ b/DDCore/src/plugins/StandardPlugins.cpp
@@ -259,3 +259,6 @@ static long exec_SimpleGDMLWriter(LCDD& lcdd, int argc, char** argv) {
 
 DECLARE_APPLY(DD4hepSimpleGDMLWriter,exec_SimpleGDMLWriter)
 
+#include "DD4hep/SurfaceInstaller.h"
+typedef SurfaceInstaller TestSurfacesPlugin;
+DECLARE_SURFACE_INSTALLER(TestSurfaces,TestSurfacesPlugin)
-- 
GitLab