cleaner config / config-map api understanding inheritance

* Config is now resolved against the ancestor where it is defined, e.g. 
attributeWhenReady;
  (but do we need a way to specify that config should be resolved against the 
resolver?)
* submap is no longer supported for entity config; findKeys has been introduced
* many methods tidied and deprecated


Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/0d655e05
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/0d655e05
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/0d655e05

Branch: refs/heads/master
Commit: 0d655e0503ae1cdf7ad4f95b5321118041bd0592
Parents: 914982e
Author: Alex Heneveld <alex.henev...@cloudsoftcorp.com>
Authored: Tue Sep 20 16:43:43 2016 +0100
Committer: Alex Heneveld <alex.henev...@cloudsoftcorp.com>
Committed: Wed Sep 21 16:06:07 2016 +0100

----------------------------------------------------------------------
 .../apache/brooklyn/api/objs/Configurable.java  |   5 +
 .../BrooklynComponentTemplateResolver.java      |  46 ++-
 .../brooklyn/ConfigInheritanceYamlTest.java     |  22 +-
 .../brooklyn/camp/brooklyn/ObjectsYamlTest.java |   9 +
 .../core/config/BasicConfigInheritance.java     | 185 ++++------
 .../apache/brooklyn/core/config/ConfigKeys.java |  37 --
 .../config/internal/AbstractConfigMapImpl.java  | 367 ++++++++++++++-----
 .../AncestorContainerAndKeyValueIterator.java   |  12 +-
 .../internal/BasicConfigValueAtContainer.java   |  54 ---
 .../internal/LazyContainerAndKeyValue.java      |  27 +-
 .../core/effector/ssh/SshEffectorTasks.java     |  67 ++--
 .../brooklyn/core/entity/AbstractEntity.java    |   8 +-
 .../internal/ConfigMapViewWithStringKeys.java   |  10 +-
 .../core/entity/internal/EntityConfigMap.java   |  69 +---
 .../core/internal/BrooklynPropertiesImpl.java   |  23 +-
 .../core/location/AbstractLocation.java         |  13 +-
 .../core/location/BasicLocationRegistry.java    |   4 +-
 .../location/internal/LocationConfigMap.java    |  92 ++---
 .../entitlement/PerUserEntitlementManager.java  |  11 +-
 .../BasicExternalConfigSupplierRegistry.java    |   2 +-
 .../internal/DeferredBrooklynProperties.java    |  11 +-
 .../mgmt/rebind/BasicEntityRebindSupport.java   |   2 +-
 .../mgmt/rebind/BasicLocationRebindSupport.java |   4 +-
 .../mgmt/rebind/dto/MementosGenerators.java     |   6 +-
 .../AbstractConfigurationSupportInternal.java   |  35 +-
 .../core/objs/AbstractEntityAdjunct.java        |  11 +-
 .../brooklyn/core/objs/AdjunctConfigMap.java    |  55 +--
 .../core/objs/BasicConfigurableObject.java      |  13 +-
 .../core/objs/BrooklynObjectInternal.java       |  19 +-
 .../core/server/BrooklynServerPaths.java        |   4 +-
 .../FixedListMachineProvisioningLocation.java   |   4 +-
 .../brooklyn/util/core/ClassLoaderUtils.java    |   2 +-
 .../brooklyn/util/core/task/ssh/SshTasks.java   |  30 +-
 .../brooklyn/core/entity/EntityConfigTest.java  |  13 +-
 .../core/mgmt/rebind/RebindFailuresTest.java    |  30 +-
 .../util/core/internal/FlagUtilsTest.java       |   7 +
 .../jclouds/JcloudsByonLocationResolver.java    |   2 +-
 .../location/jclouds/JcloudsLocation.java       |   2 +-
 .../AbstractPortableTemplateBuilder.java        |   2 +-
 .../apache/brooklyn/rest/BrooklynWebConfig.java |   4 +-
 .../rest/resources/EntityConfigResource.java    |   7 +-
 .../rest/resources/PolicyConfigResource.java    |   4 +-
 .../rest/transform/LocationTransformer.java     |  17 +-
 .../rest/resources/LocationResourceTest.java    |  23 +-
 .../rest/util/EntityLocationUtilsTest.java      |   2 +-
 .../BrooklynNodeUpgradeEffectorBody.java        |   2 +-
 .../base/VanillaSoftwareProcessTest.java        |   3 +-
 .../brooklyn/config/ConfigInheritance.java      | 180 ++++-----
 .../brooklyn/config/ConfigInheritances.java     | 185 ++++++++++
 .../org/apache/brooklyn/config/ConfigKey.java   |   8 +-
 .../org/apache/brooklyn/config/ConfigMap.java   | 103 ++++--
 .../brooklyn/config/ConfigValueAtContainer.java |  17 +-
 .../apache/brooklyn/config/StringConfigMap.java |  10 +
 .../util/exceptions/ReferenceWithError.java     |  14 +-
 54 files changed, 1097 insertions(+), 797 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java
----------------------------------------------------------------------
diff --git a/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java 
b/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java
index 02eee54..ea36c4d 100644
--- a/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java
+++ b/api/src/main/java/org/apache/brooklyn/api/objs/Configurable.java
@@ -18,11 +18,14 @@
  */
 package org.apache.brooklyn.api.objs;
 
+import java.util.Set;
+
 import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
 
 import com.google.common.annotations.Beta;
+import com.google.common.base.Predicate;
 
 /**
  * Something that has mutable config, such as an entity or policy.
@@ -94,5 +97,7 @@ public interface Configurable {
          * @see {@link #setConfig(ConfigKey, Task)}
          */
         <T> T set(HasConfigKey<T> key, Task<T> val);
+        
+        Set<ConfigKey<?>> findKeys(Predicate<ConfigKey<?>> predicate);
     }
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
----------------------------------------------------------------------
diff --git 
a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
 
b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
index 2f7c643..ccf18c0 100644
--- 
a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
+++ 
b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/creation/BrooklynComponentTemplateResolver.java
@@ -46,6 +46,7 @@ import 
org.apache.brooklyn.camp.spi.ApplicationComponentTemplate;
 import org.apache.brooklyn.camp.spi.AssemblyTemplate;
 import org.apache.brooklyn.camp.spi.PlatformComponentTemplate;
 import org.apache.brooklyn.config.ConfigInheritance;
+import org.apache.brooklyn.config.ConfigInheritances;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.config.ConfigValueAtContainer;
 import org.apache.brooklyn.core.catalog.internal.CatalogUtils;
@@ -73,6 +74,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Function;
+import com.google.common.base.Functions;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Maps;
 
@@ -289,25 +291,27 @@ public class BrooklynComponentTemplateResolver {
         Collection<FlagConfigKeyAndValueRecord> records = 
findAllFlagsAndConfigKeyValues(spec, bag);
         Set<String> keyNamesUsed = new LinkedHashSet<String>();
         for (FlagConfigKeyAndValueRecord r: records) {
-            // run through flags *and* config keys (may be overkill, but...)
+            // flags and config keys tracked separately, look at each (may be 
overkill but it's what we've always done)
             
+            Function<Maybe<Object>, Maybe<Object>> rawConvFn = 
Functions.identity();
             if (r.getFlagMaybeValue().isPresent()) {
                 final String flag = r.getFlagName();
                 final ConfigKey<Object> key = (ConfigKey<Object>) 
r.getConfigKey();
                 if (key==null) ConfigKeys.newConfigKey(Object.class, flag);
                 final Object ownValueF = new SpecialFlagsTransformer(loader, 
encounteredRegisteredTypeIds).apply(r.getFlagMaybeValue().get());
 
+                Function<EntitySpec<?>, Maybe<Object>> rawEvalFn = new 
Function<EntitySpec<?>,Maybe<Object>>() {
+                    @Override
+                    public Maybe<Object> apply(EntitySpec<?> input) {
+                        return spec.getFlags().containsKey(flag) ? 
Maybe.of((Object)spec.getFlags().get(flag)) : Maybe.absent();
+                    }
+                };
                 Iterable<? extends 
ConfigValueAtContainer<EntitySpec<?>,Object>> ckvi = MutableList.of(
-                    new LazyContainerAndKeyValue<EntitySpec<?>,Object>(key, 
null, new Function<EntitySpec<?>,Maybe<Object>>() {
-                        @Override
-                        public Maybe<Object> apply(EntitySpec<?> input) {
-                            return spec.getFlags().containsKey(flag) ? 
Maybe.of((Object)spec.getFlags().get(flag)) : Maybe.absent();
-                        }
-                    }));
+                    new LazyContainerAndKeyValue<EntitySpec<?>,Object>(key, 
null, rawEvalFn, rawConvFn));
                 
-                ConfigValueAtContainer<EntitySpec<?>,Object> combinedVal = 
getDefaultConfigInheritance().resolveInheriting(
-                    key, Maybe.ofAllowingNull(ownValueF), null,
-                    ckvi.iterator(), InheritanceContext.TYPE_DEFINITION);
+                ConfigValueAtContainer<EntitySpec<?>,Object> combinedVal = 
ConfigInheritances.resolveInheriting(
+                    null, key, Maybe.ofAllowingNull(ownValueF), 
Maybe.<Object>absent(),
+                    ckvi.iterator(), InheritanceContext.TYPE_DEFINITION, 
getDefaultConfigInheritance()).getWithoutError();
                 
                 spec.configure(flag, combinedVal.get());
                 keyNamesUsed.add(flag);
@@ -316,17 +320,19 @@ public class BrooklynComponentTemplateResolver {
             if (r.getConfigKeyMaybeValue().isPresent()) {
                 final ConfigKey<Object> key = (ConfigKey<Object>) 
r.getConfigKey();
                 final Object ownValueF = new SpecialFlagsTransformer(loader, 
encounteredRegisteredTypeIds).apply(r.getConfigKeyMaybeValue().get());
+                
+                Function<EntitySpec<?>, Maybe<Object>> rawEvalFn = new 
Function<EntitySpec<?>,Maybe<Object>>() {
+                    @Override
+                    public Maybe<Object> apply(EntitySpec<?> input) {
+                        return spec.getConfig().containsKey(key) ? 
Maybe.of(spec.getConfig().get(key)) : Maybe.absent();
+                    }
+                };
                 Iterable<? extends 
ConfigValueAtContainer<EntitySpec<?>,Object>> ckvi = MutableList.of(
-                    new LazyContainerAndKeyValue<EntitySpec<?>,Object>(key, 
null, new Function<EntitySpec<?>,Maybe<Object>>() {
-                        @Override
-                        public Maybe<Object> apply(EntitySpec<?> input) {
-                            return spec.getConfig().containsKey(key) ? 
Maybe.of(spec.getConfig().get(key)) : Maybe.absent();
-                        }
-                    }));
+                    new LazyContainerAndKeyValue<EntitySpec<?>,Object>(key, 
null, rawEvalFn, rawConvFn));
                 
-                ConfigValueAtContainer<EntitySpec<?>,Object> combinedVal = 
getDefaultConfigInheritance().resolveInheriting(
-                    key, Maybe.ofAllowingNull(ownValueF), null,
-                    ckvi.iterator(), InheritanceContext.TYPE_DEFINITION);
+                ConfigValueAtContainer<EntitySpec<?>,Object> combinedVal = 
ConfigInheritances.resolveInheriting(
+                    null, key, Maybe.ofAllowingNull(ownValueF), 
Maybe.<Object>absent(),
+                    ckvi.iterator(), InheritanceContext.TYPE_DEFINITION, 
getDefaultConfigInheritance()).getWithoutError();
                 
                 spec.configure(key, combinedVal.get());
                 keyNamesUsed.add(key.getName());
@@ -341,7 +347,7 @@ public class BrooklynComponentTemplateResolver {
                 continue;
             }
             ConfigKey<?> key = entry.getValue();
-            if (!ConfigKeys.isKeyReinheritable(key, 
InheritanceContext.TYPE_DEFINITION)) {
+            if (!ConfigInheritances.isKeyReinheritable(key, 
InheritanceContext.TYPE_DEFINITION)) {
                 spec.removeConfig(key);
                 spec.removeFlag(key.getName());
             }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigInheritanceYamlTest.java
----------------------------------------------------------------------
diff --git 
a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigInheritanceYamlTest.java
 
b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigInheritanceYamlTest.java
index 349adae..9a71aed 100644
--- 
a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigInheritanceYamlTest.java
+++ 
b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ConfigInheritanceYamlTest.java
@@ -32,7 +32,6 @@ import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.core.config.MapConfigKey;
 import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.entity.EntityAsserts;
-import org.apache.brooklyn.core.entity.internal.EntityConfigMap;
 import org.apache.brooklyn.core.sensor.Sensors;
 import org.apache.brooklyn.core.test.entity.TestEntity;
 import org.apache.brooklyn.entity.software.base.EmptySoftwareProcess;
@@ -221,16 +220,9 @@ public class ConfigInheritanceYamlTest extends 
AbstractYamlTest {
                 ImmutableMap.of("mykey", "myval", "templateOptions", 
ImmutableMap.of("myOptionsKey", "myOptionsVal")));
     }
     
-    /**
-     * TODO This hangs because the attributeWhenReady self-reference is 
resolved against the entity
-     * looking up the config value (i.e. the child). Therefore it waits for 
the TestEntity to have
-     * a value for that sensor, but this never happens. The way to avoid this 
is to explicitly set
-     * the component that the attributeWhenReady should apply to (e.g. see 
{@link #testInheritsParentConfigTask()}.
-     * 
-     * Do we want to just exclude this test? Or do we want to "fix" it? Which 
entity should the
-     * attributeWhenReady apply to?
-     */
-    @Test(groups={"Broken", "WIP"}, enabled=false)
+    // Fixed Sept 2016, attributeWhenReady self-reference is now resolved 
against the entity defining the config value.
+    // Prior to this it was resolved against the caller's scope.
+    @Test
     public void testInheritsParentConfigTaskWithSelfScope() throws Exception {
         String yaml = Joiner.on("\n").join(
                 "services:",
@@ -758,12 +750,8 @@ public class ConfigInheritanceYamlTest extends 
AbstractYamlTest {
                 ImmutableMap.of("mykey1", "myval1", "mykey2", "myval2", 
"mykey3", "myval3"));
     }
 
-    /**
-     * TODO Has always failed, and probably hard to fix?! This is due to the 
way 
-     * {@link EntityConfigMap#setInheritedConfig(Map, 
org.apache.brooklyn.util.core.config.ConfigBag)} works:
-     * the parent overrides the grandparent's config. So we only get 
mykey2+mykey3.
-     */
-    @Test(groups={"Broken", "WIP"})
+    // Fixed Sept 2016, inheritance is now computed with respect to defined 
keys and propagated upwards when traversing ancestors
+    @Test
     public void testExtendsParentMultipleLevels() throws Exception {
         addCatalogItems(
                 "brooklyn.catalog:",

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
----------------------------------------------------------------------
diff --git 
a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
 
b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
index c372a72..f1ea8eb 100644
--- 
a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
+++ 
b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/ObjectsYamlTest.java
@@ -21,6 +21,7 @@ package org.apache.brooklyn.camp.brooklyn;
 import static org.testng.Assert.assertEquals;
 
 import java.util.List;
+import java.util.Set;
 import java.util.concurrent.atomic.AtomicBoolean;
 
 import org.apache.brooklyn.api.entity.Entity;
@@ -33,6 +34,7 @@ import org.apache.brooklyn.core.config.ConfigKeys;
 import org.apache.brooklyn.core.entity.Entities;
 import org.apache.brooklyn.core.mgmt.ManagementContextInjectable;
 import org.apache.brooklyn.core.test.entity.TestEntity;
+import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.apache.brooklyn.util.core.flags.SetFromFlag;
 import org.apache.brooklyn.util.core.flags.TypeCoercions;
@@ -42,6 +44,8 @@ import org.testng.Assert;
 import org.testng.annotations.Test;
 
 import com.google.common.base.Charsets;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 import com.google.common.hash.HashCode;
 import com.google.common.hash.Hashing;
@@ -182,6 +186,11 @@ public class ObjectsYamlTest extends AbstractYamlTest {
             public <T> T set(HasConfigKey<T> key, Task<T> val) {
                 return set(key.getConfigKey(), val);
             }
+
+            @Override
+            public Set<ConfigKey<?>> findKeys(Predicate<ConfigKey<?>> 
predicate) {
+                return 
MutableSet.copyOf(Iterables.filter(bag.getAllConfigAsConfigKeyMap().keySet(), 
predicate));
+            }
         }
     }
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/config/BasicConfigInheritance.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/config/BasicConfigInheritance.java
 
b/core/src/main/java/org/apache/brooklyn/core/config/BasicConfigInheritance.java
index edd8550..2ed7d48 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/config/BasicConfigInheritance.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/config/BasicConfigInheritance.java
@@ -18,45 +18,43 @@
  */
 package org.apache.brooklyn.core.config;
 
-import java.util.Iterator;
 import java.util.Map;
-import java.util.NoSuchElementException;
-
-import javax.annotation.Nullable;
 
 import org.apache.brooklyn.config.ConfigInheritance;
+import org.apache.brooklyn.config.ConfigInheritances;
+import 
org.apache.brooklyn.config.ConfigInheritances.BasicConfigValueAtContainer;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.config.ConfigValueAtContainer;
-import org.apache.brooklyn.core.config.internal.BasicConfigValueAtContainer;
-import org.apache.brooklyn.core.config.internal.LazyContainerAndKeyValue;
 import org.apache.brooklyn.util.collections.CollectionMerger;
+import org.apache.brooklyn.util.exceptions.ReferenceWithError;
 import org.apache.brooklyn.util.guava.Maybe;
 
-import com.google.common.base.Function;
-
 public class BasicConfigInheritance implements ConfigInheritance {
 
     private static final long serialVersionUID = -5916548049057961051L;
 
+    public static final String CONFLICT_RESOLUTION_STRATEGY_DEEP_MERGE = 
"deep_merge";
+    public static final String CONFLICT_RESOLUTION_STRATEGY_OVERWRITE = 
"overwrite";
+    
     /** Indicates that a config key value should not be passed down from a 
container where it is defined.
      * Unlike {@link #NEVER_INHERITED} these values can be passed down if set 
as anonymous keys at a container
      * (ie the container does not expect it) to a container which does expect 
it, but it will not be passed down further. 
      * If the inheritor also defines a value the parent's value is ignored 
irrespective 
      * (as in {@link #OVERWRITE}; see {@link #NOT_REINHERITED_ELSE_DEEP_MERGE} 
if merging is desired). */
-    public static BasicConfigInheritance NOT_REINHERITED = new 
BasicConfigInheritance(false,"overwrite",false);
+    public static BasicConfigInheritance NOT_REINHERITED = new 
BasicConfigInheritance(false,CONFLICT_RESOLUTION_STRATEGY_OVERWRITE,false);
     /** As {@link #NOT_REINHERITED} but in cases where a value is inherited 
because a parent did not recognize it,
      * if the inheritor also defines a value the two values should be merged. 
*/
-    public static BasicConfigInheritance NOT_REINHERITED_ELSE_DEEP_MERGE = new 
BasicConfigInheritance(false,"deep_merge",false);
+    public static BasicConfigInheritance NOT_REINHERITED_ELSE_DEEP_MERGE = new 
BasicConfigInheritance(false,CONFLICT_RESOLUTION_STRATEGY_DEEP_MERGE,false);
     /** Indicates that a key's value should never be inherited, even if 
defined on a container that does not know the key.
      * Most usages will prefer {@link #NOT_REINHERITED}. */
-    public static BasicConfigInheritance NEVER_INHERITED = new 
BasicConfigInheritance(false,"overwrite",true);
+    public static BasicConfigInheritance NEVER_INHERITED = new 
BasicConfigInheritance(false,CONFLICT_RESOLUTION_STRATEGY_OVERWRITE,true);
     /** Indicates that if a key has a value at both an ancestor and a 
descendant, the descendant and his descendants
      * will prefer the value at the descendant. */
-    public static BasicConfigInheritance OVERWRITE = new 
BasicConfigInheritance(true,"overwrite",false);
+    public static BasicConfigInheritance OVERWRITE = new 
BasicConfigInheritance(true,CONFLICT_RESOLUTION_STRATEGY_OVERWRITE,false);
     /** Indicates that if a key has a value at both an ancestor and a 
descendant, the descendant and his descendants
      * should attempt to merge the values. If the values are not mergable 
behaviour is undefined
      * (and often the descendant's value will simply overwrite). */
-    public static BasicConfigInheritance DEEP_MERGE = new 
BasicConfigInheritance(true,"deep_merge",false);
+    public static BasicConfigInheritance DEEP_MERGE = new 
BasicConfigInheritance(true,CONFLICT_RESOLUTION_STRATEGY_DEEP_MERGE,false);
     
     // reinheritable? true/false; if false, children/descendants/inheritors 
will never see it; default true
     protected final boolean isReinherited;
@@ -80,118 +78,89 @@ public class BasicConfigInheritance implements 
ConfigInheritance {
         return null;
     }
     
+
     @Override
-    public <TContainer,TValue> ConfigValueAtContainer<TContainer,TValue> 
resolveInheriting(
-            @Nullable ConfigKey<TValue> key, Maybe<TValue> localValue, 
TContainer container,
-            Iterator<? extends ConfigValueAtContainer<TContainer,TValue>> 
ancestorContainerKeyValues, ConfigInheritanceContext context) {
-        ConfigInheritance inh = key==null ? null : 
key.getInheritanceByContext(context);
-        if (inh==null) inh = this;
-        if (inh!=this) return inh.resolveInheriting(key, localValue, 
container, ancestorContainerKeyValues, context);
-        
-        ConfigValueAtContainer<TContainer,TValue> v2 = null;
-        if 
(OVERWRITE.conflictResolutionStrategy.equals(conflictResolutionStrategy) && 
-                (localValue.isPresent() || useLocalDefaultValue)) {
-            // don't inherit
-        } else if (ancestorContainerKeyValues==null || 
!ancestorContainerKeyValues.hasNext()) {
-            // nothing to inherit
-        } else {
-            // check whether parent allows us to get inherited value
-            ConfigValueAtContainer<TContainer,TValue> c = 
ancestorContainerKeyValues.next();
-            ConfigInheritance inh2 = c.getKey()==null ? null : 
c.getKey().getInheritanceByContext(context);
-            if (inh2!=null && !ConfigKeys.isKeyReinheritable(c.getKey(), 
context)) {
-                // can't inherit
-            } else {
-                // get inherited value
-                if (inh2==null) inh2=this;
-                v2 = inh2.resolveInheriting(c.getKey()!=null ? c.getKey() : 
null, 
-                    c.isValueExplicitlySet() ? c.asMaybe() : 
Maybe.<TValue>absent(), c.getContainer(), 
-                        ancestorContainerKeyValues, context);
-            }
+    public <TContainer, TValue> boolean 
isReinheritable(ConfigValueAtContainer<TContainer, TValue> parent, 
ConfigInheritanceContext context) {
+        if (!equals(ConfigInheritances.findInheritance(parent, context, 
this))) 
+            throw new IllegalStateException("Method can only be invoked on 
inheritance at "+parent);
+        return isReinherited();
+    }
+    
+    @Override
+    public <TContainer,TValue> boolean considerParent(
+            ConfigValueAtContainer<TContainer,TValue> local,
+            ConfigValueAtContainer<TContainer,TValue> parent,
+            ConfigInheritanceContext context) {
+        if (!equals(ConfigInheritances.findInheritance(local, context, this))) 
+            throw new IllegalStateException("Method can only be invoked on 
inheritance at "+local);
+        if (parent==null) return false;
+        if 
(CONFLICT_RESOLUTION_STRATEGY_OVERWRITE.equals(conflictResolutionStrategy)) {
+            // overwrite means ignore if there's an explicit value, or we're 
using the local default
+            return !local.isValueExplicitlySet() && !getUseLocalDefaultValue();
         }
+        return true;
+    }
 
-        BasicConfigValueAtContainer<TContainer,TValue> v = new 
BasicConfigValueAtContainer<TContainer,TValue>();
-        v.setContainer(container);
-        v.setKey(key);
+    @Override
+    public <TContainer,TValue> 
ReferenceWithError<ConfigValueAtContainer<TContainer,TValue>> resolveWithParent(
+            ConfigValueAtContainer<TContainer,TValue> local,
+            ConfigValueAtContainer<TContainer,TValue> parent,
+            ConfigInheritanceContext context) {
         
-        Maybe<TValue> localValueOrConflictableDefault = localValue.isPresent() 
? localValue : 
-            useLocalDefaultValue ? v.getDefaultValueMaybe() : 
Maybe.<TValue>absent();
-        if (v2!=null && v2.isValueExplicitlySet() && 
!localValueOrConflictableDefault.isPresent()) return v2;
-        if (v2==null || !v2.isValueExplicitlySet()) {
-            v.setValueWasExplicitlySet(localValue.isPresent());
-            v.setValue(v.isValueExplicitlySet() ? localValue : 
v.getDefaultValueMaybe()); 
-        } else {
-            v.setValue(resolveConflict(key, localValue, v2.asMaybe()));
-            v.setValueWasExplicitlySet(true);
+        if (!parent.isValueExplicitlySet() && !getUseLocalDefaultValue()) 
+            return ReferenceWithError.newInstanceWithoutError(new 
BasicConfigValueAtContainer<TContainer,TValue>(local));
+        
+        // parent explicitly set (or we might have to merge defaults), 
+        // and by the contract of this method we can assume reinheritable
+        if (!local.isValueExplicitlySet() && !getUseLocalDefaultValue())
+            return ReferenceWithError.newInstanceWithoutError(new 
BasicConfigValueAtContainer<TContainer,TValue>(parent));
+
+        // both explicitly set or defaults applicable, and not overwriting; it 
should be merge
+        if 
(CONFLICT_RESOLUTION_STRATEGY_DEEP_MERGE.equals(conflictResolutionStrategy)) {
+            BasicConfigValueAtContainer<TContainer, TValue> result = new 
BasicConfigValueAtContainer<TContainer,TValue>(local);
+            ReferenceWithError<Maybe<? extends TValue>> resolvedValue = 
deepMerge(
+                local.isValueExplicitlySet() ? local.asMaybe() : 
local.getDefaultValue(), 
+                parent.isValueExplicitlySet() ? parent.asMaybe() : 
parent.getDefaultValue());
+            result.setValue(resolvedValue.getWithoutError());
+            return ReferenceWithError.newInstanceThrowingError(result, 
resolvedValue.getError());
         }
-        return v;
+        
+        return resolveWithParentCustomStrategy(local, parent, context);
     }
-    /** only invoked if there is an ancestor value; custom strategies can 
overwrite */
-    protected <T> Maybe<T> resolveConflict(ConfigKey<T> key, Maybe<T> 
localValue, Maybe<T> ancestorValue) {
-        if 
(OVERWRITE.conflictResolutionStrategy.equals(conflictResolutionStrategy)) {
-            if (localValue.isPresent()) return localValue;
-            if (useLocalDefaultValue) return (key==null || 
!key.hasDefaultValue()) ? Maybe.<T>absent() : 
Maybe.ofAllowingNull(key.getDefaultValue());
-            return ancestorValue;
-        }
-        if 
(DEEP_MERGE.conflictResolutionStrategy.equals(conflictResolutionStrategy)) {
-            localValue = localValue.isPresent() ? localValue : 
-                useLocalDefaultValue && key!=null && key.hasDefaultValue() ? 
Maybe.ofAllowingNull(key.getDefaultValue()) :
-                Maybe.<T>absent();
-            @SuppressWarnings("unchecked")
-            Maybe<T> result = (Maybe<T>) deepMerge(localValue, ancestorValue);
-            return result;
-        }
-        throw new IllegalStateException("Unknown config conflict resolution 
strategy '"+conflictResolutionStrategy+"' evaluating "+key);
+    
+    protected <TContainer, TValue> 
ReferenceWithError<ConfigValueAtContainer<TContainer, TValue>> 
resolveWithParentCustomStrategy(
+            ConfigValueAtContainer<TContainer, TValue> local, 
ConfigValueAtContainer<TContainer, TValue> parent,
+            ConfigInheritanceContext context) {
+        throw new IllegalStateException("Unknown config conflict resolution 
strategy '"+conflictResolutionStrategy+"' evaluating "+local+"/"+parent);
     }
-    private static <T> Maybe<? extends T> deepMerge(Maybe<? extends T> val1, 
Maybe<? extends T> val2) {
+    
+    private static <T> ReferenceWithError<Maybe<? extends T>> 
deepMerge(Maybe<? extends T> val1, Maybe<? extends T> val2) {
         if (val2.isAbsent() || val2.isNull()) {
-            return val1;
+            return ReferenceWithError.newInstanceWithoutError(val1);
         } else if (val1.isAbsent()) {
-            return val2;
+            return ReferenceWithError.newInstanceWithoutError(val2);
         } else if (val1.isNull()) {
-            return val1; // an explicit null means an override; don't merge
+            return ReferenceWithError.newInstanceWithoutError(val1); // an 
explicit null means an override; don't merge
         } else if (val1.get() instanceof Map && val2.get() instanceof Map) {
             @SuppressWarnings({ "unchecked", "rawtypes" })
             Maybe<T> result = 
(Maybe)Maybe.of(CollectionMerger.builder().build().merge((Map<?,?>)val1.get(), 
(Map<?,?>)val2.get()));
-            return result;
+            return ReferenceWithError.newInstanceWithoutError(result);
         } else {
             // cannot merge; just return val1
-            return val1;
+            return ReferenceWithError.newInstanceThrowingError(val1, new 
IllegalArgumentException("Cannot merge '"+val1.get()+"' and '"+val2.get()+"'"));
         }
     }
-
-    public static class 
AncestorContainerAndKeyValueIterator<TContainer,TValue> implements 
Iterator<ConfigValueAtContainer<TContainer,TValue>> {
-        private TContainer lastContainer;
-        private final Function<TContainer, ConfigKey<TValue>> 
keyFindingFunction; 
-        private final Function<TContainer, Maybe<TValue>> 
localEvaluationFunction; 
-        private final Function<TContainer, TContainer> parentFunction;
-        
-        public AncestorContainerAndKeyValueIterator(TContainer childContainer, 
-                Function<TContainer, ConfigKey<TValue>> keyFindingFunction, 
-                Function<TContainer, Maybe<TValue>> localEvaluationFunction, 
-                Function<TContainer, TContainer> parentFunction) {
-            this.lastContainer = childContainer;
-            this.keyFindingFunction = keyFindingFunction;
-            this.localEvaluationFunction = localEvaluationFunction;
-            this.parentFunction = parentFunction;
-        }
-
-        @Override
-        public boolean hasNext() {
-            return parentFunction.apply(lastContainer)!=null;
-        }
-        
-        @Override
-        public ConfigValueAtContainer<TContainer,TValue> next() {
-            TContainer nextContainer = parentFunction.apply(lastContainer);
-            if (nextContainer==null) throw new NoSuchElementException("Cannot 
search ancestors further than "+lastContainer);
-            lastContainer = nextContainer;
-            return new 
LazyContainerAndKeyValue<TContainer,TValue>(keyFindingFunction.apply(lastContainer),
 lastContainer, localEvaluationFunction);
-        }
-
-        @Override
-        public void remove() {
-            throw new UnsupportedOperationException("This iterator does not 
support removal");
-        }
+    
+    public boolean isReinherited() {
+        return isReinherited;
+    }
+    
+    public String getConflictResolutionStrategy() {
+        return conflictResolutionStrategy;
+    }
+    
+    public boolean getUseLocalDefaultValue() {
+        return useLocalDefaultValue;
     }
     
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/config/ConfigKeys.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/core/config/ConfigKeys.java 
b/core/src/main/java/org/apache/brooklyn/core/config/ConfigKeys.java
index 2743b80..6359907 100644
--- a/core/src/main/java/org/apache/brooklyn/core/config/ConfigKeys.java
+++ b/core/src/main/java/org/apache/brooklyn/core/config/ConfigKeys.java
@@ -22,26 +22,20 @@ import java.util.Map;
 
 import javax.annotation.Nonnull;
 
-import org.apache.brooklyn.config.ConfigInheritance;
 import org.apache.brooklyn.config.ConfigInheritance.ConfigInheritanceContext;
 import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.config.ConfigValueAtContainer;
 import 
org.apache.brooklyn.core.config.BasicConfigKey.BasicConfigKeyOverwriting;
-import org.apache.brooklyn.core.config.internal.LazyContainerAndKeyValue;
 import org.apache.brooklyn.core.sensor.AttributeSensorAndConfigKey;
 import org.apache.brooklyn.core.sensor.BasicAttributeSensorAndConfigKey;
 import org.apache.brooklyn.core.sensor.PortAttributeSensorAndConfigKey;
 import 
org.apache.brooklyn.core.sensor.TemplatedStringAttributeSensorAndConfigKey;
-import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.core.config.ConfigBag;
-import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.text.Strings;
 import org.apache.brooklyn.util.time.Duration;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.CaseFormat;
-import com.google.common.base.Function;
 import com.google.common.base.Preconditions;
 import com.google.common.reflect.TypeToken;
 
@@ -289,35 +283,4 @@ public class ConfigKeys {
 
     }
 
-    /** determine whether a key is reinheritable from the point in the given 
inheritance hierarchy where it is introduced;
-     * default is true, but some keys may define not being reinherited or may 
have that effective result
-     * <p>
-     * note that this does not mean a value should never be *inherited*; 
-     * callers should query with the key defined at a given point in a 
hierarchy,
-     * so if a key is not defined at some point in the hierarchy
-     * (eg not on a type in the type hierarchy, or not an an entity in the 
runtime management hierarchy)
-     * then null should be passed and values will be reinheritable */
-    public static <T> boolean isKeyReinheritable(final ConfigKey<T> key, final 
ConfigInheritanceContext context) {
-        if (key==null) return true;
-        ConfigInheritance inh = key.getInheritanceByContext(context);
-        if (inh==null) return true;
-        if (inh instanceof BasicConfigInheritance) {
-            return ((BasicConfigInheritance)inh).isReinherited;
-        }
-        
-        // evaluate by faking a parent who sets a value and seeing if it's 
reinherited
-        Iterable<? extends ConfigValueAtContainer<Void,T>> ckvi = 
MutableList.of(
-            new LazyContainerAndKeyValue<Void,T>(key, null, new 
Function<Void,Maybe<T>>() {
-                @Override
-                public Maybe<T> apply(Void input) {
-                    return Maybe.ofAllowingNull(null);
-                }
-            }));
-        
-        ConfigValueAtContainer<Void,T> combinedVal = 
BasicConfigInheritance.OVERWRITE.resolveInheriting(
-            key, Maybe.<T>absent(), null,
-            ckvi.iterator(), InheritanceContext.TYPE_DEFINITION);
-        return combinedVal.isValueExplicitlySet();
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/config/internal/AbstractConfigMapImpl.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/config/internal/AbstractConfigMapImpl.java
 
b/core/src/main/java/org/apache/brooklyn/core/config/internal/AbstractConfigMapImpl.java
index 6c31b97..e964d24 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/config/internal/AbstractConfigMapImpl.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/config/internal/AbstractConfigMapImpl.java
@@ -20,31 +20,46 @@ package org.apache.brooklyn.core.config.internal;
 
 import java.util.Collections;
 import java.util.LinkedHashMap;
+import java.util.List;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.Future;
 
+import javax.annotation.Nonnull;
+import javax.annotation.Nullable;
+
 import org.apache.brooklyn.api.mgmt.ExecutionContext;
 import org.apache.brooklyn.api.objs.BrooklynObject;
+import org.apache.brooklyn.config.ConfigInheritance;
+import org.apache.brooklyn.config.ConfigInheritances;
+import 
org.apache.brooklyn.config.ConfigInheritances.BasicConfigValueAtContainer;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
-import org.apache.brooklyn.config.ConfigMap;
+import org.apache.brooklyn.config.ConfigMap.ConfigMapWithInheritance;
+import org.apache.brooklyn.config.ConfigValueAtContainer;
+import org.apache.brooklyn.core.config.BasicConfigInheritance;
 import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.config.ConfigKeys.InheritanceContext;
 import org.apache.brooklyn.core.config.Sanitizer;
 import org.apache.brooklyn.core.config.StructuredConfigKey;
-import org.apache.brooklyn.core.entity.internal.ConfigMapViewWithStringKeys;
 import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
+import org.apache.brooklyn.util.collections.MutableList;
 import org.apache.brooklyn.util.collections.MutableMap;
+import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.apache.brooklyn.util.core.flags.TypeCoercions;
 import org.apache.brooklyn.util.core.internal.ConfigKeySelfExtracting;
 import org.apache.brooklyn.util.core.task.DeferredSupplier;
+import org.apache.brooklyn.util.exceptions.ReferenceWithError;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.Iterables;
 
-public abstract class AbstractConfigMapImpl implements ConfigMap {
+public abstract class AbstractConfigMapImpl<TContainer extends BrooklynObject> 
implements ConfigMapWithInheritance<TContainer> {
 
     /*
      * Changed Sept 2016 so that keys can determine inheritance strategy at 
every level in the hierarchy,
@@ -53,9 +68,10 @@ public abstract class AbstractConfigMapImpl implements 
ConfigMap {
 
     private static final Logger LOG = 
LoggerFactory.getLogger(AbstractConfigMapImpl.class);
     
-    protected final ConfigMapViewWithStringKeys mapViewWithStringKeys = new 
ConfigMapViewWithStringKeys(this);
+    @SuppressWarnings("deprecation")
+    protected final transient 
org.apache.brooklyn.core.entity.internal.ConfigMapViewWithStringKeys 
mapViewWithStringKeys = new 
org.apache.brooklyn.core.entity.internal.ConfigMapViewWithStringKeys(this);
 
-    protected BrooklynObjectInternal bo;
+    protected TContainer bo;
     
     /**
      * Map of configuration information that is defined at start-up time for 
the entity. These
@@ -64,27 +80,30 @@ public abstract class AbstractConfigMapImpl implements 
ConfigMap {
      */
     protected final Map<ConfigKey<?>,Object> ownConfig;
     
-    protected AbstractConfigMapImpl(BrooklynObject bo) {
+    protected AbstractConfigMapImpl(TContainer bo) {
         // Not using ConcurrentMap, because want to (continue to) allow null 
values.
         // Could use ConcurrentMapAcceptingNullVals (with the associated 
performance hit on entrySet() etc).
         this(bo, Collections.synchronizedMap(new LinkedHashMap<ConfigKey<?>, 
Object>()));
     }
-    protected AbstractConfigMapImpl(BrooklynObject bo, Map<ConfigKey<?>, 
Object> storage) {
-        this.bo = (BrooklynObjectInternal) bo;
+    protected AbstractConfigMapImpl(TContainer bo, Map<ConfigKey<?>, Object> 
storage) {
+        this.bo = bo;
         this.ownConfig = storage;
     }
 
-    public BrooklynObjectInternal getBrooklynObject() {
+    public TContainer getContainer() {
         return bo;
     }
     
+    protected final BrooklynObjectInternal getBrooklynObject() {
+        return (BrooklynObjectInternal)bo;
+    }
+    
     public <T> T getConfig(ConfigKey<T> key) {
-        return getConfigImpl(key).orNull();
+        return getConfigImpl(key, false).getWithoutError().get();
     }
     
-
     public <T> T getConfig(HasConfigKey<T> key) {
-        return getConfigImpl(key.getConfigKey()).orNull();
+        return getConfigImpl(key.getConfigKey(), 
false).getWithoutError().get();
     }
     
     @Override
@@ -92,58 +111,38 @@ public abstract class AbstractConfigMapImpl implements 
ConfigMap {
         return getConfigRaw(key, false);
     }
 
-    protected abstract <T> Maybe<T> getConfigImpl(ConfigKey<T> key);
-    
     protected abstract ExecutionContext getExecutionContext(BrooklynObject bo);
     protected abstract void postLocalEvaluate(ConfigKey<?> key, BrooklynObject 
bo, Maybe<?> rawValue, Maybe<?> resolvedValue);
     
-    protected class LocalEvaluateKeyValue<TContainer extends BrooklynObject, 
TValue> implements Function<TContainer,Maybe<TValue>> {
-        ConfigKey<TValue> keyIgnoringInheritance;
-        
-        public LocalEvaluateKeyValue(ConfigKey<TValue> keyIgnoringInheritance) 
{
-            this.keyIgnoringInheritance = keyIgnoringInheritance;
-        }
-        
-        @Override
-        public Maybe<TValue> apply(TContainer bo) {
-            ExecutionContext exec = getExecutionContext(bo);
-            
-            ConfigMap configMap = 
((BrooklynObjectInternal)bo).config().getInternalConfigMap();
-            Map<ConfigKey<?>,Object> ownConfig = 
((AbstractConfigMapImpl)configMap).ownConfig;
-            Maybe<Object> rawValue = 
configMap.getConfigLocalRaw(keyIgnoringInheritance);
-            Maybe<TValue> ownValue;
-            
-            // Get own value
-            if (keyIgnoringInheritance instanceof ConfigKeySelfExtracting) {
-                if 
(((ConfigKeySelfExtracting<TValue>)keyIgnoringInheritance).isSet(ownConfig)) {
-                    Map<ConfigKey<?>, ?> ownCopy;
-                    synchronized (ownConfig) {
-                        // wasteful to make a copy to look up; maybe try once 
opportunistically?
-                        ownCopy = MutableMap.copyOf(ownConfig);
-                    }
-                    ownValue = Maybe.of(((ConfigKeySelfExtracting<TValue>) 
keyIgnoringInheritance).extractValue(ownCopy, exec));
-                } else {
-                    ownValue = Maybe.<TValue>absent();
-                }
-            } else {
-                // all our keys are self-extracting
-                LOG.warn("Unexpected key type "+keyIgnoringInheritance+" 
("+keyIgnoringInheritance.getClass()+") in "+bo+"; ignoring value");
-                ownValue = Maybe.<TValue>absent();
-            }
-
-            postLocalEvaluate(keyIgnoringInheritance, bo, rawValue, ownValue);
-            return ownValue;
-        }
+    @Override
+    public Map<ConfigKey<?>,Object> getAllConfigLocalRaw() {
+        Map<ConfigKey<?>,Object> result = new 
LinkedHashMap<ConfigKey<?>,Object>();
+        result.putAll(ownConfig);
+        return Collections.unmodifiableMap(result);
     }
     
-    /** an immutable copy of the config defined at this entity, ie not 
inherited */
-    public Map<ConfigKey<?>,Object> getLocalConfig() {
-        Map<ConfigKey<?>,Object> result = new 
LinkedHashMap<ConfigKey<?>,Object>(ownConfig.size());
+    /** an immutable copy of the config visible at this entity, local and 
inherited (preferring local) */
+    @Override @Deprecated
+    public Map<ConfigKey<?>,Object> getAllConfig() {
+        Map<ConfigKey<?>,Object> result = new 
LinkedHashMap<ConfigKey<?>,Object>();
+        if (getParent()!=null)
+            result.putAll( 
getParentInternal().config().getInternalConfigMap().getAllConfig() );
         result.putAll(ownConfig);
         return Collections.unmodifiableMap(result);
     }
-    
-    /** Creates an immutable copy of the config defined at this entity, ie not 
inherited, including those that did not match config keys */
+
+    /** Creates an immutable copy of the config visible at this entity, local 
and inherited (preferring local), including those that did not match config 
keys */
+    @Deprecated
+    public ConfigBag getAllConfigBag() {
+        ConfigBag result = ConfigBag.newInstance().putAll(ownConfig);
+        if (getParent()!=null) {
+            result.putIfAbsent(
+                
((AbstractConfigMapImpl<?>)getParentInternal().config().getInternalConfigMap()).getAllConfigBag()
 );
+        }
+        return result.seal();
+    }
+
+    /** As {@link #getLocalConfigRaw()} but in a {@link ConfigBag} for 
convenience */
     public ConfigBag getLocalConfigBag() {
         return ConfigBag.newInstance().putAll(ownConfig).seal();
     }
@@ -170,7 +169,7 @@ public abstract class AbstractConfigMapImpl implements 
ConfigMap {
     }
  
     @SuppressWarnings("unchecked")
-    public void addToLocalBag(Map<?,?> vals) {
+    public void putAll(Map<?,?> vals) {
 //        ConfigBag ownConfigBag = ConfigBag.newInstance().putAll(vals);
 //        ownConfig.putAll(ownConfigBag.getAllConfigAsConfigKeyMap());
         // below seems more straightforward; should be the same.
@@ -188,45 +187,30 @@ public abstract class AbstractConfigMapImpl implements 
ConfigMap {
         }
     }
     
-    public void removeFromLocalBag(String key) {
-        // previously removed the string (?)
+    public void removeKey(String key) {
         ownConfig.remove(ConfigKeys.newConfigKey(Object.class, key));
     }
 
-    public void removeFromLocalBag(ConfigKey<?> key) {
+    public void removeKey(ConfigKey<?> key) {
         ownConfig.remove(key);
     }
 
-    protected abstract BrooklynObjectInternal getParent();
-    
-    @Override
+    protected final TContainer getParent() {
+        return getParentOfContainer(getContainer());
+    }
+
+    protected final BrooklynObjectInternal getParentInternal() {
+        return (BrooklynObjectInternal) getParent();
+    }
+
+    @Override @Deprecated
     public Maybe<Object> getConfigRaw(ConfigKey<?> key, boolean 
includeInherited) {
-        // TODO does not currently respect inheritance modes
+        // does not currently respect inheritance modes
         if (ownConfig.containsKey(key)) return Maybe.of(ownConfig.get(key));
         if (!includeInherited || getParent()==null) return Maybe.absent();
-        return getParent().config().getInternalConfigMap().getConfigRaw(key, 
includeInherited);
+        return 
getParentInternal().config().getInternalConfigMap().getConfigRaw(key, 
includeInherited);
     }
     
-    /** an immutable copy of the config visible at this entity, local and 
inherited (preferring local) */
-    // TODO deprecate because key inheritance not respected
-    public Map<ConfigKey<?>,Object> getAllConfig() {
-        Map<ConfigKey<?>,Object> result = new 
LinkedHashMap<ConfigKey<?>,Object>();
-        if (getParent()!=null)
-            result.putAll( 
getParent().config().getInternalConfigMap().getAllConfig() );
-        result.putAll(ownConfig);
-        return Collections.unmodifiableMap(result);
-    }
-    
-    /** Creates an immutable copy of the config visible at this entity, local 
and inherited (preferring local), including those that did not match config 
keys */
-    // TODO deprecate because key inheritance not respected
-    public ConfigBag getAllConfigBag() {
-        ConfigBag result = ConfigBag.newInstance().putAll(ownConfig);
-        if (getParent()!=null) {
-            result.putIfAbsent(
-                
((AbstractConfigMapImpl)getParent().config().getInternalConfigMap()).getAllConfigBag()
 );
-        }
-        return result.seal();
-    }
     protected Object coerceConfigVal(ConfigKey<?> key, Object v) {
         if ((v instanceof Future) || (v instanceof DeferredSupplier)) {
             // no coercion for these (coerce on exit)
@@ -269,6 +253,219 @@ public abstract class AbstractConfigMapImpl implements 
ConfigMap {
         return ownConfig.isEmpty();
     }
     
+    protected ConfigInheritance getDefaultRuntimeInheritance() {
+        return BasicConfigInheritance.OVERWRITE; 
+    }
+
+    public <T> ReferenceWithError<ConfigValueAtContainer<TContainer,T>> 
getConfigAndContainer(ConfigKey<T> key) {
+        return getConfigImpl(key, false);
+    }
+
+    protected abstract TContainer getParentOfContainer(TContainer container);
+    
+    @Nullable protected final <T> ConfigKey<T> getKeyAtContainer(TContainer 
container, ConfigKey<T> queryKey) {
+        if (container==null) return null;
+        @SuppressWarnings("unchecked")
+        ConfigKey<T> candidate = (ConfigKey<T>) 
getKeyAtContainerImpl(container, queryKey);
+        return candidate;
+    }
+    
+    @Nullable protected abstract <T> ConfigKey<?> 
getKeyAtContainerImpl(@Nonnull TContainer container, ConfigKey<T> queryKey);
+
+    protected Maybe<Object> getRawValueAtContainer(TContainer container, 
ConfigKey<? extends Object> configKey) {
+        return 
((BrooklynObjectInternal)container).config().getInternalConfigMap().getConfigLocalRaw(configKey);
+    }
+    protected Maybe<Object> resolveRawValueFromContainer(TContainer container, 
ConfigKey<?> key, Object value) {
+        Map<ConfigKey<?>, Object> oc = ((AbstractConfigMapImpl<?>) 
((BrooklynObjectInternal)container).config().getInternalConfigMap()).ownConfig;
+        if (key instanceof ConfigKeySelfExtracting) {
+            if (((ConfigKeySelfExtracting<?>)key).isSet(oc)) {
+                Map<ConfigKey<?>, ?> ownCopy;
+                synchronized (oc) {
+                    // wasteful to make a copy to look up; maybe try once 
opportunistically?
+                    ownCopy = MutableMap.copyOf(oc);
+                }
+                return Maybe.of((Object) ((ConfigKeySelfExtracting<?>) 
key).extractValue(ownCopy, getExecutionContext(container)) );
+            } else {
+                return Maybe.absent();
+            }
+        } else {
+            // all our keys are self-extracting
+            LOG.warn("Unexpected key type "+key+" ("+key.getClass()+") in 
"+bo+"; ignoring value");
+            return Maybe.absent();
+        }
+    }
+
+    @SuppressWarnings("unchecked")
+    protected <T> T coerce(Object value, Class<T> type) {
+        if (type==null || value==null) return (T) value;
+        return (T) TypeCoercions.coerce(value, type);
+    }
+    
+    protected <T> ReferenceWithError<ConfigValueAtContainer<TContainer,T>> 
getConfigImpl(final ConfigKey<T> queryKey, final boolean raw) {
+        // In case this entity class has overridden the given key (e.g. to set 
default), then retrieve this entity's key
+        Function<TContainer, ConfigKey<T>> keyFn = new Function<TContainer, 
ConfigKey<T>>() {
+            @Override public ConfigKey<T> apply(TContainer input) {
+                // should return null if the key is not known, to indicate 
selected inheritance rules from base key should take effect
+                return getKeyAtContainer(input, queryKey);
+            }
+        };
+        ConfigKey<T> ownKey = keyFn.apply(getContainer());
+        if (ownKey==null) ownKey = queryKey;
+        @SuppressWarnings("unchecked")
+        final Class<T> type = (Class<T>) ownKey.getType();
+        
+        // takes type of own key (or query key if own key not available)
+        // takes default of own key if available and has default, else of 
query key
+        
+        Function<Maybe<Object>, Maybe<T>> coerceFn = new 
Function<Maybe<Object>, Maybe<T>>() {
+            @SuppressWarnings("unchecked") @Override public Maybe<T> 
apply(Maybe<Object> input) {
+                if (raw || input==null || input.isAbsent()) return 
(Maybe<T>)input;
+                return Maybe.ofAllowingNull(coerce(input.get(), type));
+            }
+        };
+        // prefer default and type of ownKey
+        Maybe<T> defaultValue = raw ? Maybe.<T>absent() :
+            ownKey.hasDefaultValue() ? 
coerceFn.apply(Maybe.of((Object)ownKey.getDefaultValue())) : 
+            queryKey.hasDefaultValue() ? 
coerceFn.apply(Maybe.of((Object)queryKey.getDefaultValue())) :
+                Maybe.<T>absent();
+            
+        if (ownKey instanceof ConfigKeySelfExtracting) {
+            
+            Function<TContainer, Maybe<Object>> lookupFn = new 
Function<TContainer, Maybe<Object>>() {
+                @Override public Maybe<Object> apply(TContainer input) {
+                    Maybe<Object> result = getRawValueAtContainer(input, 
queryKey);
+                    if (!raw) result = resolveRawValueFromContainer(input, 
queryKey, result);
+                    return result;
+                }
+            };
+            Function<TContainer, TContainer> parentFn = new 
Function<TContainer, TContainer>() {
+                @Override public TContainer apply(TContainer input) {
+                    return getParentOfContainer(input);
+                }
+            };
+            AncestorContainerAndKeyValueIterator<TContainer, T> ckvi = new 
AncestorContainerAndKeyValueIterator<TContainer,T>(
+                getContainer(), keyFn, lookupFn, coerceFn, parentFn);
+            
+            return ConfigInheritances.resolveInheriting(
+                getContainer(), ownKey, 
coerceFn.apply(lookupFn.apply(getContainer())), defaultValue, 
+                ckvi, InheritanceContext.RUNTIME_MANAGEMENT, 
getDefaultRuntimeInheritance());
+            
+        } else {
+            String message = "Config key "+ownKey+" of "+getBrooklynObject()+" 
is not a ConfigKeySelfExtracting; cannot retrieve value; returning default";
+            LOG.warn(message);
+            return ReferenceWithError.newInstanceThrowingError(new 
BasicConfigValueAtContainer<TContainer,T>(getContainer(), ownKey, null, false,
+                    defaultValue),
+                new IllegalStateException(message));
+        }
+    }
+    
+    public List<ConfigValueAtContainer<TContainer,?>> 
getConfigAllInheritedRaw(ConfigKey<?> queryKey) {
+        List<ConfigValueAtContainer<TContainer, ?>> result = MutableList.of();
+        TContainer c = getContainer();
+        int count=0;
+
+        final InheritanceContext context = 
InheritanceContext.RUNTIME_MANAGEMENT;
+        ConfigInheritance currentInheritance = 
ConfigInheritances.findInheritance(queryKey, context, 
getDefaultRuntimeInheritance());
+        
+        BasicConfigValueAtContainer<TContainer, Object> last = null;
+        
+        while (c!=null) {
+            Maybe<Object> v = getRawValueAtContainer(c, queryKey);
+            BasicConfigValueAtContainer<TContainer, Object> next = new 
BasicConfigValueAtContainer<TContainer, Object>(c, getKeyAtContainer(c, 
queryKey), v);
+            
+            if (last!=null && !currentInheritance.considerParent(last, next, 
context)) break;
+            
+            currentInheritance = 
ConfigInheritances.findInheritance(next.getKey(), 
InheritanceContext.RUNTIME_MANAGEMENT, currentInheritance);
+            if (count>0 && !currentInheritance.isReinheritable(next, context)) 
break;
+            
+            if (next.isValueExplicitlySet()) result.add(0, next);
+
+            last = next;
+            c = getParentOfContainer(c);
+        }
+        
+        return result;
+    }
+    
+    @Override
+    public Set<ConfigKey<?>> findKeys(Predicate<ConfigKey<?>> filter) {
+        MutableSet<ConfigKey<?>> result = MutableSet.of();
+        result.addAll(Iterables.filter(ownConfig.keySet(), filter));
+        // due to set semantics local should be added first, it prevents equal 
items from parent from being added on top
+        if (getParent()!=null) {
+            result.addAll( 
getParentInternal().config().getInternalConfigMap().findKeys(filter) );
+        }
+        return result;
+    }
+    
+    @SuppressWarnings("unchecked")
+    public ReferenceWithError<ConfigValueAtContainer<TContainer,?>> 
getConfigInheritedRaw(ConfigKey<?> key) {
+        return (ReferenceWithError<ConfigValueAtContainer<TContainer,?>>) 
(ReferenceWithError<?>) getConfigImpl(key, true);
+    }
+    
+    @Override
+    public Map<ConfigKey<?>, Object> 
getAllConfigInheritedRawValuesIgnoringErrors() {
+        Map<ConfigKey<?>, 
ReferenceWithError<ConfigValueAtContainer<TContainer, ?>>> input = 
getAllConfigInheritedRawWithErrors();
+        Map<ConfigKey<?>, Object> result = MutableMap.of();
+        for (Map.Entry<ConfigKey<?>, 
ReferenceWithError<ConfigValueAtContainer<TContainer, ?>>> pair: 
input.entrySet()) {
+            result.put(pair.getKey(), pair.getValue().getWithoutError().get());
+        }
+        return result;
+    }
+    @Override
+    public Map<ConfigKey<?>, 
ReferenceWithError<ConfigValueAtContainer<TContainer, ?>>> 
getAllConfigInheritedRawWithErrors() {
+        return getSelectedConfigInheritedRaw(false);
+    }
+    
+    public 
Map<ConfigKey<?>,ReferenceWithError<ConfigValueAtContainer<TContainer,?>>> 
getAllReinheritableConfigRaw() {
+        return getSelectedConfigInheritedRaw(true);
+    }
+
+    protected 
Map<ConfigKey<?>,ReferenceWithError<ConfigValueAtContainer<TContainer,?>>> 
getSelectedConfigInheritedRaw(boolean onlyReinheritable) {
+        
Map<ConfigKey<?>,ReferenceWithError<ConfigValueAtContainer<TContainer,?>>> 
parents = MutableMap.of();
+        if (getParent()!=null) {
+            @SuppressWarnings("unchecked")
+            
Map<ConfigKey<?>,ReferenceWithError<ConfigValueAtContainer<TContainer,?>>> po = 
(Map<ConfigKey<?>,ReferenceWithError<ConfigValueAtContainer<TContainer,?>>>) 
(Map<?,?>)
+                
getParentInternal().config().getInternalConfigMap().getAllReinheritableConfigRaw();
+            parents.putAll(po);
+        }
+        
+        Map<ConfigKey<?>, Object> local = getAllConfigLocalRaw();
+        
+        
Map<ConfigKey<?>,ReferenceWithError<ConfigValueAtContainer<TContainer,?>>> 
result = MutableMap.of();
+
+        for (ConfigKey<?> k: local.keySet()) {
+            Object v = local.get(k);
+            ReferenceWithError<ConfigValueAtContainer<TContainer, ?>> vpr = 
parents.remove(k);
+            @SuppressWarnings("unchecked")
+            ConfigValueAtContainer<TContainer, Object> vp = vpr==null ? null : 
(ConfigValueAtContainer<TContainer,Object>) vpr.getWithoutError();
+            ConfigInheritance inh = ConfigInheritances.findInheritance(k, 
InheritanceContext.RUNTIME_MANAGEMENT, getDefaultRuntimeInheritance());
+            ConfigValueAtContainer<TContainer,Object> vl = new 
BasicConfigValueAtContainer<TContainer,Object>(getContainer(), k, 
Maybe.ofAllowingNull(v));
+            ReferenceWithError<ConfigValueAtContainer<TContainer, Object>> vlr 
= null;
+            if (inh.considerParent(vl, vp, 
InheritanceContext.RUNTIME_MANAGEMENT)) {
+                vlr = inh.resolveWithParent(vl, vp, 
InheritanceContext.RUNTIME_MANAGEMENT);
+            } else {
+                // no need to consider parent, just take vl
+                vlr = ReferenceWithError.newInstanceWithoutError(vl);
+            }
+            if (onlyReinheritable) {
+                if (ConfigInheritances.findInheritance(k, 
InheritanceContext.RUNTIME_MANAGEMENT, getDefaultRuntimeInheritance())
+                        .isReinheritable(vl, 
InheritanceContext.RUNTIME_MANAGEMENT)) {
+                    // continue
+                } else {
+                    // skip this one
+                    continue;
+                }
+            }
+            @SuppressWarnings("unchecked")
+            ReferenceWithError<ConfigValueAtContainer<TContainer, ?>> vlro = 
(ReferenceWithError<ConfigValueAtContainer<TContainer, ?>>) 
(ReferenceWithError<?>) vlr;
+            result.put(k, vlro);
+        }
+        result.putAll(parents);
+        
+        return result;
+    }
+    
     @Override
     public String toString() {
         Map<ConfigKey<?>, Object> sanitizeConfig;

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/config/internal/AncestorContainerAndKeyValueIterator.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/config/internal/AncestorContainerAndKeyValueIterator.java
 
b/core/src/main/java/org/apache/brooklyn/core/config/internal/AncestorContainerAndKeyValueIterator.java
index 62fb970..f20f0d0 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/config/internal/AncestorContainerAndKeyValueIterator.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/config/internal/AncestorContainerAndKeyValueIterator.java
@@ -30,16 +30,19 @@ import com.google.common.base.Function;
 public class AncestorContainerAndKeyValueIterator<TContainer,TValue> 
implements Iterator<ConfigValueAtContainer<TContainer,TValue>> {
     private TContainer lastContainer;
     private final Function<TContainer, ConfigKey<TValue>> keyFindingFunction; 
-    private final Function<TContainer, Maybe<TValue>> localEvaluationFunction; 
+    private final Function<TContainer, Maybe<Object>> 
lookupResolutionFunction; 
+    private final Function<Maybe<Object>, Maybe<TValue>> coercionFunction; 
     private final Function<TContainer, TContainer> parentFunction;
     
     public AncestorContainerAndKeyValueIterator(TContainer childContainer, 
             Function<TContainer, ConfigKey<TValue>> keyFindingFunction, 
-            Function<TContainer, Maybe<TValue>> localEvaluationFunction, 
+            Function<TContainer, Maybe<Object>> lookupResolutionFunction, 
+            Function<Maybe<Object>, Maybe<TValue>> coercionFunction, 
             Function<TContainer, TContainer> parentFunction) {
         this.lastContainer = childContainer;
         this.keyFindingFunction = keyFindingFunction;
-        this.localEvaluationFunction = localEvaluationFunction;
+        this.lookupResolutionFunction = lookupResolutionFunction;
+        this.coercionFunction = coercionFunction;
         this.parentFunction = parentFunction;
     }
 
@@ -53,7 +56,8 @@ public class 
AncestorContainerAndKeyValueIterator<TContainer,TValue> implements
         TContainer nextContainer = parentFunction.apply(lastContainer);
         if (nextContainer==null) throw new NoSuchElementException("Cannot 
search ancestors further than "+lastContainer);
         lastContainer = nextContainer;
-        return new 
LazyContainerAndKeyValue<TContainer,TValue>(keyFindingFunction.apply(lastContainer),
 lastContainer, localEvaluationFunction);
+        return new 
LazyContainerAndKeyValue<TContainer,TValue>(keyFindingFunction.apply(lastContainer),
 lastContainer, 
+            lookupResolutionFunction, coercionFunction);
     }
 
     @Override

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/config/internal/BasicConfigValueAtContainer.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/config/internal/BasicConfigValueAtContainer.java
 
b/core/src/main/java/org/apache/brooklyn/core/config/internal/BasicConfigValueAtContainer.java
deleted file mode 100644
index 79041d4..0000000
--- 
a/core/src/main/java/org/apache/brooklyn/core/config/internal/BasicConfigValueAtContainer.java
+++ /dev/null
@@ -1,54 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements.  See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership.  The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied.  See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-package org.apache.brooklyn.core.config.internal;
-
-import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.config.ConfigValueAtContainer;
-import org.apache.brooklyn.util.guava.Maybe;
-
-public class BasicConfigValueAtContainer<TContainer,TValue> implements 
ConfigValueAtContainer<TContainer,TValue> {
-    
-    TContainer container = null;
-    Maybe<TValue> value = Maybe.absent();
-    boolean valueWasExplicitlySet;
-    ConfigKey<TValue> key = null;
-    
-    @Override public TContainer getContainer() { return container; }
-    @Override public TValue get() { return value.orNull(); }
-    @Override public Maybe<TValue> asMaybe() { return value; }
-    @Override public boolean isValueExplicitlySet() { return 
valueWasExplicitlySet; }
-    @Override public ConfigKey<TValue> getKey() { return key; }
-    @Override public TValue getDefaultValue() { return 
getDefaultValueMaybe().orNull(); }
-    
-    public void setContainer(TContainer container) {
-        this.container = container;
-    }
-    public void setValue(Maybe<TValue> value) {
-        this.value = value;
-    }
-    public void setValueWasExplicitlySet(boolean valueWasExplicitlySet) {
-        this.valueWasExplicitlySet = valueWasExplicitlySet;
-    }
-    public void setKey(ConfigKey<TValue> key) {
-        this.key = key;
-    }
-    
-    public Maybe<TValue> getDefaultValueMaybe() { return key!=null && 
key.hasDefaultValue() ? Maybe.ofAllowingNull(key.getDefaultValue()) : 
Maybe.<TValue>absent(); }
-    
-}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/config/internal/LazyContainerAndKeyValue.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/config/internal/LazyContainerAndKeyValue.java
 
b/core/src/main/java/org/apache/brooklyn/core/config/internal/LazyContainerAndKeyValue.java
index df11735..fec13af 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/config/internal/LazyContainerAndKeyValue.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/config/internal/LazyContainerAndKeyValue.java
@@ -28,18 +28,23 @@ public class LazyContainerAndKeyValue<TContainer,TValue> 
implements ConfigValueA
     
     private final TContainer container;
     private final ConfigKey<TValue> key;
-    private final Function<TContainer,Maybe<TValue>> evaluationFunction;
+    private final Function<TContainer,Maybe<Object>> lookupResolutionFunction;
+    private final Function<Maybe<Object>,Maybe<TValue>> conversionFunction;
     private Maybe<TValue> resolved;
     
-    public LazyContainerAndKeyValue(ConfigKey<TValue> key, TContainer 
container, Function<TContainer, Maybe<TValue>> evaluationFunction) {
+    public LazyContainerAndKeyValue(ConfigKey<TValue> key, TContainer 
container, 
+            Function<TContainer, Maybe<Object>> lookupResolutionFunction,
+            Function<Maybe<Object>, Maybe<TValue>> conversionFunction) {
         this.key = key;
         this.container = container;
-        this.evaluationFunction = evaluationFunction;
+        this.lookupResolutionFunction = lookupResolutionFunction;
+        this.conversionFunction = conversionFunction;
     }
 
     protected synchronized Maybe<TValue> resolve() {
         if (resolved==null) { 
-            resolved = evaluationFunction.apply(getContainer());
+            resolved = conversionFunction.apply(
+                lookupResolutionFunction.apply(getContainer()));
         }
         return resolved;
     }
@@ -52,13 +57,13 @@ public class LazyContainerAndKeyValue<TContainer,TValue> 
implements ConfigValueA
     @Override
     public TValue get() {
         if (resolve().isPresent()) return resolve().get();
-        return getDefaultValue();
+        return getDefaultValue().orNull();
     }
     
     @Override
     public Maybe<TValue> asMaybe() {
         if (resolve().isPresent()) return resolve();
-        return getDefaultValueMaybe();
+        return getDefaultValue();
     }
 
     @Override
@@ -72,12 +77,8 @@ public class LazyContainerAndKeyValue<TContainer,TValue> 
implements ConfigValueA
     }
 
     @Override
-    public TValue getDefaultValue() {
-        return getDefaultValueMaybe().orNull();
-    }
-    
-    public Maybe<TValue> getDefaultValueMaybe() {
+    public Maybe<TValue> getDefaultValue() {
         if (key==null || !key.hasDefaultValue()) return Maybe.absent();
-        return Maybe.of(key.getDefaultValue());
+        return 
conversionFunction.apply(Maybe.of((Object)key.getDefaultValue()));
     }
-}
\ No newline at end of file
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java
 
b/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java
index 29c1480..1f46314 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/effector/ssh/SshEffectorTasks.java
@@ -20,6 +20,7 @@ package org.apache.brooklyn.core.effector.ssh;
 
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import javax.annotation.Nullable;
 
@@ -30,17 +31,16 @@ import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.config.StringConfigMap;
 import org.apache.brooklyn.core.config.ConfigKeys;
+import org.apache.brooklyn.core.config.ConfigPredicates;
 import org.apache.brooklyn.core.config.ConfigUtils;
 import org.apache.brooklyn.core.effector.EffectorBody;
 import org.apache.brooklyn.core.effector.EffectorTasks;
 import org.apache.brooklyn.core.effector.EffectorTasks.EffectorTaskFactory;
-import org.apache.brooklyn.core.effector.ssh.SshEffectorTasks;
 import org.apache.brooklyn.core.entity.EntityInternal;
 import org.apache.brooklyn.core.location.internal.LocationInternal;
 import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
 import org.apache.brooklyn.location.ssh.SshMachineLocation;
+import org.apache.brooklyn.util.collections.MutableSet;
 import org.apache.brooklyn.util.core.config.ConfigBag;
 import org.apache.brooklyn.util.core.internal.ssh.SshTool;
 import org.apache.brooklyn.util.core.task.Tasks;
@@ -53,7 +53,10 @@ import 
org.apache.brooklyn.util.core.task.ssh.internal.AbstractSshExecTaskFactor
 import org.apache.brooklyn.util.core.task.ssh.internal.PlainSshExecTaskFactory;
 import org.apache.brooklyn.util.core.task.system.ProcessTaskFactory;
 import org.apache.brooklyn.util.core.task.system.ProcessTaskWrapper;
+import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.ssh.BashCommands;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
 
 import com.google.common.annotations.Beta;
 import com.google.common.base.Function;
@@ -291,42 +294,42 @@ public class SshEffectorTasks {
      * the SshTool is created or re-used by the SshMachineLocation making use 
of these properties */
     @Beta
     public static Map<String, Object> getSshFlags(Entity entity, Location 
optionalLocation) {
-        ConfigBag allConfig = ConfigBag.newInstance();
+        Set<ConfigKey<?>> sshConfig = MutableSet.of();
         
-        StringConfigMap globalConfig = 
((EntityInternal)entity).getManagementContext().getConfig();
-        allConfig.putAll(globalConfig.getAllConfig());
+        
sshConfig.addAll(((EntityInternal)entity).config().findKeys(ConfigPredicates.nameStartsWith(SshTool.BROOKLYN_CONFIG_KEY_PREFIX)));
         
         if (optionalLocation!=null)
-            
allConfig.putAll(((LocationInternal)optionalLocation).config().getBag());
+            
sshConfig.addAll(optionalLocation.config().findKeys(ConfigPredicates.nameStartsWith(SshTool.BROOKLYN_CONFIG_KEY_PREFIX)));
         
-        allConfig.putAll(((EntityInternal)entity).config().getBag());
+        StringConfigMap globalConfig = 
((EntityInternal)entity).getManagementContext().getConfig();
+        
sshConfig.addAll(globalConfig.findKeys(ConfigPredicates.nameStartsWith(SshTool.BROOKLYN_CONFIG_KEY_PREFIX)));
         
         Map<String, Object> result = Maps.newLinkedHashMap();
-        for (String keyS : allConfig.getAllConfig().keySet()) {
-            if (keyS.startsWith(SshTool.BROOKLYN_CONFIG_KEY_PREFIX)) {
-                ConfigKey<?> key = ConfigKeys.newConfigKey(Object.class, keyS);
-                
-                Object val = allConfig.getStringKey(keyS);
-                
-                /*
-                 * NOV 2013 changing this to rely on config above being 
inserted in the right order,
-                 * so entity config will be preferred over location, and 
location over global.
-                 * If that is consistent then remove the lines below.
-                 * (We can also accept null entity and so combine with 
SshTasks.getSshFlags.)
-                 */
-                
-//                // have to use raw config to test whether the config is set
-//                Object val = 
((EntityInternal)entity).getConfigMap().getRawConfig(key);
-//                if (val!=null) {
-//                    val = entity.getConfig(key);
-//                } else {
-//                    val = globalConfig.getRawConfig(key);
-//                    if (val!=null) val = globalConfig.getConfig(key);
-//                }
-//                if (val!=null) {
-                    
result.put(ConfigUtils.unprefixedKey(SshTool.BROOKLYN_CONFIG_KEY_PREFIX, 
key).getName(), val);
-//                }
+        for (ConfigKey<?> key : sshConfig) {
+            /*
+             * Rely on config in the right order:
+             * entity config will be preferred over location, and location 
over global.
+             * (We can also accept null entity and so combine with 
SshTasks.getSshFlags.)
+             */
+            
+            Maybe<Object> mv = ((EntityInternal)entity).config().getRaw(key);
+            Object v = null;
+            if (v==null && mv.isPresent()) {
+                v = entity.config().get(key);
+            }
+            
+            if (mv.isAbsent() && optionalLocation!=null) {
+                mv = ((LocationInternal)optionalLocation).config().getRaw(key);
+            }
+            if (v==null && mv.isPresent()) {
+                v = optionalLocation.config().get(key);
+            }
+
+            if (mv.isAbsent()) {
+                v = globalConfig.getConfig(key);
             }
+            
+            
result.put(ConfigUtils.unprefixedKey(SshTool.BROOKLYN_CONFIG_KEY_PREFIX, 
key).getName(), v);
         }
         return result;
     }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java 
b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
index 8ba1bc3..6c5f73e 100644
--- a/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
+++ b/core/src/main/java/org/apache/brooklyn/core/entity/AbstractEntity.java
@@ -408,7 +408,7 @@ public abstract class AbstractEntity extends 
AbstractBrooklynObject implements E
         
         if (!flags.isEmpty()) {
             LOG.warn("Unsupported flags when configuring {}; storing: {}", 
this, flags);
-            configsInternal.addToLocalBag(flags);
+            configsInternal.putAll(flags);
         }
 
         return this;
@@ -542,8 +542,8 @@ public abstract class AbstractEntity extends 
AbstractBrooklynObject implements E
             if (iconUrl.isNull()) iconUrl.set(oldIconUrl);
 
             configsInternal = new EntityConfigMap(this, 
managementContext.getStorage().<ConfigKey<?>, Object>getMap(getId()+"-config"));
-            if (oldConfig.getLocalConfig().size() > 0) {
-                configsInternal.setLocalConfig(oldConfig.getLocalConfig());
+            if (!oldConfig.isEmpty()) {
+                
configsInternal.setLocalConfig(oldConfig.getAllConfigLocalRaw());
             }
             config().refreshInheritedConfig();
 
@@ -1212,7 +1212,7 @@ public abstract class AbstractEntity extends 
AbstractBrooklynObject implements E
             ConfigConstraints.assertValid(AbstractEntity.this, key, val);
         }
         
-        protected AbstractConfigMapImpl getConfigsInternal() {
+        protected AbstractConfigMapImpl<?> getConfigsInternal() {
             return configsInternal;
         }
 

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/entity/internal/ConfigMapViewWithStringKeys.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/entity/internal/ConfigMapViewWithStringKeys.java
 
b/core/src/main/java/org/apache/brooklyn/core/entity/internal/ConfigMapViewWithStringKeys.java
index 7d91af4..38f83c7 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/entity/internal/ConfigMapViewWithStringKeys.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/entity/internal/ConfigMapViewWithStringKeys.java
@@ -24,21 +24,23 @@ import java.util.Map;
 import java.util.Set;
 
 import org.apache.brooklyn.config.ConfigKey;
+import org.apache.brooklyn.config.ConfigMap;
 import org.apache.brooklyn.core.config.BasicConfigKey;
 
-import com.google.common.annotations.Beta;
 import com.google.common.collect.Sets;
 
 /**
  * Internal class that presents a view over a ConfigMap, so it looks like a 
Map (with the
  * keys being the config key names).
+ * 
+ * @deprecated since 0.10.0 removed support, no longer needed
  */
-@Beta
+@Deprecated
 public class ConfigMapViewWithStringKeys implements Map<String,Object> {
 
-    private org.apache.brooklyn.config.ConfigMap target;
+    private ConfigMap target;
 
-    public ConfigMapViewWithStringKeys(org.apache.brooklyn.config.ConfigMap 
target) {
+    public ConfigMapViewWithStringKeys(ConfigMap target) {
         this.target = target;
     }
     

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/entity/internal/EntityConfigMap.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/entity/internal/EntityConfigMap.java
 
b/core/src/main/java/org/apache/brooklyn/core/entity/internal/EntityConfigMap.java
index 15f8ffa..400694e 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/entity/internal/EntityConfigMap.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/entity/internal/EntityConfigMap.java
@@ -26,28 +26,20 @@ import org.apache.brooklyn.api.entity.Entity;
 import org.apache.brooklyn.api.mgmt.ExecutionContext;
 import org.apache.brooklyn.api.mgmt.Task;
 import org.apache.brooklyn.api.objs.BrooklynObject;
-import org.apache.brooklyn.config.ConfigInheritance;
 import org.apache.brooklyn.config.ConfigKey;
-import org.apache.brooklyn.config.ConfigValueAtContainer;
-import org.apache.brooklyn.core.config.BasicConfigInheritance;
-import 
org.apache.brooklyn.core.config.BasicConfigInheritance.AncestorContainerAndKeyValueIterator;
-import org.apache.brooklyn.core.config.ConfigKeys.InheritanceContext;
 import org.apache.brooklyn.core.config.internal.AbstractConfigMapImpl;
-import org.apache.brooklyn.core.entity.EntityFunctions;
 import org.apache.brooklyn.core.entity.EntityInternal;
-import org.apache.brooklyn.core.objs.BrooklynObjectInternal;
 import 
org.apache.brooklyn.core.objs.BrooklynObjectInternal.ConfigurationSupportInternal;
-import org.apache.brooklyn.util.core.internal.ConfigKeySelfExtracting;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
-import com.google.common.base.Function;
 import com.google.common.base.Predicate;
 import com.google.common.collect.Maps;
 
-public class EntityConfigMap extends AbstractConfigMapImpl {
+public class EntityConfigMap extends AbstractConfigMapImpl<Entity> {
 
+    @SuppressWarnings("unused")
     private static final Logger LOG = 
LoggerFactory.getLogger(EntityConfigMap.class);
 
     public EntityConfigMap(EntityInternal entity) {
@@ -62,17 +54,17 @@ public class EntityConfigMap extends AbstractConfigMapImpl {
      * @deprecated since 0.10.0 kept for serialization */ @Deprecated
     private EntityInternal entity;
     @Override
-    public BrooklynObjectInternal getBrooklynObject() {
-        BrooklynObjectInternal result = super.getBrooklynObject();
-        if (result!=null) return result;
+    public EntityInternal getContainer() {
+        Entity result = super.getContainer();
+        if (result!=null) return (EntityInternal) result;
 
         synchronized (this) {
-            result = super.getBrooklynObject();
-            if (result!=null) return result;
+            result = super.getContainer();
+            if (result!=null) return (EntityInternal) result;
             bo = entity;
             entity = null;
         }
-        return super.getBrooklynObject();
+        return (EntityInternal) super.getBrooklynObject();
     }
 
     protected EntityInternal getEntity() {
@@ -99,45 +91,19 @@ public class EntityConfigMap extends AbstractConfigMapImpl {
             
((EntityInternal)bo).getManagementSupport().getEntityChangeListener().onConfigChanged(key);
         }
     }
-    
-    @Override
-    protected <T> Maybe<T> getConfigImpl(ConfigKey<T> key) {
-        Function<Entity, ConfigKey<T>> keyFn = 
EntityFunctions.configKeyFinder(key, null);
-        
-        // In case this entity class has overridden the given key (e.g. to set 
default), then retrieve this entity's key
-        ConfigKey<T> ownKey = keyFn.apply(getEntity());
-        if (ownKey==null) ownKey = key;
         
-        LocalEvaluateKeyValue<Entity,T> evalFn = new 
LocalEvaluateKeyValue<Entity,T>(ownKey);
-
-        if (ownKey instanceof ConfigKeySelfExtracting) {
-            Maybe<T> ownExplicitValue = evalFn.apply(getEntity());
-            
-            AncestorContainerAndKeyValueIterator<Entity, T> ckvi = new 
AncestorContainerAndKeyValueIterator<Entity,T>(
-                getEntity(), keyFn, evalFn, EntityFunctions.parent());
-            
-            ConfigValueAtContainer<Entity,T> result = 
getDefaultRuntimeInheritance().resolveInheriting(ownKey,
-                ownExplicitValue, getEntity(),
-                ckvi, InheritanceContext.RUNTIME_MANAGEMENT);
-        
-            return result.asMaybe();
-        } else {
-            LOG.warn("Config key {} of {} is not a ConfigKeySelfExtracting; 
cannot retrieve value; returning default", ownKey, getBrooklynObject());
-            return Maybe.absent();
-        }
-    }
-
-    private ConfigInheritance getDefaultRuntimeInheritance() {
-        return BasicConfigInheritance.OVERWRITE; 
+    @Override
+    protected Entity getParentOfContainer(Entity container) {
+        if (container==null) return null;
+        return container.getParent();
     }
 
     @Override
-    protected BrooklynObjectInternal getParent() {
-        return (EntityInternal) getEntity().getParent();
+    protected <T> ConfigKey<?> getKeyAtContainerImpl(Entity container, 
ConfigKey<T> queryKey) {
+        return container.getEntityType().getConfigKey(queryKey.getName());
     }
-    
-    @Override
-    // TODO deprecate or clarify syntax 
+
+    @Override @Deprecated
     public EntityConfigMap submap(Predicate<ConfigKey<?>> filter) {
         EntityConfigMap m = new EntityConfigMap(getEntity(), 
Maps.<ConfigKey<?>, Object>newLinkedHashMap());
         synchronized (ownConfig) {
@@ -153,9 +119,10 @@ public class EntityConfigMap extends AbstractConfigMapImpl 
{
         return m;
     }
 
+    @Deprecated
     private void merge(EntityConfigMap local, EntityConfigMap parent) {
         for (ConfigKey<?> k: parent.ownConfig.keySet()) {
-            // TODO apply inheritance
+            // should apply inheritance; but only used in submap which is 
deprecated
             if (!local.ownConfig.containsKey(k)) {
                 local.ownConfig.put(k, parent.ownConfig.get(k));
             }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynPropertiesImpl.java
----------------------------------------------------------------------
diff --git 
a/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynPropertiesImpl.java
 
b/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynPropertiesImpl.java
index 9ed6a17..03fb13d 100644
--- 
a/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynPropertiesImpl.java
+++ 
b/core/src/main/java/org/apache/brooklyn/core/internal/BrooklynPropertiesImpl.java
@@ -19,7 +19,6 @@
 package org.apache.brooklyn.core.internal;
 
 import static com.google.common.base.Preconditions.checkNotNull;
-import groovy.lang.Closure;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -29,9 +28,11 @@ import java.io.InputStream;
 import java.net.URL;
 import java.util.Arrays;
 import java.util.LinkedHashMap;
+import java.util.LinkedHashSet;
 import java.util.Map;
 import java.util.NoSuchElementException;
 import java.util.Properties;
+import java.util.Set;
 
 import org.apache.brooklyn.config.ConfigKey;
 import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
@@ -54,6 +55,8 @@ import com.google.common.base.Predicate;
 import com.google.common.base.Throwables;
 import com.google.common.collect.Maps;
 
+import groovy.lang.Closure;
+
 /**
  * TODO methods in this class are not thread safe.
  * intention is that they are set during startup and not modified thereafter.
@@ -455,13 +458,29 @@ public class BrooklynPropertiesImpl extends LinkedHashMap 
implements BrooklynPro
     }
     
     @Override
-    public Map<ConfigKey<?>, Object> getAllConfig() {
+    public Map<ConfigKey<?>,Object> getAllConfigLocalRaw() {
         Map<ConfigKey<?>, Object> result = new LinkedHashMap<ConfigKey<?>, 
Object>();
         for (Object entry: entrySet())
             result.put(new BasicConfigKey<Object>(Object.class, 
""+((Map.Entry)entry).getKey()), ((Map.Entry)entry).getValue());
         return result;
     }
 
+    @Override @Deprecated
+    public Map<ConfigKey<?>, Object> getAllConfig() {
+        return getAllConfigLocalRaw();
+    }
+
+    @Override
+    public Set<ConfigKey<?>> findKeys(Predicate<ConfigKey<?>> filter) {
+        Set<ConfigKey<?>> result = new LinkedHashSet<ConfigKey<?>>();
+        for (Object entry: entrySet()) {
+            ConfigKey<?> k = new BasicConfigKey<Object>(Object.class, 
""+((Map.Entry)entry).getKey());
+            if (filter.apply(k))
+                result.add(new BasicConfigKey<Object>(Object.class, 
""+((Map.Entry)entry).getKey()));
+        }
+        return result;
+    }
+    
     @Override
     public BrooklynPropertiesImpl submap(Predicate<ConfigKey<?>> filter) {
         BrooklynPropertiesImpl result = Factory.newEmpty();

Reply via email to