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.Sendable;
010import edu.wpi.first.util.sendable.SendableBuilder;
011import edu.wpi.first.util.sendable.SendableRegistry;
012import java.util.HashSet;
013import java.util.Set;
014
015/**
016 * A {@link Sendable} base class for {@link Command}s.
017 *
018 * <p>This class is provided by the NewCommands VendorDep
019 */
020public abstract class CommandBase implements Sendable, Command {
021  protected Set<Subsystem> m_requirements = new HashSet<>();
022
023  protected CommandBase() {
024    String name = getClass().getName();
025    SendableRegistry.add(this, name.substring(name.lastIndexOf('.') + 1));
026  }
027
028  /**
029   * Adds the specified requirements to the command.
030   *
031   * @param requirements the requirements to add
032   */
033  public final void addRequirements(Subsystem... requirements) {
034    for (Subsystem requirement : requirements) {
035      m_requirements.add(requireNonNullParam(requirement, "requirement", "addRequirements"));
036    }
037  }
038
039  @Override
040  public Set<Subsystem> getRequirements() {
041    return m_requirements;
042  }
043
044  @Override
045  public String getName() {
046    return SendableRegistry.getName(this);
047  }
048
049  /**
050   * Sets the name of this Command.
051   *
052   * @param name name
053   */
054  @Override
055  public void setName(String name) {
056    SendableRegistry.setName(this, name);
057  }
058
059  /**
060   * Gets the subsystem name of this Command.
061   *
062   * @return Subsystem name
063   */
064  public String getSubsystem() {
065    return SendableRegistry.getSubsystem(this);
066  }
067
068  /**
069   * Sets the subsystem name of this Command.
070   *
071   * @param subsystem subsystem name
072   */
073  public void setSubsystem(String subsystem) {
074    SendableRegistry.setSubsystem(this, subsystem);
075  }
076
077  /**
078   * Initializes this sendable. Useful for allowing implementations to easily extend SendableBase.
079   *
080   * @param builder the builder used to construct this sendable
081   */
082  @Override
083  public void initSendable(SendableBuilder builder) {
084    builder.setSmartDashboardType("Command");
085    builder.addStringProperty(".name", this::getName, null);
086    builder.addBooleanProperty(
087        "running",
088        this::isScheduled,
089        value -> {
090          if (value) {
091            if (!isScheduled()) {
092              schedule();
093            }
094          } else {
095            if (isScheduled()) {
096              cancel();
097            }
098          }
099        });
100    builder.addBooleanProperty(
101        ".isParented", () -> CommandScheduler.getInstance().isComposed(this), null);
102    builder.addStringProperty(
103        "interruptBehavior", () -> getInterruptionBehavior().toString(), null);
104    builder.addBooleanProperty("runsWhenDisabled", this::runsWhenDisabled, null);
105  }
106}