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 2016/07/07 09:18:42 UTC
[08/10] brooklyn-server git commit: Merge branch 'master' into
misc-cleanup-javalang-and-type-coercion
Merge branch 'master' into misc-cleanup-javalang-and-type-coercion
fix conflict: Class.forName change upstream now ClassLoaderUtils, replicated locally
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/ecf37212
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/ecf37212
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/ecf37212
Branch: refs/heads/master
Commit: ecf372126581e3cbffab16c014e00cda0f7539d4
Parents: b1999e3 8929ef3
Author: Alex Heneveld <al...@cloudsoftcorp.com>
Authored: Thu Jul 7 10:16:08 2016 +0100
Committer: Alex Heneveld <al...@cloudsoftcorp.com>
Committed: Thu Jul 7 10:16:08 2016 +0100
----------------------------------------------------------------------
.../spi/creation/CampInternalUtils.java | 5 +-
.../spi/dsl/methods/BrooklynDslCommon.java | 17 +-
.../brooklyn/spi/dsl/methods/DslComponent.java | 132 +++--
.../camp/brooklyn/ApplicationsYamlTest.java | 40 +-
.../camp/brooklyn/ByonLocationsYamlTest.java | 2 +-
.../brooklyn/ConfigInheritanceYamlTest.java | 4 +-
.../ConfigLocationInheritanceYamlTest.java | 6 +-
.../brooklyn/EmptySoftwareProcessYamlTest.java | 2 +-
.../brooklyn/EmptyWindowsProcessYamlTest.java | 2 +-
.../camp/brooklyn/EntitiesYamlTest.java | 22 +-
.../camp/brooklyn/EntityNameYamlTest.java | 2 +-
.../camp/brooklyn/EntityRefsYamlTest.java | 186 +++++++
.../camp/brooklyn/ExternalConfigYamlTest.java | 15 +-
.../camp/brooklyn/IdentityYamlTest.java | 82 +++
.../LocationExternalConfigYamlTest.java | 2 +-
.../camp/brooklyn/ReferencedYamlTest.java | 24 +-
.../brooklyn/catalog/CatalogYamlAppTest.java | 41 +-
.../brooklyn/catalog/CatalogYamlCombiTest.java | 27 +-
.../catalog/CatalogYamlEntityNameTest.java | 27 +-
.../brooklyn/catalog/CatalogYamlEntityTest.java | 217 ++++----
.../catalog/CatalogYamlLocationTest.java | 24 +-
.../brooklyn/catalog/CatalogYamlPolicyTest.java | 21 +-
.../brooklyn/catalog/CatalogYamlRebindTest.java | 3 +-
.../catalog/CatalogYamlTemplateTest.java | 16 +-
.../catalog/CatalogYamlVersioningTest.java | 14 +-
.../catalog/SpecParameterParsingTest.java | 2 +
.../catalog/SpecParameterUnwrappingTest.java | 88 ++--
.../CreatePasswordSensorIntegrationTest.java | 2 +-
.../brooklyn/test/lite/CampYamlLiteTest.java | 23 +-
.../resources/test-referencing-entities.yaml | 2 +-
.../core/BrooklynFeatureEnablement.java | 126 +++--
.../catalog/internal/CatalogBomScanner.java | 27 +-
.../brooklyn/core/effector/AddSensor.java | 15 +-
.../apache/brooklyn/core/entity/Entities.java | 162 ++++--
.../drivers/ReflectiveEntityDriverFactory.java | 5 +-
.../brooklyn/core/location/geo/HostGeoInfo.java | 3 +-
.../JavaBrooklynClassLoadingContext.java | 18 +-
.../core/mgmt/entitlement/Entitlements.java | 6 +-
.../internal/AbstractManagementContext.java | 3 +-
.../transformer/CompoundTransformerLoader.java | 3 +-
.../brooklyn/core/objs/BrooklynTypes.java | 5 +-
.../core/sensor/DurationSinceSensor.java | 7 +-
.../core/sensor/ssh/SshCommandSensor.java | 2 +-
.../enricher/stock/PercentageEnricher.java | 117 +++++
.../location/byon/ByonLocationResolver.java | 4 +-
.../location/ssh/SshMachineLocation.java | 3 +-
.../brooklyn/util/core/ClassLoaderUtils.java | 249 +++++++++
.../brooklyn/util/core/flags/TypeCoercions.java | 26 +-
core/src/main/resources/catalog.bom | 3 +-
...rooklynFeatureEnablementPerformanceTest.java | 56 ++
.../core/BrooklynFeatureEnablementTest.java | 25 +-
.../internal/StaticTypePlanTransformer.java | 3 +-
.../brooklyn/core/entity/EntitiesTest.java | 46 +-
.../core/mgmt/rebind/RebindCatalogItemTest.java | 90 ++--
.../core/mgmt/rebind/RebindEnricherTest.java | 2 +-
.../core/mgmt/rebind/RebindEntityTest.java | 2 +-
.../objs/BasicSpecParameterFromClassTest.java | 5 +-
.../enricher/stock/PercentageEnricherTest.java | 327 ++++++++++++
.../entity/group/DynamicClusterTest.java | 10 +-
karaf/apache-brooklyn/pom.xml | 9 +
.../src/main/resources/etc/default.catalog.bom | 416 +++++++++++++--
.../etc/org.apache.brooklyn.osgilauncher.cfg | 24 +-
karaf/features/src/main/feature/feature.xml | 27 +-
.../resources/OSGI-INF/blueprint/blueprint.xml | 2 +-
.../init/src/main/resources/catalog-classes.bom | 507 +++++++++++++++++++
.../blueprints/AbstractBlueprintTest.java | 2 +-
.../Windows7zipBlueprintLiveTest.java | 2 +-
launcher/src/test/resources/7zip-catalog.yaml | 4 +-
.../resources/rebind-test-catalog-additions.bom | 3 +-
.../src/test/resources/rebind-test-catalog.bom | 3 +-
policy/src/main/resources/catalog.bom | 16 +-
pom.xml | 2 +
.../rest/resources/EntityConfigResource.java | 4 +-
.../rest/resources/LocationResource.java | 13 +-
.../brooklyn/rest/resources/PolicyResource.java | 7 +-
.../provider/DelegatingSecurityProvider.java | 10 +-
.../rest/resources/ApplicationResourceTest.java | 28 +-
.../rest/resources/CatalogResourceTest.java | 133 +++--
.../rest/resources/LocationResourceTest.java | 12 +-
.../vanilla-software-process-with-resource.yaml | 8 +-
.../main/resources/brooklyn/default.catalog.bom | 6 +-
server-cli/src/main/resources/catalog.bom | 6 +-
.../java/org/apache/brooklyn/cli/CliTest.java | 1 +
.../apache/brooklyn/entity/chef/ChefConfig.java | 4 -
.../entity/chef/ChefLifecycleEffectorTasks.java | 2 +-
.../brooklyn/entity/chef/ChefSoloDriver.java | 2 +-
.../entity/java/VanillaJavaAppSshDriver.java | 2 +-
.../entity/machine/AddMachineMetrics.java | 9 +
.../entity/machine/MachineAttributes.java | 6 +
.../HardcodedCatalogEntitySpecResolver.java | 59 ++-
.../org/apache/brooklyn/feed/jmx/JmxHelper.java | 24 +-
software/base/src/main/resources/catalog.bom | 3 +-
.../BrooklynNodeIntegrationTest.java | 4 +-
.../location/winrm/WinRmMachineLocation.java | 11 +-
.../brooklyn/test/framework/BaseTest.java | 9 +-
.../test/framework/TargetableTestComponent.java | 11 +
.../framework/TargetableTestComponentImpl.java | 52 +-
.../test/framework/TestSshCommandImpl.java | 29 +-
test-framework/src/main/resources/catalog.bom | 9 +-
.../framework/TargetableTestComponentTest.java | 146 ++++++
.../test/framework/TestSshCommandTest.java | 41 +-
.../entities/src/main/resources/catalog.bom | 3 +-
.../main/resources/yaml-ref-back-catalog.bom | 1 +
.../main/resources/yaml-ref-parent-catalog.bom | 1 +
.../src/main/resources/catalog.bom | 3 +-
.../src/main/resources/catalog.bom | 3 +-
.../src/main/resources/catalog.bom | 6 +-
107 files changed, 3345 insertions(+), 740 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ecf37212/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
----------------------------------------------------------------------
diff --cc camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
index 309785d,a67d89e..d496fd7
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/BrooklynDslCommon.java
@@@ -45,7 -45,9 +45,8 @@@ import org.apache.brooklyn.core.mgmt.in
import org.apache.brooklyn.core.mgmt.persist.DeserializingClassRenamesProvider;
import org.apache.brooklyn.core.sensor.DependentConfiguration;
import org.apache.brooklyn.util.collections.MutableMap;
+ import org.apache.brooklyn.util.core.ClassLoaderUtils;
import org.apache.brooklyn.util.core.config.ConfigBag;
-import org.apache.brooklyn.util.core.flags.ClassCoercionException;
import org.apache.brooklyn.util.core.flags.FlagUtils;
import org.apache.brooklyn.util.core.flags.TypeCoercions;
import org.apache.brooklyn.util.core.task.DeferredSupplier;
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ecf37212/core/src/main/java/org/apache/brooklyn/core/mgmt/entitlement/Entitlements.java
----------------------------------------------------------------------
diff --cc core/src/main/java/org/apache/brooklyn/core/mgmt/entitlement/Entitlements.java
index df3f7a8,e867c76..d8cf934
--- a/core/src/main/java/org/apache/brooklyn/core/mgmt/entitlement/Entitlements.java
+++ b/core/src/main/java/org/apache/brooklyn/core/mgmt/entitlement/Entitlements.java
@@@ -35,9 -35,9 +35,10 @@@ import org.apache.brooklyn.core.config.
import org.apache.brooklyn.core.internal.BrooklynProperties;
import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
import org.apache.brooklyn.core.mgmt.persist.DeserializingClassRenamesProvider;
+ import org.apache.brooklyn.util.core.ClassLoaderUtils;
import org.apache.brooklyn.util.core.task.Tasks;
import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Maybe;
import org.apache.brooklyn.util.javalang.Reflections;
import org.apache.brooklyn.util.text.Strings;
import org.slf4j.Logger;
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/ecf37212/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java
----------------------------------------------------------------------
diff --cc core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java
index 0169827,94a0991..3f64a4d
--- a/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java
@@@ -36,16 -50,23 +36,18 @@@ import org.apache.brooklyn.core.interna
import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
import org.apache.brooklyn.core.sensor.Sensors;
import org.apache.brooklyn.util.JavaGroovyEquivalents;
-import org.apache.brooklyn.util.collections.MutableSet;
-import org.apache.brooklyn.util.collections.QuorumCheck;
-import org.apache.brooklyn.util.collections.QuorumCheck.QuorumChecks;
+ import org.apache.brooklyn.util.core.ClassLoaderUtils;
import org.apache.brooklyn.util.core.task.Tasks;
+ import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.guava.Maybe;
-import org.apache.brooklyn.util.javalang.Enums;
+import org.apache.brooklyn.util.javalang.Boxing;
import org.apache.brooklyn.util.javalang.JavaClassNames;
-import org.apache.brooklyn.util.net.Cidr;
-import org.apache.brooklyn.util.net.Networking;
-import org.apache.brooklyn.util.net.UserAndHostAndPort;
-import org.apache.brooklyn.util.text.StringEscapes.JavaStringEscapes;
-import org.apache.brooklyn.util.text.Strings;
-import org.apache.brooklyn.util.time.Duration;
-import org.apache.brooklyn.util.time.Time;
-import org.apache.brooklyn.util.yaml.Yamls;
+import org.apache.brooklyn.util.javalang.Reflections;
+import org.apache.brooklyn.util.javalang.coerce.CommonAdaptorTypeCoercions;
+import org.apache.brooklyn.util.javalang.coerce.EnumTypeCoercions;
+import org.apache.brooklyn.util.javalang.coerce.PrimitiveStringTypeCoercions;
+import org.apache.brooklyn.util.javalang.coerce.TypeCoercer;
+import org.apache.brooklyn.util.javalang.coerce.TypeCoercerExtensible;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@@ -61,152 -97,400 +63,152 @@@ public class TypeCoercions
private TypeCoercions() {}
- /** Store the coercion {@link Function functions} in a {@link Table table}. */
- @GuardedBy("TypeCoercions.class")
- private static Table<Class, Class, Function> registry = HashBasedTable.create();
-
- /**
- * Attempts to coerce {@code value} to {@code targetType}.
- * <p>
- * Maintains a registry of adapter functions for type pairs in a {@link Table} which
- * is searched after checking various strategies, including the following:
- * <ul>
- * <li>{@code value.asTargetType()}
- * <li>{@code TargetType.fromType(value)} (if {@code value instanceof Type})
- * <li>{@code value.targetTypeValue()} (handy for primitives)
- * <li>{@code TargetType.valueOf(value)} (for enums)
- * </ul>
- * <p>
- * A default set of adapters will handle most common Java-type coercions
- * as well as <code>String</code> coercion to:
- * <ul>
- * <li> {@link Set}, {@link List}, {@link Map} and similar -- parses as YAML
- * <li> {@link Date} -- parses using {@link Time#parseDate(String)}
- * <li> {@link Duration} -- parses using {@link Duration#parse(String)}
- * </ul>
- */
- public static <T> T coerce(Object value, Class<T> targetType) {
- return coerce(value, TypeToken.of(targetType));
+ static TypeCoercerExtensible coercer;
+ static {
+ coercer = TypeCoercerExtensible.newEmpty();
+ BrooklynInitialization.initTypeCoercionStandardAdapters();
+ }
+
+ public static void initStandardAdapters() {
- new CommonAdaptorTypeCoercions(coercer).registerAllAdapters();
++ new BrooklynCommonAdaptorTypeCoercions(coercer).registerAllAdapters();
+ registerDeprecatedBrooklynAdapters();
+ registerBrooklynAdapters();
+ registerGroovyAdapters();
}
+
+ public static <T> T coerce(Object input, Class<T> type) { return coercer.coerce(input, type); }
+ public static <T> T coerce(Object input, TypeToken<T> type) { return coercer.coerce(input, type); }
+ public static <T> Maybe<T> tryCoerce(Object input, Class<T> type) { return coercer.tryCoerce(input, type); }
+ public static <T> Maybe<T> tryCoerce(Object input, TypeToken<T> type) { return coercer.tryCoerce(input, type); }
- /** @see #coerce(Object, Class); allows a null value in the contents of the Maybe */
- public static <T> Maybe<T> tryCoerce(Object value, TypeToken<T> targetTypeToken) {
- try {
- return Maybe.ofAllowingNull( coerce(value, targetTypeToken) );
- } catch (Throwable t) {
- Exceptions.propagateIfFatal(t);
- return Maybe.absent(t);
- }
+ public static <A,B> Function<? super A,B> registerAdapter(Class<A> sourceType, Class<B> targetType, Function<? super A,B> fn) {
+ return coercer.registerAdapter(sourceType, targetType, fn);
}
- /** @see #coerce(Object, Class) */
- @SuppressWarnings({ "unchecked" })
- public static <T> T coerce(Object value, TypeToken<T> targetTypeToken) {
- if (value==null) return null;
- Class<? super T> targetType = targetTypeToken.getRawType();
+ public static <T> Function<Object, T> function(final Class<T> type) {
+ return coercer.function(type);
+ }
- //recursive coercion of parameterized collections and map entries
- if (targetTypeToken.getType() instanceof ParameterizedType) {
- if (value instanceof Collection && Collection.class.isAssignableFrom(targetType)) {
- Type[] arguments = ((ParameterizedType) targetTypeToken.getType()).getActualTypeArguments();
- if (arguments.length != 1) {
- throw new IllegalStateException("Unexpected number of parameters in collection type: " + arguments);
- }
- Collection coerced = Lists.newLinkedList();
- TypeToken<?> listEntryType = TypeToken.of(arguments[0]);
- for (Object entry : (Iterable<?>) value) {
- coerced.add(coerce(entry, listEntryType));
- }
- if (Set.class.isAssignableFrom(targetType)) {
- return (T) Sets.newLinkedHashSet(coerced);
- } else {
- return (T) Lists.newArrayList(coerced);
- }
- } else if (value instanceof Map && Map.class.isAssignableFrom(targetType)) {
- Type[] arguments = ((ParameterizedType) targetTypeToken.getType()).getActualTypeArguments();
- if (arguments.length != 2) {
- throw new IllegalStateException("Unexpected number of parameters in map type: " + arguments);
- }
- Map coerced = Maps.newLinkedHashMap();
- TypeToken<?> mapKeyType = TypeToken.of(arguments[0]);
- TypeToken<?> mapValueType = TypeToken.of(arguments[1]);
- for (Map.Entry entry : ((Map<?,?>) value).entrySet()) {
- coerced.put(coerce(entry.getKey(), mapKeyType), coerce(entry.getValue(), mapValueType));
- }
- return (T) Maps.newLinkedHashMap(coerced);
+ @SuppressWarnings({"unused", "deprecation", "unchecked", "rawtypes"})
+ public static void registerDeprecatedBrooklynAdapters() {
+ registerAdapter(Closure.class, ConfigurableEntityFactory.class, new Function<Closure,ConfigurableEntityFactory>() {
+ @Override
+ public ConfigurableEntityFactory apply(Closure input) {
+ return new ClosureEntityFactory(input);
}
- }
-
- if (targetType.isInstance(value)) return (T) value;
-
- // TODO use registry first?
-
- //deal with primitive->primitive casting
- if (isPrimitiveOrBoxer(targetType) && isPrimitiveOrBoxer(value.getClass())) {
- // Don't just rely on Java to do its normal casting later; if caller writes
- // long `l = coerce(new Integer(1), Long.class)` then letting java do its casting will fail,
- // because an Integer will not automatically be unboxed and cast to a long
- return castPrimitive(value, (Class<T>)targetType);
- }
-
- //deal with string->primitive
- if (value instanceof String && isPrimitiveOrBoxer(targetType)) {
- return stringToPrimitive((String)value, (Class<T>)targetType);
- }
-
- //deal with primitive->string
- if (isPrimitiveOrBoxer(value.getClass()) && targetType.equals(String.class)) {
- return (T) value.toString();
- }
-
- //look for value.asType where Type is castable to targetType
- String targetTypeSimpleName = getVerySimpleName(targetType);
- if (targetTypeSimpleName!=null && targetTypeSimpleName.length()>0) {
- for (Method m: value.getClass().getMethods()) {
- if (m.getName().startsWith("as") && m.getParameterTypes().length==0 &&
- targetType.isAssignableFrom(m.getReturnType()) ) {
- if (m.getName().equals("as"+getVerySimpleName(m.getReturnType()))) {
- try {
- return (T) m.invoke(value);
- } catch (Exception e) {
- throw new ClassCoercionException("Cannot coerce type "+value.getClass()+" to "+targetType.getCanonicalName()+" ("+value+"): "+m.getName()+" adapting failed, "+e);
- }
- }
+ });
+ Function<?,?> ignoredVarHereToAllowSuppressDeprecationWarning1 = registerAdapter(org.apache.brooklyn.core.entity.factory.EntityFactory.class, ConfigurableEntityFactory.class, new Function<org.apache.brooklyn.core.entity.factory.EntityFactory,ConfigurableEntityFactory>() {
+ @Override
+ public ConfigurableEntityFactory apply(org.apache.brooklyn.core.entity.factory.EntityFactory input) {
+ if (input instanceof ConfigurableEntityFactory) return (ConfigurableEntityFactory)input;
+ return new ConfigurableEntityFactoryFromEntityFactory(input);
+ }
+ });
+ Function<?,?> ignoredVarHereToAllowSuppressDeprecationWarning2 = registerAdapter(Closure.class, org.apache.brooklyn.core.entity.factory.EntityFactory.class, new Function<Closure,org.apache.brooklyn.core.entity.factory.EntityFactory>() {
+ @Override
+ public org.apache.brooklyn.core.entity.factory.EntityFactory apply(Closure input) {
+ return new ClosureEntityFactory(input);
+ }
+ });
+ }
+
+ @SuppressWarnings("rawtypes")
+ public static void registerBrooklynAdapters() {
+ registerAdapter(String.class, AttributeSensor.class, new Function<String,AttributeSensor>() {
+ @Override
+ public AttributeSensor apply(final String input) {
+ Entity entity = BrooklynTaskTags.getContextEntity(Tasks.current());
+ if (entity!=null) {
+ Sensor<?> result = entity.getEntityType().getSensor(input);
+ if (result instanceof AttributeSensor)
+ return (AttributeSensor) result;
}
+ return Sensors.newSensor(Object.class, input);
}
- }
-
- //now look for static TargetType.fromType(Type t) where value instanceof Type
- for (Method m: targetType.getMethods()) {
- if (((m.getModifiers()&Modifier.STATIC)==Modifier.STATIC) &&
- m.getName().startsWith("from") && m.getParameterTypes().length==1 &&
- m.getParameterTypes()[0].isInstance(value)) {
- if (m.getName().equals("from"+getVerySimpleName(m.getParameterTypes()[0]))) {
- try {
- return (T) m.invoke(null, value);
- } catch (Exception e) {
- throw new ClassCoercionException("Cannot coerce type "+value.getClass()+" to "+targetType.getCanonicalName()+" ("+value+"): "+m.getName()+" adapting failed, "+e);
- }
+ });
+ registerAdapter(String.class, Sensor.class, new Function<String,Sensor>() {
+ @Override
+ public AttributeSensor apply(final String input) {
+ Entity entity = BrooklynTaskTags.getContextEntity(Tasks.current());
+ if (entity!=null) {
+ Sensor<?> result = entity.getEntityType().getSensor(input);
+ if (result != null)
+ return (AttributeSensor) result;
}
+ return Sensors.newSensor(Object.class, input);
}
- }
-
- //ENHANCEMENT could look in type hierarchy of both types for a conversion method...
-
- //primitives get run through again boxed up
- Class boxedT = UNBOXED_TO_BOXED_TYPES.get(targetType);
- Class boxedVT = UNBOXED_TO_BOXED_TYPES.get(value.getClass());
- if (boxedT!=null || boxedVT!=null) {
- try {
- if (boxedT==null) boxedT=targetType;
- Object boxedV;
- if (boxedVT==null) { boxedV = value; }
- else { boxedV = boxedVT.getConstructor(value.getClass()).newInstance(value); }
- return (T) coerce(boxedV, boxedT);
- } catch (Exception e) {
- throw new ClassCoercionException("Cannot coerce type "+value.getClass()+" to "+targetType.getCanonicalName()+" ("+value+"): unboxing failed, "+e);
+ });
+ }
+
+ @SuppressWarnings("rawtypes")
+ public static void registerGroovyAdapters() {
+ registerAdapter(Closure.class, Predicate.class, new Function<Closure,Predicate>() {
+ @Override
+ public Predicate<?> apply(final Closure closure) {
+ return new Predicate<Object>() {
+ @Override public boolean apply(Object input) {
+ return (Boolean) closure.call(input);
+ }
+ };
}
- }
-
- //for enums call valueOf with the string representation of the value
- if (targetType.isEnum()) {
- T result = (T) stringToEnum((Class<Enum>) targetType, null).apply(String.valueOf(value));
- if (result != null) return result;
- }
-
- //now look in registry
- synchronized (TypeCoercions.class) {
- Map<Class, Function> adapters = registry.row(targetType);
- for (Map.Entry<Class, Function> entry : adapters.entrySet()) {
- if (entry.getKey().isInstance(value)) {
- T result = (T) entry.getValue().apply(value);
-
- // Check if need to unwrap again (e.g. if want List<Integer> and are given a String "1,2,3"
- // then we'll have so far converted to List.of("1", "2", "3"). Call recursively.
- // First check that value has changed, to avoid stack overflow!
- if (!Objects.equal(value, result) && targetTypeToken.getType() instanceof ParameterizedType) {
- // Could duplicate check for `result instanceof Collection` etc; but recursive call
- // will be fine as if that doesn't match we'll safely reach `targetType.isInstance(value)`
- // and just return the result.
- return coerce(result, targetTypeToken);
+ });
+ registerAdapter(Closure.class, Function.class, new Function<Closure,Function>() {
+ @Override
+ public Function apply(final Closure closure) {
+ return new Function() {
+ @Override public Object apply(Object input) {
+ return closure.call(input);
}
- return result;
- }
+ };
}
- }
-
- //not found
- if (targetType.isEnum()) {
- try {
- throw new ClassCoercionException("Invalid value '"+value+"' for "+JavaClassNames.simpleClassName(targetType)+"; expected one of "+
- Arrays.asList((Object[])targetType.getMethod("values").invoke(null)));
- } catch (ClassCoercionException e) {
- throw e;
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- // fall back to below
+ });
+ registerAdapter(Object.class, TimeDuration.class, new Function<Object,TimeDuration>() {
+ @SuppressWarnings("deprecation")
+ @Override
+ public TimeDuration apply(final Object input) {
+ log.warn("deprecated automatic coercion of Object to TimeDuration (set breakpoint in TypeCoercions to inspect, convert to Duration)");
+ return JavaGroovyEquivalents.toTimeDuration(input);
}
- }
- throw new ClassCoercionException("Cannot coerce type "+value.getClass().getCanonicalName()+" to "+targetType.getCanonicalName()+" ("+value+"): no adapter known");
- }
-
- /**
- * Returns a function that does a type coercion to the given type. For example,
- * {@code TypeCoercions.function(Double.class)} will return a function that will
- * coerce its input value to a {@link Double} (or throw a {@link ClassCoercionException}
- * if that is not possible).
- */
- public static <T> Function<Object, T> function(final Class<T> type) {
- return new CoerceFunction<T>(type);
+ });
+ registerAdapter(TimeDuration.class, Long.class, new Function<TimeDuration,Long>() {
+ @Override
+ public Long apply(final TimeDuration input) {
+ log.warn("deprecated automatic coercion of TimeDuration to Long (set breakpoint in TypeCoercions to inspect, use Duration instead of Long!)");
+ return input.toMilliseconds();
+ }
+ });
}
-
- private static class CoerceFunction<T> implements Function<Object, T> {
- private final Class<T> type;
- public CoerceFunction(Class<T> type) {
- this.type = type;
- }
- @Override
- public T apply(Object input) {
- return coerce(input, type);
- }
- }
+ // ---- legacy compatibility
- /**
- * Type coercion {@link Function function} for {@link Enum enums}.
- * <p>
- * Tries to convert the string to {@link CaseFormat#UPPER_UNDERSCORE} first,
- * handling all of the different {@link CaseFormat format} possibilites. Failing
- * that, it tries a case-insensitive comparison with the valid enum values.
- * <p>
- * Returns {@code defaultValue} if the string cannot be converted.
- *
- * @see TypeCoercions#coerce(Object, Class)
- * @see Enum#valueOf(Class, String)
- */
+ /** @deprecated since 0.10.0 see method in {@link EnumTypeCoercions} */ @Deprecated
public static <E extends Enum<E>> Function<String, E> stringToEnum(final Class<E> type, @Nullable final E defaultValue) {
- return new StringToEnumFunction<E>(type, defaultValue);
+ return EnumTypeCoercions.stringToEnum(type, defaultValue);
}
-
- private static class StringToEnumFunction<E extends Enum<E>> implements Function<String, E> {
- private final Class<E> type;
- private final E defaultValue;
- public StringToEnumFunction(Class<E> type, @Nullable E defaultValue) {
- this.type = type;
- this.defaultValue = defaultValue;
- }
- @Override
- public E apply(String input) {
- Preconditions.checkNotNull(input, "input");
- List<String> options = ImmutableList.of(
- input,
- CaseFormat.LOWER_HYPHEN.to(CaseFormat.UPPER_UNDERSCORE, input),
- CaseFormat.LOWER_UNDERSCORE.to(CaseFormat.UPPER_UNDERSCORE, input),
- CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, input),
- CaseFormat.UPPER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, input));
- for (String value : options) {
- try {
- return Enum.valueOf(type, value);
- } catch (IllegalArgumentException iae) {
- continue;
- }
- }
- Maybe<E> result = Enums.valueOfIgnoreCase(type, input);
- return (result.isPresent()) ? result.get() : defaultValue;
- }
- }
-
- /**
- * Sometimes need to explicitly cast primitives, rather than relying on Java casting.
- * For example, when using generics then type-erasure means it doesn't actually cast,
- * which causes tests to fail with 0 != 0.0
- */
- @SuppressWarnings("unchecked")
+ /** @deprecated since 0.10.0 see method in {@link PrimitiveStringTypeCoercions} */ @Deprecated
public static <T> T castPrimitive(Object value, Class<T> targetType) {
- if (value==null) return null;
- assert isPrimitiveOrBoxer(targetType) : "targetType="+targetType;
- assert isPrimitiveOrBoxer(value.getClass()) : "value="+targetType+"; valueType="+value.getClass();
-
- Class<?> sourceWrapType = Primitives.wrap(value.getClass());
- Class<?> targetWrapType = Primitives.wrap(targetType);
-
- // optimization, for when already correct type
- if (sourceWrapType == targetWrapType) {
- return (T) value;
- }
-
- if (targetWrapType == Boolean.class) {
- // only char can be mapped to boolean
- // (we could say 0=false, nonzero=true, but there is no compelling use case so better
- // to encourage users to write as boolean)
- if (sourceWrapType == Character.class)
- return (T) stringToPrimitive(value.toString(), targetType);
-
- throw new ClassCoercionException("Cannot cast "+sourceWrapType+" ("+value+") to "+targetType);
- } else if (sourceWrapType == Boolean.class) {
- // boolean can't cast to anything else
-
- throw new ClassCoercionException("Cannot cast "+sourceWrapType+" ("+value+") to "+targetType);
- }
-
- // for whole-numbers (where casting to long won't lose anything)...
- long v = 0;
- boolean islong = true;
- if (sourceWrapType == Character.class) {
- v = (long) ((Character)value).charValue();
- } else if (sourceWrapType == Byte.class) {
- v = (long) ((Byte)value).byteValue();
- } else if (sourceWrapType == Short.class) {
- v = (long) ((Short)value).shortValue();
- } else if (sourceWrapType == Integer.class) {
- v = (long) ((Integer)value).intValue();
- } else if (sourceWrapType == Long.class) {
- v = ((Long)value).longValue();
- } else {
- islong = false;
- }
- if (islong) {
- if (targetWrapType == Character.class) return (T) Character.valueOf((char)v);
- if (targetWrapType == Byte.class) return (T) Byte.valueOf((byte)v);
- if (targetWrapType == Short.class) return (T) Short.valueOf((short)v);
- if (targetWrapType == Integer.class) return (T) Integer.valueOf((int)v);
- if (targetWrapType == Long.class) return (T) Long.valueOf((long)v);
- if (targetWrapType == Float.class) return (T) Float.valueOf((float)v);
- if (targetWrapType == Double.class) return (T) Double.valueOf((double)v);
- throw new IllegalStateException("Unexpected: sourceType="+sourceWrapType+"; targetType="+targetWrapType);
- }
-
- // for real-numbers (cast to double)...
- double d = 0;
- boolean isdouble = true;
- if (sourceWrapType == Float.class) {
- d = (double) ((Float)value).floatValue();
- } else if (sourceWrapType == Double.class) {
- d = (double) ((Double)value).doubleValue();
- } else {
- isdouble = false;
- }
- if (isdouble) {
- if (targetWrapType == Character.class) return (T) Character.valueOf((char)d);
- if (targetWrapType == Byte.class) return (T) Byte.valueOf((byte)d);
- if (targetWrapType == Short.class) return (T) Short.valueOf((short)d);
- if (targetWrapType == Integer.class) return (T) Integer.valueOf((int)d);
- if (targetWrapType == Long.class) return (T) Long.valueOf((long)d);
- if (targetWrapType == Float.class) return (T) Float.valueOf((float)d);
- if (targetWrapType == Double.class) return (T) Double.valueOf((double)d);
- throw new IllegalStateException("Unexpected: sourceType="+sourceWrapType+"; targetType="+targetWrapType);
- } else {
- throw new IllegalStateException("Unexpected: sourceType="+sourceWrapType+"; targetType="+targetWrapType);
- }
+ return PrimitiveStringTypeCoercions.castPrimitive(value, targetType);
}
+ /** @deprecated since 0.10.0 see method in {@link PrimitiveStringTypeCoercions} */ @Deprecated
public static boolean isPrimitiveOrBoxer(Class<?> type) {
- return Primitives.allPrimitiveTypes().contains(type) || Primitives.allWrapperTypes().contains(type);
+ return PrimitiveStringTypeCoercions.isPrimitiveOrBoxer(type);
}
-
- @SuppressWarnings("unchecked")
+
+ /** @deprecated since 0.10.0 see method in {@link PrimitiveStringTypeCoercions} */ @Deprecated
public static <T> T stringToPrimitive(String value, Class<T> targetType) {
- assert Primitives.allPrimitiveTypes().contains(targetType) || Primitives.allWrapperTypes().contains(targetType) : "targetType="+targetType;
- // If char, then need to do explicit conversion
- if (targetType == Character.class || targetType == char.class) {
- if (value.length() == 1) {
- return (T) (Character) value.charAt(0);
- } else if (value.length() != 1) {
- throw new ClassCoercionException("Cannot coerce type String to "+targetType.getCanonicalName()+" ("+value+"): adapting failed");
- }
- }
- value = value.trim();
- // For boolean we could use valueOf, but that returns false whereas we'd rather throw errors on bad values
- if (targetType == Boolean.class || targetType == boolean.class) {
- if ("true".equalsIgnoreCase(value)) return (T) Boolean.TRUE;
- if ("false".equalsIgnoreCase(value)) return (T) Boolean.FALSE;
- if ("yes".equalsIgnoreCase(value)) return (T) Boolean.TRUE;
- if ("no".equalsIgnoreCase(value)) return (T) Boolean.FALSE;
- if ("t".equalsIgnoreCase(value)) return (T) Boolean.TRUE;
- if ("f".equalsIgnoreCase(value)) return (T) Boolean.FALSE;
- if ("y".equalsIgnoreCase(value)) return (T) Boolean.TRUE;
- if ("n".equalsIgnoreCase(value)) return (T) Boolean.FALSE;
-
- throw new ClassCoercionException("Cannot coerce type String to "+targetType.getCanonicalName()+" ("+value+"): adapting failed");
- }
-
- // Otherwise can use valueOf reflectively
- Class<?> wrappedType;
- if (Primitives.allPrimitiveTypes().contains(targetType)) {
- wrappedType = Primitives.wrap(targetType);
- } else {
- wrappedType = targetType;
- }
-
- try {
- return (T) wrappedType.getMethod("valueOf", String.class).invoke(null, value);
- } catch (Exception e) {
- ClassCoercionException tothrow = new ClassCoercionException("Cannot coerce "+JavaStringEscapes.wrapJavaString(value)+" to "+targetType.getCanonicalName()+" ("+value+"): adapting failed");
- tothrow.initCause(e);
- throw tothrow;
- }
+ return PrimitiveStringTypeCoercions.stringToPrimitive(value, targetType);
}
- /** returns the simple class name, and for any inner class the portion after the $ */
+ /** @deprecated since 0.10.0 see {@link JavaClassNames#verySimpleClassName(Class)} */ @Deprecated
+ @SuppressWarnings("rawtypes")
public static String getVerySimpleName(Class c) {
- String s = c.getSimpleName();
- if (s.indexOf('$')>=0)
- s = s.substring(s.lastIndexOf('$')+1);
- return s;
+ return JavaClassNames.verySimpleClassName(c);
}
+
+ /** @deprecated since 0.10.0 see {@link Boxing#PRIMITIVE_TO_BOXED} and its <code>inverse()</code> method */
+ @SuppressWarnings("rawtypes")
public static final Map<Class,Class> BOXED_TO_UNBOXED_TYPES = ImmutableMap.<Class,Class>builder().
put(Integer.class, Integer.TYPE).
put(Long.class, Long.TYPE).
@@@ -252,4 -531,374 +254,26 @@@
}
return null;
}
-
- /** Registers an adapter for use with type coercion. Returns any old adapter. */
- public synchronized static <A,B> Function registerAdapter(Class<A> sourceType, Class<B> targetType, Function<? super A,B> fn) {
- return registry.put(targetType, sourceType, fn);
- }
-
- static { BrooklynInitialization.initTypeCoercionStandardAdapters(); }
+
- public static void initStandardAdapters() {
- registerAdapter(CharSequence.class, String.class, new Function<CharSequence,String>() {
- @Override
- public String apply(CharSequence input) {
- return input.toString();
- }
- });
- registerAdapter(byte[].class, String.class, new Function<byte[],String>() {
- @Override
- public String apply(byte[] input) {
- return new String(input);
- }
- });
- registerAdapter(Collection.class, Set.class, new Function<Collection,Set>() {
- @SuppressWarnings("unchecked")
- @Override
- public Set apply(Collection input) {
- return Sets.newLinkedHashSet(input);
- }
- });
- registerAdapter(Collection.class, List.class, new Function<Collection,List>() {
- @SuppressWarnings("unchecked")
- @Override
- public List apply(Collection input) {
- return Lists.newArrayList(input);
- }
- });
- registerAdapter(String.class, InetAddress.class, new Function<String,InetAddress>() {
- @Override
- public InetAddress apply(String input) {
- return Networking.getInetAddressWithFixedName(input);
- }
- });
- registerAdapter(String.class, HostAndPort.class, new Function<String,HostAndPort>() {
- @Override
- public HostAndPort apply(String input) {
- return HostAndPort.fromString(input);
- }
- });
- registerAdapter(String.class, UserAndHostAndPort.class, new Function<String,UserAndHostAndPort>() {
- @Override
- public UserAndHostAndPort apply(String input) {
- return UserAndHostAndPort.fromString(input);
- }
- });
- registerAdapter(String.class, Cidr.class, new Function<String,Cidr>() {
- @Override
- public Cidr apply(String input) {
- return new Cidr(input);
- }
- });
- registerAdapter(String.class, URL.class, new Function<String,URL>() {
- @Override
- public URL apply(String input) {
- try {
- return new URL(input);
- } catch (Exception e) {
- throw Exceptions.propagate(e);
- }
- }
- });
- registerAdapter(URL.class, String.class, new Function<URL,String>() {
- @Override
- public String apply(URL input) {
- return input.toString();
- }
- });
- registerAdapter(String.class, URI.class, new Function<String,URI>() {
- @Override
- public URI apply(String input) {
- return URI.create(input);
- }
- });
- registerAdapter(URI.class, String.class, new Function<URI,String>() {
- @Override
- public String apply(URI input) {
- return input.toString();
- }
- });
- registerAdapter(Closure.class, ConfigurableEntityFactory.class, new Function<Closure,ConfigurableEntityFactory>() {
- @SuppressWarnings("unchecked")
- @Override
- public ConfigurableEntityFactory apply(Closure input) {
- return new ClosureEntityFactory(input);
- }
- });
- @SuppressWarnings({"unused", "deprecation"})
- Function<?,?> ignoredVarHereToAllowSuppressDeprecationWarning1 = registerAdapter(org.apache.brooklyn.core.entity.factory.EntityFactory.class, ConfigurableEntityFactory.class, new Function<org.apache.brooklyn.core.entity.factory.EntityFactory,ConfigurableEntityFactory>() {
- @SuppressWarnings("unchecked")
- @Override
- public ConfigurableEntityFactory apply(org.apache.brooklyn.core.entity.factory.EntityFactory input) {
- if (input instanceof ConfigurableEntityFactory) return (ConfigurableEntityFactory)input;
- return new ConfigurableEntityFactoryFromEntityFactory(input);
- }
- });
- @SuppressWarnings({"unused", "deprecation"})
- Function<?,?> ignoredVarHereToAllowSuppressDeprecationWarning2 = registerAdapter(Closure.class, org.apache.brooklyn.core.entity.factory.EntityFactory.class, new Function<Closure,org.apache.brooklyn.core.entity.factory.EntityFactory>() {
- @SuppressWarnings("unchecked")
- @Override
- public org.apache.brooklyn.core.entity.factory.EntityFactory apply(Closure input) {
- return new ClosureEntityFactory(input);
- }
- });
- registerAdapter(Closure.class, Predicate.class, new Function<Closure,Predicate>() {
- @Override
- public Predicate<?> apply(final Closure closure) {
- return new Predicate<Object>() {
- @Override public boolean apply(Object input) {
- return (Boolean) closure.call(input);
- }
- };
- }
- });
- registerAdapter(Closure.class, Function.class, new Function<Closure,Function>() {
- @Override
- public Function apply(final Closure closure) {
- return new Function() {
- @Override public Object apply(Object input) {
- return closure.call(input);
- }
- };
- }
- });
- registerAdapter(Object.class, Duration.class, new Function<Object,Duration>() {
- @Override
- public Duration apply(final Object input) {
- return org.apache.brooklyn.util.time.Duration.of(input);
- }
- });
- registerAdapter(Object.class, TimeDuration.class, new Function<Object,TimeDuration>() {
- @SuppressWarnings("deprecation")
- @Override
- public TimeDuration apply(final Object input) {
- log.warn("deprecated automatic coercion of Object to TimeDuration (set breakpoint in TypeCoercions to inspect, convert to Duration)");
- return JavaGroovyEquivalents.toTimeDuration(input);
- }
- });
- registerAdapter(TimeDuration.class, Long.class, new Function<TimeDuration,Long>() {
- @Override
- public Long apply(final TimeDuration input) {
- log.warn("deprecated automatic coercion of TimeDuration to Long (set breakpoint in TypeCoercions to inspect, use Duration instead of Long!)");
- return input.toMilliseconds();
- }
- });
- registerAdapter(Integer.class, AtomicLong.class, new Function<Integer,AtomicLong>() {
- @Override public AtomicLong apply(final Integer input) {
- return new AtomicLong(input);
- }
- });
- registerAdapter(Long.class, AtomicLong.class, new Function<Long,AtomicLong>() {
- @Override public AtomicLong apply(final Long input) {
- return new AtomicLong(input);
- }
- });
- registerAdapter(String.class, AtomicLong.class, new Function<String,AtomicLong>() {
- @Override public AtomicLong apply(final String input) {
- return new AtomicLong(Long.parseLong(input.trim()));
- }
- });
- registerAdapter(Integer.class, AtomicInteger.class, new Function<Integer,AtomicInteger>() {
- @Override public AtomicInteger apply(final Integer input) {
- return new AtomicInteger(input);
- }
- });
- registerAdapter(String.class, AtomicInteger.class, new Function<String,AtomicInteger>() {
- @Override public AtomicInteger apply(final String input) {
- return new AtomicInteger(Integer.parseInt(input.trim()));
- }
- });
- /** This always returns a {@link Double}, cast as a {@link Number};
- * however primitives and boxers get exact typing due to call in #stringToPrimitive */
- registerAdapter(String.class, Number.class, new Function<String,Number>() {
- @Override
- public Number apply(String input) {
- return Double.valueOf(input);
- }
- });
- registerAdapter(BigDecimal.class, Double.class, new Function<BigDecimal,Double>() {
- @Override
- public Double apply(BigDecimal input) {
- return input.doubleValue();
- }
- });
- registerAdapter(BigInteger.class, Long.class, new Function<BigInteger,Long>() {
- @Override
- public Long apply(BigInteger input) {
- return input.longValue();
- }
- });
- registerAdapter(BigInteger.class, Integer.class, new Function<BigInteger,Integer>() {
- @Override
- public Integer apply(BigInteger input) {
- return input.intValue();
- }
- });
- registerAdapter(String.class, BigDecimal.class, new Function<String,BigDecimal>() {
- @Override
- public BigDecimal apply(String input) {
- return new BigDecimal(input);
- }
- });
- registerAdapter(Double.class, BigDecimal.class, new Function<Double,BigDecimal>() {
- @Override
- public BigDecimal apply(Double input) {
- return BigDecimal.valueOf(input);
- }
- });
- registerAdapter(String.class, BigInteger.class, new Function<String,BigInteger>() {
- @Override
- public BigInteger apply(String input) {
- return new BigInteger(input);
- }
- });
- registerAdapter(Long.class, BigInteger.class, new Function<Long,BigInteger>() {
- @Override
- public BigInteger apply(Long input) {
- return BigInteger.valueOf(input);
- }
- });
- registerAdapter(Integer.class, BigInteger.class, new Function<Integer,BigInteger>() {
- @Override
- public BigInteger apply(Integer input) {
- return BigInteger.valueOf(input);
- }
- });
- registerAdapter(String.class, Date.class, new Function<String,Date>() {
- @Override
- public Date apply(final String input) {
- return Time.parseDate(input);
- }
- });
- registerAdapter(String.class, Class.class, new Function<String,Class>() {
- @Override
- public Class apply(final String input) {
- try {
- return new ClassLoaderUtils(this.getClass()).loadClass(input);
- } catch (ClassNotFoundException e) {
- throw Exceptions.propagate(e);
- }
- }
- });
- registerAdapter(String.class, AttributeSensor.class, new Function<String,AttributeSensor>() {
- @Override
- public AttributeSensor apply(final String input) {
- Entity entity = BrooklynTaskTags.getContextEntity(Tasks.current());
- if (entity!=null) {
- Sensor<?> result = entity.getEntityType().getSensor(input);
- if (result instanceof AttributeSensor)
- return (AttributeSensor) result;
- }
- return Sensors.newSensor(Object.class, input);
- }
- });
- registerAdapter(String.class, Sensor.class, new Function<String,Sensor>() {
- @Override
- public AttributeSensor apply(final String input) {
- Entity entity = BrooklynTaskTags.getContextEntity(Tasks.current());
- if (entity!=null) {
- Sensor<?> result = entity.getEntityType().getSensor(input);
- if (result != null)
- return (AttributeSensor) result;
- }
- return Sensors.newSensor(Object.class, input);
- }
- });
- registerAdapter(String.class, List.class, new Function<String,List>() {
- @Override
- public List<String> apply(final String input) {
- return JavaStringEscapes.unwrapJsonishListIfPossible(input);
- }
- });
- registerAdapter(String.class, Set.class, new Function<String,Set>() {
- @Override
- public Set<String> apply(final String input) {
- return MutableSet.copyOf(JavaStringEscapes.unwrapJsonishListIfPossible(input)).asUnmodifiable();
- }
- });
- registerAdapter(String.class, QuorumCheck.class, new Function<String,QuorumCheck>() {
- @Override
- public QuorumCheck apply(final String input) {
- return QuorumChecks.of(input);
- }
- });
- registerAdapter(Iterable.class, String[].class, new Function<Iterable, String[]>() {
- @Nullable
- @Override
- public String[] apply(@Nullable Iterable list) {
- if (list == null) return null;
- String[] result = new String[Iterables.size(list)];
- int count = 0;
- for (Object element : list) {
- result[count++] = coerce(element, String.class);
- }
- return result;
- }
- });
- registerAdapter(Iterable.class, Integer[].class, new Function<Iterable, Integer[]>() {
- @Nullable
- @Override
- public Integer[] apply(@Nullable Iterable list) {
- if (list == null) return null;
- Integer[] result = new Integer[Iterables.size(list)];
- int count = 0;
- for (Object element : list) {
- result[count++] = coerce(element, Integer.class);
- }
- return result;
- }
- });
- registerAdapter(Iterable.class, int[].class, new Function<Iterable, int[]>() {
- @Nullable
- @Override
- public int[] apply(@Nullable Iterable list) {
- if (list == null) return null;
- int[] result = new int[Iterables.size(list)];
- int count = 0;
- for (Object element : list) {
- result[count++] = coerce(element, int.class);
- }
- return result;
- }
- });
- registerAdapter(String.class, Map.class, new Function<String,Map>() {
- @Override
- public Map apply(final String input) {
- Exception error = null;
-
- // first try wrapping in braces if needed
- if (!input.trim().startsWith("{")) {
- try {
- return apply("{ "+input+" }");
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- // prefer this error
- error = e;
- // fall back to parsing without braces, e.g. if it's multiline
- }
- }
++ public static class BrooklynCommonAdaptorTypeCoercions extends CommonAdaptorTypeCoercions {
++
++ public BrooklynCommonAdaptorTypeCoercions(TypeCoercerExtensible coercer) { super(coercer); }
+
- try {
- return Yamls.getAs( Yamls.parseAll(input), Map.class );
- } catch (Exception e) {
- Exceptions.propagateIfFatal(e);
- if (error!=null && input.indexOf('\n')==-1) {
- // prefer the original error if it wasn't braced and wasn't multiline
- e = error;
++ @SuppressWarnings("rawtypes")
++ @Override
++ public void registerClassForNameAdapters() {
++ registerAdapter(String.class, Class.class, new Function<String,Class>() {
++ @Override
++ public Class apply(final String input) {
++ try {
++ //return Class.forName(input);
++ return new ClassLoaderUtils(this.getClass()).loadClass(input);
++ } catch (ClassNotFoundException e) {
++ throw Exceptions.propagate(e);
+ }
- throw new IllegalArgumentException("Cannot parse string as map with flexible YAML parsing; "+
- (e instanceof ClassCastException ? "yaml treats it as a string" :
- (e instanceof IllegalArgumentException && Strings.isNonEmpty(e.getMessage())) ? e.getMessage() :
- ""+e) );
+ }
-
- // NB: previously we supported this also, when we did json above;
- // yaml support is better as it supports quotes (and better than json because it allows dropping quotes)
- // snake-yaml, our parser, also accepts key=value -- although i'm not sure this is strictly yaml compliant;
- // our tests will catch it if snake behaviour changes, and we can reinstate this
- // (but note it doesn't do quotes; see http://code.google.com/p/guava-libraries/issues/detail?id=412 for that):
-// return ImmutableMap.copyOf(Splitter.on(",").trimResults().omitEmptyStrings().withKeyValueSeparator("=").split(input));
- }
- });
++ });
++ }
++
+ }
}