package com.linkedin.thirdeye.client.timeseries;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
import org.apache.commons.collections.comparators.ComparableComparator;
import org.apache.commons.lang.ObjectUtils;
import org.joda.time.DateTime;
public class TimeSeriesRow implements Comparable<TimeSeriesRow> {
private final long start;
private final long end;
private final List<String> dimensionNames;
private final List<String> dimensionValues;
private final List<TimeSeriesMetric> metrics;
private static final String DELIM = "\t\t";
private TimeSeriesRow(Builder builder) {
this.start = builder.start.getMillis();
this.end = builder.end.getMillis();
this.dimensionNames = builder.dimensionNames;
this.dimensionValues = builder.dimensionValues;
this.metrics = builder.metrics;
}
public long getStart() {
return start;
}
public long getEnd() {
return end;
}
public List<String> getDimensionNames() {
return dimensionNames;
}
public List<String> getDimensionValues() {
return dimensionValues;
}
public List<TimeSeriesMetric> getMetrics() {
return metrics;
}
@Override
public boolean equals(Object o) {
if (!(o instanceof TimeSeriesRow)) {
return false;
}
TimeSeriesRow ts = (TimeSeriesRow) o;
return Objects.equals(start, ts.getStart())
&& Objects.equals(end, ts.getEnd())
&& Objects.equals(dimensionNames, ts.getDimensionNames())
&& Objects.equals(dimensionValues, ts.getDimensionValues())
&& Objects.equals(metrics, ts.getMetrics());
}
@Override
public int hashCode() {
return Objects.hash(start, end, dimensionNames, dimensionValues, metrics);
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append(start).append(DELIM).append(end).append(DELIM).append(dimensionNames).append(DELIM)
.append(dimensionValues);
for (TimeSeriesMetric metric : metrics) {
sb.append(DELIM).append(metric.getValue());
}
return sb.toString();
}
@Override
public int compareTo(TimeSeriesRow o) {
int startDiff = ObjectUtils.compare(this.start, o.start);
if (startDiff != 0)
return startDiff;
int dimensionNameDiff = compareListOfComparable(this.dimensionNames, o.dimensionNames);
if (dimensionNameDiff != 0)
return dimensionNameDiff;
int dimensionValueDiff = compareListOfComparable(this.dimensionValues, o.dimensionValues);
if (dimensionValueDiff != 0)
return dimensionValueDiff;
return compareListOfComparable(this.metrics, o.metrics);
}
private static <E extends Comparable<E>> int compareListOfComparable(List<E> a, List<E> b) {
if (a == null && b == null) return 0;
if (a == null) return -1;
if (b == null) return 1;
int sizeA = a.size();
int sizeB = b.size();
int sizeDiff = ObjectUtils.compare(sizeA, sizeB);
if (sizeDiff != 0) {
return sizeDiff;
}
for (int i = 0; i < sizeA; i++) {
E comparableA = a.get(i);
E comparableB = b.get(i);
int comparableDiff = ObjectUtils.compare(comparableA, comparableB);
if (comparableDiff != 0) {
return comparableDiff;
}
}
return 0;
}
static class Builder {
private DateTime start;
private DateTime end;
private List<String> dimensionNames = Collections.singletonList("all");
private List<String> dimensionValues = Collections.singletonList("all");
private final List<TimeSeriesMetric> metrics = new ArrayList<>();
public void setStart(DateTime start) {
this.start = start;
}
public void setEnd(DateTime end) {
this.end = end;
}
public void setDimensionNames(List<String> dimensionNames) {
this.dimensionNames = dimensionNames;
}
public void setDimensionValues(List<String> dimensionValues) {
this.dimensionValues = dimensionValues;
}
public void addMetric(String metricName, double value) {
this.metrics.add(new TimeSeriesMetric(metricName, value));
}
public void addMetrics(TimeSeriesMetric... metrics) {
Collections.addAll(this.metrics, metrics);
}
public TimeSeriesRow build() {
return new TimeSeriesRow(this);
}
public void clear() {
setStart(null);
setEnd(null);
setDimensionNames(null);
setDimensionValues(null);
this.metrics.clear();
}
}
public static class TimeSeriesMetric implements Comparable<TimeSeriesMetric> {
private final String metricName;
private final Double value;
public TimeSeriesMetric(String metricName, Double value) {
this.metricName = metricName;
this.value = value;
}
@Override
public int hashCode() {
return Objects.hash(metricName, value);
}
@Override
public boolean equals(Object o) {
if (!(o instanceof TimeSeriesMetric)) {
return false;
}
TimeSeriesMetric ts = (TimeSeriesMetric) o;
return Objects.equals(metricName, ts.getMetricName())
&& Objects.equals(value, ts.getValue());
}
@Override
public int compareTo(TimeSeriesMetric otherMetric) {
// shouldn't ever need to compare by value
return this.metricName.compareTo(otherMetric.metricName);
}
public String getMetricName() {
return metricName;
}
public Double getValue() {
return value;
}
}
}