package com.framsticks.core; import java.util.HashSet; import java.util.Set; 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.Param; 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.util.dispatching.Dispatching; 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 Thread implements Tree { private static final Logger log = Logger.getLogger(Tree.class); private Node root; @Override public void setRoot(Node node) { root = node; } @Override public @Nonnull Node getRoot() { assert root != null; return root; } public boolean isRootAssigned() { // assert isActive(); return root != null; } protected Set listeners = new HashSet(); public AbstractTree() { setName("entity"); } protected void tryRegisterOnChangeEvents(Path path) { } protected void fireRun(Exception e) { for (TreeListener l : this.listeners) { l.onRun(e); } } protected void fireStop(Exception e) { for (TreeListener l : this.listeners) { l.onStop(e); } } @Override public void addListener(final TreeListener listener) { assert Dispatching.isThreadSafe(); Dispatching.dispatchIfNotActive(this, new RunAt(ThrowExceptionHandler.getInstance()) { @Override protected void runAt() { listeners.add(listener); } }); } @Override public void removeListener(final TreeListener listener) { assert Dispatching.isThreadSafe(); Dispatching.dispatchIfNotActive(this, new RunAt(ThrowExceptionHandler.getInstance()) { @Override protected void runAt() { listeners.remove(listener); } }); } protected void fireListChange(Path path, ListChange change) { assert isActive(); for (TreeListener l : this.listeners) { l.onListChange(path, change); } } @Override public void notifyOfFetch(Path path) { fireFetch(path); } protected void fireFetch(Path path) { assert isActive(); for (TreeListener l : this.listeners) { l.onFetch(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 protected void joinableStart() { dispatch(new RunAt(ThrowExceptionHandler.getInstance()) { @Override protected void runAt() { if (!isRootAssigned()) { setRoot(new Node(Param.build().name("Tree").id(getName()).type("o").finish(CompositeParam.class), null)); } } }); super.joinableStart(); } @Override public void putInfoIntoCache(FramsClass framclass) { registry.putFramsClass(framclass); } }