This is an automated email from the ASF dual-hosted git repository. heneveld pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/brooklyn-server.git
commit 55f1c81c39082cb201c9b47552ef459a763d243a Author: Alex Heneveld <[email protected]> AuthorDate: Wed Feb 13 13:42:22 2019 +0000 allow the types of parameters to be extended programmatically and misc comments to clarify some immediate resolution semantics --- .../brooklyn/core/config/ConfigConstraints.java | 5 +++ .../brooklyn/core/objs/BasicSpecParameter.java | 43 ++++++++++++++++------ .../brooklyn/core/objs/BrooklynObjectInternal.java | 5 +++ 3 files changed, 41 insertions(+), 12 deletions(-) diff --git a/core/src/main/java/org/apache/brooklyn/core/config/ConfigConstraints.java b/core/src/main/java/org/apache/brooklyn/core/config/ConfigConstraints.java index bcc9a25..a47c79a 100644 --- a/core/src/main/java/org/apache/brooklyn/core/config/ConfigConstraints.java +++ b/core/src/main/java/org/apache/brooklyn/core/config/ConfigConstraints.java @@ -156,6 +156,11 @@ public abstract class ConfigConstraints<T extends BrooklynObject> { if (!isValueValid(ck, maybeValue.get())) { violating.add(configKey); } + } else { + // absent means did not resolve in time or not coercible; + // code will return `Maybe.of(null)` if it is unset, + // and coercion errors are handled when the value is _set_ or _needed_ + // (this allows us to deal with edge cases where we can't *immediately* coerce) } } return violating; diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/BasicSpecParameter.java b/core/src/main/java/org/apache/brooklyn/core/objs/BasicSpecParameter.java index b2c24aa..640d6dd 100644 --- a/core/src/main/java/org/apache/brooklyn/core/objs/BasicSpecParameter.java +++ b/core/src/main/java/org/apache/brooklyn/core/objs/BasicSpecParameter.java @@ -27,6 +27,7 @@ import java.util.Date; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.function.BiFunction; import org.apache.brooklyn.api.catalog.CatalogConfig; import org.apache.brooklyn.api.entity.Entity; @@ -53,6 +54,7 @@ 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.guava.Maybe; +import org.apache.brooklyn.util.text.Strings; import org.apache.brooklyn.util.time.Duration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -73,7 +75,7 @@ public class BasicSpecParameter<T> implements SpecParameter<T>{ private static final long serialVersionUID = -4728186276307619778L; private static final Logger log = LoggerFactory.getLogger(BasicSpecParameter.class); - + private final String label; /** pinning may become a priority or other more expansive indicator */ @@ -197,6 +199,15 @@ public class BasicSpecParameter<T> implements SpecParameter<T>{ return type; } + /** Allows extensions to define additional types that are supported for parameters in YAML. + * Rules should return a TypeToken if the given name is known, null if not handled, or + * throw if the name is decisively problematic. Handlers will throw if no rules match. + */ + @Beta + public static void addCustomTypeNameInference(String ruleName, BiFunction<String,BrooklynClassLoadingContext,TypeToken<?>> rule) { + ParseYamlInputs.customTypeNameInferencing.put(ruleName, rule); + } + private static final class ParseYamlInputs { private static final String DEFAULT_TYPE = "string"; private static final Map<String, Class<?>> BUILT_IN_TYPES = ImmutableMap.<String, Class<?>>builder() @@ -217,6 +228,19 @@ public class BasicSpecParameter<T> implements SpecParameter<T>{ .put("port", PortRange.class) .build(); + /** Map of rule-name to rule; see {@link BasicSpecParameter#addCustomTypeNameInference(String, BiFunction)} */ + public static Map<String,BiFunction<String,BrooklynClassLoadingContext,TypeToken<?>>> customTypeNameInferencing = MutableMap.of(); + static { + customTypeNameInferencing.put("simple types ("+Strings.join(BUILT_IN_TYPES.keySet(), ", ")+")", + (name, loaderContext) -> BUILT_IN_TYPES.containsKey(name.toLowerCase()) ? + TypeToken.of(BUILT_IN_TYPES.get(name.toLowerCase())) : null); + customTypeNameInferencing.put("Java types", (name, loaderContext) -> { + // Assume it's a Java type + Maybe<Class<?>> inputType = loaderContext.tryLoadClass(name); + return inputType.isPresent() ? TypeToken.of(inputType.get()) : null; + }); + } + private static List<SpecParameter<?>> parseParameters(List<?> inputsRaw, Function<Object, Object> specialFlagTransformer, BrooklynClassLoadingContext loader) { if (inputsRaw == null) return ImmutableList.of(); List<SpecParameter<?>> inputs = new ArrayList<>(inputsRaw.size()); @@ -319,21 +343,16 @@ public class BasicSpecParameter<T> implements SpecParameter<T>{ } } - @SuppressWarnings({ "rawtypes" }) private static TypeToken inferType(String typeRaw, BrooklynClassLoadingContext loader) { if (typeRaw == null) return TypeToken.of(String.class); String type = typeRaw.trim(); - if (BUILT_IN_TYPES.containsKey(type.toLowerCase())) { - return TypeToken.of(BUILT_IN_TYPES.get(type.toLowerCase())); - } else { - // Assume it's a Java type - Maybe<Class<?>> inputType = loader.tryLoadClass(type); - if (inputType.isPresent()) { - return TypeToken.of(inputType.get()); - } else { - throw new IllegalArgumentException("The type '" + type + "' for a catalog input not recognised as a built-in (" + BUILT_IN_TYPES.keySet() + ") or a java type"); - } + for (BiFunction<String,BrooklynClassLoadingContext,TypeToken<?>> f: customTypeNameInferencing.values()) { + TypeToken<?> result = f.apply(type, loader); + if (result!=null) return result; } + throw new IllegalArgumentException("The type '" + type + "' for a parameter is not recognised; supported items are: " + + Strings.join(customTypeNameInferencing.keySet(), ", ")); + } @SuppressWarnings({ "unchecked", "rawtypes" }) diff --git a/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynObjectInternal.java b/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynObjectInternal.java index 972612b..7446030 100644 --- a/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynObjectInternal.java +++ b/core/src/main/java/org/apache/brooklyn/core/objs/BrooklynObjectInternal.java @@ -132,6 +132,11 @@ public interface BrooklynObjectInternal extends BrooklynObject, Rebindable { * including returning a default if the config key is unset, * returning a {@link Maybe#absent absent} if the uncoerced * does not support immediate resolution. + * This also returns {@link Maybe#absent absent} if the value + * or default value cannot be coerced to the type required by the key, + * with coercion errors typically handled when setting or when getting + * the "really needed" values, not when validating constraints which + * is one of the main use cases of this method. * <p> * Note: if no value for the key is available, not even as a default, * this returns a {@link Maybe#isPresent()} containing <code>null</code>
