package com.framsticks.remote; import static com.framsticks.core.TreeOperations.*; import com.framsticks.core.Mode; import com.framsticks.core.Node; import com.framsticks.core.Path; import com.framsticks.params.AccessInterface; import com.framsticks.params.CompositeParam; import com.framsticks.params.FramsClass; import com.framsticks.core.Tree; import com.framsticks.util.dispatching.Future; import com.framsticks.util.dispatching.FutureHandler; import com.framsticks.util.dispatching.ThrowExceptionHandler; import com.framsticks.util.FramsticksException; import com.framsticks.util.Logging; import com.framsticks.util.Stopwatch; import org.apache.log4j.Logger; import static com.framsticks.util.lang.Containers.filterInstanceof; import com.framsticks.util.dispatching.RunAt; /** * @author Piotr Sniegowski */ public class RecursiveFetcher { private final static Logger log = Logger.getLogger(RecursiveFetcher.class.getName()); protected final Tree tree; protected final Future future; protected int dispatched; protected final Stopwatch stopwatch = new Stopwatch(); public RecursiveFetcher(Tree tree, final Path path, Future future) { this.tree = tree; this.future = future; dispatched = 1; process(path); } protected void finished() { assert tree.isActive(); log.info("recursively fetched in " + stopwatch); future.pass(null); } protected void process(final Path path) { assert tree.isActive(); if (path == null || !path.isResolved()) { log.warn("path " + path + " is not resolved - skipping"); } else { AccessInterface access = bindAccess(path); FramsClass framsClass = access.getFramsClass(); assert framsClass != null; for (CompositeParam p : filterInstanceof(access.getParams(), CompositeParam.class)) { Object child = access.get(p, Object.class); final Path childPath = path.appendNode(new Node(p, child)); if (childPath.isResolved() && getInfoFromCache(childPath) != null) { ++dispatched; tree.dispatch(new RunAt(ThrowExceptionHandler.getInstance()) { @Override protected void runAt() { fetch(childPath); } }); continue; } ++dispatched; tree.resolve(childPath, new FutureHandler(Logging.logger(log, "resolve", RecursiveFetcher.this)) { @Override protected void result(Path result) { assert tree.isActive(); fetch(result); } }); } } --dispatched; if (dispatched == 0) { finished(); } } protected void fetch(final Path path) { tree.get(path, Mode.FETCH, new Future() { @Override public void handle(FramsticksException e) { log.error("failed to fetch values for " + path + ": " + e); process(null); } @Override protected void result(Object object) { process(path); } }); } }