@Override protected <T> Task<T> runAtEntity( final Entity entity, final Effector<T> eff, @SuppressWarnings("rawtypes") final Map parameters) { manageIfNecessary(entity, eff); // prefer to submit this from the current execution context so it sets up correct cross-context // chaining ExecutionContext ec = BasicExecutionContext.getCurrentExecutionContext(); if (ec == null) { log.debug("Top-level effector invocation: {} on {}", eff, entity); ec = getExecutionContext(entity); } return ec.submit(Effectors.invocation(entity, eff, parameters)); }
/** * attempt to resolve the given value as the given type, waiting on futures, submitting if * necessary, and coercing as allowed by TypeCoercions; contextMessage (optional) will be * displayed in status reports while it waits (e.g. the name of the config key being looked up) */ @SuppressWarnings({"unchecked", "rawtypes"}) public static <T> T resolveValue( Object v, Class<T> type, ExecutionContext exec, String contextMessage) throws ExecutionException, InterruptedException { // if the expected type is a closure or map and that's what we have, we're done (or if it's // null); // but not allowed to return a future or DeferredSupplier as the resolved value if (v == null || (type.isInstance(v) && !Future.class.isInstance(v) && !DeferredSupplier.class.isInstance(v))) return (T) v; try { // if it's a task or a future, we wait for the task to complete if (v instanceof Task) { // if it's a task, we make sure it is submitted // (perhaps could run it here? ... tbd) if (!((Task) v).isSubmitted()) { exec.submit((Task) v); } } if (v instanceof Future) { final Future<?> vfuture = (Future<?>) v; // including tasks, above if (!vfuture.isDone()) { final AtomicReference<Object> vref = new AtomicReference<Object>(v); withBlockingDetails( "Waiting for " + (contextMessage != null ? contextMessage + ", " : "") + v, new Callable<Void>() { public Void call() throws Exception { vref.set(vfuture.get()); return null; } }); v = vref.get(); } else { v = vfuture.get(); } } else if (v instanceof DeferredSupplier<?>) { v = ((DeferredSupplier<?>) v).get(); } else if (v instanceof Map) { // and if a map or list we look inside Map result = Maps.newLinkedHashMap(); for (Map.Entry<?, ?> entry : ((Map<?, ?>) v).entrySet()) { result.put( entry.getKey(), resolveValue( entry.getValue(), type, exec, (contextMessage != null ? contextMessage + ", " : "") + "map entry " + entry.getKey())); } return (T) result; } else if (v instanceof List) { List result = Lists.newArrayList(); int count = 0; for (Object it : (List) v) { result.add( resolveValue( it, type, exec, (contextMessage != null ? contextMessage + ", " : "") + "list entry " + count)); count++; } return (T) result; } else { return TypeCoercions.coerce(v, type); } } catch (Exception e) { throw new IllegalArgumentException( "Error resolving " + (contextMessage != null ? contextMessage + ", " : "") + v + ", in " + exec + ": " + e, e); } return resolveValue(v, type, exec, contextMessage); }