From 5904636f081c8deb193b58aba791889c7cc1b93b Mon Sep 17 00:00:00 2001
From: Markus Frank <markus.frank@cern.ch>
Date: Thu, 30 Jun 2016 12:38:08 +0000
Subject: [PATCH] Improv4ed implementation of conditions

---
 DDCond/CMakeLists.txt                         |   5 +-
 DDCond/include/DDCond/ConditionsDataLoader.h  |   8 +-
 DDCond/include/DDCond/ConditionsIOVPool.h     |  20 +-
 DDCond/include/DDCond/ConditionsInterna.h     |  68 ++++--
 DDCond/include/DDCond/ConditionsListener.h    |  62 ++++++
 DDCond/include/DDCond/ConditionsManager.h     |  34 ++-
 DDCond/include/DDCond/ConditionsPool.h        |  60 ++++--
 DDCond/include/DDCond/ConditionsTest.h        |  73 +++++++
 DDCond/src/ConditionsDataLoader.cpp           |   4 +-
 DDCond/src/ConditionsIOVPool.cpp              |  66 +++---
 DDCond/src/ConditionsInterna.cpp              | 198 +++++++++++++-----
 DDCond/src/ConditionsListener.cpp             |  26 +++
 DDCond/src/ConditionsManager.cpp              |  63 +++++-
 DDCond/src/ConditionsPool.cpp                 |  46 +++-
 DDCond/src/ConditionsTest.cpp                 |  12 +-
 .../src/{ => plugins}/ConditionsExample.cpp   |  69 +++---
 .../{ => plugins}/ConditionsLinearPool.cpp    | 149 ++++++++-----
 .../plugins/ConditionsManagerInstaller.cpp    |  39 ++++
 .../{ => plugins}/ConditionsMultiLoader.cpp   | 120 ++++++-----
 DDCond/src/{ => plugins}/ConditionsParser.cpp |   4 +-
 DDCond/src/plugins/ConditionsPlugins.cpp      | 137 ++++++++++++
 DDCond/src/plugins/ConditionsUpdate.cpp       |  15 ++
 .../src/{ => plugins}/ConditionsXmlLoader.cpp |  49 +++--
 DDCore/include/DD4hep/Conditions.h            |  51 ++++-
 DDCore/include/DD4hep/InstanceCount.h         |  14 ++
 DDCore/include/DD4hep/LCDD.h                  |  16 +-
 DDCore/include/DD4hep/LCDDLoad.h              |  26 ++-
 DDCore/include/DD4hep/Operators.h             |  68 ++++++
 DDCore/include/DD4hep/PluginCreators.h        |   4 +-
 DDCore/include/DD4hep/Primitives.h            |   6 +-
 DDCore/include/DD4hep/Readout.h               |   2 +
 .../include/DD4hep/objects/BasicGrammar_inl.h |  18 +-
 .../DD4hep/objects/ConditionsInterna.h        |  52 +++--
 DDCore/include/XML/UriReader.h                |  42 +++-
 DDCore/src/Conditions.cpp                     | 118 ++++++++++-
 DDCore/src/ConditionsInterna.cpp              |  50 ++++-
 DDCore/src/Evaluator/setStdMath.cpp           | 122 +++++++----
 DDCore/src/LCDDImp.cpp                        |   9 +-
 DDCore/src/LCDDImp.h                          |   5 +
 DDCore/src/LCDDLoad.cpp                       |  14 +-
 DDCore/src/Readout.cpp                        |  22 +-
 DDCore/src/XML/DocumentHandler.cpp            |   2 +-
 DDCore/src/XML/UriReader.cpp                  |  25 +++
 DDCore/src/plugins/Compact2Objects.cpp        |  56 +++--
 DDCore/src/plugins/StandardPlugins.cpp        |  79 +++----
 UtilityApps/src/dd4hep_python.cpp             |  51 -----
 46 files changed, 1624 insertions(+), 555 deletions(-)
 create mode 100644 DDCond/include/DDCond/ConditionsListener.h
 create mode 100644 DDCond/include/DDCond/ConditionsTest.h
 create mode 100644 DDCond/src/ConditionsListener.cpp
 rename DDCond/src/{ => plugins}/ConditionsExample.cpp (88%)
 rename DDCond/src/{ => plugins}/ConditionsLinearPool.cpp (66%)
 create mode 100644 DDCond/src/plugins/ConditionsManagerInstaller.cpp
 rename DDCond/src/{ => plugins}/ConditionsMultiLoader.cpp (59%)
 rename DDCond/src/{ => plugins}/ConditionsParser.cpp (99%)
 create mode 100644 DDCond/src/plugins/ConditionsPlugins.cpp
 create mode 100644 DDCond/src/plugins/ConditionsUpdate.cpp
 rename DDCond/src/{ => plugins}/ConditionsXmlLoader.cpp (83%)
 create mode 100644 DDCore/include/DD4hep/Operators.h
 delete mode 100644 UtilityApps/src/dd4hep_python.cpp

diff --git a/DDCond/CMakeLists.txt b/DDCond/CMakeLists.txt
index d27c519a6..0b3c2e2de 100644
--- a/DDCond/CMakeLists.txt
+++ b/DDCond/CMakeLists.txt
@@ -15,4 +15,7 @@ dd4hep_package(    DDCond
   INSTALL_INCLUDES include/DDCond)
 
 #---DDCond library --------------------------------------------------------------
-dd4hep_add_plugin ( DDCond SOURCES src/*.cpp )
+dd4hep_add_package_library(DDCond SOURCES src/*.cpp )
+
+#---DDCond components -----------------------------------------------------------
+dd4hep_add_plugin ( DDCondPlugins  SOURCES  src/plugins/*.cpp )
diff --git a/DDCond/include/DDCond/ConditionsDataLoader.h b/DDCond/include/DDCond/ConditionsDataLoader.h
index 2b6bcd2dd..78948d20f 100644
--- a/DDCond/include/DDCond/ConditionsDataLoader.h
+++ b/DDCond/include/DDCond/ConditionsDataLoader.h
@@ -44,7 +44,8 @@ namespace DD4hep {
      */
     class ConditionsDataLoader : public NamedObject, public PropertyConfigurable   {
     public:
-      typedef std::vector<std::string> Sources;
+      typedef std::pair<std::string, IOV> Source;
+      typedef std::vector<Source> Sources;
       typedef ConditionsDataLoader base_t;
 
     protected:
@@ -67,7 +68,7 @@ namespace DD4hep {
       /// Default destructor
       virtual ~ConditionsDataLoader();
       /// Add data source definition to loader
-      void addSource(const std::string& source);
+      void addSource(const std::string& source, const IOV& iov);
       /// Load  a condition set given a Detector Element and the conditions name according to their validity
       virtual size_t load(DetElement det,
                           const std::string& cond,
@@ -78,6 +79,9 @@ namespace DD4hep {
                                 const std::string& cond,
                                 const IOV& req_validity,
                                 RangeConditions& conditions) = 0;
+      virtual size_t update(const IOV& req_validity,
+			    RangeConditions& conditions,
+			    IOV& conditions_validity) = 0;
     };
 
   } /* End namespace Conditions             */
diff --git a/DDCond/include/DDCond/ConditionsIOVPool.h b/DDCond/include/DDCond/ConditionsIOVPool.h
index 764b56607..7319c39de 100644
--- a/DDCond/include/DDCond/ConditionsIOVPool.h
+++ b/DDCond/include/DDCond/ConditionsIOVPool.h
@@ -41,13 +41,18 @@ namespace DD4hep {
     class ConditionsIOVPool  {
     public:
       typedef ConditionsPool* Entry;
-      typedef std::map<std::pair<int,int>, Entry > Entries;
+      typedef std::map<IOV::Key, Entry > Entries;
+      typedef std::set<int>              Keys;
+      
       Entries        entries;
+      Keys           keys;
+      Keys           traced_keys;
     public:
       /// Default constructor
       ConditionsIOVPool();
       /// Default destructor
       virtual ~ConditionsIOVPool();
+      bool addKey(Condition c);
       /// Retrieve  a condition set given a Detector Element and the conditions name according to their validity
       void __find(DetElement detector,
                   const std::string& condition_name,
@@ -59,12 +64,13 @@ namespace DD4hep {
                         const IOV& req_validity,
                         RangeConditions& result);
       /// Select all ACTIVE conditions, which do no longer match the IOV requirement
-      void __select_expired(const IOV& required_validity, 
-                            RangeConditions& result);
-      void __update_expired(ConditionsDataLoader& loader,
-                            ConditionsPool& pool,
-                            RangeConditions& expired,
-                            const IOV& required_validity);
+      void select(const IOV& required_validity, 
+		  RangeConditions& valid,
+		  RangeConditions& expired,
+		  IOV& conditions_validity);
+      /// Remove all key based pools with an age beyon the minimum age. 
+      /** @return Number of conditions cleaned up and removed.                       */
+      int clean(int max_age);
    };
 
   } /* End namespace Conditions             */
diff --git a/DDCond/include/DDCond/ConditionsInterna.h b/DDCond/include/DDCond/ConditionsInterna.h
index 6ca9ab592..90f775f50 100644
--- a/DDCond/include/DDCond/ConditionsInterna.h
+++ b/DDCond/include/DDCond/ConditionsInterna.h
@@ -35,6 +35,7 @@ namespace DD4hep {
     class Entry;
     class ConditionsPool;
     class ConditionsIOVPool;
+    class ConditionsListener;
     class ConditionsDataLoader;
 
     /// Conditions internal namespace declaration
@@ -57,25 +58,28 @@ namespace DD4hep {
        *  \ingroup DD4HEP_CONDITIONS
        */
       class ConditionsManagerObject : public NamedObject, public PropertyConfigurable {
-      public:
-        friend class ConditionsDataLoader;
+        friend class DD4hep::Conditions::ConditionsPool;
+        friend class DD4hep::Conditions::ConditionsDataLoader;
 
-        typedef dd4hep_ptr<ConditionsDataLoader> Loader;
-        typedef std::vector<IOVType>  IOVTypes;
-        typedef std::vector<ConditionsIOVPool*> TypedConditionPool;
+      public:
+        typedef dd4hep_ptr<ConditionsDataLoader>     Loader;
+        typedef std::vector<IOVType>                 IOVTypes;
+        typedef std::vector<ConditionsIOVPool*>      TypedConditionPool;
 
         typedef std::map<IOV::Key, ReplacementPool*> ReplacementCache;
-        typedef std::vector<ReplacementPool*> FreePools;
+        typedef std::vector<ReplacementPool*>        FreePools;
+	typedef std::pair<ConditionsListener*,void*> Listener;
+	typedef std::set<Listener>                   Listeners;
 
       public:
         /// Property: maximal number of IOV types to be handled
-        int                m_maxIOVTypes;
+        int                    m_maxIOVTypes;
         /// Property: ConditionsPool constructor type (default: empty. MUST BE SET!)
-        std::string        m_poolType;
+        std::string            m_poolType;
         /// Property: UpdatePool constructor type (default: DD4hep_ConditionsLinearUpdatePool)
-        std::string        m_updateType;
-        /// Property: ReplacementPool constructor type (default: DD4hep_ConditionsLinearReplacementPool)
-        std::string        m_replType;
+        std::string            m_updateType;
+        /// Property: UserPool constructor type (default: DD4hep_ConditionsLinearUserPool)
+        std::string            m_userType;
         /// Property: Conditions loader type (default: "multi" -> DD4hep_Conditions_multi_Loader)
         std::string            m_loaderType;
 
@@ -85,6 +89,10 @@ namespace DD4hep {
         IOVTypes               m_iovTypes;
         /// Managed pool of typed conditions idexed by IOV-type and IOV key
         TypedConditionPool     m_pool;
+	/// Conditions listeners on registration of new conditions
+	Listeners              m_onRegister;
+	/// Conditions listeners on de-registration of new conditions
+	Listeners              m_onRemove;
         /// Lock to protect the update/delayed conditions pool
         dd4hep_mutex_t         m_updateLock;
         /// Lock to protect the pool of all known conditions
@@ -125,6 +133,14 @@ namespace DD4hep {
         /// Push registered set of conditions to the corresponding detector elements
         void __push_immediate(RangeConditions& rc);
 
+	void registerCallee(Listeners& listeners, const Listener& callee, bool add);
+
+	/// Listener invocation when a condition is registered to the cache
+	void onRegister(Condition condition);
+
+	/// Listener invocation when a condition is deregistered from the cache
+	void onRemove(Condition condition);
+
       public:
         /// Set a single conditions value to be managed.
         /// Requires EXTERNALLY held lock on update pool!
@@ -139,41 +155,51 @@ namespace DD4hep {
 
         void initialize();
 
+	/// (Un)Registration of conditions listeners with callback when a new condition is registered
+	void callOnRegister(const Listener& callee, bool add);
+	/// (Un)Registration of conditions listeners with callback when a condition is unregistered
+	void callOnRemove(const Listener& callee, bool add);
+
         /// Register new IOV type if it does not (yet) exist.
         /** Returns (false,pointer) if IOV existed and
          *  (true,pointer) if new IOV was registered to the manager.
          */
         std::pair<bool, const IOVType*> registerIOVType(size_t iov_type, const std::string& iov_name);
       
+        /// Access IOV by its type
+        const IOVTypes& iovTypes () const   {   return  m_iovTypes;  }
+
         /// Access IOV by its type
         const IOVType* iovType (size_t iov_type) const;
 
         /// Access IOV by its name
         const IOVType* iovType (const std::string& iov_name) const;
 
+	/// Create IOV from string
+	void fromString(const std::string& iov_str, IOV& iov);
+
         /// Register IOV using new string data
         ConditionsPool* registerIOV(const std::string& data);
+
         /// Register IOV with type and key
         ConditionsPool* registerIOV(const IOVType& typ, IOV::Key key);
 
+	/// Register new condition with the conditions store. Unlocked version, not multi-threaded
+	bool registerUnlocked(ConditionsPool* pool, Condition cond);
 
         /// Prepare all updates to the clients with the defined IOV
-        void prepare(const IOV& required_validity);
+        long prepare(const IOV& required_validity, dd4hep_ptr<ConditionsPool>& user_pool);
 
         /// Enable all updates to the clients with the defined IOV
-        void enable(const IOV& required_validity);
-
-        /// Validate the conditions set and age all unused conditions
-        void validate(const IOV& iov);
-
-        /// Age conditions, which are no longer used and to be removed eventually
-        void age();
+        long enable(const IOV& required_validity, dd4hep_ptr<ConditionsPool>& user_pool);
 
         /// Clean conditions, which are above the age limit.
-        void clean();
+	/** @return Number of conditions cleaned up and removed  */
+        int clean(const IOVType* typ, int max_age);
 
         /// Full cleanup of all managed conditions.
-        void clear();
+	/** @return pair<Number of pools cleared, Number of conditions cleaned up and removed> */
+	std::pair<int,int> clear();
 
         /// Push all pending updates to the conditions store. 
         /** Note:
diff --git a/DDCond/include/DDCond/ConditionsListener.h b/DDCond/include/DDCond/ConditionsListener.h
new file mode 100644
index 000000000..13fc81772
--- /dev/null
+++ b/DDCond/include/DDCond/ConditionsListener.h
@@ -0,0 +1,62 @@
+// $Id$
+//==========================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+#ifndef DD4HEP_CONDITIONS_CONDITIONSLISTENER_H
+#define DD4HEP_CONDITIONS_CONDITIONSLISTENER_H
+
+// Framework include files
+#include "DD4hep/Conditions.h"
+
+// C/C++ include files
+
+/// Namespace for the AIDA detector description toolkit
+namespace DD4hep {
+
+  /// Namespace for the geometry part of the AIDA detector description toolkit
+  namespace Conditions {
+
+    /// Forward declarations
+    class IOV;
+    class IOVType;
+    class ConditionsPool;
+
+    /// Base class to be implemented by objects to listen on condition callbacks
+    /**
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_CONDITIONS
+     */
+    class ConditionsListener  {
+    public:
+      /// Default constructor
+      ConditionsListener();
+      /// Default destructor
+      virtual ~ConditionsListener();
+      /// ConditionsListener dummy implementation: onRegister new IOV type
+      virtual void onRegisterIOVType(const IOVType* /* type */, void* /* param */)  { }
+      /// ConditionsListener dummy implementation: onRegister new condition
+      virtual void onRegisterCondition(Condition /* cond */, void* /* param */)  { }
+      /// ConditionsListener dummy implementation: onRegister new conditions pool
+      virtual void onRegisterPool(ConditionsPool* /* pool */, void* /* param */)  { }
+
+      /// ConditionsListener dummy implementation: onRemove a condition
+      virtual void onRemoveCondition(Condition /* cond */, void* /* param */)  { }
+      /// ConditionsListener dummy implementation: onRemove a conditions pool
+      virtual void onRemovePool(ConditionsPool* /* pool */, void* /* param */)  { }
+     };
+
+  } /* End namespace Geometry               */
+} /* End namespace DD4hep                   */
+
+#endif /* DD4HEP_CONDITIONS_CONDITIONSLISTENER_H  */
diff --git a/DDCond/include/DDCond/ConditionsManager.h b/DDCond/include/DDCond/ConditionsManager.h
index 99ecf36bb..db58d9e47 100644
--- a/DDCond/include/DDCond/ConditionsManager.h
+++ b/DDCond/include/DDCond/ConditionsManager.h
@@ -15,6 +15,7 @@
 #define DDCOND_CONDITIONSMANAGER_H
 
 // Framework include files
+#include "DD4hep/Memory.h"
 #include "DD4hep/Conditions.h"
 #include "DD4hep/ComponentProperties.h"
 
@@ -26,6 +27,8 @@ namespace DD4hep {
 
     // Forward declarations
     class Entry;
+    class ConditionsPool;
+    class ConditionsIOVPool;
     class ConditionsDataLoader;
 
     /// Conditions internal namespace
@@ -45,9 +48,9 @@ namespace DD4hep {
       /// Standard object type
       typedef Interna::ConditionsManagerObject Object;
       typedef ConditionsDataLoader             Loader;
-      typedef std::vector<IOVType*>            IOVTypes;
-      typedef std::map<DetElement,Container>   DetectorConditions;
+      typedef std::vector<IOVType>             IOVTypes;
       typedef std::map<IOVType*,Container>     TypeConditions;
+      typedef std::map<DetElement,Container>   DetectorConditions;
 
     public:
 
@@ -95,11 +98,29 @@ namespace DD4hep {
       /// Access the availible/known IOV types
       const IOVTypes& iovTypes()  const;
 
+      /// Access the used/registered IOV types
+      const std::vector<const IOVType*> iovTypesUsed() const;
+
+      /// Access conditions pool by iov type
+      ConditionsIOVPool* iovPool(const IOVType& type)  const;
+
+      /// Create IOV from string
+      void fromString(const std::string& iov_str, IOV& iov);
+
       /// Register new IOV type if it does not (yet) exist.
       /** Returns (false,pointer) if IOV existed and
        *  (true,pointer) if new IOV was registered to the manager.
        */
       std::pair<bool, const IOVType*> registerIOVType(size_t iov_type, const std::string& iov_name);
+
+      /// Register IOV with type and key
+      ConditionsPool* registerIOV(const IOVType& typ, IOV::Key key);
+
+      /// Register new condition with the conditions store. Unlocked version, not multi-threaded
+      bool registerUnlocked(const IOVType* type, IOV::Key key, Condition cond);
+
+      /// Register new condition with the conditions store. Unlocked version, not multi-threaded
+      bool registerUnlocked(ConditionsPool* pool, Condition cond);
       
       /// Access IOV by its type
       const IOVType* iovType (size_t iov_type) const;
@@ -113,11 +134,8 @@ namespace DD4hep {
       /// Unlock the internal data structures. This enables calls to "register", etc.
       void unlock();
 
-      /// Age conditions, which are no longer used and to be removed eventually
-      void age();
-
       /// Clean conditions, which are above the age limit.
-      void clean();
+      void clean(const IOVType* typ, int max_age);
 
       /// Full cleanup of all managed conditions.
       void clear();
@@ -129,10 +147,10 @@ namespace DD4hep {
       void pushUpdates();
 
       /// Prepare all updates to the clients with the defined IOV
-      void prepare(const IOV& required_validity);
+      long prepare(const IOV& required_validity, dd4hep_ptr<ConditionsPool>& user_pool);
       
       /// Enable all updates to the clients with the defined IOV
-      void enable(const IOV& required_validity);
+      long enable(const IOV& required_validity, dd4hep_ptr<ConditionsPool>& user_pool);
       
       /// Retrieve a condition given a Detector Element and the conditions name
       Condition get(DetElement detector,
diff --git a/DDCond/include/DDCond/ConditionsPool.h b/DDCond/include/DDCond/ConditionsPool.h
index ab2e3ac3d..9d824916e 100644
--- a/DDCond/include/DDCond/ConditionsPool.h
+++ b/DDCond/include/DDCond/ConditionsPool.h
@@ -16,9 +16,9 @@
 
 // Framework include files
 #include "DD4hep/Mutex.h"
+#include "DD4hep/Detector.h"
 #include "DD4hep/Conditions.h"
-#include "DD4hep/NamedObject.h"
-#include "DD4hep/objects/ConditionsInterna.h"
+#include "DDCond/ConditionsManager.h"
 
 /// Namespace for the AIDA detector description toolkit
 namespace DD4hep {
@@ -46,18 +46,27 @@ namespace DD4hep {
      *  \ingroup DD4HEP_CONDITIONS
      */
     class ConditionsPool : public NamedObject {
-      
+    protected:
+      /// Handle to conditions manager object
+      ConditionsManager m_manager;
+
     public:
-      enum { AGE_NONE = 0, 
-             AGE_ANY  = 9999999,
+      enum { AGE_NONE    = 0, 
+             AGE_ANY     = 9999999,
              AGE_EXPIRED = 12345678
       };
-
+      enum { NO_POOL_TYPE     = 0,
+	     UPDATE_POOL_TYPE = 1,
+	     USER_POOL_TYPE   = 2
+      };
+      /// IOV type of the conditions hosted by this pool
       const IOVType*   iovType;
+      /// The IOV of the conditions hosted
       IOV*             iov;
-      /// Temporary buffer
-      ReplacementPool* updates;
+      /// Aging value
       int              age_value;
+      /// Pool type (regular, user, ipdate,...)
+      int              pool_type;
 
     protected:
 
@@ -69,16 +78,17 @@ namespace DD4hep {
        */
       virtual Condition create(ConditionsPool* pool, const Entry* cond);
 
-      /// Check if detector and name match
-      bool match(const DetElement::Object* det, int hash, const Condition::Object* c)  const {
-        return det == c->detector.ptr() && hash == c->hash;
-      }
-
     public:
       /// Default constructor
-      ConditionsPool();
+      ConditionsPool(ConditionsManager mgr);
       /// Default destructor. Note: pool must be cleared by the subclass!
       virtual ~ConditionsPool();
+      /// Print pool basics
+      void print(const std::string& opt)   const;
+      /// Listener invocation when a condition is registered to the cache
+      void onRegister(Condition condition);
+      /// Listener invocation when a condition is deregistered from the cache
+      void onRemove(Condition condition);
       /// Register a new condition to this pool
       virtual void insert(Condition cond) = 0;
       /// Register a new condition to this pool. May overload for performance reasons.
@@ -93,8 +103,12 @@ namespace DD4hep {
       virtual void select(DetElement det, const std::string& cond_name, RangeConditions& result) = 0;
       /// Select all conditions contained
       virtual void select_all(RangeConditions& result) = 0;
+      /// Select all conditions contained
+      virtual void select_all(ConditionsPool& selection_pool) = 0;
       /// Select the conditons, used also by the DetElement of the condition
       virtual void select_used(RangeConditions& result) = 0;
+      /// Total entry count
+      virtual int count()  const = 0;
     };
 
     /// Interface for conditions pool optimized to host conditions updates.
@@ -111,9 +125,11 @@ namespace DD4hep {
 
     public:
       /// Default constructor
-      UpdatePool();
+      UpdatePool(ConditionsManager mgr);
       /// Default destructor.
       virtual ~UpdatePool();
+      /// Pool type identifier
+      static int poolType()  {  return UPDATE_POOL_TYPE; }
       /// Adopt all entries sorted by IOV. Entries will be removed from the pool
       virtual void popEntries(UpdateEntries& entries) = 0;
       /// Register a new condition to this pool
@@ -130,14 +146,18 @@ namespace DD4hep {
      *  \author  M.Frank
      *  \version 1.0
      */
-    class ReplacementPool : public ConditionsPool  {
+    class UserPool : public ConditionsPool  {
     public:
       /// Default constructor
-      ReplacementPool();
+      UserPool(ConditionsManager mgr);
       /// Default destructor.
-      virtual ~ReplacementPool();
-      /// Pop conditions. May overloade for performance reasons!
-      virtual void popEntries(RangeConditions& entries) = 0;
+      virtual ~UserPool();
+      /// Pool type identifier
+      static int poolType()  {  return USER_POOL_TYPE; }
+      /// Access the interval of validity for this user pool
+      virtual const IOV& validity() const = 0;
+      /// Update interval of validity for this user pool (should only be called by ConditionsManager)
+      virtual void setValidity(const IOV& value) = 0;
     };
 
   } /* End namespace Conditions             */
diff --git a/DDCond/include/DDCond/ConditionsTest.h b/DDCond/include/DDCond/ConditionsTest.h
new file mode 100644
index 000000000..b6d519ae2
--- /dev/null
+++ b/DDCond/include/DDCond/ConditionsTest.h
@@ -0,0 +1,73 @@
+// $Id$
+//==========================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+#ifndef DDCOND_CONDITIONSTEST_H
+#define DDCOND_CONDITIONSTEST_H
+
+// Framework include files
+#include "DD4hep/LCDD.h"
+#include "DD4hep/Printout.h"
+#include "DD4hep/Conditions.h"
+#include "DD4hep/DetFactoryHelper.h"
+#include "DD4hep/objects/ConditionsInterna.h"
+
+#include "DDCond/ConditionsManager.h"
+#include "DDCond/ConditionsIOVPool.h"
+#include "DDCond/ConditionsInterna.h"
+
+/// Namespace for the AIDA detector description toolkit
+namespace DD4hep {
+
+  /// Namespace for the geometry part of the AIDA detector description toolkit
+  namespace Conditions {
+
+    /// Namespace for test environments in DDCond
+    namespace Test  {
+
+      using Geometry::LCDD;
+      using Geometry::Position;
+      using Geometry::DetElement;
+
+      struct TestEnv {
+        LCDD& lcdd;
+        DetElement detector;
+        ConditionsManager manager;
+        Handle<ConditionsDataLoader> loader;
+        const IOVType* epoch;
+        const IOVType* run;
+
+        TestEnv(LCDD& _lcdd, const std::string& detector_name);
+        /// Find daughter element of the detector object
+        DetElement daughter(const std::string& sub_path)  const;
+
+        void add_xml_data_source(const std::string& file, const std::string& iov);
+        void dump_conditions_pools();
+        static void dump_detector_element(DetElement elt);
+        static void dump_conditions_tree(DetElement elt);
+      };
+
+      template <typename T> void print_condition(Condition condition);
+      template <typename T> void print_bound_value(Condition condition, const char* norm=0);
+      template <typename T> void print_conditions(const RangeConditions& rc);
+      void check_discrete_condition(Condition c, const IOV& iov);
+
+      template<typename T> const T& access_val(Condition c)   {
+        if ( !c->is_bound() )   {
+          c.bind<T>();
+        }
+        return c.get<T>();
+      }
+    }
+  }
+}
+#endif // DDCOND_CONDITIONSTEST_H
diff --git a/DDCond/src/ConditionsDataLoader.cpp b/DDCond/src/ConditionsDataLoader.cpp
index ca0ba6679..e9c9b1562 100644
--- a/DDCond/src/ConditionsDataLoader.cpp
+++ b/DDCond/src/ConditionsDataLoader.cpp
@@ -35,8 +35,8 @@ ConditionsDataLoader::~ConditionsDataLoader()   {
 }
 
 /// Add data source definition to loader
-void ConditionsDataLoader::addSource(const string& source)   {
-  m_sources.push_back(source);
+void ConditionsDataLoader::addSource(const string& source, const IOV& iov)   {
+  m_sources.push_back(make_pair(source,iov));
 }
 
 /// Queue update to manager.
diff --git a/DDCond/src/ConditionsIOVPool.cpp b/DDCond/src/ConditionsIOVPool.cpp
index b732e3924..5c057c314 100644
--- a/DDCond/src/ConditionsIOVPool.cpp
+++ b/DDCond/src/ConditionsIOVPool.cpp
@@ -16,6 +16,7 @@
 #include "DD4hep/Printout.h"
 #include "DD4hep/InstanceCount.h"
 #include "DDCond/ConditionsIOVPool.h"
+#include "DD4hep/objects/ConditionsInterna.h"
 #include "DDCond/ConditionsDataLoader.h"
 
 using namespace DD4hep;
@@ -31,13 +32,21 @@ ConditionsIOVPool::~ConditionsIOVPool()  {
   InstanceCount::decrement(this);
 }
 
+bool ConditionsIOVPool::addKey(Condition c)   {
+  // TODO: Should be: det.path()+'#'+c->name; instead of c->comment
+  int hash = c->hash;
+  c->flags |= Interna::ConditionObject::ACTIVE;
+  keys.insert(hash);
+  return true;
+}
+
 void ConditionsIOVPool::__find(DetElement detector,
                                const std::string& condition_name,
                                const IOV& req_validity,
                                RangeConditions& result)
 {
   if ( !entries.empty() )  {
-    const IOV::Key req_key = req_validity.key(); // 8 bytes => better copy!
+    const IOV::Key req_key = req_validity.key(); // 16 bytes => better copy!
     for(Entries::const_iterator i=entries.begin(); i!=entries.end(); ++i)  {
       if ( IOV::key_contains_range((*i).first, req_key) )  {
         (*i).second->select(detector, condition_name, result);
@@ -66,46 +75,45 @@ void ConditionsIOVPool::__find_range(DetElement detector,
   }
 }
 
+/// Remove all key based pools with an age beyon the minimum age
+int ConditionsIOVPool::clean(int max_age)   {
+  Entries rest;
+  int count = 0;
+  for(Entries::const_iterator i=entries.begin(); i!=entries.end(); ++i)  {
+    ConditionsPool* pool = (*i).second;
+    if ( pool->age_value >= max_age )   {
+      count += pool->count();
+      pool->print("Remove");
+      delete pool;
+    }
+    else
+      rest.insert(make_pair(pool->iov->keyData,pool));
+  }
+  entries = rest;
+  return count;
+}
+
 /// Select all ACTIVE conditions, which do no longer match the IOV requirement
-void ConditionsIOVPool::__select_expired(const IOV& required_validity, RangeConditions& result)  {
+void ConditionsIOVPool::select(const IOV& required_validity, 
+			       RangeConditions& valid,
+			       RangeConditions& expired,
+			       IOV& conditions_validity)
+{
   if ( !entries.empty() )  {
-    const IOV::Key req_key = required_validity.key(); // 8 bytes => better copy!
+    const IOV::Key req_key = required_validity.key(); // 16 bytes => better copy!
     for(Entries::const_iterator i=entries.begin(); i!=entries.end(); ++i)  {
       ConditionsPool* pool = (*i).second;
       if ( !IOV::key_contains_range((*i).first, req_key) )  {
         if ( pool->age_value == ConditionsPool::AGE_NONE ) {
           // Now check the content:
-          pool->select_used(result);
+          pool->select_used(expired);
         }
         ++pool->age_value;
         continue;
       }
+      conditions_validity.iov_intersection((*i).first);
+      pool->select_used(valid);
       pool->age_value = 0;
     }
   }
 }
-
-/// Select all ACTIVE conditions, which do no longer match the IOV requirement
-void ConditionsIOVPool::__update_expired(ConditionsDataLoader& loader,
-                                         ConditionsPool& new_pool,
-                                         RangeConditions& updates,
-                                         const IOV& required_validity)  {
-
-  RangeConditions upda;
-  for(RangeConditions::const_iterator i=updates.begin(); i!=updates.end(); ++i)  {
-    Condition::Object* condition = (*i).ptr();
-    Condition c = new_pool.exists(condition);
-    if ( c.isValid() )  {
-      upda.push_back(c);
-      continue;
-    }
-    size_t items = loader.load(condition->detector,condition->name,required_validity,upda);
-    if ( items < 1 )  {
-      // Error: no such condition
-      except("ConditionsManager","+++ update_expired: Cannot update condition %s.%s [%s] to iov:%s.",
-             condition->detector.path().c_str(), condition->name.c_str(),
-             condition->iov->str().c_str(), required_validity.str().c_str());
-    }
-  }
-  updates = upda;
-}
diff --git a/DDCond/src/ConditionsInterna.cpp b/DDCond/src/ConditionsInterna.cpp
index 140893c53..cb516d200 100644
--- a/DDCond/src/ConditionsInterna.cpp
+++ b/DDCond/src/ConditionsInterna.cpp
@@ -31,6 +31,7 @@
 #include "DDCond/ConditionsManager.h"
 #include "DDCond/ConditionsDataLoader.h"
 #include "DDCond/ConditionsInterna.h"
+#include "DDCond/ConditionsListener.h"
 
 using namespace std;
 using namespace DD4hep;
@@ -118,7 +119,7 @@ namespace {
           const IOV::Key& k = (*i)->iov->key();
           if ( k.first   <= test.first+1 && k.second >= test.first  ) test.first = k.second;
           if ( k.first+1 <= test.second  && k.second >= test.second ) test.second = k.first;
-          //printout(INFO,"Test","IOV: %d,%d --> %d,%d",k.first,k.second, test.first, test.second);
+          //printout(INFO,"Test","IOV: %ld,%ld --> %ld,%ld",k.first,k.second, test.first, test.second);
           if ( test.first >= test.second ) return true;
         }
         if ( test.first <= iov.keyData.first && test.second >= iov.keyData.second ) return false;
@@ -135,6 +136,14 @@ namespace {
     }
   }
 
+  template <typename PMF>
+  void __callListeners(const ConditionsManagerObject::Listeners& listeners, PMF pmf, Condition& cond)  {
+    for(ConditionsManagerObject::Listeners::const_iterator i=listeners.begin(); i!=listeners.end(); ++i)  {
+      const ConditionsManagerObject::Listener& listener = *i;
+      (listener.first->*pmf)(cond, listener.second);
+    }
+  }
+
   /// Helper class to be injected into the world object to allow loading from DetElements directly.....
   struct lcdd_cond_loader : public ConditionsLoader  {
     ConditionsManager m_manager;
@@ -145,21 +154,8 @@ namespace {
       return m_manager->get(element, key, iov);
     }
   };
-
-  int install_cond_mgr (Geometry::LCDD& lcdd, int /* argc */, char** /* argv */)  {
-    typedef Interna::ConditionsManagerObject ConditionsManagerObject;
-    Handle<ConditionsManagerObject> mgr(lcdd.extension<ConditionsManagerObject>(false));
-    if ( !mgr.isValid() )  {
-      ConditionsManager mgr_handle(lcdd);
-      lcdd.addExtension<ConditionsManagerObject>(mgr_handle.ptr());
-      printout(INFO,"ConditionsManager","+++ Successfully installed conditions manager instance.");
-    }
-    return 1;
-  }
 }
 
-DECLARE_APPLY(DD4hepConditionsManagerInstaller,install_cond_mgr)
-
 /// Standard constructor
 ConditionsManagerObject::ConditionsManagerObject(LCDD& lcdd)
   : NamedObject(), m_lcdd(lcdd), m_iovTypes(), m_pool(), 
@@ -171,8 +167,8 @@ ConditionsManagerObject::ConditionsManagerObject(LCDD& lcdd)
   declareProperty("MaxIOVTypes",         m_maxIOVTypes=32);
   declareProperty("PoolType",            m_poolType   = "");
   declareProperty("UpdatePoolType",      m_updateType = "DD4hep_ConditionsLinearUpdatePool");
-  declareProperty("ReplacementPoolType", m_replType   = "DD4hep_ConditionsLinearReplacementPool");
-  declareProperty("LoaderType",     m_loaderType = "multi");
+  declareProperty("UserPoolType",        m_userType   = "DD4hep_ConditionsLinearUserPool");
+  declareProperty("LoaderType",          m_loaderType = "multi");
   m_iovTypes.resize(m_maxIOVTypes,IOVType());
   m_pool.resize(m_maxIOVTypes,0);
 }
@@ -186,10 +182,10 @@ ConditionsManagerObject::~ConditionsManagerObject()   {
 void ConditionsManagerObject::initialize()  {
   if ( !m_updatePool.get() )  {
     string typ = "DD4hep_Conditions_"+m_loaderType+"_Loader";
-    char* argv[] = {(char*)"ConditionsDataLoader", (char*)this, 0};
-    m_loader.adopt(createPlugin<ConditionsDataLoader>(typ,m_lcdd,2,argv));
-
-    m_updatePool.adopt(createPlugin<UpdatePool>(m_updateType,m_lcdd));
+    const void* argv_loader[] = {"ConditionsDataLoader", this, 0};
+    const void* argv_pool[] = {this, 0};
+    m_loader.adopt(createPlugin<ConditionsDataLoader>(typ,m_lcdd,2,argv_loader));
+    m_updatePool.adopt(createPlugin<UpdatePool>(m_updateType,m_lcdd,1,argv_pool));
     if ( !m_updatePool.get() )  {
       except("ConditionsManager","+++ The update pool of type %s cannot be created. [%s]",
              m_updateType.c_str(),Errors::noSys().c_str());
@@ -202,6 +198,35 @@ void ConditionsManagerObject::initialize()  {
   }
 }
 
+void ConditionsManagerObject::registerCallee(Listeners& listeners, const Listener& callee, bool add)  {
+  if ( add )  {
+    listeners.insert(callee);
+    return;
+  }
+  Listeners::iterator i=listeners.find(callee);
+  if ( i != listeners.end() ) listeners.erase(i);  
+}
+
+/// (Un)Registration of conditions listeners with callback when a new condition is registered
+void ConditionsManagerObject::callOnRegister(const Listener& callee, bool add)  {
+  registerCallee(m_onRegister, callee, add);
+}
+
+/// (Un)Registration of conditions listeners with callback when a condition is de-registered
+void ConditionsManagerObject::callOnRemove(const Listener& callee, bool add)  {
+  registerCallee(m_onRemove, callee, add);
+}
+
+/// Call this when a condition is registered to the cache
+void ConditionsManagerObject::onRegister(Condition condition)    {
+  __callListeners(m_onRegister, &ConditionsListener::onRegisterCondition, condition);
+}
+
+/// Call this when a condition is deregistered from the cache
+void ConditionsManagerObject::onRemove(Condition condition)   {
+  __callListeners(m_onRemove, &ConditionsListener::onRemoveCondition, condition);
+}
+
 /// Register new IOV type if it does not (yet) exist.
 pair<bool, const IOVType*> ConditionsManagerObject::registerIOVType(size_t iov_type, const string& iov_name)   {
   if ( iov_type<m_iovTypes.size() )  {
@@ -243,8 +268,8 @@ const IOVType* ConditionsManagerObject::iovType (const string& iov_name) const
   return 0;
 }
 
-/// Register IOV using new string data
-ConditionsPool* ConditionsManagerObject::registerIOV(const string& data)   {
+/// Create IOV from string
+void ConditionsManagerObject::fromString(const std::string& data, IOV& iov)   {
   size_t id1 = data.find(',');
   size_t id2 = data.find('#');
   if ( id2 == string::npos )  {
@@ -254,9 +279,9 @@ ConditionsPool* ConditionsManagerObject::registerIOV(const string& data)   {
   IOV::Key key;
   int nents = 0;
   if ( id1 != string::npos )
-    nents = ::sscanf(data.c_str(),"%d,%d#",&key.first,&key.second) == 2 ? 2 : 0;
+    nents = ::sscanf(data.c_str(),"%ld,%ld#",&key.first,&key.second) == 2 ? 2 : 0;
   else  {
-    nents = ::sscanf(data.c_str(),"%d#",&key.first) == 1 ? 1 : 0;
+    nents = ::sscanf(data.c_str(),"%ld#",&key.first) == 1 ? 1 : 0;
     key.second = key.first;
   }
   if ( nents == 0 )   {
@@ -272,13 +297,23 @@ ConditionsPool* ConditionsManagerObject::registerIOV(const string& data)   {
     except("ConditionsManager","+++ Unknown IOV type requested from data: %s. [%s]",
            data.c_str(),Errors::invalidArg().c_str());
   }
+  iov.type    = typ->type;
+  iov.iovType = typ;
+  iov.set(key);
+}
+
+/// Register IOV using new string data
+ConditionsPool* ConditionsManagerObject::registerIOV(const string& data)   {
+  IOV iov(0);
+  // Convert string to IOV
+  fromString(data, iov);
   // IOV read and checked. Now register it.
-  return registerIOV(*typ, key);
+  // The validity of iov->iovType is already ensured in 'fromString'
+  return registerIOV(*iov.iovType, iov.keyData);
 }
 
 /// Register IOV with type and key
 ConditionsPool* ConditionsManagerObject::registerIOV(const IOVType& typ, IOV::Key key)   {
-
   // IOV read and checked. Now register it, but always locked!
   ConditionsIOVPool* pool = m_pool[typ.type];
   dd4hep_lock_t lock(m_poolLock);
@@ -289,7 +324,8 @@ ConditionsPool* ConditionsManagerObject::registerIOV(const IOVType& typ, IOV::Ke
   if ( i != pool->entries.end() )   {
     return (*i).second;
   }
-  ConditionsPool* cond_pool = createPlugin<ConditionsPool>(m_poolType,m_lcdd);
+  const void* argv_pool[] = {this, 0};
+  ConditionsPool* cond_pool = createPlugin<ConditionsPool>(m_poolType,m_lcdd,1,argv_pool);
   IOV* iov = new IOV(&typ);
   iov->type      = typ.type;
   iov->keyData   = key;
@@ -298,6 +334,26 @@ ConditionsPool* ConditionsManagerObject::registerIOV(const IOVType& typ, IOV::Ke
   return cond_pool;
 }
 
+/// Register new condition with the conditions store. Unlocked version, not multi-threaded
+bool ConditionsManagerObject::registerUnlocked(ConditionsPool* pool, Condition cond)   {
+  if ( pool && cond.isValid() )  {
+    ConditionsIOVPool* iov_pool = m_pool[pool->iov->type];
+    iov_pool->addKey(cond);
+    cond->pool = pool;
+    cond->iov  = pool->iov;
+    pool->insert(cond);
+    __callListeners(m_onRegister, &ConditionsListener::onRegisterCondition, cond);
+    return true;
+  }
+  else if ( !pool )
+    except("ConditionsManager","+++ Unknown Conditions pool to register entry. [%s]",
+           Errors::invalidArg().c_str());
+  else if ( !cond.isValid() )
+    except("ConditionsManager","+++ Invalid condition objects may not be registered. [%s]",
+           Errors::invalidArg().c_str());
+  return false;
+}
+
 /// Set a single conditions value to be managed. 
 /// Requires external lock on update pool!
 Condition ConditionsManagerObject::__queue_update(Entry* e)   {
@@ -314,19 +370,28 @@ Condition ConditionsManagerObject::__queue_update(Entry* e)   {
   return Condition();
 }
 
-/// Age conditions, which are no longer used and to be removed eventually
-void ConditionsManagerObject::age()   {
-  //call_member_func(m_pool, &ConditionsPool::age);
-}
-
 /// Clean conditions, which are above the age limit.
-void ConditionsManagerObject::clean()   {
-  //call_member_func(m_pool, &ConditionsPool::clean);
+int ConditionsManagerObject::clean(const IOVType* typ, int max_age)   {
+  int count = 0;
+  dd4hep_lock_t lock(m_updateLock);
+  ConditionsIOVPool* pool = m_pool[typ->type];
+  if ( pool )  {
+    count += pool->clean(max_age);
+  }
+  return count;
 }
 
 /// Full cleanup of all managed conditions.
-void ConditionsManagerObject::clear()   {
-  //call_member_func(m_pool, &ConditionsPool::clear);
+pair<int,int> ConditionsManagerObject::clear()   {
+  pair<int,int> count(0,0);
+  for( TypedConditionPool::iterator i=m_pool.begin(); i != m_pool.end(); ++i)  {
+    ConditionsIOVPool* p = *i;
+    if ( p )  {
+      ++count.first;
+      count.second += p->clean(0);
+    }
+  }
+  return count;
 }
 
 /// Push all pending updates to the conditions store
@@ -353,36 +418,50 @@ void ConditionsManagerObject::pushUpdates()   {
 }
 
 /// Prepare all updates to the clients with the defined IOV
-void ConditionsManagerObject::prepare(const IOV& required_validity)   {
+long ConditionsManagerObject::prepare(const IOV& required_validity, dd4hep_ptr<ConditionsPool>& up)   {
   const IOVType* typ = check_iov_type<Discrete>(this, &required_validity);
   if ( typ )  {
-    ConditionsPool*  cp = 0;
+    RangeConditions valid, expired;
     ConditionsIOVPool* pool = m_pool[typ->type];
-    if ( pool )  {{
-        dd4hep_lock_t lock(m_poolLock);
-        cp = registerIOV(*typ, required_validity.key());
-        if ( !cp->updates ) 
-          cp->updates = createPlugin<ReplacementPool>(m_replType,m_lcdd);
-      }
-      /// First push any pending updates and register them to pending pools...
-      pushUpdates();
-      RangeConditions updates;
-      pool->__select_expired(required_validity, updates);
-      pool->__update_expired(*m_loader, *cp, updates, required_validity);
-      cp->updates->insert(updates);
+    if ( 0 == up.get() || up->pool_type != ConditionsPool::USER_POOL_TYPE )  {
+      const void* argv_pool[] = {this, 0};
+      ConditionsPool* cp = createPlugin<ConditionsPool>(m_userType,m_lcdd,1,argv_pool);
+      up.adopt(cp);
     }
-    return;
+    UserPool *user_pool = (UserPool*)up.get();
+    if ( user_pool->pool_type != UserPool::poolType() )   {
+      except("ConditionsManager","+++ Unknown User POOL type:%d",
+	     user_pool->pool_type, Errors::invalidArg().c_str());
+    }
+    /// First push any pending updates and register them to pending pools...
+    IOV pool_iov(typ);
+    pool_iov.reset();
+    pool_iov.invert();
+
+    pushUpdates();
+    pool->select(required_validity, valid, expired, pool_iov);
+    user_pool->clear();
+    user_pool->insert(valid);
+    long num_expired = (long)expired.size();
+    if ( num_expired > 0 )  {
+      m_loader->update(required_validity, expired, pool_iov);
+      user_pool->insert(expired);
+    }
+    user_pool->setValidity(pool_iov);
+    return num_expired;
   }
   except("ConditionsManager","+++ Unknown IOV type requested to enable conditions. [%s]",
          Errors::invalidArg().c_str());
+  return -1;
 }
 
 /// Enable all updates to the clients with the defined IOV
-void ConditionsManagerObject::enable(const IOV& required_validity)   {
+long ConditionsManagerObject::enable(const IOV& required_validity, dd4hep_ptr<ConditionsPool>& user_pool)   {
   if ( !locked )   {
     ConditionsIOVPool* pool = m_pool[required_validity.type];
     if ( pool )  {
-      ReplacementPool* rep_pool = 0;
+#if 0
+      UserPool* rep_pool = 0;
       pushUpdates();
       {
         dd4hep_lock_t lock(m_poolLock);
@@ -396,13 +475,15 @@ void ConditionsManagerObject::enable(const IOV& required_validity)   {
       RangeConditions entries;
       rep_pool->popEntries(entries);
       __push_immediate(entries);
-      return;
+#endif
+      return 0;
     }
     except("ConditionsManager","+++ Unknown IOV type requested to enable conditions. [%s]",
            Errors::invalidArg().c_str());
   }
   except("ConditionsManager","+++ Cannot enable new conditions for IOV:%s in locked state! [%s]",
          required_validity.str().c_str(), Errors::invalidArg().c_str());
+  return 0;
 }
 
 /// Register a new managed condition
@@ -425,9 +506,12 @@ void ConditionsManagerObject::registerCondition(Condition c)    {
         (*it).second->insert(c);
         return;
       }
-      ConditionsPool* cp = createPlugin<ConditionsPool>(m_poolType,m_lcdd);
+      const void* argv_pool[] = {this, 0};
+      ConditionsPool* cp = createPlugin<ConditionsPool>(m_poolType,m_lcdd,1,argv_pool);
       pool->entries.insert(make_pair(iov->keyData,cp));
+      pool->addKey(c);
       cp->insert(c);
+      onRegister(c);
     }
     return;
   }
@@ -439,8 +523,8 @@ bool ConditionsManagerObject::__find(DetElement det,
                                      const std::string& cond,
                                      const IOV& req_validity,
                                      RangeConditions& conditions)   {
-  ConditionsIOVPool* p = 0;
   {
+    ConditionsIOVPool* p = 0;
     dd4hep_lock_t locked_action(m_poolLock);
     p = m_pool[req_validity.type]; // Existence already checked by caller!
     p->__find(det, cond, req_validity, conditions);
@@ -458,8 +542,8 @@ bool ConditionsManagerObject::__find_range(DetElement det,
                                            const IOV& req_validity,
                                            RangeConditions& conditions)
 {
-  ConditionsIOVPool* p = 0;
   {
+    ConditionsIOVPool* p = 0;
     dd4hep_lock_t locked_action(m_poolLock);
     p = m_pool[req_validity.type]; // Existence alread checked by caller!
     p->__find_range(det, cond, req_validity, conditions);
diff --git a/DDCond/src/ConditionsListener.cpp b/DDCond/src/ConditionsListener.cpp
new file mode 100644
index 000000000..fe1b92e32
--- /dev/null
+++ b/DDCond/src/ConditionsListener.cpp
@@ -0,0 +1,26 @@
+// $Id$
+//==========================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+
+// Framework include files
+#include "DDCond/ConditionsListener.h"
+
+using namespace DD4hep::Conditions;
+
+/// Default constructor
+ConditionsListener::ConditionsListener()   {
+}
+
+/// Default destructor
+ConditionsListener::~ConditionsListener()   {
+}
diff --git a/DDCond/src/ConditionsManager.cpp b/DDCond/src/ConditionsManager.cpp
index 488797a58..2b8733843 100644
--- a/DDCond/src/ConditionsManager.cpp
+++ b/DDCond/src/ConditionsManager.cpp
@@ -20,6 +20,7 @@
 
 #include "DDCond/ConditionsInterna.h"
 #include "DDCond/ConditionsManager.h"
+#include "DDCond/ConditionsPool.h"
 
 using namespace std;
 using namespace DD4hep;
@@ -48,7 +49,6 @@ ConditionsManager::ConditionsManager(LCDD& lcdd)  {
  
 /// Default destructor
 ConditionsManager::~ConditionsManager()   {
-  access()->clear();
 }
 
 /// Access to the property manager
@@ -71,7 +71,22 @@ pair<bool, const IOVType*>
 ConditionsManager::registerIOVType(size_t iov_type, const string& iov_name)   {
   return access()->registerIOVType(iov_type, iov_name);
 }
-      
+
+/// Access the availible/known IOV types
+const ConditionsManager::IOVTypes& ConditionsManager::iovTypes()  const   {
+  return access()->iovTypes();
+}
+
+/// Access the used/registered IOV types
+const vector<const IOVType*> ConditionsManager::iovTypesUsed() const  {
+  Object* obj = access();
+  vector<const IOVType*> result;
+  const IOVTypes& types = obj->iovTypes();
+  for(IOVTypes::const_iterator i=types.begin(); i!=types.end(); ++i)
+    if ( int((*i).type) != IOVType::UNKNOWN_IOV ) result.push_back(&(*i));
+  return result;
+}
+  
 /// Access IOV by its type
 const IOVType* ConditionsManager::iovType (size_t iov_type) const  {
   return access()->iovType(iov_type);
@@ -82,14 +97,40 @@ const IOVType* ConditionsManager::iovType (const string& iov_name) const   {
   return access()->iovType(iov_name);
 }
 
-/// Age conditions, which are no longer used and to be removed eventually
-void ConditionsManager::age()   {
-  access()->age();
+/// Access conditions pool by iov type
+ConditionsIOVPool* ConditionsManager::iovPool(const IOVType& type)  const   {
+  Object* obj = access();
+  if ( int(type.type) != IOVType::UNKNOWN_IOV && type.type < obj->m_pool.size() )  {
+    ConditionsIOVPool* pool = obj->m_pool[type.type];
+    if ( pool )   {
+      return pool;
+    }
+  }
+  except("ConditionsManager","+++ Attempt to access invalid iov pool of type:%d. [%s]",
+	 type.type, Errors::linkRange().c_str());
+  return 0;
+}
+
+/// Create IOV from string
+void ConditionsManager::fromString(const string& iov_str, IOV& iov)  {
+  access()->fromString(iov_str, iov);
+}
+
+/// Register new condition with the conditions store. Unlocked version, not multi-threaded
+bool ConditionsManager::registerUnlocked(const IOVType* type, IOV::Key key, Condition cond)   {
+  Object* obj = access();
+  ConditionsPool* pool = obj->registerIOV(*type, key);
+  return obj->registerUnlocked(pool, cond);
+}
+
+/// Register new condition with the conditions store. Unlocked version, not multi-threaded
+bool ConditionsManager::registerUnlocked(ConditionsPool* pool, Condition cond)   {
+  return access()->registerUnlocked(pool, cond);
 }
 
 /// Clean conditions, which are above the age limit.
-void ConditionsManager::clean()   {
-  access()->clean();
+void ConditionsManager::clean(const IOVType* typ, int max_age)   {
+  access()->clean(typ, max_age);
 }
 
 /// Full cleanup of all managed conditions.
@@ -133,13 +174,13 @@ void ConditionsManager::unlock()   {
 }
 
 /// Enable all updates to the clients with the defined IOV
-void ConditionsManager::enable(const IOV& required_validity)   {
-  access()->enable(required_validity);
+long ConditionsManager::enable(const IOV& required_validity, dd4hep_ptr<ConditionsPool>& user_pool)   {
+  return access()->enable(required_validity, user_pool);
 }
  
 /// Prepare all updates to the clients with the defined new IOV. Changes are not yet applied
-void ConditionsManager::prepare(const IOV& required_validity)   {
-  access()->prepare(required_validity);
+long ConditionsManager::prepare(const IOV& required_validity, dd4hep_ptr<ConditionsPool>& user_pool)   {
+  return access()->prepare(required_validity, user_pool);
 }
  
 /// Retrieve a condition given the conditions path = <Detector Element path>.<conditions name>
diff --git a/DDCond/src/ConditionsPool.cpp b/DDCond/src/ConditionsPool.cpp
index ebed15f67..4e726197f 100644
--- a/DDCond/src/ConditionsPool.cpp
+++ b/DDCond/src/ConditionsPool.cpp
@@ -14,27 +14,30 @@
 
 // Framework include files
 #include "DD4hep/Handle.inl"
+#include "DD4hep/Printout.h"
 #include "DD4hep/InstanceCount.h"
 #include "DD4hep/objects/ConditionsInterna.h"
 
 #include "DDCond/ConditionsPool.h"
 #include "DDCond/ConditionsEntry.h"
+#include "DDCond/ConditionsInterna.h"
 
 using std::string;
+using namespace DD4hep;
 using namespace DD4hep::Conditions;
 
 DD4HEP_INSTANTIATE_HANDLE_NAMED(ConditionsPool);
 
 /// Default constructor
-ConditionsPool::ConditionsPool()
-  : NamedObject(), iovType(0), iov(0), updates(0), age_value(AGE_NONE)
+ConditionsPool::ConditionsPool(ConditionsManager mgr)
+  : NamedObject(), m_manager(mgr),
+    iovType(0), iov(0), age_value(AGE_NONE), pool_type(NO_POOL_TYPE)
 {
   InstanceCount::increment(this);
 }
 
 /// Default destructor
 ConditionsPool::~ConditionsPool()   {
-  DD4hep::deletePtr(updates);
   // Should, but cannot clear here, since clear is a virtual overload.
   InstanceCount::decrement(this);
 }
@@ -55,9 +58,39 @@ Condition ConditionsPool::create(ConditionsPool* pool, const Entry* entry)   {
   return c;
 }
 
+/// Print pool basics
+void ConditionsPool::print(const string& opt)   const  {
+  const IOVType* iov_type = iov->iovType;
+  if ( iov_type->name == "epoch" )  {
+    time_t since = iov->key().first;
+    time_t until = iov->key().second;
+    char c_since[64], c_until[64];
+    struct tm time_buff;
+    ::strftime(c_since,sizeof(c_since),"%d-%m-%Y %H:%M:%S",::gmtime_r(&since,&time_buff));
+    ::strftime(c_until,sizeof(c_until),"%d-%m-%Y %H:%M:%S",::gmtime_r(&until,&time_buff));
+    printout(INFO,"Conditions","+++ %s Conditions for pool with IOV: %s(%d) age:%3d [%4d entries] [%s -> %s] ",
+	     opt.c_str(), iov_type->name.c_str(), iov_type->type, age_value, count(), c_since, c_until);
+  }
+  else  {
+    printout(INFO,"Example","+++ %s Conditions for pool with IOV: %-32s age:%3d [%4d entries]",
+	     opt.c_str(), iov->str().c_str(), age_value, count());
+  }
+}
+
+/// Listener invocation when a condition is registered to the cache
+void ConditionsPool::onRegister(Condition condition)   {
+  m_manager.ptr()->onRegister(condition);
+}
+
+/// Listener invocation when a condition is deregistered from the cache
+void ConditionsPool::onRemove(Condition condition)   {
+  m_manager.ptr()->onRemove(condition);
+}
+
 /// Default constructor
-UpdatePool::UpdatePool() : ConditionsPool()
+UpdatePool::UpdatePool(ConditionsManager mgr) : ConditionsPool(mgr)
 {
+  pool_type = UPDATE_POOL_TYPE;
 }
 
 /// Default destructor
@@ -65,9 +98,10 @@ UpdatePool::~UpdatePool()   {
 }
 
 /// Default constructor
-ReplacementPool::ReplacementPool()  : ConditionsPool() {
+UserPool::UserPool(ConditionsManager mgr)  : ConditionsPool(mgr) {
+  pool_type = USER_POOL_TYPE;
 }
 
 /// Default destructor.
-ReplacementPool::~ReplacementPool()   {
+UserPool::~UserPool()   {
 }
diff --git a/DDCond/src/ConditionsTest.cpp b/DDCond/src/ConditionsTest.cpp
index d93a8c555..d017bb8f1 100644
--- a/DDCond/src/ConditionsTest.cpp
+++ b/DDCond/src/ConditionsTest.cpp
@@ -14,7 +14,8 @@
 
 // Framework include files
 #include "DD4hep/DetectorTools.h"
-#include "ConditionsTest.h"
+#include "DDCond/ConditionsTest.h"
+#include "DD4hep/objects/ConditionsInterna.h"
 
 // C/C++ include files
 #include <vector>
@@ -178,7 +179,7 @@ Test::TestEnv::TestEnv(LCDD& _lcdd, const string& detector_name)
   manager["LoaderType"]     = "multi";
   manager["PoolType"]       = "DD4hep_ConditionsLinearPool";
   manager["UpdatePoolType"] = "DD4hep_ConditionsLinearUpdatePool";
-  manager["ReplacementPoolType"] = "DD4hep_ConditionsLinearReplacementPool";
+  manager["UserPoolType"]   = "DD4hep_ConditionsLinearUserPool";
   manager->initialize();
   detector = lcdd.detector(detector_name);
   if ( detector.isValid() )  {
@@ -200,12 +201,13 @@ DetElement Test::TestEnv::daughter(const string& sub_path)  const  {
   return DD4hep::Geometry::DetectorTools::findDaughterElement(detector,sub_path);
 }
 
-void Test::TestEnv::add_xml_data_source(const string& file)   {
+void Test::TestEnv::add_xml_data_source(const string& file, const string& iov_str)   {
   string source = "xml:"+string(::getenv("DD4hepINSTALL"))+file;
-  this->loader->addSource(source);
+  IOV iov(0);
+  this->manager->fromString(iov_str, iov);
+  this->loader->addSource(source, iov);
 }
 
-
 void Test::TestEnv::dump_conditions_pools()
 {
   typedef RangeConditions _R;
diff --git a/DDCond/src/ConditionsExample.cpp b/DDCond/src/plugins/ConditionsExample.cpp
similarity index 88%
rename from DDCond/src/ConditionsExample.cpp
rename to DDCond/src/plugins/ConditionsExample.cpp
index 9b3cc3482..b78f049ae 100644
--- a/DDCond/src/ConditionsExample.cpp
+++ b/DDCond/src/plugins/ConditionsExample.cpp
@@ -13,7 +13,7 @@
 //==========================================================================
 
 // Framework include files
-#include "ConditionsTest.h"
+#include "DDCond/ConditionsTest.h"
 
 using namespace std;
 using namespace DD4hep;
@@ -64,16 +64,15 @@ namespace  {
   }
 
   void print_tpc_discrete_conditions(Test::TestEnv& env, int epoch_min, int epoch_max, int run_min, int run_max)   {
+    dd4hep_ptr<ConditionsPool> pool_run, pool_epoch;
     IOV iov_epoch(env.epoch), iov_run(env.run);
-    iov_epoch.keyData.first  = epoch_min;
-    iov_epoch.keyData.second = epoch_max;
-    iov_run.keyData.first    = run_min;
-    iov_run.keyData.second   = run_max;
-
-    env.manager.prepare(iov_run);
-    env.manager.enable(iov_run);
-    env.manager.prepare(iov_epoch);
-    env.manager.enable(iov_epoch);
+    iov_epoch.set(epoch_min, epoch_max);
+    iov_run.set(run_min, run_max);
+
+    env.manager.prepare(iov_run, pool_run);
+    env.manager.enable(iov_run, pool_run);
+    env.manager.prepare(iov_epoch, pool_epoch);
+    env.manager.enable(iov_epoch, pool_epoch);
     print_tpc_discrete_conditions(env, iov_epoch, iov_run);
   }
 
@@ -86,8 +85,7 @@ namespace  {
   void print_tpc_range_conditions(Test::TestEnv& env, int run_min, int run_max)   {
     RangeConditions cond;
     IOV iov_run(env.run);
-    iov_run.keyData.first    = run_min;
-    iov_run.keyData.second   = run_max;
+    iov_run.set(run_min, run_max);
     try {
       cond = env.manager.getRange(env.detector,"TPC_A_align",iov_run);
       Test::print_conditions<void>(cond);
@@ -108,17 +106,17 @@ namespace  {
     printout(INFO,"Example1","+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
     Test::TestEnv env(lcdd, "TPC");
 
-    env.add_xml_data_source("/examples/Conditions/xml/TPC.xml");
-    env.add_xml_data_source("/examples/Conditions/xml/TPC_run_563543.xml");
-    env.add_xml_data_source("/examples/Conditions/xml/TPC_run_234567.xml");
+    env.add_xml_data_source("/examples/Conditions/xml/TPC.xml","1396887257,1396887257#epoch");
+    env.add_xml_data_source("/examples/Conditions/xml/TPC_run_563543.xml","563543#run");
+    env.add_xml_data_source("/examples/Conditions/xml/TPC_run_234567.xml","234567#run");
     print_tpc_discrete_conditions(env);
     env.dump_conditions_pools();
 
     print_tpc_range_conditions(env,234567,563543);  // Should fail !
     print_tpc_range_conditions(env,123456,563543);  // Should fail !
 
-    env.add_xml_data_source("/examples/Conditions/xml/TPC_run_filler.xml");
-    env.add_xml_data_source("/examples/Conditions/xml/TPC_run_123456.xml");
+    env.add_xml_data_source("/examples/Conditions/xml/TPC_run_filler.xml","0,999999#run");
+    env.add_xml_data_source("/examples/Conditions/xml/TPC_run_123456.xml","123456#run");
     print_tpc_range_conditions(env,123456,900000);  // Now it should succeed
     return 1;
   }
@@ -141,37 +139,36 @@ namespace  {
     printout(INFO,"Example1","+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
     Test::TestEnv env(lcdd, "TPC");
     
-    env.add_xml_data_source("/examples/Conditions/xml/TPC.xml");
-    env.add_xml_data_source("/examples/Conditions/xml/TPC_run_563543.xml");
-    env.add_xml_data_source("/examples/Conditions/xml/TPC_run_234567.xml");
-    env.add_xml_data_source("/examples/Conditions/xml/TPC_run_filler.xml");
-    env.add_xml_data_source("/examples/Conditions/xml/TPC_run_123456.xml");
+    env.add_xml_data_source("/examples/Conditions/xml/TPC.xml","1396887257,1396887257#epoch");
+    env.add_xml_data_source("/examples/Conditions/xml/TPC_run_563543.xml","563543#run");
+    env.add_xml_data_source("/examples/Conditions/xml/TPC_run_234567.xml","234567#run");
+    env.add_xml_data_source("/examples/Conditions/xml/TPC_run_filler.xml","0,999999#run");
+    env.add_xml_data_source("/examples/Conditions/xml/TPC_run_123456.xml","123456#run");
 
     
     IOV iov_epoch(env.epoch), iov_run(env.run);
-    iov_epoch.keyData.first  = 1396887257;
-    iov_epoch.keyData.second = 1396887257;
-    iov_run.keyData.first    = 563543;
-    iov_run.keyData.second   = 563543;
-
-    env.manager.prepare(iov_run);
-    env.manager.enable(iov_run);
-    env.manager.prepare(iov_epoch);
-    env.manager.enable(iov_epoch);
+    dd4hep_ptr<ConditionsPool> pool_run, pool_epoch;
+    iov_epoch.set(1396887257);
+    iov_run.set(563543);
+
+    env.manager.prepare(iov_run, pool_run);
+    env.manager.enable(iov_run, pool_run);
+    env.manager.prepare(iov_epoch, pool_epoch);
+    env.manager.enable(iov_epoch, pool_epoch);
     print_tpc_epoch_conditions(env, iov_epoch);
     print_tpc_run_conditions(env, iov_run, true);
     printout(INFO,"Example1","===================================================================");
 
     printout(INFO,"Example1","===================================================================");
-    iov_run.keyData.first = iov_run.keyData.second = 123456;
-    env.manager.prepare(iov_run);
-    iov_run.keyData.first = iov_run.keyData.second = 563543;
+    iov_run.set(123456);
+    env.manager.prepare(iov_run, pool_run);
+    iov_run.set(563543);
     print_tpc_run_conditions(env, iov_run, false);
     printout(INFO,"Example1","===================================================================");
 
     printout(INFO,"Example1","===================================================================");
-    iov_run.keyData.first = iov_run.keyData.second = 123456;
-    env.manager.enable(iov_run);
+    iov_run.set(123456);
+    env.manager.enable(iov_run, pool_run);
     print_tpc_run_conditions(env, iov_run, true);
     return 1;
   }
diff --git a/DDCond/src/ConditionsLinearPool.cpp b/DDCond/src/plugins/ConditionsLinearPool.cpp
similarity index 66%
rename from DDCond/src/ConditionsLinearPool.cpp
rename to DDCond/src/plugins/ConditionsLinearPool.cpp
index f3650360c..97f5ef50f 100644
--- a/DDCond/src/ConditionsLinearPool.cpp
+++ b/DDCond/src/plugins/ConditionsLinearPool.cpp
@@ -15,7 +15,10 @@
 #define DDCOND_CONDITIONSLINEARPOOL_H
 
 // Framework include files
+#include "DD4hep/objects/DetectorInterna.h"
+#include "DD4hep/objects/ConditionsInterna.h"
 #include "DDCond/ConditionsPool.h"
+#include "DDCond/ConditionsInterna.h"
 
 // C/C++ include files
 #include <list>
@@ -31,44 +34,57 @@ namespace DD4hep {
      *
      *  \author  M.Frank
      *  \version 1.0
-     *  \ingroup DD4HEP_GEOMETRY
      *  \ingroup DD4HEP_CONDITIONS
      */
     template<typename MAPPING, typename BASE> 
     class ConditionsLinearPool : public BASE   {
     protected:
+      typedef BASE    Base;
       typedef MAPPING Mapping;
-      Mapping      m_conditions;
-
+      Mapping           m_conditions;
     public:
       /// Default constructor
-      ConditionsLinearPool();
+      ConditionsLinearPool(ConditionsManager mgr);
 
       /// Default destructor
       virtual ~ConditionsLinearPool();
 
+      /// Total entry count
+      virtual int count()  const   {
+	return (int)m_conditions.size();
+      }
+      /// Check if detector and name match
+      bool __match(const DetElement::Object* det, int hash, const Condition::Object* c)  const {
+        return det == c->detector.ptr() && hash == c->hash;
+      }
+
       /// Register a new condition to this pool
       virtual void insert(Condition condition)    {
-        m_conditions.insert(m_conditions.end(),condition.ptr());
+	Condition::Object* c = condition.access();
+        m_conditions.insert(m_conditions.end(),c);
       }
 
       /// Register a new condition to this pool. May overload for performance reasons.
       virtual void insert(RangeConditions& new_entries)   {
-        for(RangeConditions::iterator i=new_entries.begin(); i!=new_entries.end(); ++i)
-          m_conditions.insert(m_conditions.end(),(*i).ptr());
+        for(RangeConditions::iterator i=new_entries.begin(); i!=new_entries.end(); ++i)  {
+	  Condition::Object* c = (*i).access();
+          m_conditions.insert(m_conditions.end(),c);
+	}
       }
 
       /// Register a new condition to this pool
       virtual Condition insertEntry(ConditionsPool* pool, Entry* cond)   {
-        MAPPING& m = this->ConditionsLinearPool<MAPPING,BASE>::m_conditions;
         Condition c = this->create(pool, cond);
-        m.insert(m.end(),c.ptr());
+	this->insert(c);
         return c;
       }
 
       /// Full cleanup of all managed conditions.
       virtual void clear()   {
-        for_each(m_conditions.begin(), m_conditions.end(), DD4hep::deleteObject<Condition::Object>);
+	for(typename Mapping::iterator i=m_conditions.begin(); i != m_conditions.end(); ++i)
+	  this->ConditionsPool::onRemove(*i);
+	for(typename Mapping::iterator i=m_conditions.begin(); i != m_conditions.end(); ++i)
+	  DD4hep::deleteObject<Condition::Object>(*i);
         m_conditions.clear();
       }
 
@@ -78,7 +94,7 @@ namespace DD4hep {
           int hash = DD4hep::hash32(cond_name);
           DetElement::Object* ptr = det.ptr();
           for(typename Mapping::const_iterator i=m_conditions.begin(); i!=m_conditions.end(); ++i)
-            if ( this->ConditionsPool::match(ptr,hash,(*i)) ) return *i;
+            if ( __match(ptr,hash,(*i)) ) return *i;
         }
         return Condition();
       }
@@ -88,7 +104,7 @@ namespace DD4hep {
         int hash = DD4hep::hash32(test->name);
         DetElement::Object* ptr = test->detector.ptr();
         for(typename Mapping::const_iterator i=m_conditions.begin(); i!=m_conditions.end(); ++i)  {
-          if ( this->ConditionsPool::match(ptr,hash,(*i)) ) return *i;
+          if ( __match(ptr,hash,(*i)) ) return *i;
         }
         return Condition();
       }
@@ -99,7 +115,7 @@ namespace DD4hep {
           int hash = DD4hep::hash32(cond_name);
           DetElement::Object* ptr = det.ptr();
           for(typename Mapping::const_iterator i=m_conditions.begin(); i!=m_conditions.end(); ++i)
-            if ( this->ConditionsPool::match(ptr,hash,(*i)) ) result.push_back(*i); 
+            if ( __match(ptr,hash,(*i)) ) result.push_back(*i); 
         }
       }
 
@@ -127,6 +143,13 @@ namespace DD4hep {
           result.push_back(*i); 
       }
 
+      /// Select the conditons, used also by the DetElement of the condition
+      virtual void select_all(ConditionsPool& selection_pool) {
+        for(typename Mapping::const_iterator i=m_conditions.begin(); i!=m_conditions.end(); ++i)  {
+	  selection_pool.insert(*i);
+	}
+      }
+
       /// Select the conditions matching the DetElement and the conditions name
       virtual void select_range(DetElement det,
                                 const std::string& cond_name,
@@ -139,7 +162,7 @@ namespace DD4hep {
           int hash = DD4hep::hash32(cond_name);
           DetElement::Object* ptr = det.ptr();
           for(typename Mapping::const_iterator i=m_conditions.begin(); i!=m_conditions.end(); ++i)  {
-            if ( this->ConditionsPool::match(ptr,hash,(*i)) )   {
+            if ( __match(ptr,hash,(*i)) )   {
               const IOV* _iov = (*i)->iov;
               unsigned int typ = _iov->iovType ? _iov->iovType->type : _iov->type;
               if ( req_typ == typ )   {
@@ -157,42 +180,65 @@ namespace DD4hep {
           }
         }
       }
-
     };
 
-
-    template<typename MAPPING> class ConditionsLinearReplacementPool 
-      : public ConditionsLinearPool<MAPPING,ReplacementPool>
+    /// Class implementing the conditions user pool for a given IOV type
+    /**
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_CONDITIONS
+     */
+    template<typename MAPPING> class ConditionsLinearUserPool 
+      : public ConditionsLinearPool<MAPPING,UserPool>
     {
+      IOV m_iov;
     public:
       /// Default constructor
-      ConditionsLinearReplacementPool() : ConditionsLinearPool<MAPPING,ReplacementPool>() {}
+      ConditionsLinearUserPool(ConditionsManager mgr) 
+	: ConditionsLinearPool<MAPPING,UserPool>(mgr), m_iov(0)
+      {
+	this->ConditionsPool::iov = &m_iov;
+	this->ConditionsPool::iovType = 0;
+      }
 
       /// Default destructor
-      virtual ~ConditionsLinearReplacementPool()  {}
-      /// Full cleanup of all managed conditions.
-      virtual void clear()   {
-        this->ConditionsLinearPool<MAPPING,ReplacementPool>::m_conditions.clear();
+      virtual ~ConditionsLinearUserPool()  {}
+
+      /// Access the interval of validity for this user pool
+      virtual const IOV& validity() const  {
+	return this->m_iov;
+      }
+      /// Update interval of validity for this user pool (should only be called by ConditionsManager)
+      virtual void setValidity(const IOV& value)   {
+	this->m_iov = value;
+	this->ConditionsPool::iovType = m_iov.iovType;
       }
 
-      /// Pop conditions. May overloade for performance reasons!
-      virtual void popEntries(RangeConditions& entries)   {
-        MAPPING& m = this->ConditionsLinearPool<MAPPING,ReplacementPool>::m_conditions;
-        if ( !m.empty() )  {
-          for(typename MAPPING::iterator i=m.begin(); i!=m.end(); ++i)
-            entries.push_back((*i));        
-          m.clear();
-        }
+      /// Full cleanup of all managed conditions.
+      virtual void clear()   {
+	m_iov = IOV(0);
+        this->ConditionsLinearPool<MAPPING,UserPool>::m_conditions.clear();
       }
     };
 
 
+    /// Class implementing the conditions update pool for a given IOV type
+    /**
+     *
+     *  \author  M.Frank
+     *  \version 1.0
+     *  \ingroup DD4HEP_CONDITIONS
+     */
     template<typename MAPPING> class ConditionsLinearUpdatePool 
       : public ConditionsLinearPool<MAPPING,UpdatePool>
     {
     public:
       /// Default constructor
-      ConditionsLinearUpdatePool() : ConditionsLinearPool<MAPPING,UpdatePool>() {}
+      ConditionsLinearUpdatePool(ConditionsManager mgr)
+	: ConditionsLinearPool<MAPPING,UpdatePool>(mgr) 
+      {
+      }
 
       /// Default destructor
       virtual ~ConditionsLinearUpdatePool()  {}
@@ -231,15 +277,14 @@ namespace DD4hep {
 
 // Framework include files
 //#include "DDCond/ConditionsLinearPool.h"
+#include "DD4hep/Printout.h"
 #include "DD4hep/InstanceCount.h"
-#include "DD4hep/objects/DetectorInterna.h"
-#include "DD4hep/objects/ConditionsInterna.h"
 
 using namespace DD4hep::Conditions;
 
 /// Default constructor
 template<typename MAPPING, typename BASE>
-ConditionsLinearPool<MAPPING,BASE>::ConditionsLinearPool() : BASE() {
+ConditionsLinearPool<MAPPING,BASE>::ConditionsLinearPool(ConditionsManager mgr) : BASE(mgr)  {
   InstanceCount::increment(this);
 }
 
@@ -252,21 +297,29 @@ ConditionsLinearPool<MAPPING,BASE>::~ConditionsLinearPool()  {
 
 #include "DD4hep/Factories.h"
 namespace {
-  void* create_vector_pool(DD4hep::Geometry::LCDD&, int, char**)
-  {  return new ConditionsLinearPool<std::vector<Condition::Object*> , ConditionsPool>();  }
-  void* create_list_pool(DD4hep::Geometry::LCDD&, int, char**)
-  {  return new ConditionsLinearPool<std::list<Condition::Object*> , ConditionsPool>();    }
-  void* create_replacement_pool(DD4hep::Geometry::LCDD&, int, char**)  {
-    ReplacementPool* pool = new ConditionsLinearReplacementPool<std::vector<Condition::Object*> >();
+  ConditionsManager _mgr(int argc, char** argv)  {
+    if ( argc > 0 )  {
+      ConditionsManager::Object* m = (ConditionsManager::Object*)argv[0];
+      return m;
+    }
+    DD4hep::except("ConditionsLinearPool","++ Insufficient arguments: arg[0] = ConditionManager!");
+    return ConditionsManager(0);
+  }
+  void* create_vector_pool(DD4hep::Geometry::LCDD&, int argc, char** argv)
+  {  return new ConditionsLinearPool<std::vector<Condition::Object*> , ConditionsPool>(_mgr(argc,argv));  }
+  void* create_list_pool(DD4hep::Geometry::LCDD&, int argc, char** argv)
+  {  return new ConditionsLinearPool<std::list<Condition::Object*> , ConditionsPool>(_mgr(argc,argv));    }
+  void* create_user_pool(DD4hep::Geometry::LCDD&, int argc, char** argv)  {
+    UserPool* pool = new ConditionsLinearUserPool<std::vector<Condition::Object*> >(_mgr(argc,argv));
     return pool;
   }
-  void* create_update_pool(DD4hep::Geometry::LCDD&, int, char**)  {
-    UpdatePool* pool = new ConditionsLinearUpdatePool<std::vector<Condition::Object*> >();
+  void* create_update_pool(DD4hep::Geometry::LCDD&, int argc, char** argv)  {
+    UpdatePool* pool = new ConditionsLinearUpdatePool<std::vector<Condition::Object*> >(_mgr(argc,argv));
     return pool;
   }
 }
-DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearPool,      create_vector_pool)
-DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearListPool,  create_list_pool)
-DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearVectorPool,create_vector_pool)
-DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearReplacementPool, create_replacement_pool)
-DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearUpdatePool, create_update_pool)
+DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearPool,            create_vector_pool)
+DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearListPool,        create_list_pool)
+DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearVectorPool,      create_vector_pool)
+DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearUserPool,        create_user_pool)
+DECLARE_LCDD_CONSTRUCTOR(DD4hep_ConditionsLinearUpdatePool,      create_update_pool)
diff --git a/DDCond/src/plugins/ConditionsManagerInstaller.cpp b/DDCond/src/plugins/ConditionsManagerInstaller.cpp
new file mode 100644
index 000000000..5463d660b
--- /dev/null
+++ b/DDCond/src/plugins/ConditionsManagerInstaller.cpp
@@ -0,0 +1,39 @@
+// $Id$
+//==========================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+
+// Framework include files
+#include "DD4hep/LCDD.h"
+#include "DD4hep/Plugins.h"
+#include "DD4hep/Printout.h"
+#include "DD4hep/Factories.h"
+#include "DDCond/ConditionsManager.h"
+#include "DDCond/ConditionsInterna.h"
+
+namespace {
+  using namespace DD4hep;
+  using namespace DD4hep::Conditions;
+
+  int install_cond_mgr (Geometry::LCDD& lcdd, int /* argc */, char** /* argv */)  {
+    typedef Interna::ConditionsManagerObject ConditionsManagerObject;
+    Handle<ConditionsManagerObject> mgr(lcdd.extension<ConditionsManagerObject>(false));
+    if ( !mgr.isValid() )  {
+      ConditionsManager mgr_handle(lcdd);
+      lcdd.addExtension<ConditionsManagerObject>(mgr_handle.ptr());
+      printout(INFO,"ConditionsManager","+++ Successfully installed conditions manager instance.");
+    }
+    return 1;
+  }
+}
+
+DECLARE_APPLY(DD4hepConditionsManagerInstaller,install_cond_mgr)
diff --git a/DDCond/src/ConditionsMultiLoader.cpp b/DDCond/src/plugins/ConditionsMultiLoader.cpp
similarity index 59%
rename from DDCond/src/ConditionsMultiLoader.cpp
rename to DDCond/src/plugins/ConditionsMultiLoader.cpp
index fff24204b..9931ea7c8 100644
--- a/DDCond/src/ConditionsMultiLoader.cpp
+++ b/DDCond/src/plugins/ConditionsMultiLoader.cpp
@@ -55,11 +55,11 @@ namespace DD4hep {
                                 const std::string& cond,
                                 const IOV& req_validity,
                                 RangeConditions& conditions);
-      size_t load_source(const std::string& nam,
-                         DetElement det,
-                         const std::string& cond,
-                         const IOV& req_validity,
-                         RangeConditions& conditions);
+      /// Update a range of conditions according to the required IOV
+      virtual size_t update(const IOV& req_validity,
+			    RangeConditions& conditions,
+			    IOV& conditions_validity);
+      ConditionsDataLoader* load_source(const std::string& nam,const IOV& req_validity);
     };
   } /* End namespace Geometry               */
 } /* End namespace DD4hep                   */
@@ -70,6 +70,7 @@ namespace DD4hep {
 #include "DD4hep/Printout.h"
 #include "DD4hep/Factories.h"
 #include "DD4hep/PluginCreators.h"
+#include "DD4hep/objects/ConditionsInterna.h"
 
 // Forward declartions
 using std::string;
@@ -94,40 +95,36 @@ ConditionsMultiLoader::ConditionsMultiLoader(LCDD& lcdd, ConditionsManager mgr,
 ConditionsMultiLoader::~ConditionsMultiLoader() {
 } 
 
-size_t ConditionsMultiLoader::load_source(const std::string& nam,
-                                          DetElement det,
-                                          const std::string& cond,
-                                          const IOV& req_validity, 
-                                          RangeConditions& conditions)
+ConditionsDataLoader* ConditionsMultiLoader::load_source(const std::string& nam,const IOV& req_validity)
 {
-  size_t idx = nam.find(':');
-  if ( idx == string::npos )   {
-    except("ConditionsMultiLoader","Invalid data source specification: "+nam);
-  }
-  string ident = nam.substr(0,idx);
-  Loaders::iterator ild = m_loaders.find(ident);
-  ConditionsDataLoader* loader = 0;
-  if ( ild == m_loaders.end() )  {
-    string typ = "DD4hep_Conditions_"+ident+"_Loader";
-    string fac = ident+"_ConditionsDataLoader";
-    char* argv[] = {(char*)fac.c_str(), (char*)m_mgr.ptr(), 0};
-    loader = createPlugin<ConditionsDataLoader>(typ,m_lcdd,2,argv);
-    if ( !loader )  {
-      except("ConditionsMultiLoader",
-             "Failed to create conditions loader of type: "+typ+" to read:"+nam);
+  OpenSources::iterator iop = m_openSources.find(nam);
+  if ( iop == m_openSources.end() )  {
+    size_t idx = nam.find(':');
+    if ( idx == string::npos )   {
+      except("ConditionsMultiLoader","Invalid data source specification: "+nam);
     }
+    string ident = nam.substr(0,idx);
+    Loaders::iterator ild = m_loaders.find(ident);
+    ConditionsDataLoader* loader = 0;
+    if ( ild == m_loaders.end() )  {
+      string typ = "DD4hep_Conditions_"+ident+"_Loader";
+      string fac = ident+"_ConditionsDataLoader";
+      const void* argv[] = {fac.c_str(), m_mgr.ptr(), 0};
+      loader = createPlugin<ConditionsDataLoader>(typ,m_lcdd,2,argv);
+      if ( !loader )  {
+	except("ConditionsMultiLoader",
+	       "Failed to create conditions loader of type: "+typ+" to read:"+nam);
+      }
+    }
+    else  {
+      loader = (*ild).second;
+    }
+    loader->addSource(nam.substr(idx+1),req_validity);
+    m_loaders[ident] = loader;
+    m_openSources[nam] = loader;
+    return loader;
   }
-  else  {
-    loader = (*ild).second;
-  }
-  loader->addSource(nam.substr(idx+1));
-  m_loaders[ident] = loader;
-  m_openSources[nam] = loader;
-  size_t items = loader->load(det, cond, req_validity, conditions);
-  if ( items > 0 )  {
-    return items;
-  }
-  return 0;
+  return (*iop).second;
 }
 
 /// Load  a condition set given a Detector Element and the conditions name according to their validity
@@ -138,13 +135,14 @@ size_t ConditionsMultiLoader::load_range(DetElement det,
   size_t len = conditions.size();
   // No better idea: Must chack all sources to find the required condition
   for(Sources::const_iterator i=m_sources.begin(); i != m_sources.end(); ++i)  {
-    const string& nam = *i;
-    OpenSources::iterator iop = m_openSources.find(nam);
-    if ( iop == m_openSources.end() )  {
-      load_source(nam, det, cond, req_validity, conditions);
-      continue;
+    const IOV& iov = (*i).second;
+    if ( iov.type == req_validity.type )  {
+      if ( IOV::key_partially_contained(iov.keyData,req_validity.keyData) )  { 
+	const string& nam = (*i).first;
+	ConditionsDataLoader* loader = load_source(nam, req_validity);
+	loader->load(det, cond, req_validity, conditions);
+      }
     }
-    (*iop).second->load(det, cond, req_validity, conditions);
   }
   return conditions.size() - len;
 }
@@ -157,18 +155,36 @@ size_t ConditionsMultiLoader::load(DetElement det,
   size_t len = conditions.size();
   // No better idea: Must chack all sources to find the required condition
   for(Sources::const_iterator i=m_sources.begin(); i != m_sources.end(); ++i)  {
-    const string& nam = *i;
-    size_t items = 0;
-    OpenSources::iterator iop = m_openSources.find(nam);
-    if ( iop == m_openSources.end() )  {
-      items = load_source(nam, det, cond, req_validity, conditions);
-      if ( items > 0 )  {
-        return items;
+    const IOV& iov = (*i).second;
+    if ( iov.type == req_validity.type )  {
+      if ( IOV::key_partially_contained(iov.keyData,req_validity.keyData) )  {
+	const string& nam = (*i).first;
+	ConditionsDataLoader* loader = load_source(nam, req_validity);
+	loader->load(det, cond, req_validity, conditions);
       }
-      continue;
     }
-    items = (*iop).second->load(det, cond, req_validity, conditions);
-    if ( items > 0 ) return items;
   }
   return conditions.size() - len;
 }
+
+/// Update a range of conditions according to the required IOV
+size_t ConditionsMultiLoader::update(const IOV& req_iov,
+				     RangeConditions& updates,
+				     IOV& conditions_validity)  {
+  RangeConditions upda;
+  for(RangeConditions::const_iterator i=updates.begin(); i!=updates.end(); ++i)  {
+    Condition::Object* cond = (*i).ptr();
+    size_t items = load(cond->detector,cond->name,req_iov,upda);
+    if ( items < 1 )  {
+      // Error: no such condition
+      except("ConditionsManager",
+	     "+++ update_expired: Cannot update condition %s.%s [%s] to iov:%s.",
+             cond->detector.path().c_str(), cond->name.c_str(),
+             cond->iov->str().c_str(), req_iov.str().c_str());
+    }
+  }
+  updates = upda;
+  for(RangeConditions::const_iterator i=updates.begin(); i!=updates.end(); ++i)
+    conditions_validity.iov_intersection((*i).iov());
+  return updates.size();
+}
diff --git a/DDCond/src/ConditionsParser.cpp b/DDCond/src/plugins/ConditionsParser.cpp
similarity index 99%
rename from DDCond/src/ConditionsParser.cpp
rename to DDCond/src/plugins/ConditionsParser.cpp
index 3b066781e..3ae79d99a 100644
--- a/DDCond/src/ConditionsParser.cpp
+++ b/DDCond/src/plugins/ConditionsParser.cpp
@@ -1,4 +1,4 @@
-// $Id: $
+// $Id$
 //==========================================================================
 //  AIDA Detector description implementation for LCD
 //--------------------------------------------------------------------------
@@ -67,7 +67,7 @@ namespace DD4hep {
   }
 
   ConversionArg* _getArgs(void* param)   {
-    ConversionArg* arg = (ConversionArg*)param;
+    ConversionArg* arg = static_cast<ConversionArg*>(param);
     return arg;
   }
   /// Helper: Extract the required detector element from the parsing information
diff --git a/DDCond/src/plugins/ConditionsPlugins.cpp b/DDCond/src/plugins/ConditionsPlugins.cpp
new file mode 100644
index 000000000..f18aab69c
--- /dev/null
+++ b/DDCond/src/plugins/ConditionsPlugins.cpp
@@ -0,0 +1,137 @@
+// $Id$
+//==========================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+
+// Framework include files
+#include "DD4hep/LCDD.h"
+#include "DD4hep/Printout.h"
+#include "DD4hep/Conditions.h"
+#include "DD4hep/DetFactoryHelper.h"
+
+#include "DDCond/ConditionsManager.h"
+#include "DDCond/ConditionsIOVPool.h"
+#include "DDCond/ConditionsInterna.h"
+#include "DDCond/ConditionsPool.h"
+#include "DDCond/ConditionsInterna.h"
+
+using namespace std;
+using namespace DD4hep;
+using namespace DD4hep::Conditions;
+using Geometry::LCDD;
+using Geometry::Position;
+using Geometry::DetElement;
+
+namespace {
+
+  int ddcond_dump_conditions_functor(lcdd_t& lcdd, bool print_conditions)   {
+    typedef std::vector<const IOVType*> _T;
+    typedef ConditionsIOVPool::Entries _E;
+    typedef RangeConditions _R;
+    ConditionsManager manager = ConditionsManager::from(lcdd);
+
+    const _T types = manager.iovTypesUsed();
+    for( _T::const_iterator i = types.begin(); i != types.end(); ++i )    {
+      const IOVType* type = *i;
+      if ( type )   {
+	ConditionsIOVPool* pool = manager.iovPool(*type);
+	if ( pool )  {
+	  const _E& e = pool->entries;
+	  printout(INFO,"CondPoolDump","+++ ConditionsIOVPool for type %s  [%d IOV entries]",
+		   type->str().c_str(), int(e.size()));
+	  for (_E::const_iterator j=e.begin(); j != e.end(); ++j)  {
+	    ConditionsPool* cp = (*j).second;
+	    cp->print("");
+	    if ( print_conditions )   {
+	      _R rc;
+	      cp->select_all(rc);
+	      //print_conditions<void>(rc);
+	    }
+	  }
+	}
+      }
+    }
+    printout(INFO,"Example","SUCCESS: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+    printout(INFO,"Example","SUCCESS: +++ Conditions pools successfully dumped");
+    printout(INFO,"Example","SUCCESS: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++");
+    return 1;
+  }
+
+  int ddcond_dump_pools(LCDD& lcdd, int /* argc */, char** /* argv */)   {
+    return ddcond_dump_conditions_functor(lcdd,false);
+  }
+  int ddcond_dump_conditions(LCDD& lcdd, int /* argc */, char** /* argv */)   {
+    return ddcond_dump_conditions_functor(lcdd,true);
+  }
+}
+
+DECLARE_APPLY(DD4hepDDCondPoolDump,ddcond_dump_pools)
+DECLARE_APPLY(DD4hepDDCondConditionsDump,ddcond_dump_conditions)
+
+namespace {
+  /// Plugin entry point.
+  static long synchronize_conditions(lcdd_t& lcdd, int argc, char** argv) {
+    if ( argc > 0 )   {
+      string iov_type = argv[0];
+      IOV::Key::first_type iov_key = *(IOV::Key::first_type*)argv[1];
+      ConditionsManager    manager = ConditionsManager::from(lcdd);
+      const IOVType*       epoch   = manager.iovType(iov_type);
+      dd4hep_ptr<ConditionsPool> user_pool;
+      IOV  iov(epoch);
+
+      iov.set(iov_key);
+      long num_expired = manager.prepare(iov, user_pool);
+      if ( iov_type == "epoch" )  {
+	char   c_evt[64];
+	struct tm evt;
+	::gmtime_r(&iov_key, &evt);
+	::strftime(c_evt,sizeof(c_evt),"%T %F",&evt);
+	printout(INFO,"Conditions",
+		 "+++ ConditionsUpdate: Updated %ld conditions... event time: %s",
+		 num_expired, c_evt);
+      }
+      else  {
+	printout(INFO,"Conditions",
+		 "+++ ConditionsUpdate: Updated %ld conditions... key[%s]: %ld",
+		 num_expired, iov_type.c_str(), iov_key);
+      }
+      manager.enable(iov, user_pool);
+      user_pool->print("User pool");
+      manager.clean(epoch, 20);
+      user_pool->clear();
+      return 1;
+    }
+    except("DDDB","+++ Failed update DDDB conditions. No event time argument given!");
+    return 0;
+  }
+}
+DECLARE_APPLY(DD4hep_ConditionsSynchronize,synchronize_conditions)
+
+namespace {
+  /// Plugin entry point.
+  static long clean_conditions(lcdd_t& lcdd, int argc, char** argv) {
+    if ( argc > 0 )   {
+      string iov_type = argv[0];
+      int max_age = *(int*)argv[1];
+      printout(INFO,"Conditions",
+	       "+++ ConditionsUpdate: Cleaning conditions... type:%s max age:%d",
+	       iov_type.c_str(), max_age);
+      ConditionsManager manager = ConditionsManager::from(lcdd);
+      const IOVType* epoch = manager.iovType(iov_type);
+      manager.clean(epoch, max_age);
+      return 1;
+    }
+    except("DDDB","+++ Failed cleaning conditions. Insufficient arguments!");
+    return 0;
+  }
+}
+DECLARE_APPLY(DD4hep_ConditionsClean,clean_conditions)
diff --git a/DDCond/src/plugins/ConditionsUpdate.cpp b/DDCond/src/plugins/ConditionsUpdate.cpp
new file mode 100644
index 000000000..4937051bb
--- /dev/null
+++ b/DDCond/src/plugins/ConditionsUpdate.cpp
@@ -0,0 +1,15 @@
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+//  \author  Markus Frank
+//  \date    2016-02-02
+//  \version 1.0
+//
+//==========================================================================
+// $Id$
+
diff --git a/DDCond/src/ConditionsXmlLoader.cpp b/DDCond/src/plugins/ConditionsXmlLoader.cpp
similarity index 83%
rename from DDCond/src/ConditionsXmlLoader.cpp
rename to DDCond/src/plugins/ConditionsXmlLoader.cpp
index 06febf215..55ac34bb6 100644
--- a/DDCond/src/ConditionsXmlLoader.cpp
+++ b/DDCond/src/plugins/ConditionsXmlLoader.cpp
@@ -54,6 +54,10 @@ namespace DD4hep {
                           const std::string& cond,
                           const IOV& req_validity,
                           RangeConditions& conditions);
+      /// Update a range of conditions according to the required IOV
+      virtual size_t update(const IOV& req_validity,
+			    RangeConditions& conditions,
+			    Conditions::IOV& iov_intersection);
     };
 
   } /* End namespace Geometry               */
@@ -65,6 +69,8 @@ namespace DD4hep {
 #include "DD4hep/Printout.h"
 #include "DD4hep/Factories.h"
 #include "DD4hep/PluginCreators.h"
+#include "DD4hep/objects/ConditionsInterna.h"
+
 #include "XML/XMLElements.h"
 #include "XML/DocumentHandler.h"
 #include "DDCond/ConditionsInterna.h"
@@ -138,21 +144,21 @@ size_t ConditionsXmlLoader::load(DetElement det,
 {
   size_t len = conditions.size();
   if ( m_buffer.empty() && !m_sources.empty() )  {
-    return load_source(*(m_sources.begin()), det, cond, req_validity, conditions);
+    return load_source(m_sources.begin()->first, det, cond, req_validity, conditions);
   }
   for (Buffer::iterator j=m_buffer.begin(); j!=m_buffer.end(); ++j)  {
     Condition condition = *j;
-    if ( det == condition->detector && cond == condition->name )  {
-      if ( req_validity.contains(*condition->iov) )   {
-        conditions.push_back(condition);
-        m_buffer.erase(j);
-        return conditions.size()-len;
+    if ( det == condition->detector )  {
+      const IOV* iov = condition->iov;
+      if ( IOV::partial_match(req_validity,*iov) )  {
+	if ( cond == condition->name )  {
+	  conditions.push_back(condition);
+	  m_buffer.erase(j);
+	  return conditions.size()-len;
+	}
       }
     }
   }
-  if ( !m_sources.empty() )  {
-    return load_source(*(m_sources.begin()), det, cond, req_validity, conditions);
-  }
   return conditions.size()-len;
 }
 
@@ -163,20 +169,17 @@ size_t ConditionsXmlLoader::load_range(DetElement det,
 {
   size_t len = conditions.size();
   while ( !m_sources.empty() )  {
-    load_source(*(m_sources.begin()), det, cond, req_validity, conditions);
+    load_source(m_sources.begin()->first, det, cond, req_validity, conditions);
   }
   std::vector<Condition> keep;
-  for (size_t j=0; j<m_buffer.size(); ++j)  {
-    Condition condition = m_buffer[j];
-    if ( det == condition->detector && cond == condition->name )  {
+  for (Buffer::iterator j=m_buffer.begin(); j!=m_buffer.end(); ++j)  {
+    Condition condition = *j;
+    if ( det == condition->detector )  {
       const IOV* iov = condition->iov;
-      if ( IOV::same_type(req_validity,*iov) )  {
-        if ( IOV::key_is_contained(req_validity.key(),iov->key()) ||
-             IOV::key_overlaps_lower_end(req_validity.key(),iov->key()) || 
-             IOV::key_overlaps_higher_end(req_validity.key(),iov->key()) )  {
-          conditions.push_back(condition);
-          continue;
-        }
+      if ( IOV::partial_match(req_validity,*iov) )  {
+	if ( cond == condition->name )  {
+	  conditions.push_back(condition);
+	}
       }
     }
     keep.push_back(condition);
@@ -184,3 +187,9 @@ size_t ConditionsXmlLoader::load_range(DetElement det,
   m_buffer = keep;
   return conditions.size()-len;
 }
+
+/// Update a range of conditions according to the required IOV
+size_t ConditionsXmlLoader::update(const IOV&,RangeConditions&, IOV&)  {
+  except("ConditionsXmlLoader","+++ update: Invalid call!");
+  return 0;
+}
diff --git a/DDCore/include/DD4hep/Conditions.h b/DDCore/include/DD4hep/Conditions.h
index 8af4b3f06..f61150c78 100644
--- a/DDCore/include/DD4hep/Conditions.h
+++ b/DDCore/include/DD4hep/Conditions.h
@@ -73,13 +73,11 @@ namespace DD4hep {
     class IOV   {
       friend class Condition;
     private:
-      /// No IOC copies!
-      explicit IOV(const IOV&) {}
       /// Initializing constructor: Does not set reference to IOVType !
       explicit IOV();
     public:
       /// Key definition
-      typedef std::pair<int,int> Key;
+      typedef std::pair<long,long> Key;
 
       const IOVType* iovType;
       Key            keyData;
@@ -89,6 +87,11 @@ namespace DD4hep {
 
       /// Initializing constructor
       explicit IOV(const IOVType* typ);
+      /// Copy constructor
+      explicit IOV(const IOV& copy);
+      /// Copy constructor
+      explicit IOV(const IOVType* typ, const Key& key);
+
       /// Standard Destructor
       ~IOV();
       /// Move the data content: 'from' will be reset to NULL
@@ -101,6 +104,26 @@ namespace DD4hep {
       bool is_discrete() const           {  return keyData.first == keyData.second;  }
       /// Get the local key of the IOV
       Key  key() const                   {  return keyData;                          }
+
+      /// Set discrete IOV value
+      void set(const Key& value);
+      /// Set discrete IOV value
+      void set(Key::first_type value);
+      /// Set range IOV value
+      void set(Key::first_type val_1, Key::second_type val_2);
+      /// Set keys to unphysical values (LONG_MAX, LONG_MIN)
+      void reset();
+      /// Invert the key values (first=second and second=first)
+      void invert();
+      /// Set the intersection of this IOV with the argument IOV
+      void iov_intersection(const IOV& comparator);
+       /// Set the intersection of this IOV with the argument IOV
+      void iov_intersection(const IOV::Key& comparator);
+      /// Set the union of this IOV with the argument IOV
+      void iov_union(const IOV& comparator);
+      /// Set the union of this IOV with the argument IOV
+      void iov_union(const IOV::Key& comparator);
+
       /// Check for validity containment
       /** Check if the caller 'iov' is of the same type and the range 
        *  is fully conained by the caller.
@@ -124,6 +147,20 @@ namespace DD4hep {
       /// Check if IOV 'test' has an overlap on the upper interval edge with IOV 'key'
       static bool key_overlaps_higher_end(const Key& key, const Key& test)         
       {   return key.second >= test.first && key.second <= test.second;     }
+      /// Check if IOV 'test' has an overlap on the upper interval edge with IOV 'key'
+      static bool key_partially_contained(const Key& key, const Key& test)         
+      {   
+	return 
+	  (test.first <= key.first  && key.second   >= test.second) || // test fully contained in key
+	  (test.first <= key.first  && key.first    <= test.second) || // test overlaps left edge of key
+	  (test.first <= key.second && key.second   <= test.second);   // test overlaps right edge of key
+      }
+      /// Check if IOV 'test' is of same type and is fully contained in iov
+      static bool full_match(const IOV& iov, const IOV& test)
+      {   return same_type(iov,test) && key_is_contained(iov.keyData,test.keyData);      }
+      /// Check if IOV 'test' is of same type and is at least partially contained in iov
+      static bool partial_match(const IOV& iov, const IOV& test)
+      {   return same_type(iov,test) && key_partially_contained(iov.keyData,test.keyData);      }
     };
     
 
@@ -155,9 +192,11 @@ namespace DD4hep {
 
     public:
       /// Create data block from string representation
-      void fromString(const std::string& rep);
+      bool fromString(const std::string& rep);
       /// Create string representation of the data block
-      std::string str();
+      std::string str()  const;
+      /// Access type id of the condition
+      const std::type_info& typeInfo() const;
       /// Check if object is already bound....
       bool is_bound()  const  {  return 0 != pointer; }
       /// Generic getter. Specify the exact type, not a polymorph type
@@ -238,7 +277,7 @@ namespace DD4hep {
        *  Note: The type definition is possible exactly once.
        *  Any further rebindings MUST match the identical type.
        */
-      template <typename T> Condition& bind();
+      template <typename T> T& bind();
       /// Generic getter. Specify the exact type, not a polymorph type
       template <typename T> T& get();
       /// Generic getter (const version). Specify the exact type, not a polymorph type
diff --git a/DDCore/include/DD4hep/InstanceCount.h b/DDCore/include/DD4hep/InstanceCount.h
index 3f74373e2..9fda7e87e 100644
--- a/DDCore/include/DD4hep/InstanceCount.h
+++ b/DDCore/include/DD4hep/InstanceCount.h
@@ -135,5 +135,19 @@ namespace DD4hep {
     static void doTracing(bool value);
   };
 
+  /// Helper class to count call stack depths of certain functions
+  /**
+   * Small class to count re-entrancy calls
+   *
+   *  \author  M.Frank
+   *  \version 1.0
+   *  \ingroup DD4HEP
+   */
+  template <typename T> struct Increment {
+    static int& counter() { static int cnt=0; return cnt; }
+    Increment() { ++counter(); }
+    ~Increment() { --counter(); }
+  };
+
 } /* End namespace DD4hep             */
 #endif    /* DD4HEP_GEOMETRY_INSTANCECOUNT_H     */
diff --git a/DDCore/include/DD4hep/LCDD.h b/DDCore/include/DD4hep/LCDD.h
index 1dc401f82..2abdc39da 100644
--- a/DDCore/include/DD4hep/LCDD.h
+++ b/DDCore/include/DD4hep/LCDD.h
@@ -54,7 +54,6 @@ namespace DD4hep {
     return vs ;
   }
   
-
   // Foward declarations
   class NamedObject;
 
@@ -68,6 +67,11 @@ namespace DD4hep {
     BUILD_NONE = 0, BUILD_DEFAULT = 1, BUILD_SIMU = BUILD_DEFAULT, BUILD_RECO, BUILD_DISPLAY, BUILD_ENVELOPE
   };
 
+  /// Namespace for the AIDA detector description toolkit supporting XML utilities
+  namespace XML {
+    class UriReader;
+  }
+
   /// Namespace for the geometry part of the AIDA detector description toolkit
   namespace Geometry {
 
@@ -88,6 +92,7 @@ namespace DD4hep {
     class LCDD {
     public:
       /// Type definition of a map of named handles
+      typedef XML::UriReader UriReader;
       typedef Handle<NamedObject> NamedHandle;
       typedef std::map<std::string, NamedHandle > HandleMap;
       typedef std::map<std::string, std::string> PropertyValues;
@@ -278,11 +283,16 @@ namespace DD4hep {
       /// Add a field component by named reference to the detector description
       virtual LCDD& addField(const Ref_t& field) = 0;
 
-      /// Read compact geometry description or alignment file
+      /// Deprecated call (use fromXML): Read compact geometry description or alignment file
       virtual void fromCompact(const std::string& fname, LCDDBuildType type = BUILD_DEFAULT) = 0;
       /// Read any geometry description or alignment file
       virtual void fromXML(const std::string& fname, LCDDBuildType type = BUILD_DEFAULT) = 0;
-      ///
+      /// Read any geometry description or alignment file with external XML entity resolution
+      virtual void fromXML(const std::string& fname,
+			   UriReader* entity_resolver,
+			   LCDDBuildType type = BUILD_DEFAULT) = 0;
+
+      /// Stupid legacy method
       virtual void dump() const = 0;
       /// Manipulate geometry using facroy converter
       virtual long apply(const char* factory, int argc, char** argv) = 0;
diff --git a/DDCore/include/DD4hep/LCDDLoad.h b/DDCore/include/DD4hep/LCDDLoad.h
index 5979065b0..ba0fdbb97 100644
--- a/DDCore/include/DD4hep/LCDDLoad.h
+++ b/DDCore/include/DD4hep/LCDDLoad.h
@@ -20,13 +20,19 @@
 // C/C++ include files
 #include <stdexcept>
 
-/*
- *   DD4hep namespace declaration
- */
+/// Namespace for the AIDA detector description toolkit
 namespace DD4hep {
 
-  namespace XML  { class Handle_t; }
-  namespace Geometry { class LCDD; }
+  /// Namespace for the AIDA detector description toolkit supporting XML utilities
+  namespace XML  { 
+    class Handle_t;
+    class UriReader;
+  }
+
+  /// Namespace for the geometry part of the AIDA detector description toolkit
+  namespace Geometry {
+    class LCDD;
+  }
 
   /// Data implementation class of the LCDD interface
   /** @class LCDDLoad   LCDDLoad.h  DD4hep/LCDDLoad.h
@@ -37,6 +43,7 @@ namespace DD4hep {
   class LCDDLoad  {
   public:
     friend class Geometry::LCDD;
+
   protected:
     /// Reference to the LCDD instance
     Geometry::LCDD* m_lcdd;
@@ -44,11 +51,12 @@ namespace DD4hep {
     LCDDLoad(Geometry::LCDD* lcdd);
     /// Default destructor
     virtual ~LCDDLoad();
+
   public:
-    /// Adopt all data from source structure.
-    virtual void processXML(const std::string& fname);
-    /// Adopt all data from source structure.
-    virtual void processXML(const XML::Handle_t& base, const std::string& fname);
+    /// Process XML unit and adopt all data from source structure.
+    virtual void processXML(const std::string& fname, XML::UriReader* entity_resolver=0);
+    /// Process XML unit and adopt all data from source structure.
+    virtual void processXML(const XML::Handle_t& base, const std::string& fname, XML::UriReader* entity_resolver=0);
     /// Process a given DOM (sub-) tree
     virtual void processXMLElement(const std::string& msg_source, const XML::Handle_t& root);
     /// Process a given DOM (sub-) tree
diff --git a/DDCore/include/DD4hep/Operators.h b/DDCore/include/DD4hep/Operators.h
new file mode 100644
index 000000000..ee4185097
--- /dev/null
+++ b/DDCore/include/DD4hep/Operators.h
@@ -0,0 +1,68 @@
+// $Id$
+//==========================================================================
+//  AIDA Detector description implementation for LCD
+//--------------------------------------------------------------------------
+// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
+// All rights reserved.
+//
+// For the licensing terms see $DD4hepINSTALL/LICENSE.
+// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
+//
+// Author     : M.Frank
+//
+//==========================================================================
+
+#ifndef DD4HEP_DD4HEP_OPERATORS_H
+#define DD4HEP_DD4HEP_OPERATORS_H
+
+// C/C++ include files
+#include <string>
+
+/// Namespace for the AIDA detector description toolkit
+namespace DD4hep {
+
+  /// Helper functor to select elements by name (using name() member method)
+  template <typename T> class ByName {
+  private:
+    /// Assignment operator
+    template <typename Q> ByName<T>& operator=(const ByName<Q>& copy)  { return *this; }
+  public:
+    /// Reference name
+    const std::string& name;
+    /// Standard constructor
+    ByName(const std::string& nam) : name(nam) {}
+    /// Copy constructor
+    ByName(const ByName& copy) : name(copy.name) {}
+    /// Operator to select from object containers
+    bool operator()(const T& entry)  const  {  return entry.name()  == name;  }
+    /// Operator to select from pointer containers
+    bool operator()(const T* entry)  const  {  return entry->name() == name;  }
+  };
+  template <typename T> ByName<T> byName(const std::string& n) { return ByName<T>(n); }
+  template <typename T> ByName<T> byName(const T* o) { return ByName<T>(o->name()); }
+  template <typename T> ByName<T> byName(const T& o) { return ByName<T>(o.name()); }
+
+  /// Helper functor to select elements by name (using name member variable)
+  template <typename T> class ByNameAttr {
+  private:
+    /// Assignment operator
+    template <typename Q> ByNameAttr<T>& operator=(const ByNameAttr<Q>& copy)  { return *this; }
+  public:
+    /// Reference name
+    const std::string& name;
+    /// Standard constructor
+    ByNameAttr(const std::string& nam) : name(nam) {}
+    /// Copy constructor
+    ByNameAttr(const ByNameAttr& copy) : name(copy.name) {}
+    /// Operator to select from object containers
+    bool operator()(const T& entry)  const  {  return entry.name  == name;  }
+    /// Operator to select from pointer containers
+    bool operator()(const T* entry)  const  {  return entry->name == name;  }
+  };
+
+  template <typename T> ByNameAttr<T> byNameAttr(const std::string& nam) { return ByNameAttr<T>(nam); }
+  template <typename T> ByNameAttr<T> byNameAttr(const T* o) { return ByNameAttr<T>(o->name); }
+  template <typename T> ByNameAttr<T> byNameAttr(const T& o) { return ByNameAttr<T>(o.name);  }
+
+}      // End namespace DD4hep
+#endif // DD4HEP_DD4HEP_OPERATORS_H
diff --git a/DDCore/include/DD4hep/PluginCreators.h b/DDCore/include/DD4hep/PluginCreators.h
index 68aef2dd3..a925ebc4b 100644
--- a/DDCore/include/DD4hep/PluginCreators.h
+++ b/DDCore/include/DD4hep/PluginCreators.h
@@ -53,10 +53,10 @@ namespace DD4hep {
     return (plugin_t*)createPlugin(factory, lcdd, arg, __cast::cast);
   }
   /// Handler for factories of type: ConstructionFactory with casted return type
-  template <typename T> T* createPlugin(const std::string& factory, Geometry::LCDD& lcdd, int argc, char** argv)   {
+  template <typename T> T* createPlugin(const std::string& factory, Geometry::LCDD& lcdd, int argc, const void** argv)   {
     typedef T plugin_t;
     struct __cast{ static void* cast(void* p) { return &dynamic_cast<plugin_t&>(*(plugin_t*)p); } };
-    return (plugin_t*)createPlugin(factory, lcdd, argc, argv, __cast::cast);
+    return (plugin_t*)createPlugin(factory, lcdd, argc, (char**)argv, __cast::cast);
   }
 
 } /* End namespace DD4hep      */
diff --git a/DDCore/include/DD4hep/Primitives.h b/DDCore/include/DD4hep/Primitives.h
index ab58d895c..fb9c21060 100644
--- a/DDCore/include/DD4hep/Primitives.h
+++ b/DDCore/include/DD4hep/Primitives.h
@@ -278,7 +278,7 @@ namespace DD4hep {
       DestroyObject<typename M::mapped_type>()(p.second);
     }
     void operator()() const {
-      for_each(object.begin(),object.end(),(*this));
+      if ( !object.empty() ) for_each(object.begin(),object.end(),(*this));
     }
   };
   template <typename M> DestroyObjects<M> destroyObjects(M& m) {
@@ -302,7 +302,7 @@ namespace DD4hep {
       DestroyObject<typename M::key_type>()(p.first);
     }
     void operator()() const {
-      for_each(object.begin(),object.end(),(*this));
+      if ( !object.empty() ) for_each(object.begin(),object.end(),(*this));
     }
   };
   template <typename M> DestroyFirst<M> destroyFirst(M& m) {
@@ -340,7 +340,7 @@ namespace DD4hep {
       ReleaseObject<typename M::mapped_type>()(p.second);
     }
     void operator()() const {
-      for_each(object.begin(),object.end(),(*this));
+      if ( !object.empty() ) for_each(object.begin(),object.end(),(*this));
     }
   };
   template <typename M> ReleaseObject<typename M::value_type> releaseObject(M&) {
diff --git a/DDCore/include/DD4hep/Readout.h b/DDCore/include/DD4hep/Readout.h
index cdeba3c36..556fd5731 100644
--- a/DDCore/include/DD4hep/Readout.h
+++ b/DDCore/include/DD4hep/Readout.h
@@ -81,6 +81,8 @@ namespace DD4hep {
       std::vector<std::string> collectionNames()  const;
       /// Access hit collections if present
       std::vector<const HitCollection*> collections()  const;
+      /// Access number of hit collections
+      size_t numCollections() const;
       /// Assign IDDescription to readout structure
       void setIDDescriptor(const Ref_t& spec) const;
       /// Access IDDescription structure
diff --git a/DDCore/include/DD4hep/objects/BasicGrammar_inl.h b/DDCore/include/DD4hep/objects/BasicGrammar_inl.h
index 8210f2fb8..b996a40d3 100644
--- a/DDCore/include/DD4hep/objects/BasicGrammar_inl.h
+++ b/DDCore/include/DD4hep/objects/BasicGrammar_inl.h
@@ -278,21 +278,27 @@ namespace DD4hep {
   template<typename T> inline int eval_obj(T* p, const std::string& str)  {
     return BasicGrammar::instance<T>().fromString(p,pre_parse_obj(str));
   }
+
+  /// User object evaluator
+  /// Do NOTHING version! Function present to formally satisfy code. User implementation required
+  template<typename T> inline int eval_none(T*, const std::string&)  {
+    return 1;
+  }
   
   // Containers of objects are not handled!
   
 }      // End namespace DD4hep
 
-#define DD4HEP_DEFINE_PARSER_GRAMMAR_TYPE(x)  \
-namespace DD4hep {                            \
+#define DD4HEP_DEFINE_PARSER_GRAMMAR_TYPE(x)                           \
+namespace DD4hep {                                                     \
   template<> const BasicGrammar& BasicGrammar::instance<x>()  { static Grammar<x> s; return s;}}
 
-#define DD4HEP_DEFINE_PARSER_GRAMMAR_EVAL(x,func)  \
-  namespace DD4hep {                                                    \
+#define DD4HEP_DEFINE_PARSER_GRAMMAR_EVAL(x,func)                      \
+  namespace DD4hep {                                                   \
     template<> int Grammar<x >::evaluate(void* p, const std::string& v) const { return func ((x*)p,v); }}
 
-#define DD4HEP_DEFINE_PARSER_GRAMMAR(x,func)    \
-  DD4HEP_DEFINE_PARSER_GRAMMAR_TYPE(x)          \
+#define DD4HEP_DEFINE_PARSER_GRAMMAR(x,func)                           \
+  DD4HEP_DEFINE_PARSER_GRAMMAR_TYPE(x)                                 \
   DD4HEP_DEFINE_PARSER_GRAMMAR_EVAL(x,func)
 
 #if defined(DD4HEP_HAVE_ALL_PARSERS)
diff --git a/DDCore/include/DD4hep/objects/ConditionsInterna.h b/DDCore/include/DD4hep/objects/ConditionsInterna.h
index f067cda6b..5cec605f5 100644
--- a/DDCore/include/DD4hep/objects/ConditionsInterna.h
+++ b/DDCore/include/DD4hep/objects/ConditionsInterna.h
@@ -61,7 +61,8 @@ namespace DD4hep {
         BOUND_DATA = 1<<2
       } _DataTypes;
       /// Data buffer: plain data are allocated directly on this buffer
-      unsigned int data[16];
+      /** Internal data buffer is sufficient to store any vector  */
+      unsigned char data[sizeof(std::vector<void*>)];
       /// Destructor function -- only set if the object is valid
       void (*destruct)(void*);
       /// Constructor function -- only set if the object is valid
@@ -70,19 +71,26 @@ namespace DD4hep {
     public:
       /// Data buffer type: Must be a bitmap!
       int type;
-
       /// Standard initializing constructor
       BlockData();
+      /// Copy constructor
+      BlockData(const BlockData& data);
       /// Standard Destructor
       ~BlockData();
+      /// Assignment operator
+      BlockData& operator=(const BlockData& clone);
       /// Move the data content: 'from' will be reset to NULL
-      void move(BlockData& from);
-      /// Set data value
-      void bind(const BasicGrammar* grammar,
+      bool move(BlockData& from);
+      /// Bind data value
+      bool bind(const BasicGrammar* grammar,
                 void (*ctor)(void*,const void*),
                 void (*dtor)(void*));
+      /// Bind data value
+      template <typename T> T& bind();
       /// Set data value
       void assign(const void* ptr,const std::type_info& typ);
+      /// Bind grammar and assign value
+      template<typename T> T& set(const std::string& value);
     };
 
     /// The data class behind a conditions container handle.
@@ -164,6 +172,7 @@ namespace DD4hep {
         const IOVType* iov_type() const;
         /// Check if object is already bound....
         bool is_bound()  const  {  return data.is_bound(); }
+	bool is_traced()  const {  return true;            }
       };
 
       /// The data class behind a conditions container handle.
@@ -212,7 +221,7 @@ namespace DD4hep {
     } /* End namespace Interna    */
 
     template <typename T> static void copyObject(void* t, const void* s)  {
-      *((T*)t) = *((const T*)s);
+      new(t) T(*(const T*)s);
     }
     template <typename T> static void destructObject(void* p)  {
       T* t = (T*)p;
@@ -228,14 +237,24 @@ namespace DD4hep {
       if (!grammar || (grammar->type() != typeid(T))) { throw std::bad_cast(); }
       return *(T*)pointer;
     }
+    /// Bind data value
+    template <typename T> T& BlockData::bind()  {
+      this->bind(&BasicGrammar::instance<T>(),copyObject<T>,destructObject<T>);
+      return *(new(this->pointer) T());
+    }
+    /// Bind grammar and assign value
+    template <typename T> T& BlockData::set(const std::string& value)   {
+      T& ret = this->bind<T>();
+      if ( !value.empty() && !this->fromString(value) )  {
+	throw std::runtime_error("BlockData::set> Failed to bind type "+
+				 typeName(typeid(T))+" to condition data block.");
+      }
+      return ret;
+    }
     /// Bind the data of the conditions object to a given format.
-    template <typename T> Condition& Condition::bind()   {
+    template <typename T> T& Condition::bind()   {
       Object* o = access();
-      BlockData& b = o->data;
-      b.bind(&BasicGrammar::instance<T>(),copyObject<T>,destructObject<T>);
-      new(b.pointer) T();
-      if ( !o->value.empty() ) b.fromString(o->value);
-      return *this;
+      return o->data.set<T>(o->value);
     }
     /// Generic getter. Specify the exact type, not a polymorph type
     template <typename T> T& Condition::get() {
@@ -251,11 +270,18 @@ namespace DD4hep {
 
 #define DD4HEP_DEFINE_CONDITIONS_TYPE(x)            \
   namespace DD4hep { namespace Conditions  {        \
-      template Condition& Condition::bind<x>();     \
+      template x& Condition::bind<x>();           \
       template x& Condition::get<x>();              \
       template const x& Condition::get<x>() const;  \
     }}
 
+#define DD4HEP_DEFINE_EXTERNAL_CONDITIONS_TYPE(x)      \
+  namespace DD4hep { namespace Conditions  {           \
+      template <> x& Condition::bind<x>();           \
+      template <> x& Condition::get<x>();              \
+      template <> const x& Condition::get<x>() const;  \
+    }}
+
 #if defined(DD4HEP_HAVE_ALL_PARSERS)
 #define DD4HEP_DEFINE_CONDITIONS_CONT(x)        \
   DD4HEP_DEFINE_CONDITIONS_TYPE(x)              \
diff --git a/DDCore/include/XML/UriReader.h b/DDCore/include/XML/UriReader.h
index 3d6d3b53b..cc78156f5 100644
--- a/DDCore/include/XML/UriReader.h
+++ b/DDCore/include/XML/UriReader.h
@@ -34,14 +34,54 @@ namespace DD4hep {
      *  \ingroup DD4HEP_XML
      */
     class UriReader {
+    public:
+      struct UserContext {
+	UserContext() {}
+	virtual ~UserContext() {}
+      };
     public:
       /// Default constructor
       UriReader()  {}
       /// Default destructor
       virtual ~UriReader();
+      /// Access to local context
+      virtual UserContext* context()  {  return 0;  }
       /// Resolve a given URI to a string containing the data
-      virtual bool load(const std::string& system_id, std::string& data) = 0;
+      virtual bool load(const std::string& system_id, std::string& data);
+      /// Resolve a given URI to a string containing the data with context
+      virtual bool load(const std::string& system_id, UserContext* context, std::string& data) = 0;
     };
+
+    /// Class supporting to read data given a URI
+    /**
+     *  Wrapper to read XML URI using a virtual reader instance.
+     *  This implementation allows to externally chain an argument 
+     *  structure to the resolution function, which allows to set/retrieve
+     *  further arguments such as e.g. conditions IOVs.
+     *
+     *  \author   M.Frank
+     *  \version  1.0
+     *  \ingroup DD4HEP_XML
+     */
+    class UriContextReader : public UriReader  {
+    protected:
+      /// Pointer to true reader object
+      UriReader* m_reader;
+      /// Pointer to user context
+      UriReader::UserContext* m_context;
+    public:
+      /// Default constructor
+      UriContextReader(UriReader* reader, UriReader::UserContext* ctxt);
+      /// Default destructor
+      virtual ~UriContextReader();
+      /// Access to local context
+      virtual UserContext* context()  {  return m_context;  }
+      /// Resolve a given URI to a string containing the data
+      virtual bool load(const std::string& system_id, std::string& data);
+      /// Resolve a given URI to a string containing the data with context
+      virtual bool load(const std::string& system_id, UserContext* context, std::string& data);
+    };
+
   }       /* End namespace XML               */
 }         /* End namespace DD4hep            */
 #endif    /* DD4HEP_XML_URIREADER_H          */
diff --git a/DDCore/src/Conditions.cpp b/DDCore/src/Conditions.cpp
index 8356a094f..392bdc9f2 100644
--- a/DDCore/src/Conditions.cpp
+++ b/DDCore/src/Conditions.cpp
@@ -19,6 +19,8 @@
 #include "DD4hep/objects/DetectorInterna.h"
 #include "DD4hep/objects/ConditionsInterna.h"
 
+#include <climits>
+
 using namespace std;
 using namespace DD4hep::Conditions;
 
@@ -34,14 +36,88 @@ IOV::IOV() : iovType(0), keyData(0,0), optData(0)  {
 }
 
 /// Initializing constructor
-IOV::IOV(const IOVType* typ) : iovType(typ), keyData(0,0), optData(0)  {
-  type = typ ? typ->type : int(IOVType::UNKNOWN_IOV);
+IOV::IOV(const IOVType* t) : iovType(t), keyData(0,0), optData(0)  {
+  type = t ? t->type : int(IOVType::UNKNOWN_IOV);
+}
+
+/// Copy constructor
+IOV::IOV(const IOV& c) 
+  : iovType(c.iovType), keyData(c.keyData), optData(c.optData), type(c.type)
+{
+}
+
+/// Copy constructor
+IOV::IOV(const IOVType* t, const Key& k)
+  : iovType(t), keyData(k), optData(0)
+{
+  type = t ? t->type : int(IOVType::UNKNOWN_IOV);
 }
 
 /// Standard Destructor
 IOV::~IOV()  {
 }
 
+/// Set discrete IOV value
+void IOV::set(const Key& value)  {
+  keyData = value;
+}
+
+/// Set discrete IOV value
+void IOV::set(Key::first_type value)  {
+  keyData.first = keyData.second = value;
+}
+
+/// Set range IOV value
+void IOV::set(Key::first_type val_1, Key::second_type val_2)  {
+  keyData.first  = val_1;
+  keyData.second = val_2;
+}
+
+/// Set keys to unphysical values (LONG_MAX, LONG_MIN)
+void IOV::reset()  {
+  keyData.first  = LONG_MAX;
+  keyData.second = LONG_MIN;
+}
+
+/// Set keys to unphysical values (LONG_MAX, LONG_MIN)
+void IOV::invert()  {
+  Key::first_type tmp = keyData.first;
+  keyData.first  = keyData.second;
+  keyData.second = tmp;
+}
+
+void IOV::iov_intersection(const IOV& validity)   {
+  if ( !iovType )
+    *this = validity;
+  else if ( validity.keyData.first > keyData.first ) 
+    keyData.first = validity.keyData.first;
+  if ( validity.keyData.second < keyData.second )
+    keyData.second = validity.keyData.second;
+}
+
+void IOV::iov_intersection(const IOV::Key& validity)   {
+  if ( validity.first > keyData.first ) 
+    keyData.first = validity.first;
+  if ( validity.second < keyData.second )
+    keyData.second = validity.second;
+}
+
+void IOV::iov_union(const IOV& validity)   {
+  if ( !iovType )
+    *this = validity;
+  else if ( validity.keyData.first < keyData.first ) 
+    keyData.first = validity.keyData.first;
+  if ( validity.keyData.second > keyData.second )
+    keyData.second = validity.keyData.second;
+}
+
+void IOV::iov_union(const IOV::Key& validity)   {
+  if ( validity.first < keyData.first ) 
+    keyData.first = validity.first;
+  if ( validity.second > keyData.second )
+    keyData.second = validity.second;
+}
+
 /// Move the data content: 'from' will be reset to NULL
 void IOV::move(IOV& from)   {
   ::memcpy(this,&from,sizeof(IOV));
@@ -54,11 +130,28 @@ void IOV::move(IOV& from)   {
 string IOV::str()  const  {
   char text[256];
   if ( iovType )  {
-    ::snprintf(text,sizeof(text),"%s(%d):[%d-%d]",
-               iovType->name.c_str(),int(iovType->type),keyData.first, keyData.second);
+    if ( iovType->name[0] != 'e' )   {
+      ::snprintf(text,sizeof(text),"%s(%d):[%ld-%ld]",
+		 iovType->name.c_str(),int(iovType->type),keyData.first, keyData.second);
+    }
+    else if ( iovType->name == "epoch" )  {
+      time_t since = keyData.first;
+      time_t until = keyData.second;
+      char c_since[64], c_until[64];
+      struct tm time_buff;
+      ::strftime(c_since,sizeof(c_since),"%d-%m-%Y %H:%M:%S",::gmtime_r(&since,&time_buff));
+      ::strftime(c_until,sizeof(c_until),"%d-%m-%Y %H:%M:%S",::gmtime_r(&until,&time_buff));
+      ::snprintf(text,sizeof(text),"%s(%d):[%s-%s]",
+		 iovType->name.c_str(),iovType->type,
+		 c_since, c_until);
+    }
+    else   {
+      ::snprintf(text,sizeof(text),"%s(%d):[%ld-%ld]",
+		 iovType->name.c_str(),int(iovType->type),keyData.first, keyData.second);
+    }
   }
   else  {
-    ::snprintf(text,sizeof(text),"%d:[%d-%d]",type,keyData.first, keyData.second);
+    ::snprintf(text,sizeof(text),"%d:[%ld-%ld]",type,keyData.first, keyData.second);
   }
   return text;
 }
@@ -82,22 +175,29 @@ Block::~Block()   {
 }
 
 /// Create data block from string representation
-void Block::fromString(const string& rep)   {
+bool Block::fromString(const string& rep)   {
   if ( pointer && grammar )  {
-    grammar->fromString(pointer,rep);
-    return;
+    return grammar->fromString(pointer,rep);
   }
   throw runtime_error("Conditions data block is unbound. Cannot parse string representation.");
 }
 
 /// Create string representation of the data block
-string Block::str()   {
+string Block::str()  const  {
   if ( pointer && grammar )  {
     return grammar->str(pointer);
   }
   throw runtime_error("Conditions data block is unbound. Cannot create string representation.");
 }
 
+/// Access type id of the condition
+const std::type_info& Block::typeInfo() const  {
+  if ( pointer && grammar ) {
+    return grammar->type();
+  }
+  throw runtime_error("Conditions data block is unbound. Cannot determine type information!");
+}
+
 /// Initializing constructor
 Condition::Condition(const string& nam,const string& typ) : Handle<Object>()  {
   Object* o = new Object();
diff --git a/DDCore/src/ConditionsInterna.cpp b/DDCore/src/ConditionsInterna.cpp
index 60daa05ac..c5e91ffea 100644
--- a/DDCore/src/ConditionsInterna.cpp
+++ b/DDCore/src/ConditionsInterna.cpp
@@ -33,6 +33,17 @@ DD4HEP_INSTANTIATE_HANDLE_NAMED(Interna::ConditionContainer);
 
 /// Standard initializing constructor
 BlockData::BlockData() : Block(), destruct(0), copy(0), type(0)   {
+  InstanceCount::increment(this);
+}
+
+/// Copy constructor
+BlockData::BlockData(const BlockData& c) 
+  : Block(c), destruct(c.destruct), copy(c.copy), type(c.type)   {
+  grammar = 0;
+  pointer = 0;
+  this->bind(c.grammar,c.copy,c.destruct);
+  this->copy(pointer,c.pointer);
+  InstanceCount::increment(this);
 }
 
 /// Standard Destructor
@@ -43,10 +54,11 @@ BlockData::~BlockData()   {
   }
   pointer = 0;
   grammar = 0;
+  InstanceCount::decrement(this);
 }
-#if 0
+
 /// Move the data content: 'from' will be reset to NULL
-void BlockData::move(BlockData& from)   {
+bool BlockData::move(BlockData& from)   {
   pointer = from.pointer;
   grammar = from.grammar;
   ::memcpy(data,from.data,sizeof(data));
@@ -59,10 +71,37 @@ void BlockData::move(BlockData& from)   {
   from.copy = 0;
   from.pointer = 0;
   from.grammar = 0;
+  return true;
+}
+
+/// Copy constructor
+BlockData& BlockData::operator=(const BlockData& c)   {
+  if ( this != &c )  {
+    if ( this->grammar == c.grammar )   {
+      if ( destruct )  {
+	(*destruct)(pointer);
+	if ( (type&ALLOC_DATA) == ALLOC_DATA ) ::operator delete(pointer);
+      }
+      pointer = 0;
+      grammar = 0;
+    }
+    if ( this->grammar == 0 )  {
+      this->Block::operator=(c);
+      this->destruct = c.destruct;
+      this->copy = c.copy;
+      this->type = c.type;
+      this->grammar = 0;
+      this->bind(c.grammar,c.copy,c.destruct);
+      this->copy(pointer,c.pointer);
+      return *this;
+    }
+    except("Conditions","You may not bind condition data multiple times!");
+  }
+  return *this;
 }
-#endif
+
 /// Set data value
-void BlockData::bind(const BasicGrammar* g, void (*ctor)(void*,const void*), void (*dtor)(void*))   {
+bool BlockData::bind(const BasicGrammar* g, void (*ctor)(void*,const void*), void (*dtor)(void*))   {
   if ( !grammar )  {
     size_t len = g->sizeOf();
     grammar  = g;
@@ -71,7 +110,7 @@ void BlockData::bind(const BasicGrammar* g, void (*ctor)(void*,const void*), voi
     (len > sizeof(data))
       ? (pointer=::operator new(len),type=ALLOC_DATA)
       : (pointer=data,type=PLAIN_DATA);
-    return;
+    return true;
   }
   else if ( grammar == g )  {
     // We cannot ingore secondary requests for data bindings.
@@ -79,6 +118,7 @@ void BlockData::bind(const BasicGrammar* g, void (*ctor)(void*,const void*), voi
     except("Conditions","You may not bind conditions multiple times!");
   }
   typeinfoCheck(grammar->type(),g->type(),"Conditions data blocks may not be assigned.");
+  return false;
 }
 
 /// Set data value
diff --git a/DDCore/src/Evaluator/setStdMath.cpp b/DDCore/src/Evaluator/setStdMath.cpp
index fb452c518..ece8f7081 100644
--- a/DDCore/src/Evaluator/setStdMath.cpp
+++ b/DDCore/src/Evaluator/setStdMath.cpp
@@ -9,28 +9,45 @@
 
 using namespace std;
 
-static double eval_abs  (double a)           { return (a < 0) ? -a : a; }
-static double eval_min  (double a, double b) { return (a < b) ?  a : b; }
-static double eval_max  (double a, double b) { return (a > b) ?  a : b; }
-static double eval_sqrt (double a)           { return std::sqrt(a); }
-static double eval_pow  (double a, double b) { return std::pow(a,b); }
-static double eval_sin  (double a)           { return std::sin(a); }
-static double eval_cos  (double a)           { return std::cos(a); }
-static double eval_tan  (double a)           { return std::tan(a); }
-static double eval_asin (double a)           { return std::asin(a); }
-static double eval_acos (double a)           { return std::acos(a); }
-static double eval_atan (double a)           { return std::atan(a); }
-static double eval_atan2(double a, double b) { return std::atan2(a,b); }
-static double eval_sinh (double a)           { return std::sinh(a); }
-static double eval_cosh (double a)           { return std::cosh(a); }
-static double eval_tanh (double a)           { return std::tanh(a); }
-static double eval_exp  (double a)           { return std::exp(a); }
-static double eval_log  (double a)           { return std::log(a); }
-static double eval_log10(double a)           { return std::log10(a); }
-static double eval_double(double a)          { return a;              }
-static double eval_int  (double a)           { return (double)int(a); }
-static double eval_nint (double a)           { return std::floor(a); }
-static double eval_floor(double a)           { return std::floor(a); }
+static double eval_abs  (double a)           { return (a < 0) ? -a : a;        }
+static double eval_fabs (double a)           { return std::fabs(a);            }
+static double eval_fmod (double a, double b) { return std::fmod(a,b);          }
+static double eval_min  (double a, double b) { return (a < b) ?  a : b;        }
+static double eval_max  (double a, double b) { return (a > b) ?  a : b;        }
+static double eval_sqrt (double a)           { return std::sqrt(a);            }
+static double eval_cbrt (double a)           { return std::cbrt(a);            }
+static double eval_pow  (double a, double b) { return std::pow(a,b);           }
+static double eval_sin  (double a)           { return std::sin(a);             }
+static double eval_cos  (double a)           { return std::cos(a);             }
+static double eval_tan  (double a)           { return std::tan(a);             }
+static double eval_asin (double a)           { return std::asin(a);            }
+static double eval_acos (double a)           { return std::acos(a);            }
+static double eval_atan (double a)           { return std::atan(a);            }
+static double eval_atan2(double a, double b) { return std::atan2(a,b);         }
+static double eval_sinh (double a)           { return std::sinh(a);            }
+static double eval_cosh (double a)           { return std::cosh(a);            }
+static double eval_tanh (double a)           { return std::tanh(a);            }
+static double eval_exp  (double a)           { return std::exp(a);             }
+static double eval_exp2 (double a)           { return std::exp2(a);            }
+static double eval_exp10(double a)           { return ::exp10(a);              }
+static double eval_expm1(double a)           { return std::expm1(a);           }
+static double eval_log  (double a)           { return std::log(a);             }
+static double eval_logb (double a)           { return std::logb(a);            }
+static double eval_log10(double a)           { return std::log10(a);           }
+static double eval_log1p(double a)           { return std::log1p(a);           }
+static double eval_hypot(double a, double b) { return std::hypot(a,b);         }
+static double eval_erf  (double a)           { return std::erf(a);             }
+static double eval_erfc (double a)           { return std::erfc(a);            }
+static double eval_gamma(double a)           { return ::gamma(a);              }
+static double eval_double(double a)          { return a;                       }
+static double eval_int  (double a)           { return (double)int(a);          }
+static double eval_nint (double a)           { return std::floor(a);           }
+static double eval_floor(double a)           { return std::floor(a);           }
+static double eval_round(double a)           { return std::round(a);           }
+static double eval_ceil (double a)           { return std::ceil(a);            }
+static double eval_isnan(double a)           { return std::isnan(a);           }
+static double eval_isinf(double a)           { return std::isinf(a);           }
+static double eval_nearbyint(double a)       { return std::nearbyint(a);       }
 
 namespace XmlTools {
 
@@ -54,28 +71,45 @@ namespace XmlTools {
 
     //   S E T   S T A N D A R D   F U N C T I O N S
 
-    setFunction("floor", eval_floor);
-    setFunction("double",eval_double);
-    setFunction("int",   eval_int);
-    setFunction("nint",  eval_nint);
-    setFunction("abs",   eval_abs);
-    setFunction("min",   eval_min);
-    setFunction("max",   eval_max);
-    setFunction("sqrt",  eval_sqrt);
-    setFunction("pow",   eval_pow);
-    setFunction("sin",   eval_sin);
-    setFunction("cos",   eval_cos);
-    setFunction("tan",   eval_tan);
-    setFunction("asin",  eval_asin);
-    setFunction("acos",  eval_acos);
-    setFunction("atan",  eval_atan);
-    setFunction("atan2", eval_atan2);
-    setFunction("sinh",  eval_sinh);
-    setFunction("cosh",  eval_cosh);
-    setFunction("tanh",  eval_tanh);
-    setFunction("exp",   eval_exp);
-    setFunction("log",   eval_log);
-    setFunction("log10", eval_log10);
+    setFunction("abs",        eval_abs);
+    setFunction("fabs",       eval_fabs);
+    setFunction("fmod",       eval_fmod);
+    setFunction("min",        eval_min);
+    setFunction("max",        eval_max);
+    setFunction("sqrt",       eval_sqrt);
+    setFunction("cbrt",       eval_cbrt);
+    setFunction("pow",        eval_pow);
+    setFunction("sin",        eval_sin);
+    setFunction("cos",        eval_cos);
+    setFunction("tan",        eval_tan);
+    setFunction("asin",       eval_asin);
+    setFunction("acos",       eval_acos);
+    setFunction("atan",       eval_atan);
+    setFunction("atan2",      eval_atan2);
+    setFunction("sinh",       eval_sinh);
+    setFunction("cosh",       eval_cosh);
+    setFunction("tanh",       eval_tanh);
+    setFunction("exp",        eval_exp);
+    setFunction("exp2",       eval_exp2);
+    setFunction("exp10",      eval_exp10);
+    setFunction("expm1",      eval_expm1);
+    setFunction("log",        eval_log);
+    setFunction("logb",       eval_logb);
+    setFunction("log10",      eval_log10);
+    setFunction("log1p",      eval_log1p);
+    setFunction("hypot",      eval_hypot);
+    setFunction("erf",        eval_erf);
+    setFunction("erfc",       eval_erfc);
+    setFunction("gamma",      eval_gamma);
+    setFunction("double",     eval_double);
+    setFunction("int",        eval_int);
+    setFunction("nint",       eval_nint);
+    setFunction("floor",      eval_floor);
+    setFunction("round",      eval_round);
+    setFunction("ceil",       eval_ceil);
+    setFunction("isnan",      eval_isnan);
+    setFunction("isinf",      eval_isinf);
+    setFunction("nearbyint",  eval_nearbyint);
   }
 
 } // namespace XmlTools
diff --git a/DDCore/src/LCDDImp.cpp b/DDCore/src/LCDDImp.cpp
index b116a8c79..d62e5fd57 100644
--- a/DDCore/src/LCDDImp.cpp
+++ b/DDCore/src/LCDDImp.cpp
@@ -535,6 +535,7 @@ void LCDDImp::init() {
   }
 }
 
+/// Read any geometry description or alignment file
 void LCDDImp::fromXML(const string& xmlfile, LCDDBuildType build_type) {
   TypePreserve build_type_preserve(m_buildType = build_type);
 #if DD4HEP_USE_PYROOT
@@ -543,10 +544,16 @@ void LCDDImp::fromXML(const string& xmlfile, LCDDBuildType build_type) {
   cmd = "lcdd.fromXML('" + xmlfile + "')";
   TPython::Exec(cmd.c_str());
 #else
-  processXML(xmlfile);
+  processXML(xmlfile,0);
 #endif
 }
 
+/// Read any geometry description or alignment file with external XML entity resolution
+void LCDDImp::fromXML(const std::string& fname, UriReader* entity_resolver, LCDDBuildType build_type)  {
+  TypePreserve build_type_preserve(m_buildType = build_type);
+  processXML(fname,entity_resolver);
+}
+
 void LCDDImp::dump() const {
   TGeoManager* mgr = m_manager;
   mgr->SetVisLevel(4);
diff --git a/DDCore/src/LCDDImp.h b/DDCore/src/LCDDImp.h
index deea2400d..025b85669 100644
--- a/DDCore/src/LCDDImp.h
+++ b/DDCore/src/LCDDImp.h
@@ -81,6 +81,11 @@ namespace DD4hep {
       /// Read any XML file
       virtual void fromXML(const std::string& fname, LCDDBuildType type = BUILD_DEFAULT);
 
+      /// Read any geometry description or alignment file with external XML entity resolution
+      virtual void fromXML(const std::string& fname,
+			   UriReader* entity_resolver,
+			   LCDDBuildType type = BUILD_DEFAULT);
+
       virtual void dump() const;
 
       /// Manipulate geometry using facroy converter
diff --git a/DDCore/src/LCDDLoad.cpp b/DDCore/src/LCDDLoad.cpp
index d298825a3..8936dd412 100644
--- a/DDCore/src/LCDDLoad.cpp
+++ b/DDCore/src/LCDDLoad.cpp
@@ -43,9 +43,10 @@ LCDDLoad::LCDDLoad(Geometry::LCDD* lcdd) : m_lcdd(lcdd)  {
 LCDDLoad::~LCDDLoad() {
 }
 
-void LCDDLoad::processXML(const string& xmlfile) {
+/// Process XML unit and adopt all data from source structure.
+void LCDDLoad::processXML(const string& xmlfile, XML::UriReader* entity_resolver) {
   try {
-    XML::DocumentHolder doc(XML::DocumentHandler().load(xmlfile));
+    XML::DocumentHolder doc(XML::DocumentHandler().load(xmlfile,entity_resolver));
     XML::Handle_t handle = doc.root();
     processXMLElement(xmlfile,handle);
   }
@@ -61,10 +62,11 @@ void LCDDLoad::processXML(const string& xmlfile) {
 }
 
 
-void LCDDLoad::processXML(const XML::Handle_t& base, const string& xmlfile) {
+/// Process XML unit and adopt all data from source structure.
+void LCDDLoad::processXML(const XML::Handle_t& base, const string& xmlfile, XML::UriReader* entity_resolver) {
   try {
     XML::Strng_t xml(xmlfile);
-    XML::DocumentHolder doc(XML::DocumentHandler().load(base,xml));
+    XML::DocumentHolder doc(XML::DocumentHandler().load(base,xml,entity_resolver));
     XML::Handle_t handle = doc.root();
     processXMLElement(xmlfile,handle);
   }
@@ -79,6 +81,7 @@ void LCDDLoad::processXML(const XML::Handle_t& base, const string& xmlfile) {
   }
 }
 
+/// Process a given DOM (sub-) tree
 void LCDDLoad::processXMLElement(const std::string& xmlfile, const XML::Handle_t& xml_root) {
   string tag = xml_root.tag();
   string type = tag + "_XML_reader";
@@ -98,6 +101,7 @@ void LCDDLoad::processXMLElement(const std::string& xmlfile, const XML::Handle_t
   }
 }
 
+/// Process a given DOM (sub-) tree
 void LCDDLoad::processXMLElement(const XML::Handle_t& xml_root, LCDDBuildType /* type */) {
   string tag = xml_root.tag();
   string type = tag + "_XML_reader";
@@ -113,7 +117,7 @@ void LCDDLoad::processXMLElement(const XML::Handle_t& xml_root, LCDDBuildType /*
     }
   }
   result = *(long*) result;
-  if (result != 1) {
+  if (result != 1)   {
     throw runtime_error("DD4hep: Failed to parse the XML element with tag " 
 			+ tag + " with the plugin " + type);
   }
diff --git a/DDCore/src/Readout.cpp b/DDCore/src/Readout.cpp
index c1b4875d8..48b7b3cc3 100644
--- a/DDCore/src/Readout.cpp
+++ b/DDCore/src/Readout.cpp
@@ -23,7 +23,6 @@
 using namespace std;
 using namespace DD4hep;
 using namespace DD4hep::Geometry;
-using dd4hep::mm;
 
 /// Copy constructor
 HitCollection::HitCollection(const HitCollection& c)
@@ -32,7 +31,7 @@ HitCollection::HitCollection(const HitCollection& c)
 }
 
 /// Initializing constructor
-HitCollection::HitCollection(const std::string& n, const std::string& k, long k_min, long k_max)  
+HitCollection::HitCollection(const string& n, const string& k, long k_min, long k_max)  
   : name(n), key(k), key_min(k_min), key_max(k_max)
 {
 }
@@ -53,9 +52,18 @@ Readout::Readout(const string& nam) {
   assign(new ReadoutObject(), nam, "readout");
 }
 
+/// Access number of hit collections
+size_t Readout::numCollections() const   {
+  if ( isValid() ) {
+    Object& ro = object<Object>();
+    return ro.hits.size();
+  }
+  throw runtime_error("DD4hep: Readout::numCollections: Cannot access object data [Invalid Handle]");
+}
+
 /// Access names of hit collections
-std::vector<std::string> Readout::collectionNames()  const   {
-  std::vector<std::string> colls;
+vector<string> Readout::collectionNames()  const   {
+  vector<string> colls;
   if ( isValid() ) {
     Object& ro = object<Object>();
     if ( !ro.hits.empty() )  {
@@ -68,8 +76,8 @@ std::vector<std::string> Readout::collectionNames()  const   {
 }
 
 /// Access hit collections
-std::vector<const HitCollection*> Readout::collections()  const   {
-  std::vector<const HitCollection*> colls;
+vector<const HitCollection*> Readout::collections()  const   {
+  vector<const HitCollection*> colls;
   if ( isValid() ) {
     Object& ro = object<Object>();
     if ( !ro.hits.empty() )  {
@@ -78,7 +86,7 @@ std::vector<const HitCollection*> Readout::collections()  const   {
     }
     return colls;
   }
-  throw runtime_error("DD4hep: Readout::collectionsNames: Cannot access object data [Invalid Handle]");
+  throw runtime_error("DD4hep: Readout::collections: Cannot access object data [Invalid Handle]");
 }
 
 /// Assign IDDescription to readout structure
diff --git a/DDCore/src/XML/DocumentHandler.cpp b/DDCore/src/XML/DocumentHandler.cpp
index 70d311711..d959d9d8b 100644
--- a/DDCore/src/XML/DocumentHandler.cpp
+++ b/DDCore/src/XML/DocumentHandler.cpp
@@ -479,7 +479,7 @@ Document DocumentHandler::load(const std::string& fname, UriReader* reader) cons
 /// Load XML file and parse it using URI resolver to read data.
 Document DocumentHandler::load(Handle_t base, const XmlChar* fname, UriReader* reader) const  {
   string path = system_path(base, fname);
-  return load(path,0);
+  return load(path,reader);
 }
 
 /// Parse a standalong XML string into a document.
diff --git a/DDCore/src/XML/UriReader.cpp b/DDCore/src/XML/UriReader.cpp
index 536627b19..9a4342e04 100644
--- a/DDCore/src/XML/UriReader.cpp
+++ b/DDCore/src/XML/UriReader.cpp
@@ -18,3 +18,28 @@
 /// Default destructor
 DD4hep::XML::UriReader::~UriReader()   {
 }
+
+/// Resolve a given URI to a string containing the data
+bool DD4hep::XML::UriReader::load(const std::string& system_id, std::string& data)   {
+  return this->load(system_id, context(), data);
+}
+
+/// Default constructor
+DD4hep::XML::UriContextReader::UriContextReader(UriReader* reader, UriReader::UserContext* ctxt)
+  : m_reader(reader), m_context(ctxt)
+{
+}
+
+/// Default destructor
+DD4hep::XML::UriContextReader::~UriContextReader()   {
+}
+
+/// Resolve a given URI to a string containing the data
+bool DD4hep::XML::UriContextReader::load(const std::string& system_id, std::string& data)   {
+  return m_reader->load(system_id, context(), data);
+}
+
+/// Resolve a given URI to a string containing the data
+bool DD4hep::XML::UriContextReader::load(const std::string& system_id, UserContext* ctxt, std::string& data)   {
+  return m_reader->load(system_id, ctxt, data);
+}
diff --git a/DDCore/src/plugins/Compact2Objects.cpp b/DDCore/src/plugins/Compact2Objects.cpp
index e308ef7ae..b307fefd6 100644
--- a/DDCore/src/plugins/Compact2Objects.cpp
+++ b/DDCore/src/plugins/Compact2Objects.cpp
@@ -50,18 +50,18 @@ namespace DD4hep {
     struct AlignmentFile;
     struct DetElementInclude {};
   }
-  template <> void Converter<Plugin>::operator()(xml_h e) const;
-  template <> void Converter<Constant>::operator()(xml_h e) const;
-  template <> void Converter<Material>::operator()(xml_h e) const;
-  template <> void Converter<Atom>::operator()(xml_h e) const;
-  template <> void Converter<VisAttr>::operator()(xml_h e) const;
-  template <> void Converter<AlignmentEntry>::operator()(xml_h e) const;
-  template <> void Converter<Region>::operator()(xml_h e) const;
-  template <> void Converter<Readout>::operator()(xml_h e) const;
-  template <> void Converter<Segmentation>::operator()(xml_h e) const;
-  template <> void Converter<LimitSet>::operator()(xml_h e) const;
-  template <> void Converter<Property>::operator()(xml_h e) const;
-  template <> void Converter<CartesianField>::operator()(xml_h e) const;
+  template <> void Converter<Plugin>::operator()(xml_h element) const;
+  template <> void Converter<Constant>::operator()(xml_h element) const;
+  template <> void Converter<Material>::operator()(xml_h element) const;
+  template <> void Converter<Atom>::operator()(xml_h element) const;
+  template <> void Converter<VisAttr>::operator()(xml_h element) const;
+  template <> void Converter<AlignmentEntry>::operator()(xml_h element) const;
+  template <> void Converter<Region>::operator()(xml_h element) const;
+  template <> void Converter<Readout>::operator()(xml_h element) const;
+  template <> void Converter<Segmentation>::operator()(xml_h element) const;
+  template <> void Converter<LimitSet>::operator()(xml_h element) const;
+  template <> void Converter<Property>::operator()(xml_h element) const;
+  template <> void Converter<CartesianField>::operator()(xml_h element) const;
   template <> void Converter<SensitiveDetector>::operator()(xml_h element) const;
   template <> void Converter<DetElement>::operator()(xml_h element) const;
   template <> void Converter<GdmlFile>::operator()(xml_h element) const;
@@ -1018,15 +1018,25 @@ template <> void Converter<Compact>::operator()(xml_h element) const {
 }
 
 #ifdef _WIN32
-template Converter<Atom>;
-template Converter<Compact>;
-template Converter<Readout>;
-template Converter<VisAttr>;
-template Converter<Constant>;
-template Converter<LimitSet>;
-template Converter<Material>;
-template Converter<DetElement>;
-template Converter<AlignmentEntry>;
-template Converter<SensitiveDetector>;
-template Converter<CartesianField>;
+  template Converter<Plugin>;
+  template Converter<Constant>;
+  template Converter<Material>;
+  template Converter<Atom>;
+  template Converter<VisAttr>;
+  template Converter<AlignmentEntry>;
+  template Converter<Region>;
+  template Converter<Readout>;
+  template Converter<Segmentation>;
+  template Converter<LimitSet>;
+  template Converter<Property>;
+  template Converter<CartesianField>;
+  template Converter<SensitiveDetector>;
+  template Converter<DetElement>;
+  template Converter<GdmlFile>;
+  template Converter<XMLFile>;
+  template Converter<AlignmentFile>;
+  template Converter<Header>;
+  template Converter<DetElementInclude>;
+  template Converter<Compact>;
+
 #endif
diff --git a/DDCore/src/plugins/StandardPlugins.cpp b/DDCore/src/plugins/StandardPlugins.cpp
index 632edcba8..ff08b6379 100644
--- a/DDCore/src/plugins/StandardPlugins.cpp
+++ b/DDCore/src/plugins/StandardPlugins.cpp
@@ -211,58 +211,59 @@ static long dump_volume_tree(LCDD& lcdd, int argc, char** argv) {
     bool m_printVolIDs;
     bool m_printPositions;
     bool m_printSensitivesOnly;
-    Actor(int argc, char** argv) 
+    Actor(int ac, char** av) 
       : m_printVolIDs(false), m_printPositions(false), m_printSensitivesOnly(false)
     {
-      for(int i=0; i<argc; ++i)  {
-	char c = ::tolower(argv[i][0]);
-	if ( c == 'v' ) m_printVolIDs = true;
-	else if ( c == 'p' ) m_printPositions = true;
-	else if ( c == 's' ) m_printSensitivesOnly = true;
+      for(int i=0; i<ac; ++i)  {
+        char c = ::tolower(av[i][0]);
+        if ( c == 'v' ) m_printVolIDs = true;
+        else if ( c == 'p' ) m_printPositions = true;
+        else if ( c == 's' ) m_printSensitivesOnly = true;
       }
     }
+
     long dump(TGeoNode* ideal, TGeoNode* aligned,int level, VIDs volids) const {
       char fmt[128];
       string opt_info;
       PlacedVolume pv(ideal);
       bool sensitive = false;
       if ( m_printPositions || m_printVolIDs )  {
-	stringstream log;
-	if ( m_printPositions )  {
-	  const double* trans = ideal->GetMatrix()->GetTranslation();
-	  ::snprintf(fmt, sizeof(fmt), "Pos: (%f,%f,%f) ",trans[0],trans[1],trans[2]);
-	  log << fmt;
-	}
-	// Top level volume! have no volume ids
-	if ( m_printVolIDs && ideal && ideal->GetMotherVolume() )  {
-	  VIDs vid = pv.volIDs();
-	  if ( !vid.empty() )  {
-	    sensitive = true;
-	    log << " VolID: ";
-	    volids.std::vector<VID>::insert(volids.end(),vid.begin(),vid.end());
-	    for(VIDs::const_iterator i=volids.begin(); i!=volids.end(); ++i)  {
-	      ::snprintf(fmt, sizeof(fmt), "%s:%2d ",(*i).first.c_str(), (*i).second);
-	      log << fmt;
-	    }
-	  }
-	}
-	opt_info = log.str();
+        stringstream log;
+        if ( m_printPositions )  {
+          const double* trans = ideal->GetMatrix()->GetTranslation();
+          ::snprintf(fmt, sizeof(fmt), "Pos: (%f,%f,%f) ",trans[0],trans[1],trans[2]);
+          log << fmt;
+        }
+        // Top level volume! have no volume ids
+        if ( m_printVolIDs && ideal && ideal->GetMotherVolume() )  {
+          VIDs vid = pv.volIDs();
+          if ( !vid.empty() )  {
+            sensitive = true;
+            log << " VolID: ";
+            volids.std::vector<VID>::insert(volids.end(),vid.begin(),vid.end());
+            for(VIDs::const_iterator i=volids.begin(); i!=volids.end(); ++i)  {
+              ::snprintf(fmt, sizeof(fmt), "%s:%2d ",(*i).first.c_str(), (*i).second);
+              log << fmt;
+            }
+          }
+        }
+        opt_info = log.str();
       }
       TGeoVolume* volume = ideal->GetVolume();
       if ( !m_printSensitivesOnly || (m_printSensitivesOnly && sensitive) )  {
-	if ( ideal == aligned )  {
-	  ::snprintf(fmt,sizeof(fmt),"%03d %%-%ds %%s (%%s: %%s) \t[%p] %%s",
-		     level+1,2*level+1,(void*)ideal);
-	}
-	else  {
-	  ::snprintf(fmt,sizeof(fmt),"%03d %%-%ds %%s (%%s: %%s) Ideal:%p Aligned:%p %%s",
-		     level+1,2*level+1,(void*)ideal,(void*)aligned);
-	}
-	printout(INFO,"+++",fmt,"",
-		 aligned->GetName(),
-		 volume->GetTitle(),
-		 volume->GetShape()->IsA()->GetName(),
-		 opt_info.c_str());
+        if ( ideal == aligned )  {
+          ::snprintf(fmt,sizeof(fmt),"%03d %%-%ds %%s (%%s: %%s) \t[%p] %%s",
+                     level+1,2*level+1,(void*)ideal);
+        }
+        else  {
+          ::snprintf(fmt,sizeof(fmt),"%03d %%-%ds %%s (%%s: %%s) Ideal:%p Aligned:%p %%s",
+                     level+1,2*level+1,(void*)ideal,(void*)aligned);
+        }
+        printout(INFO,"+++",fmt,"",
+                 aligned->GetName(),
+                 volume->GetTitle(),
+                 volume->GetShape()->IsA()->GetName(),
+                 opt_info.c_str());
       }
       for (Int_t idau = 0, ndau = aligned->GetNdaughters(); idau < ndau; ++idau)  {
         TGeoNode*   ideal_daughter   = ideal->GetDaughter(idau);
diff --git a/UtilityApps/src/dd4hep_python.cpp b/UtilityApps/src/dd4hep_python.cpp
deleted file mode 100644
index 4e1a826f2..000000000
--- a/UtilityApps/src/dd4hep_python.cpp
+++ /dev/null
@@ -1,51 +0,0 @@
-// $Id$
-//==========================================================================
-//  AIDA Detector description implementation for LCD
-//--------------------------------------------------------------------------
-// Copyright (C) Organisation europeenne pour la Recherche nucleaire (CERN)
-// All rights reserved.
-//
-// For the licensing terms see $DD4hepINSTALL/LICENSE.
-// For the list of contributors see $DD4hepINSTALL/doc/CREDITS.
-//
-// Author     : M.Frank
-//
-//==========================================================================
-#include "TSystem.h"
-#include "TInterpreter.h"
-#include "DDG4/Python/DDPython.h"
-#include <vector>
-
-static int load_libs(const std::vector<char*>& libs)  {
-  for(size_t i=0; i<libs.size(); ++i)   {
-    int ret = gSystem->Load(libs[i]);
-    if ( 0 != ret )   {
-      ::printf("+++ Failed to load library: %s [ignored]\n",libs[i]);
-      return ret;
-    }
-    else  {
-      ::printf("+++ Successfully loaded library: %s\n",libs[i]);
-    }
-  }
-  return 0;
-}
-
-int main(int argc, char** argv)   {
-  std::vector<char*> args;
-  std::vector<char*> libs;
-  int first_arg = 0;
-  int ret;
-
-  for(int i=first_arg; i<argc; ++i)  {
-    if ( 0 == ::strcmp(argv[i],"-L") )
-      libs.push_back(argv[++i]);
-    else
-      args.push_back(argv[i]);
-  }
-  if ( 0 == (ret=load_libs(libs)) )   {
-    ::printf("+++ Calling now Py_Main...\n");
-    ret = DD4hep::DDPython::run_interpreter(args.size(), &args[0]);
-    //::printf("+++ Return code Py_Main=%d\n",ret);
-  }
-  return ret;
-}
-- 
GitLab