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.util.ErrorMessages.requireNonNullParam; 008 009import edu.wpi.first.util.sendable.SendableBuilder; 010import java.util.Set; 011import java.util.function.Supplier; 012 013/** 014 * Defers Command construction to runtime. Runs the command returned by the supplier when this 015 * command is initialized, and ends when it ends. Useful for performing runtime tasks before 016 * creating a new command. If this command is interrupted, it will cancel the command. 017 * 018 * <p>Note that the supplier <i>must</i> create a new Command each call. For selecting one of a 019 * preallocated set of commands, use {@link SelectCommand}. 020 * 021 * <p>This class is provided by the NewCommands VendorDep 022 */ 023public class DeferredCommand extends Command { 024 private final Command m_nullCommand = 025 new PrintCommand("[DeferredCommand] Supplied command was null!"); 026 027 private final Supplier<Command> m_supplier; 028 private Command m_command = m_nullCommand; 029 030 /** 031 * Creates a new DeferredCommand that runs the supplied command when initialized, and ends when it 032 * ends. Useful for lazily creating commands at runtime. The {@link Supplier} will be called each 033 * time this command is initialized. The Supplier <i>must</i> create a new Command each call. 034 * 035 * @param supplier The command supplier 036 * @param requirements The command requirements. This is a {@link Set} to prevent accidental 037 * omission of command requirements. Use {@link Set#of()} to easily construct a requirement 038 * set. 039 */ 040 @SuppressWarnings("this-escape") 041 public DeferredCommand(Supplier<Command> supplier, Set<Subsystem> requirements) { 042 m_supplier = requireNonNullParam(supplier, "supplier", "DeferredCommand"); 043 addRequirements(requirements.toArray(new Subsystem[0])); 044 } 045 046 @Override 047 public void initialize() { 048 var cmd = m_supplier.get(); 049 if (cmd != null) { 050 m_command = cmd; 051 CommandScheduler.getInstance().registerComposedCommands(m_command); 052 } 053 m_command.initialize(); 054 } 055 056 @Override 057 public void execute() { 058 m_command.execute(); 059 } 060 061 @Override 062 public boolean isFinished() { 063 return m_command.isFinished(); 064 } 065 066 @Override 067 public void end(boolean interrupted) { 068 m_command.end(interrupted); 069 m_command = m_nullCommand; 070 } 071 072 @Override 073 @SuppressWarnings("PMD.CompareObjectsWithEquals") 074 public void initSendable(SendableBuilder builder) { 075 super.initSendable(builder); 076 builder.addStringProperty( 077 "deferred", () -> m_command == m_nullCommand ? "null" : m_command.getName(), null); 078 } 079}