001/*----------------------------------------------------------------------------*/
002/* Copyright (c) 2008-2018 FIRST. All Rights Reserved.                        */
003/* Open Source Software - may be modified and shared by FRC teams. The code   */
004/* must be accompanied by the FIRST BSD license file in the root directory of */
005/* the project.                                                               */
006/*----------------------------------------------------------------------------*/
007
008package edu.wpi.first.wpilibj;
009
010import java.util.Vector;
011
012import edu.wpi.first.networktables.EntryListenerFlags;
013import edu.wpi.first.networktables.NetworkTable;
014import edu.wpi.first.networktables.NetworkTableEntry;
015import edu.wpi.first.networktables.NetworkTableInstance;
016import edu.wpi.first.wpilibj.hal.FRCNetComm.tResourceType;
017import edu.wpi.first.wpilibj.hal.HAL;
018
019import static java.util.Objects.requireNonNull;
020
021/**
022 * The preferences class provides a relatively simple way to save important values to the roboRIO to
023 * access the next time the roboRIO is booted.
024 *
025 * <p> This class loads and saves from a file inside the roboRIO. The user can not access the file
026 * directly, but may modify values at specific fields which will then be automatically saved to the
027 * file by the NetworkTables server. </p>
028 *
029 * <p> This class is thread safe. </p>
030 *
031 * <p> This will also interact with {@link NetworkTable} by creating a table called "Preferences"
032 * with all the key-value pairs. </p>
033 */
034public class Preferences {
035  /**
036   * The Preferences table name.
037   */
038  private static final String TABLE_NAME = "Preferences";
039  /**
040   * The singleton instance.
041   */
042  private static Preferences instance;
043  /**
044   * The network table.
045   */
046  private final NetworkTable m_table;
047
048  /**
049   * Returns the preferences instance.
050   *
051   * @return the preferences instance
052   */
053  public static synchronized Preferences getInstance() {
054    if (instance == null) {
055      instance = new Preferences();
056    }
057    return instance;
058  }
059
060  /**
061   * Creates a preference class.
062   */
063  private Preferences() {
064    m_table = NetworkTableInstance.getDefault().getTable(TABLE_NAME);
065    m_table.getEntry(".type").setString("RobotPreferences");
066    // Listener to set all Preferences values to persistent
067    // (for backwards compatibility with old dashboards).
068    m_table.addEntryListener(
069        (table, key, entry, value, flags) -> entry.setPersistent(),
070        EntryListenerFlags.kImmediate | EntryListenerFlags.kNew);
071    HAL.report(tResourceType.kResourceType_Preferences, 0);
072  }
073
074  /**
075   * Gets the vector of keys.
076   * @return a vector of the keys
077   */
078  public Vector<String> getKeys() {
079    return new Vector<>(m_table.getKeys());
080  }
081
082  /**
083   * Puts the given string into the preferences table.
084   *
085   * @param key   the key
086   * @param value the value
087   * @throws NullPointerException if value is null
088   */
089  public void putString(String key, String value) {
090    requireNonNull(value, "Provided value was null");
091
092    NetworkTableEntry entry = m_table.getEntry(key);
093    entry.setString(value);
094    entry.setPersistent();
095  }
096
097  /**
098   * Puts the given int into the preferences table.
099   *
100   * @param key   the key
101   * @param value the value
102   */
103  public void putInt(String key, int value) {
104    NetworkTableEntry entry = m_table.getEntry(key);
105    entry.setDouble(value);
106    entry.setPersistent();
107  }
108
109  /**
110   * Puts the given double into the preferences table.
111   *
112   * @param key   the key
113   * @param value the value
114   */
115  public void putDouble(String key, double value) {
116    NetworkTableEntry entry = m_table.getEntry(key);
117    entry.setDouble(value);
118    entry.setPersistent();
119  }
120
121  /**
122   * Puts the given float into the preferences table.
123   *
124   * @param key   the key
125   * @param value the value
126   */
127  public void putFloat(String key, float value) {
128    NetworkTableEntry entry = m_table.getEntry(key);
129    entry.setDouble(value);
130    entry.setPersistent();
131  }
132
133  /**
134   * Puts the given boolean into the preferences table.
135   *
136   * @param key   the key
137   * @param value the value
138   */
139  public void putBoolean(String key, boolean value) {
140    NetworkTableEntry entry = m_table.getEntry(key);
141    entry.setBoolean(value);
142    entry.setPersistent();
143  }
144
145  /**
146   * Puts the given long into the preferences table.
147   *
148   * @param key   the key
149   * @param value the value
150   */
151  public void putLong(String key, long value) {
152    NetworkTableEntry entry = m_table.getEntry(key);
153    entry.setDouble(value);
154    entry.setPersistent();
155  }
156
157  /**
158   * Returns whether or not there is a key with the given name.
159   *
160   * @param key the key
161   * @return if there is a value at the given key
162   */
163  public boolean containsKey(String key) {
164    return m_table.containsKey(key);
165  }
166
167  /**
168   * Remove a preference.
169   *
170   * @param key the key
171   */
172  public void remove(String key) {
173    m_table.delete(key);
174  }
175
176  /**
177   * Returns the string at the given key. If this table does not have a value for that position,
178   * then the given backup value will be returned.
179   *
180   * @param key    the key
181   * @param backup the value to return if none exists in the table
182   * @return either the value in the table, or the backup
183   */
184  public String getString(String key, String backup) {
185    return m_table.getEntry(key).getString(backup);
186  }
187
188  /**
189   * Returns the int at the given key. If this table does not have a value for that position, then
190   * the given backup value will be returned.
191   *
192   * @param key    the key
193   * @param backup the value to return if none exists in the table
194   * @return either the value in the table, or the backup
195   */
196  public int getInt(String key, int backup) {
197    return (int) m_table.getEntry(key).getDouble(backup);
198  }
199
200  /**
201   * Returns the double at the given key. If this table does not have a value for that position,
202   * then the given backup value will be returned.
203   *
204   * @param key    the key
205   * @param backup the value to return if none exists in the table
206   * @return either the value in the table, or the backup
207   */
208  public double getDouble(String key, double backup) {
209    return m_table.getEntry(key).getDouble(backup);
210  }
211
212  /**
213   * Returns the boolean at the given key. If this table does not have a value for that position,
214   * then the given backup value will be returned.
215   *
216   * @param key    the key
217   * @param backup the value to return if none exists in the table
218   * @return either the value in the table, or the backup
219   */
220  public boolean getBoolean(String key, boolean backup) {
221    return m_table.getEntry(key).getBoolean(backup);
222  }
223
224  /**
225   * Returns the float at the given key. If this table does not have a value for that position, then
226   * the given backup value will be returned.
227   *
228   * @param key    the key
229   * @param backup the value to return if none exists in the table
230   * @return either the value in the table, or the backup
231   */
232  public float getFloat(String key, float backup) {
233    return (float) m_table.getEntry(key).getDouble(backup);
234  }
235
236  /**
237   * Returns the long at the given key. If this table does not have a value for that position, then
238   * the given backup value will be returned.
239   *
240   * @param key    the key
241   * @param backup the value to return if none exists in the table
242   * @return either the value in the table, or the backup
243   */
244  public long getLong(String key, long backup) {
245    return (long) m_table.getEntry(key).getDouble(backup);
246  }
247}