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    entry.setPersistent();
113  }
114
115  /**
116   * Puts the given int into the preferences table.
117   *
118   * @param key the key
119   * @param value the value
120   */
121  public static void setInt(String key, int value) {
122    NetworkTableEntry entry = m_table.getEntry(key);
123    entry.setDouble(value);
124    entry.setPersistent();
125  }
126
127  /**
128   * Puts the given int into the preferences table.
129   *
130   * @param key the key
131   * @param value the value
132   * @deprecated Use {@link #setInt(String, int)}
133   */
134  @Deprecated
135  public static void putInt(String key, int value) {
136    setInt(key, value);
137  }
138
139  /**
140   * Puts the given int into the preferences table if it doesn't already exist.
141   *
142   * @param key The key
143   * @param value The value
144   */
145  public static void initInt(String key, int value) {
146    NetworkTableEntry entry = m_table.getEntry(key);
147    entry.setDefaultDouble(value);
148    entry.setPersistent();
149  }
150
151  /**
152   * Puts the given double into the preferences table.
153   *
154   * @param key the key
155   * @param value the value
156   */
157  public static void setDouble(String key, double value) {
158    NetworkTableEntry entry = m_table.getEntry(key);
159    entry.setDouble(value);
160    entry.setPersistent();
161  }
162
163  /**
164   * Puts the given double into the preferences table.
165   *
166   * @param key the key
167   * @param value the value
168   * @deprecated Use {@link #setDouble(String, double)}
169   */
170  @Deprecated
171  public static void putDouble(String key, double value) {
172    setDouble(key, value);
173  }
174
175  /**
176   * Puts the given double into the preferences table if it doesn't already exist.
177   *
178   * @param key The key
179   * @param value The value
180   */
181  public static void initDouble(String key, double value) {
182    NetworkTableEntry entry = m_table.getEntry(key);
183    entry.setDefaultDouble(value);
184    entry.setPersistent();
185  }
186
187  /**
188   * Puts the given float into the preferences table.
189   *
190   * @param key the key
191   * @param value the value
192   */
193  public static void setFloat(String key, float value) {
194    NetworkTableEntry entry = m_table.getEntry(key);
195    entry.setDouble(value);
196    entry.setPersistent();
197  }
198
199  /**
200   * Puts the given float into the preferences table.
201   *
202   * @param key the key
203   * @param value the value
204   * @deprecated Use {@link #setFloat(String, float)}
205   */
206  @Deprecated
207  public static void putFloat(String key, float value) {
208    setFloat(key, value);
209  }
210
211  /**
212   * Puts the given float into the preferences table if it doesn't already exist.
213   *
214   * @param key The key
215   * @param value The value
216   */
217  public static void initFloat(String key, float value) {
218    NetworkTableEntry entry = m_table.getEntry(key);
219    entry.setDefaultDouble(value);
220    entry.setPersistent();
221  }
222
223  /**
224   * Puts the given boolean into the preferences table.
225   *
226   * @param key the key
227   * @param value the value
228   */
229  public static void setBoolean(String key, boolean value) {
230    NetworkTableEntry entry = m_table.getEntry(key);
231    entry.setBoolean(value);
232    entry.setPersistent();
233  }
234
235  /**
236   * Puts the given boolean into the preferences table.
237   *
238   * @param key the key
239   * @param value the value
240   * @deprecated Use {@link #setBoolean(String, boolean)}
241   */
242  @Deprecated
243  public static void putBoolean(String key, boolean value) {
244    setBoolean(key, value);
245  }
246
247  /**
248   * Puts the given boolean into the preferences table if it doesn't already exist.
249   *
250   * @param key The key
251   * @param value The value
252   */
253  public static void initBoolean(String key, boolean value) {
254    NetworkTableEntry entry = m_table.getEntry(key);
255    entry.setDefaultBoolean(value);
256    entry.setPersistent();
257  }
258
259  /**
260   * Puts the given long into the preferences table.
261   *
262   * @param key the key
263   * @param value the value
264   */
265  public static void setLong(String key, long value) {
266    NetworkTableEntry entry = m_table.getEntry(key);
267    entry.setDouble(value);
268    entry.setPersistent();
269  }
270
271  /**
272   * Puts the given long into the preferences table.
273   *
274   * @param key the key
275   * @param value the value
276   * @deprecated Use {@link #setLong(String, long)}
277   */
278  @Deprecated
279  public static void putLong(String key, long value) {
280    setLong(key, value);
281  }
282
283  /**
284   * Puts the given long into the preferences table if it doesn't already exist.
285   *
286   * @param key The key
287   * @param value The value
288   */
289  public static void initLong(String key, long value) {
290    NetworkTableEntry entry = m_table.getEntry(key);
291    entry.setDefaultDouble(value);
292    entry.setPersistent();
293  }
294
295  /**
296   * Returns whether or not there is a key with the given name.
297   *
298   * @param key the key
299   * @return if there is a value at the given key
300   */
301  public static boolean containsKey(String key) {
302    return m_table.containsKey(key);
303  }
304
305  /**
306   * Remove a preference.
307   *
308   * @param key the key
309   */
310  public static void remove(String key) {
311    m_table.delete(key);
312  }
313
314  /** Remove all preferences. */
315  public static void removeAll() {
316    for (String key : m_table.getKeys()) {
317      if (!".type".equals(key)) {
318        remove(key);
319      }
320    }
321  }
322
323  /**
324   * Returns the string at the given key. If this table does not have a value for that position,
325   * then the given backup value will be returned.
326   *
327   * @param key the key
328   * @param backup the value to return if none exists in the table
329   * @return either the value in the table, or the backup
330   */
331  public static String getString(String key, String backup) {
332    return m_table.getEntry(key).getString(backup);
333  }
334
335  /**
336   * Returns the int at the given key. If this table does not have a value for that position, then
337   * the given backup value will be returned.
338   *
339   * @param key the key
340   * @param backup the value to return if none exists in the table
341   * @return either the value in the table, or the backup
342   */
343  public static int getInt(String key, int backup) {
344    return (int) m_table.getEntry(key).getDouble(backup);
345  }
346
347  /**
348   * Returns the double at the given key. If this table does not have a value for that position,
349   * then the given backup value will be returned.
350   *
351   * @param key the key
352   * @param backup the value to return if none exists in the table
353   * @return either the value in the table, or the backup
354   */
355  public static double getDouble(String key, double backup) {
356    return m_table.getEntry(key).getDouble(backup);
357  }
358
359  /**
360   * Returns the boolean at the given key. If this table does not have a value for that position,
361   * then the given backup value will be returned.
362   *
363   * @param key the key
364   * @param backup the value to return if none exists in the table
365   * @return either the value in the table, or the backup
366   */
367  public static boolean getBoolean(String key, boolean backup) {
368    return m_table.getEntry(key).getBoolean(backup);
369  }
370
371  /**
372   * Returns the float at the given key. If this table does not have a value for that position, then
373   * the given backup value will be returned.
374   *
375   * @param key the key
376   * @param backup the value to return if none exists in the table
377   * @return either the value in the table, or the backup
378   */
379  public static float getFloat(String key, float backup) {
380    return (float) m_table.getEntry(key).getDouble(backup);
381  }
382
383  /**
384   * Returns the long at the given key. If this table does not have a value for that position, then
385   * the given backup value will be returned.
386   *
387   * @param key the key
388   * @param backup the value to return if none exists in the table
389   * @return either the value in the table, or the backup
390   */
391  public static long getLong(String key, long backup) {
392    return (long) m_table.getEntry(key).getDouble(backup);
393  }
394}