package com.framsticks.core; import java.util.List; import javax.annotation.Nonnull; import org.apache.log4j.Logger; import com.framsticks.communication.File; import com.framsticks.params.AccessInterface; import com.framsticks.params.CompositeParam; import com.framsticks.params.FramsClass; import com.framsticks.params.ListAccess; import com.framsticks.params.Param; import com.framsticks.params.PrimitiveParam; import com.framsticks.params.ValueParam; import com.framsticks.params.types.ObjectParam; import com.framsticks.params.types.ProcedureParam; import com.framsticks.parsers.Loaders; import com.framsticks.parsers.MultiParamLoader; import com.framsticks.util.FramsticksException; import com.framsticks.util.dispatching.Future; import com.framsticks.util.dispatching.FutureHandler; import com.framsticks.util.dispatching.RunAt; import static com.framsticks.util.dispatching.Dispatching.*; public final class TreeOperations { private static final Logger log = Logger.getLogger(TreeOperations.class.getName()); private TreeOperations() { } public static @Nonnull FramsClass processFetchedInfo(Tree tree, File file) { assert tree.isActive(); FramsClass framsClass = Loaders.loadFramsClass(file.getContent()); if ("/".equals(file.getPath())) { if (tree.getRoot().getParam().getContainedTypeName() == null) { tree.setRoot(new Node(Param.build().name("Tree").id(tree.getName()).type("o " + framsClass.getId()).finish(CompositeParam.class), tree.getRoot().getObject())); } } tree.putInfoIntoCache(framsClass); return framsClass; } public static FramsClass getInfo(Path path) { Tree tree = path.getTree(); assert tree.isActive(); final String name = path.getTop().getParam().getContainedTypeName(); return tree.getInfoFromCache(name); } public static void findInfo(final Path path, final Future future) { try { Tree tree = path.getTree(); assert tree.isActive(); final FramsClass framsClass = getInfo(path); if (framsClass != null) { future.pass(framsClass); return; } tree.info(path, future); } catch (FramsticksException e) { future.handle(e); } } public static void processFetchedValues(Path path, List files) { Tree tree = path.getTree(); assert tree.isActive(); assert files.size() == 1; assert path.isTheSame(files.get(0).getPath()); Node node = path.getTop(); MultiParamLoader loader = new MultiParamLoader(); loader.setNewSource(files.get(0).getContent()); loader.addBreakCondition(MultiParamLoader.Status.AfterObject); try { if (node.getParam() instanceof ObjectParam) { loader.addAccessInterface(TreeOperations.bindAccess(tree, node)); loader.go(); tree.notifyOfFetch(path); return; } ListAccess listAccess = ((ListAccess) TreeOperations.bindAccess(tree, node)); assert listAccess != null; listAccess.clearValues(); AccessInterface elementAccess = listAccess.getElementAccess(); loader.addAccessInterface(elementAccess); MultiParamLoader.Status status; while ((status = loader.go()) != MultiParamLoader.Status.Finished) { if (status == MultiParamLoader.Status.AfterObject) { AccessInterface accessInterface = loader.getLastAccessInterface(); String id = listAccess.computeIdentifierFor(accessInterface.getSelected()); //TODO listAccessParam Param param = Param.build().forAccess(accessInterface).id(id).finish(); Object child = accessInterface.getSelected(); accessInterface.select(null); assert child != null; TreeOperations.bindAccess(tree, node).set((ValueParam) param, child); } } tree.notifyOfFetch(path); } catch (Exception e) { log.error("exception occurred while loading: " + e); } } public static void resolveAndGet(final Tree tree, final String targetPath, final Future future) { resolve(tree, targetPath, new FutureHandler(future) { @Override protected void result(final Path path) { assert path.isResolved(targetPath); //TODO Future tree.get(path, Mode.FETCH, new FutureHandler(future) { @Override protected void result(Object object) { future.pass(path); } }); } }); } public static void resolve(final Path path, final Future future) { final Tree tree = path.getTree(); assert tree.isActive(); if (path.getTop().getObject() != null) { if (getInfoFromCache(path) != null) { future.pass(path); return; } TreeOperations.findInfo(path, new FutureHandler(future) { @Override protected void result(FramsClass result) { future.pass(path); } }); return; } TreeOperations.findInfo(path, new FutureHandler(future) { @Override protected void result(FramsClass result) { assert tree.isActive(); assert path.getTop().getParam().isMatchingContainedName(result.getId()); Path p = (path.getTop().getParam().getContainedTypeName() != null ? path : path.tryFindResolution()); future.pass(TreeOperations.createIfNeeded(p)); } }); } public static Path createIfNeeded(Tree tree, String path) { assert tree.isActive(); Path p; while (!(p = Path.to(tree, path)).isResolved(path)) { tree.create(p); } return p; } public static Path createIfNeeded(Path path) { Tree tree = path.getTree(); assert tree.isActive(); if (path.isResolved()) { return path; } return tree.create(path); } public static @Nonnull AccessInterface bindAccess(Tree tree, String path) { return bindAccess(Path.to(tree, path)); } public static @Nonnull AccessInterface bindAccess(Tree tree, Node node) { assert tree.isActive(); assert node.getObject() != null; try { return tree.prepareAccess(node.getParam()).select(node.getObject()); } catch (FramsticksException e) { throw new FramsticksException().msg("failed to prepare access for param").arg("param", node.getParam()).cause(e); // log.error("failed to bind access for " + node.getParam() + ": " + e); } } public static @Nonnull AccessInterface bindAccess(Path path) { assert path.getTree().isActive(); path.assureResolved(); return bindAccess(path.getTree(), path.getTop()); } public static void set(final Path path, final PrimitiveParam param, final Object value, final Future future) { final Tree tree = path.getTree(); dispatchIfNotActive(tree, new RunAt(future) { @Override protected void runAt() { tree.set(path, param, value, future); } }); } public static void call(final Path path, final ProcedureParam param, final Object[] arguments, final Future future) { final Tree tree = path.getTree(); dispatchIfNotActive(tree, new RunAt(future) { @Override protected void runAt() { tree.call(path, param, arguments, future); } }); } /** This might not be correct. */ public static void resolve(final Tree tree, final String targetPath, final Future future) { dispatchIfNotActive(tree, new RunAt(future) { @Override protected void runAt() { tree.resolve(Path.to(tree, targetPath), new FutureHandler(future) { @Override protected void result(Path result) { assert result.getTree().isActive(); if (result.isResolved(targetPath)) { future.pass(result); return; } resolve(tree, targetPath, future); } }); } }); } public static FramsClass getInfoFromCache(Path path) { assert path.getTree().isActive(); return path.getTree().getInfoFromCache(path.getTop().getParam().getContainedTypeName()); } }