From 8b0770ab41723c47b8fccd30bbe7c3a9f63e0b6b Mon Sep 17 00:00:00 2001
From: Markus Frank <Markus.Frank@cern.ch>
Date: Fri, 15 Jul 2022 11:08:42 +0200
Subject: [PATCH] Improve property parsing. Add DDG4 example to test properties

---
 DDCore/include/DD4hep/GrammarParsed.h         |  26 +-
 DDCore/src/DetectorImp.cpp                    |   3 +-
 DDCore/src/GrammarTypes.cpp                   |  12 +-
 DDCore/src/Handle.cpp                         |   2 +-
 DDParsers/include/Parsers/spirit/GrammarsV2.h |   4 +-
 DDParsers/src/Spirit/Evaluators.cpp           |   8 +-
 examples/ClientTests/src/Property_test.cpp    |  39 +-
 examples/DDG4/CMakeLists.txt                  |  11 +-
 examples/DDG4/scripts/TestProperties.py       | 138 +++++++
 examples/DDG4/src/PropertyTestAction.cpp      | 346 ++++++++++++++++++
 10 files changed, 559 insertions(+), 30 deletions(-)
 create mode 100644 examples/DDG4/scripts/TestProperties.py
 create mode 100644 examples/DDG4/src/PropertyTestAction.cpp

diff --git a/DDCore/include/DD4hep/GrammarParsed.h b/DDCore/include/DD4hep/GrammarParsed.h
index d8e9aae27..45509c693 100644
--- a/DDCore/include/DD4hep/GrammarParsed.h
+++ b/DDCore/include/DD4hep/GrammarParsed.h
@@ -26,10 +26,10 @@
 #endif
 
 /// Framework include files
-#include "DD4hep/Grammar.h"
-#include "DD4hep/Printout.h"
-#include "Parsers/Parsers.h"
-#include "Evaluator/Evaluator.h"
+#include <DD4hep/Grammar.h>
+#include <DD4hep/Printout.h>
+#include <Parsers/Parsers.h>
+#include <Evaluator/Evaluator.h>
 
 /// C/C++ include files
 #include <string>
@@ -170,8 +170,22 @@ namespace dd4hep {
       else   {
 	TYPE temp;
 	std::map<std::string,std::string> map_buff;
-	std::string temp_str = grammar_pre_parse_map(str);
-	sc = ::dd4hep::Parsers::parse(map_buff,temp_str);
+	// If we get called from python, the values and keys are already in string form
+	sc = 0;
+	try  {
+	  sc = ::dd4hep::Parsers::parse(map_buff,str);
+	}
+	catch(...)    {
+	}
+	if ( !sc )  {
+	  // Otherwise stringyfy the values
+	  std::string temp_str = grammar_pre_parse_map(str);
+	  try  {
+	    sc = ::dd4hep::Parsers::parse(map_buff,temp_str);
+	  }
+	  catch(...)    {
+	  }
+	}
 	if ( sc )   {
 	  for(const auto& _o : map_buff )    {
 	    typename TYPE::key_type _k;
diff --git a/DDCore/src/DetectorImp.cpp b/DDCore/src/DetectorImp.cpp
index 03482a426..12262bb72 100644
--- a/DDCore/src/DetectorImp.cpp
+++ b/DDCore/src/DetectorImp.cpp
@@ -79,7 +79,8 @@ namespace {
     recursive_mutex  lock;
     map<string, Detector*> detectors;
     Instances() = default;
-    ~Instances() = default;
+    ~Instances()  {
+    }
     Detector* get(const string& name)   {
       auto i = detectors.find(name);
       return i == detectors.end() ? 0 : (*i).second;
diff --git a/DDCore/src/GrammarTypes.cpp b/DDCore/src/GrammarTypes.cpp
index 29120752a..53d59c176 100644
--- a/DDCore/src/GrammarTypes.cpp
+++ b/DDCore/src/GrammarTypes.cpp
@@ -12,13 +12,15 @@
 //==========================================================================
 
 // Framework include files
-#include "DD4hep/GrammarParsed.h"
-
-#include "Math/Point3D.h"
-#include "Math/Vector4D.h"
-#include "Math/Vector3D.h"
+#include <DD4hep/GrammarParsed.h>
 
 #ifndef DD4HEP_PARSERS_NO_ROOT
+
+/// ROOT include files
+#include <Math/Point3D.h>
+#include <Math/Vector4D.h>
+#include <Math/Vector3D.h>
+
 namespace ROOT {
   namespace Math {
     /// Allow point insertion of a point in maps
diff --git a/DDCore/src/Handle.cpp b/DDCore/src/Handle.cpp
index bd1663411..df467c4c5 100644
--- a/DDCore/src/Handle.cpp
+++ b/DDCore/src/Handle.cpp
@@ -94,7 +94,7 @@ namespace dd4hep  {
   }
 
   bool _toBool(const string& value) {
-    return value == "true" || value == "yes";
+    return value == "true" || value == "yes" || value == "True";
   }
 
   /// String conversions: string to float value
diff --git a/DDParsers/include/Parsers/spirit/GrammarsV2.h b/DDParsers/include/Parsers/spirit/GrammarsV2.h
index a229fa21d..a97d68f9c 100644
--- a/DDParsers/include/Parsers/spirit/GrammarsV2.h
+++ b/DDParsers/include/Parsers/spirit/GrammarsV2.h
@@ -139,9 +139,9 @@ namespace dd4hep {  namespace Parsers {
       typedef bool ResultT;
       BoolGrammar() : BoolGrammar::base_type( boolean_literal ) {
         boolean_literal =
-          (qi::lit("true") | "True" | "TRUE" | "1")[qi::_val=true]
+          (qi::lit("true") | qi::lit("True") | qi::lit("TRUE") | "1")[qi::_val=true]
           |
-          (qi::lit("false") | "False" | "FALSE" | "0")[qi::_val=false];
+	  (qi::lit("false") | qi::lit("False") | qi::lit("FALSE") | "0")[qi::_val=false];
       }
       qi::rule<Iterator, bool(), Skipper> boolean_literal;
     };
diff --git a/DDParsers/src/Spirit/Evaluators.cpp b/DDParsers/src/Spirit/Evaluators.cpp
index c88e40ebc..4a0c9f44a 100755
--- a/DDParsers/src/Spirit/Evaluators.cpp
+++ b/DDParsers/src/Spirit/Evaluators.cpp
@@ -51,8 +51,8 @@ namespace dd4hep {  namespace Parsers {
       std::stringstream err;
       auto result = eval.evaluate(value, err);
       if (result.first != tools::Evaluator::OK) {
-        std::cerr << value << ": " << err.str() << std::endl;
-        throw std::runtime_error("dd4hep::Properties: Severe error during expression evaluation of " + value);
+        throw std::runtime_error("dd4hep::Properties: Severe error during expression evaluation of " + 
+				 value + " : " + err.str());
       }
       return result.second;
     }
@@ -60,8 +60,8 @@ namespace dd4hep {  namespace Parsers {
       std::stringstream err;
       auto result = eval.evaluate(value, err);
       if (result.first != tools::Evaluator::OK) {
-        std::cerr << value << ": " << err.str() << std::endl;
-        throw std::runtime_error("dd4hep::Properties: Severe error during expression evaluation of " + value);
+        throw std::runtime_error("dd4hep::Properties: Severe error during expression evaluation of " +
+				 value + " : " + err.str());
       }
       return (float) result.second;
     }
diff --git a/examples/ClientTests/src/Property_test.cpp b/examples/ClientTests/src/Property_test.cpp
index d88be3ca7..46dc6e9e9 100644
--- a/examples/ClientTests/src/Property_test.cpp
+++ b/examples/ClientTests/src/Property_test.cpp
@@ -92,10 +92,14 @@ static int property_test(Detector& /* description */, int /* argc */, char** /*
   result += _test_prop<bool>                     ("prop_bool",               "true");
   result += _test_prop<int>                      ("prop_int",                "11");
   result += _test_prop<int>                      ("prop_int_eval",           "1*11");
+  result += _test_prop<long>                     ("prop_long",               "1111");
+  result += _test_prop<long>                     ("prop_long_eval",          "1*1111");
+  result += _test_prop<ulong>                    ("prop_ulong",              "11111");
+  result += _test_prop<ulong>                    ("prop_ulong_eval",         "1*11111");
   result += _test_prop<float>                    ("prop_float",              "1.11");
   result += _test_prop<float>                    ("prop_float_eval",         "1.11*GeV");
-  result += _test_prop<double>                   ("prop_double",             "1.11");
-  result += _test_prop<double>                   ("prop_double_eval",        "1.11*GeV");
+  result += _test_prop<double>                   ("prop_double",             "1.1111");
+  result += _test_prop<double>                   ("prop_double_eval",        "1.1111*GeV");
   result += _test_prop<XYZPoint>                 ("prop_XYZPoint",           "(1, 2, 3)");
   result += _test_prop<XYZPoint>                 ("prop_XYZPoint_eval",      "(1*m, 2*m, 3*m)");
   result += _test_prop<XYZVector>                ("prop_XYZVector",          "(1, 2, 3)");
@@ -103,14 +107,16 @@ static int property_test(Detector& /* description */, int /* argc */, char** /*
   result += _test_prop<PxPyPzE>                  ("prop_PxPyPzEVector",      "(1, 2, 3, 4)");
   result += _test_prop<PxPyPzE>                  ("prop_PxPyPzEVector_eval", "(1*GeV, 2*GeV, 3*GeV, 4*GeV)");
   cout << "+----------------------------------------------------------------------------------------------------------" << endl;
-  result += _test_map <map<string, string> >     ("map_str_str",             "{'a':   'a',      'b': 'bb',        'c': 'ccc'}");
-  result += _test_map <map<string, bool> >       ("map_str_bool",            "{'a':   true,     'b':  false,      'c':  true}");
-  result += _test_map <map<string, int> >        ("map_str_int",             "{'a':   11,       'b':  200,        'c':  3000}");
-  result += _test_map <map<string, int> >        ("map_str_int_eval",        "{'a':   1*11,     'b': 2*100,       'c': 3*1000}");
-  result += _test_map <map<string, float> >      ("map_str_float",           "{'a':   1.11,     'b': 22.22,       'c': 333.33}");
-  result += _test_map <map<string, float> >      ("map_str_float_eval",      "{'a':   1.11*GeV, 'b': 22.22*MeV,   'c': 333.3*TeV}");
-  result += _test_map <map<string, double> >     ("map_str_double",          "{'a':   1.11,     'b': 22.22,       'c': 333.33}");
-  result += _test_map <map<string, double> >     ("map_str_double_eval",     "{'a':   1.11*GeV, 'b': 22.22*MeV,   'c': 333.3*TeV}");
+  result += _test_map <map<string, string> >     ("map_str_str",             "{'a':   'a',      'b':  'bb',       'c':  'ccc'}");
+  result += _test_map <map<string, bool> >       ("map_str_bool",            "{'a':   true,     'b': false,       'c':   true}");
+  result += _test_map <map<string, int> >        ("map_str_int",             "{'a':   11,       'b':   222,       'c':   3333}");
+  result += _test_map <map<string, int> >        ("map_str_int_eval",        "{'a':  1*11,      'b': 2*111,       'c': 3*1111}");
+  result += _test_map <map<string, long> >       ("map_str_long",            "{'a':   111,      'b':   222,       'c':   3333}");
+  result += _test_map <map<string, long> >       ("map_str_long_eval",       "{'a': 1*111,      'b': 2*111,       'c': 3*1111}");
+  result += _test_map <map<string, float> >      ("map_str_float",           "{'a':   1.11,     'b': 22.22,       'c':   333.33}");
+  result += _test_map <map<string, float> >      ("map_str_float_eval",      "{'a':  '1.11*GeV','b':'22.22*MeV',  'c':  '333.3*TeV'}");
+  result += _test_map <map<string, double> >     ("map_str_double",          "{'a':   1.11,     'b': 22.22,       'c':   333.33}");
+  result += _test_map <map<string, double> >     ("map_str_double_eval",     "{'a':  '1.11*GeV','b':'22.22*MeV',  'c':  '333.3*TeV'}");
   //result += _test_map <map<string, XYZPoint> >   ("map_str_XYZPoint",        "{['a', (1, 2, 3)]}");//, 'b': (10,20,30), 'c': (100,200,300)}");
   //result += _test_map <map<string, XYZVector> >  ("map_str_XYZVector",       "{'a': (1, 2, 3), 'b': (10,20,30), 'c': (100,200,300)}");
   //result += _test_map <map<string, PxPyPzE> >    ("map_str_PxPyPzEVector",   "{'a': (1, 2, 3, 4), 'b': (10,20,30,40), 'c': (100,200,300,400)}");
@@ -119,6 +125,8 @@ static int property_test(Detector& /* description */, int /* argc */, char** /*
   result += _test_map <map<int, bool> >          ("map_int_bool",            "{ 10:   true,       200:  false,        3000:      true}");
   result += _test_map <map<int, int> >           ("map_int_int",             "{ 10:   11,         200:  200,          3000:      3000}");
   result += _test_map <map<int, int> >           ("map_int_int_eval",        "{ 10:   1*11,       200: 2*100,         3000:    3*1000}");
+  result += _test_map <map<int, long> >          ("map_int_long",            "{ 10:   111,        200:   222,         3000:   3333}");
+  result += _test_map <map<int, long> >          ("map_int_long_eval",       "{ 10: 1*111,        200: 2*111,         3000: 3*1111}");
   result += _test_map <map<int, float> >         ("map_int_float",           "{ 10:   1.11,       200:   22.22,       3000:    333.33}");
   result += _test_map <map<int, float> >         ("map_int_float_eval",      "{ 10:   1.11*GeV,   200:   22.22*MeV,   3000: 333.3*TeV}");
   result += _test_map <map<int, double> >        ("map_int_double",          "{ 10:   1.11,       200:   22.22,       3000:    333.33}");
@@ -144,6 +152,9 @@ static int property_test(Detector& /* description */, int /* argc */, char** /*
   result += _test_cont<set<bool> >               ("set_bool",                "{true,                   false,              true}");
   result += _test_cont<set<int> >                ("set_int",                 "{11,                     222,               3333}");
   result += _test_cont<set<int> >                ("set_int_eval",            "{1*11,                   2*111,           3*1111}");
+  result += _test_cont<set<int> >                ("set_int",                 "{11,                     222,               3333}");
+  result += _test_cont<set<long> >               ("set_long_eval",           "{1*11,                   2*111,           3*1111}");
+  result += _test_cont<set<long> >               ("set_long",                "{11,                     222,               3333}");
   result += _test_cont<set<float> >              ("set_float",               "{1.11,                   22.22,             333.33}");
   result += _test_cont<set<float> >              ("set_float_eval",          "{1.11*GeV,               22.22*MeV,         333.3*TeV}");
   result += _test_cont<set<double> >             ("set_double",              "{1.11,                   22.22,             333.33}");
@@ -159,6 +170,10 @@ static int property_test(Detector& /* description */, int /* argc */, char** /*
   result += _test_cont<vector<bool> >            ("vector_bool",              "{true,                   false,              true}");
   result += _test_cont<vector<int> >             ("vector_int",               "{11,                     222,               3333}");
   result += _test_cont<vector<int> >             ("vector_int_eval",          "{1*11,                   2*111,           3*1111}");
+  result += _test_cont<vector<long> >            ("vector_long_eval",         "{1*11,                   2*111,           3*1111}");
+  result += _test_cont<vector<long> >            ("vector_long",              "{11,                     222,               3333}");
+  result += _test_cont<vector<ulong> >           ("vector_ulong_eval",        "{1*11,                   2*111,           3*1111}");
+  result += _test_cont<vector<ulong> >           ("vector_ulong",             "{11,                     222,               3333}");
   result += _test_cont<vector<float> >           ("vector_float",             "{1.11,                   22.22,             333.33}");
   result += _test_cont<vector<float> >           ("vector_float_eval",        "{1.11*GeV,               22.22*MeV,         333.3*TeV}");
   result += _test_cont<vector<double> >          ("vector_double",            "{1.11,                   22.22,             333.33}");
@@ -174,6 +189,10 @@ static int property_test(Detector& /* description */, int /* argc */, char** /*
   result += _test_cont<list<bool> >              ("list_bool",                "{true,                   false,              true}");
   result += _test_cont<list<int> >               ("list_int",                 "{11,                     222,               3333}");
   result += _test_cont<list<int> >               ("list_int_eval",            "{1*11,                   2*111,           3*1111}");
+  result += _test_cont<list<long> >              ("list_long_eval",           "{1*11,                   2*111,           3*1111}");
+  result += _test_cont<list<long> >              ("list_long",                "{11,                     222,               3333}");
+  result += _test_cont<list<ulong> >             ("list_ulong_eval",          "{1*11,                   2*111,           3*1111}");
+  result += _test_cont<list<ulong> >             ("list_ulong",               "{11,                     222,               3333}");
   result += _test_cont<list<float> >             ("list_float",               "{1.11,                   22.22,             333.33}");
   result += _test_cont<list<float> >             ("list_float_eval",          "{1.11*GeV,               22.22*MeV,         333.3*TeV}");
   result += _test_cont<list<double> >            ("list_double",              "{1.11,                   22.22,             333.33}");
diff --git a/examples/DDG4/CMakeLists.txt b/examples/DDG4/CMakeLists.txt
index 663de1ef2..dd5273d58 100644
--- a/examples/DDG4/CMakeLists.txt
+++ b/examples/DDG4/CMakeLists.txt
@@ -44,7 +44,8 @@ if (DD4HEP_USE_GEANT4)
   install(FILES ${LIBRARY_OUTPUT_PATH}/G__DDG4UserDict.rootmap DESTINATION lib)
   #
   #
-  dd4hep_install_dir(data DESTINATION ${CMAKE_INSTALL_PREFIX}/examples/DDG4 )
+  dd4hep_install_dir(data    DESTINATION ${CMAKE_INSTALL_PREFIX}/examples/DDG4 )
+  dd4hep_install_dir(scripts DESTINATION ${CMAKE_INSTALL_PREFIX}/examples/DDG4 )
   #
   dd4hep_configure_scripts (DDG4 DEFAULT_SETUP WITH_TESTS)
   #
@@ -61,4 +62,12 @@ if (DD4HEP_USE_GEANT4)
     EXEC_ARGS  ${Python_EXECUTABLE} ${DD4hep_ROOT}/examples/DDG4/examples/readHEPMC.py
                       ${DDG4examples_INSTALL}/data/LHCb_MinBias_HepMC.txt
     REGEX_PASS "Geant4InputAction\\[Input\\]: Event 27 Error when moving to event -  EOF")
+  #
+  # Test property types with specialized action
+  dd4hep_add_test_reg( DDG4_Test_property_types
+    COMMAND    "${CMAKE_INSTALL_PREFIX}/bin/run_test_DDG4.sh"
+    EXEC_ARGS  ${Python_EXECUTABLE} ${DDG4examples_INSTALL}/scripts/TestProperties.py
+    REGEX_PASS "Test PASSED"
+    REGEX_FAIL " ERROR ;EXCEPTION;Exception"
+  )
 endif()
diff --git a/examples/DDG4/scripts/TestProperties.py b/examples/DDG4/scripts/TestProperties.py
new file mode 100644
index 000000000..a0acfb0b4
--- /dev/null
+++ b/examples/DDG4/scripts/TestProperties.py
@@ -0,0 +1,138 @@
+# ==========================================================================
+#  AIDA Detector description implementation
+# --------------------------------------------------------------------------
+# 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.
+#
+# ==========================================================================
+from __future__ import absolute_import, unicode_literals
+import DDG4
+import sys
+import os
+from g4units import GeV, MeV, m
+#
+#
+"""
+
+   dd4hep example setup using the python configuration
+
+   \author  M.Frank
+   \version 1.0
+
+"""
+
+
+def run():
+
+  kernel = DDG4.Kernel()
+  install_dir = os.environ['DD4hepExamplesINSTALL']
+  kernel.loadGeometry(str("file:" + install_dir + "/examples/ClientTests/compact/SiliconBlock.xml"))
+
+  DDG4.importConstants(kernel.detectorDescription(), debug=False)
+
+  geant4 = DDG4.Geant4(kernel)
+  ui = geant4.setupCshUI(vis=None)
+
+  # Now the calorimeters
+  act = DDG4.Action(kernel, str('PropertyTestAction/Test'));
+  act.prop_str  =             'Hello World!'
+  act.prop_bool  =            True
+  act.prop_int  =             1234
+  act.prop_long  =            3456
+  act.prop_ulong =            4567
+  act.prop_float  =           1234567.8
+  act.prop_double  =          1234567.8
+  act.prop_XYZPoint  =        (1,2,3)
+  act.prop_XYZVector  =       (1*m,2*m,3*m)
+  act.prop_PxPyPzEVector  =   (1*GeV,2*GeV,3*GeV,4*GeV)
+
+  act.map_str_str  =          {'a': 'AA',   'b': 'BB',   'c': 'CC'}
+  act.map_str_bool =          {'a': 1,      'b': 0,      'c': 1}
+  act.map_str_int =           {'a': 11,     'b': 22,     'c': 33}
+  act.map_str_long =          {'a': 111,    'b': 222,    'c': 333}
+  #act.map_str_ulong =         {'a': 1111,   'b': 2222,   'c': 3333}
+  act.map_str_float =         {'a': 11.11,  'b': 22.22,  'c': 33.33}
+  act.map_str_double =        {'a': 11.111, 'b': 22.222, 'c': 33.333}
+
+  act.map_int_str =           {100: 'AA',   200: 'BB',   300: 'CC'}
+  act.map_int_bool =          {100: 1,      200: 0,      300: 1}
+  act.map_int_int =           {100: 11,     200: 22,     300: 33}
+  act.map_int_long =          {100: 111,    200: 222,    300: 333}
+  #act.map_int_ulong =         {100: 1111,   200: 2222,   300: 3333}
+  act.map_int_float =         {100: 11.11,  200: 22.22,  300: 33.33}
+  act.map_int_double =        {100: 11.111, 200: 22.222, 300: 33.333}
+
+  act.map_int_str =           {100*10: 'AA',   200*10: 'BB',   300*10: 'CC'}
+  act.map_int_bool =          {100*10: 1,      200*10: 0,      300*10: 1}
+  act.map_int_int =           {100*10: 11,     200*10: 22,     300*10: 33}
+  act.map_int_long =          {100*10: 111,    200*10: 222,    300*10: 333}
+  #act.map_int_ulong =         {100*10: 1111,   200*10: 2222,   300*10: 3333}
+  act.map_int_float =         {100*10: 11.11,  200*10: 22.22,  300*10: 33.33}
+  act.map_int_double =        {100*10: 11.111, 200*10: 22.222, 300*10: 33.333}
+
+  act.set_str =               ['aa', 'bb', 'cc' ,'dd']
+  act.set_bool =              [0,0,0,1,1,1]
+  act.set_int =               [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8]
+  act.set_long =              [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8]
+  #act.set_ulong =             [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8]
+  act.set_float =             [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8]
+  act.set_double =            [0*m, 1*m, 2*m, 3*m, 4*m, 5*m, 6*m, 7*m, 8*m, 8*m, 8*m]
+  act.set_XYZPoint =          [(1,2,3),(11,22,33),(111,222,333),(1111,2222,3333)]
+  act.set_XYZVector =         [(1,2,3),(11,22,33),(111,222,333),(1111,2222,3333)]
+  act.set_PxPyPzEVector =     [(1*GeV,2*GeV,3*GeV,4*GeV), (11*GeV,22*GeV,33*GeV,44*GeV), (111*GeV,222*GeV,333*GeV,444*GeV)]
+
+  act.list_str =              ['aa', 'bb', 'cc' ,'dd']
+  act.list_bool =             [0,0,0,1,1,1]
+  act.list_int =              [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8]
+  act.list_long =             [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8]
+  act.list_ulong =            [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8]
+  act.list_float =            [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8]
+  act.list_double =           [0*m, 1*m, 2*m, 3*m, 4*m, 5*m, 6*m, 7*m, 8*m, 8*m, 8*m]
+  act.list_XYZPoint =         [(1,2,3),(11,22,33),(111,222,333),(1111,2222,3333)]
+  act.list_XYZVector =        [(1,2,3),(11,22,33),(111,222,333),(1111,2222,3333)]
+  act.list_PxPyPzEVector =    [(1*GeV,2*GeV,3*GeV,4*GeV), (11*GeV,22*GeV,33*GeV,44*GeV), (111*GeV,222*GeV,333*GeV,444*GeV)]
+
+  act.vector_str =            ['aa', 'bb', 'cc' ,'dd']
+  act.vector_bool =           [0,0,0,1,1,1]
+  act.vector_int =            [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8]
+  act.vector_long =           [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8]
+  act.vector_ulong =          [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8]
+  act.vector_float =          [0, 1, 2, 3, 4, 5, 6, 7, 8, 8, 8]
+  act.vector_double =         [0*m, 1*m, 2*m, 3*m, 4*m, 5*m, 6*m, 7*m, 8*m, 8*m, 8*m]
+  act.vector_XYZPoint =       [(1,2,3),(11,22,33),(111,222,333),(1111,2222,3333)]
+  act.vector_XYZVector =      [(1,2,3),(11,22,33),(111,222,333),(1111,2222,3333)]
+  act.vector_PxPyPzEVector =  [(1*GeV,2*GeV,3*GeV,4*GeV), (11*GeV,22*GeV,33*GeV,44*GeV), (111*GeV,222*GeV,333*GeV,444*GeV)]
+
+  #  Check read access:
+  print('-------------------------------------------------------')
+  print(act.prop_str)              #     'Hello World!'
+  print(act.prop_bool)             #     True
+  print(act.prop_int)              #     1234
+  print(act.prop_float)            #     1234567.8
+  print(act.prop_double)           #     1234567.8
+  print(act.prop_XYZPoint)         #     (1,2,3)
+  print(act.prop_XYZVector)        #     (1*m,2*m,3*m)
+  print(act.prop_PxPyPzEVector)    #     (1*GeV,2*GeV,3*GeV,4*GeV)
+  print('-------------------------------------------------------')
+
+  act.enableUI()
+
+  phys = geant4.setupPhysics('FTFP_BERT')
+  phys.dump()
+  ui.Commands = [
+    '/ddg4/Test/show',
+    '/ddg4/Test/dumpProperties',
+    '/ddg4/UI/exit'
+  ]
+  kernel.NumEvents = 0
+  kernel.configure()
+  kernel.initialize()
+  kernel.run()
+  kernel.terminate()
+
+
+if __name__ == "__main__":
+  run()
diff --git a/examples/DDG4/src/PropertyTestAction.cpp b/examples/DDG4/src/PropertyTestAction.cpp
new file mode 100644
index 000000000..e18f7bea0
--- /dev/null
+++ b/examples/DDG4/src/PropertyTestAction.cpp
@@ -0,0 +1,346 @@
+//==========================================================================
+//  AIDA Detector description implementation 
+//--------------------------------------------------------------------------
+// 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     : M.Frank
+//
+//==========================================================================
+#ifndef DD4HEP_DDG4_PROPERTYTESTACTION_H
+#define DD4HEP_DDG4_PROPERTYTESTACTION_H
+
+/// Framework include files
+#include <DDG4/Geant4Action.h>
+#include <DD4hep/ComponentProperties.h>
+
+/// ROOT include files
+#include <Math/Point3D.h>
+#include <Math/Vector4D.h>
+#include <Math/Vector3D.h>
+
+/// C/C++ include files
+#include <map>
+#include <set>
+#include <list>
+#include <vector>
+
+/// Namespace example name of the user
+namespace DD4hepTests   {
+
+  using namespace std;
+
+  /// Class to measure the energy of escaping tracks
+  /** Class to measure the energy of escaping tracks of a detector using Geant 4
+   * Measure escaping energy....
+   *
+   *  \author  M.Frank
+   *  \version 1.0
+   *  \ingroup DD4HEP_SIMULATION
+   */
+  class PropertyTestAction : public dd4hep::sim::Geant4Action {
+  public:
+    using XYZPoint  = ROOT::Math::XYZPoint;
+    using XYZVector = ROOT::Math::XYZVector;
+    using PxPyPzE   = ROOT::Math::PxPyPzEVector;
+    typedef unsigned long ulong;
+
+    string                   prop_str;               // 'a'
+    bool                     prop_bool;              // true
+    int                      prop_int;               // 11
+    long                     prop_long;              // 11
+    unsigned long            prop_ulong;             // 11
+    float                    prop_float;             // 1.11
+    double                   prop_double;            // 1.11
+    XYZPoint                 prop_XYZPoint;          // (1, 2, 3)
+    XYZVector                prop_XYZVector;         // (1, 2, 3)
+    PxPyPzE                  prop_PxPyPzEVector;     // (1, 2, 3, 4)
+
+    map<string, string>      map_str_str;            // {'a':   'a',      'b': 'bb',        'c': 'ccc'}
+    map<string, bool>        map_str_bool;           // {'a':   true,     'b':  false,      'c':  true}
+    map<string, int>         map_str_int;            // {'a':   11,       'b':  200,        'c':  3000}
+    map<string, long>        map_str_long;           // {'a':   11,       'b':  200,        'c':  3000}
+    //map<string, ulong>       map_str_ulong;          // {'a':   11,       'b':  200,        'c':  3000}
+    map<string, float>       map_str_float;          // {'a':   1.11,     'b': 22.22,       'c': 333.33}
+    map<string, double>      map_str_double;         // {'a':   1.11,     'b': 22.22,       'c': 333.33}
+
+    map<int, string>         map_int_str;            // { 10:   'a',        200:   'bb',        3000: '    ccc'}
+    map<int, bool>           map_int_bool;           // { 10:   true,       200:  false,        3000:      true}
+    map<int, int>            map_int_int;            // { 10:   11,         200:  200,          3000:      3000}
+    map<int, long>           map_int_long;           // { 10:   11,         200:  200,          3000:      3000}
+    //map<int, ulong>          map_int_ulong;          // { 10:   11,         200:  200,          3000:      3000}
+    map<int, float>          map_int_float;          // { 10:   1.11,       200:   22.22,       3000:    333.33}
+    map<int, double>         map_int_double;         // { 10:   1.11,       200:   22.22,       3000:    333.33}
+
+    set<string>              set_str;                // {'a',                    'bb',              'ccc'}
+    set<bool>                set_bool;               // {true,                   false,              true}
+    set<int>                 set_int;                // {11,                     222,               3333}
+    set<long>                set_long;               // {11,                     222,               3333}
+    //set<ulong>               set_ulong;              // {11,                     222,               3333}
+    set<float>               set_float;              // {1.11,                   22.22,             333.33}
+    set<double>              set_double;             // {1.11,                   22.22,             333.33}
+    set<XYZPoint>            set_XYZPoint;           // {(1, 2, 3),              (10,20,30),       (100,200,300)}
+    set<XYZVector>           set_XYZVector;          // {(1, 2, 3),              (10,20,30),       (100,200,300)}
+    set<PxPyPzE>             set_PxPyPzEVector;      // {(1, 2, 3,4),            (10,20,30,40),    (100,200,300,400)}
+
+    vector<string>           vector_str;              // {'a',                    'bb',              'ccc'}
+    vector<bool>             vector_bool;             // {true,                   false,              true}
+    vector<int>              vector_int;              // {11,                     222,               3333}
+    vector<long>             vector_long;             // {11,                     222,               3333}
+    vector<ulong>            vector_ulong;            // {11,                     222,               3333}
+    vector<float>            vector_float;            // {1.11,                   22.22,             333.33}
+    vector<double>           vector_double;           // {1.11,                   22.22,             333.33}
+    vector<XYZPoint>         vector_XYZPoint;         // {(1, 2, 3),              (10,20,30), (100,200,300)}
+    vector<XYZVector>        vector_XYZVector;        // {(1, 2, 3),              (10,20,30), (100,200,300)}
+    vector<PxPyPzE>          vector_PxPyPzEVector;    // {(1, 2, 3,4),            (10,20,30,40),    (100,200,300,400)}
+
+    list<string>             list_str;                // {'a',                    'bb',              'ccc'}
+    list<bool>               list_bool;               // {true,                   false,              true}
+    list<int>                list_int;                // {11,                     222,               3333}
+    list<long>               list_long;               // {11,                     222,               3333}
+    list<ulong>              list_ulong;              // {11,                     222,               3333}
+    list<float>              list_float;              // {1.11,                   22.22,             333.33}
+    list<double>             list_double;             // {1.11,                   22.22,             333.33}
+    list<XYZPoint>           list_XYZPoint;           // {(1, 2, 3),              (10,20,30), (100,200,300)}
+    list<XYZVector>          list_XYZVector;          // {(1, 2, 3),              (10,20,30), (100,200,300)}
+    list<PxPyPzE>            list_PxPyPzEVector;      // {(1, 2, 3,4),            (10,20,30,40),    (100,200,300,400)}
+
+  public:
+    /// Standard constructor
+    PropertyTestAction(dd4hep::sim::Geant4Context* context, const std::string& nam);
+    /// Default destructor
+    virtual ~PropertyTestAction() = default;
+    /// Dump properties to screen
+    void dumpProperties()  const;
+    /// Install command control messenger
+    virtual void installCommandMessenger()  override;
+  };
+}      // End namespace dd4hep
+#endif /* DD4HEP_DDG4_PROPERTYTESTACTION_H */
+
+//====================================================================
+//  AIDA Detector description implementation 
+//--------------------------------------------------------------------
+// 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     : M.Frank
+//
+//====================================================================
+
+// Framework include files
+#include <DDG4/Geant4UIMessenger.h>
+
+#include <iostream>
+#include <sstream>
+
+using namespace std;
+
+namespace {
+  string str_rep(string in, const string& pat, const string& rep)   {
+    size_t idx = string::npos;
+    string res = in;
+    while( (idx=res.find(pat)) != string::npos )
+      res.replace(idx, pat.length(), rep);
+    return res;
+  }
+  void _print(stringstream& log)   {
+    auto res = str_rep(log.str(), "( ", "(");
+    cout << res << endl;
+  }
+  /// Dump properties to screen
+  template <typename T> int dump_item(const string& tag, const T& value)    {
+    try  {
+      stringstream log;
+      log << "| " << setw(32) << left << tag << " " << setw(6) << left << value;
+      _print(log);
+    }
+    catch(const exception& e)   {
+      cout << "Test FAILED: " << tag << " Exception: " << e.what() << endl;
+      return 1;
+    }
+    return 0;
+  }
+  template <typename T> int dump_cont(const string& tag, const T& value)    {
+    try  {
+      stringstream log;
+      log << "| " << setw(32) << left << tag << " ";
+      for(const auto& p : value)
+	log << setw(6) << left << p << "  ";
+      _print(log);
+    }
+    catch(const exception& e)   {
+      cout << "Test FAILED: " << tag << " Exception: " << e.what() << endl;
+      return 1;
+    }
+    return 0;
+  }
+  template <typename T> int dump_map(const string& tag, const T& value)    {
+    try  {
+      stringstream log;
+      log << "| " << setw(32) << left << tag << " ";
+      for(const auto& p : value)
+	log << setw(6) << left << p.first << " = " << setw(10) << left << p.second << "  ";
+      _print(log);
+    }
+    catch(const exception& e)   {
+      cout << "Test FAILED: " << tag << " Exception: " << e.what() << endl;
+      return 1;
+    }
+    return 0;
+  }
+}
+
+/// Standard constructor
+DD4hepTests::PropertyTestAction::PropertyTestAction(dd4hep::sim::Geant4Context* ctxt, const string& nam)
+  : dd4hep::sim::Geant4Action(ctxt, nam)
+{
+  declareProperty("prop_str",   prop_str); 
+  declareProperty("prop_bool",  prop_bool);
+  declareProperty("prop_int",   prop_int);
+  declareProperty("prop_long",  prop_long);
+  declareProperty("prop_ulong",  prop_ulong);
+  declareProperty("prop_float", prop_float);           
+  declareProperty("prop_double", prop_double);          
+  declareProperty("prop_XYZPoint", prop_XYZPoint);        
+  declareProperty("prop_XYZVector", prop_XYZVector);         
+  declareProperty("prop_PxPyPzEVector", prop_PxPyPzEVector);
+
+  declareProperty("map_str_str", map_str_str);
+  declareProperty("map_str_bool", map_str_bool);
+  declareProperty("map_str_int", map_str_int);
+  declareProperty("map_str_long", map_str_long);
+  //declareProperty("map_str_ulong", map_str_ulong);
+  declareProperty("map_str_float", map_str_float);
+  declareProperty("map_str_double", map_str_double);
+
+  declareProperty("map_int_str", map_int_str);
+  declareProperty("map_int_bool", map_int_bool);
+  declareProperty("map_int_int", map_int_int);
+  declareProperty("map_int_long", map_int_long);
+  //declareProperty("map_int_ulong", map_int_ulong);
+  declareProperty("map_int_float", map_int_float);
+  declareProperty("map_int_double", map_int_double);
+
+  declareProperty("set_str", set_str);
+  declareProperty("set_bool", set_bool);
+  declareProperty("set_int", set_int);
+  declareProperty("set_long", set_long);
+  //declareProperty("set_ulong", set_ulong);
+  declareProperty("set_float", set_float);
+  declareProperty("set_double", set_double);
+  declareProperty("set_XYZPoint", set_XYZPoint);
+  declareProperty("set_XYZVector", set_XYZVector);
+  declareProperty("set_PxPyPzEVector", set_PxPyPzEVector);
+
+  declareProperty("vector_str", vector_str);
+  declareProperty("vector_bool", vector_bool);
+  declareProperty("vector_int", vector_int);
+  declareProperty("vector_long", vector_long);
+  declareProperty("vector_ulong", vector_ulong);
+  declareProperty("vector_float", vector_float);
+  declareProperty("vector_double", vector_double);
+  declareProperty("vector_XYZPoint", vector_XYZPoint);
+  declareProperty("vector_XYZVector", vector_XYZVector);
+  declareProperty("vector_PxPyPzEVector", vector_PxPyPzEVector);
+
+  declareProperty("list_str", list_str);
+  declareProperty("list_bool", list_bool);
+  declareProperty("list_int", list_int);
+  declareProperty("list_long", list_long);
+  declareProperty("list_ulong", list_ulong);
+  declareProperty("list_float", list_float);
+  declareProperty("list_double", list_double);
+  declareProperty("list_XYZPoint", list_XYZPoint);
+  declareProperty("list_XYZVector", list_XYZVector);
+  declareProperty("list_PxPyPzEVector", list_PxPyPzEVector);
+}
+
+/// Install command control messenger
+void DD4hepTests::PropertyTestAction::installCommandMessenger()   {
+  this->Geant4Action::installCommandMessenger();
+  m_control->addCall("dumpProperties", "Execute property check",
+                     dd4hep::Callback(this).make(&PropertyTestAction::dumpProperties),0);
+}
+
+/// Dump properties to screen
+void DD4hepTests::PropertyTestAction::dumpProperties()  const    {
+  int result = 0;
+  const char* line = "+----------------------------------------------------------------------------------------------------------";
+  cout << line << endl;
+  result += dump_item("prop_str", prop_str); 
+  result += dump_item("prop_bool", prop_bool);
+  result += dump_item("prop_int", prop_int);
+  result += dump_item("prop_long", prop_long);
+  result += dump_item("prop_ulong", prop_ulong);
+  result += dump_item("prop_float", prop_float);           
+  result += dump_item("prop_double", prop_double);          
+  result += dump_item("prop_XYZPoint", prop_XYZPoint);        
+  result += dump_item("prop_XYZVector", prop_XYZVector);         
+  result += dump_item("prop_PxPyPzEVector", prop_PxPyPzEVector);
+  cout << line << endl;
+  result += dump_map("map_str_str", map_str_str);
+  result += dump_map("map_str_bool", map_str_bool);
+  result += dump_map("map_str_int", map_str_int);
+  result += dump_map("map_str_long", map_str_long);
+  //result += dump_map("map_str_ulong", map_str_ulong);
+  result += dump_map("map_str_float", map_str_float);
+  result += dump_map("map_str_double", map_str_double);
+  cout << line << endl;
+  result += dump_map("map_int_str", map_int_str);
+  result += dump_map("map_int_bool", map_int_bool);
+  result += dump_map("map_int_int", map_int_int);
+  result += dump_map("map_int_long", map_int_long);
+  //result += dump_map("map_int_ulong", map_int_ulong);
+  result += dump_map("map_int_float", map_int_float);
+  result += dump_map("map_int_double", map_int_double);
+  cout << line << endl;
+  result += dump_cont("set_str", set_str);
+  result += dump_cont("set_bool", set_bool);
+  result += dump_cont("set_int", set_int);
+  result += dump_cont("set_long", set_long);
+  //result += dump_cont("set_ulong", set_ulong);
+  result += dump_cont("set_float", set_float);
+  result += dump_cont("set_double", set_double);
+  result += dump_cont("set_XYZPoint", set_XYZPoint);
+  result += dump_cont("set_XYZVector", set_XYZVector);
+  result += dump_cont("set_PxPyPzEVector", set_PxPyPzEVector);
+  cout << line << endl;
+  result += dump_cont("vector_str", vector_str);
+  result += dump_cont("vector_bool", vector_bool);
+  result += dump_cont("vector_int", vector_int);
+  result += dump_cont("vector_long", vector_long);
+  result += dump_cont("vector_ulong", vector_ulong);
+  result += dump_cont("vector_float", vector_float);
+  result += dump_cont("vector_double", vector_double);
+  result += dump_cont("vector_XYZPoint", vector_XYZPoint);
+  result += dump_cont("vector_XYZVector", vector_XYZVector);
+  result += dump_cont("vector_PxPyPzEVector", vector_PxPyPzEVector);
+  cout << line << endl;
+  result += dump_cont("list_str", list_str);
+  result += dump_cont("list_bool", list_bool);
+  result += dump_cont("list_int", list_int);
+  result += dump_cont("list_long", list_long);
+  result += dump_cont("list_ulong", list_ulong);
+  result += dump_cont("list_float", list_float);
+  result += dump_cont("list_double", list_double);
+  result += dump_cont("list_XYZPoint", list_XYZPoint);
+  result += dump_cont("list_XYZVector", list_XYZVector);
+  result += dump_cont("list_PxPyPzEVector", list_PxPyPzEVector);
+  cout << line << endl;
+
+  if ( 0 == result )
+    cout << endl << "Test PASSED" << endl << endl;
+  else
+    cout << endl << "Test FAILED" << endl << "===> " << result << " Subtests FAILED" << endl;
+  cout << line << endl;
+}
+
+#include "DDG4/Factories.h"
+DECLARE_GEANT4ACTION_NS(DD4hepTests,PropertyTestAction)
-- 
GitLab