package com.yoursway.ide.application.controllers; import static com.google.common.collect.Lists.newArrayList; import static com.google.common.collect.Maps.newHashMap; import static com.yoursway.utils.DebugOutputHelper.simpleNameOf; import static com.yoursway.utils.YsStrings.nullToEmpty; import static com.yoursway.utils.bugs.Severity.USER_COMMAND_IGNORED; import java.util.Collection; import java.util.Map; import com.yoursway.ide.application.view.impl.commands.Command; import com.yoursway.ide.application.view.impl.commands.Handler; import com.yoursway.utils.bugs.Bugs; import com.yoursway.utils.disposable.Disposable; import com.yoursway.utils.disposable.Disposer; public class Context implements Disposable, PublicContext { private final Context parent; private boolean active; private Collection<Context> activeChildren = newArrayList(); private Map<Command, Handler> handlers = newHashMap(); public Context(Disposer disposer) { this.parent = null; this.active = true; disposer.addDisposeListener(this); } public Context(Disposer disposer, Context parent) { if (parent == null) throw new NullPointerException("parent is null"); this.parent = parent; disposer.addDisposeListener(this); } public void addHandler(Command command, Handler handler) { if (command == null) throw new NullPointerException("command is null"); if (handler == null) throw new NullPointerException("handler is null"); handlers.put(command, handler); } public void setActive(boolean active) { if (parent == null) throw new IllegalStateException("Cannot activate/deactivate the root context"); if (active != this.active) { this.active = active; if (active) parent.addActiveChild(this); else parent.removeActiveChild(this); } } void addActiveChild(Context context) { if (context == null) throw new NullPointerException("context is null"); activeChildren.add(context); } void removeActiveChild(Context context) { if (context == null) throw new NullPointerException("context is null"); activeChildren.remove(context); } public void dispose() { if (parent != null) setActive(false); } public void execute(Command command) { if (!tryExecute(command)) Bugs.illegalCaseRecovery(USER_COMMAND_IGNORED, "No handler found for " + simpleNameOf(command) + " " + command.toString()); } private boolean tryExecute(Command command) { if (tryExecuteWithChildren(command)) return true; else if (parent != null) return parent.tryExecuteWithParents(command); else return false; } private boolean tryExecuteWithParents(Command command) { if (tryExecuteHere(command)) return true; else if (parent != null) return parent.tryExecuteWithParents(command); else return false; } private boolean tryExecuteWithChildren(Command command) { for (Context child : activeChildren) if (child.tryExecute(command)) return true; return tryExecuteHere(command); } private boolean tryExecuteHere(Command command) { Handler handler = handlers.get(command); if (handler == null) return false; else return handler.run(command); } }