blob: 1cfb395bcad1fc702738ca07ce373f964f6f1aed [file] [log] [blame]
Jian Lib6859e12016-03-01 09:29:24 -08001/*
Brian O'Connor5ab426f2016-04-09 01:19:45 -07002 * Copyright 2016-present Open Networking Laboratory
Jian Lib6859e12016-03-01 09:29:24 -08003 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package org.onosproject.ui.chart;
18
Jian Li15468822016-04-15 16:28:11 -070019import com.google.common.collect.Lists;
Jian Lib6859e12016-03-01 09:29:24 -080020import com.google.common.collect.Maps;
Jian Li15468822016-04-15 16:28:11 -070021import com.google.common.collect.Sets;
Jian Lib6859e12016-03-01 09:29:24 -080022
Jian Li1077dd72016-04-26 11:10:20 -070023import java.util.ArrayList;
Jian Lib6859e12016-03-01 09:29:24 -080024import java.util.Arrays;
Jian Li1077dd72016-04-26 11:10:20 -070025import java.util.Collection;
26import java.util.HashMap;
Jian Li15468822016-04-15 16:28:11 -070027import java.util.List;
Jian Lib6859e12016-03-01 09:29:24 -080028import java.util.Map;
Jian Li15468822016-04-15 16:28:11 -070029import java.util.Set;
Jian Lib6859e12016-03-01 09:29:24 -080030
31import static com.google.common.base.Preconditions.checkArgument;
32import static com.google.common.base.Preconditions.checkNotNull;
33
34/**
Jian Li15468822016-04-15 16:28:11 -070035 * A simple model of time series chart data.
Jian Lib6859e12016-03-01 09:29:24 -080036 * <p>
37 * Note that this is not a full MVC type model; the expected usage pattern
Simon Huntb0582492016-09-20 18:26:38 -070038 * is to create an empty chart, add data points (by consulting the business
39 * model), and produce the list of data points which contain a label and a set
40 * of data values for all serials.
Jian Lib6859e12016-03-01 09:29:24 -080041 */
42public class ChartModel {
43
Jian Li15468822016-04-15 16:28:11 -070044 private final Set<String> seriesSet;
45 private final String[] seriesArray;
Jian Li72f3f102016-04-28 12:40:57 -070046 private final List<Object> labels = Lists.newArrayList();
Jian Li15468822016-04-15 16:28:11 -070047 private final List<DataPoint> dataPoints = Lists.newArrayList();
Jian Li1077dd72016-04-26 11:10:20 -070048 private final Map<String, Annot> annotations = new HashMap<>();
Jian Lib6859e12016-03-01 09:29:24 -080049
50 /**
51 * Constructs a chart model with initialized series set.
52 *
Jian Lib6859e12016-03-01 09:29:24 -080053 * @param series a set of series
54 */
Jian Li15468822016-04-15 16:28:11 -070055 public ChartModel(String... series) {
Jian Lib6859e12016-03-01 09:29:24 -080056 checkNotNull(series, "series cannot be null");
57 checkArgument(series.length > 0, "must be at least one series");
Jian Lib6859e12016-03-01 09:29:24 -080058
Jian Li15468822016-04-15 16:28:11 -070059 seriesSet = Sets.newHashSet(series);
60
61 if (seriesSet.size() != series.length) {
62 throw new IllegalArgumentException("duplicate series detected");
Jian Lib6859e12016-03-01 09:29:24 -080063 }
64
Jian Li15468822016-04-15 16:28:11 -070065 this.seriesArray = Arrays.copyOf(series, series.length);
Jian Lib6859e12016-03-01 09:29:24 -080066 }
67
68 private void checkDataPoint(DataPoint dataPoint) {
Jian Li15468822016-04-15 16:28:11 -070069 checkArgument(dataPoint.size() == seriesCount(),
Jian Lib6859e12016-03-01 09:29:24 -080070 "data size should be equal to number of series");
71 }
72
73 /**
Jian Li15468822016-04-15 16:28:11 -070074 * Checks the validity of the given series.
75 *
76 * @param series series name
77 */
78 private void checkSeries(String series) {
79 checkNotNull(series, "must provide a series name");
80 if (!seriesSet.contains(series)) {
81 throw new IllegalArgumentException("unknown series: " + series);
82 }
83 }
84
85 /**
Jian Lib6859e12016-03-01 09:29:24 -080086 * Returns the number of series in this chart model.
87 *
88 * @return number of series
89 */
90 public int seriesCount() {
Jian Li15468822016-04-15 16:28:11 -070091 return seriesSet.size();
Jian Lib6859e12016-03-01 09:29:24 -080092 }
93
94 /**
Jian Li15468822016-04-15 16:28:11 -070095 * Adds a data point to the chart model.
Jian Lib6859e12016-03-01 09:29:24 -080096 *
Jian Li72f3f102016-04-28 12:40:57 -070097 * @param label label instance
Jian Li15468822016-04-15 16:28:11 -070098 * @return the data point, for chaining
Jian Lib6859e12016-03-01 09:29:24 -080099 */
Jian Li72f3f102016-04-28 12:40:57 -0700100 public DataPoint addDataPoint(Object label) {
Jian Li15468822016-04-15 16:28:11 -0700101 DataPoint dp = new DataPoint();
102 labels.add(label);
103 dataPoints.add(dp);
104 return dp;
Jian Lib6859e12016-03-01 09:29:24 -0800105 }
106
107 /**
108 * Returns all of series.
109 *
110 * @return an array of series
111 */
112 public String[] getSeries() {
Jian Li15468822016-04-15 16:28:11 -0700113 return seriesArray;
Jian Lib6859e12016-03-01 09:29:24 -0800114 }
115
116 /**
Jian Li15468822016-04-15 16:28:11 -0700117 * Returns all of data points in order.
Jian Lib6859e12016-03-01 09:29:24 -0800118 *
119 * @return an array of data points
120 */
121 public DataPoint[] getDataPoints() {
Jian Li15468822016-04-15 16:28:11 -0700122 return dataPoints.toArray(new DataPoint[dataPoints.size()]);
123 }
124
125 /**
126 * Returns all of labels in order.
127 *
128 * @return an array of labels
129 */
130 public Object[] getLabels() {
Jian Li72f3f102016-04-28 12:40:57 -0700131 return labels.toArray(new Object[labels.size()]);
Jian Li15468822016-04-15 16:28:11 -0700132 }
133
134 /**
135 * Returns the number of data points in this chart model.
136 *
137 * @return number of data points
138 */
139 public int dataPointCount() {
140 return dataPoints.size();
Jian Lib6859e12016-03-01 09:29:24 -0800141 }
142
143 /**
144 * Returns the last element inside all of data points.
145 *
146 * @return data point
147 */
148 public DataPoint getLastDataPoint() {
Jian Li15468822016-04-15 16:28:11 -0700149 return dataPoints.get(dataPoints.size() - 1);
Jian Lib6859e12016-03-01 09:29:24 -0800150 }
151
152 /**
Jian Li1077dd72016-04-26 11:10:20 -0700153 * Inserts a new annotation.
154 *
155 * @param key key of annotation
156 * @param value value of annotation
157 */
158 public void addAnnotation(String key, Object value) {
159 annotations.put(key, new Annot(key, value));
160 }
161
162 /**
163 * Returns the annotations in this chart.
164 *
165 * @return annotations
166 */
167 public Collection<Annot> getAnnotations() {
168 return new ArrayList<>(annotations.values());
169 }
170
171 /**
172 * Model of an annotation.
173 */
174 public class Annot {
175 private final String key;
176 private final Object value;
177
178 /**
179 * Constructs an annotation with the given key and value.
180 *
181 * @param key the key
182 * @param value the value
183 */
184 public Annot(String key, Object value) {
185 this.key = key;
186 this.value = value;
187 }
188
189 /**
190 * Returns the annotation's key.
191 *
192 * @return key
193 */
194 public String key() {
195 return key;
196 }
197
198 /**
199 * Returns the annotation's value.
200 *
201 * @return value
202 */
203 public Object value() {
204 return value;
205 }
206
207 /**
208 * Returns the value as a string.
209 * This default implementation uses the value's toString() method.
210 *
211 * @return the value as a string
212 */
213 public String valueAsString() {
214 return value.toString();
215 }
216 }
217
218 /**
Jian Lib6859e12016-03-01 09:29:24 -0800219 * A class of data point.
220 */
221 public class DataPoint {
222 // values for all series
Jian Li72f3f102016-04-28 12:40:57 -0700223 private final Map<String, Object> data = Maps.newHashMap();
Jian Lib6859e12016-03-01 09:29:24 -0800224
225 /**
Jian Li15468822016-04-15 16:28:11 -0700226 * Sets the data value for the given series of this data point.
Jian Lib6859e12016-03-01 09:29:24 -0800227 *
Jian Li15468822016-04-15 16:28:11 -0700228 * @param series series name
Jian Li1077dd72016-04-26 11:10:20 -0700229 * @param value value to set
Jian Li15468822016-04-15 16:28:11 -0700230 * @return self, for chaining
Jian Lib6859e12016-03-01 09:29:24 -0800231 */
Jian Li72f3f102016-04-28 12:40:57 -0700232 public DataPoint data(String series, Object value) {
Jian Li15468822016-04-15 16:28:11 -0700233 checkSeries(series);
234 data.put(series, value);
235 return this;
Jian Lib6859e12016-03-01 09:29:24 -0800236 }
237
238 /**
Jian Li15468822016-04-15 16:28:11 -0700239 * Returns the data value with the given series for this data point.
Jian Lib6859e12016-03-01 09:29:24 -0800240 *
Jian Li72f3f102016-04-28 12:40:57 -0700241 * @param series series name
Jian Li15468822016-04-15 16:28:11 -0700242 * @return data value
Jian Lib6859e12016-03-01 09:29:24 -0800243 */
Jian Li72f3f102016-04-28 12:40:57 -0700244 public Object get(String series) {
Jian Li15468822016-04-15 16:28:11 -0700245 return data.get(series);
246 }
247
248 /**
249 * Return the data value with the same order of series.
250 *
251 * @return an array of ordered data values
252 */
Jian Li72f3f102016-04-28 12:40:57 -0700253 public Object[] getAll() {
254 Object[] value = new Object[getSeries().length];
Jian Li15468822016-04-15 16:28:11 -0700255 int idx = 0;
256 for (String s : getSeries()) {
257 value[idx] = get(s);
258 idx++;
259 }
260 return value;
Jian Lib6859e12016-03-01 09:29:24 -0800261 }
262
263 /**
264 * Returns the size of data point.
Jian Lib6859e12016-03-01 09:29:24 -0800265 *
Jian Li15468822016-04-15 16:28:11 -0700266 * @return the size of data point
Jian Lib6859e12016-03-01 09:29:24 -0800267 */
Jian Li15468822016-04-15 16:28:11 -0700268 public int size() {
269 return data.size();
Jian Lib6859e12016-03-01 09:29:24 -0800270 }
Jian Li72f3f102016-04-28 12:40:57 -0700271
272 /**
273 * Returns the value of the data point as a string, using the
274 * formatter appropriate for the series.
275 *
276 * @param series series
277 * @return formatted data point value
278 */
279 public String getAsString(String series) {
280 return get(series).toString();
281 }
282
283 /**
284 * Returns the row as an array of formatted strings.
285 *
286 * @return the string format of data points
287 */
288 public String[] getAsStrings() {
289 List<String> formatted = new ArrayList<>(size());
290 for (String c : seriesArray) {
291 formatted.add(getAsString(c));
292 }
293 return formatted.toArray(new String[formatted.size()]);
294 }
Jian Lib6859e12016-03-01 09:29:24 -0800295 }
296}