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<Object> location() {
+ return new DslLocationSupplier(this, 0);
+ }
+
+ @DslAccessible
+ public BrooklynDslDeferredSupplier<Object> location(Object index) {
+ return new DslLocationSupplier(this, index);
+ }
+
+ protected final static class DslLocationSupplier extends
BrooklynDslDeferredSupplier<Object> {
+ 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<Object> getImmediately() {
+ Callable<Object> job = new Callable<Object>() {
+ @Override public Object call() {
+ Maybe<Entity> targetEntityMaybe =
component.getImmediately();
+ if (targetEntityMaybe.isAbsent()) return
ImmediateValueNotAvailableException.newAbsentWrapping("Target entity not
available: "+component, targetEntityMaybe);
+ Entity targetEntity = targetEntityMaybe.get();
+
+ int indexI = resolveIndex(true);
+
+ Collection<Location> 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<Object> newTask() {
+ boolean immediate = false;
+
+ Callable<Object> job = new Callable<Object>() {
+ @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<Location> 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:<nil> scopeComponent:<nil> scope:THIS] index:3]
brooklyn.wrapper_app | true
```
which users may find confusing?
---