/** * 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(); }
<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; }
@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); } }
/** * 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()); }