001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2008-2012 SonarSource
004     * mailto:contact AT sonarsource DOT com
005     *
006     * Sonar is free software; you can redistribute it and/or
007     * modify it under the terms of the GNU Lesser General Public
008     * License as published by the Free Software Foundation; either
009     * version 3 of the License, or (at your option) any later version.
010     *
011     * Sonar is distributed in the hope that it will be useful,
012     * but WITHOUT ANY WARRANTY; without even the implied warranty of
013     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
014     * Lesser General Public License for more details.
015     *
016     * You should have received a copy of the GNU Lesser General Public
017     * License along with Sonar; if not, write to the Free Software
018     * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02
019     */
020    package org.sonar.api.measures;
021    
022    import com.google.common.annotations.Beta;
023    import org.apache.commons.lang.builder.ReflectionToStringBuilder;
024    import org.sonar.api.qualitymodel.Characteristic;
025    
026    import java.math.BigDecimal;
027    import java.math.RoundingMode;
028    import java.util.Date;
029    
030    /**
031     * A class to handle measures.
032     *
033     * @since 1.10
034     */
035    public class Measure {
036      protected static final int MAX_TEXT_SIZE = 96;
037    
038      /**
039       * Default precision when saving a float type metric
040       */
041      public static final int DEFAULT_PRECISION = 1;
042    
043      private Long id; // for internal use
044      protected String metricKey;
045      protected Metric metric;
046      protected Double value;
047      protected String data;
048      protected String description;
049      protected Metric.Level alertStatus;
050      protected String alertText;
051      protected Integer tendency;
052      protected Date date;
053      protected Double variation1, variation2, variation3, variation4, variation5;
054      protected String url;
055      protected Characteristic characteristic;
056      protected Integer personId;
057      protected PersistenceMode persistenceMode = PersistenceMode.FULL;
058    
059      public Measure(String metricKey) {
060        this.metricKey = metricKey;
061      }
062    
063      /**
064       * Creates a measure with a metric
065       *
066       * @param metric the metric
067       */
068      public Measure(Metric metric) {
069        this.metric = metric;
070        this.metricKey = metric.getKey();
071      }
072    
073      /**
074       * Creates a measure with a metric and a value
075       *
076       * @param metric the metric
077       * @param value  its value
078       */
079      public Measure(Metric metric, Double value) {
080        this.metric = metric;
081        this.metricKey = metric.getKey();
082        setValue(value);
083      }
084    
085      /**
086       * Creates a measure with a metric, a value and a precision for the value
087       *
088       * @param metric    the metric
089       * @param value     its value
090       * @param precision the value precision
091       */
092      public Measure(Metric metric, Double value, int precision) {
093        this.metric = metric;
094        this.metricKey = metric.getKey();
095        setValue(value, precision);
096      }
097    
098      /**
099       * Creates a measure with a metric, a value and a data field
100       *
101       * @param metric the metric
102       * @param value  the value
103       * @param data   the data field
104       */
105      public Measure(Metric metric, Double value, String data) {
106        this.metric = metric;
107        this.metricKey = metric.getKey();
108        setValue(value);
109        setData(data);
110      }
111    
112      /**
113       * * Creates a measure with a metric and a data field
114       *
115       * @param metric the metric
116       * @param data   the data field
117       */
118      public Measure(Metric metric, String data) {
119        this.metric = metric;
120        this.metricKey = metric.getKey();
121        setData(data);
122      }
123    
124      /**
125       * Creates a measure with a metric and an alert level
126       *
127       * @param metric the metric
128       * @param level  the alert level
129       */
130      public Measure(Metric metric, Metric.Level level) {
131        this.metric = metric;
132        this.metricKey = metric.getKey();
133        if (level != null) {
134          this.data = level.toString();
135        }
136      }
137    
138      /**
139       * Creates an empty measure
140       */
141      public Measure() {
142      }
143    
144      /**
145       * Gets the persistence mode of the measure. Default persistence mode is FULL, except when instantiating the measure with a String
146       * parameter.
147       */
148      public PersistenceMode getPersistenceMode() {
149        return persistenceMode;
150      }
151    
152      /**
153       * <p>
154       * Sets the persistence mode of a measure.
155       * </p>
156       * <p>
157       * <b>WARNING : </b>Being able to reuse measures saved in memory is only possible within the same tree. In a multi-module project for
158       * example, a measure save in memory at the module level will not be accessible by the root project. In that case, database should be
159       * used.
160       * </p>
161       *
162       * @param mode the mode
163       * @return the measure object instance
164       */
165      public Measure setPersistenceMode(PersistenceMode mode) {
166        this.persistenceMode = mode;
167        return this;
168      }
169    
170      /**
171       * @return return the measures underlying metric
172       */
173      public Metric getMetric() {
174        return metric;
175      }
176    
177      public String getMetricKey() {
178        return metricKey;
179      }
180    
181      /**
182       * Set the underlying metric
183       *
184       * @param metric the metric
185       * @return the measure object instance
186       */
187      public Measure setMetric(Metric metric) {
188        this.metric = metric;
189        this.metricKey = metric.getKey();
190        return this;
191      }
192    
193      /**
194       * @return transforms and returns the data fields as a level of alert
195       */
196      public Metric.Level getDataAsLevel() {
197        if (data != null) {
198          return Metric.Level.valueOf(data);
199        }
200        return null;
201      }
202    
203      public boolean hasData() {
204        return data != null;
205      }
206    
207      /**
208       * @return the date of the measure, i.e. the date the measure was taken. Used only in TimeMachine queries
209       */
210      public Date getDate() {
211        return date;
212      }
213    
214      /**
215       * Sets the date of the measure - Used only in TimeMachine queries
216       *
217       * @param date the date
218       * @return the measure object instance
219       */
220      public Measure setDate(Date date) {
221        this.date = date;
222        return this;
223      }
224    
225      /**
226       * @return the value of the measure as a double
227       */
228      public Double getValue() {
229        return value;
230      }
231    
232      /**
233       * @return the value of the measure as an int
234       */
235      public Integer getIntValue() {
236        if (value == null) {
237          return null;
238        }
239        return value.intValue();
240      }
241    
242      /**
243       * Sets the measure value with the default precision of 1
244       *
245       * @param v the measure value
246       * @return the measure object instance
247       */
248      public Measure setValue(Double v) {
249        return setValue(v, DEFAULT_PRECISION);
250      }
251    
252      /**
253       * Sets the measure value as an int
254       *
255       * @param i the value
256       * @return the measure object instance
257       */
258      public Measure setIntValue(Integer i) {
259        if (i == null) {
260          this.value = null;
261        } else {
262          this.value = Double.valueOf(i);
263        }
264        return this;
265      }
266    
267      /**
268       * Sets the measure value with a given precision
269       *
270       * @param v         the measure value
271       * @param precision the measure value precision
272       * @return the measure object instance
273       */
274      public Measure setValue(Double v, int precision) {
275        if (v != null) {
276          if (Double.isNaN(v)) {
277            throw new IllegalArgumentException("Measure value can not be NaN");
278          }
279          this.value = scaleValue(v, precision);
280        } else {
281          this.value = null;
282        }
283        return this;
284      }
285    
286      private double scaleValue(double value, int scale) {
287        BigDecimal bd = BigDecimal.valueOf(value);
288        return bd.setScale(scale, RoundingMode.HALF_UP).doubleValue();
289      }
290    
291      /**
292       * @return the data field of the measure
293       */
294      public String getData() {
295        return data;
296      }
297    
298      /**
299       * Sets the data field of the measure.
300       *
301       * @param s the data
302       * @return the measure object instance
303       */
304      public Measure setData(String s) {
305        this.data = s;
306        return this;
307      }
308    
309      /**
310       * Sets an alert level as the data field
311       *
312       * @param level the alert level
313       * @return the measure object instance
314       */
315      public Measure setData(Metric.Level level) {
316        if (level == null) {
317          this.data = null;
318        } else {
319          this.data = level.toString();
320        }
321        return this;
322      }
323    
324      /**
325       * @since 2.7
326       */
327      public Measure unsetData() {
328        this.data = null;
329        return this;
330      }
331    
332      /**
333       * @return the description of the measure
334       */
335      public String getDescription() {
336        return description;
337      }
338    
339      /**
340       * Sets the measure description
341       *
342       * @param description the description
343       * @return the measure object instance
344       */
345      public Measure setDescription(String description) {
346        this.description = description;
347        return this;
348      }
349    
350      /**
351       * @return the alert status of the measure
352       */
353      public Metric.Level getAlertStatus() {
354        return alertStatus;
355      }
356    
357      /**
358       * Set the alert status of the measure
359       *
360       * @param status the status
361       * @return the measure object instance
362       */
363      public Measure setAlertStatus(Metric.Level status) {
364        this.alertStatus = status;
365        return this;
366      }
367    
368      /**
369       * @return the text associated to the alert on the measure
370       */
371      public String getAlertText() {
372        return alertText;
373      }
374    
375      /**
376       * Sets the text associated to the alert on the measure
377       *
378       * @param alertText the text
379       * @return the measure object instance
380       */
381      public Measure setAlertText(String alertText) {
382        this.alertText = alertText;
383        return this;
384      }
385    
386      /**
387       * Gets the measure tendency
388       *
389       * @return the tendency
390       */
391      public Integer getTendency() {
392        return tendency;
393      }
394    
395      /**
396       * Sets the tendency for the measure - Internal use only
397       *
398       * @param tendency the tendency
399       * @return the measure object instance
400       */
401      public Measure setTendency(Integer tendency) {
402        this.tendency = tendency;
403        return this;
404      }
405    
406      /**
407       * @return the measure id - Internal use only
408       */
409      public Long getId() {
410        return id;
411      }
412    
413      /**
414       * Sets the measure id - Internal use only
415       *
416       * @param id the id
417       * @return the measure object instance
418       */
419      public Measure setId(Long id) {
420        this.id = id;
421        return this;
422      }
423    
424      /**
425       * @return the first variation value
426       * @since 2.5
427       */
428      public Double getVariation1() {
429        return variation1;
430      }
431    
432      /**
433       * Internal use only
434       *
435       * @since 2.5
436       */
437      public Measure setVariation1(Double d) {
438        this.variation1 = d;
439        return this;
440      }
441    
442      /**
443       * @return the second variation value
444       * @since 2.5
445       */
446      public Double getVariation2() {
447        return variation2;
448      }
449    
450      /**
451       * Internal use only
452       *
453       * @since 2.5
454       */
455      public Measure setVariation2(Double d) {
456        this.variation2 = d;
457        return this;
458      }
459    
460      /**
461       * @return the third variation value
462       * @since 2.5
463       */
464      public Double getVariation3() {
465        return variation3;
466      }
467    
468      /**
469       * Internal use only
470       *
471       * @since 2.5
472       */
473      public Measure setVariation3(Double d) {
474        this.variation3 = d;
475        return this;
476      }
477    
478      /**
479       * @return the third variation value
480       * @since 2.5
481       */
482      public Double getVariation4() {
483        return variation4;
484      }
485    
486      /**
487       * Internal use only
488       *
489       * @since 2.5
490       */
491      public Measure setVariation4(Double d) {
492        this.variation4 = d;
493        return this;
494      }
495    
496      /**
497       * @return the third variation value
498       * @since 2.5
499       */
500      public Double getVariation5() {
501        return variation5;
502      }
503    
504      /**
505       * Internal use only
506       *
507       * @since 2.5
508       */
509      public Measure setVariation5(Double d) {
510        this.variation5 = d;
511        return this;
512      }
513    
514      /**
515       * @since 2.5
516       */
517      public Double getVariation(int index) {
518        switch (index) {
519          case 1:
520            return variation1;
521          case 2:
522            return variation2;
523          case 3:
524            return variation3;
525          case 4:
526            return variation4;
527          case 5:
528            return variation5;
529          default:
530            throw new IndexOutOfBoundsException("Index should be in range from 1 to 5");
531        }
532      }
533    
534      /**
535       * Internal use only
536       *
537       * @since 2.5
538       */
539      public Measure setVariation(int index, Double d) {
540        switch (index) {
541          case 1:
542            variation1 = d;
543            break;
544          case 2:
545            variation2 = d;
546            break;
547          case 3:
548            variation3 = d;
549            break;
550          case 4:
551            variation4 = d;
552            break;
553          case 5:
554            variation5 = d;
555            break;
556          default:
557            throw new IndexOutOfBoundsException("Index should be in range from 1 to 5");
558        }
559        return this;
560      }
561    
562      /**
563       * @return the url of the measure
564       */
565      public String getUrl() {
566        return url;
567      }
568    
569      /**
570       * Sets the URL of the measure
571       *
572       * @param url the url
573       * @return the measure object instance
574       */
575      public Measure setUrl(String url) {
576        this.url = url;
577        return this;
578      }
579    
580      /**
581       * @since 2.3
582       */
583      public final Characteristic getCharacteristic() {
584        return characteristic;
585      }
586    
587      /**
588       * @since 2.3
589       */
590      public final Measure setCharacteristic(Characteristic characteristic) {
591        this.characteristic = characteristic;
592        return this;
593      }
594    
595      /**
596       * @since 2.14
597       */
598      @Beta
599      public Integer getPersonId() {
600        return personId;
601      }
602    
603      /**
604       * @since 2.14
605       */
606      @Beta
607      public Measure setPersonId(Integer i) {
608        this.personId = i;
609        return this;
610      }
611    
612      @Override
613      public boolean equals(Object o) {
614        if (this == o) {
615          return true;
616        }
617        if (o == null || getClass() != o.getClass()) {
618          return false;
619        }
620    
621        Measure measure = (Measure) o;
622        if (metricKey != null ? !metricKey.equals(measure.metricKey) : measure.metricKey != null) {
623          return false;
624        }
625        if (characteristic != null ? !characteristic.equals(measure.characteristic) : measure.characteristic != null) {
626          return false;
627        }
628        if (personId != null ? !personId.equals(measure.personId) : measure.personId != null) {
629          return false;
630        }
631        return true;
632      }
633    
634      @Override
635      public int hashCode() {
636        int result = metricKey != null ? metricKey.hashCode() : 0;
637        result = 31 * result + (characteristic != null ? characteristic.hashCode() : 0);
638        result = 31 * result + (personId != null ? personId.hashCode() : 0);
639        return result;
640      }
641    
642      @Override
643      public String toString() {
644        return ReflectionToStringBuilder.toString(this);
645      }
646    }