Github user geomacy commented on a diff in the pull request:
https://github.com/apache/brooklyn-server/pull/971#discussion_r196149356
--- Diff:
camp/camp-brooklyn/src/main/java/org/apache/brooklyn/camp/brooklyn/spi/dsl/methods/DslComponent.java
---
@@ -737,6 +720,130 @@ public String toString() {
}
}
+@DslAccessible
+public BrooklynDslDeferredSupplier location() {
+return new DslLocationSupplier(this, 0);
+}
+
+@DslAccessible
+public BrooklynDslDeferredSupplier location(Object index) {
+return new DslLocationSupplier(this, index);
+}
+
+protected final static class DslLocationSupplier extends
BrooklynDslDeferredSupplier {
+private static final long serialVersionUID = 5597335296158584040L;
+private final DslComponent component;
+private final Object index;
+
+public DslLocationSupplier(DslComponent component, Object index) {
+this.component = Preconditions.checkNotNull(component);
+this.index = index;
+}
+
+@Override
+public final Maybe getImmediately() {
+Callable job = new Callable() {
+@Override public Object call() {
+Maybe targetEntityMaybe =
component.getImmediately();
+if (targetEntityMaybe.isAbsent()) return
ImmediateValueNotAvailableException.newAbsentWrapping("Target entity not
available: "+component, targetEntityMaybe);
+Entity targetEntity = targetEntityMaybe.get();
+
+int indexI = resolveIndex(true);
+
+Collection locations =
getLocations(targetEntity);
+if (locations.isEmpty()) {
+throw new
ImmediateValueNotAvailableException("Target entity has no locations:
"+component);
+} else if (locations.size() < (indexI + 1)) {
+throw new IndexOutOfBoundsException("Target entity
("+component+") has "+locations.size()+" location(s), but requested index
"+index);
+}
+Location result = Iterables.get(locations, indexI);
+if (result == null) {
+throw new NullPointerException("Target entity
("+component+") has null location at index "+index);
+}
+return result;
+}
+};
+
+return findExecutionContext(this).getImmediately(job);
+}
+
+// Pattern copied from DslConfigSupplier; see that for explanation
+@Override
+public Task newTask() {
+boolean immediate = false;
+
+Callable job = new Callable() {
+@Override
+public Object call() throws Exception {
+Entity targetEntity = component.get();
+
+// this is always run in a new dedicated task
(possibly a fake task if immediate), so no need to clear
+checkAndTagForRecursiveReference(targetEntity);
+
+int indexI = resolveIndex(immediate);
+
+// TODO Try repeatedly if no location(s)?
+Collection locations =
getLocations(targetEntity);
+if (locations.size() < (indexI + 1)) {
+throw new IndexOutOfBoundsException("Target entity
("+component+") has "+locations.size()+" location(s), but requested index
"+index);
--- End diff --
The behaviour is perhaps a bit odd from the app point of view. Say you set
a config value to a location with a bad index, the exception is logged in
`brooklyn.debug.log` (not `info`), but the config value is still rendered in
the application, which doesn't go on fire. The value isn't a location of
course, but the supplier:
```
$ br app bn ent BEN config
Key| Value
camp.template.id | yJlI9Z2t
testLocN | map[component:map[componentId:
componentIdSupplier: scopeComponent: scope:THIS] index:3]
brooklyn.wrapper_app | true
```
which users may find confusing?
---