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;
006
007import static edu.wpi.first.wpilibj.util.ErrorMessages.requireNonNullParam;
008
009import edu.wpi.first.hal.FRCNetComm.tResourceType;
010import edu.wpi.first.hal.HAL;
011import edu.wpi.first.networktables.EntryListenerFlags;
012import edu.wpi.first.networktables.NetworkTable;
013import edu.wpi.first.networktables.NetworkTableEntry;
014import edu.wpi.first.networktables.NetworkTableInstance;
015import java.util.Collection;
016
017/**
018 * The preferences class provides a relatively simple way to save important values to the roboRIO to
019 * access the next time the roboRIO is booted.
020 *
021 * <p>This class loads and saves from a file inside the roboRIO. The user can not access the file
022 * directly, but may modify values at specific fields which will then be automatically saved to the
023 * file by the NetworkTables server.
024 *
025 * <p>This class is thread safe.
026 *
027 * <p>This will also interact with {@link NetworkTable} by creating a table called "Preferences"
028 * with all the key-value pairs.
029 */
030public final class Preferences {
031  /** The Preferences table name. */
032  private static final String TABLE_NAME = "Preferences";
033  /** The singleton instance. */
034  private static Preferences instance;
035  /** The network table. */
036  private static final NetworkTable m_table;
037
038  /**
039   * Returns the preferences instance.
040   *
041   * @return the preferences instance
042   * @deprecated Use the static methods
043   */
044  @Deprecated
045  public static synchronized Preferences getInstance() {
046    if (instance == null) {
047      instance = new Preferences();
048    }
049    return instance;
050  }
051
052  /** Creates a preference class. */
053  private Preferences() {}
054
055  static {
056    m_table = NetworkTableInstance.getDefault().getTable(TABLE_NAME);
057    m_table.getEntry(".type").setString("RobotPreferences");
058    // Listener to set all Preferences values to persistent
059    // (for backwards compatibility with old dashboards).
060    m_table.addEntryListener(
061        (table, key, entry, value, flags) -> entry.setPersistent(),
062        EntryListenerFlags.kImmediate | EntryListenerFlags.kNew);
063    HAL.report(tResourceType.kResourceType_Preferences, 0);
064  }
065
066  /**
067   * Gets the preferences keys.
068   *
069   * @return a collection of the keys
070   */
071  public static Collection<String> getKeys() {
072    return m_table.getKeys();
073  }
074
075  /**
076   * Puts the given string into the preferences table.
077   *
078   * @param key the key
079   * @param value the value
080   * @throws NullPointerException if value is null
081   */
082  public static void setString(String key, String value) {
083    requireNonNullParam(value, "value", "setString");
084
085    NetworkTableEntry entry = m_table.getEntry(key);
086    entry.setString(value);
087    entry.setPersistent();
088  }
089
090  /**
091   * Puts the given string into the preferences table.
092   *
093   * @param key the key
094   * @param value the value
095   * @throws NullPointerException if value is null
096   * @deprecated Use {@link #setString(String, String)}
097   */
098  @Deprecated
099  public static void putString(String key, String value) {
100    setString(key, value);
101  }
102
103  /**
104   * Puts the given string into the preferences table if it doesn't already exist.
105   *
106   * @param key The key
107   * @param value The value
108   */
109  public static void initString(String key, String value) {
110    NetworkTableEntry entry = m_table.getEntry(key);
111    entry.setDefaultString(value);
112  }
113
114  /**
115   * Puts the given int into the preferences table.
116   *
117   * @param key the key
118   * @param value the value
119   */
120  public static void setInt(String key, int value) {
121    NetworkTableEntry entry = m_table.getEntry(key);
122    entry.setDouble(value);
123    entry.setPersistent();
124  }
125
126  /**
127   * Puts the given int into the preferences table.
128   *
129   * @param key the key
130   * @param value the value
131   * @deprecated Use {@link #setInt(String, int)}
132   */
133  @Deprecated
134  public static void putInt(String key, int value) {
135    setInt(key, value);
136  }
137
138  /**
139   * Puts the given int into the preferences table if it doesn't already exist.
140   *
141   * @param key The key
142   * @param value The value
143   */
144  public static void initInt(String key, int value) {
145    NetworkTableEntry entry = m_table.getEntry(key);
146    entry.setDefaultDouble(value);
147  }
148
149  /**
150   * Puts the given double into the preferences table.
151   *
152   * @param key the key
153   * @param value the value
154   */
155  public static void setDouble(String key, double value) {
156    NetworkTableEntry entry = m_table.getEntry(key);
157    entry.setDouble(value);
158    entry.setPersistent();
159  }
160
161  /**
162   * Puts the given double into the preferences table.
163   *
164   * @param key the key
165   * @param value the value
166   * @deprecated Use {@link #setDouble(String, double)}
167   */
168  @Deprecated
169  public static void putDouble(String key, double value) {
170    setDouble(key, value);
171  }
172
173  /**
174   * Puts the given double into the preferences table if it doesn't already exist.
175   *
176   * @param key The key
177   * @param value The value
178   */
179  public static void initDouble(String key, double value) {
180    NetworkTableEntry entry = m_table.getEntry(key);
181    entry.setDefaultDouble(value);
182  }
183
184  /**
185   * Puts the given float into the preferences table.
186   *
187   * @param key the key
188   * @param value the value
189   */
190  public static void setFloat(String key, float value) {
191    NetworkTableEntry entry = m_table.getEntry(key);
192    entry.setDouble(value);
193    entry.setPersistent();
194  }
195
196  /**
197   * Puts the given float into the preferences table.
198   *
199   * @param key the key
200   * @param value the value
201   * @deprecated Use {@link #setFloat(String, float)}
202   */
203  @Deprecated
204  public static void putFloat(String key, float value) {
205    setFloat(key, value);
206  }
207
208  /**
209   * Puts the given float into the preferences table if it doesn't already exist.
210   *
211   * @param key The key
212   * @param value The value
213   */
214  public static void initFloat(String key, float value) {
215    NetworkTableEntry entry = m_table.getEntry(key);
216    entry.setDefaultDouble(value);
217  }
218
219  /**
220   * Puts the given boolean into the preferences table.
221   *
222   * @param key the key
223   * @param value the value
224   */
225  public static void setBoolean(String key, boolean value) {
226    NetworkTableEntry entry = m_table.getEntry(key);
227    entry.setBoolean(value);
228    entry.setPersistent();
229  }
230
231  /**
232   * Puts the given boolean into the preferences table.
233   *
234   * @param key the key
235   * @param value the value
236   * @deprecated Use {@link #setBoolean(String, boolean)}
237   */
238  @Deprecated
239  public static void putBoolean(String key, boolean value) {
240    setBoolean(key, value);
241  }
242
243  /**
244   * Puts the given boolean into the preferences table if it doesn't already exist.
245   *
246   * @param key The key
247   * @param value The value
248   */
249  public static void initBoolean(String key, boolean value) {
250    NetworkTableEntry entry = m_table.getEntry(key);
251    entry.setDefaultBoolean(value);
252  }
253
254  /**
255   * Puts the given long into the preferences table.
256   *
257   * @param key the key
258   * @param value the value
259   */
260  public static void setLong(String key, long value) {
261    NetworkTableEntry entry = m_table.getEntry(key);
262    entry.setDouble(value);
263    entry.setPersistent();
264  }
265
266  /**
267   * Puts the given long into the preferences table.
268   *
269   * @param key the key
270   * @param value the value
271   * @deprecated Use {@link #setLong(String, long)}
272   */
273  @Deprecated
274  public static void putLong(String key, long value) {
275    setLong(key, value);
276  }
277
278  /**
279   * Puts the given long into the preferences table if it doesn't already exist.
280   *
281   * @param key The key
282   * @param value The value
283   */
284  public static void initLong(String key, long value) {
285    NetworkTableEntry entry = m_table.getEntry(key);
286    entry.setDefaultDouble(value);
287  }
288
289  /**
290   * Returns whether or not there is a key with the given name.
291   *
292   * @param key the key
293   * @return if there is a value at the given key
294   */
295  public static boolean containsKey(String key) {
296    return m_table.containsKey(key);
297  }
298
299  /**
300   * Remove a preference.
301   *
302   * @param key the key
303   */
304  public static void remove(String key) {
305    m_table.delete(key);
306  }
307
308  /** Remove all preferences. */
309  public static void removeAll() {
310    for (String key : m_table.getKeys()) {
311      if (!".type".equals(key)) {
312        remove(key);
313      }
314    }
315  }
316
317  /**
318   * Returns the string at the given key. If this table does not have a value for that position,
319   * then the given backup value will be returned.
320   *
321   * @param key the key
322   * @param backup the value to return if none exists in the table
323   * @return either the value in the table, or the backup
324   */
325  public static String getString(String key, String backup) {
326    return m_table.getEntry(key).getString(backup);
327  }
328
329  /**
330   * Returns the int at the given key. If this table does not have a value for that position, then
331   * the given backup value will be returned.
332   *
333   * @param key the key
334   * @param backup the value to return if none exists in the table
335   * @return either the value in the table, or the backup
336   */
337  public static int getInt(String key, int backup) {
338    return (int) m_table.getEntry(key).getDouble(backup);
339  }
340
341  /**
342   * Returns the double at the given key. If this table does not have a value for that position,
343   * then the given backup value will be returned.
344   *
345   * @param key the key
346   * @param backup the value to return if none exists in the table
347   * @return either the value in the table, or the backup
348   */
349  public static double getDouble(String key, double backup) {
350    return m_table.getEntry(key).getDouble(backup);
351  }
352
353  /**
354   * Returns the boolean at the given key. If this table does not have a value for that position,
355   * then the given backup value will be returned.
356   *
357   * @param key the key
358   * @param backup the value to return if none exists in the table
359   * @return either the value in the table, or the backup
360   */
361  public static boolean getBoolean(String key, boolean backup) {
362    return m_table.getEntry(key).getBoolean(backup);
363  }
364
365  /**
366   * Returns the float at the given key. If this table does not have a value for that position, then
367   * the given backup value will be returned.
368   *
369   * @param key the key
370   * @param backup the value to return if none exists in the table
371   * @return either the value in the table, or the backup
372   */
373  public static float getFloat(String key, float backup) {
374    return (float) m_table.getEntry(key).getDouble(backup);
375  }
376
377  /**
378   * Returns the long at the given key. If this table does not have a value for that position, then
379   * the given backup value will be returned.
380   *
381   * @param key the key
382   * @param backup the value to return if none exists in the table
383   * @return either the value in the table, or the backup
384   */
385  public static long getLong(String key, long backup) {
386    return (long) m_table.getEntry(key).getDouble(backup);
387  }
388}