View Javadoc
1   package org.opentrafficsim.draw.egtf;
2   
3   import java.util.LinkedHashMap;
4   import java.util.Map;
5   
6   /**
7    * Data source for the EGTF. These are obtained using {@code EGTF.getDataSource()}.
8    * <p>
9    * Copyright (c) 2013-2024 Delft University of Technology, PO Box 5, 2600 AA, Delft, the Netherlands. All rights reserved. <br>
10   * BSD-style license. See <a href="https://opentrafficsim.org/docs/license.html">OpenTrafficSim License</a>.
11   * </p>
12   * @author <a href="https://github.com/wjschakel">Wouter Schakel</a>
13   */
14  public final class DataSource
15  {
16      /** Unique name. */
17      private final String name;
18  
19      /** Data stream of this data source. */
20      private final Map<String, DataStream<?>> streams = new LinkedHashMap<>();
21  
22      /**
23       * Constructor.
24       * @param name String; unique name
25       */
26      DataSource(final String name)
27      {
28          this.name = name;
29      }
30  
31      /**
32       * Returns the name.
33       * @return String; name
34       */
35      public String getName()
36      {
37          return this.name;
38      }
39  
40      /**
41       * Add a non-speed stream for the quantity to this data source.
42       * @param quantity Quantity&lt;T, ?&gt;; quantity
43       * @param thetaCong T; standard deviation of this quantity of measurements in congestion by this data source
44       * @param thetaFree T; standard deviation of this quantity of measurements in free flow by this data source
45       * @param <T> implicit data type
46       * @return DataStream; the created data stream
47       * @throws IllegalArgumentException if the quantity is speed
48       */
49      public <T extends Number> DataStream<T> addStream(final Quantity<T, ?> quantity, final T thetaCong, final T thetaFree)
50      {
51          return addStreamSI(quantity, thetaCong.doubleValue(), thetaFree.doubleValue());
52      }
53  
54      /**
55       * Add a stream for the quantity to this data source.
56       * @param quantity Quantity&lt;T, ?&gt;; quantity
57       * @param thetaCong double; standard deviation of this quantity of measurements in congestion by this data source in SI
58       * @param thetaFree double; standard deviation of this quantity of measurements in free flow by this data source in SI
59       * @param <T> implicit data type
60       * @return DataStream; the created data stream
61       */
62      public <T extends Number> DataStream<T> addStreamSI(final Quantity<T, ?> quantity, final double thetaCong,
63              final double thetaFree)
64      {
65          if (this.streams.containsKey(quantity.getName()))
66          {
67              throw new IllegalStateException(
68                      String.format("Data source %s already has a stream for quantity %s.", this.name, quantity.getName()));
69          }
70          if (thetaCong <= 0.0 || thetaFree <= 0.0)
71          {
72              throw new IllegalArgumentException("Standard deviation must be positive and above 0.");
73          }
74          DataStream<T> dataStream = new DataStream<>(this, quantity, thetaCong, thetaFree);
75          this.streams.put(quantity.getName(), dataStream);
76          return dataStream;
77      }
78  
79      /**
80       * Get a stream for the quantity of this data source. If no stream has been created, one will be created with 1.0 standard
81       * deviation.
82       * @param quantity Quantity&lt;T, ?&gt;; quantity
83       * @return DataStream&lt;T&gt;; stream for the quantity of this data source
84       * @param <T> implicit data type
85       */
86      @SuppressWarnings({"unchecked"})
87      public <T extends Number> DataStream<T> getStream(final Quantity<T, ?> quantity)
88      {
89          if (!this.streams.containsKey(quantity.getName()))
90          {
91              addStreamSI(quantity, 1.0, 1.0);
92          }
93          return (DataStream<T>) this.streams.get(quantity.getName());
94      }
95  
96      /** {@inheritDoc} */
97      @Override
98      public int hashCode()
99      {
100         final int prime = 31;
101         int result = 1;
102         result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
103         return result;
104     }
105 
106     /** {@inheritDoc} */
107     @Override
108     public boolean equals(final Object obj)
109     {
110         if (this == obj)
111         {
112             return true;
113         }
114         if (obj == null)
115         {
116             return false;
117         }
118         if (getClass() != obj.getClass())
119         {
120             return false;
121         }
122         DataSource other = (DataSource) obj;
123         if (this.name == null)
124         {
125             if (other.name != null)
126             {
127                 return false;
128             }
129         }
130         else if (!this.name.equals(other.name))
131         {
132             return false;
133         }
134         return true;
135     }
136 
137     /** {@inheritDoc} */
138     @Override
139     public String toString()
140     {
141         return "DataSource [" + this.name + "]";
142     }
143 
144 }