blob: 40c3028fcb709091400d553fe65ae855d0ac0a7b [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
38 * is to create an empty chart, add data points (by consulting the business model),
39 * and produce the list of data points which contain a label and a set of data
40 * values for all serials.
41 */
42public class ChartModel {
43
Jian Li15468822016-04-15 16:28:11 -070044 private final Set<String> seriesSet;
45 private final String[] seriesArray;
46 private final List<Long> labels = Lists.newArrayList();
47 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 Li15468822016-04-15 16:28:11 -070097 * @return the data point, for chaining
Jian Lib6859e12016-03-01 09:29:24 -080098 */
Jian Li15468822016-04-15 16:28:11 -070099 public DataPoint addDataPoint(Long label) {
100 DataPoint dp = new DataPoint();
101 labels.add(label);
102 dataPoints.add(dp);
103 return dp;
Jian Lib6859e12016-03-01 09:29:24 -0800104 }
105
106 /**
107 * Returns all of series.
108 *
109 * @return an array of series
110 */
111 public String[] getSeries() {
Jian Li15468822016-04-15 16:28:11 -0700112 return seriesArray;
Jian Lib6859e12016-03-01 09:29:24 -0800113 }
114
115 /**
Jian Li15468822016-04-15 16:28:11 -0700116 * Returns all of data points in order.
Jian Lib6859e12016-03-01 09:29:24 -0800117 *
118 * @return an array of data points
119 */
120 public DataPoint[] getDataPoints() {
Jian Li15468822016-04-15 16:28:11 -0700121 return dataPoints.toArray(new DataPoint[dataPoints.size()]);
122 }
123
124 /**
125 * Returns all of labels in order.
126 *
127 * @return an array of labels
128 */
129 public Object[] getLabels() {
130 return labels.toArray(new Long[labels.size()]);
131 }
132
133 /**
134 * Returns the number of data points in this chart model.
135 *
136 * @return number of data points
137 */
138 public int dataPointCount() {
139 return dataPoints.size();
Jian Lib6859e12016-03-01 09:29:24 -0800140 }
141
142 /**
143 * Returns the last element inside all of data points.
144 *
145 * @return data point
146 */
147 public DataPoint getLastDataPoint() {
Jian Li15468822016-04-15 16:28:11 -0700148 return dataPoints.get(dataPoints.size() - 1);
Jian Lib6859e12016-03-01 09:29:24 -0800149 }
150
151 /**
Jian Li1077dd72016-04-26 11:10:20 -0700152 * Inserts a new annotation.
153 *
154 * @param key key of annotation
155 * @param value value of annotation
156 */
157 public void addAnnotation(String key, Object value) {
158 annotations.put(key, new Annot(key, value));
159 }
160
161 /**
162 * Returns the annotations in this chart.
163 *
164 * @return annotations
165 */
166 public Collection<Annot> getAnnotations() {
167 return new ArrayList<>(annotations.values());
168 }
169
170 /**
171 * Model of an annotation.
172 */
173 public class Annot {
174 private final String key;
175 private final Object value;
176
177 /**
178 * Constructs an annotation with the given key and value.
179 *
180 * @param key the key
181 * @param value the value
182 */
183 public Annot(String key, Object value) {
184 this.key = key;
185 this.value = value;
186 }
187
188 /**
189 * Returns the annotation's key.
190 *
191 * @return key
192 */
193 public String key() {
194 return key;
195 }
196
197 /**
198 * Returns the annotation's value.
199 *
200 * @return value
201 */
202 public Object value() {
203 return value;
204 }
205
206 /**
207 * Returns the value as a string.
208 * This default implementation uses the value's toString() method.
209 *
210 * @return the value as a string
211 */
212 public String valueAsString() {
213 return value.toString();
214 }
215 }
216
217 /**
Jian Lib6859e12016-03-01 09:29:24 -0800218 * A class of data point.
219 */
220 public class DataPoint {
221 // values for all series
Jian Li15468822016-04-15 16:28:11 -0700222 private final Map<String, Double> data = Maps.newHashMap();
Jian Lib6859e12016-03-01 09:29:24 -0800223
224 /**
Jian Li15468822016-04-15 16:28:11 -0700225 * Sets the data value for the given series of this data point.
Jian Lib6859e12016-03-01 09:29:24 -0800226 *
Jian Li15468822016-04-15 16:28:11 -0700227 * @param series series name
Jian Li1077dd72016-04-26 11:10:20 -0700228 * @param value value to set
Jian Li15468822016-04-15 16:28:11 -0700229 * @return self, for chaining
Jian Lib6859e12016-03-01 09:29:24 -0800230 */
Jian Li15468822016-04-15 16:28:11 -0700231 public DataPoint data(String series, Double value) {
232 checkSeries(series);
233 data.put(series, value);
234 return this;
Jian Lib6859e12016-03-01 09:29:24 -0800235 }
236
237 /**
Jian Li15468822016-04-15 16:28:11 -0700238 * Returns the data value with the given series for this data point.
Jian Lib6859e12016-03-01 09:29:24 -0800239 *
Jian Li15468822016-04-15 16:28:11 -0700240 * @return data value
Jian Lib6859e12016-03-01 09:29:24 -0800241 */
Jian Li15468822016-04-15 16:28:11 -0700242 public Double get(String series) {
243 return data.get(series);
244 }
245
246 /**
247 * Return the data value with the same order of series.
248 *
249 * @return an array of ordered data values
250 */
251 public Double[] getAll() {
252 Double[] value = new Double[getSeries().length];
253 int idx = 0;
254 for (String s : getSeries()) {
255 value[idx] = get(s);
256 idx++;
257 }
258 return value;
Jian Lib6859e12016-03-01 09:29:24 -0800259 }
260
261 /**
262 * Returns the size of data point.
Jian Lib6859e12016-03-01 09:29:24 -0800263 *
Jian Li15468822016-04-15 16:28:11 -0700264 * @return the size of data point
Jian Lib6859e12016-03-01 09:29:24 -0800265 */
Jian Li15468822016-04-15 16:28:11 -0700266 public int size() {
267 return data.size();
Jian Lib6859e12016-03-01 09:29:24 -0800268 }
269 }
270}