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.networktables;
006
007import java.nio.ByteBuffer;
008import java.util.function.Consumer;
009
010/** NetworkTables Entry. */
011public final class NetworkTableEntry {
012  /** Flag values (as returned by {@link #getFlags()}). */
013  public static final int kPersistent = 0x01;
014
015  /**
016   * Construct from native handle.
017   *
018   * @param inst Instance
019   * @param handle Native handle
020   */
021  public NetworkTableEntry(NetworkTableInstance inst, int handle) {
022    m_inst = inst;
023    m_handle = handle;
024  }
025
026  /**
027   * Determines if the native handle is valid.
028   *
029   * @return True if the native handle is valid, false otherwise.
030   */
031  public boolean isValid() {
032    return m_handle != 0;
033  }
034
035  /**
036   * Gets the native handle for the entry.
037   *
038   * @return Native handle
039   */
040  public int getHandle() {
041    return m_handle;
042  }
043
044  /**
045   * Gets the instance for the entry.
046   *
047   * @return Instance
048   */
049  public NetworkTableInstance getInstance() {
050    return m_inst;
051  }
052
053  /**
054   * Determines if the entry currently exists.
055   *
056   * @return True if the entry exists, false otherwise.
057   */
058  public boolean exists() {
059    return NetworkTablesJNI.getType(m_handle) != 0;
060  }
061
062  /**
063   * Gets the name of the entry (the key).
064   *
065   * @return the entry's name
066   */
067  public String getName() {
068    return NetworkTablesJNI.getEntryName(m_handle);
069  }
070
071  /**
072   * Gets the type of the entry.
073   *
074   * @return the entry's type
075   */
076  public NetworkTableType getType() {
077    return NetworkTableType.getFromInt(NetworkTablesJNI.getType(m_handle));
078  }
079
080  /**
081   * Returns the flags.
082   *
083   * @return the flags (bitmask)
084   */
085  public int getFlags() {
086    return NetworkTablesJNI.getEntryFlags(m_handle);
087  }
088
089  /**
090   * Gets the last time the entry's value was changed.
091   *
092   * @return Entry last change time
093   */
094  public long getLastChange() {
095    return NetworkTablesJNI.getEntryLastChange(m_handle);
096  }
097
098  /**
099   * Gets combined information about the entry.
100   *
101   * @return Entry information
102   */
103  public EntryInfo getInfo() {
104    return NetworkTablesJNI.getEntryInfoHandle(m_inst, m_handle);
105  }
106
107  /**
108   * Gets the entry's value. Returns a value with type NetworkTableType.kUnassigned if the value
109   * does not exist.
110   *
111   * @return the entry's value
112   */
113  public NetworkTableValue getValue() {
114    return NetworkTablesJNI.getValue(m_handle);
115  }
116
117  /**
118   * Gets the entry's value as a boolean. If the entry does not exist or is of different type, it
119   * will return the default value.
120   *
121   * @param defaultValue the value to be returned if no value is found
122   * @return the entry's value or the given default value
123   */
124  public boolean getBoolean(boolean defaultValue) {
125    return NetworkTablesJNI.getBoolean(m_handle, defaultValue);
126  }
127
128  /**
129   * Gets the entry's value as a double. If the entry does not exist or is of different type, it
130   * will return the default value.
131   *
132   * @param defaultValue the value to be returned if no value is found
133   * @return the entry's value or the given default value
134   */
135  public double getDouble(double defaultValue) {
136    return NetworkTablesJNI.getDouble(m_handle, defaultValue);
137  }
138
139  /**
140   * Gets the entry's value as a double. If the entry does not exist or is of different type, it
141   * will return the default value.
142   *
143   * @param defaultValue the value to be returned if no value is found
144   * @return the entry's value or the given default value
145   */
146  public Number getNumber(Number defaultValue) {
147    return NetworkTablesJNI.getDouble(m_handle, defaultValue.doubleValue());
148  }
149
150  /**
151   * Gets the entry's value as a string. If the entry does not exist or is of different type, it
152   * will return the default value.
153   *
154   * @param defaultValue the value to be returned if no value is found
155   * @return the entry's value or the given default value
156   */
157  public String getString(String defaultValue) {
158    return NetworkTablesJNI.getString(m_handle, defaultValue);
159  }
160
161  /**
162   * Gets the entry's value as a raw value (byte array). If the entry does not exist or is of
163   * different type, it will return the default value.
164   *
165   * @param defaultValue the value to be returned if no value is found
166   * @return the entry's value or the given default value
167   */
168  public byte[] getRaw(byte[] defaultValue) {
169    return NetworkTablesJNI.getRaw(m_handle, defaultValue);
170  }
171
172  /**
173   * Gets the entry's value as a boolean array. If the entry does not exist or is of different type,
174   * it will return the default value.
175   *
176   * @param defaultValue the value to be returned if no value is found
177   * @return the entry's value or the given default value
178   */
179  public boolean[] getBooleanArray(boolean[] defaultValue) {
180    return NetworkTablesJNI.getBooleanArray(m_handle, defaultValue);
181  }
182
183  /**
184   * Gets the entry's value as a boolean array. If the entry does not exist or is of different type,
185   * it will return the default value.
186   *
187   * @param defaultValue the value to be returned if no value is found
188   * @return the entry's value or the given default value
189   */
190  public Boolean[] getBooleanArray(Boolean[] defaultValue) {
191    return NetworkTableValue.fromNative(
192        NetworkTablesJNI.getBooleanArray(m_handle, NetworkTableValue.toNative(defaultValue)));
193  }
194
195  /**
196   * Gets the entry's value as a double array. If the entry does not exist or is of different type,
197   * it will return the default value.
198   *
199   * @param defaultValue the value to be returned if no value is found
200   * @return the entry's value or the given default value
201   */
202  public double[] getDoubleArray(double[] defaultValue) {
203    return NetworkTablesJNI.getDoubleArray(m_handle, defaultValue);
204  }
205
206  /**
207   * Gets the entry's value as a double array. If the entry does not exist or is of different type,
208   * it will return the default value.
209   *
210   * @param defaultValue the value to be returned if no value is found
211   * @return the entry's value or the given default value
212   */
213  public Double[] getDoubleArray(Double[] defaultValue) {
214    return NetworkTableValue.fromNative(
215        NetworkTablesJNI.getDoubleArray(m_handle, NetworkTableValue.toNative(defaultValue)));
216  }
217
218  /**
219   * Gets the entry's value as a double array. If the entry does not exist or is of different type,
220   * it will return the default value.
221   *
222   * @param defaultValue the value to be returned if no value is found
223   * @return the entry's value or the given default value
224   */
225  public Number[] getNumberArray(Number[] defaultValue) {
226    return NetworkTableValue.fromNative(
227        NetworkTablesJNI.getDoubleArray(m_handle, NetworkTableValue.toNative(defaultValue)));
228  }
229
230  /**
231   * Gets the entry's value as a string array. If the entry does not exist or is of different type,
232   * it will return the default value.
233   *
234   * @param defaultValue the value to be returned if no value is found
235   * @return the entry's value or the given default value
236   */
237  public String[] getStringArray(String[] defaultValue) {
238    return NetworkTablesJNI.getStringArray(m_handle, defaultValue);
239  }
240
241  /**
242   * Checks if a data value is of a type that can be placed in a NetworkTable entry.
243   *
244   * @param data the data to check
245   * @return true if the data can be placed in an entry, false if it cannot
246   */
247  public static boolean isValidDataType(Object data) {
248    return data instanceof Number
249        || data instanceof Boolean
250        || data instanceof String
251        || data instanceof double[]
252        || data instanceof Double[]
253        || data instanceof Number[]
254        || data instanceof boolean[]
255        || data instanceof Boolean[]
256        || data instanceof String[]
257        || data instanceof byte[]
258        || data instanceof Byte[];
259  }
260
261  /**
262   * Sets the entry's value if it does not exist.
263   *
264   * @param defaultValue the default value to set
265   * @return False if the entry exists with a different type
266   * @throws IllegalArgumentException if the value is not a known type
267   */
268  public boolean setDefaultValue(Object defaultValue) {
269    if (defaultValue instanceof NetworkTableValue) {
270      long time = ((NetworkTableValue) defaultValue).getTime();
271      Object otherValue = ((NetworkTableValue) defaultValue).getValue();
272      switch (((NetworkTableValue) defaultValue).getType()) {
273        case kBoolean:
274          return NetworkTablesJNI.setDefaultBoolean(m_handle, time, (Boolean) otherValue);
275        case kDouble:
276          return NetworkTablesJNI.setDefaultDouble(
277              m_handle, time, ((Number) otherValue).doubleValue());
278        case kString:
279          return NetworkTablesJNI.setDefaultString(m_handle, time, (String) otherValue);
280        case kRaw:
281          return NetworkTablesJNI.setDefaultRaw(m_handle, time, (byte[]) otherValue);
282        case kBooleanArray:
283          return NetworkTablesJNI.setDefaultBooleanArray(m_handle, time, (boolean[]) otherValue);
284        case kDoubleArray:
285          return NetworkTablesJNI.setDefaultDoubleArray(m_handle, time, (double[]) otherValue);
286        case kStringArray:
287          return NetworkTablesJNI.setDefaultStringArray(m_handle, time, (String[]) otherValue);
288        case kRpc:
289          // TODO
290        default:
291          return true;
292      }
293    } else if (defaultValue instanceof Boolean) {
294      return setDefaultBoolean((Boolean) defaultValue);
295    } else if (defaultValue instanceof Number) {
296      return setDefaultNumber((Number) defaultValue);
297    } else if (defaultValue instanceof String) {
298      return setDefaultString((String) defaultValue);
299    } else if (defaultValue instanceof byte[]) {
300      return setDefaultRaw((byte[]) defaultValue);
301    } else if (defaultValue instanceof boolean[]) {
302      return setDefaultBooleanArray((boolean[]) defaultValue);
303    } else if (defaultValue instanceof double[]) {
304      return setDefaultDoubleArray((double[]) defaultValue);
305    } else if (defaultValue instanceof Boolean[]) {
306      return setDefaultBooleanArray((Boolean[]) defaultValue);
307    } else if (defaultValue instanceof Number[]) {
308      return setDefaultNumberArray((Number[]) defaultValue);
309    } else if (defaultValue instanceof String[]) {
310      return setDefaultStringArray((String[]) defaultValue);
311    } else {
312      throw new IllegalArgumentException(
313          "Value of type " + defaultValue.getClass().getName() + " cannot be put into a table");
314    }
315  }
316
317  /**
318   * Sets the entry's value if it does not exist.
319   *
320   * @param defaultValue the default value to set
321   * @return False if the entry exists with a different type
322   */
323  public boolean setDefaultBoolean(boolean defaultValue) {
324    return NetworkTablesJNI.setDefaultBoolean(m_handle, 0, defaultValue);
325  }
326
327  /**
328   * Sets the entry's value if it does not exist.
329   *
330   * @param defaultValue the default value to set
331   * @return False if the entry exists with a different type
332   */
333  public boolean setDefaultDouble(double defaultValue) {
334    return NetworkTablesJNI.setDefaultDouble(m_handle, 0, defaultValue);
335  }
336
337  /**
338   * Sets the entry's value if it does not exist.
339   *
340   * @param defaultValue the default value to set
341   * @return False if the entry exists with a different type
342   */
343  public boolean setDefaultNumber(Number defaultValue) {
344    return NetworkTablesJNI.setDefaultDouble(m_handle, 0, defaultValue.doubleValue());
345  }
346
347  /**
348   * Sets the entry's value if it does not exist.
349   *
350   * @param defaultValue the default value to set
351   * @return False if the entry exists with a different type
352   */
353  public boolean setDefaultString(String defaultValue) {
354    return NetworkTablesJNI.setDefaultString(m_handle, 0, defaultValue);
355  }
356
357  /**
358   * Sets the entry's value if it does not exist.
359   *
360   * @param defaultValue the default value to set
361   * @return False if the entry exists with a different type
362   */
363  public boolean setDefaultRaw(byte[] defaultValue) {
364    return NetworkTablesJNI.setDefaultRaw(m_handle, 0, defaultValue);
365  }
366
367  /**
368   * Sets the entry's value if it does not exist.
369   *
370   * @param defaultValue the default value to set
371   * @return False if the entry exists with a different type
372   */
373  public boolean setDefaultBooleanArray(boolean[] defaultValue) {
374    return NetworkTablesJNI.setDefaultBooleanArray(m_handle, 0, defaultValue);
375  }
376
377  /**
378   * Sets the entry's value if it does not exist.
379   *
380   * @param defaultValue the default value to set
381   * @return False if the entry exists with a different type
382   */
383  public boolean setDefaultBooleanArray(Boolean[] defaultValue) {
384    return NetworkTablesJNI.setDefaultBooleanArray(
385        m_handle, 0, NetworkTableValue.toNative(defaultValue));
386  }
387
388  /**
389   * Sets the entry's value if it does not exist.
390   *
391   * @param defaultValue the default value to set
392   * @return False if the entry exists with a different type
393   */
394  public boolean setDefaultDoubleArray(double[] defaultValue) {
395    return NetworkTablesJNI.setDefaultDoubleArray(m_handle, 0, defaultValue);
396  }
397
398  /**
399   * Sets the entry's value if it does not exist.
400   *
401   * @param defaultValue the default value to set
402   * @return False if the entry exists with a different type
403   */
404  public boolean setDefaultNumberArray(Number[] defaultValue) {
405    return NetworkTablesJNI.setDefaultDoubleArray(
406        m_handle, 0, NetworkTableValue.toNative(defaultValue));
407  }
408
409  /**
410   * Sets the entry's value if it does not exist.
411   *
412   * @param defaultValue the default value to set
413   * @return False if the entry exists with a different type
414   */
415  public boolean setDefaultStringArray(String[] defaultValue) {
416    return NetworkTablesJNI.setDefaultStringArray(m_handle, 0, defaultValue);
417  }
418
419  /**
420   * Sets the entry's value.
421   *
422   * @param value the value that will be assigned
423   * @return False if the table key already exists with a different type
424   * @throws IllegalArgumentException if the value is not a known type
425   */
426  public boolean setValue(Object value) {
427    if (value instanceof NetworkTableValue) {
428      long time = ((NetworkTableValue) value).getTime();
429      Object otherValue = ((NetworkTableValue) value).getValue();
430      switch (((NetworkTableValue) value).getType()) {
431        case kBoolean:
432          return NetworkTablesJNI.setBoolean(m_handle, time, (Boolean) otherValue, false);
433        case kDouble:
434          return NetworkTablesJNI.setDouble(
435              m_handle, time, ((Number) otherValue).doubleValue(), false);
436        case kString:
437          return NetworkTablesJNI.setString(m_handle, time, (String) otherValue, false);
438        case kRaw:
439          return NetworkTablesJNI.setRaw(m_handle, time, (byte[]) otherValue, false);
440        case kBooleanArray:
441          return NetworkTablesJNI.setBooleanArray(m_handle, time, (boolean[]) otherValue, false);
442        case kDoubleArray:
443          return NetworkTablesJNI.setDoubleArray(m_handle, time, (double[]) otherValue, false);
444        case kStringArray:
445          return NetworkTablesJNI.setStringArray(m_handle, time, (String[]) otherValue, false);
446        case kRpc:
447          // TODO
448        default:
449          return true;
450      }
451    } else if (value instanceof Boolean) {
452      return setBoolean((Boolean) value);
453    } else if (value instanceof Number) {
454      return setNumber((Number) value);
455    } else if (value instanceof String) {
456      return setString((String) value);
457    } else if (value instanceof byte[]) {
458      return setRaw((byte[]) value);
459    } else if (value instanceof boolean[]) {
460      return setBooleanArray((boolean[]) value);
461    } else if (value instanceof double[]) {
462      return setDoubleArray((double[]) value);
463    } else if (value instanceof Boolean[]) {
464      return setBooleanArray((Boolean[]) value);
465    } else if (value instanceof Number[]) {
466      return setNumberArray((Number[]) value);
467    } else if (value instanceof String[]) {
468      return setStringArray((String[]) value);
469    } else {
470      throw new IllegalArgumentException(
471          "Value of type " + value.getClass().getName() + " cannot be put into a table");
472    }
473  }
474
475  /**
476   * Sets the entry's value.
477   *
478   * @param value the value to set
479   * @return False if the entry exists with a different type
480   */
481  public boolean setBoolean(boolean value) {
482    return NetworkTablesJNI.setBoolean(m_handle, 0, value, false);
483  }
484
485  /**
486   * Sets the entry's value.
487   *
488   * @param value the value to set
489   * @return False if the entry exists with a different type
490   */
491  public boolean setDouble(double value) {
492    return NetworkTablesJNI.setDouble(m_handle, 0, value, false);
493  }
494
495  /**
496   * Sets the entry's value.
497   *
498   * @param value the value to set
499   * @return False if the entry exists with a different type
500   */
501  public boolean setNumber(Number value) {
502    return NetworkTablesJNI.setDouble(m_handle, 0, value.doubleValue(), false);
503  }
504
505  /**
506   * Sets the entry's value.
507   *
508   * @param value the value to set
509   * @return False if the entry exists with a different type
510   */
511  public boolean setString(String value) {
512    return NetworkTablesJNI.setString(m_handle, 0, value, false);
513  }
514
515  /**
516   * Sets the entry's value.
517   *
518   * @param value the value to set
519   * @return False if the entry exists with a different type
520   */
521  public boolean setRaw(byte[] value) {
522    return NetworkTablesJNI.setRaw(m_handle, 0, value, false);
523  }
524
525  /**
526   * Sets the entry's value.
527   *
528   * @param value the value to set
529   * @param len the length of the value
530   * @return False if the entry exists with a different type
531   */
532  public boolean setRaw(ByteBuffer value, int len) {
533    if (!value.isDirect()) {
534      throw new IllegalArgumentException("must be a direct buffer");
535    }
536    if (value.capacity() < len) {
537      throw new IllegalArgumentException("buffer is too small, must be at least " + len);
538    }
539    return NetworkTablesJNI.setRaw(m_handle, 0, value, len, false);
540  }
541
542  /**
543   * Sets the entry's value.
544   *
545   * @param value the value to set
546   * @return False if the entry exists with a different type
547   */
548  public boolean setBooleanArray(boolean[] value) {
549    return NetworkTablesJNI.setBooleanArray(m_handle, 0, value, false);
550  }
551
552  /**
553   * Sets the entry's value.
554   *
555   * @param value the value to set
556   * @return False if the entry exists with a different type
557   */
558  public boolean setBooleanArray(Boolean[] value) {
559    return NetworkTablesJNI.setBooleanArray(m_handle, 0, NetworkTableValue.toNative(value), false);
560  }
561
562  /**
563   * Sets the entry's value.
564   *
565   * @param value the value to set
566   * @return False if the entry exists with a different type
567   */
568  public boolean setDoubleArray(double[] value) {
569    return NetworkTablesJNI.setDoubleArray(m_handle, 0, value, false);
570  }
571
572  /**
573   * Sets the entry's value.
574   *
575   * @param value the value to set
576   * @return False if the entry exists with a different type
577   */
578  public boolean setNumberArray(Number[] value) {
579    return NetworkTablesJNI.setDoubleArray(m_handle, 0, NetworkTableValue.toNative(value), false);
580  }
581
582  /**
583   * Sets the entry's value.
584   *
585   * @param value the value to set
586   * @return False if the entry exists with a different type
587   */
588  public boolean setStringArray(String[] value) {
589    return NetworkTablesJNI.setStringArray(m_handle, 0, value, false);
590  }
591
592  /**
593   * Sets the entry's value. If the value is of different type, the type is changed to match the new
594   * value.
595   *
596   * @param value the value to set
597   * @throws IllegalArgumentException if the value is not a known type
598   */
599  public void forceSetValue(Object value) {
600    if (value instanceof NetworkTableValue) {
601      long time = ((NetworkTableValue) value).getTime();
602      Object otherValue = ((NetworkTableValue) value).getValue();
603      switch (((NetworkTableValue) value).getType()) {
604        case kBoolean:
605          NetworkTablesJNI.setBoolean(m_handle, time, (Boolean) otherValue, true);
606          return;
607        case kDouble:
608          NetworkTablesJNI.setDouble(m_handle, time, ((Number) otherValue).doubleValue(), true);
609          return;
610        case kString:
611          NetworkTablesJNI.setString(m_handle, time, (String) otherValue, true);
612          return;
613        case kRaw:
614          NetworkTablesJNI.setRaw(m_handle, time, (byte[]) otherValue, true);
615          return;
616        case kBooleanArray:
617          NetworkTablesJNI.setBooleanArray(m_handle, time, (boolean[]) otherValue, true);
618          return;
619        case kDoubleArray:
620          NetworkTablesJNI.setDoubleArray(m_handle, time, (double[]) otherValue, true);
621          return;
622        case kStringArray:
623          NetworkTablesJNI.setStringArray(m_handle, time, (String[]) otherValue, true);
624          return;
625        case kRpc:
626          // TODO
627        default:
628          return;
629      }
630    } else if (value instanceof Boolean) {
631      forceSetBoolean((Boolean) value);
632    } else if (value instanceof Number) {
633      forceSetNumber((Number) value);
634    } else if (value instanceof String) {
635      forceSetString((String) value);
636    } else if (value instanceof byte[]) {
637      forceSetRaw((byte[]) value);
638    } else if (value instanceof boolean[]) {
639      forceSetBooleanArray((boolean[]) value);
640    } else if (value instanceof double[]) {
641      forceSetDoubleArray((double[]) value);
642    } else if (value instanceof Boolean[]) {
643      forceSetBooleanArray((Boolean[]) value);
644    } else if (value instanceof Number[]) {
645      forceSetNumberArray((Number[]) value);
646    } else if (value instanceof String[]) {
647      forceSetStringArray((String[]) value);
648    } else {
649      throw new IllegalArgumentException(
650          "Value of type " + value.getClass().getName() + " cannot be put into a table");
651    }
652  }
653
654  /**
655   * Sets the entry's value. If the value is of different type, the type is changed to match the new
656   * value.
657   *
658   * @param value the value to set
659   */
660  public void forceSetBoolean(boolean value) {
661    NetworkTablesJNI.setBoolean(m_handle, 0, value, true);
662  }
663
664  /**
665   * Sets the entry's value. If the value is of different type, the type is changed to match the new
666   * value.
667   *
668   * @param value the value to set
669   */
670  public void forceSetDouble(double value) {
671    NetworkTablesJNI.setDouble(m_handle, 0, value, true);
672  }
673
674  /**
675   * Sets the entry's value. If the value is of different type, the type is changed to match the new
676   * value.
677   *
678   * @param value the value to set
679   */
680  public void forceSetNumber(Number value) {
681    NetworkTablesJNI.setDouble(m_handle, 0, value.doubleValue(), true);
682  }
683
684  /**
685   * Sets the entry's value. If the value is of different type, the type is changed to match the new
686   * value.
687   *
688   * @param value the value to set
689   */
690  public void forceSetString(String value) {
691    NetworkTablesJNI.setString(m_handle, 0, value, true);
692  }
693
694  /**
695   * Sets the entry's value. If the value is of different type, the type is changed to match the new
696   * value.
697   *
698   * @param value the value to set
699   */
700  public void forceSetRaw(byte[] value) {
701    NetworkTablesJNI.setRaw(m_handle, 0, value, true);
702  }
703
704  /**
705   * Sets the entry's value. If the value is of different type, the type is changed to match the new
706   * value.
707   *
708   * @param value the value to set
709   */
710  public void forceSetBooleanArray(boolean[] value) {
711    NetworkTablesJNI.setBooleanArray(m_handle, 0, value, true);
712  }
713
714  /**
715   * Sets the entry's value. If the value is of different type, the type is changed to match the new
716   * value.
717   *
718   * @param value the value to set
719   */
720  public void forceSetBooleanArray(Boolean[] value) {
721    NetworkTablesJNI.setBooleanArray(m_handle, 0, NetworkTableValue.toNative(value), true);
722  }
723
724  /**
725   * Sets the entry's value. If the value is of different type, the type is changed to match the new
726   * value.
727   *
728   * @param value the value to set
729   */
730  public void forceSetDoubleArray(double[] value) {
731    NetworkTablesJNI.setDoubleArray(m_handle, 0, value, true);
732  }
733
734  /**
735   * Sets the entry's value. If the value is of different type, the type is changed to match the new
736   * value.
737   *
738   * @param value the value to set
739   */
740  public void forceSetNumberArray(Number[] value) {
741    NetworkTablesJNI.setDoubleArray(m_handle, 0, NetworkTableValue.toNative(value), true);
742  }
743
744  /**
745   * Sets the entry's value. If the value is of different type, the type is changed to match the new
746   * value.
747   *
748   * @param value the value to set
749   */
750  public void forceSetStringArray(String[] value) {
751    NetworkTablesJNI.setStringArray(m_handle, 0, value, true);
752  }
753
754  /**
755   * Sets flags.
756   *
757   * @param flags the flags to set (bitmask)
758   */
759  public void setFlags(int flags) {
760    NetworkTablesJNI.setEntryFlags(m_handle, getFlags() | flags);
761  }
762
763  /**
764   * Clears flags.
765   *
766   * @param flags the flags to clear (bitmask)
767   */
768  public void clearFlags(int flags) {
769    NetworkTablesJNI.setEntryFlags(m_handle, getFlags() & ~flags);
770  }
771
772  /** Make value persistent through program restarts. */
773  public void setPersistent() {
774    setFlags(kPersistent);
775  }
776
777  /** Stop making value persistent through program restarts. */
778  public void clearPersistent() {
779    clearFlags(kPersistent);
780  }
781
782  /**
783   * Returns whether the value is persistent through program restarts.
784   *
785   * @return True if the value is persistent.
786   */
787  public boolean isPersistent() {
788    return (getFlags() & kPersistent) != 0;
789  }
790
791  /** Deletes the entry. */
792  public void delete() {
793    NetworkTablesJNI.deleteEntry(m_handle);
794  }
795
796  /**
797   * Create a callback-based RPC entry point. Only valid to use on the server. The callback function
798   * will be called when the RPC is called. This function creates RPC version 0 definitions (raw
799   * data in and out).
800   *
801   * @param callback callback function
802   */
803  public void createRpc(Consumer<RpcAnswer> callback) {
804    m_inst.createRpc(this, callback);
805  }
806
807  /**
808   * Call a RPC function. May be used on either the client or server. This function is non-blocking.
809   * Either {@link RpcCall#getResult()} or {@link RpcCall#cancelResult()} must be called on the
810   * return value to either get or ignore the result of the call.
811   *
812   * @param params parameter
813   * @return RPC call object.
814   */
815  public RpcCall callRpc(byte[] params) {
816    return new RpcCall(this, NetworkTablesJNI.callRpc(m_handle, params));
817  }
818
819  /**
820   * Add a listener for changes to the entry.
821   *
822   * @param listener the listener to add
823   * @param flags bitmask specifying desired notifications
824   * @return listener handle
825   */
826  public int addListener(Consumer<EntryNotification> listener, int flags) {
827    return m_inst.addEntryListener(this, listener, flags);
828  }
829
830  /**
831   * Remove a listener from receiving entry events.
832   *
833   * @param listener the listener to be removed
834   */
835  public void removeListener(int listener) {
836    m_inst.removeEntryListener(listener);
837  }
838
839  @Override
840  public boolean equals(Object other) {
841    if (other == this) {
842      return true;
843    }
844    if (!(other instanceof NetworkTableEntry)) {
845      return false;
846    }
847
848    return m_handle == ((NetworkTableEntry) other).m_handle;
849  }
850
851  @Override
852  public int hashCode() {
853    return m_handle;
854  }
855
856  private final NetworkTableInstance m_inst;
857  private final int m_handle;
858}