1 // This file is part of OpenTSDB.
2 // Copyright (C) 2015  The OpenTSDB Authors.
3 //
4 // This program is free software: you can redistribute it and/or modify it
5 // under the terms of the GNU Lesser General Public License as published by
6 // the Free Software Foundation, either version 2.1 of the License, or (at your
7 // option) any later version.  This program is distributed in the hope that it
8 // will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty
9 // of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser
10 // General Public License for more details.  You should have received a copy
11 // of the GNU Lesser General Public License along with this program.  If not,
12 // see <http://www.gnu.org/licenses/>.
13 package net.opentsdb.query.pojo;
14 
15 import java.util.NoSuchElementException;
16 
17 import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
18 import com.fasterxml.jackson.annotation.JsonProperty;
19 import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
20 import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
21 import com.google.common.base.Objects;
22 
23 import net.opentsdb.core.Aggregators;
24 import net.opentsdb.query.expression.NumericFillPolicy;
25 import net.opentsdb.utils.DateTime;
26 
27 /**
28  * Pojo builder class used for serdes of a metric component of a query
29  * @since 2.3
30  */
31 @JsonDeserialize(builder = Metric.Builder.class)
32 public class Metric extends Validatable {
33   /** The name of the metric */
34   private String metric;
35 
36   /** An ID for the metric */
37   private String id;
38 
39   /** The ID of a filter set */
40   private String filter;
41 
42   /** An optional time offset for time over time expressions */
43   private String time_offset;
44 
45   /** An optional aggregation override for the metric */
46   private String aggregator;
47 
48   /** A fill policy for dealing with missing values in the metric */
49   private NumericFillPolicy fill_policy;
50 
51   /**
52    * Default ctor
53    * @param builder The builder to pull values from
54    */
Metric(Builder builder)55   public Metric(Builder builder) {
56     metric = builder.metric;
57     id = builder.id;
58     filter = builder.filter;
59     time_offset = builder.timeOffset;
60     aggregator = builder.aggregator;
61     fill_policy = builder.fillPolicy;
62   }
63 
64   /** @return the name of the metric */
getMetric()65   public String getMetric() {
66     return metric;
67   }
68 
69   /** @return an ID for the metric */
getId()70   public String getId() {
71     return id;
72   }
73 
74   /** @return the ID of a filter set */
getFilter()75   public String getFilter() {
76     return filter;
77   }
78 
79   /** @return an optional time offset for time over time expressions */
getTimeOffset()80   public String getTimeOffset() {
81     return time_offset;
82   }
83 
84   /** @return an optional aggregation override for the metric */
getAggregator()85   public String getAggregator() {
86     return aggregator;
87   }
88 
89   /** @return a fill policy for dealing with missing values in the metric */
getFillPolicy()90   public NumericFillPolicy getFillPolicy() {
91     return fill_policy;
92   }
93 
94   /** @return A new builder for the metric */
Builder()95   public static Builder Builder() {
96     return new Builder();
97   }
98 
99   /** Validates the metric
100    * @throws IllegalArgumentException if one or more parameters were invalid
101    */
validate()102   public void validate() {
103     if (metric == null || metric.isEmpty()) {
104       throw new IllegalArgumentException("missing or empty metric");
105     }
106 
107     if (id == null || id.isEmpty()) {
108       throw new IllegalArgumentException("missing or empty id");
109     }
110     Query.validateId(id);
111 
112     if (time_offset != null) {
113       DateTime.parseDateTimeString(time_offset, null);
114     }
115 
116     if (aggregator != null && !aggregator.isEmpty()) {
117       try {
118         Aggregators.get(aggregator.toLowerCase());
119       } catch (final NoSuchElementException e) {
120         throw new IllegalArgumentException("Invalid aggregator");
121       }
122     }
123 
124     if (fill_policy != null) {
125       fill_policy.validate();
126     }
127   }
128 
129   @Override
equals(final Object o)130   public boolean equals(final Object o) {
131     if (this == o)
132       return true;
133     if (o == null || getClass() != o.getClass())
134       return false;
135 
136     final Metric that = (Metric) o;
137 
138     return Objects.equal(that.filter, filter)
139         && Objects.equal(that.id, id)
140         && Objects.equal(that.metric, metric)
141         && Objects.equal(that.time_offset, time_offset)
142         && Objects.equal(that.aggregator, aggregator)
143         && Objects.equal(that.fill_policy, fill_policy);
144   }
145 
146   @Override
hashCode()147   public int hashCode() {
148     return Objects.hashCode(metric, id, filter, time_offset, aggregator,
149         fill_policy);
150   }
151 
152   /**
153    * A builder for a metric component of a query
154    */
155   @JsonIgnoreProperties(ignoreUnknown = true)
156   @JsonPOJOBuilder(buildMethodName = "build", withPrefix = "")
157   public static final class Builder {
158     @JsonProperty
159     private String metric;
160     @JsonProperty
161     private String id;
162     @JsonProperty
163     private String filter;
164     @JsonProperty
165     private String timeOffset;
166     @JsonProperty
167     private String aggregator;
168     @JsonProperty
169     private NumericFillPolicy fillPolicy;
170 
setMetric(String metric)171     public Builder setMetric(String metric) {
172       this.metric = metric;
173       return this;
174     }
175 
setId(String id)176     public Builder setId(String id) {
177       Query.validateId(id);
178       this.id = id;
179       return this;
180     }
181 
setFilter(String filter)182     public Builder setFilter(String filter) {
183       this.filter = filter;
184       return this;
185     }
186 
setTimeOffset(String time_offset)187     public Builder setTimeOffset(String time_offset) {
188       this.timeOffset = time_offset;
189       return this;
190     }
191 
setAggregator(String aggregator)192     public Builder setAggregator(String aggregator) {
193       this.aggregator = aggregator;
194       return this;
195     }
196 
setFillPolicy(NumericFillPolicy fill_policy)197     public Builder setFillPolicy(NumericFillPolicy fill_policy) {
198       this.fillPolicy = fill_policy;
199       return this;
200     }
201 
build()202     public Metric build() {
203       return new Metric(this);
204     }
205   }
206 }
207