private static Object getImmediateValue(Object value, @Nullable Entity context, @Nullable Boolean immediately, @Nullable Duration timeout) { return Tasks.resolving(value) .as(Object.class) .defaultValue(UNRESOLVED) .timeout(timeout) .immediately(immediately == null ? false : immediately.booleanValue()) .context(context) .swallowExceptions() .get(); }
@SuppressWarnings("unchecked") private U resolveImmediately(Object rawVal, Sensor<U> targetSensor) { if (rawVal == Entities.UNCHANGED || rawVal == Entities.REMOVE) { // If it's a special marker-object, then don't try to transform it return (U) rawVal; } // evaluate immediately, or return null. // For vals that implement ImmediateSupplier, we'll use that to get the value // (or Maybe.absent) without blocking. // Otherwise, the Tasks.resolving will give it its best shot at resolving without // blocking on external events (such as waiting for another entity's sensor). return (U) Tasks.resolving(rawVal).as(targetSensor.getType()) .context(entity) .description("Computing sensor "+targetSensor+" from "+rawVal) .immediately(true) .getMaybe().orNull(); } }
<S> ValueResolver<S> cloneReplacingValueAndType(Object newValue, Class<S> superType) { // superType expected to be either type or Object.class if (!superType.isAssignableFrom(type)) { throw new IllegalStateException("superType must be assignable from " + type); } ValueResolver<S> result = new ValueResolver<S>(newValue, superType) .context(exec).description(description) .embedResolutionInTask(embedResolutionInTask) .deep(forceDeep) .timeout(timeout) .immediately(immediately) .recursive(recursive); if (returnDefaultOnGet) { if (!superType.isInstance(defaultValue)) { throw new IllegalStateException("Existing default value " + defaultValue + " not compatible with new type " + superType); } @SuppressWarnings("unchecked") S typedDefaultValue = (S)defaultValue; result.defaultValue(typedDefaultValue); } if (swallowExceptions) result.swallowExceptions(); return result; }
/** * Resolves the given object, blocking on futures and coercing it to the given type. If the object is a * map or iterable (or a list of map of maps, etc, etc) then walks these maps/iterables to convert all of * their values to the given type. For example, the following will return a list containing a map with "1"="true": * * {@code Object result = resolveDeepValue(ImmutableList.of(ImmutableMap.of(1, true)), String.class, exec)} * * To perform a deep conversion of futures contained within Iterables or Maps without coercion of each element, * the type should normally be Object, not the type of the collection. This differs from * {@link #resolveValue(Object, Class, ExecutionContext, String)} which will accept Map and Iterable * as the required type. */ public static <T> T resolveDeepValue(Object v, Class<T> type, ExecutionContext exec, String contextMessage) throws ExecutionException, InterruptedException { return new ValueResolver<T>(v, type).context(exec).deep(true).description(contextMessage).get(); }
/** @see #resolveValue(Object, Class, ExecutionContext, String) */ public static <T> T resolveValue(Object v, Class<T> type, @Nullable ExecutionContext exec) throws ExecutionException, InterruptedException { return new ValueResolver<T>(v, type).context(exec).get(); }
private Map<Sensor<?>, Sensor<?>> resolveSensorMappings(Map<?,?> mapping) { if (mapping == null) { return MutableMap.of(); } Map<Sensor<?>, Sensor<?>> result = MutableMap.of(); for (Map.Entry<?,?> entry : mapping.entrySet()) { Object keyO = entry.getKey(); Object valueO = entry.getValue(); Sensor<?> key = Tasks.resolving(keyO).as(Sensor.class).immediately(true).context(producer).get(); Sensor<?> value = Tasks.resolving(valueO).as(Sensor.class).immediately(true).context(producer).get(); result.put(key, value); } return result; }
public void testNonRecursiveBlocking() throws Exception { Object result = Tasks.resolving(new WrappingImmediateAndDeferredSupplier(new FailingImmediateAndDeferredSupplier())) .as(Object.class) .context(app) .immediately(false) .recursive(false) .get(); assertEquals(result.getClass(), FailingImmediateAndDeferredSupplier.class); }
@Test(dataProvider="resolveTypes") public void testNextOrLastFound(ResolveType resolveType) { FailingImmediateAndDeferredSupplier failingExpected = new FailingImmediateAndDeferredSupplier(); WrappingImmediateAndDeferredSupplier wrapperExpected = new WrappingImmediateAndDeferredSupplier(failingExpected); ValueResolver<Object> resolver = Tasks.resolving(wrapperExpected) .as(Object.class) .context(app) .immediately(resolveType.isImmediate()); ValueResolverIterator<Object> iter = resolver.iterator(); Maybe<Object> actual = iter.nextOrLast(FailingImmediateAndDeferredSupplier.class); assertTrue(actual.isPresent()); assertNotEquals(actual, iter.last()); }
@SuppressWarnings({ "unchecked", "rawtypes" }) protected static EffectorSummary.ParameterSummary<?> parameterSummary(Entity entity, ParameterType<?> parameterType) { try { Maybe<?> defaultValue = Tasks.resolving(parameterType.getDefaultValue()) .as(parameterType.getParameterClass()) .context(entity) .immediately(true) .getMaybe(); return new ParameterSummary(parameterType.getName(), parameterType.getParameterClassName(), parameterType.getDescription(), WebResourceUtils.getValueForDisplay(defaultValue.orNull(), true, false), Sanitizer.IS_SECRET_PREDICATE.apply(parameterType.getName())); } catch (Exception e) { throw Exceptions.propagate(e); } } }
static Maybe<?> execDslEventually(BrooklynDslDeferredSupplier<?> dsl, Class<?> type, Entity context, Duration timeout) { return Tasks.resolving(dsl).as(type) .context(context) .description("Computing "+dsl) .timeout(timeout) .getMaybe(); } }
@Test(dataProvider="resolveTypes") public void testNull(ResolveType resolveType) { ValueResolver<Void> resolver = Tasks.resolving(null) .as(Void.class) .context(app) .immediately(resolveType.isImmediate()); assertNull(resolver.get()); ValueResolverIterator<Void> iter = resolver.iterator(); assertTrue(iter.hasNext()); assertNull(iter.next().get()); assertFalse(iter.hasNext()); Maybe<Object> voidOrLast = resolver.iterator().nextOrLast(Void.class); assertNull(voidOrLast.get()); Maybe<Void> voidItem = resolver.iterator().next(Void.class); assertTrue(voidItem.isAbsent()); Maybe<Void> lastItem = resolver.iterator().last(); assertNull(lastItem.get()); }
/** * For resolving a "simple" config key - i.e. where there's not custom logic inside a * {@link StructuredConfigKey} such as a {@link MapConfigKey}. For those, we'd need to do the * same as is in {@link #get(ConfigKey)}, but non-blocking! * See {@link #getNonBlockingResolvingStructuredKey(ConfigKey)}. */ protected <T> Maybe<T> getNonBlockingResolvingSimple(ConfigKey<T> key) { // TODO See AbstractConfigMapImpl.getConfigImpl, for how it looks up the "container" of the // key, so that it gets the right context entity etc. // getRaw returns Maybe(val) if the key was explicitly set (where val can be null) // or Absent if the config key was unset. Object unresolved = getRaw(key).or(key.getDefaultValue()); Maybe<Object> resolved = Tasks.resolving(unresolved) .as(Object.class) .immediately(true) .deep(true) .context(getContext()) .getMaybe(); if (resolved.isAbsent()) return Maybe.Absent.<T>castAbsent(resolved); // likely we don't need this coercion if we set as(key.getType()) above, // but that needs confirmation and quite a lot of testing return TypeCoercions.tryCoerce(resolved.get(), key.getTypeToken()); }
public void testImmediateSupplierWithTimeoutUsesBlocking() { MyImmediateAndDeferredSupplier supplier = new MyImmediateAndDeferredSupplier(); CallInfo callInfo = Tasks.resolving(supplier).as(CallInfo.class).context(app).timeout(Asserts.DEFAULT_LONG_TIMEOUT).get(); assertRealTaskNotFromMethod(callInfo, "testImmediateSupplierWithTimeoutUsesBlocking"); }
@Override public synchronized void run() { if (effector == null) return; if (!(isRunning() && getManagementContext().isRunning())) return; try { ConfigBag bag = ResolvingConfigBag.newInstanceExtending(getManagementContext(), config().getBag()); Map<String, Object> args = EntityInitializers.resolve(bag, EFFECTOR_ARGUMENTS); LOG.debug("{}: Resolving arguments for {}: {}", new Object[] { this, effector.getName(), Iterables.toString(args.keySet()) }); Map<String, Object> resolved = (Map) Tasks.resolving(args, Object.class) .deep(true) .context(entity) .get(); LOG.debug("{}: Invoking effector on {}, {}({})", new Object[] { this, entity, effector.getName(), resolved }); Object result = entity.invoke(effector, resolved).getUnchecked(); LOG.debug("{}: Effector {} returned {}", new Object[] { this, effector.getName(), result }); } catch (RuntimeInterruptedException rie) { // Gracefully stop Thread.currentThread().interrupt(); } catch (Throwable t) { LOG.warn("{}: Exception running {}: {}", new Object[] { this, effector.getName(), t.getMessage() }); Exceptions.propagate(t); } }
@Test public void testMultipleReferencesJava() throws Exception { final Entity app = createAndStartApplication(loadYaml("test-referencing-entities.yaml")); waitForApplicationTasks(app); Entity root1 = Tasks.resolving(new DslComponent(Scope.ROOT, "xxx").newTask(), Entity.class).context(app).embedResolutionInTask(true).get(); Assert.assertEquals(root1, app); Entity c1 = Tasks.resolving(new DslComponent(Scope.GLOBAL, "c1").newTask(), Entity.class).context(app).embedResolutionInTask(true).get(); Assert.assertEquals(c1, Iterables.getOnlyElement(Entities.descendantsAndSelf(app, EntityPredicates.displayNameEqualTo("child 1")))); Entity e1 = Tasks.resolving(new DslComponent(Scope.PARENT, "xxx").newTask(), Entity.class).context(c1).embedResolutionInTask(true).get(); Assert.assertEquals(e1, Iterables.getOnlyElement(Entities.descendantsAndSelf(app, EntityPredicates.displayNameEqualTo("entity 1")))); Entity root2 = Tasks.resolving(new DslComponent(Scope.ROOT, "xxx").newTask(), Entity.class).context(c1).embedResolutionInTask(true).get(); Assert.assertEquals(root2, app); Entity c1a = Tasks.resolving(BrooklynDslCommon.descendant("c1").newTask(), Entity.class).context(e1).embedResolutionInTask(true).get(); Assert.assertEquals(c1a, c1); Entity e1a = Tasks.resolving(BrooklynDslCommon.ancestor("e1").newTask(), Entity.class).context(c1).embedResolutionInTask(true).get(); Assert.assertEquals(e1a, e1); try { Tasks.resolving(BrooklynDslCommon.ancestor("c1").newTask(), Entity.class).context(e1).embedResolutionInTask(true).get(); Assert.fail("Should not have found c1 as ancestor of e1"); } catch (Exception e) { /* expected */ } }
private static ValueResolverIterator<Boolean> resolveLatchIterator(EntityInternal entity, Object val, ConfigKey<Boolean> key) { return Tasks.resolving(val, Boolean.class) .context(entity.getExecutionContext()) .description("config " + key.getName()) .iterator(); }
if (expired) return Maybe.absent("Nested resolution of "+getOriginalValue()+" did not complete within "+timeout); checkTypeNotNull(); Object v = this.value; if (allowImmediateExecution && isEvaluatingImmediately()) { ? new ValueResolver<T>(result.get(), type, this).getMaybe() : result : result; if (!task.isSubmitted()) { if (exec==null) { return Maybe.absent("Value for unsubmitted task '"+getDescription()+"' requested but no execution context available"); if (isEvaluatingImmediately()) { return ImmediateSupplier.ImmediateValueNotAvailableException.newAbsentWithExceptionSupplier(); String description = getDescription(); Maybe vm = Tasks.withBlockingDetails("Waiting for "+description, callable); if (vm.isAbsent()) return vm; return Maybe.absent("Embedding in task needed for '"+getDescription()+"' but no execution context available"); String description = getDescription(); TaskBuilder<Object> tb = Tasks.<Object>builder() .body(callable) Maybe<?> kk = new ValueResolver(entry.getKey(), type, this)
private Maybe<Entity> getResolvedConfigInTask(final Entity entity, final ConfigKey<Entity> key) { return Tasks.resolving(Tasks.<Entity>builder().body( Functionals.callable(Suppliers.compose(EntityFunctions.config(key), Suppliers.ofInstance(entity))) ).build()) .as(Entity.class) .context(entity).embedResolutionInTask(true) .getMaybe(); }