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 unique name
25 */
26 DataSource(final String name)
27 {
28 this.name = name;
29 }
30
31 /**
32 * Returns the name.
33 * @return 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
43 * @param thetaCong standard deviation of this quantity of measurements in congestion by this data source
44 * @param thetaFree standard deviation of this quantity of measurements in free flow by this data source
45 * @param <T> implicit data type
46 * @return 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
57 * @param thetaCong standard deviation of this quantity of measurements in congestion by this data source in SI
58 * @param thetaFree standard deviation of this quantity of measurements in free flow by this data source in SI
59 * @param <T> implicit data type
60 * @return 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
83 * @return 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 @Override
97 public int hashCode()
98 {
99 final int prime = 31;
100 int result = 1;
101 result = prime * result + ((this.name == null) ? 0 : this.name.hashCode());
102 return result;
103 }
104
105 @Override
106 public boolean equals(final Object obj)
107 {
108 if (this == obj)
109 {
110 return true;
111 }
112 if (obj == null)
113 {
114 return false;
115 }
116 if (getClass() != obj.getClass())
117 {
118 return false;
119 }
120 DataSource other = (DataSource) obj;
121 if (this.name == null)
122 {
123 if (other.name != null)
124 {
125 return false;
126 }
127 }
128 else if (!this.name.equals(other.name))
129 {
130 return false;
131 }
132 return true;
133 }
134
135 @Override
136 public String toString()
137 {
138 return "DataSource [" + this.name + "]";
139 }
140
141 }