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?


---

Reply via email to