You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@brooklyn.apache.org by ge...@apache.org on 2016/12/20 11:10:21 UTC
[03/13] brooklyn-server git commit: Deferred DSL evaluation,
allowing for chaining
Deferred DSL evaluation, allowing for chaining
Project: http://git-wip-us.apache.org/repos/asf/brooklyn-server/repo
Commit: http://git-wip-us.apache.org/repos/asf/brooklyn-server/commit/d71141ef
Tree: http://git-wip-us.apache.org/repos/asf/brooklyn-server/tree/d71141ef
Diff: http://git-wip-us.apache.org/repos/asf/brooklyn-server/diff/d71141ef
Branch: refs/heads/master
Commit: d71141ef995351ff172ade6e00f6f251a4479ee9
Parents: 2e0ee18
Author: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Authored: Thu Dec 8 12:29:51 2016 +0200
Committer: Svetoslav Neykov <sv...@cloudsoftcorp.com>
Committed: Tue Dec 13 09:15:35 2016 +0200
----------------------------------------------------------------------
.../spi/dsl/BrooklynDslInterpreter.java | 24 ++--
.../camp/brooklyn/spi/dsl/DslCallable.java | 26 ++++
.../spi/dsl/DslDeferredFunctionCall.java | 124 +++++++++++++++++++
.../brooklyn/spi/dsl/methods/DslComponent.java | 3 +-
.../camp/brooklyn/dsl/DslYamlBlockingTest.java | 3 +-
5 files changed, 167 insertions(+), 13 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d71141ef/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java
index f43d33c..5e61b43 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/BrooklynDslInterpreter.java
@@ -32,13 +32,12 @@ import org.apache.brooklyn.camp.spi.resolve.PlanInterpreter.PlanInterpreterAdapt
import org.apache.brooklyn.camp.spi.resolve.interpret.PlanInterpretationNode;
import org.apache.brooklyn.camp.spi.resolve.interpret.PlanInterpretationNode.Role;
import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Maybe;
import org.apache.brooklyn.util.javalang.Reflections;
import org.apache.brooklyn.util.text.Strings;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import com.google.common.base.Optional;
-
/**
* {@link PlanInterpreter} which understands the $brooklyn DSL
*/
@@ -175,19 +174,22 @@ public class BrooklynDslInterpreter extends PlanInterpreterAdapter {
o = BrooklynDslCommon.Functions.class;
fn = Strings.removeFromStart(fn, "function.");
}
+ List<Object> args = new ArrayList<>();
+ for (Object arg: f.getArgs()) {
+ args.add( deepEvaluation ? evaluate(arg, true) : arg );
+ }
try {
- List<Object> args = new ArrayList<>();
- for (Object arg: f.getArgs()) {
- args.add( deepEvaluation ? evaluate(arg, true) : arg );
+ if (o instanceof BrooklynDslDeferredSupplier && !(o instanceof DslCallable)) {
+ return new DslDeferredFunctionCall((BrooklynDslDeferredSupplier<?>) o, fn, args);
+ } else {
+ // Would prefer to keep the invocation logic encapsulated in DslDeferredFunctionCall, but
+ // for backwards compatibility will evaluate as much as possible eagerly (though it shouldn't matter in theory).
+ return DslDeferredFunctionCall.invokeOn(o, fn, args);
}
- Optional<Object> v = Reflections.invokeMethodWithArgs(o, fn, args);
- if (v.isPresent()) return v.get();
} catch (Exception e) {
Exceptions.propagateIfFatal(e);
- throw Exceptions.propagate(new InvocationTargetException(e, "Error invoking '"+fn+"' on '"+o+"'"));
+ throw Exceptions.propagate(new InvocationTargetException(e, "Error invoking '"+fn+"' on '"+o+"' with arguments "+args+""));
}
-
- throw new IllegalArgumentException("No such function '"+fn+"' on "+o);
}
-
+
}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d71141ef/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslCallable.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslCallable.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslCallable.java
new file mode 100644
index 0000000..4eeddb7
--- /dev/null
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslCallable.java
@@ -0,0 +1,26 @@
+/*
+ * Copyright 2016 The Apache Software Foundation.
+ *
+ * Licensed 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.spi.dsl;
+
+import org.apache.brooklyn.util.core.task.DeferredSupplier;
+
+/**
+ * Marker interface so the evaluator can tell apart objects which are {@link DeferredSupplier}
+ * but which expect DSL methods called on them instead of the value they supply.
+ */
+public interface DslCallable {
+
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d71141ef/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslDeferredFunctionCall.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslDeferredFunctionCall.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslDeferredFunctionCall.java
new file mode 100644
index 0000000..20d1a4e
--- /dev/null
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/DslDeferredFunctionCall.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2016 The Apache Software Foundation.
+ *
+ * Licensed 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.spi.dsl;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.List;
+import java.util.concurrent.Callable;
+
+import org.apache.brooklyn.api.mgmt.Task;
+import org.apache.brooklyn.core.mgmt.BrooklynTaskTags;
+import org.apache.brooklyn.util.core.task.Tasks;
+import org.apache.brooklyn.util.exceptions.Exceptions;
+import org.apache.brooklyn.util.guava.Maybe;
+import org.apache.brooklyn.util.javalang.Reflections;
+
+import com.google.common.base.Joiner;
+import com.google.common.base.Objects;
+
+public class DslDeferredFunctionCall extends BrooklynDslDeferredSupplier<Object> {
+
+ private static final long serialVersionUID = 3243262633795112155L;
+
+ // TODO should this be some of the super types?
+ private BrooklynDslDeferredSupplier<?> object;
+ private String fnName;
+ private List<?> args;
+
+ public DslDeferredFunctionCall(BrooklynDslDeferredSupplier<?> o, String fn, List<Object> args) {
+ this.object = o;
+ this.fnName = fn;
+ this.args = args;
+ }
+
+ @Override
+ public Maybe<Object> getImmediately() {
+ Maybe<?> obj = object.getImmediately();
+ if (obj.isPresent()) {
+ if (obj.isNull()) {
+ throw new IllegalArgumentException("Deferred function call, " + object +
+ " evaluates to null (when calling " + fnName + "(" + toString(args) + "))");
+ }
+ return Maybe.of(invokeOn(obj.get()));
+ }
+ return Maybe.absent("Could not evaluate immediately " + object);
+ }
+
+ @Override
+ public Task<Object> newTask() {
+ return Tasks.builder()
+ .displayName("Deferred function call " + object + "." + fnName + "(" + toString(args) + ")")
+ .tag(BrooklynTaskTags.TRANSIENT_TASK_TAG)
+ .dynamic(false)
+ .body(new Callable<Object>() {
+ @Override
+ public Object call() throws Exception {
+ Object obj = object.get();
+ if (obj == null) {
+ throw new IllegalArgumentException("Deferred function call, " + object +
+ " evaluates to null (when calling " + fnName + "(" + DslDeferredFunctionCall.toString(args) + "))");
+ }
+ return invokeOn(obj);
+ }
+
+ }).build();
+ }
+
+ protected Object invokeOn(Object obj) {
+ return invokeOn(obj, fnName, args);
+ }
+
+ protected static Object invokeOn(Object obj, String fnName, List<?> args) {
+ Maybe<Object> v;
+ try {
+ v = Reflections.invokeMethodFromArgs(obj, fnName, args);
+ } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException e) {
+ Exceptions.propagateIfFatal(e);
+ throw Exceptions.propagate(new InvocationTargetException(e, "Error invoking '"+fnName+"("+toString(args)+")' on '"+obj+"'"));
+ }
+ if (v.isPresent()) {
+ // Value is most likely another BrooklynDslDeferredSupplier - let the caller handle it,
+ return v.get();
+ } else {
+ throw new IllegalArgumentException("No such function '"+fnName+"("+toString(args)+")' on "+obj);
+ }
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hashCode(object, fnName, args);
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null || getClass() != obj.getClass()) return false;
+ DslDeferredFunctionCall that = DslDeferredFunctionCall.class.cast(obj);
+ return Objects.equal(this.object, that.object) &&
+ Objects.equal(this.fnName, that.fnName) &&
+ Objects.equal(this.args, that.args);
+ }
+
+ @Override
+ public String toString() {
+ return object + "." + fnName + "(" + toString(args) + ")";
+ }
+
+ private static String toString(List<?> args) {
+ if (args == null) return "";
+ return Joiner.on(", ").join(args);
+ }
+}
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d71141ef/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
index 7274b2e..ea8e818 100644
--- a/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
+++ b/camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
@@ -31,6 +31,7 @@ import org.apache.brooklyn.api.sensor.AttributeSensor;
import org.apache.brooklyn.api.sensor.Sensor;
import org.apache.brooklyn.camp.brooklyn.BrooklynCampConstants;
import org.apache.brooklyn.camp.brooklyn.spi.dsl.BrooklynDslDeferredSupplier;
+import org.apache.brooklyn.camp.brooklyn.spi.dsl.DslCallable;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.entity.Entities;
@@ -62,7 +63,7 @@ import com.google.common.base.Predicates;
import com.google.common.collect.Iterables;
import com.google.common.util.concurrent.Callables;
-public class DslComponent extends BrooklynDslDeferredSupplier<Entity> {
+public class DslComponent extends BrooklynDslDeferredSupplier<Entity> implements DslCallable {
private static final long serialVersionUID = -7715984495268724954L;
http://git-wip-us.apache.org/repos/asf/brooklyn-server/blob/d71141ef/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/dsl/DslYamlBlockingTest.java
----------------------------------------------------------------------
diff --git a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/dsl/DslYamlBlockingTest.java b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/dsl/DslYamlBlockingTest.java
index 280b060..772a28f 100644
--- a/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/dsl/DslYamlBlockingTest.java
+++ b/camp/camp-brooklyn/src/test/java/org/apache/brooklyn/camp/brooklyn/dsl/DslYamlBlockingTest.java
@@ -23,6 +23,7 @@ import org.apache.brooklyn.api.entity.Entity;
import org.apache.brooklyn.api.mgmt.Task;
import org.apache.brooklyn.api.sensor.AttributeSensor;
import org.apache.brooklyn.camp.brooklyn.AbstractYamlTest;
+import org.apache.brooklyn.camp.brooklyn.spi.dsl.DslCallable;
import org.apache.brooklyn.config.ConfigKey;
import org.apache.brooklyn.core.config.ConfigKeys;
import org.apache.brooklyn.core.entity.EntityInternal;
@@ -615,7 +616,7 @@ public class DslYamlBlockingTest extends AbstractYamlTest {
assertEquals(getConfigEventually(app, DEST), Boolean.TRUE);
}
- public static class DslTestCallable implements DeferredSupplier<TestDslSupplier>, ImmediateSupplier<TestDslSupplier> {
+ public static class DslTestCallable implements DslCallable, DeferredSupplier<TestDslSupplier>, ImmediateSupplier<TestDslSupplier> {
@Override
public Maybe<TestDslSupplier> getImmediately() {