http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/utils/common/src/main/java/org/apache/brooklyn/config/ConfigInheritance.java
----------------------------------------------------------------------
diff --git 
a/utils/common/src/main/java/org/apache/brooklyn/config/ConfigInheritance.java 
b/utils/common/src/main/java/org/apache/brooklyn/config/ConfigInheritance.java
index e415a1c..dffa548 100644
--- 
a/utils/common/src/main/java/org/apache/brooklyn/config/ConfigInheritance.java
+++ 
b/utils/common/src/main/java/org/apache/brooklyn/config/ConfigInheritance.java
@@ -19,12 +19,14 @@
 package org.apache.brooklyn.config;
 
 import java.io.Serializable;
-import java.util.Iterator;
 import java.util.Map;
 
+import javax.annotation.Nonnull;
 import javax.annotation.Nullable;
 
+import 
org.apache.brooklyn.config.ConfigInheritances.BasicConfigValueAtContainer;
 import org.apache.brooklyn.util.collections.CollectionMerger;
+import org.apache.brooklyn.util.exceptions.ReferenceWithError;
 import org.apache.brooklyn.util.guava.Maybe;
 import org.apache.brooklyn.util.text.Strings;
 
@@ -33,7 +35,8 @@ import com.google.common.annotations.Beta;
 @SuppressWarnings("serial")
 public interface ConfigInheritance extends Serializable {
     
-    /** marker interface for inheritance contexts, for keys which can define 
one or more inheritance patterns */
+    /** marker interface for inheritance contexts, for keys which can define 
one or more inheritance patterns;
+     * implementers can define their own, e.g. in an enum */
     public interface ConfigInheritanceContext {}
 
     /** @deprecated since 0.10.0 see implementations of this interface */ 
@Deprecated
@@ -54,40 +57,64 @@ public interface ConfigInheritance extends Serializable {
     @Deprecated
     InheritanceMode isInherited(ConfigKey<?> key, Object from, Object to);
 
-    /** 
-     * given a key and local value, together with an optional record of 
ancestor containers (eg an entity) and associated data,
-     * this finds the value for a config key <b>applying the appropriate 
inheritance strategies</b>.
-     * for instance this may merge a map throughout a container hierarchy, 
-     * or this may traverse up until a non-reinheritable key definition is 
found and in the absence of values lower
-     * in the hierarchy this will return the default value of the key 
+    /** Returns whether any value from the given node or ancestors can be 
considered 
+     * for inheritance by descendants, according to the {@link 
ConfigInheritance} defined there.
+     * Implementations should not normally consider the value here
+     * as there may be other ancestors whose values have not yet been 
considered and are not supplied.
+     * <p> 
+     * If there is a {@link ConfigInheritance} defined at this node,
+     * this method must be called on that instance and that instance only.
+     * In that case it is an error to invoke this method on any other {@link 
ConfigInheritance} instance. 
+     * If there is not one, the config generally should be considered 
reinheritable.
      * <p>
-     * this uses an interface on the input so that:
-     * - the caller can supply the hierarchy
-     * - hierarchy is only traversed as far as needed
-     * - caller can do full resolution as required for local values
+     * Consumers will typically find the methods in {@link ConfigInheritances} 
more convenient. */
+    public <TContainer,TValue> boolean isReinheritable(
+        @Nullable ConfigValueAtContainer<TContainer,TValue> parent,
+        ConfigInheritanceContext context);
+    
+    /** Returns whether any value from the parent or its ancestors should be 
considered 
+     * by the given local container, according to the {@link 
ConfigInheritance} defined there.
+     * This defines the {@link ConfigInheritance} of the local container 
typically considering
+     * the value of the key there. 
+     * Implementations should not normally consider the value of the parent
+     * as there may be other ancestors whose values have not yet been 
considered and are not supplied,
+     * but it may determine that a local value is sufficient to render it 
unnecessary to consider the parent.
+     * <p>
+     * If there is a {@link ConfigInheritance} defined at the local container,
+     * this method must be called on that instance and that instance only.
+     * In that case it is an error to invoke this method on any other {@link 
ConfigInheritance} instance. 
      * <p>
-     * this returns in interface so that caller can get the value, 
-     * and if needed also find the container where the key is defined.
-     * that can be useful for when the value needs to be further resolved,
-     * e.g. a DSL function or a URL. the returned value may be evaluated 
lazily,
-     * i.e. the actual traversal and evaluation may be deferred until a method 
on
-     * the returned object is invoked.
+     * Consumers should consider this in conjuction with the 
+     * {@link #isReinheritable(ConfigValueAtContainer, 
ConfigInheritanceContext)}
+     * status of the parent (if present).
+     * Implementers need not duplicate a call to that method. 
+     * Consumers will typically find the methods in {@link ConfigInheritances} 
more convenient. */
+    public <TContainer,TValue> boolean considerParent(
+        @Nonnull ConfigValueAtContainer<TContainer,TValue> local,
+        @Nullable ConfigValueAtContainer<TContainer,TValue> parent,
+        ConfigInheritanceContext context);
+
+    /** Returns the result after inheritance between the local container and a 
"resolveParent" 
+     * representation of the parent's evaluation of the key considering its 
ancestors.
+     * The parent here can be assumed to be the result of resolution with its 
ancestors,
+     * and reinheritance can be assumed to be permitted. 
+     * Consumers should invoke this only after checking 
+     * {@link #considerParent(ConfigValueAtContainer, ConfigValueAtContainer, 
ConfigInheritanceContext)}
+     * on the local node and {@link #isReinheritable(ConfigValueAtContainer, 
ConfigInheritanceContext)}
+     * on the original parent node, 
+     * and then {@link #resolveWithParent(ConfigValueAtContainer, 
ConfigValueAtContainer, ConfigInheritanceContext)}
+     * on the original parent node with its respective resolvedParent.
      * <p>
-     * this object is taken as the default inheritance and used if no 
inheritance is
-     * defined on the key.
+     * If there is a {@link ConfigInheritance} defined at the local container,
+     * this method must be called on that instance and that instance only.
+     * In that case it is an error to invoke this method on any other {@link 
ConfigInheritance} instance. 
      * <p>
-     * so that the caller can determine if a key/value is to be exported to 
children from a container,
-     * this method should accept an iterable whose first entry has a null 
container
-     * and whose second entry gives the container, key, and potential value to 
be exported.
-     * if null is returned the caller knows nothing is to be exported to 
children.
-     */
-    <TContainer,TValue> ConfigValueAtContainer<TContainer,TValue> 
resolveInheriting(
-        ConfigKey<TValue> key,
-        @Nullable Maybe<TValue> localValue,
-        @Nullable TContainer container,
-        Iterator<? extends ConfigValueAtContainer<TContainer,TValue>> 
ancestorContainerKeyValues,
+     * Consumers will typically find the methods in {@link ConfigInheritances} 
more convenient. */
+    public <TContainer,TValue> 
ReferenceWithError<ConfigValueAtContainer<TContainer,TValue>> resolveWithParent(
+        @Nonnull ConfigValueAtContainer<TContainer,TValue> local,
+        @Nonnull ConfigValueAtContainer<TContainer,TValue> resolvedParent,
         ConfigInheritanceContext context);
-    
+
     /** @deprecated since 0.10.0 see implementations of this interface */ 
@Deprecated
     public static class Legacy {
         public static ConfigInheritance fromString(String val) {
@@ -105,71 +132,43 @@ public interface ConfigInheritance extends Serializable {
             }
         }
         private abstract static class LegacyAbstractConversion implements 
ConfigInheritance {
-            private static class Result<TContainer,TValue> implements 
ConfigValueAtContainer<TContainer,TValue> {
-                TContainer container = null;
-                Maybe<TValue> value = Maybe.absent();
-                boolean isValueSet = false;
-                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 
isValueSet; }
-                @Override public ConfigKey<TValue> getKey() { return key; }
-                @Override public TValue getDefaultValue() { return key==null ? 
null : key.getDefaultValue(); }
+
+            @Override
+            public <TContainer, TValue> boolean 
isReinheritable(ConfigValueAtContainer<TContainer, TValue> parent, 
ConfigInheritanceContext context) {
+                return getMode()!=InheritanceMode.NONE;
+            }
+            
+            @Override
+            public <TContainer,TValue> boolean considerParent(
+                    ConfigValueAtContainer<TContainer,TValue> local,
+                    @Nullable ConfigValueAtContainer<TContainer,TValue> parent,
+                    ConfigInheritanceContext context) {
+                if (parent==null) return false;
+                if (getMode()==InheritanceMode.NONE) return false;
+                if (getMode()==InheritanceMode.IF_NO_EXPLICIT_VALUE) return 
!local.isValueExplicitlySet();
+                return true;
             }
 
-            // close copy of method in BasicConfigInheritance for this legacy 
compatibility evaluation
             @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 (getMode()==InheritanceMode.IF_NO_EXPLICIT_VALUE && 
localValue.isPresent()) {
-                    // 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) inh2 = this;
-                    if (getMode()==InheritanceMode.NONE) {
-                        // can't inherit
-                    } else {
-                        // get inherited value
-                        v2 = inh2.resolveInheriting(c.getKey(), 
-                            c.isValueExplicitlySet() ? c.asMaybe() : 
Maybe.<TValue>absent(), c.getContainer(), 
-                                ancestorContainerKeyValues, context);
-                    }
-                }
+            public <TContainer,TValue> 
ReferenceWithError<ConfigValueAtContainer<TContainer,TValue>> resolveWithParent(
+                    ConfigValueAtContainer<TContainer,TValue> local,
+                    ConfigValueAtContainer<TContainer,TValue> parent,
+                    ConfigInheritanceContext context) {
+                // parent can be assumed to be set, but might not have a value
+                if (!parent.isValueExplicitlySet())
+                    return ReferenceWithError.newInstanceWithoutError(new 
BasicConfigValueAtContainer<TContainer,TValue>(local));
+                    
+                if (!local.isValueExplicitlySet()) 
+                    return ReferenceWithError.newInstanceWithoutError(new 
BasicConfigValueAtContainer<TContainer,TValue>(parent));
 
-                if (v2!=null && v2.isValueExplicitlySet() && 
!localValue.isPresent()) return v2;
-                Result<TContainer,TValue> v = new Result<TContainer,TValue>();
-                v.container = container;
-                if (v2==null || !v2.isValueExplicitlySet()) {
-                    v.isValueSet = localValue.isPresent();
-                    v.value = v.isValueExplicitlySet() ? localValue : 
-                        key!=null && key.hasDefaultValue() ? 
Maybe.of(key.getDefaultValue()) : Maybe.<TValue>absent(); 
-                } else {
-                    v.value = Maybe.of(resolveConflict(key, localValue, 
v2.asMaybe()));
-                    v.isValueSet = true;
-                }
-                return v;
-            }
-            /** only invoked if there is an ancestor value; custom strategies 
can overwrite */
-            protected <T> T resolveConflict(ConfigKey<T> key, Maybe<T> 
localValue, Maybe<T> ancestorValue) {
-                if (getMode()==InheritanceMode.IF_NO_EXPLICIT_VALUE) {
-                    if (localValue.isPresent()) return localValue.get();
-                    return ancestorValue.orNull();
-                }
+                // both explicitly set, and not overwrite or none
                 if (getMode()==InheritanceMode.DEEP_MERGE) {
-                    return deepMerge(localValue, ancestorValue).orNull();
+                    BasicConfigValueAtContainer<TContainer, TValue> result = 
new BasicConfigValueAtContainer<TContainer,TValue>(local);
+                    result.setValue( deepMerge(local.asMaybe(), 
parent.asMaybe()) );
+                    return ReferenceWithError.newInstanceWithoutError(result);
                 }
-                throw new IllegalStateException("Unknown config conflict 
resolution strategy '"+getMode()+"' evaluating "+key);
+                
+                throw new IllegalStateException("Unknown config conflict 
resolution strategy '"+getMode()+"' evaluating "+local+"/"+parent);
             }
             private static <T> Maybe<? extends T> deepMerge(Maybe<? extends T> 
val1, Maybe<? extends T> val2) {
                 if (val2.isAbsent() || val2.isNull()) {
@@ -187,6 +186,7 @@ public interface ConfigInheritance extends Serializable {
                     return val1;
                 }
             }
+            
             @Override
             public InheritanceMode isInherited(ConfigKey<?> key, Object from, 
Object to) {
                 return getMode();

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/utils/common/src/main/java/org/apache/brooklyn/config/ConfigInheritances.java
----------------------------------------------------------------------
diff --git 
a/utils/common/src/main/java/org/apache/brooklyn/config/ConfigInheritances.java 
b/utils/common/src/main/java/org/apache/brooklyn/config/ConfigInheritances.java
new file mode 100644
index 0000000..95d80ff
--- /dev/null
+++ 
b/utils/common/src/main/java/org/apache/brooklyn/config/ConfigInheritances.java
@@ -0,0 +1,185 @@
+/*
+ * 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.config;
+
+import java.util.Iterator;
+
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.config.ConfigInheritance.ConfigInheritanceContext;
+import org.apache.brooklyn.util.exceptions.ReferenceWithError;
+import org.apache.brooklyn.util.guava.Maybe;
+
+public class ConfigInheritances {
+    
+    /** 
+     * given a key and local value, together with an optional record of 
ancestor containers (eg an entity) and associated data,
+     * this finds the value for a config key <b>applying the appropriate 
inheritance strategies</b>.
+     * for instance this may merge a map throughout a container hierarchy, 
+     * or this may traverse up until a non-reinheritable key definition is 
found and in the absence of values lower
+     * in the hierarchy this will return the default value of the key 
+     * <p>
+     * this uses an interface on the input so that:
+     * - the caller can supply the hierarchy
+     * - hierarchy is only traversed as far as needed
+     * - caller can do full resolution as required for local values
+     * <p>
+     * this returns in interface so that caller can get the value, 
+     * and if needed also find the container where the key is defined.
+     * that can be useful for when the value needs to be further resolved,
+     * e.g. a DSL function or a URL. the returned value may be evaluated 
lazily,
+     * i.e. the actual traversal and evaluation may be deferred until a method 
on
+     * the returned object is invoked.
+     * <p>
+     * this object is taken as the default inheritance and used if no 
inheritance is
+     * defined on the key.
+     * <p>
+     * so that the caller can determine if a key/value is to be exported to 
children from a container,
+     * this method should accept an iterable whose first entry has a null 
container
+     * and whose second entry gives the container, key, and potential value to 
be exported.
+     * if null is returned the caller knows nothing is to be exported to 
children.
+     */
+    public static <TContainer,TValue> 
ReferenceWithError<ConfigValueAtContainer<TContainer,TValue>> resolveInheriting(
+            @Nullable TContainer container,
+            ConfigKey<TValue> key,
+            @Nullable Maybe<TValue> localValue,
+            @Nullable Maybe<TValue> defaultValue,
+            
+            Iterator<? extends ConfigValueAtContainer<TContainer,TValue>> 
ancestorContainerKeyValues,
+            ConfigInheritanceContext context,
+            ConfigInheritance defaultInheritance) {
+        return resolveInheriting(new 
BasicConfigValueAtContainer<TContainer,TValue>(container, key, localValue, 
localValue.isPresent(), defaultValue), 
+            ancestorContainerKeyValues, key, context, defaultInheritance);
+    }
+    
+    /** as {@link #resolveInheriting(Object, ConfigKey, Maybe, Iterator, 
ConfigInheritanceContext, ConfigInheritance)}
+     * but convenient when the local info is already in a {@link 
ConfigValueAtContainer} */
+    public static <TContainer,TValue> 
ReferenceWithError<ConfigValueAtContainer<TContainer,TValue>> resolveInheriting(
+        ConfigValueAtContainer<TContainer,TValue> local,
+        Iterator<? extends ConfigValueAtContainer<TContainer,TValue>> 
ancestorContainerKeyValues,
+        ConfigKey<TValue> queryKey,
+        ConfigInheritanceContext context,
+        ConfigInheritance defaultInheritance) {
+                    
+        if (ancestorContainerKeyValues.hasNext()) {
+            ConfigValueAtContainer<TContainer, TValue> parent = 
ancestorContainerKeyValues.next();
+            ConfigInheritance parentInheritance = findInheritance(parent, 
context, null);
+            if (parentInheritance==null || 
parentInheritance.isReinheritable(parent, context)) {
+                ConfigInheritance currentInheritance = findInheritance(local, 
context, findInheritance(queryKey, context, defaultInheritance));
+                if (currentInheritance.considerParent(local, parent, context)) 
{
+                    ReferenceWithError<ConfigValueAtContainer<TContainer, 
TValue>> parentResult = resolveInheriting(parent, ancestorContainerKeyValues, 
queryKey, context, currentInheritance);
+                    
ReferenceWithError<ConfigValueAtContainer<TContainer,TValue>> resultWithParent 
= currentInheritance.resolveWithParent(local, parentResult.getWithoutError(), 
context);
+                    if (resultWithParent!=null && 
resultWithParent.getWithoutError()!=null && 
resultWithParent.getWithoutError().isValueExplicitlySet()) {
+                        if (!resultWithParent.hasError() && parentResult!=null 
&& parentResult.hasError()) {
+                            return 
ReferenceWithError.newInstanceThrowingError(resultWithParent.getWithoutError(), 
parentResult.getError());
+                        }
+                        return resultWithParent;
+                    }
+                }
+            }
+        }
+        BasicConfigValueAtContainer<TContainer, TValue> result = new 
BasicConfigValueAtContainer<TContainer, TValue>(local);
+        if (!local.isValueExplicitlySet() && 
local.getDefaultValue().isPresent()) {
+            result.value = local.getDefaultValue();
+        }
+        return ReferenceWithError.newInstanceWithoutError(result);
+    }
+    
+    /** finds the {@link ConfigInheritance} to use based on the given 
container, or the default if none is present there */
+    public static ConfigInheritance 
findInheritance(ConfigValueAtContainer<?,?> local, ConfigInheritanceContext 
context, ConfigInheritance defaultInheritance) {
+        if (local==null) return defaultInheritance;
+        return findInheritance(local.getKey(), context, defaultInheritance);
+    }
+    public static ConfigInheritance findInheritance(ConfigKey<?> localKey, 
ConfigInheritanceContext context, ConfigInheritance defaultInheritance) {
+        if (localKey==null) return defaultInheritance;
+        ConfigInheritance keyInheritance = 
localKey.getInheritanceByContext(context);
+        if (keyInheritance==null) return defaultInheritance;
+        return keyInheritance;
+    }
+
+    
+    public static class BasicConfigValueAtContainer<TContainer,TValue> 
implements ConfigValueAtContainer<TContainer,TValue> {
+        
+        TContainer container = null;
+        Maybe<? extends TValue> value = Maybe.absent();
+        boolean valueWasExplicitlySet = false;
+        ConfigKey<? extends TValue> key = null;
+        Maybe<TValue> defaultValue = null;
+        
+        public BasicConfigValueAtContainer() {}
+        public 
BasicConfigValueAtContainer(ConfigValueAtContainer<TContainer,TValue> toCopy) {
+            this(toCopy.getContainer(), toCopy.getKey(), toCopy.asMaybe(), 
toCopy.isValueExplicitlySet(), toCopy.getDefaultValue());
+        }
+        public BasicConfigValueAtContainer(TContainer container, ConfigKey<? 
extends TValue> key, Maybe<? extends TValue> value) {
+            this(container, key, value, value.isPresent());
+        }
+        public BasicConfigValueAtContainer(TContainer container, ConfigKey<? 
extends TValue> key, Maybe<? extends TValue> value, boolean isValueSet) {
+            this(container, key, value, isValueSet, null);
+        }
+        public BasicConfigValueAtContainer(TContainer container, ConfigKey<? 
extends TValue> key, Maybe<? extends TValue> value, boolean isValueSet, 
Maybe<TValue> defaultValue) {
+            this.container = container;
+            this.key = key;
+            this.valueWasExplicitlySet = isValueSet;
+            this.defaultValue = defaultValue;
+            this.value = value!=null && (value.isPresent() || isValueSet || 
key==null || !key.hasDefaultValue()) ? value 
+                : getDefaultValue();
+        }
+
+        @Override public TContainer getContainer() { return container; }
+        @Override public TValue get() { return value.orNull(); }
+        @Override public Maybe<? extends TValue> asMaybe() { return value; }
+        @Override public boolean isValueExplicitlySet() { return 
valueWasExplicitlySet; }
+        @Override public ConfigKey<? extends TValue> getKey() { return key; }
+        
+        public void setContainer(TContainer container) {
+            this.container = container;
+        }
+        public void setValue(Maybe<? extends TValue> value) {
+            this.value = value;
+        }
+        public void setValueWasExplicitlySet(boolean valueWasExplicitlySet) {
+            this.valueWasExplicitlySet = valueWasExplicitlySet;
+        }
+        public void setKey(ConfigKey<? extends TValue> key) {
+            this.key = key;
+        }
+        
+        public Maybe<TValue> getDefaultValue() { 
+            if (defaultValue!=null) return defaultValue;
+            // explicit absent default value means don't look at key
+            return key!=null && key.hasDefaultValue() ? 
Maybe.ofAllowingNull((TValue) key.getDefaultValue()) : Maybe.<TValue>absent(); 
+        }
+        
+    }
+    
+    /** 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) {
+        ConfigInheritance inh = ConfigInheritances.findInheritance(key, 
context, null);
+        if (inh==null) return true;
+        return inh.isReinheritable(null, null);
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/utils/common/src/main/java/org/apache/brooklyn/config/ConfigKey.java
----------------------------------------------------------------------
diff --git 
a/utils/common/src/main/java/org/apache/brooklyn/config/ConfigKey.java 
b/utils/common/src/main/java/org/apache/brooklyn/config/ConfigKey.java
index 4426aa8..a494c0b 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/config/ConfigKey.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/config/ConfigKey.java
@@ -103,9 +103,13 @@ public interface ConfigKey<T> {
      * @deprecated since 0.10.0 use {@link #getInheritanceByContext()} */ 
     @Deprecated @Nullable
     ConfigInheritance getInheritance();
-    
-    // TODO javadoc
+
+    /** @return The inheritance model for this key in the given {@link 
ConfigInheritanceContext} */ 
     @Nullable ConfigInheritance 
getInheritanceByContext(ConfigInheritanceContext context);
+    /** @return A summary of the inheritance models for this key in various 
{@link ConfigInheritanceContext} instances.
+     * Implementations may have a simple map, whereas others could be more 
sophisticated. 
+     * {@link #getInheritanceByContext(ConfigInheritanceContext)} may be 
preferred if inheritance contexts are complex
+     * (but usually, and in brooklyn, they aren't). */
     Map<ConfigInheritanceContext,ConfigInheritance> getInheritanceByContext();
 
     /**

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/utils/common/src/main/java/org/apache/brooklyn/config/ConfigMap.java
----------------------------------------------------------------------
diff --git 
a/utils/common/src/main/java/org/apache/brooklyn/config/ConfigMap.java 
b/utils/common/src/main/java/org/apache/brooklyn/config/ConfigMap.java
index 2cc5068..7b0b576 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/config/ConfigMap.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/config/ConfigMap.java
@@ -18,11 +18,15 @@
  */
 package org.apache.brooklyn.config;
 
+import java.util.List;
 import java.util.Map;
+import java.util.Set;
 
 import org.apache.brooklyn.config.ConfigKey.HasConfigKey;
+import org.apache.brooklyn.util.exceptions.ReferenceWithError;
 import org.apache.brooklyn.util.guava.Maybe;
 
+import com.google.common.annotations.Beta;
 import com.google.common.base.Predicate;
 
 public interface ConfigMap {
@@ -42,32 +46,12 @@ public interface ConfigMap {
      *        whether to traverse it or not; has no effects where there is no 
inheritance 
      * @return raw, unresolved, uncoerced value of key in map,  
      *         but <b>not</b> any default on the key
+     *         
+     * @deprecated since 0.10.0 in favour of {@link ConfigMapWithInheritance} 
methods
      */
-    // TODO behaviour of this is undefined if the key specifies a merge
+    @Deprecated  // and confirmed no uses
     public Maybe<Object> getConfigRaw(ConfigKey<?> key, boolean 
includeInherited);
 
-    // TODO sketch of new/better implementations
-//    /** As {@link #getConfigLocalRaw(ConfigKey)} but respecting the 
inheritance rules.
-//     * Because inheritance may not be applicable when working with raw 
values the result
-//     * is wrapped in a {@link ReferenceWithError}, and if any aspect of 
inheritance 
-//     * could not be applied, calls to {@link ReferenceWithError#get()} will 
throw
-//     * (but {@link ReferenceWithError#getWithoutError()} will not).
-//     * <p>
-//     * Note that most modes (eg overwrite, not-inherit) will not cause 
issues during inheritance
-//     * so this method is ordinarily fine to use.  Problems arise when a 
merge inheritance mode
-//     * is specified and it is attempting to merge a raw value which is not 
mergeable.
-//     * <p>
-//     * See also {@link #getConfigAllInheritedRaw(ConfigKey)} which returns 
the complete set
-//     * of inherited values.
-//     * 
-//     * @param key  key to look up
-//     */    
-//    public ReferenceWithError<ContainerAndValue<Object>> 
getConfigInheritedRaw(ConfigKey<?> key);
-//
-//    /** As {@link #getConfigLocalRaw(ConfigKey)} but returning all 
containers through the inheritance
-//     * hierarchy where a value is set (but stopping if it encounters a key 
is not inheritable from a container). */
-//    public List<ContainerAndValue<Object>> 
getConfigAllInheritedRaw(ConfigKey<?> key);
-    
     /** returns the value stored against the given key, 
      * <b>not</b> any default,
      * <b>not</b> inherited (if there is an inheritance hierarchy),
@@ -77,20 +61,85 @@ public interface ConfigMap {
      */
     public Maybe<Object> getConfigLocalRaw(ConfigKey<?> key);
 
-    /** returns a map of all config keys to their raw (unresolved+uncoerced) 
contents */
-    // TODO deprecate
+    /** returns a read-only map of all local config keys with their raw 
(unresolved+uncoerced) contents */
+    public Map<ConfigKey<?>,Object> getAllConfigLocalRaw();
+    
+    /** returns a map of all config keys to their raw (unresolved+uncoerced) 
contents 
+     *         
+     * @deprecated since 0.10.0 in favour of {@link #getAllConfigLocalRaw()} 
for local
+     * and {@link ConfigMapWithInheritance} methods for inherited;
+     * kept on some sub-interfaces (eg Brooklyn properties) */
+    @Deprecated  // and confirmed no uses (besides sub-interface)
     public Map<ConfigKey<?>,Object> getAllConfig();
 
-    /** returns submap matching the given filter predicate; see 
ConfigPredicates for common predicates */
+    /** returns submap matching the given filter predicate; see 
ConfigPredicates for common predicates
+     * @deprecated since 0.10.0 use {@link #findKeys(Predicate)} then do 
whatever is desired for the values;
+     * kept on {@link StringConfigMap} */
+    @Deprecated  // and confirmed no uses (besides sub-interface)
+    // deprecated because this becomes irritating to implement in a 
hierarchical world, it requires caching the predicate;
+    // also it encourages subsequent calls to deprecated methods such as 
#getAllConfig
     public ConfigMap submap(Predicate<ConfigKey<?>> filter);
+    
+    /** returns all keys matching the given filter predicate; see 
ConfigPredicates for common predicates */
+    public Set<ConfigKey<?>> findKeys(Predicate<ConfigKey<?>> filter);
 
     /** returns a read-only map view which has string keys (corresponding to 
the config key names);
      * callers encouraged to use the typed keys (and so not use this method),
-     * but in some compatibility areas having a Properties-like view is useful 
*/
+     * but in some compatibility areas having a Properties-like view is useful
+     * 
+     * @deprecated since 0.10.0 use the corresponding methods to return {@link 
ConfigKey}-based maps,
+     * then pass to a ConfigBag to get a string-map view; kept for {@link 
StringConfigMap}
+     */
+    @Deprecated  // and confirmed no uses (besides sub-interface)
     public Map<String,Object> asMapWithStringKeys();
     
     public int size();
     
     public boolean isEmpty();
     
+    public interface ConfigMapWithInheritance<TContainer> extends ConfigMap {
+        
+        /** Returns the container where a given key is defined, in addition to 
the value and data on the key it is defined against,
+         * wrapped in something which will report any error during evaluation 
(in some cases these errors may otherwise
+         * be silently ignored) */
+        public <T> ReferenceWithError<ConfigValueAtContainer<TContainer,T>> 
getConfigAndContainer(ConfigKey<T> key);
+        
+        /** As {@link #getConfigLocalRaw(ConfigKey)} but respecting the 
inheritance rules.
+         * Because inheritance may not be applicable when working with raw 
values the result
+         * is wrapped in a {@link ReferenceWithError}, and if any aspect of 
inheritance 
+         * could not be applied, calls to {@link ReferenceWithError#get()} 
will throw
+         * (but {@link ReferenceWithError#getWithoutError()} will not).
+         * Default values will be available from {@link 
ConfigValueAtContainer#getDefaultValue()}
+         * but will not be considered for {@link ConfigValueAtContainer#get()} 
or {@link ConfigValueAtContainer#asMaybe()}.
+         * <p>
+         * Note that most modes (eg overwrite, not-inherit) will not cause 
issues during inheritance
+         * so this method is ordinarily fine to use.  Problems arise when a 
merge inheritance mode
+         * is specified and it is attempting to merge a raw value which is not 
mergeable.
+         * <p>
+         * See also {@link #getConfigAllInheritedRaw(ConfigKey)} which returns 
the complete set
+         * of inherited values.
+         * 
+         * @param key  key to look up
+         */    
+        public ReferenceWithError<ConfigValueAtContainer<TContainer,?>> 
getConfigInheritedRaw(ConfigKey<?> key);
+    
+        /** As {@link #getConfigLocalRaw(ConfigKey)} but returning all 
containers through the inheritance
+         * hierarchy where a value is set (but stopping if it encounters a key 
is not inheritable from a container).
+         * <p>
+         * The list is in order with the highest ancestor first. Config 
inheritance strategies are not
+         * applied, apart from aborting ancestor traversal if inheritance of a 
key is blocked there. */
+        public List<ConfigValueAtContainer<TContainer,?>> 
getConfigAllInheritedRaw(ConfigKey<?> key);
+        
+        /** returns a read-only map of all config keys local and inherited 
together with best-effort raw values
+         * as per {@link #getConfigAllInheritedRaw(ConfigKey)} */
+        @Beta
+        public 
Map<ConfigKey<?>,ReferenceWithError<ConfigValueAtContainer<TContainer,?>>> 
getAllConfigInheritedRawWithErrors();
+        /** as {@link #getAllConfigInheritedRawWithErrors()} but simplified 
API, just giving values, ignoring any errors */
+        @Beta
+        public Map<ConfigKey<?>,Object> 
getAllConfigInheritedRawValuesIgnoringErrors();
+
+        /** as {@link #getAllConfigInheritedRaw()} but removes any entries 
which should not be re-inheritable by descendants */
+        public 
Map<ConfigKey<?>,ReferenceWithError<ConfigValueAtContainer<TContainer,?>>> 
getAllReinheritableConfigRaw();
+    }
+    
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/utils/common/src/main/java/org/apache/brooklyn/config/ConfigValueAtContainer.java
----------------------------------------------------------------------
diff --git 
a/utils/common/src/main/java/org/apache/brooklyn/config/ConfigValueAtContainer.java
 
b/utils/common/src/main/java/org/apache/brooklyn/config/ConfigValueAtContainer.java
index 38e1259..a4c60ca 100644
--- 
a/utils/common/src/main/java/org/apache/brooklyn/config/ConfigValueAtContainer.java
+++ 
b/utils/common/src/main/java/org/apache/brooklyn/config/ConfigValueAtContainer.java
@@ -24,17 +24,20 @@ import com.google.common.base.Supplier;
 
 public interface ConfigValueAtContainer<TContainer,TValue> extends 
Supplier<TValue> {
     
-    /** Returns the value, or null */
+    /** Returns the value for this key, or null.  Technically this returns 
{@link #asMaybe()} or null. */
     TValue get();
-    /** Absent if no value can be found, typically including no default value. 
*/ 
-    Maybe<TValue> asMaybe();
-    /** If false, the contents of {@link #get()} will have come from {@link 
#getDefaultValue()}. */
+    /** Absent if no value can be found, typically meaning no default value, 
but in raw value lookups it may ignore default values. */ 
+    Maybe<? extends TValue> asMaybe();
+    /** If false, any contents of {@link #get()} will have come from {@link 
#getDefaultValue()}. */
     boolean isValueExplicitlySet();
     
     /** The container where the value was found (possibly an ancestor of the 
queried object) */
     TContainer getContainer();
     
-    ConfigKey<TValue> getKey();
-    TValue getDefaultValue();
-    
+    ConfigKey<? extends TValue> getKey();
+    /** The default value on the key, if available and permitted, 
+     * possibly coerced or resolved in the scope of {@link #getContainer()},
+     * and possibly absent e.g. in raw value lookups */
+    Maybe<TValue> getDefaultValue();
+
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/utils/common/src/main/java/org/apache/brooklyn/config/StringConfigMap.java
----------------------------------------------------------------------
diff --git 
a/utils/common/src/main/java/org/apache/brooklyn/config/StringConfigMap.java 
b/utils/common/src/main/java/org/apache/brooklyn/config/StringConfigMap.java
index e0e8e8f..b327442 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/config/StringConfigMap.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/config/StringConfigMap.java
@@ -20,6 +20,8 @@ package org.apache.brooklyn.config;
 
 import java.util.Map;
 
+import com.google.common.base.Predicate;
+
 /** convenience extension where map is principally strings or converted to 
strings
  * (supporting BrooklynProperties) */
 public interface StringConfigMap extends ConfigMap {
@@ -32,4 +34,12 @@ public interface StringConfigMap extends ConfigMap {
      * and 'defaultIfNone' (a default value to return if there is no such 
property);
      * defaults to no warning and null default value */
     public String getFirst(@SuppressWarnings("rawtypes") Map flags, String... 
keys);
+    
+    /** returns submap matching the given filter predicate; see 
ConfigPredicates for common predicates */
+    public StringConfigMap submap(Predicate<ConfigKey<?>> filter);
+    
+    /** returns a read-only map view which has string keys (corresponding to 
the config key names);
+     * callers encouraged to use the typed keys (and so not use this method),
+     * but in some compatibility areas having a Properties-like view is useful 
*/
+    public Map<String,Object> asMapWithStringKeys();
 }

http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/0d655e05/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/ReferenceWithError.java
----------------------------------------------------------------------
diff --git 
a/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/ReferenceWithError.java
 
b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/ReferenceWithError.java
index 95ddd71..7885659 100644
--- 
a/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/ReferenceWithError.java
+++ 
b/utils/common/src/main/java/org/apache/brooklyn/util/exceptions/ReferenceWithError.java
@@ -31,18 +31,20 @@ public class ReferenceWithError<T> implements Supplier<T> {
     private final Throwable error;
     private final boolean maskError;
 
-    /** returns a reference which includes an error, and where attempts to get 
the content cause the error to throw */
-    public static <T> ReferenceWithError<T> newInstanceThrowingError(T object, 
Throwable error) {
+    /** returns a reference which includes an error, and where attempts to get 
the content cause the error to throw
+     * (unless the error supplied is null in which case behaviour is as per 
{@link #newInstanceWithoutError(Object)}) */
+    public static <T,U extends T> ReferenceWithError<T> 
newInstanceThrowingError(@Nullable U object, @Nullable Throwable error) {
         return new ReferenceWithError<T>(object, error, false);
     }
     
-    /** returns a reference which includes an error, but attempts to get the 
content do not cause the error to throw */
-    public static <T> ReferenceWithError<T> newInstanceMaskingError(T object, 
Throwable error) {
+    /** returns a reference which includes an error, but attempts to get the 
content do not cause the error to throw
+     * (unless the error supplied is null in which case behaviour is as per 
{@link #newInstanceWithoutError(Object)}) */
+    public static <T,U extends T> ReferenceWithError<T> 
newInstanceMaskingError(@Nullable U object, @Nullable Throwable error) {
         return new ReferenceWithError<T>(object, error, true);
     }
     
     /** returns a reference which does not have any error; attempts to get the 
content are safe */
-    public static <T> ReferenceWithError<T> newInstanceWithoutError(T object) {
+    public static <T,U extends T> ReferenceWithError<T> 
newInstanceWithoutError(@Nullable U object) {
         return new ReferenceWithError<T>(object, null, false);
     }
     
@@ -84,7 +86,7 @@ public class ReferenceWithError<T> implements Supplier<T> {
             Exceptions.propagate(error);
     }
 
-    /** returns the error (not throwing) */
+    /** returns the error (not throwing) or null if no error */
     public Throwable getError() {
         return error;
     }

Reply via email to