diff --git a/Control/AthenaConfiguration/CMakeLists.txt b/Control/AthenaConfiguration/CMakeLists.txt
index 9f1ab05d497938c6a9f6c6c4f9ad97ec76fd7aea..d7316c7fbbd39f9ca49e3c3fbe083b38fa645c67 100644
--- a/Control/AthenaConfiguration/CMakeLists.txt
+++ b/Control/AthenaConfiguration/CMakeLists.txt
@@ -14,7 +14,7 @@ atlas_install_scripts( share/confTool.py python/iconfTool/iconfTool )
 atlas_install_data( share/*.ref )
 
 atlas_add_test( ComponentAccumulatorTest
-   SCRIPT python -m unittest -v AthenaConfiguration.ComponentAccumulator 
+   SCRIPT python -m unittest -v AthenaConfiguration.ComponentAccumulatorTest
    POST_EXEC_SCRIPT nopost.sh )
 
 atlas_add_test( UnifyPropertiesTest
diff --git a/Control/AthenaConfiguration/python/ComponentAccumulator.py b/Control/AthenaConfiguration/python/ComponentAccumulator.py
index 40c4b80b7cb06f21ae8df50de6e59ce698e2a535..6c44b4f06cd1a6fa4f89dc6dffd4a58ed7c23613 100644
--- a/Control/AthenaConfiguration/python/ComponentAccumulator.py
+++ b/Control/AthenaConfiguration/python/ComponentAccumulator.py
@@ -5,7 +5,6 @@ from AthenaCommon.Configurable import Configurable,ConfigurableService,Configura
 from AthenaCommon.CFElements import isSequence,findSubSequence,findAlgorithm,flatSequencers,findOwningSequence,checkSequenceConsistency
 from AthenaCommon.AlgSequence import AthSequencer
 
-from AthenaConfiguration.AthConfigFlags import AthConfigFlags
 import GaudiKernel.GaudiHandles as GaudiHandles
 from GaudiKernel.GaudiHandles import PublicToolHandle, PublicToolHandleArray, ServiceHandle, PrivateToolHandle, PrivateToolHandleArray
 import ast
@@ -40,6 +39,7 @@ class ComponentAccumulator(object):
 
         #To check if this accumulator was merged:
         self._wasMerged=False
+        self._isMergable=True
 
 
     def empty(self):
@@ -465,7 +465,9 @@ class ComponentAccumulator(object):
 
         if not isinstance(other,ComponentAccumulator):
             raise TypeError("Attempt merge wrong type %s. Only instances of ComponentAccumulator can be added" % type(other).__name__)
-
+        
+        if not other._isMergable:
+            raise ConfigurationError("Attempted to merge the accumulator that was unsafely manipulated (likely with foreach_component, ...)")
 
         if not Configurable.configurableRun3Behavior:
             raise ConfigurationError("discoverd Configurable.configurableRun3Behavior=False while working woth ComponentAccumulator")
@@ -603,6 +605,7 @@ class ComponentAccumulator(object):
     def store(self,outfile,nEvents=10,useBootStrapFile=True,threaded=False):
         from AthenaCommon.Utils.unixtools import find_datafile
         import pickle
+        self._isMergable = True # this is CA we store, it is ok it is not mergable
         if useBootStrapFile:
             import glob
             # first load basics from the bootstrap-pickle
@@ -738,7 +741,6 @@ class ComponentAccumulator(object):
         self._wasMerged=True
 
     def createApp(self,OutputLevel=3):
-        log = logging.getLogger("ComponentAccumulator")
         self._wasMerged=True
         from Gaudi.Main import BootstrapHelper
         bsh=BootstrapHelper()
@@ -774,14 +776,14 @@ class ComponentAccumulator(object):
             name=comp.getJobOptName()
             for k, v in comp.getValuedProperties().items():
                 if isinstance(v,Configurable):
-                    log.debug("Adding "+name+"."+k+" = "+v.getFullName())
+                    self._msg.debug("Adding "+name+"."+k+" = "+v.getFullName())
                     bsh.addPropertyToCatalogue(jos,name,k,v.getFullName())
                     addCompToJos(v)
                 elif isinstance(v,GaudiHandles.GaudiHandleArray):
                     bsh.addPropertyToCatalogue(jos,name,k,str([ v1.getFullName() for v1 in v ]))
                 else:
                     if not isSequence(comp) and k!="Members": #This property his handled separatly
-                        log.debug("Adding "+name+"."+k+" = "+str(v))
+                        self._msg.debug("Adding "+name+"."+k+" = "+str(v))
                         bsh.addPropertyToCatalogue(jos,name,k,str(v))
                     pass
                 pass
@@ -796,7 +798,7 @@ class ComponentAccumulator(object):
 
         #Add tree of algorithm sequences:
         for seqName, algoList in flatSequencers( self._sequence ).iteritems():
-            log.debug("Members of %s : %s" % (seqName,str([alg.getFullName() for alg in algoList])))
+            self._msg.debug("Members of %s : %s" % (seqName,str([alg.getFullName() for alg in algoList])))
             bsh.addPropertyToCatalogue(jos,seqName,"Members",str( [alg.getFullName() for alg in algoList]))
             for alg in algoList:
                 addCompToJos(alg)
@@ -821,7 +823,6 @@ class ComponentAccumulator(object):
 
 
     def run(self,maxEvents=None,OutputLevel=3):
-        log = logging.getLogger("ComponentAccumulator")
         app = self.createApp (OutputLevel)
 
         #Determine maxEvents
@@ -831,22 +832,22 @@ class ComponentAccumulator(object):
             else:
                 maxEvents=-1
 
-        print "INITIALIZE STEP"
+        self._msg.info("INITIALIZE STEP")
         sc = app.initialize()
         if not sc.isSuccess():
-            log.error("Failed to initialize AppMgr")
+            self._msg.error("Failed to initialize AppMgr")
             return sc
 
         app.printAlgsSequences() #could be removed later ....
 
         sc = app.start()
         if not sc.isSuccess():
-            log.error("Failed to start AppMgr")
+            self._msg.error("Failed to start AppMgr")
             return sc
 
         sc = app.run(maxEvents)
         if not sc.isSuccess():
-            log.error("Failure running application")
+            self._msg.error("Failure running application")
             return sc
 
         app.stop().ignore()
@@ -856,6 +857,27 @@ class ComponentAccumulator(object):
         sc1 = app.terminate()
         return sc1
 
+    def foreach_component(self, path):
+        """ Utility to set properties of components using wildcards
+        
+        Example:
+        forcomps(ca, "*/HLTTop/*/*Hypo*").OutputLevel=VERBOSE
+        
+        The compoments name & locations in the CF tree are translated into the unix like path. 
+        Components of matching path are taken under consideration in setting the property.
+        If the property is set succesfully an INFO message is printed. Else, a warning is printed.      
+        
+        The convention for path of nested components is as follows:
+        Sequencer - only the name is used in the path
+        Algorithm - full name - type/instance_name (aka full name) is used
+        PrivateTools - the name of the property + the type/instance_name are added
+        PublicTools - are located under ToolSvc/ and type/instance_name is used
+        Services - located under SvcMgr/ and type/instance_name is used
+        """
+        from AthenaConfiguration.PropSetterProxy import PropSetterProxy
+        self._isMergable=False
+        return PropSetterProxy(self, path)
+
 
 
 def CAtoGlobalWrapper(cfgmethod,flags):
@@ -865,304 +887,3 @@ def CAtoGlobalWrapper(cfgmethod,flags):
 
      result.appendToGlobals()
      return
-
-
-
-# self test
-import unittest
-
-class TestComponentAccumulator( unittest.TestCase ):
-    def setUp(self):
-
-        Configurable.configurableRun3Behavior+=1
-        # trivial case without any nested sequences
-        from AthenaCommon.Configurable import ConfigurablePyAlgorithm # guinea pig algorithms
-        from AthenaCommon.CFElements import seqAND, parOR
-        from AthenaCommon.Logging import log
-        from AthenaCommon.Constants import DEBUG
-
-        log.setLevel(DEBUG)
-
-        dummyCfgFlags=AthConfigFlags()
-        dummyCfgFlags.lock()
-
-        class Algo(ConfigurablePyAlgorithm):
-            def __init__(self, name):
-                super( ConfigurablePyAlgorithm, self ).__init__( name )
-
-        def AlgsConf1(flags):
-            acc = ComponentAccumulator()
-            a1=Algo("Algo1")
-            a2=Algo("Algo2")
-            return acc,[a1,a2]
-
-
-        def AlgsConf2(flags):
-            acc = ComponentAccumulator()
-            result,algs=AlgsConf1( flags )
-            acc.merge(result)
-            algs.append(Algo("Algo3"))
-            return acc,algs
-
-        acc = ComponentAccumulator()
-
-        # top level algs
-        acc1,algs=AlgsConf2(dummyCfgFlags)
-        acc.merge(acc1)
-        acc.addEventAlgo(algs)
-
-        def AlgsConf3(flags):
-            acc = ComponentAccumulator()
-            na1=Algo("NestedAlgo1")
-            return acc,na1
-
-        def AlgsConf4(flags):
-            acc,na1= AlgsConf3( flags )
-            NestedAlgo2 = Algo("NestedAlgo2")
-            NestedAlgo2.OutputLevel=7
-            return acc,na1,NestedAlgo2
-
-        acc.addSequence( seqAND("Nest") )
-        acc.addSequence( seqAND("subSequence1"), parentName="Nest" )
-        acc.addSequence( parOR("subSequence2"), parentName="Nest" )
-
-        acc.addSequence( seqAND("sub2Sequence1"), parentName="subSequence1")
-        acc.addSequence( seqAND("sub3Sequence1"), parentName="subSequence1")
-        acc.addSequence( seqAND("sub4Sequence1"), parentName="subSequence1")
-
-        accNA1=AlgsConf4(dummyCfgFlags)
-        acc.merge(accNA1[0])
-        acc.addEventAlgo(accNA1[1:],"sub2Sequence1" )
-        acc.store(open("testFile.pkl", "w"))
-        self.acc = acc
-
-
-    def test_algorihmsAreAdded( self ):
-        self.assertEqual( findAlgorithm( self.acc.getSequence(), "Algo1", 1).name(), "Algo1", "Algorithm not added to a top sequence" )
-        self.assertEqual( findAlgorithm( self.acc.getSequence(), "Algo2", 1).name(),  "Algo2", "Algorithm not added to a top sequence" )
-        self.assertEqual( findAlgorithm( self.acc.getSequence(), "Algo3", 1).name(), "Algo3", "Algorithm not added to a top sequence" )
-
-    def test_sequencesAreAdded( self ):
-        self.assertIsNotNone( self.acc.getSequence("subSequence1" ), "Adding sub-sequence failed" )
-        self.assertIsNotNone( self.acc.getSequence("subSequence2" ), "Adding sub-sequence failed" )
-        self.assertIsNotNone( self.acc.getSequence("sub2Sequence1"), "Adding sub-sequence failed" )
-        self.assertIsNotNone( findSubSequence( self.acc.getSequence("subSequence1"), "sub2Sequence1"), "Adding sub-sequence done in a wrong place" )
-
-    def test_algorithmsInNestedSequences( self ):
-        self.assertIsNotNone( findAlgorithm( self.acc.getSequence(), "NestedAlgo1" ), "Algorithm added to nested sequence" )
-        self.assertIsNotNone( findAlgorithm( self.acc.getSequence(), "NestedAlgo1", 1 ) is None, "Algorithm mistakenly in top sequence" )
-        self.assertIsNotNone( findAlgorithm( findSubSequence( self.acc.getSequence(), "sub2Sequence1"), "NestedAlgo1", 1 ), "Algorithm not in right sequence" )
-
-
-    def test_readBackConfiguration( self ):
-        import pickle
-        with open( "testFile.pkl" ) as f:
-            s = pickle.load( f )
-            self.assertIsNotNone( s, "The pickle has no content")
-
-class TestHLTCF( unittest.TestCase ):
-    def runTest( self ):
-        # replicate HLT issue, it occured because the sequnces were recorded in the order of storing in the dict and thus the
-        # some of them (in this case hltSteps) did not have properties recorded
-        from AthenaCommon.CFElements import seqAND, seqOR, parOR
-        from AthenaCommon.Configurable import ConfigurablePyAlgorithm # guinea pig algorithms
-        Configurable.configurableRun3Behavior=1
-        acc = ComponentAccumulator()
-        acc.addSequence( seqOR("hltTop") )
-        algos2 = ConfigurablePyAlgorithm( "RecoAlgInTop" )
-        acc.addEventAlgo( algos2, sequenceName="hltTop" ) # some algo
-        acc.addSequence( seqAND("hltSteps"), parentName="hltTop" )
-        acc.addSequence( parOR("hltStep_1"), parentName="hltSteps" )
-        acc.addSequence( seqAND("L2CaloEgammaSeq"), "hltStep_1" )
-        acc.addSequence( parOR("hltStep_2"), parentName="hltSteps" )
-        acc.moveSequence( "L2CaloEgammaSeq", "hltStep_2" )
-
-        acc.store(open("testFile2.pkl", "w"))
-        import pickle
-        f = open("testFile2.pkl")
-        s = pickle.load(f)
-        f.close()
-        self.assertNotEqual( s['hltSteps']['Members'], '[]', "Empty set of members in hltSteps, Sequences recording order metters" )
-
-
-class MultipleParentsInSequences( unittest.TestCase ):
-    def runTest( self ):
-       # test if an algorithm (or sequence) can be controlled by more than one sequence
-        Configurable.configurableRun3Behavior=1
-        from AthenaCommon.CFElements import seqAND
-        from AthenaCommon.Configurable import ConfigurablePyAlgorithm # guinea pig algorithms
-        accTop = ComponentAccumulator()
-
-        recoSeq = seqAND("seqReco")
-        recoAlg = ConfigurablePyAlgorithm( "recoAlg" )
-        recoSeq += recoAlg
-
-        acc1 = ComponentAccumulator()
-        acc1.addSequence( seqAND("seq1") )
-        acc1.addSequence( recoSeq, parentName="seq1" )
-
-        acc2 = ComponentAccumulator()
-        acc2.addSequence( seqAND("seq2") )
-        acc2.addSequence( recoSeq, parentName="seq2" )
-
-        accTop.merge( acc1 )
-        accTop.merge( acc2 )
-
-        accTop.printConfig()
-
-        self.assertIsNotNone( findAlgorithm( accTop.getSequence( "seq1" ), "recoAlg" ), "Algorithm missing in the first sequence" )
-        self.assertIsNotNone( findAlgorithm( accTop.getSequence( "seq2" ), "recoAlg" ), "Algorithm missing in the second sequence" )
-        s = accTop.getSequence( "seqReco" )
-        self.assertEqual( len( s.getChildren() ), 1, "Wrong number of algorithms in reco seq: %d " % len( s.getChildren() ) )
-        self.assertIs( findAlgorithm( accTop.getSequence( "seq1" ), "recoAlg" ), findAlgorithm( accTop.getSequence( "seq2" ), "recoAlg" ), "Algorithms are cloned" )
-        self.assertIs( findAlgorithm( accTop.getSequence( "seq1" ), "recoAlg" ), recoAlg, "Clone of the original inserted in sequence" )
-
-        accTop.store( open("dummy.pkl", "w") )
-        import pickle
-        # check if the recording did not harm the sequences
-        with open("dummy.pkl") as f:
-            s = pickle.load( f )
-            self.assertEquals( s['seq1']["Members"], "['AthSequencer/seqReco']", "After pickling recoSeq missing in seq1 " + s['seq1']["Members"])
-            self.assertEquals( s['seq2']["Members"], "['AthSequencer/seqReco']", "After pickling recoSeq missing in seq2 " + s['seq2']["Members"])
-            self.assertEquals( s['seqReco']["Members"], "['ConfigurablePyAlgorithm/recoAlg']", "After pickling seqReco is corrupt " + s['seqReco']["Members"] )
-
-class ForbidRecursiveSequences( unittest.TestCase ):
-    def runTest( self ):
-        #Can't add a sequence with the same name below itself, e.g.
-        # \__ AthAlgSeq (seq: PAR AND)
-        #    \__ seq1 (seq: SEQ AND)
-        #       \__ seq1 (seq: SEQ AND)
-        def selfSequence():
-            Configurable.configurableRun3Behavior=1
-            from AthenaCommon.CFElements import seqAND
-            accTop = ComponentAccumulator()
-            accTop.wasMerged()
-            seq1 = seqAND("seq1")
-            seq1_again = seqAND("seq1")
-            accTop.addSequence(seq1)
-            accTop.addSequence(seq1_again, parentName = "seq1")
-
-        #Allowed to add a sequence with the same name at same depth, e.g.
-        # \__ AthAlgSeq (seq: PAR AND)
-        #    \__ seq1 (seq: SEQ AND)
-        #       \__ seq2 (seq: SEQ AND)
-        #       \__ seq2 (seq: SEQ AND)
-        # should not raise any exceptions
-        def selfTwinSequence():
-            Configurable.configurableRun3Behavior=1
-            from AthenaCommon.CFElements import seqAND
-            accTop = ComponentAccumulator()
-            accTop.wasMerged()
-            seq1 = seqAND("seq1")
-            seq2 = seqAND("seq2")
-            seq2_again = seqAND("seq1")
-            accTop.addSequence(seq1)
-            accTop.addSequence(seq2, parentName = "seq1")
-            accTop.addSequence(seq2_again, parentName = "seq1")
-            accTop.wasMerged()
-            
-
-        #Can't add a sequence with the same name two steps below itself, e.g.
-        # \__ AthAlgSeq (seq: PAR AND)
-        #    \__ seq1 (seq: SEQ AND)
-        #       \__ seq2 (seq: SEQ AND)
-        #          \__ seq1 (seq: SEQ AND)
-        def selfGrandParentSequence():
-            Configurable.configurableRun3Behavior=1
-            from AthenaCommon.CFElements import seqAND
-            accTop = ComponentAccumulator()
-            accTop.store( open("test.pkl", "w") )#silence RuntimeError
-            seq1 = seqAND("seq1")
-            seq2 = seqAND("seq2")
-            seq1_again = seqAND("seq1")
-            accTop.addSequence(seq1)
-            accTop.addSequence(seq2, parentName = "seq1")
-            accTop.addSequence(seq1_again, parentName = "seq2")
-            accTop.wasMerged()
-
-        #Can't merge sequences with the same name two steps below itself, e.g.
-        # \__ AthAlgSeq (seq: PAR AND)
-        #    \__ seq1 (seq: SEQ AND)
-        #       \__ seq2 (seq: SEQ AND)
-        #          \__ seq1 (seq: SEQ AND)
-        def selfMergedGrandParentSequence():
-            Configurable.configurableRun3Behavior=1
-            from AthenaCommon.CFElements import seqAND
-            acc1=ComponentAccumulator()
-            acc1.wasMerged()
-            acc1.addSequence(seqAND("seq1"))
-            acc2=ComponentAccumulator()
-            acc2.wasMerged()
-            acc2.addSequence(seqAND("seq2"))
-            acc2.addSequence(seqAND("seq1"), "seq2")
-            acc1.merge(acc2)
-
-        self.assertRaises(RuntimeError, selfSequence )
-        self.assertRaises(RuntimeError, selfGrandParentSequence )
-        self.assertRaises(RuntimeError, selfMergedGrandParentSequence )
-
-class FailedMerging( unittest.TestCase ):
-    def runTest( self ):
-        topCA = ComponentAccumulator()
-
-        def badMerge():
-            someCA = ComponentAccumulator()
-            topCA.merge(  (someCA, 1, "hello")  )
-        self.assertRaises(RuntimeError, badMerge )
-        topCA.wasMerged()
-
-
-class MergeMovingAlgorithms( unittest.TestCase ):
-    def runTest( self ):
-        Configurable.configurableRun3Behavior=1
-        from AthenaCommon.CFElements import seqAND
-        from AthenaCommon.Configurable import ConfigurablePyAlgorithm # guinea pig algorithms
-        destinationCA = ComponentAccumulator()
-        destinationCA.addSequence( seqAND("dest") )
-
-        sourceCA = ComponentAccumulator()
-        sourceCA.addEventAlgo(ConfigurablePyAlgorithm("alg1"))
-        sourceCA.addEventAlgo(ConfigurablePyAlgorithm("alg2"))
-        sourceCA.addSequence( seqAND("innerSeq") )
-        sourceCA.addEventAlgo(ConfigurablePyAlgorithm("alg3"), sequenceName="innerSeq" )
-
-        destinationCA.merge( sourceCA, sequenceName="dest"  )
-
-        #destinationCA.merge( sourceCA )
-        self.assertIsNotNone( findAlgorithm( destinationCA.getSequence("dest"), "alg1" ), "Algorithm not placed in sub-sequence" )
-        self.assertIsNotNone( findSubSequence( destinationCA.getSequence(), "innerSeq" ), "The sequence is not added" )
-        self.assertIsNotNone( findAlgorithm( destinationCA.getSequence("dest"), "alg3" ), "Algorithm deep in thesource CA not placed in sub-sequence of destiantion CA" )
-        destinationCA.wasMerged()
-        sourceCA.wasMerged()
-
-class TestComponentAccumulatorAccessors( unittest.TestCase ):
-    def runTest( self ):
-        ca = ComponentAccumulator()
-        from AthenaCommon.Configurable import ConfigurablePyAlgorithm # guinea pig algorithms
-        ca.addEventAlgo(ConfigurablePyAlgorithm("alg1"))
-        
-        self.assertIsNotNone( ca.getEventAlgo(), "Found single alg")
-        self.assertEquals( len(ca.getEventAlgos()), 1 , "Found single alg")
-# no idea why this assersts do not recognise exceptions        
-#        self.assertRaises(ConfigurationError, ca.getEventAlgo("alg2")) 
-        
-        ca.addEventAlgo(ConfigurablePyAlgorithm("alg2"))
-
-        self.assertIsNotNone( ca.getEventAlgo("alg2"), "Found single alg")
-        self.assertEquals( len(ca.getEventAlgos()), 2 , "Found single alg")
- #       self.assertRaises(ConfigurationError, ca.getEventAlgo(), "Single Alg API ambiguity")
-
-        class Tool(ConfigurableAlgTool):
-            def __init__(self, *args, **kwargs):
-                super(Tool, self).__init__(*args, **kwargs)
-            def getDlls(self):
-                return None
-
-
-        ca.addPublicTool( Tool(name="tool1") )
-        self.assertIsNotNone( ca.getPublicTool(), "Found single tool")
-        ca.addPublicTool( Tool(name="tool2") )
-#        self.assertRaises(ConfigurationError, ca.getPublicTool(), "Found single tool")
-
-if __name__ == "__main__":
-    unittest.main()
diff --git a/Control/AthenaConfiguration/python/ComponentAccumulatorTest.py b/Control/AthenaConfiguration/python/ComponentAccumulatorTest.py
new file mode 100644
index 0000000000000000000000000000000000000000..b97d2d485fe2385ad1061f7d73f15270b2ac87da
--- /dev/null
+++ b/Control/AthenaConfiguration/python/ComponentAccumulatorTest.py
@@ -0,0 +1,320 @@
+# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+
+# self test of ComponentAccumulator
+
+from AthenaConfiguration.ComponentAccumulator import ComponentAccumulator
+from AthenaConfiguration.AthConfigFlags import AthConfigFlags
+from AthenaCommon.CFElements import findSubSequence,findAlgorithm
+from AthenaCommon.Configurable import Configurable, ConfigurablePyAlgorithm # guinea pig algorithms
+from AthenaCommon.CFElements import seqAND, seqOR, parOR
+from AthenaCommon.Logging import log
+from AthenaCommon.Constants import DEBUG, INFO
+
+import unittest
+
+class TestComponentAccumulator( unittest.TestCase ):
+    def setUp(self):
+
+
+        # trivial case without any nested sequences
+
+        Configurable.configurableRun3Behavior+=1
+
+        log.setLevel(DEBUG)
+
+        dummyCfgFlags=AthConfigFlags()
+        dummyCfgFlags.lock()
+
+        class Algo(ConfigurablePyAlgorithm):
+            def __init__(self, name):
+                super( ConfigurablePyAlgorithm, self ).__init__( name )
+
+        def AlgsConf1(flags):
+            acc = ComponentAccumulator()
+            a1=Algo("Algo1")
+            a2=Algo("Algo2")
+            return acc,[a1,a2]
+
+
+        def AlgsConf2(flags):
+            acc = ComponentAccumulator()
+            result,algs=AlgsConf1( flags )
+            acc.merge(result)
+            a = Algo("Algo3")
+            print "algo3 when created", id(a)
+            algs.append(a)
+            return acc,algs
+
+        acc = ComponentAccumulator()
+
+        # top level algs
+        acc1,algs=AlgsConf2(dummyCfgFlags)
+        acc.merge(acc1)
+        acc.addEventAlgo(algs)
+
+        def AlgsConf3(flags):
+            acc = ComponentAccumulator()
+            na1=Algo("NestedAlgo1")
+            return acc,na1
+
+        def AlgsConf4(flags):
+            acc,na1= AlgsConf3( flags )
+            NestedAlgo2 = Algo("NestedAlgo2")
+            NestedAlgo2.OutputLevel=7
+            return acc,na1,NestedAlgo2
+
+        acc.addSequence( seqAND("Nest") )
+        acc.addSequence( seqAND("subSequence1"), parentName="Nest" )
+        acc.addSequence( parOR("subSequence2"), parentName="Nest" )
+
+        acc.addSequence( seqAND("sub2Sequence1"), parentName="subSequence1")
+        acc.addSequence( seqAND("sub3Sequence1"), parentName="subSequence1")
+        acc.addSequence( seqAND("sub4Sequence1"), parentName="subSequence1")
+
+        accNA1=AlgsConf4(dummyCfgFlags)
+        acc.merge(accNA1[0])
+        acc.addEventAlgo(accNA1[1:],"sub2Sequence1" )
+        acc.store(open("testFile.pkl", "w"))
+        self.acc = acc
+
+
+    def test_algorihmsAreAdded( self ):
+        self.assertEqual( findAlgorithm( self.acc.getSequence(), "Algo1", 1).name(), "Algo1", "Algorithm not added to a top sequence" )
+        self.assertEqual( findAlgorithm( self.acc.getSequence(), "Algo2", 1).name(),  "Algo2", "Algorithm not added to a top sequence" )
+        self.assertEqual( findAlgorithm( self.acc.getSequence(), "Algo3", 1).name(), "Algo3", "Algorithm not added to a top sequence" )
+
+    def test_sequencesAreAdded( self ):
+        self.assertIsNotNone( self.acc.getSequence("subSequence1" ), "Adding sub-sequence failed" )
+        self.assertIsNotNone( self.acc.getSequence("subSequence2" ), "Adding sub-sequence failed" )
+        self.assertIsNotNone( self.acc.getSequence("sub2Sequence1"), "Adding sub-sequence failed" )
+        self.assertIsNotNone( findSubSequence( self.acc.getSequence("subSequence1"), "sub2Sequence1"), "Adding sub-sequence done in a wrong place" )
+
+    def test_algorithmsInNestedSequences( self ):
+        self.assertIsNotNone( findAlgorithm( self.acc.getSequence(), "NestedAlgo1" ), "Algorithm added to nested sequence" )
+        self.assertIsNotNone( findAlgorithm( self.acc.getSequence(), "NestedAlgo1", 1 ) is None, "Algorithm mistakenly in top sequence" )
+        self.assertIsNotNone( findAlgorithm( findSubSequence( self.acc.getSequence(), "sub2Sequence1"), "NestedAlgo1", 1 ), "Algorithm not in right sequence" )
+
+
+    def test_readBackConfiguration( self ):
+        import pickle
+        with open( "testFile.pkl" ) as f:
+            s = pickle.load( f )
+            self.assertIsNotNone( s, "The pickle has no content")
+
+    def test_foreach_component( self ):
+        from AthenaCommon.Logging import logging
+        logging.getLogger('foreach_component').setLevel(DEBUG)
+        algo3 = self.acc.getEventAlgo("Algo3")        
+        algo3.OutputLevel = INFO
+        self.acc.foreach_component("*/Algo3").OutputLevel = DEBUG # restet to debug level
+        self.assertEqual( algo3.OutputLevel, DEBUG, "wrong OutputLevel value for Algo3")
+        self.acc.foreach_component("*sub2*/*").OutputLevel = INFO 
+        self.assertEqual(self.acc.getEventAlgo("NestedAlgo1").OutputLevel, INFO, "wrong OutputLevel value for NestedAlgo1")
+        self.assertEqual(self.acc.getEventAlgo("NestedAlgo2").OutputLevel, INFO, "wrong OutputLevel value for NestedAlgo1")
+
+        
+
+class TestHLTCF( unittest.TestCase ):
+    def runTest( self ):
+        # replicate HLT issue, it occured because the sequnces were recorded in the order of storing in the dict and thus the
+        # some of them (in this case hltSteps) did not have properties recorded
+
+
+        Configurable.configurableRun3Behavior=1
+        acc = ComponentAccumulator()
+        acc.addSequence( seqOR("hltTop") )
+        algos2 = ConfigurablePyAlgorithm( "RecoAlgInTop" )
+        acc.addEventAlgo( algos2, sequenceName="hltTop" ) # some algo
+        acc.addSequence( seqAND("hltSteps"), parentName="hltTop" )
+        acc.addSequence( parOR("hltStep_1"), parentName="hltSteps" )
+        acc.addSequence( seqAND("L2CaloEgammaSeq"), "hltStep_1" )
+        acc.addSequence( parOR("hltStep_2"), parentName="hltSteps" )
+        acc.moveSequence( "L2CaloEgammaSeq", "hltStep_2" )
+
+        acc.store(open("testFile2.pkl", "w"))
+        import pickle
+        f = open("testFile2.pkl")
+        s = pickle.load(f)
+        f.close()
+        self.assertNotEqual( s['hltSteps']['Members'], '[]', "Empty set of members in hltSteps, Sequences recording order metters" )
+
+
+class MultipleParentsInSequences( unittest.TestCase ):
+    def runTest( self ):
+       # test if an algorithm (or sequence) can be controlled by more than one sequence
+        Configurable.configurableRun3Behavior=1
+
+        accTop = ComponentAccumulator()
+
+        recoSeq = seqAND("seqReco")
+        recoAlg = ConfigurablePyAlgorithm( "recoAlg" )
+        recoSeq += recoAlg
+
+        acc1 = ComponentAccumulator()
+        acc1.addSequence( seqAND("seq1") )
+        acc1.addSequence( recoSeq, parentName="seq1" )
+
+        acc2 = ComponentAccumulator()
+        acc2.addSequence( seqAND("seq2") )
+        acc2.addSequence( recoSeq, parentName="seq2" )
+
+        accTop.merge( acc1 )
+        accTop.merge( acc2 )
+
+        accTop.printConfig()
+
+        self.assertIsNotNone( findAlgorithm( accTop.getSequence( "seq1" ), "recoAlg" ), "Algorithm missing in the first sequence" )
+        self.assertIsNotNone( findAlgorithm( accTop.getSequence( "seq2" ), "recoAlg" ), "Algorithm missing in the second sequence" )
+        s = accTop.getSequence( "seqReco" )
+        self.assertEqual( len( s.getChildren() ), 1, "Wrong number of algorithms in reco seq: %d " % len( s.getChildren() ) )
+        self.assertIs( findAlgorithm( accTop.getSequence( "seq1" ), "recoAlg" ), findAlgorithm( accTop.getSequence( "seq2" ), "recoAlg" ), "Algorithms are cloned" )
+        self.assertIs( findAlgorithm( accTop.getSequence( "seq1" ), "recoAlg" ), recoAlg, "Clone of the original inserted in sequence" )
+
+        accTop.store( open("dummy.pkl", "w") )
+        import pickle
+        # check if the recording did not harm the sequences
+        with open("dummy.pkl") as f:
+            s = pickle.load( f )
+            self.assertEquals( s['seq1']["Members"], "['AthSequencer/seqReco']", "After pickling recoSeq missing in seq1 " + s['seq1']["Members"])
+            self.assertEquals( s['seq2']["Members"], "['AthSequencer/seqReco']", "After pickling recoSeq missing in seq2 " + s['seq2']["Members"])
+            self.assertEquals( s['seqReco']["Members"], "['ConfigurablePyAlgorithm/recoAlg']", "After pickling seqReco is corrupt " + s['seqReco']["Members"] )
+
+class ForbidRecursiveSequences( unittest.TestCase ):
+    def runTest( self ):
+        #Can't add a sequence with the same name below itself, e.g.
+        # \__ AthAlgSeq (seq: PAR AND)
+        #    \__ seq1 (seq: SEQ AND)
+        #       \__ seq1 (seq: SEQ AND)
+        def selfSequence():
+            Configurable.configurableRun3Behavior=1
+            from AthenaCommon.CFElements import seqAND
+            accTop = ComponentAccumulator()
+            accTop.wasMerged()
+            seq1 = seqAND("seq1")
+            seq1_again = seqAND("seq1")
+            accTop.addSequence(seq1)
+            accTop.addSequence(seq1_again, parentName = "seq1")
+
+        #Allowed to add a sequence with the same name at same depth, e.g.
+        # \__ AthAlgSeq (seq: PAR AND)
+        #    \__ seq1 (seq: SEQ AND)
+        #       \__ seq2 (seq: SEQ AND)
+        #       \__ seq2 (seq: SEQ AND)
+        # should not raise any exceptions
+        def selfTwinSequence():
+            Configurable.configurableRun3Behavior=1
+            from AthenaCommon.CFElements import seqAND
+            accTop = ComponentAccumulator()
+            accTop.wasMerged()
+            seq1 = seqAND("seq1")
+            seq2 = seqAND("seq2")
+            seq2_again = seqAND("seq1")
+            accTop.addSequence(seq1)
+            accTop.addSequence(seq2, parentName = "seq1")
+            accTop.addSequence(seq2_again, parentName = "seq1")
+            accTop.wasMerged()
+            
+
+        #Can't add a sequence with the same name two steps below itself, e.g.
+        # \__ AthAlgSeq (seq: PAR AND)
+        #    \__ seq1 (seq: SEQ AND)
+        #       \__ seq2 (seq: SEQ AND)
+        #          \__ seq1 (seq: SEQ AND)
+        def selfGrandParentSequence():
+            Configurable.configurableRun3Behavior=1
+            from AthenaCommon.CFElements import seqAND
+            accTop = ComponentAccumulator()
+            seq1 = seqAND("seq1")
+            seq2 = seqAND("seq2")
+            seq1_again = seqAND("seq1")
+            accTop.addSequence(seq1)
+            accTop.addSequence(seq2, parentName = "seq1")
+            accTop.addSequence(seq1_again, parentName = "seq2")
+            accTop.wasMerged()
+
+        #Can't merge sequences with the same name two steps below itself, e.g.
+        # \__ AthAlgSeq (seq: PAR AND)
+        #    \__ seq1 (seq: SEQ AND)
+        #       \__ seq2 (seq: SEQ AND)
+        #          \__ seq1 (seq: SEQ AND)
+        def selfMergedGrandParentSequence():
+            Configurable.configurableRun3Behavior=1
+            from AthenaCommon.CFElements import seqAND
+            acc1=ComponentAccumulator()
+            acc1.wasMerged()
+            acc1.addSequence(seqAND("seq1"))
+            acc2=ComponentAccumulator()
+            acc2.wasMerged()
+            acc2.addSequence(seqAND("seq2"))
+            acc2.addSequence(seqAND("seq1"), "seq2")
+            acc1.merge(acc2)
+
+        self.assertRaises(RuntimeError, selfSequence )
+        self.assertRaises(RuntimeError, selfGrandParentSequence )
+        self.assertRaises(RuntimeError, selfMergedGrandParentSequence )
+
+class FailedMerging( unittest.TestCase ):
+    def runTest( self ):
+        topCA = ComponentAccumulator()
+
+        def badMerge():
+            someCA = ComponentAccumulator()
+            topCA.merge(  (someCA, 1, "hello")  )
+        self.assertRaises(RuntimeError, badMerge )
+        topCA.wasMerged()
+
+
+class MergeMovingAlgorithms( unittest.TestCase ):
+    def runTest( self ):
+        Configurable.configurableRun3Behavior=1
+        destinationCA = ComponentAccumulator()
+        destinationCA.addSequence( seqAND("dest") )
+
+        sourceCA = ComponentAccumulator()
+        sourceCA.addEventAlgo(ConfigurablePyAlgorithm("alg1"))
+        sourceCA.addEventAlgo(ConfigurablePyAlgorithm("alg2"))
+        sourceCA.addSequence( seqAND("innerSeq") )
+        sourceCA.addEventAlgo(ConfigurablePyAlgorithm("alg3"), sequenceName="innerSeq" )
+
+        destinationCA.merge( sourceCA, sequenceName="dest"  )
+
+        #destinationCA.merge( sourceCA )
+        self.assertIsNotNone( findAlgorithm( destinationCA.getSequence("dest"), "alg1" ), "Algorithm not placed in sub-sequence" )
+        self.assertIsNotNone( findSubSequence( destinationCA.getSequence(), "innerSeq" ), "The sequence is not added" )
+        self.assertIsNotNone( findAlgorithm( destinationCA.getSequence("dest"), "alg3" ), "Algorithm deep in thesource CA not placed in sub-sequence of destiantion CA" )
+        destinationCA.wasMerged()
+        sourceCA.wasMerged()
+
+
+class TestComponentAccumulatorAccessors( unittest.TestCase ):
+    def runTest( self ):
+        ca = ComponentAccumulator()
+        from AthenaCommon.Configurable import ConfigurablePyAlgorithm,ConfigurableAlgTool
+        ca.addEventAlgo(ConfigurablePyAlgorithm("alg1"))
+        
+        self.assertIsNotNone( ca.getEventAlgo(), "Found single alg")
+        self.assertEquals( len(ca.getEventAlgos()), 1 , "Found single alg")
+# no idea why this assersts do not recognise exceptions        
+#        self.assertRaises(ConfigurationError, ca.getEventAlgo("alg2")) 
+        
+        ca.addEventAlgo(ConfigurablePyAlgorithm("alg2"))
+
+        self.assertIsNotNone( ca.getEventAlgo("alg2"), "Found single alg")
+        self.assertEquals( len(ca.getEventAlgos()), 2 , "Found single alg")
+ #       self.assertRaises(ConfigurationError, ca.getEventAlgo(), "Single Alg API ambiguity")
+
+        class Tool(ConfigurableAlgTool):
+            def __init__(self, *args, **kwargs):
+                super(Tool, self).__init__(*args, **kwargs)
+            def getDlls(self):
+                return None
+
+
+        ca.addPublicTool( Tool(name="tool1") )
+        self.assertIsNotNone( ca.getPublicTool(), "Found single tool")
+        ca.addPublicTool( Tool(name="tool2") )
+#        self.assertRaises(ConfigurationError, ca.getPublicTool(), "Found single tool")
+
+
+if __name__ == "__main__":
+    unittest.main()
diff --git a/Control/AthenaConfiguration/python/PropSetterProxy.py b/Control/AthenaConfiguration/python/PropSetterProxy.py
new file mode 100644
index 0000000000000000000000000000000000000000..e55e6e32fa2b15c2c6517c5c0f2c36a0f60d5676
--- /dev/null
+++ b/Control/AthenaConfiguration/python/PropSetterProxy.py
@@ -0,0 +1,79 @@
+# Copyright (C) 2002-2019 CERN for the benefit of the ATLAS collaboration
+from AthenaCommon.Logging import logging
+from AthenaCommon.CFElements import isSequence
+from AthenaCommon.Configurable import ConfigurableAlgTool
+from GaudiKernel.GaudiHandles import PrivateToolHandle, PrivateToolHandleArray
+class PropSetterProxy(object):
+   __compPaths = {}
+   __scannedCA = None
+
+   def __init__(self, ca, path):      
+      self.__path = path      
+      self.__findComponents( ca )
+      
+   def __setattr__(self, name, value):
+       if name.startswith("_PropSetterProxy"):
+           return super(PropSetterProxy, self).__setattr__(name, value)
+
+       msg = logging.getLogger('foreach_component')
+       if name != "OutputLevel":
+           msg.warning( "Only OutputLevel is allowed to be changed with the foreach_component at the moment"  )
+           return
+
+       
+       import fnmatch
+       for component_path, component in PropSetterProxy.__compPaths.iteritems():
+           if fnmatch.fnmatch( component_path, self.__path ):
+               if name in component.getProperties():
+                   try:
+                       setattr( component, name, value )
+                       msg.info( "Set property: %s to value %s of component %s because it matched %s " % ( name, str(value), component_path, self.__path )   )
+                   except Exception, ex:
+                       msg.warning( "Failed to set property: %s to value %s of component %s because it matched %s, reason: %s" % ( name, str(value), component_path, self.__path, str(ex) )   )
+                       pass
+               else:
+                   msg.warning( "No such a property: %s in component %s, tried to set it because it matched %s" % ( name, component_path, self.__path )   )
+
+
+   def __findComponents(self, ca):
+       if ca is not PropSetterProxy.__scannedCA:
+           PropSetterProxy.__scannedCA = ca
+           PropSetterProxy.__compPaths = {}
+           def __add(path, comp):
+               if comp.getName() == "":
+                   return
+               PropSetterProxy.__compPaths[ path ] = comp
+
+
+           for svc in ca._services:
+               PropSetterProxy.__compPaths['SvcMgr/'+svc.getFullName()] = svc
+           for t in ca._publicTools:
+               PropSetterProxy.__compPaths['ToolSvc/'+t.getFullName()] = t
+           
+           def __nestAlg(startpath, comp): # it actually dives inside the algorithms and (sub) tools               
+               if comp.getName() == "":
+                   return
+               for name, value in comp.getProperties().iteritems():
+                   if isinstance( value, ConfigurableAlgTool ) or isinstance( value, PrivateToolHandle ):
+                       __add( startpath+"/"+name+"/"+value.getFullName(), value )
+                       __nestAlg( startpath+"/"+name+"/"+value.getName(), value )
+                   if isinstance( value, PrivateToolHandleArray):
+                       for toolIndex,t in enumerate(value):
+                           __add( startpath+"/"+name+"/"+t.getFullName(), t )
+                           __nestAlg( startpath+"/"+name+"/"+t.getName(), value[toolIndex] )
+                           
+               
+           def __nestSeq( startpath, seq ):
+               for c in seq.getChildren():
+                   if isSequence(c):
+                       __nestSeq( startpath+"/"+c.getName(), c )                       
+                   else: # the algorithm or tool
+                       __add( startpath+"/"+c.getFullName(),  c )
+                       __nestAlg( startpath+"/"+c.getFullName(), c )
+
+           __nestSeq("", ca._sequence)
+            
+            
+
+
+
diff --git a/Trigger/TrigValidation/TrigUpgradeTest/share/newJOtest.py b/Trigger/TrigValidation/TrigUpgradeTest/share/newJOtest.py
index 52d08bb197a1867bcebbcdcc4025ddaafe42608c..f569bc47d3e2f77eae00af5ccba93ea8c9078b2e 100644
--- a/Trigger/TrigValidation/TrigUpgradeTest/share/newJOtest.py
+++ b/Trigger/TrigValidation/TrigUpgradeTest/share/newJOtest.py
@@ -36,7 +36,7 @@ flags.Trigger.L1Decoder.forceEnableAllChains = True
 
 flags.lock()
 
-from AthenaCommon.Constants import INFO,DEBUG
+from AthenaCommon.Constants import INFO,DEBUG,WARNING
 acc = ComponentAccumulator()
 
 from ByteStreamCnvSvc.ByteStreamConfig import TrigBSReadCfg
@@ -62,12 +62,16 @@ acc.getEventAlgo( "TrigSignatureMoniMT" ).OutputLevel=DEBUG
 print acc.getEventAlgo( "TrigSignatureMoniMT" )
 
 
-# from TrigUpgradeTest.TestUtils import applyMenu
-# applyMenu( acc.getEventAlgo( "L1Decoder" ) )
-#acc.getEventAlgo( "L1Decoder" ).OutputLevel=DEBUG
-#acc.getEventAlgo( "L2ElectronCaloHypo" ).OutputLevel=DEBUG
-#acc.getEventAlgo( "FastEMCaloAlgo" ).OutputLevel=DEBUG
-#acc.getEventAlgo( "Filter_for_L2PhotonCaloHypo" ).OutputLevel=DEBUG
+from AthenaCommon.Logging import logging
+logging.getLogger('forcomps').setLevel(DEBUG)
+acc.foreach_component("*/L1Decoder").OutputLevel = DEBUG
+acc.foreach_component("*/L1Decoder/*Tool").OutputLevel = DEBUG # tools
+acc.foreach_component("*HLTTop/*Hypo*").OutputLevel = DEBUG # hypo algs
+acc.foreach_component("*HLTTop/*Hypo*/*Tool*").OutputLevel = DEBUG # hypo tools
+acc.foreach_component("*HLTTop/RoRSeqFilter/*").OutputLevel = DEBUG # filters
+acc.foreach_component("*HLTTop/*Input*").OutputLevel = DEBUG # input makers
+acc.foreach_component("*HLTTop/*GenericMonitoringTool*").OutputLevel = WARNING # silcence mon tools (addressing by type)
+
 
 acc.printConfig()
 
@@ -80,3 +84,4 @@ with file(fname, "w") as p:
 
 
 
+