You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by sv...@apache.org on 2017/05/23 14:23:39 UTC
[1/6] brooklyn-server git commit: Test jclouds TemplateOptions
coercions
Repository: brooklyn-server
Updated Branches:
refs/heads/master 377454ed8 -> 6287271b8
Test jclouds TemplateOptions coercions
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/610c720f
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/610c720f
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/610c720f
Branch: refs/heads/master
Commit: 610c720f73476b6a63770916f72cc9d8da75c334
Parents: 1b23cb6
Author: Aled Sage <al...@gmail.com>
Authored: Mon May 22 14:08:34 2017 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Tue May 23 14:45:33 2017 +0100
----------------------------------------------------------------------
.../JcloudsTemplateOptionsYamlTest.java | 118 +++++++++++++++++++
.../JcloudsTemplateOptionsStubbedTest.java | 102 ++++++++++++++++
2 files changed, 220 insertions(+)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/610c720f/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/JcloudsTemplateOptionsYamlTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/JcloudsTemplateOptionsYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/JcloudsTemplateOptionsYamlTest.java
new file mode 100644
index 0000000..943266b
--- /dev/null
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/JcloudsTemplateOptionsYamlTest.java
@@ -0,0 +1,118 @@
+/*
+ * 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.camp.brooklyn;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.NoSuchElementException;
+
+import org.apache.brooklyn.api.entity.Application;
+import org.apache.brooklyn.api.entity.Entity;
+import org.apache.brooklyn.api.entity.EntitySpec;
+import org.apache.brooklyn.camp.brooklyn.JcloudsCustomizerInstantiationYamlDslTest.RecordingLocationCustomizer;
+import org.apache.brooklyn.camp.brooklyn.spi.creation.CampTypePlanTransformer;
+import org.apache.brooklyn.core.entity.trait.Startable;
+import org.apache.brooklyn.core.typereg.RegisteredTypeLoadingContexts;
+import org.apache.brooklyn.entity.machine.MachineEntity;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
+import org.jclouds.googlecomputeengine.domain.Instance.ServiceAccount;
+import org.testng.annotations.AfterMethod;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicates;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+/**
+ * Tests that jcouds TemplateOptions are constructed properly from yaml blueprints.
+ */
+@Test
+public class JcloudsTemplateOptionsYamlTest extends AbstractJcloudsStubYamlTest {
+
+ @BeforeMethod(alwaysRun=true)
+ @Override
+ public void setUp() throws Exception {
+ RecordingLocationCustomizer.clear();
+ super.setUp();
+ }
+
+ @AfterMethod(alwaysRun=true)
+ @Override
+ public void tearDown() throws Exception {
+ try {
+ super.tearDown();
+ } finally {
+ RecordingLocationCustomizer.clear();
+ }
+ }
+
+ @Override
+ protected String getLocationSpec() {
+ return "jclouds:google-compute-engine:us-central1-a";
+ }
+
+ @Test
+ public void testCoercesStronglyTypedTemplateOption() throws Exception {
+ String yaml = Joiner.on("\n").join(
+ "location: " + LOCATION_CATALOG_ID,
+ "services:\n" +
+ "- type: " + MachineEntity.class.getName(),
+ " brooklyn.config:",
+ " onbox.base.dir.skipResolution: true",
+ " sshMonitoring.enabled: false",
+ " metrics.usage.retrieve: false",
+ " enabled: true",
+ " provisioning.properties:",
+ " templateOptions:",
+ " serviceAccounts:",
+ " - email: myemail",
+ " scopes:",
+ " - myscope1",
+ " - myscope2",
+ " customizer:",
+ " $brooklyn:object:",
+ " type: " + RecordingLocationCustomizer.class.getName(),
+ " object.fields:",
+ " enabled: $brooklyn:config(\"enabled\")");
+
+ EntitySpec<?> spec = managementContext.getTypeRegistry().createSpecFromPlan(CampTypePlanTransformer.FORMAT, yaml, RegisteredTypeLoadingContexts.spec(Application.class), EntitySpec.class);
+ Entity app = managementContext.getEntityManager().createEntity(spec);
+
+ app.invoke(Startable.START, ImmutableMap.<String, Object>of()).get();
+
+ GoogleComputeEngineTemplateOptions options = (GoogleComputeEngineTemplateOptions) findTemplateOptionsInCustomizerArgs();
+ assertEquals(options.serviceAccounts(), ImmutableList.of(
+ ServiceAccount.create("myemail", ImmutableList.of("myscope1", "myscope2"))));
+ }
+
+ private TemplateOptions findTemplateOptionsInCustomizerArgs() {
+ for (RecordingLocationCustomizer.CallParams call : RecordingLocationCustomizer.calls) {
+ Optional<?> templateOptions = Iterables.tryFind(call.args, Predicates.instanceOf(TemplateOptions.class));
+ if (templateOptions.isPresent()) {
+ return (TemplateOptions) templateOptions.get();
+ }
+ }
+ throw new NoSuchElementException();
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/610c720f/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsTemplateOptionsStubbedTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsTemplateOptionsStubbedTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsTemplateOptionsStubbedTest.java
new file mode 100644
index 0000000..a65b759
--- /dev/null
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsTemplateOptionsStubbedTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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.location.jclouds;
+
+import static org.testng.Assert.assertEquals;
+
+import org.apache.brooklyn.location.jclouds.StubbedComputeServiceRegistry.AbstractNodeCreator;
+import org.apache.brooklyn.location.jclouds.StubbedComputeServiceRegistry.NodeCreator;
+import org.jclouds.compute.ComputeService;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.NodeMetadata.Status;
+import org.jclouds.compute.domain.NodeMetadataBuilder;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
+import org.jclouds.googlecomputeengine.domain.Instance.ServiceAccount;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.testng.annotations.BeforeMethod;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class JcloudsTemplateOptionsStubbedTest extends AbstractJcloudsStubbedUnitTest {
+
+ @SuppressWarnings("unused")
+ private static final Logger log = LoggerFactory.getLogger(JcloudsImageChoiceStubbedLiveTest.class);
+
+ @BeforeMethod(alwaysRun=true)
+ @Override
+ public void setUp() throws Exception {
+ super.setUp();
+ initNodeCreatorAndJcloudsLocation(newNodeCreator(), ImmutableMap.of());
+ }
+
+ /**
+ * For overriding.
+ */
+ protected String getLocationSpec() {
+ return "jclouds:google-compute-engine:us-central1-a";
+ }
+
+
+ @Override
+ protected NodeCreator newNodeCreator() {
+ return new AbstractNodeCreator() {
+ @Override protected NodeMetadata newNode(String group, Template template) {
+ NodeMetadata result = new NodeMetadataBuilder()
+ .id("myid")
+ .credentials(LoginCredentials.builder().identity("myuser").credential("mypassword").build())
+ .loginPort(22)
+ .status(Status.RUNNING)
+ .publicAddresses(ImmutableList.of("173.194.32.123"))
+ .privateAddresses(ImmutableList.of("172.168.10.11"))
+ .build();
+ return result;
+ }
+ };
+ }
+
+ @Test
+ public void testTemplateOption() throws Exception {
+ ServiceAccount serviceAccount = ServiceAccount.create("myemail", ImmutableList.of("myscope1"));
+
+ RecordingLocationCustomizer customizer = new RecordingLocationCustomizer();
+ obtainMachine(ImmutableMap.builder()
+ .put(JcloudsLocation.JCLOUDS_LOCATION_CUSTOMIZERS, ImmutableList.of(customizer))
+ .put(JcloudsLocation.TEMPLATE_OPTIONS, ImmutableMap.of(
+ "serviceAccounts", ImmutableList.of(serviceAccount)))
+ .build());
+
+ GoogleComputeEngineTemplateOptions options = (GoogleComputeEngineTemplateOptions) customizer.templateOptions;
+ assertEquals(options.serviceAccounts(), ImmutableList.of(serviceAccount));
+ }
+
+ private static class RecordingLocationCustomizer extends BasicJcloudsLocationCustomizer {
+ TemplateOptions templateOptions;
+
+ @Override
+ public void customize(JcloudsLocation location, ComputeService computeService, TemplateOptions templateOptions) {
+ this.templateOptions = templateOptions;
+ }
+ }
+}
[2/6] brooklyn-server git commit: jclouds TypeCoercions for domain
objects
Posted by sv...@apache.org.
jclouds TypeCoercions for domain objects
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/1b23cb6b
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/1b23cb6b
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/1b23cb6b
Branch: refs/heads/master
Commit: 1b23cb6b6e7471258835b1f0e4820a78f9d5251f
Parents: 57ded18
Author: Aled Sage <al...@gmail.com>
Authored: Mon May 22 14:09:29 2017 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Tue May 23 14:45:33 2017 +0100
----------------------------------------------------------------------
.../location/jclouds/JcloudsLocation.java | 4 +-
.../jclouds/JcloudsLocationResolver.java | 6 +-
.../location/jclouds/JcloudsTypeCoercions.java | 168 +++++++++++
.../JcloudsTypeCoercionsWithBuilderTest.java | 250 +++++++++++++++++
.../JcloudsTypeCoercionsWithCreateTest.java | 278 +++++++++++++++++++
5 files changed, 704 insertions(+), 2 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/1b23cb6b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
index de71585..074ec5f 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocation.java
@@ -210,7 +210,9 @@ public class JcloudsLocation extends AbstractCloudMachineProvisioningLocation im
@SetFromFlag // so it's persisted
private final Map<MachineLocation,String> vmInstanceIds = Maps.newLinkedHashMap();
- static { Networking.init(); }
+ static {
+ Networking.init();
+ }
public JcloudsLocation() {
super();
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/1b23cb6b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocationResolver.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocationResolver.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocationResolver.java
index aba0a3e..2c2f3ef 100644
--- a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocationResolver.java
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsLocationResolver.java
@@ -50,7 +50,11 @@ public class JcloudsLocationResolver implements LocationResolver {
// from http://docs.amazonwebservices.com/general/latest/gr/rande.html as of Apr 2012.
// it is suggested not to maintain this list here, instead to require aws-ec2 explicitly named.
"eu-west-1","us-east-1","us-west-1","us-west-2","ap-southeast-1","ap-northeast-1","sa-east-1");
-
+
+ static {
+ JcloudsTypeCoercions.init();
+ }
+
private ManagementContext managementContext;
@Override
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/1b23cb6b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsTypeCoercions.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsTypeCoercions.java b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsTypeCoercions.java
new file mode 100644
index 0000000..56534ed
--- /dev/null
+++ b/locations/jclouds/src/main/java/org/apache/brooklyn/location/jclouds/JcloudsTypeCoercions.java
@@ -0,0 +1,168 @@
+/*
+ * 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.location.jclouds;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.List;
+import java.util.Map;
+import java.util.Optional;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import org.apache.brooklyn.util.core.flags.MethodCoercions;
+import org.apache.brooklyn.util.core.flags.TypeCoercions;
+import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.javalang.coerce.TryCoercer;
+import org.jclouds.json.SerializedNames;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Sets;
+import com.google.common.collect.Sets.SetView;
+import com.google.common.reflect.TypeToken;
+
+public class JcloudsTypeCoercions {
+
+ private JcloudsTypeCoercions() {}
+
+ private static final AtomicBoolean initialized = new AtomicBoolean(false);
+
+ public static void init() {
+ synchronized (initialized) {
+ if (initialized.compareAndSet(false, true)) {
+ TypeCoercions.registerAdapter(new CoercionFromAutoValueBuilder());
+ TypeCoercions.registerAdapter(new CoercionFromAutoValueCreate());
+ }
+ }
+ }
+
+ static class CoercionFromAutoValueBuilder implements TryCoercer {
+ @Override
+ public <T> Maybe<T> tryCoerce(Object input, TypeToken<T> targetTypeToken) {
+ Class<? super T> targetType = targetTypeToken.getRawType();
+
+ // If we don't have a map of named params, we can't map it to builder methods
+ if (!(input instanceof Map)) {
+ return null;
+ }
+
+ Optional<Method> builderMethod = findBuilderMethod(targetType);
+ if (!builderMethod.isPresent()) return null;
+
+ Maybe<?> builder = MethodCoercions.tryFindAndInvokeMultiParameterMethod(targetType, ImmutableList.of(builderMethod.get()), ImmutableList.of());
+ if (builder.isAbsent()) {
+ return (Maybe<T>) (Maybe) builder;
+ }
+
+ Optional<Method> buildMethod = findBuildMethod(builder.get());
+ if (!buildMethod.isPresent()) {
+ return Maybe.absent("Builder for "+targetType.getCanonicalName()+" has no build() method");
+ }
+
+ for (Map.Entry<?, ?> entry : ((Map<?,?>)input).entrySet()) {
+ String key = (String) entry.getKey();
+ Object val = entry.getValue();
+
+ Maybe<?> invoked = MethodCoercions.tryFindAndInvokeBestMatchingMethod(builder.get(), key, val);
+ if (invoked.isAbsent()) {
+ RuntimeException cause = Maybe.Absent.getException(invoked);
+ return Maybe.absent("Builder for "+targetType.getCanonicalName()+" failed to call method for "+key, cause);
+ }
+ }
+
+ Maybe<?> result = MethodCoercions.tryFindAndInvokeMultiParameterMethod(builder.get(), ImmutableList.of(buildMethod.get()), ImmutableList.of());
+ if (result.isAbsent()) {
+ RuntimeException cause = Maybe.Absent.getException(result);
+ return Maybe.absent("Builder for "+targetType.getCanonicalName()+" failed to call build method", cause);
+ } else {
+ return (Maybe<T>) (Maybe) result;
+ }
+ }
+
+ private Optional<Method> findBuilderMethod(Class<?> clazz) {
+ for (Method m: clazz.getMethods()) {
+ if (((m.getModifiers()&Modifier.STATIC) == Modifier.STATIC) && m.getName().equals("builder")
+ && m.getParameterTypes().length == 0) {
+ return Optional.of(m);
+ }
+ }
+ return Optional.empty();
+ }
+
+ private Optional<Method> findBuildMethod(Object instance) {
+ for (Method m: instance.getClass().getMethods()) {
+ if (((m.getModifiers()&Modifier.STATIC) != Modifier.STATIC) && m.getName().equals("build")
+ && m.getParameterTypes().length == 0) {
+ return Optional.of(m);
+ }
+ }
+ return Optional.empty();
+ }
+ }
+
+ static class CoercionFromAutoValueCreate implements TryCoercer {
+ @Override
+ public <T> Maybe<T> tryCoerce(Object input, TypeToken<T> targetTypeToken) {
+ Class<? super T> targetType = targetTypeToken.getRawType();
+ Maybe<?> result = null;
+ Maybe<?> firstError = null;
+
+ // If we don't have a map of named params, we can't map it to "@SerializedNames"?
+ if (!(input instanceof Map)) {
+ return null;
+ }
+
+ Optional<Method> method = findCreateMethod(targetType);
+ if (!method.isPresent()) return null;
+
+ // Do we have a map of args, and need to look at the "@SerializedNames" annotation?
+ if (method.get().isAnnotationPresent(SerializedNames.class)) {
+ String[] argNames = method.get().getAnnotation(SerializedNames.class).value();
+
+ SetView<?> extraArgs = Sets.difference(((Map<?,?>)input).keySet(), ImmutableSet.copyOf(argNames));
+ if (!extraArgs.isEmpty()) {
+ return Maybe.absent("create() for "+targetType.getCanonicalName()+" does not accept extra args "+extraArgs);
+ }
+
+ List<Object> orderedArgs = Lists.newArrayList();
+ for (String argName : argNames) {
+ orderedArgs.add(((Map<?,?>)input).get(argName));
+ }
+ result = MethodCoercions.tryFindAndInvokeMultiParameterMethod(targetType, ImmutableList.of(method.get()), orderedArgs);
+ if (result != null && result.isPresent()) return Maybe.of((T)result.get());
+ if (result != null && firstError == null) firstError = result;
+ }
+
+ //not found
+ if (firstError != null) return (Maybe<T>) (Maybe) firstError;
+ return null;
+ }
+
+ private Optional<Method> findCreateMethod(Class<?> clazz) {
+ for (Method m: clazz.getMethods()) {
+ if (((m.getModifiers()&Modifier.STATIC) == Modifier.STATIC) && m.getName().equals("create")
+ && clazz.isAssignableFrom(m.getReturnType())) {
+ return Optional.of(m);
+ }
+ }
+ return Optional.empty();
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/1b23cb6b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsTypeCoercionsWithBuilderTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsTypeCoercionsWithBuilderTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsTypeCoercionsWithBuilderTest.java
new file mode 100644
index 0000000..f863102
--- /dev/null
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsTypeCoercionsWithBuilderTest.java
@@ -0,0 +1,250 @@
+/*
+ * 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.location.jclouds;
+
+import static org.apache.brooklyn.util.core.flags.TypeCoercions.coerce;
+import static org.testng.Assert.assertEquals;
+
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.javalang.coerce.ClassCoercionException;
+import org.testng.annotations.Test;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableMap;
+
+public class JcloudsTypeCoercionsWithBuilderTest {
+
+ static {
+ JcloudsTypeCoercions.init();
+ }
+
+ @Test
+ public void testCallsBuilder() {
+ assertEquals(
+ coerce(ImmutableMap.of("arg1", "val1", "arg2", "val2"), MyClazz.class),
+ MyClazz.builder().arg1("val1").arg2("val2").build());
+ assertEquals(
+ coerce(ImmutableMap.of("arg2", "val2", "arg1", "val1"), MyClazz.class),
+ MyClazz.builder().arg1("val1").arg2("val2").build());
+ assertEquals(
+ coerce(ImmutableMap.of("arg1", "val1"), MyClazz.class),
+ MyClazz.builder().arg1("val1").build());
+ assertEquals(
+ coerce(ImmutableMap.of("arg2", "val2"), MyClazz.class),
+ MyClazz.builder().arg2("val2").build());
+ }
+
+ @Test
+ public void testFailsIfExtraArgs() {
+ try {
+ coerce(ImmutableMap.of("arg1", "val1", "arg2", "val2", "arg3", "val3"), MyClazz.class);
+ Asserts.shouldHaveFailedPreviously();
+ } catch (ClassCoercionException e) {
+ Asserts.expectedFailureContains(e, "Builder for", "MyClazz", "failed to call method for arg3");
+ }
+ }
+
+ @Test
+ public void testFailsIfNoBuildMethod() {
+ try {
+ coerce(ImmutableMap.of("arg1", "val1"), MyClazzWithNoBuildMethod.class);
+ Asserts.shouldHaveFailedPreviously();
+ } catch (ClassCoercionException e) {
+ Asserts.expectedFailureContains(e, "Builder for", "MyClazzWithNoBuildMethod", "has no build() method");
+ }
+ }
+
+ @Test
+ public void testFailsIfNoNoargBuildMethod() {
+ try {
+ coerce(ImmutableMap.of("arg1", "val1"), MyClazzWithNoNoargBuildMethod.class);
+ Asserts.shouldHaveFailedPreviously();
+ } catch (ClassCoercionException e) {
+ Asserts.expectedFailureContains(e, "Builder for", "MyClazzWithNoNoargBuildMethod", "has no build() method");
+ }
+ }
+
+ @Test
+ public void testFailsIfNoNoargBuilderMethod() {
+ try {
+ coerce(ImmutableMap.of("arg1", "val1"), MyClazzWithNoNoargBuilderMethod.class);
+ Asserts.shouldHaveFailedPreviously();
+ } catch (ClassCoercionException e) {
+ Asserts.expectedFailureContains(e, "MyClazzWithNoNoargBuilderMethod", "no adapter known");
+ }
+ }
+
+ @Test
+ public void testCompositeOfCreatedObjs() {
+ assertEquals(
+ coerce(ImmutableMap.of("val",ImmutableMap.of("arg1", "val1", "arg2", "val2")), MyCompositeClazz.class),
+ MyCompositeClazz.builder().val((MyClazz.builder().arg1("val1").arg2("val2").build())).build());
+ }
+
+ public static class MyClazz {
+ private final String arg1;
+ private final String arg2;
+
+ public static class Builder {
+ private String arg1;
+ private String arg2;
+
+ public Builder arg1(String val) {
+ this.arg1 = val;
+ return this;
+ }
+ public Builder arg2(String val) {
+ this.arg2 = val;
+ return this;
+ }
+ public MyClazz build() {
+ return new MyClazz(arg1, arg2);
+ }
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ private MyClazz(String arg1, String arg2) {
+ this.arg1 = arg1;
+ this.arg2 = arg2;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || obj.getClass() != getClass()) return false;
+ MyClazz o = (MyClazz) obj;
+ return Objects.equal(arg1, o.arg1) && Objects.equal(arg2, o.arg2);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(arg1, arg2);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this).add("arg1", arg1).add("arg2", arg2).toString();
+ }
+ }
+
+ public static class MyCompositeClazz {
+ private final MyClazz val;
+
+ public static class Builder {
+ private MyClazz val;
+
+ public Builder val(MyClazz val) {
+ this.val = val;
+ return this;
+ }
+ public MyCompositeClazz build() {
+ return new MyCompositeClazz(val);
+ }
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ private MyCompositeClazz(MyClazz val) {
+ this.val = val;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null || obj.getClass() != getClass()) return false;
+ MyCompositeClazz o = (MyCompositeClazz) obj;
+ return Objects.equal(val, o.val);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(val);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this).add("val", val).toString();
+ }
+ }
+
+ public static class MyClazzWithNoNoargBuilderMethod {
+ @SuppressWarnings("unused")
+ private final String arg1;
+
+ public static class Builder {
+ private String arg1;
+
+ public Builder arg1(String val) {
+ this.arg1 = val;
+ return this;
+ }
+ public MyClazzWithNoNoargBuilderMethod build() {
+ return new MyClazzWithNoNoargBuilderMethod(arg1);
+ }
+ }
+
+ public static Builder builder(String extraArg) {
+ return new Builder();
+ }
+
+ private MyClazzWithNoNoargBuilderMethod(String arg1) {
+ this.arg1 = arg1;
+ }
+ }
+
+ public static class MyClazzWithNoBuildMethod {
+ public static class Builder {
+ public Builder arg1(String val) {
+ return this;
+ }
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ private MyClazzWithNoBuildMethod(String arg1) {
+ }
+ }
+
+ public static class MyClazzWithNoNoargBuildMethod {
+ public static class Builder {
+ private String arg1;
+
+ public Builder arg1(String val) {
+ this.arg1 = val;
+ return this;
+ }
+ public MyClazzWithNoNoargBuildMethod build(String extraArg) {
+ return new MyClazzWithNoNoargBuildMethod(arg1);
+ }
+ }
+
+ public static Builder builder() {
+ return new Builder();
+ }
+
+ private MyClazzWithNoNoargBuildMethod(String arg1) {
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/1b23cb6b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsTypeCoercionsWithCreateTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsTypeCoercionsWithCreateTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsTypeCoercionsWithCreateTest.java
new file mode 100644
index 0000000..8adab07
--- /dev/null
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsTypeCoercionsWithCreateTest.java
@@ -0,0 +1,278 @@
+/*
+ * 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.location.jclouds;
+
+import static org.apache.brooklyn.util.core.flags.TypeCoercions.coerce;
+import static org.testng.Assert.assertEquals;
+
+import java.util.List;
+import java.util.Map;
+
+import org.apache.brooklyn.test.Asserts;
+import org.apache.brooklyn.util.javalang.coerce.ClassCoercionException;
+import org.jclouds.json.SerializedNames;
+import org.testng.annotations.Test;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+public class JcloudsTypeCoercionsWithCreateTest {
+
+ static {
+ JcloudsTypeCoercions.init();
+ }
+
+ @Test
+ public void testCallsCreate() {
+ assertEquals(
+ coerce(ImmutableMap.of("arg1", "val1", "arg2", "val2"), MyClazz.class),
+ MyClazz.create("val1", "val2"));
+ assertEquals(
+ coerce(ImmutableMap.of("arg2", "val2", "arg1", "val1"), MyClazz.class),
+ MyClazz.create("val1", "val2"));
+ assertEquals(
+ coerce(ImmutableMap.of("arg1", "val1"), MyClazz.class),
+ MyClazz.create("val1", null));
+ assertEquals(
+ coerce(ImmutableMap.of("arg2", "val2"), MyClazz.class),
+ MyClazz.create(null, "val2"));
+ }
+
+ @Test
+ public void testFailsIfExtraArgs() {
+ try {
+ coerce(ImmutableMap.of("arg1", "val1", "arg2", "val2", "arg3", "val3"), MyClazz.class);
+ Asserts.shouldHaveFailedPreviously();
+ } catch (ClassCoercionException e) {
+ Asserts.expectedFailureContains(e, "create()", "MyClazz", "does not accept extra args [arg3]");
+ }
+ }
+
+ @Test
+ public void testCallsCreateWithPrimitives() {
+ assertEquals(
+ coerce(ImmutableMap.builder().put("boolArg", true).put("byteArg", (byte)1).put("shortArg", (short)2)
+ .put("intArg", (int)3).put("longArg", (long)4).put("floatArg", (float)5.0)
+ .put("doubleArg", (double)6.0).build(), MyClazzWithPrimitives.class),
+ MyClazzWithPrimitives.create(true, (byte)1, (short)2, (int)3, (long)4, (float)5.0, (double)6.0));
+ assertEquals(
+ coerce(ImmutableMap.builder().put("boolArg", "true").put("byteArg", "1").put("shortArg", "2")
+ .put("intArg", "3").put("longArg", "4").put("floatArg", "5.0")
+ .put("doubleArg", "6.0").build(), MyClazzWithPrimitives.class),
+ MyClazzWithPrimitives.create(true, (byte)1, (short)2, (int)3, (long)4, (float)5.0, (double)6.0));
+ }
+ @Test
+ public void testListOfCreatedObjs() {
+ assertEquals(
+ coerce(ImmutableMap.of("vals", ImmutableList.of()), ListOfMyClazz.class),
+ ListOfMyClazz.create(ImmutableList.of()));
+ assertEquals(
+ coerce(ImmutableMap.of("vals", ImmutableList.of(ImmutableMap.of("arg1", "val1", "arg2", "val2"))), ListOfMyClazz.class),
+ ListOfMyClazz.create(ImmutableList.of(MyClazz.create("val1", "val2"))));
+ }
+
+ @Test
+ public void testCompositeOfCreatedObjs() {
+ assertEquals(
+ coerce(ImmutableMap.of("val",ImmutableMap.of("arg1", "val1", "arg2", "val2")), MyCompositeClazz.class),
+ MyCompositeClazz.create(MyClazz.create("val1", "val2")));
+ }
+
+ @Test
+ public void testMapOfCreatedObjs() {
+ assertEquals(
+ coerce(ImmutableMap.of("vals", ImmutableMap.of()), MapOfMyClazz.class),
+ MapOfMyClazz.create(ImmutableMap.of()));
+ assertEquals(
+ coerce(ImmutableMap.of("vals", ImmutableMap.of("key1", ImmutableMap.of("arg1", "val1", "arg2", "val2"))), MapOfMyClazz.class),
+ MapOfMyClazz.create(ImmutableMap.of("key1", MyClazz.create("val1", "val2"))));
+ }
+
+ public static class MyClazz {
+ private final String arg1;
+ private final String arg2;
+
+ @SerializedNames({"arg1", "arg2"})
+ public static MyClazz create(String arg1, String arg2) {
+ return new MyClazz(arg1, arg2);
+ }
+
+ private MyClazz(String arg1, String arg2) {
+ this.arg1 = arg1;
+ this.arg2 = arg2;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof MyClazz)) return false;
+ MyClazz o = (MyClazz) obj;
+ return Objects.equal(arg1, o.arg1) && Objects.equal(arg2, o.arg2);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(arg1, arg2);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this).add("arg1", arg1).add("arg2", arg2).toString();
+ }
+ }
+
+ public static class MyCompositeClazz {
+ private final MyClazz val;
+
+ @SerializedNames({"val"})
+ public static MyCompositeClazz create(MyClazz val) {
+ return new MyCompositeClazz(val);
+ }
+
+ private MyCompositeClazz(MyClazz val) {
+ this.val = val;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof MyCompositeClazz)) return false;
+ MyCompositeClazz o = (MyCompositeClazz) obj;
+ return Objects.equal(val, o.val);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(val);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this).add("val", val).toString();
+ }
+ }
+
+ public static class MyClazzWithPrimitives {
+ private final boolean boolArg;
+ private final byte byteArg;
+ private final short shortArg;
+ private final int intArg;
+ private final long longArg;
+ private final float floatArg;
+ private final double doubleArg;
+
+ @SerializedNames({"boolArg", "byteArg", "shortArg", "intArg", "longArg", "floatArg", "doubleArg"})
+ public static MyClazzWithPrimitives create(boolean boolArg, byte byteArg, short shortArg, int intArg, long longArg, float floatArg, double doubleArg) {
+ return new MyClazzWithPrimitives(boolArg, byteArg, shortArg, intArg, longArg, floatArg, doubleArg);
+ }
+
+ private MyClazzWithPrimitives(boolean boolArg, byte byteArg, short shortArg, int intArg, long longArg, float floatArg, double doubleArg) {
+ this.boolArg = boolArg;
+ this.byteArg = byteArg;
+ this.shortArg = shortArg;
+ this.intArg = intArg;
+ this.longArg = longArg;
+ this.floatArg = floatArg;
+ this.doubleArg = doubleArg;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof MyClazzWithPrimitives)) return false;
+ MyClazzWithPrimitives o = (MyClazzWithPrimitives) obj;
+ return Objects.equal(boolArg, o.boolArg) && Objects.equal(byteArg, o.byteArg)
+ && Objects.equal(shortArg, o.shortArg) && Objects.equal(intArg, o.intArg)
+ && Objects.equal(longArg, o.longArg) && Objects.equal(floatArg, o.floatArg)
+ && Objects.equal(doubleArg, o.doubleArg);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(boolArg, byteArg, shortArg, intArg, longArg, floatArg, doubleArg);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this).add("boolArg", boolArg).add("byteArg", byteArg)
+ .add("shortArg", shortArg).add("intArg", intArg).add("longArg", longArg)
+ .add("floatArg", floatArg).add("doubleArg", doubleArg)
+ .toString();
+ }
+ }
+
+ public static class ListOfMyClazz {
+ private final List<MyClazz> vals;
+
+ @SerializedNames({"vals"})
+ public static ListOfMyClazz create(List<MyClazz> vals) {
+ return new ListOfMyClazz(vals);
+ }
+
+ private ListOfMyClazz(List<MyClazz> vals) {
+ this.vals = vals;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof ListOfMyClazz)) return false;
+ ListOfMyClazz o = (ListOfMyClazz) obj;
+ return Objects.equal(vals, o.vals);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(vals);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this).add("vals", vals).toString();
+ }
+ }
+
+ public static class MapOfMyClazz {
+ private final Map<String, MyClazz> vals;
+
+ @SerializedNames({"vals"})
+ public static MapOfMyClazz create(Map<String, MyClazz> vals) {
+ return new MapOfMyClazz(vals);
+ }
+
+ private MapOfMyClazz(Map<String, MyClazz> vals) {
+ this.vals = vals;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof MapOfMyClazz)) return false;
+ MapOfMyClazz o = (MapOfMyClazz) obj;
+ return Objects.equal(vals, o.vals);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(vals);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this).add("vals", vals).toString();
+ }
+ }
+}
[6/6] brooklyn-server git commit: Closes #693
Posted by sv...@apache.org.
Closes #693
jclouds TemplateOptions type coercions
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/6287271b
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/6287271b
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/6287271b
Branch: refs/heads/master
Commit: 6287271b8a5e7f32756049e7443b6933c82142c6
Parents: 377454e 610c720
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Tue May 23 17:23:25 2017 +0300
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Tue May 23 17:23:25 2017 +0300
----------------------------------------------------------------------
.../brooklyn/AbstractJcloudsStubYamlTest.java | 9 +-
.../JcloudsTemplateOptionsYamlTest.java | 118 ++++++++
.../util/core/flags/MethodCoercions.java | 84 ++++--
.../brooklyn/util/core/flags/TypeCoercions.java | 15 +-
.../util/core/flags/MethodCoercionsTest.java | 83 ++++--
.../location/jclouds/JcloudsLocation.java | 4 +-
.../jclouds/JcloudsLocationResolver.java | 6 +-
.../location/jclouds/JcloudsTypeCoercions.java | 168 +++++++++++
.../jclouds/AbstractJcloudsStubbedUnitTest.java | 27 +-
.../jclouds/JcloudsStubTemplateBuilder.java | 204 ++++++++++----
.../JcloudsTemplateOptionsStubbedTest.java | 102 +++++++
.../JcloudsTypeCoercionsWithBuilderTest.java | 250 +++++++++++++++++
.../JcloudsTypeCoercionsWithCreateTest.java | 278 +++++++++++++++++++
.../coerce/CommonAdaptorTryCoercions.java | 110 ++++++++
.../coerce/CommonAdaptorTypeCoercions.java | 6 +-
.../util/javalang/coerce/TryCoercer.java | 45 +++
.../javalang/coerce/TypeCoercerExtensible.java | 76 ++---
.../coerce/TypeCoercerExtensibleTest.java | 82 ++++++
18 files changed, 1503 insertions(+), 164 deletions(-)
----------------------------------------------------------------------
[3/6] brooklyn-server git commit: TypeCoercions: support more generic
coercers
Posted by sv...@apache.org.
TypeCoercions: support more generic coercers
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/b945fdc0
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/b945fdc0
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/b945fdc0
Branch: refs/heads/master
Commit: b945fdc08c41d1c3c944e9a41663d52902426baa
Parents: 377454e
Author: Aled Sage <al...@gmail.com>
Authored: Mon May 22 14:09:54 2017 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Tue May 23 14:45:33 2017 +0100
----------------------------------------------------------------------
.../brooklyn/util/core/flags/TypeCoercions.java | 15 ++-
.../coerce/CommonAdaptorTryCoercions.java | 110 +++++++++++++++++++
.../coerce/CommonAdaptorTypeCoercions.java | 6 +-
.../util/javalang/coerce/TryCoercer.java | 45 ++++++++
.../javalang/coerce/TypeCoercerExtensible.java | 76 ++++---------
.../coerce/TypeCoercerExtensibleTest.java | 82 ++++++++++++++
6 files changed, 269 insertions(+), 65 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b945fdc0/core/src/main/java/org/apache/brooklyn/util/core/flags/TypeCoercions.java
----------------------------------------------------------------------
diff --git 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
index 9b39a56..9bc25e2 100644
--- 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
@@ -18,9 +18,6 @@
*/
package org.apache.brooklyn.util.core.flags;
-import groovy.lang.Closure;
-import groovy.time.TimeDuration;
-
import java.lang.reflect.Constructor;
import java.util.Map;
@@ -40,19 +37,25 @@ import org.apache.brooklyn.util.guava.Maybe;
import org.apache.brooklyn.util.javalang.Boxing;
import org.apache.brooklyn.util.javalang.JavaClassNames;
import org.apache.brooklyn.util.javalang.Reflections;
+import org.apache.brooklyn.util.javalang.coerce.CommonAdaptorTryCoercions;
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.TryCoercer;
import org.apache.brooklyn.util.javalang.coerce.TypeCoercer;
import org.apache.brooklyn.util.javalang.coerce.TypeCoercerExtensible;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
import com.google.common.collect.ImmutableMap;
import com.google.common.reflect.TypeToken;
+import groovy.lang.Closure;
+import groovy.time.TimeDuration;
+
/** Static class providing a shared {@link TypeCoercer} for all of Brooklyn */
public class TypeCoercions {
@@ -68,6 +71,7 @@ public class TypeCoercions {
public static void initStandardAdapters() {
new BrooklynCommonAdaptorTypeCoercions(coercer).registerAllAdapters();
+ new CommonAdaptorTryCoercions(coercer).registerAllAdapters();
registerDeprecatedBrooklynAdapters();
registerBrooklynAdapters();
registerGroovyAdapters();
@@ -82,6 +86,11 @@ public class TypeCoercions {
return coercer.registerAdapter(sourceType, targetType, fn);
}
+ @Beta
+ public static void registerAdapter(TryCoercer fn) {
+ coercer.registerAdapter(fn);
+ }
+
public static <T> Function<Object, T> function(final Class<T> type) {
return coercer.function(type);
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b945fdc0/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTryCoercions.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTryCoercions.java b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTryCoercions.java
new file mode 100644
index 0000000..b0a494a
--- /dev/null
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTryCoercions.java
@@ -0,0 +1,110 @@
+/*
+ * 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.util.javalang.coerce;
+
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.List;
+
+import org.apache.brooklyn.util.exceptions.CompoundRuntimeException;
+import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.javalang.JavaClassNames;
+import org.apache.brooklyn.util.text.Strings;
+
+import com.google.common.collect.Lists;
+import com.google.common.reflect.TypeToken;
+
+/**
+ * Defines and registers common generic coercers (e.g. to call a "fromXyz" method, to
+ * convert from one type to another).
+ */
+public class CommonAdaptorTryCoercions {
+
+ private final TypeCoercerExtensible coercer;
+
+ public CommonAdaptorTryCoercions(TypeCoercerExtensible coercer) {
+ this.coercer = coercer;
+ }
+
+ public CommonAdaptorTryCoercions registerAllAdapters() {
+ registerAdapter(new TryCoercerWithFromMethod());
+ registerAdapter(new TryCoercerToEnum());
+ registerAdapter(new TryCoercerForPrimitivesAndStrings());
+ return this;
+ }
+
+ /** Registers an adapter for use with type coercion. */
+ public synchronized void registerAdapter(TryCoercer fn) {
+ coercer.registerAdapter(fn);
+ }
+
+ protected static class TryCoercerWithFromMethod implements TryCoercer {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> Maybe<T> tryCoerce(Object input, TypeToken<T> targetType) {
+ Class<? super T> rawTargetType = targetType.getRawType();
+
+ List<ClassCoercionException> exceptions = Lists.newArrayList();
+ //now look for static TargetType.fromType(Type t) where value instanceof Type
+ for (Method m: rawTargetType.getMethods()) {
+ if (((m.getModifiers()&Modifier.STATIC)==Modifier.STATIC) &&
+ m.getName().startsWith("from") && m.getParameterTypes().length==1 &&
+ m.getParameterTypes()[0].isInstance(input)) {
+ if (m.getName().equals("from"+JavaClassNames.verySimpleClassName(m.getParameterTypes()[0]))) {
+ try {
+ return Maybe.of((T) m.invoke(null, input));
+ } catch (Exception e) {
+ exceptions.add(new ClassCoercionException("Cannot coerce type "+input.getClass()+" to "+rawTargetType.getCanonicalName()+" ("+input+"): "+m.getName()+" adapting failed", e));
+ }
+ }
+ }
+ }
+ if (exceptions.isEmpty()) {
+ return null;
+ } else if (exceptions.size() == 1) {
+ return Maybe.absent(exceptions.get(0));
+ } else {
+ String errMsg = "Failed coercing type "+input.getClass()+" to "+rawTargetType.getCanonicalName();
+ return Maybe.absent(new CompoundRuntimeException(errMsg, exceptions));
+ }
+ }
+ }
+
+ protected static class TryCoercerToEnum implements TryCoercer {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> Maybe<T> tryCoerce(Object input, TypeToken<T> targetType) {
+ Class<? super T> rawTargetType = targetType.getRawType();
+
+ //for enums call valueOf with the string representation of the value
+ if (rawTargetType.isEnum()) {
+ return EnumTypeCoercions.tryCoerceUntyped(Strings.toString(input), (Class<T>)rawTargetType);
+ } else {
+ return null;
+ }
+ }
+ }
+
+ protected static class TryCoercerForPrimitivesAndStrings implements TryCoercer {
+ @Override
+ public <T> Maybe<T> tryCoerce(Object input, TypeToken<T> targetType) {
+ return PrimitiveStringTypeCoercions.tryCoerce(input, targetType.getRawType());
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b945fdc0/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTypeCoercions.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTypeCoercions.java b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTypeCoercions.java
index 03745e6..b74548e 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTypeCoercions.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/CommonAdaptorTypeCoercions.java
@@ -41,8 +41,8 @@ import org.apache.brooklyn.util.exceptions.Exceptions;
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.Strings;
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;
@@ -61,10 +61,6 @@ public class CommonAdaptorTypeCoercions {
this.coercer = coercer;
}
- public TypeCoercerExtensible getCoercer() {
- return coercer;
- }
-
public CommonAdaptorTypeCoercions registerAllAdapters() {
registerStandardAdapters();
registerRecursiveIterableAdapters();
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b945fdc0/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/TryCoercer.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/TryCoercer.java b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/TryCoercer.java
new file mode 100644
index 0000000..f410fbc
--- /dev/null
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/TryCoercer.java
@@ -0,0 +1,45 @@
+/*
+ * 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.util.javalang.coerce;
+
+import org.apache.brooklyn.util.guava.Maybe;
+
+import com.google.common.annotations.Beta;
+import com.google.common.reflect.TypeToken;
+
+/**
+ * A coercer that can be registered, which will try to coerce the given input to the given type.
+ *
+ * This can be used for "generic" coercers, such as those that look for a {@code fromValue()}
+ * method on the target type.
+ */
+@Beta
+public interface TryCoercer {
+
+ /**
+ * The meaning of the return value is:
+ * <ul>
+ * <li>null - no errors, recommend continue with fallbacks (i.e. not found).
+ * <li>absent - had some kind of exception, recommend continue with fallbacks (but can report this error if
+ * other fallbacks fail).
+ * <li>present - coercion successful.
+ * </ul>
+ */
+ <T> Maybe<T> tryCoerce(Object input, TypeToken<T> type);
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b945fdc0/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercerExtensible.java
----------------------------------------------------------------------
diff --git a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercerExtensible.java b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercerExtensible.java
index 366ae26..a673131 100644
--- a/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercerExtensible.java
+++ b/utils/common/src/main/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercerExtensible.java
@@ -18,8 +18,6 @@
*/
package org.apache.brooklyn.util.javalang.coerce;
-import java.lang.reflect.Method;
-import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
@@ -28,17 +26,15 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
-import org.apache.brooklyn.util.exceptions.CompoundRuntimeException;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.guava.Maybe;
import org.apache.brooklyn.util.javalang.Boxing;
-import org.apache.brooklyn.util.javalang.JavaClassNames;
-import org.apache.brooklyn.util.text.Strings;
import org.apache.brooklyn.util.time.Duration;
import org.apache.brooklyn.util.time.Time;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import com.google.common.annotations.Beta;
import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.collect.HashBasedTable;
@@ -77,7 +73,10 @@ public class TypeCoercerExtensible implements TypeCoercer {
/** has all the strategies (primitives, collections, etc)
* and all the adapters from {@link CommonAdaptorTypeCoercions} */
public static TypeCoercerExtensible newDefault() {
- return new CommonAdaptorTypeCoercions(newEmpty()).registerAllAdapters().getCoercer();
+ TypeCoercerExtensible result = newEmpty();
+ new CommonAdaptorTypeCoercions(result).registerAllAdapters();
+ new CommonAdaptorTryCoercions(result).registerAllAdapters();
+ return result;
}
/** has all the strategies (primitives, collections, etc) but no adapters,
@@ -87,7 +86,10 @@ public class TypeCoercerExtensible implements TypeCoercer {
}
/** Store the coercion {@link Function functions} in a {@link Table table}. */
- private Table<Class<?>, Class<?>, Function<?,?>> registry = HashBasedTable.create();
+ private final Table<Class<?>, Class<?>, Function<?,?>> registry = HashBasedTable.create();
+
+ /** Store the generic coercers. */
+ private final List<TryCoercer> genericCoercers = Lists.newCopyOnWriteArrayList();
@Override
public <T> T coerce(Object value, Class<T> targetType) {
@@ -142,13 +144,11 @@ public class TypeCoercerExtensible implements TypeCoercer {
if (targetType.isInstance(value)) return Maybe.of( (T) value );
- result = PrimitiveStringTypeCoercions.tryCoerce(value, targetType);
- if (result!=null && result.isPresent()) return result;
- if (result!=null && firstError==null) firstError = result;
-
- result = tryCoerceWithFromMethod(value, targetType);
- if (result!=null && result.isPresent()) return result;
- if (result!=null && firstError==null) firstError = result;
+ for (TryCoercer coercer : genericCoercers) {
+ result = coercer.tryCoerce(value, targetTypeToken);
+ if (result!=null && result.isPresent()) return result;
+ if (result!=null && firstError==null) firstError = result;
+ }
//ENHANCEMENT could look in type hierarchy of both types for a conversion method...
@@ -165,13 +165,6 @@ public class TypeCoercerExtensible implements TypeCoercer {
}
}
- //for enums call valueOf with the string representation of the value
- if (targetType.isEnum()) {
- result = EnumTypeCoercions.tryCoerceUntyped(Strings.toString(value), (Class<T>)targetType);
- if (result!=null && result.isPresent()) return result;
- if (result!=null && firstError==null) firstError = result;
- }
-
//now look in registry
synchronized (registry) {
Map<Class<?>, Function<?,?>> adapters = registry.row(targetType);
@@ -212,42 +205,6 @@ public class TypeCoercerExtensible implements TypeCoercer {
return Maybe.absent(new ClassCoercionException("Cannot coerce type "+value.getClass().getCanonicalName()+" to "+targetType.getCanonicalName()+" ("+value+"): no adapter known"));
}
- /**
- * The meaning of the return value is:
- * <ul>
- * <li>null - no errors, continue with fallbacks (i.e. not found).
- * <li>absent - had some kind of exception, continue with fallbacks (but can report this error if
- * other fallbacks fail).
- * <li>present - coercion successful, return value.
- * </ul>
- */
- @SuppressWarnings("unchecked")
- protected <T> Maybe<T> tryCoerceWithFromMethod(Object value, Class<? super T> targetType) {
- List<ClassCoercionException> exceptions = Lists.newArrayList();
- //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"+JavaClassNames.verySimpleClassName(m.getParameterTypes()[0]))) {
- try {
- return Maybe.of((T) m.invoke(null, value));
- } catch (Exception e) {
- exceptions.add(new ClassCoercionException("Cannot coerce type "+value.getClass()+" to "+targetType.getCanonicalName()+" ("+value+"): "+m.getName()+" adapting failed", e));
- }
- }
- }
- }
- if (exceptions.isEmpty()) {
- return null;
- } else if (exceptions.size() == 1) {
- return Maybe.absent(exceptions.get(0));
- } else {
- String errMsg = "Failed coercing type "+value.getClass()+" to "+targetType.getCanonicalName();
- return Maybe.absent(new CompoundRuntimeException(errMsg, exceptions));
- }
- }
-
@SuppressWarnings("unchecked")
protected <T> Maybe<T> tryCoerceMap(Object value, TypeToken<T> targetTypeToken) {
if (!(value instanceof Map) || !(Map.class.isAssignableFrom(targetTypeToken.getRawType()))) return null;
@@ -324,4 +281,9 @@ public class TypeCoercerExtensible implements TypeCoercer {
return (Function<? super A,B>) registry.put(targetType, sourceType, fn);
}
+ /** Registers a generic adapter for use with type coercion. */
+ @Beta
+ public synchronized void registerAdapter(TryCoercer fn) {
+ genericCoercers.add(fn);
+ }
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/b945fdc0/utils/common/src/test/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercerExtensibleTest.java
----------------------------------------------------------------------
diff --git a/utils/common/src/test/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercerExtensibleTest.java b/utils/common/src/test/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercerExtensibleTest.java
new file mode 100644
index 0000000..afb10f9
--- /dev/null
+++ b/utils/common/src/test/java/org/apache/brooklyn/util/javalang/coerce/TypeCoercerExtensibleTest.java
@@ -0,0 +1,82 @@
+/*
+ * 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.util.javalang.coerce;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Objects;
+
+import org.apache.brooklyn.util.guava.Maybe;
+import org.testng.annotations.Test;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.reflect.TypeToken;
+
+public class TypeCoercerExtensibleTest {
+
+ TypeCoercerExtensible coercer = TypeCoercerExtensible.newDefault();
+
+ protected <T> T coerce(Object x, Class<T> type) {
+ return coercer.coerce(x, type);
+ }
+ protected <T> T coerce(Object x, TypeToken<T> type) {
+ return coercer.coerce(x, type);
+ }
+
+ @Test
+ public void testRegisterNewGenericCoercer() {
+ coercer.registerAdapter(new TryCoercer() {
+ @Override
+ @SuppressWarnings("unchecked")
+ public <T> Maybe<T> tryCoerce(Object input, TypeToken<T> type) {
+ if (input instanceof String && type.getRawType() == MyClazz.class) {
+ return (Maybe<T>) Maybe.of(new MyClazz("myprefix"+input));
+ } else {
+ return null;
+ }
+ }
+ });
+
+ assertEquals(coerce("abc", MyClazz.class), new MyClazz("myprefixabc"));
+ }
+
+ public static class MyClazz {
+ private final String val;
+
+ public MyClazz(String val) {
+ this.val = val;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(val);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (!(obj instanceof MyClazz)) return false;
+ return Objects.equals(val, ((MyClazz)obj).val);
+ }
+
+ @Override
+ public String toString() {
+ return MoreObjects.toStringHelper(this).add("val", val).toString();
+ }
+ }
+}
[5/6] brooklyn-server git commit: jclouds stubbing: support different
providers
Posted by sv...@apache.org.
jclouds stubbing: support different providers
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/57ded182
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/57ded182
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/57ded182
Branch: refs/heads/master
Commit: 57ded1822c2cecfb0be0b55a7dc528cd9d7300d9
Parents: 8a832de
Author: Aled Sage <al...@gmail.com>
Authored: Mon May 22 14:06:31 2017 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Tue May 23 14:45:33 2017 +0100
----------------------------------------------------------------------
.../brooklyn/AbstractJcloudsStubYamlTest.java | 9 +-
.../jclouds/AbstractJcloudsStubbedUnitTest.java | 27 ++-
.../jclouds/JcloudsStubTemplateBuilder.java | 204 ++++++++++++++-----
3 files changed, 185 insertions(+), 55 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/57ded182/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractJcloudsStubYamlTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractJcloudsStubYamlTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractJcloudsStubYamlTest.java
index 380c132..4854160 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractJcloudsStubYamlTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/AbstractJcloudsStubYamlTest.java
@@ -105,13 +105,17 @@ public abstract class AbstractJcloudsStubYamlTest extends AbstractJcloudsStubbed
}
protected void addStubbedLocationToCatalog() {
+ String locationSpec = getLocationSpec();
+ String provider = getProvider();
+ String regionOrEndpoint = getRegion();
+
addCatalogItems(
"brooklyn.catalog:",
" id: " + LOCATION_CATALOG_ID,
" version: 1.0.0",
" itemType: location",
" item:",
- " type: " + LOCATION_SPEC,
+ " type: " + locationSpec,
" brooklyn.config:",
" identity: myidentity",
" credential: mycredential",
@@ -124,6 +128,9 @@ public abstract class AbstractJcloudsStubYamlTest extends AbstractJcloudsStubbed
" $brooklyn:object:",
" type: "+JcloudsStubTemplateBuilder.class.getName(),
" factoryMethod.name: create",
+ " factoryMethod.args:",
+ " - " + provider,
+ " - " + regionOrEndpoint,
" " + JcloudsLocation.POLL_FOR_FIRST_REACHABLE_ADDRESS_PREDICATE.getName() + ":",
" $brooklyn:object:",
" type: "+Predicates.class.getName(),
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/57ded182/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsStubbedUnitTest.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsStubbedUnitTest.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsStubbedUnitTest.java
index 37231be..83c6b7e 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsStubbedUnitTest.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/AbstractJcloudsStubbedUnitTest.java
@@ -18,8 +18,13 @@
*/
package org.apache.brooklyn.location.jclouds;
+import static com.google.common.base.Preconditions.checkNotNull;
+
import java.util.Map;
+import org.apache.brooklyn.api.location.Location;
+import org.apache.brooklyn.api.location.LocationSpec;
+import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.mgmt.internal.LocalManagementContext;
import org.apache.brooklyn.core.test.entity.LocalManagementContextForTests;
import org.apache.brooklyn.location.jclouds.StubbedComputeServiceRegistry.BasicNodeCreator;
@@ -33,7 +38,6 @@ import org.slf4j.LoggerFactory;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
-import com.google.common.base.Predicate;
import com.google.common.base.Predicates;
import com.google.common.collect.ImmutableMap;
@@ -94,7 +98,7 @@ public abstract class AbstractJcloudsStubbedUnitTest extends AbstractJcloudsLive
this.computeServiceRegistry = new StubbedComputeServiceRegistry(nodeCreator, false);
final Map<Object, Object> defaults = ImmutableMap.builder()
.put(JcloudsLocationConfig.COMPUTE_SERVICE_REGISTRY, computeServiceRegistry)
- .put(JcloudsLocationConfig.TEMPLATE_BUILDER, JcloudsStubTemplateBuilder.create())
+ .put(JcloudsLocationConfig.TEMPLATE_BUILDER, JcloudsStubTemplateBuilder.create(getProvider(), getRegion()))
.put(JcloudsLocationConfig.ACCESS_IDENTITY, "stub-identity")
.put(JcloudsLocationConfig.ACCESS_CREDENTIAL, "stub-credential")
.put(SshMachineLocation.SSH_TOOL_CLASS, RecordingSshTool.class.getName())
@@ -125,4 +129,23 @@ public abstract class AbstractJcloudsStubbedUnitTest extends AbstractJcloudsLive
protected NodeCreator newNodeCreator() {
return new BasicNodeCreator();
}
+
+ protected String getProvider() {
+ LocationSpec<?> spec = mgmt().getLocationRegistry().getLocationSpec(getLocationSpec()).get();
+ return getRequiredConfig(spec, JcloudsLocation.CLOUD_PROVIDER);
+ }
+
+ protected String getRegion() {
+ LocationSpec<? extends Location> spec = mgmt().getLocationRegistry().getLocationSpec(getLocationSpec()).get();
+ return getRequiredConfig(spec, JcloudsLocation.CLOUD_REGION_ID);
+ }
+
+ protected String getRequiredConfig(LocationSpec<?> spec, ConfigKey<String> key) {
+ String result = (String) spec.getConfig().get(key);
+ if (result != null) {
+ return result;
+ }
+ result = (String) spec.getFlags().get(key.getName());
+ return checkNotNull(result, "config "+key.getName());
+ }
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/57ded182/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsStubTemplateBuilder.java
----------------------------------------------------------------------
diff --git a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsStubTemplateBuilder.java b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsStubTemplateBuilder.java
index 0ac5fb2..e12f5cb 100644
--- a/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsStubTemplateBuilder.java
+++ b/locations/jclouds/src/test/java/org/apache/brooklyn/location/jclouds/JcloudsStubTemplateBuilder.java
@@ -18,16 +18,25 @@
*/
package org.apache.brooklyn.location.jclouds;
-import com.google.common.base.Functions;
-import com.google.common.base.Supplier;
-import com.google.common.base.Suppliers;
-import com.google.common.base.Objects.ToStringHelper;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import org.jclouds.compute.domain.*;
+import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.t2_micro;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import java.util.Set;
+import java.util.concurrent.atomic.AtomicReference;
+
+import javax.inject.Provider;
+
+import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions;
+import org.jclouds.compute.domain.Hardware;
+import org.jclouds.compute.domain.HardwareBuilder;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.compute.domain.ImageBuilder;
+import org.jclouds.compute.domain.OperatingSystem;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.domain.Processor;
+import org.jclouds.compute.domain.TemplateBuilder;
+import org.jclouds.compute.domain.internal.TemplateBuilderImpl;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.strategy.GetImageStrategy;
import org.jclouds.compute.suppliers.ImageCacheSupplier;
@@ -38,47 +47,57 @@ import org.jclouds.domain.LoginCredentials;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.functions.ImagesToRegionAndIdMap;
import org.jclouds.ec2.compute.internal.EC2TemplateBuilderImpl;
+import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.domain.RootDeviceType;
import org.jclouds.ec2.domain.VirtualizationType;
+import org.jclouds.googlecomputeengine.compute.options.GoogleComputeEngineTemplateOptions;
import org.jclouds.rest.AuthorizationException;
+import org.jclouds.softlayer.compute.options.SoftLayerTemplateOptions;
-import javax.inject.Provider;
-import java.util.Set;
-import java.util.concurrent.atomic.AtomicReference;
-
-import static org.jclouds.ec2.compute.domain.EC2HardwareBuilder.*;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
+import com.google.common.base.Functions;
+import com.google.common.base.Objects.ToStringHelper;
+import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
+import com.google.common.base.Suppliers;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
public class JcloudsStubTemplateBuilder {
- protected final Location provider = new LocationBuilder().scope(LocationScope.PROVIDER).id("aws-ec2").description("aws-ec2").build();
- protected final Location jcloudsDomainLocation = new LocationBuilder().scope(LocationScope.REGION).id("us-east-1").description("us-east-1")
- .parent(provider).build();
-
- protected final Hardware HARDWARE_SUPPORTING_BOGUS = t2_micro().id("supporting-bogus")
- .supportsImageIds(ImmutableSet.of("us-east-1/bogus-image"))
- .virtualizationType(VirtualizationType.PARAVIRTUAL)
- .rootDeviceType(RootDeviceType.EBS)
- .build();
+ protected final Location provider;
+ protected final Location jcloudsDomainLocation;
+ protected final String providerName;
+ protected final String regionName;
+
public static TemplateBuilder create() {
return new JcloudsStubTemplateBuilder().createTemplateBuilder();
}
+ public static TemplateBuilder create(String providerName, String regionName) {
+ return new JcloudsStubTemplateBuilder(providerName, regionName).createTemplateBuilder();
+ }
+
+ public JcloudsStubTemplateBuilder() {
+ this("aws-ec2", "us-east-1");
+ }
+
+ public JcloudsStubTemplateBuilder(String providerName, String regionName) {
+ this.providerName = providerName;
+ this.regionName = regionName;
+ this.provider = new LocationBuilder().scope(LocationScope.PROVIDER).id(providerName).description(providerName).build();
+ this.jcloudsDomainLocation = new LocationBuilder().scope(LocationScope.REGION).id(this.regionName).description(this.regionName)
+ .parent(provider).build();
+ }
+
public TemplateBuilder createTemplateBuilder() {
- final Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.of(
- new ImageBuilder().providerId("ebs-image-provider").name("image")
- .id("us-east-1/bogus-image").location(jcloudsDomainLocation)
- .userMetadata(ImmutableMap.of("rootDeviceType", RootDeviceType.EBS.value()))
- .operatingSystem(new OperatingSystem(OsFamily.UBUNTU, null, "1.0", VirtualizationType.PARAVIRTUAL.value(), "ubuntu", true))
- .description("description").version("1.0").defaultCredentials(LoginCredentials.builder().user("root").build())
- .status(Image.Status.AVAILABLE)
- .build()));
+ final Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.of(getImage()));
ImmutableMap<RegionAndName, Image> imageMap = (ImmutableMap<RegionAndName, Image>) ImagesToRegionAndIdMap.imagesToMap(images.get());
Supplier<LoadingCache<RegionAndName, ? extends Image>> imageCache = Suppliers.<LoadingCache<RegionAndName, ? extends Image>> ofInstance(
CacheBuilder.newBuilder().<RegionAndName, Image>build(CacheLoader.from(Functions.forMap(imageMap))));
- JcloudsStubTemplateBuilder jcloudsStubTemplateBuilder = new JcloudsStubTemplateBuilder();
- return jcloudsStubTemplateBuilder.newTemplateBuilder(images, imageCache);
+ return newTemplateBuilder(images, imageCache);
}
/**
@@ -87,10 +106,9 @@ public class JcloudsStubTemplateBuilder {
*/
@SuppressWarnings("unchecked")
protected TemplateBuilder newTemplateBuilder(Supplier<Set<? extends Image>> images, Supplier<LoadingCache<RegionAndName, ? extends Image>> imageCache) {
-
Provider<TemplateOptions> optionsProvider = mock(Provider.class);
Provider<TemplateBuilder> templateBuilderProvider = mock(Provider.class);
- TemplateOptions defaultOptions = mock(TemplateOptions.class);
+ TemplateOptions defaultOptions = newTemplateOptions();
final GetImageStrategy getImageStrategy = mock(GetImageStrategy.class);
when(optionsProvider.get()).thenReturn(defaultOptions);
@@ -98,7 +116,7 @@ public class JcloudsStubTemplateBuilder {
Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
.of(jcloudsDomainLocation));
Supplier<Set<? extends Hardware>> sizes = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
- .of(HARDWARE_SUPPORTING_BOGUS));
+ .of(getHardware()));
// AtomicReference<AuthorizationException> authException = new AtomicReference<AuthorizationException>(new AuthorizationException());
@@ -111,18 +129,100 @@ public class JcloudsStubTemplateBuilder {
}
};
- return new EC2TemplateBuilderImpl(
- locations,
- new ImageCacheSupplier(images, 60, authException, imageLoader),
- sizes,
- Suppliers.ofInstance(jcloudsDomainLocation),
- optionsProvider,
- templateBuilderProvider,
- imageCache) {
- @Override
- protected ToStringHelper string() {
- return super.string().add("type", "Stubbed-TemplateBuilder");
- }
- };
+ switch (providerName) {
+ case "aws-ec2" :
+ case "ec2" :
+ return new EC2TemplateBuilderImpl(
+ locations,
+ new ImageCacheSupplier(images, 60, authException, imageLoader),
+ sizes,
+ Suppliers.ofInstance(jcloudsDomainLocation),
+ optionsProvider,
+ templateBuilderProvider,
+ imageCache) {
+ @Override
+ protected ToStringHelper string() {
+ return super.string().add("type", "Stubbed-TemplateBuilder");
+ }
+ };
+ default:
+ return new TemplateBuilderImpl(
+ locations,
+ new ImageCacheSupplier(images, 60, authException, imageLoader),
+ sizes,
+ Suppliers.ofInstance(jcloudsDomainLocation),
+ optionsProvider,
+ templateBuilderProvider) {
+ @Override
+ protected ToStringHelper string() {
+ return super.string().add("type", "Stubbed-TemplateBuilder");
+ }
+ };
+ }
+ }
+
+ protected TemplateOptions newTemplateOptions() {
+ switch (providerName) {
+ case "aws-ec2" :
+ return new AWSEC2TemplateOptions();
+ case "ec2" :
+ return new EC2TemplateOptions();
+ case "google-compute-engine" :
+ return new GoogleComputeEngineTemplateOptions();
+ //return mock(GoogleComputeEngineTemplateOptions.class);
+ case "azurecompute" :
+ return new org.jclouds.azurecompute.compute.options.AzureComputeTemplateOptions();
+ case "azurecompute-arm" :
+ return new org.jclouds.azurecompute.arm.compute.options.AzureTemplateOptions();
+ case "softlayer" :
+ return new SoftLayerTemplateOptions();
+ default:
+ throw new UnsupportedOperationException("Unsupported stubbed TemplateOptions for provider "+providerName);
+ }
+ }
+
+ protected Image getImage() {
+ switch (providerName) {
+ case "aws-ec2" :
+ case "ec2" :
+ return new ImageBuilder().providerId("ebs-image-provider").name("image")
+ .id(regionName+"/bogus-image").location(jcloudsDomainLocation)
+ .userMetadata(ImmutableMap.of("rootDeviceType", RootDeviceType.EBS.value()))
+ .operatingSystem(new OperatingSystem(OsFamily.UBUNTU, null, "1.0", VirtualizationType.PARAVIRTUAL.value(), "ubuntu", true))
+ .description("description").version("1.0").defaultCredentials(LoginCredentials.builder().user("root").build())
+ .status(Image.Status.AVAILABLE)
+ .build();
+ case "google-compute-engine" :
+ return new ImageBuilder().providerId("gce-image-provider").name("image")
+ .id(regionName+"/bogus-image").location(jcloudsDomainLocation)
+ .operatingSystem(new OperatingSystem(OsFamily.UBUNTU, null, "1.0", VirtualizationType.PARAVIRTUAL.value(), "ubuntu", true))
+ .description("description").version("1.0").defaultCredentials(LoginCredentials.builder().user("root").build())
+ .status(Image.Status.AVAILABLE)
+ .build();
+ default:
+ throw new UnsupportedOperationException("Unsupported stubbed Image for provider "+providerName);
+ }
+ }
+
+ protected Hardware getHardware() {
+ switch (providerName) {
+ case "aws-ec2" :
+ case "ec2" :
+ return t2_micro().id("supporting-bogus")
+ .supportsImageIds(ImmutableSet.of("us-east-1/bogus-image"))
+ .virtualizationType(VirtualizationType.PARAVIRTUAL)
+ .rootDeviceType(RootDeviceType.EBS)
+ .build();
+ case "google-compute-engine" :
+ return new HardwareBuilder()
+ .providerId(providerName)
+ .id("n1-standard-1")
+ .ram(3750)
+ .processor(new Processor(1, 1234))
+ .supportsImage(Predicates.alwaysTrue())
+ .build();
+ default:
+ throw new UnsupportedOperationException("Unsupported stubbed Hardware for provider "+providerName);
+ }
}
}
[4/6] brooklyn-server git commit: MethodCoercions: add more utility
methods
Posted by sv...@apache.org.
MethodCoercions: add more utility methods
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/8a832de5
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/8a832de5
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/8a832de5
Branch: refs/heads/master
Commit: 8a832de59c513d81c4e8c97e723fc03f0aadf26a
Parents: b945fdc
Author: Aled Sage <al...@gmail.com>
Authored: Mon May 22 18:09:15 2017 +0100
Committer: Aled Sage <al...@gmail.com>
Committed: Tue May 23 14:45:33 2017 +0100
----------------------------------------------------------------------
.../util/core/flags/MethodCoercions.java | 84 +++++++++++++++-----
.../util/core/flags/MethodCoercionsTest.java | 83 ++++++++++++++-----
2 files changed, 125 insertions(+), 42 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8a832de5/core/src/main/java/org/apache/brooklyn/util/core/flags/MethodCoercions.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/apache/brooklyn/util/core/flags/MethodCoercions.java b/core/src/main/java/org/apache/brooklyn/util/core/flags/MethodCoercions.java
index a243581..b0afcdd 100644
--- a/core/src/main/java/org/apache/brooklyn/util/core/flags/MethodCoercions.java
+++ b/core/src/main/java/org/apache/brooklyn/util/core/flags/MethodCoercions.java
@@ -18,15 +18,7 @@
*/
package org.apache.brooklyn.util.core.flags;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.collect.Iterables;
-import com.google.common.reflect.TypeToken;
-
-import javax.annotation.Nullable;
-
-import org.apache.brooklyn.util.exceptions.Exceptions;
-import org.apache.brooklyn.util.guava.Maybe;
+import static com.google.common.base.Preconditions.checkNotNull;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
@@ -34,7 +26,16 @@ import java.lang.reflect.Type;
import java.util.Arrays;
import java.util.List;
-import static com.google.common.base.Preconditions.checkNotNull;
+import javax.annotation.Nullable;
+
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Maybe;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.collect.Iterables;
+import com.google.common.reflect.TypeToken;
/**
* A way of binding a loosely-specified method call into a strongly-typed Java method call.
@@ -93,7 +94,7 @@ public class MethodCoercions {
return Maybe.absent();
}
}
-
+
/**
* Returns a predicate that matches a method with the given name, and parameters that
* {@link org.apache.brooklyn.util.core.flags.TypeCoercions#tryCoerce(Object, com.google.common.reflect.TypeToken)} can process
@@ -104,21 +105,48 @@ public class MethodCoercions {
* @return a predicate that will match a compatible method
*/
public static Predicate<Method> matchMultiParameterMethod(final String methodName, final List<?> arguments) {
+ return Predicates.and(matchMethodByName(methodName), matchMultiParameterMethod(arguments));
+ }
+
+ /**
+ * Returns a predicate that matches a method with the given name.
+ *
+ * @param methodName name of the method
+ * @return a predicate that will match a compatible method
+ */
+ public static Predicate<Method> matchMethodByName(final String methodName) {
checkNotNull(methodName, "methodName");
+
+ return new Predicate<Method>() {
+ @Override
+ public boolean apply(@Nullable Method input) {
+ return (input != null) && input.getName().equals(methodName);
+ }
+ };
+ }
+
+ /**
+ * Returns a predicate that matches a method with parameters that
+ * {@link org.apache.brooklyn.util.core.flags.TypeCoercions#tryCoerce(Object, com.google.common.reflect.TypeToken)} can process
+ * from the given list of arguments.
+ *
+ * @param arguments arguments that is intended to be given
+ * @return a predicate that will match a compatible method
+ */
+ public static Predicate<Method> matchMultiParameterMethod(final List<?> arguments) {
checkNotNull(arguments, "arguments");
return new Predicate<Method>() {
@Override
public boolean apply(@Nullable Method input) {
if (input == null) return false;
- if (!input.getName().equals(methodName)) return false;
int numOptionParams = arguments.size();
Type[] parameterTypes = input.getGenericParameterTypes();
if (parameterTypes.length != numOptionParams) return false;
for (int paramCount = 0; paramCount < numOptionParams; paramCount++) {
if (!TypeCoercions.tryCoerce(((List<?>) arguments).get(paramCount),
- TypeToken.of(parameterTypes[paramCount])).isPresentAndNonNull()) return false;
+ TypeToken.of(parameterTypes[paramCount])).isPresent()) return false;
}
return true;
}
@@ -129,15 +157,13 @@ public class MethodCoercions {
* Tries to find a multiple-parameter method with each parameter compatible with (can be coerced to) the
* corresponding argument, and invokes it.
*
- * @param instance the object to invoke the method on
- * @param methodName the name of the method to invoke
+ * @param instanceOrClazz the object or class to invoke the method on
+ * @param methods the methods to choose from
* @param argument a list of the arguments to the method's parameters.
* @return the result of the method call, or {@link org.apache.brooklyn.util.guava.Maybe#absent()} if method could not be matched.
*/
- public static Maybe<?> tryFindAndInvokeMultiParameterMethod(final Object instance, final String methodName, final List<?> arguments) {
- Class<?> clazz = instance.getClass();
- Iterable<Method> methods = Arrays.asList(clazz.getMethods());
- Optional<Method> matchingMethod = Iterables.tryFind(methods, matchMultiParameterMethod(methodName, arguments));
+ public static Maybe<?> tryFindAndInvokeMultiParameterMethod(Object instanceOrClazz, Iterable<Method> methods, List<?> arguments) {
+ Optional<Method> matchingMethod = Iterables.tryFind(methods, matchMultiParameterMethod(arguments));
if (matchingMethod.isPresent()) {
Method method = matchingMethod.get();
try {
@@ -148,7 +174,7 @@ public class MethodCoercions {
Type paramType = method.getGenericParameterTypes()[paramCount];
coercedArguments[paramCount] = TypeCoercions.coerce(argument, TypeToken.of(paramType));
}
- return Maybe.of(method.invoke(instance, coercedArguments));
+ return Maybe.of(method.invoke(instanceOrClazz, coercedArguments));
} catch (IllegalAccessException | InvocationTargetException e) {
throw Exceptions.propagate(e);
}
@@ -156,6 +182,21 @@ public class MethodCoercions {
return Maybe.absent();
}
}
+
+ /**
+ * Tries to find a multiple-parameter method with each parameter compatible with (can be coerced to) the
+ * corresponding argument, and invokes it.
+ *
+ * @param instance the object to invoke the method on
+ * @param methodName the name of the method to invoke
+ * @param argument a list of the arguments to the method's parameters.
+ * @return the result of the method call, or {@link org.apache.brooklyn.util.guava.Maybe#absent()} if method could not be matched.
+ */
+ public static Maybe<?> tryFindAndInvokeMultiParameterMethod(Object instance, String methodName, List<?> arguments) {
+ Class<?> clazz = instance.getClass();
+ Iterable<Method> methods = Iterables.filter(Arrays.asList(clazz.getMethods()), matchMethodByName(methodName));
+ return tryFindAndInvokeMultiParameterMethod(instance, methods, arguments);
+ }
/**
* Tries to find a method with each parameter compatible with (can be coerced to) the corresponding argument, and invokes it.
@@ -165,7 +206,7 @@ public class MethodCoercions {
* @param argument a list of the arguments to the method's parameters, or a single argument for a single-parameter method.
* @return the result of the method call, or {@link org.apache.brooklyn.util.guava.Maybe#absent()} if method could not be matched.
*/
- public static Maybe<?> tryFindAndInvokeBestMatchingMethod(final Object instance, final String methodName, final Object argument) {
+ public static Maybe<?> tryFindAndInvokeBestMatchingMethod(Object instance, String methodName, Object argument) {
if (argument instanceof List) {
List<?> arguments = (List<?>) argument;
@@ -181,5 +222,4 @@ public class MethodCoercions {
return tryFindAndInvokeSingleParameterMethod(instance, methodName, argument);
}
}
-
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/8a832de5/core/src/test/java/org/apache/brooklyn/util/core/flags/MethodCoercionsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/org/apache/brooklyn/util/core/flags/MethodCoercionsTest.java b/core/src/test/java/org/apache/brooklyn/util/core/flags/MethodCoercionsTest.java
index e48d2b6..57adb54 100644
--- a/core/src/test/java/org/apache/brooklyn/util/core/flags/MethodCoercionsTest.java
+++ b/core/src/test/java/org/apache/brooklyn/util/core/flags/MethodCoercionsTest.java
@@ -18,22 +18,23 @@
*/
package org.apache.brooklyn.util.core.flags;
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableList;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertTrue;
+
+import java.lang.reflect.Method;
+import java.util.List;
-import org.apache.brooklyn.util.core.flags.MethodCoercions;
import org.apache.brooklyn.util.exceptions.Exceptions;
import org.apache.brooklyn.util.guava.Maybe;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
-import java.lang.reflect.Method;
-import java.util.List;
-
-import static org.testng.Assert.*;
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableList;
public class MethodCoercionsTest {
+ private Method staticMultiParameterMethod;
private Method singleParameterMethod;
private Method multiParameterMethod;
private Method singleCollectionParameterMethod;
@@ -41,6 +42,7 @@ public class MethodCoercionsTest {
@BeforeClass
public void testFixtureSetUp() {
try {
+ staticMultiParameterMethod = TestClass.class.getMethod("staticMultiParameterMethod", boolean.class, int.class);
singleParameterMethod = TestClass.class.getMethod("singleParameterMethod", int.class);
multiParameterMethod = TestClass.class.getMethod("multiParameterMethod", boolean.class, int.class);
singleCollectionParameterMethod = TestClass.class.getMethod("singleCollectionParameterMethod", List.class);
@@ -58,11 +60,19 @@ public class MethodCoercionsTest {
}
@Test
- public void testTryFindAndInvokeSingleParameterMethod() throws Exception {
- TestClass instance = new TestClass();
- Maybe<?> maybe = MethodCoercions.tryFindAndInvokeSingleParameterMethod(instance, "singleParameterMethod", "42");
- assertTrue(maybe.isPresent());
- assertTrue(instance.wasSingleParameterMethodCalled());
+ public void testMatchSingleCollectionParameterMethod() throws Exception {
+ Predicate<Method> predicate = MethodCoercions.matchSingleParameterMethod("singleCollectionParameterMethod", ImmutableList.of("42"));
+ assertFalse(predicate.apply(singleParameterMethod));
+ assertFalse(predicate.apply(multiParameterMethod));
+ assertTrue(predicate.apply(singleCollectionParameterMethod));
+ }
+
+ @Test
+ public void testMatchMethodByName() throws Exception {
+ Predicate<Method> predicate = MethodCoercions.matchMethodByName("singleParameterMethod");
+ assertTrue(predicate.apply(singleParameterMethod));
+ assertFalse(predicate.apply(multiParameterMethod));
+ assertFalse(predicate.apply(singleCollectionParameterMethod));
}
@Test
@@ -74,6 +84,14 @@ public class MethodCoercionsTest {
}
@Test
+ public void testMatchMultiParameterMethodWithoutName() throws Exception {
+ Predicate<Method> predicate = MethodCoercions.matchMultiParameterMethod(ImmutableList.of("true", "42"));
+ assertFalse(predicate.apply(singleParameterMethod));
+ assertTrue(predicate.apply(multiParameterMethod));
+ assertFalse(predicate.apply(singleCollectionParameterMethod));
+ }
+
+ @Test
public void testTryFindAndInvokeMultiParameterMethod() throws Exception {
TestClass instance = new TestClass();
Maybe<?> maybe = MethodCoercions.tryFindAndInvokeMultiParameterMethod(instance, "multiParameterMethod", ImmutableList.of("true", "42"));
@@ -82,6 +100,17 @@ public class MethodCoercionsTest {
}
@Test
+ public void testTryFindAndInvokeStaticMultiParameterMethod() throws Exception {
+ try {
+ Maybe<?> maybe = MethodCoercions.tryFindAndInvokeMultiParameterMethod(TestClass.class, ImmutableList.of(staticMultiParameterMethod), ImmutableList.of("true", "42"));
+ assertTrue(maybe.isPresent());
+ assertTrue(TestClass.wasStaticMultiParameterMethodCalled());
+ } finally {
+ TestClass.clear();
+ }
+ }
+
+ @Test
public void testTryFindAndInvokeBestMatchingMethod() throws Exception {
TestClass instance = new TestClass();
Maybe<?> maybe = MethodCoercions.tryFindAndInvokeBestMatchingMethod(instance, "singleParameterMethod", "42");
@@ -98,29 +127,43 @@ public class MethodCoercionsTest {
assertTrue(maybe.isPresent());
assertTrue(instance.wasSingleCollectionParameterMethodCalled());
}
-/*
+
@Test
- public void testMatchSingleCollectionParameterMethod() throws Exception {
- Predicate<Method> predicate = MethodCoercions.matchSingleCollectionParameterMethod("singleCollectionParameterMethod", ImmutableList.of("42"));
- assertFalse(predicate.apply(singleParameterMethod));
- assertFalse(predicate.apply(multiParameterMethod));
- assertTrue(predicate.apply(singleCollectionParameterMethod));
+ public void testTryFindAndInvokeSingleParameterMethod() throws Exception {
+ TestClass instance = new TestClass();
+ Maybe<?> maybe = MethodCoercions.tryFindAndInvokeSingleParameterMethod(instance, "singleParameterMethod", "42");
+ assertTrue(maybe.isPresent());
+ assertTrue(instance.wasSingleParameterMethodCalled());
}
@Test
public void testTryFindAndInvokeSingleCollectionParameterMethod() throws Exception {
TestClass instance = new TestClass();
- Maybe<?> maybe = MethodCoercions.tryFindAndInvokeSingleCollectionParameterMethod(instance, "singleCollectionParameterMethod", ImmutableList.of("42"));
+ Maybe<?> maybe = MethodCoercions.tryFindAndInvokeSingleParameterMethod(instance, "singleCollectionParameterMethod", ImmutableList.of("42"));
assertTrue(maybe.isPresent());
assertTrue(instance.wasSingleCollectionParameterMethodCalled());
}
-*/
+
public static class TestClass {
+ private static boolean staticMultiParameterMethodCalled;
+
private boolean singleParameterMethodCalled;
private boolean multiParameterMethodCalled;
private boolean singleCollectionParameterMethodCalled;
+ public static void staticMultiParameterMethod(boolean parameter1, int parameter2) {
+ staticMultiParameterMethodCalled = true;
+ }
+
+ public static boolean wasStaticMultiParameterMethodCalled() {
+ return staticMultiParameterMethodCalled;
+ }
+
+ public static void clear() {
+ staticMultiParameterMethodCalled = false;
+ }
+
public void singleParameterMethod(int parameter) {
singleParameterMethodCalled = true;
}