package com.framsticks.core; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import com.framsticks.params.Access; import com.framsticks.params.CompositeParam; import com.framsticks.params.EventListener; import com.framsticks.params.FramsClass; import com.framsticks.params.ParamBuilder; import com.framsticks.params.PrimitiveParam; import com.framsticks.params.annotations.AutoAppendAnnotation; import com.framsticks.params.annotations.FramsClassAnnotation; import com.framsticks.params.types.EventParam; import com.framsticks.params.types.ProcedureParam; import com.framsticks.util.FramsticksException; import com.framsticks.util.dispatching.Future; import static com.framsticks.core.TreeOperations.*; @FramsClassAnnotation public final class LocalTree extends AbstractTree { private static final Logger log = LogManager.getLogger(LocalTree.class); protected Object rootObject; /** * */ public LocalTree() { super(); } @AutoAppendAnnotation public void setRootObject(Object object) { final Class javaClass = object.getClass(); registry.registerAndBuild(javaClass); Access access = registry.createAccess(javaClass); assignRootParam(access.buildParam(new ParamBuilder()).id(getName()).finish(CompositeParam.class)); assignRootObject(object); } public Object getRootObject() { return getAssignedRoot().getObject(); } public T getRootObject(Class type) { Object result = getRootObject(); if (result == null) { throw new FramsticksException().msg("object tree is empty").arg("tree", this); } if (!type.isInstance(result)) { throw new FramsticksException().msg("object tree holds object of different kind").arg("object", result).arg("requested", type).arg("tree", this); } return type.cast(result); } @Override public void get(Path path, Future future) { assert isActive(); log.debug("requesting: {}", path); path = resolveTopSync(path); future.pass(path); } // @Override // public void get(Path path, ValueParam param, Future future) { // assert isActive(); // path = resolveTopSync(path); // future.pass(bindAccess(path).get(param, Object.class)); // } @Override public void call(Path path, ProcedureParam param, Object[] arguments, Future future) { assert isActive(); try { future.pass(bindAccess(path).call(param, arguments)); } catch (FramsticksException e) { future.handle(e); } } @Override public void info(Path path, Future future) { assert isActive(); Path p = path.tryResolveIfNeeded(); Class javaClass = p.getTopObject().getClass(); FramsClass framsClass = registry.registerReflectedIfNeeded(javaClass); if (framsClass != null) { future.pass(framsClass); } else { future.handle(new FramsticksException().msg("failed to find info for class").arg("java class", javaClass)); } } protected Path resolveTopSync(Path path) { assert isActive(); assert path.isOwner(this); if (path.getTop().getObject() != null) { return path; } Access access = bindAccess(path.getUnder()); Object object = access.get(path.getTop().getParam(), Object.class); if (object == null) { throw new FramsticksException().msg("failed to resolve").arg("path", path); } return path.appendResolution(object); } @Override public void set(Path path, PrimitiveParam param, Object value, final Future future) { assert isActive(); future.pass(bindAccess(path).set(param, value)); } public void addListener(Path path, EventParam param, EventListener listener, Class argumentType, Future future) { assert isActive(); try { bindAccess(path).reg(param, listener); future.pass(null); } catch (FramsticksException e) { future.handle(e); } } public void removeListener(Path path, EventParam param, EventListener listener, Future future) { assert isActive(); try { bindAccess(path).regRemove(param, listener); future.pass(null); } catch (FramsticksException e) { future.handle(e); } } }