You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by he...@apache.org on 2019/02/20 10:46:43 UTC
[brooklyn-server] 01/06: allow the types of parameters to be
extended programmatically
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 <al...@cloudsoftcorp.com>
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>