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 {
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  /**
036   * Append a Mechanism object that is based on this one.
037   *
038   * @param <T> The object type.
039   * @param object the object to add.
040   * @return the object given as a parameter, useful for variable assignments and call chaining.
041   * @throws UnsupportedOperationException if the object's name is already used - object names must
042   *     be unique.
043   */
044  public final synchronized <T extends MechanismObject2d> T append(T object) {
045    if (m_objects.containsKey(object.getName())) {
046      throw new UnsupportedOperationException("Mechanism object names must be unique!");
047    }
048    m_objects.put(object.getName(), object);
049    if (m_table != null) {
050      object.update(m_table.getSubTable(object.getName()));
051    }
052    return object;
053  }
054
055  final synchronized void update(NetworkTable table) {
056    m_table = table;
057    updateEntries(m_table);
058    for (MechanismObject2d obj : m_objects.values()) {
059      obj.update(m_table.getSubTable(obj.m_name));
060    }
061  }
062
063  /**
064   * Update all entries with new ones from a new table.
065   *
066   * @param table the new table.
067   */
068  protected abstract void updateEntries(NetworkTable table);
069
070  public final String getName() {
071    return m_name;
072  }
073}