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.wpilibj.smartdashboard;
006
007import edu.wpi.first.networktables.NetworkTable;
008import java.util.HashMap;
009import java.util.Map;
010
011/**
012 * Common base class for all Mechanism2d node types.
013 *
014 * <p>To append another node, call {@link #append(MechanismObject2d)}. Objects that aren't appended
015 * to a published {@link Mechanism2d} container are nonfunctional.
016 *
017 * @see Mechanism2d
018 */
019public abstract class MechanismObject2d implements AutoCloseable {
020  /** Relative to parent. */
021  private final String m_name;
022
023  private NetworkTable m_table;
024  private final Map<String, MechanismObject2d> m_objects = new HashMap<>(1);
025
026  /**
027   * Create a new Mechanism node object.
028   *
029   * @param name the node's name, must be unique.
030   */
031  protected MechanismObject2d(String name) {
032    m_name = name;
033  }
034
035  @Override
036  public void close() {
037    for (MechanismObject2d obj : m_objects.values()) {
038      obj.close();
039    }
040  }
041
042  /**
043   * Append a Mechanism object that is based on this one.
044   *
045   * @param <T> The object type.
046   * @param object the object to add.
047   * @return the object given as a parameter, useful for variable assignments and call chaining.
048   * @throws UnsupportedOperationException if the object's name is already used - object names must
049   *     be unique.
050   */
051  public final synchronized <T extends MechanismObject2d> T append(T object) {
052    if (m_objects.containsKey(object.getName())) {
053      throw new UnsupportedOperationException("Mechanism object names must be unique!");
054    }
055    m_objects.put(object.getName(), object);
056    if (m_table != null) {
057      object.update(m_table.getSubTable(object.getName()));
058    }
059    return object;
060  }
061
062  final synchronized void update(NetworkTable table) {
063    m_table = table;
064    updateEntries(m_table);
065    for (MechanismObject2d obj : m_objects.values()) {
066      obj.update(m_table.getSubTable(obj.m_name));
067    }
068  }
069
070  /**
071   * Update this object's entries with new ones from a new table.
072   *
073   * @param table the new table.
074   */
075  protected abstract void updateEntries(NetworkTable table);
076
077  /**
078   * Retrieve the object's name.
079   *
080   * @return the object's name relative to its parent.
081   */
082  public final String getName() {
083    return m_name;
084  }
085}