001// Copyright (c) FIRST and other WPILib contributors. 002// Open Source Software; you can modify and/or share it under the terms of 003// the WPILib BSD license file in the root directory of this project. 004 005package edu.wpi.first.wpilibj2.command; 006 007import static edu.wpi.first.wpilibj.util.ErrorMessages.requireNonNullParam; 008import static edu.wpi.first.wpilibj2.command.CommandGroupBase.requireUngrouped; 009 010import java.util.Map; 011import java.util.function.Supplier; 012 013/** 014 * Runs one of a selection of commands, either using a selector and a key to command mapping, or a 015 * supplier that returns the command directly at runtime. Does not actually schedule the selected 016 * command - rather, the command is run through this command; this ensures that the command will 017 * behave as expected if used as part of a CommandGroup. Requires the requirements of all included 018 * commands, again to ensure proper functioning when used in a CommandGroup. If this is undesired, 019 * consider using {@link ScheduleCommand}. 020 * 021 * <p>As this command contains multiple component commands within it, it is technically a command 022 * group; the command instances that are passed to it cannot be added to any other groups, or 023 * scheduled individually. 024 * 025 * <p>As a rule, CommandGroups require the union of the requirements of their component commands. 026 */ 027public class SelectCommand extends CommandBase { 028 private final Map<Object, Command> m_commands; 029 private final Supplier<Object> m_selector; 030 private final Supplier<Command> m_toRun; 031 private Command m_selectedCommand; 032 033 /** 034 * Creates a new selectcommand. 035 * 036 * @param commands the map of commands to choose from 037 * @param selector the selector to determine which command to run 038 */ 039 public SelectCommand(Map<Object, Command> commands, Supplier<Object> selector) { 040 requireUngrouped(commands.values()); 041 042 CommandGroupBase.registerGroupedCommands(commands.values().toArray(new Command[] {})); 043 044 m_commands = requireNonNullParam(commands, "commands", "SelectCommand"); 045 m_selector = requireNonNullParam(selector, "selector", "SelectCommand"); 046 047 m_toRun = null; 048 049 for (Command command : m_commands.values()) { 050 m_requirements.addAll(command.getRequirements()); 051 } 052 } 053 054 /** 055 * Creates a new selectcommand. 056 * 057 * @param toRun a supplier providing the command to run 058 */ 059 public SelectCommand(Supplier<Command> toRun) { 060 m_commands = null; 061 m_selector = null; 062 m_toRun = requireNonNullParam(toRun, "toRun", "SelectCommand"); 063 } 064 065 @Override 066 public void initialize() { 067 if (m_selector != null) { 068 if (!m_commands.keySet().contains(m_selector.get())) { 069 m_selectedCommand = 070 new PrintCommand( 071 "SelectCommand selector value does not correspond to" + " any command!"); 072 return; 073 } 074 m_selectedCommand = m_commands.get(m_selector.get()); 075 } else { 076 m_selectedCommand = m_toRun.get(); 077 } 078 m_selectedCommand.initialize(); 079 } 080 081 @Override 082 public void execute() { 083 m_selectedCommand.execute(); 084 } 085 086 @Override 087 public void end(boolean interrupted) { 088 m_selectedCommand.end(interrupted); 089 } 090 091 @Override 092 public boolean isFinished() { 093 return m_selectedCommand.isFinished(); 094 } 095 096 @Override 097 public boolean runsWhenDisabled() { 098 if (m_commands != null) { 099 boolean runsWhenDisabled = true; 100 for (Command command : m_commands.values()) { 101 runsWhenDisabled &= command.runsWhenDisabled(); 102 } 103 return runsWhenDisabled; 104 } else { 105 return m_toRun.get().runsWhenDisabled(); 106 } 107 } 108}