/* * Copyright 2016 Cel Skeggs * * This file is part of the CCRE, the Common Chicken Runtime Engine. * * The CCRE is free software: you can redistribute it and/or modify it under the * terms of the GNU Lesser General Public License as published by the Free * Software Foundation, either version 3 of the License, or (at your option) any * later version. * * The CCRE is distributed in the hope that it will be useful, but WITHOUT ANY * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR * A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more * details. * * You should have received a copy of the GNU Lesser General Public License * along with the CCRE. If not, see <http://www.gnu.org/licenses/>. */ package ccre.behaviors; import java.util.HashMap; import ccre.channel.CancelOutput; import ccre.channel.EventOutput; import ccre.verifier.FlowPhase; import ccre.channel.EventCell; import ccre.channel.EventInput; /** * An event channel that can be overridden for specific behaviors of a behavior * arbitrator. * * @see #attach(Behavior, EventInput) * @author skeggsc */ public final class ArbitratedEvent implements EventInput { private final BehaviorArbitrator behaviorChain; private final EventInput general; private final HashMap<Behavior, EventInput> activation = new HashMap<>(); private CancelOutput cancellator; private final EventCell cell = new EventCell(); ArbitratedEvent(BehaviorArbitrator behaviorChain, EventInput base) { this.behaviorChain = behaviorChain; this.general = base; cancellator = CancelOutput.nothing; this.update(); behaviorChain.onActiveUpdate.send(this::update); } @FlowPhase synchronized void update() { cancellator.cancel(); EventInput input = activation.get(this.behaviorChain.active); if (input == null) { input = general; } cancellator = input.send(cell); } /** * Attaches <code>input</code> such that it will be used instead of the * default source when the behavior arbitrator has <code>behavior</code> * active. * * This will be overridden by a higher-priority behavior, even if that * behavior does not override this event channel. * * @param behavior the behavior to attach to * @param input the input to use to override the default */ public void attach(Behavior behavior, EventInput input) { if (behavior == null || input == null) { throw new NullPointerException(); } if (behavior.parent != behaviorChain) { throw new IllegalArgumentException("Attached behavior for different BehaviorChain!"); } if (activation.containsKey(behavior)) { throw new IllegalArgumentException("Behavior already added: " + behavior); } activation.put(behavior, input); update(); } @Override public CancelOutput onUpdate(EventOutput notify) { return cell.onUpdate(notify); } }