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 edu.wpi.first.util.struct.Struct;
008import edu.wpi.first.util.struct.StructBuffer;
009
010/**
011 * NetworkTables struct-encoded array value topic.
012 *
013 * @param <T> value class
014 */
015public final class StructArrayTopic<T> extends Topic {
016  private StructArrayTopic(Topic topic, Struct<T> struct) {
017    super(topic.m_inst, topic.m_handle);
018    m_struct = struct;
019  }
020
021  private StructArrayTopic(NetworkTableInstance inst, int handle, Struct<T> struct) {
022    super(inst, handle);
023    m_struct = struct;
024  }
025
026  /**
027   * Create a StructArrayTopic from a generic topic.
028   *
029   * @param <T> value class (inferred from struct)
030   * @param topic generic topic
031   * @param struct struct serialization implementation
032   * @return StructArrayTopic for value class
033   */
034  public static <T> StructArrayTopic<T> wrap(Topic topic, Struct<T> struct) {
035    return new StructArrayTopic<>(topic, struct);
036  }
037
038  /**
039   * Create a StructArrayTopic from a native handle; generally
040   * NetworkTableInstance.getStructArrayTopic() should be used instead.
041   *
042   * @param <T> value class (inferred from struct)
043   * @param inst Instance
044   * @param handle Native handle
045   * @param struct struct serialization implementation
046   * @return StructArrayTopic for value class
047   */
048  public static <T> StructArrayTopic<T> wrap(
049      NetworkTableInstance inst, int handle, Struct<T> struct) {
050    return new StructArrayTopic<>(inst, handle, struct);
051  }
052
053  /**
054   * Create a new subscriber to the topic.
055   *
056   * <p>The subscriber is only active as long as the returned object is not closed.
057   *
058   * <p>Subscribers that do not match the published data type do not return any values. To determine
059   * if the data type matches, use the appropriate Topic functions.
060   *
061   * @param defaultValue default value used when a default is not provided to a getter function
062   * @param options subscribe options
063   * @return subscriber
064   */
065  public StructArraySubscriber<T> subscribe(T[] defaultValue, PubSubOption... options) {
066    return new StructArrayEntryImpl<>(
067        this,
068        StructBuffer.create(m_struct),
069        NetworkTablesJNI.subscribe(
070            m_handle, NetworkTableType.kRaw.getValue(), m_struct.getTypeString() + "[]", options),
071        defaultValue,
072        false);
073  }
074
075  /**
076   * Create a new publisher to the topic.
077   *
078   * <p>The publisher is only active as long as the returned object is not closed.
079   *
080   * <p>It is not possible to publish two different data types to the same topic. Conflicts between
081   * publishers are typically resolved by the server on a first-come, first-served basis. Any
082   * published values that do not match the topic's data type are dropped (ignored). To determine if
083   * the data type matches, use the appropriate Topic functions.
084   *
085   * @param options publish options
086   * @return publisher
087   */
088  public StructArrayPublisher<T> publish(PubSubOption... options) {
089    m_inst.addSchema(m_struct);
090    return new StructArrayEntryImpl<>(
091        this,
092        StructBuffer.create(m_struct),
093        NetworkTablesJNI.publish(
094            m_handle, NetworkTableType.kRaw.getValue(), m_struct.getTypeString() + "[]", options),
095        null,
096        true);
097  }
098
099  /**
100   * Create a new publisher to the topic, with type string and initial properties.
101   *
102   * <p>The publisher is only active as long as the returned object is not closed.
103   *
104   * <p>It is not possible to publish two different data types to the same topic. Conflicts between
105   * publishers are typically resolved by the server on a first-come, first-served basis. Any
106   * published values that do not match the topic's data type are dropped (ignored). To determine if
107   * the data type matches, use the appropriate Topic functions.
108   *
109   * @param properties JSON properties
110   * @param options publish options
111   * @return publisher
112   * @throws IllegalArgumentException if properties is not a JSON object
113   */
114  public StructArrayPublisher<T> publishEx(String properties, PubSubOption... options) {
115    m_inst.addSchema(m_struct);
116    return new StructArrayEntryImpl<>(
117        this,
118        StructBuffer.create(m_struct),
119        NetworkTablesJNI.publishEx(
120            m_handle,
121            NetworkTableType.kRaw.getValue(),
122            m_struct.getTypeString() + "[]",
123            properties,
124            options),
125        null,
126        true);
127  }
128
129  /**
130   * Create a new entry for the topic.
131   *
132   * <p>Entries act as a combination of a subscriber and a weak publisher. The subscriber is active
133   * as long as the entry is not closed. The publisher is created when the entry is first written
134   * to, and remains active until either unpublish() is called or the entry is closed.
135   *
136   * <p>It is not possible to use two different data types with the same topic. Conflicts between
137   * publishers are typically resolved by the server on a first-come, first-served basis. Any
138   * published values that do not match the topic's data type are dropped (ignored), and the entry
139   * will show no new values if the data type does not match. To determine if the data type matches,
140   * use the appropriate Topic functions.
141   *
142   * @param defaultValue default value used when a default is not provided to a getter function
143   * @param options publish and/or subscribe options
144   * @return entry
145   */
146  public StructArrayEntry<T> getEntry(T[] defaultValue, PubSubOption... options) {
147    return new StructArrayEntryImpl<>(
148        this,
149        StructBuffer.create(m_struct),
150        NetworkTablesJNI.getEntry(
151            m_handle, NetworkTableType.kRaw.getValue(), m_struct.getTypeString() + "[]", options),
152        defaultValue,
153        false);
154  }
155
156  public Struct<T> getStruct() {
157    return m_struct;
158  }
159
160  @Override
161  public boolean equals(Object other) {
162    if (other == this) {
163      return true;
164    }
165    if (!(other instanceof StructArrayTopic)) {
166      return false;
167    }
168
169    return super.equals(other) && m_struct == ((StructArrayTopic<?>) other).m_struct;
170  }
171
172  @Override
173  public int hashCode() {
174    return super.hashCode() ^ m_struct.hashCode();
175  }
176
177  private final Struct<T> m_struct;
178}