RobotCore 1.0
WPILib port to raspberry Pi
Loading...
Searching...
No Matches
NetworkTable.java
1// Copyright (c) FIRST and other WPILib contributors.
2// Open Source Software; you can modify and/or share it under the terms of
3// the WPILib BSD license file in the root directory of this project.
4
5package org.wpilib.networktables;
6
7import java.util.ArrayList;
8import java.util.EnumSet;
9import java.util.HashSet;
10import java.util.List;
11import java.util.Objects;
12import java.util.Set;
13import java.util.concurrent.ConcurrentHashMap;
14import java.util.concurrent.ConcurrentMap;
15import java.util.function.Consumer;
16import org.wpilib.util.protobuf.Protobuf;
17import org.wpilib.util.struct.Struct;
18import us.hebi.quickbuf.ProtoMessage;
19
21public final class NetworkTable {
23 public static final char PATH_SEPARATOR = '/';
24
25 private final String m_path;
26 private final String m_pathWithSep;
27 private final NetworkTableInstance m_inst;
28
36 public static String basenameKey(String key) {
37 final int slash = key.lastIndexOf(PATH_SEPARATOR);
38 if (slash == -1) {
39 return key;
40 }
41 return key.substring(slash + 1);
42 }
43
59 public static String normalizeKey(String key, boolean withLeadingSlash) {
60 String normalized;
61 if (withLeadingSlash) {
62 normalized = PATH_SEPARATOR + key;
63 } else {
64 normalized = key;
65 }
66 normalized = normalized.replaceAll(PATH_SEPARATOR + "{2,}", String.valueOf(PATH_SEPARATOR));
67
68 if (!withLeadingSlash && normalized.charAt(0) == PATH_SEPARATOR) {
69 // remove leading slash, if present
70 normalized = normalized.substring(1);
71 }
72 return normalized;
73 }
74
85 public static String normalizeKey(String key) {
86 return normalizeKey(key, true);
87 }
88
96 public static List<String> getHierarchy(String key) {
97 final String normal = normalizeKey(key, true);
98 List<String> hierarchy = new ArrayList<>();
99 if (normal.length() == 1) {
100 hierarchy.add(normal);
101 return hierarchy;
102 }
103 for (int i = 1; ; i = normal.indexOf(PATH_SEPARATOR, i + 1)) {
104 if (i == -1) {
105 // add the full key
106 hierarchy.add(normal);
107 break;
108 } else {
109 hierarchy.add(normal.substring(0, i));
110 }
111 }
112 return hierarchy;
113 }
114
116 NetworkTable(NetworkTableInstance inst, String path) {
117 m_path = path;
118 m_pathWithSep = path + PATH_SEPARATOR;
119 m_inst = inst;
120 }
121
128 return m_inst;
129 }
130
131 @Override
132 public String toString() {
133 return "NetworkTable: " + m_path;
134 }
135
142 public Topic getTopic(String name) {
143 return m_inst.getTopic(m_pathWithSep + name);
144 }
145
152 public BooleanTopic getBooleanTopic(String name) {
153 return m_inst.getBooleanTopic(m_pathWithSep + name);
154 }
155
162 public IntegerTopic getIntegerTopic(String name) {
163 return m_inst.getIntegerTopic(m_pathWithSep + name);
164 }
165
172 public FloatTopic getFloatTopic(String name) {
173 return m_inst.getFloatTopic(m_pathWithSep + name);
174 }
175
182 public DoubleTopic getDoubleTopic(String name) {
183 return m_inst.getDoubleTopic(m_pathWithSep + name);
184 }
185
192 public StringTopic getStringTopic(String name) {
193 return m_inst.getStringTopic(m_pathWithSep + name);
194 }
195
202 public RawTopic getRawTopic(String name) {
203 return m_inst.getRawTopic(m_pathWithSep + name);
204 }
205
213 return m_inst.getBooleanArrayTopic(m_pathWithSep + name);
214 }
215
223 return m_inst.getIntegerArrayTopic(m_pathWithSep + name);
224 }
225
233 return m_inst.getFloatArrayTopic(m_pathWithSep + name);
234 }
235
243 return m_inst.getDoubleArrayTopic(m_pathWithSep + name);
244 }
245
253 return m_inst.getStringArrayTopic(m_pathWithSep + name);
254 }
255
265 public <T, MessageType extends ProtoMessage<?>> ProtobufTopic<T> getProtobufTopic(
266 String name, Protobuf<T, MessageType> proto) {
267 return m_inst.getProtobufTopic(m_pathWithSep + name, proto);
268 }
269
278 public <T> StructTopic<T> getStructTopic(String name, Struct<T> struct) {
279 return m_inst.getStructTopic(m_pathWithSep + name, struct);
280 }
281
290 public <T> StructArrayTopic<T> getStructArrayTopic(String name, Struct<T> struct) {
291 return m_inst.getStructArrayTopic(m_pathWithSep + name, struct);
292 }
293
294 private final ConcurrentMap<String, NetworkTableEntry> m_entries = new ConcurrentHashMap<>();
295
302 public NetworkTableEntry getEntry(String key) {
303 NetworkTableEntry entry = m_entries.get(key);
304 if (entry == null) {
305 entry = m_inst.getEntry(m_pathWithSep + key);
306 NetworkTableEntry oldEntry = m_entries.putIfAbsent(key, entry);
307 if (oldEntry != null) {
308 entry = oldEntry;
309 }
310 }
311 return entry;
312 }
313
321 public NetworkTable getSubTable(String key) {
322 return new NetworkTable(m_inst, m_pathWithSep + key);
323 }
324
331 public boolean containsKey(String key) {
332 return !"".equals(key) && getTopic(key).exists();
333 }
334
342 public boolean containsSubTable(String key) {
343 Topic[] topics = m_inst.getTopics(m_pathWithSep + key + PATH_SEPARATOR, 0);
344 return topics.length != 0;
345 }
346
353 public List<TopicInfo> getTopicInfo(int types) {
354 List<TopicInfo> infos = new ArrayList<>();
355 int prefixLen = m_path.length() + 1;
356 for (TopicInfo info : m_inst.getTopicInfo(m_pathWithSep, types)) {
357 String relativeKey = info.name.substring(prefixLen);
358 if (relativeKey.indexOf(PATH_SEPARATOR) != -1) {
359 continue;
360 }
361 infos.add(info);
362 }
363 return infos;
364 }
365
371 public List<TopicInfo> getTopicInfo() {
372 return getTopicInfo(0);
373 }
374
381 public List<Topic> getTopics(int types) {
382 List<Topic> topics = new ArrayList<>();
383 int prefixLen = m_path.length() + 1;
384 for (TopicInfo info : m_inst.getTopicInfo(m_pathWithSep, types)) {
385 String relativeKey = info.name.substring(prefixLen);
386 if (relativeKey.indexOf(PATH_SEPARATOR) != -1) {
387 continue;
388 }
389 topics.add(info.getTopic());
390 }
391 return topics;
392 }
393
399 public List<Topic> getTopics() {
400 return getTopics(0);
401 }
402
409 public Set<String> getKeys(int types) {
410 Set<String> keys = new HashSet<>();
411 int prefixLen = m_path.length() + 1;
412 for (TopicInfo info : m_inst.getTopicInfo(m_pathWithSep, types)) {
413 String relativeKey = info.name.substring(prefixLen);
414 if (relativeKey.indexOf(PATH_SEPARATOR) != -1) {
415 continue;
416 }
417 keys.add(relativeKey);
418 }
419 return keys;
420 }
421
427 public Set<String> getKeys() {
428 return getKeys(0);
429 }
430
436 public Set<String> getSubTables() {
437 Set<String> keys = new HashSet<>();
438 int prefixLen = m_path.length() + 1;
439 for (TopicInfo info : m_inst.getTopicInfo(m_pathWithSep, 0)) {
440 String relativeKey = info.name.substring(prefixLen);
441 int endSubTable = relativeKey.indexOf(PATH_SEPARATOR);
442 if (endSubTable == -1) {
443 continue;
444 }
445 keys.add(relativeKey.substring(0, endSubTable));
446 }
447 return keys;
448 }
449
457 public boolean putValue(String key, NetworkTableValue value) {
458 return getEntry(key).setValue(value);
459 }
460
468 public boolean setDefaultValue(String key, NetworkTableValue defaultValue) {
469 return getEntry(key).setDefaultValue(defaultValue);
470 }
471
478 public NetworkTableValue getValue(String key) {
479 return getEntry(key).getValue();
480 }
481
487 public String getPath() {
488 return m_path;
489 }
490
492 @FunctionalInterface
493 public interface TableEventListener {
501 void accept(NetworkTable table, String key, NetworkTableEvent event);
502 }
503
511 public int addListener(EnumSet<NetworkTableEvent.Kind> eventKinds, TableEventListener listener) {
512 final int prefixLen = m_path.length() + 1;
513 return m_inst.addListener(
514 new String[] {m_pathWithSep},
515 eventKinds,
516 event -> {
517 String topicName = null;
518 if (event.topicInfo != null) {
519 topicName = event.topicInfo.name;
520 } else if (event.valueData != null) {
521 topicName = event.valueData.getTopic().getName();
522 }
523 if (topicName == null) {
524 return;
525 }
526 String relativeKey = topicName.substring(prefixLen);
527 if (relativeKey.indexOf(PATH_SEPARATOR) != -1) {
528 // part of a sub table
529 return;
530 }
531 listener.accept(this, relativeKey, event);
532 });
533 }
534
543 public int addListener(
544 String key, EnumSet<NetworkTableEvent.Kind> eventKinds, TableEventListener listener) {
545 NetworkTableEntry entry = getEntry(key);
546 return m_inst.addListener(entry, eventKinds, event -> listener.accept(this, key, event));
547 }
548
550 @FunctionalInterface
551 public interface SubTableListener {
559 void tableCreated(NetworkTable parent, String name, NetworkTable table);
560 }
561
570 final int prefixLen = m_path.length() + 1;
571 final NetworkTable parent = this;
572
573 return m_inst.addListener(
574 new String[] {m_pathWithSep},
576 new Consumer<>() {
577 final Set<String> m_notifiedTables = new HashSet<>();
578
579 @Override
580 public void accept(NetworkTableEvent event) {
581 if (event.topicInfo == null) {
582 return; // should not happen
583 }
584 String relativeKey = event.topicInfo.name.substring(prefixLen);
585 int endSubTable = relativeKey.indexOf(PATH_SEPARATOR);
586 if (endSubTable == -1) {
587 return;
588 }
589 String subTableKey = relativeKey.substring(0, endSubTable);
590 if (m_notifiedTables.contains(subTableKey)) {
591 return;
592 }
593 m_notifiedTables.add(subTableKey);
594 listener.tableCreated(parent, subTableKey, parent.getSubTable(subTableKey));
595 }
596 });
597 }
598
604 public void removeListener(int listener) {
605 m_inst.removeListener(listener);
606 }
607
608 @Override
609 public boolean equals(Object other) {
610 return other instanceof NetworkTable ntOther
611 && m_inst.equals(ntOther.m_inst)
612 && m_path.equals(ntOther.m_path);
613 }
614
615 @Override
616 public int hashCode() {
617 return Objects.hash(m_inst, m_path);
618 }
619}
boolean setValue(Object value)
NetworkTableValue getValue()
boolean setDefaultValue(Object defaultValue)
int addSubTableListener(SubTableListener listener)
NetworkTableValue getValue(String key)
BooleanTopic getBooleanTopic(String name)
NetworkTable getSubTable(String key)
FloatTopic getFloatTopic(String name)
static List< String > getHierarchy(String key)
StringArrayTopic getStringArrayTopic(String name)
DoubleArrayTopic getDoubleArrayTopic(String name)
IntegerTopic getIntegerTopic(String name)
IntegerArrayTopic getIntegerArrayTopic(String name)
DoubleTopic getDoubleTopic(String name)
BooleanArrayTopic getBooleanArrayTopic(String name)
boolean putValue(String key, NetworkTableValue value)
List< TopicInfo > getTopicInfo(int types)
int addListener(EnumSet< NetworkTableEvent.Kind > eventKinds, TableEventListener listener)
FloatArrayTopic getFloatArrayTopic(String name)
static String normalizeKey(String key, boolean withLeadingSlash)
StringTopic getStringTopic(String name)
int addListener(String key, EnumSet< NetworkTableEvent.Kind > eventKinds, TableEventListener listener)
NetworkTableEntry getEntry(String key)
static String basenameKey(String key)
boolean setDefaultValue(String key, NetworkTableValue defaultValue)
static String normalizeKey(String key)
void tableCreated(NetworkTable parent, String name, NetworkTable table)
void accept(NetworkTable table, String key, NetworkTableEvent event)