package com.framsticks.core; import javax.annotation.Nonnull; import org.apache.log4j.Logger; import com.framsticks.params.AccessInterface; import com.framsticks.params.CompositeParam; import com.framsticks.params.FramsClass; import com.framsticks.params.ParamsPackage; import com.framsticks.params.Registry; import com.framsticks.params.annotations.AutoAppendAnnotation; import com.framsticks.params.annotations.FramsClassAnnotation; import com.framsticks.params.annotations.ParamAnnotation; import com.framsticks.util.FramsticksException; import com.framsticks.util.dispatching.AbstractJoinable; import com.framsticks.util.dispatching.Dispatcher; import com.framsticks.util.dispatching.Dispatching; import com.framsticks.util.dispatching.ExceptionResultHandler; import com.framsticks.util.dispatching.Joinable; import com.framsticks.util.dispatching.JoinableDispatcher; import com.framsticks.util.dispatching.JoinableParent; import com.framsticks.util.dispatching.JoinableState; import com.framsticks.util.dispatching.RunAt; import com.framsticks.util.dispatching.Thread; import com.framsticks.util.dispatching.ThrowExceptionHandler; /** * @author Piotr Sniegowski */ @FramsClassAnnotation public abstract class AbstractTree extends AbstractJoinable implements Dispatcher, Tree, JoinableParent { private static final Logger log = Logger.getLogger(Tree.class); private Node root = null; private ExceptionResultHandler handler = ThrowExceptionHandler.getInstance(); private JoinableDispatcher dispatcher; @Override public void assignRootParam(CompositeParam param) { if (root != null) { throw new FramsticksException().msg("root has already specified type"); } root = new Node(this, param, null); log.info("assigned root type: " + root); } @Override public void assignRootObject(Object object) { if (root == null) { throw new FramsticksException().msg("root is has no type specified"); } if (root.getObject() != null) { throw new FramsticksException().msg("root has already object assigned").arg("current", root.getObject()).arg("candidate", object); } root = new Node(this, root.getParam(), object); log.info("assigned root object: " + root); } @Override public @Nonnull Node getAssignedRoot() { if (root == null) { throw new FramsticksException().msg("root has no type specified yet"); } return root; } public boolean isRootAssigned() { // assert isActive(); return root != null; } protected String name; public AbstractTree() { setName("tree"); } protected void tryRegisterOnChangeEvents(Path path) { } @Override public final FramsClass getInfoFromCache(String id) { assert isActive(); return registry.getFramsClass(id); } protected Registry registry = new Registry(); @Override public @Nonnull AccessInterface prepareAccess(CompositeParam param) { return registry.prepareAccess(param); } @Override public void takeAllFrom(Registry source) { registry.takeAllFrom(source); } @AutoAppendAnnotation public void usePackage(ParamsPackage paramsPackage) { log.debug("using package " + paramsPackage + " in tree " + this); paramsPackage.register(registry); } @AutoAppendAnnotation public void takeFromRegistry(Registry registry) { log.debug("taking from registry " + registry + " in tree " + this); this.registry.takeAllFrom(registry); } @Override public void putInfoIntoCache(FramsClass framclass) { registry.putFramsClass(framclass); } /** * @return the handler */ @Override public ExceptionResultHandler getExceptionHandler() { return handler; } /** * @param handler the handler to set */ @Override public void setExceptionHandler(ExceptionResultHandler handler) { this.handler = handler; } @Override public void handle(FramsticksException exception) { handler.handle(exception); } /** * @return the dispatcher */ @Override public JoinableDispatcher getDispatcher() { return dispatcher; } /** * @param dispatcher the dispatcher to set */ @Override public void setDispatcher(JoinableDispatcher dispatcher) { if (this.dispatcher != null) { throw new FramsticksException().msg("dispatcher is already set").arg("tree", this).arg("dispatcher", dispatcher); } this.dispatcher = dispatcher; } /** * @return the name */ @ParamAnnotation public String getName() { return name; } /** * @param name the name to set */ @ParamAnnotation public void setName(String name) { this.name = name; } @Override protected void joinableStart() { if (dispatcher == null) { dispatcher = new Thread(); } Dispatching.use(dispatcher, this); } @Override protected void joinableInterrupt() { Dispatching.drop(dispatcher, this); } @Override protected void joinableFinish() { } @Override protected void joinableJoin() throws InterruptedException { Dispatching.join(dispatcher); } @Override public void childChangedState(Joinable joinable, JoinableState state) { if (joinable == dispatcher) { proceedToState(state); } } @Override public boolean isActive() { if (dispatcher == null) { throw new FramsticksException().msg("no dispatcher is set for tree yet").arg("tree", this); } return dispatcher.isActive(); } @Override public void dispatch(RunAt runnable) { if (dispatcher == null) { throw new FramsticksException().msg("no dispatcher is set for tree yet").arg("tree", this); } dispatcher.dispatch(runnable); } }