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