001    /*
002     * Sonar, open source software quality management tool.
003     * Copyright (C) 2009 SonarSource SA
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 org.apache.commons.lang.builder.ToStringBuilder;
023    import org.sonar.api.BatchExtension;
024    import org.sonar.api.ServerExtension;
025    import org.sonar.api.database.BaseIdentifiable;
026    
027    import javax.persistence.*;
028    
029    /**
030     * @since 1.10
031     */
032    @Table(name = "metrics")
033    @Entity(name = "Metric")
034    public class Metric extends BaseIdentifiable implements ServerExtension, BatchExtension {
035    
036      /**
037       * A metric bigger value means a degradation
038       */
039      public final static int DIRECTION_WORST = -1;
040      /**
041       * A metric bigger value means an improvement
042       */
043      public final static int DIRECTION_BETTER = 1;
044      /**
045       * The metric direction has no meaning
046       */
047      public final static int DIRECTION_NONE = 0;
048    
049      public enum ValueType {
050        INT, FLOAT, PERCENT, BOOL, STRING, MILLISEC, DATA, LEVEL, DISTRIB, RATING
051      }
052    
053      public enum Level {
054        OK("Green"), WARN("Orange"), ERROR("Red");
055    
056        private String colorName;
057    
058        Level(String colorName) {
059          this.colorName = colorName;
060        }
061    
062        public String getColorName() {
063          return colorName;
064        }
065      }
066    
067      public enum Origin {
068        JAV, GUI, WS
069      }
070    
071      @Transient
072      private Formula formula;
073    
074      @Column(name = "name", updatable = false, nullable = false, length = 64)
075      private String key;
076    
077      @Column(name = "description", updatable = true, nullable = true, length = 255)
078      private String description;
079    
080      @Column(name = "val_type", updatable = true, nullable = true)
081      @Enumerated(EnumType.STRING)
082      private ValueType type;
083    
084      @Column(name = "direction", updatable = true, nullable = true)
085      private Integer direction;
086    
087      @Column(name = "domain", updatable = true, nullable = true, length = 60)
088      private String domain;
089    
090      @Column(name = "short_name", updatable = true, nullable = true, length = 64)
091      private String name;
092    
093      @Column(name = "qualitative", updatable = true, nullable = true)
094      private Boolean qualitative = Boolean.FALSE;
095    
096      @Column(name = "user_managed", updatable = true, nullable = true)
097      private Boolean userManaged = Boolean.FALSE;
098    
099      @Column(name = "enabled", updatable = true, nullable = true)
100      private Boolean enabled = Boolean.TRUE;
101    
102      @Column(name = "origin", updatable = true, nullable = true, length = 3)
103      @Enumerated(EnumType.STRING)
104      private Origin origin;
105    
106      @Column(name = "worst_value", updatable = true, nullable = true, precision = 30, scale = 20)
107      private Double worstValue;
108    
109      @Column(name = "best_value", updatable = true, nullable = true, precision = 30, scale = 20)
110      private Double bestValue;
111    
112      @Column(name = "optimized_best_value", updatable = true, nullable = true)
113      private Boolean optimizedBestValue;
114    
115      @Column(name = "hidden", updatable = true, nullable = true)
116      private Boolean hidden = Boolean.FALSE;
117    
118    
119      /**
120       * Creates an empty metric
121       */
122      @Deprecated public Metric() {
123      }
124    
125      /**
126       * Creates a metric based on its key. Shortcut to Metric(key, ValueType.INT)
127       *
128       * @param key the metric key
129       */
130      public Metric(String key) {
131        this(key, ValueType.INT);
132      }
133    
134      /**
135       * Creates a metric based on a key and a type. Shortcut to
136       * Metric(key, key, key, type, -1, Boolean.FALSE, null, false)
137       *
138       * @param key  the key
139       * @param type the type
140       */
141      public Metric(String key, ValueType type) {
142        this(key, key, key, type, -1, Boolean.FALSE, null, false);
143      }
144    
145      public Metric(String key, String name, String description, ValueType type, Integer direction, Boolean qualitative, String domain) {
146        this(key, name, description, type, direction, qualitative, domain, false);
147      }
148    
149      /**
150       * Creates a fully qualified metric. This defaults some values:
151       * <ul>
152       * <li>origin : Origin.JAV</li>
153       * </ul>
154       *
155       * @param key         the metric key
156       * @param name        the metric name
157       * @param description the metric description
158       * @param type        the metric type
159       * @param direction   the metric direction
160       * @param qualitative whether the metric is qualitative
161       * @param domain      the metric domain
162       * @param userManaged whether the metric is user managed
163       */
164      @Deprecated
165      public Metric(String key, String name, String description, ValueType type, Integer direction, Boolean qualitative, String domain, boolean userManaged) {
166        this.key = key;
167        this.description = description;
168        this.type = type;
169        this.direction = direction;
170        this.domain = domain;
171        this.name = name;
172        this.qualitative = qualitative;
173        this.userManaged = userManaged;
174        this.origin = Origin.JAV;
175        if (ValueType.PERCENT.equals(this.type)) {
176          this.bestValue = (direction==DIRECTION_BETTER ? 100.0 : 0.0);
177          this.worstValue = (direction==DIRECTION_BETTER ? 0.0 : 100.0);
178        }
179      }
180    
181      /**
182       * Creates a fully qualified metric. This defaults some values:
183       * <ul>
184       * <li>origin : Origin.JAV</li>
185       * <li>enabled : true</li>
186       * <li>userManaged : true</li>
187       * </ul>
188       *
189       * @param key         the metric key
190       * @param name        the metric name
191       * @param type        the metric type
192       * @param direction   the metric direction
193       * @param qualitative whether the metric is qualitative
194       * @param domain      the metric domain
195       * @param formula     the metric formula
196       */
197      public Metric(String key, String name, ValueType type, Integer direction, Boolean qualitative, String domain, Formula formula) {
198        this.key = key;
199        this.name = name;
200        this.type = type;
201        this.direction = direction;
202        this.domain = domain;
203        this.qualitative = qualitative;
204        this.origin = Origin.JAV;
205        this.enabled = true;
206        this.userManaged = false;
207        this.formula = formula;
208        if (ValueType.PERCENT.equals(this.type)) {
209          this.bestValue = (direction==DIRECTION_BETTER ? 100.0 : 0.0);
210          this.worstValue = (direction==DIRECTION_BETTER ? 0.0 : 100.0);
211        }
212      }
213    
214      /**
215       * @return the metric formula
216       */
217      public Formula getFormula() {
218        return formula;
219      }
220    
221      /**
222       * Sets the metric formula
223       *
224       * @param formula the formula
225       * @return this
226       */
227      public Metric setFormula(Formula formula) {
228        this.formula = formula;
229        return this;
230      }
231    
232      /**
233       * @return wether the metric is qualitative
234       */
235      public Boolean getQualitative() {
236        return qualitative;
237      }
238    
239      /**
240       * Sets whether the metric is qualitative
241       *
242       * @param qualitative whether the metric is qualitative
243       * @return this
244       */
245      public Metric setQualitative(Boolean qualitative) {
246        this.qualitative = qualitative;
247        return this;
248      }
249    
250      /**
251       * @return the metric key
252       */
253      public String getKey() {
254        return key;
255      }
256    
257      /**
258       * Sets the metric key
259       *
260       * @param key the key
261       * @return this
262       */
263      public Metric setKey(String key) {
264        this.key = key;
265        return this;
266      }
267    
268      /**
269       * @return the metric type
270       */
271      public ValueType getType() {
272        return type;
273      }
274    
275      /**
276       * Sets the metric type
277       *
278       * @param type the type
279       * @return this
280       */
281      public Metric setType(ValueType type) {
282        this.type = type;
283        return this;
284      }
285    
286      /**
287       * @return the metric description
288       */
289      public String getDescription() {
290        return description;
291      }
292    
293      /**
294       * Sets the metric description
295       *
296       * @param description the description
297       * @return this
298       */
299      public Metric setDescription(String description) {
300        this.description = description;
301        return this;
302      }
303    
304      /**
305       * @return whether the metric is a managed by the users (manual metric)
306       */
307      public Boolean getUserManaged() {
308        return userManaged;
309      }
310    
311      /**
312       * Sets whether the metric is user managed
313       *
314       * @param userManaged whether the metric is user managed
315       * @return this
316       */
317      public Metric setUserManaged(Boolean userManaged) {
318        this.userManaged = userManaged;
319        return this;
320      }
321    
322      /**
323       * @return whether the metric is enabled
324       */
325      public Boolean getEnabled() {
326        return enabled;
327      }
328    
329      /**
330       * Sets whether the metric is enabled
331       *
332       * @param enabled whether the metric is enabled
333       * @return this
334       */
335      public Metric setEnabled(Boolean enabled) {
336        this.enabled = enabled;
337        return this;
338      }
339    
340      /**
341       * @return the metric direction
342       */
343      public Integer getDirection() {
344        return direction;
345      }
346    
347      /**
348       * Sets the metric direction.
349       *
350       * @param direction the direction
351       */
352      public Metric setDirection(Integer direction) {
353        this.direction = direction;
354        return this;
355      }
356    
357      /**
358       * @return the domain of the metric
359       */
360      public String getDomain() {
361        return domain;
362      }
363    
364      /**
365       * Sets the domain for the metric (General, Complexity...)
366       *
367       * @param domain the domain
368       * @return this
369       */
370      public Metric setDomain(String domain) {
371        this.domain = domain;
372        return this;
373      }
374    
375      /**
376       * @return the metric name
377       */
378      public String getName() {
379        return name;
380      }
381    
382      /**
383       * Sets the metric name
384       *
385       * @param name the name
386       * @return this
387       */
388      public Metric setName(String name) {
389        this.name = name;
390        return this;
391      }
392    
393      /**
394       * @return the origin of the metric - Internal use only
395       */
396      public Origin getOrigin() {
397        return origin;
398      }
399    
400      /**
401       * Set the origin of the metric - Internal use only
402       *
403       * @param origin the origin
404       * @return this
405       */
406      public Metric setOrigin(Origin origin) {
407        this.origin = origin;
408        return this;
409      }
410    
411      public Double getWorstValue() {
412        return worstValue;
413      }
414    
415      public Double getBestValue() {
416        return bestValue;
417      }
418    
419      /**
420       * @return this
421       */
422      public Metric setWorstValue(Double d) {
423        this.worstValue = d;
424        return this;
425      }
426    
427      /**
428       * @param bestValue the best value. It can be null.
429       * @return this
430       */
431      public Metric setBestValue(Double bestValue) {
432        this.bestValue = bestValue;
433        return this;
434      }
435    
436      /**
437       * @return whether the metric is of a numeric type (int, percentage...)
438       */
439      public boolean isNumericType() {
440        return ValueType.INT.equals(type)
441            || ValueType.FLOAT.equals(type)
442            || ValueType.PERCENT.equals(type)
443            || ValueType.BOOL.equals(type)
444            || ValueType.MILLISEC.equals(type)
445            || ValueType.RATING.equals(type);
446      }
447    
448      /**
449       * @return whether the metric is of type data
450       */
451      public boolean isDataType() {
452        return ValueType.DATA.equals(type) || ValueType.DISTRIB.equals(type);
453      }
454    
455      /**
456       * @return whether the metric is of type percentage
457       */
458      public boolean isPercentageType() {
459        return ValueType.PERCENT.equals(type);
460      }
461    
462      public Metric setOptimizedBestValue(Boolean b) {
463        this.optimizedBestValue = b;
464        return this;
465      }
466    
467      public Boolean isOptimizedBestValue() {
468        return optimizedBestValue;
469      }
470    
471      public Boolean isHidden() {
472        return hidden;
473      }
474    
475      public Metric setHidden(Boolean hidden) {
476        this.hidden = hidden;
477        return this;
478      }
479    
480      @Override
481      public int hashCode() {
482        return key.hashCode();
483      }
484    
485      @Override
486      public boolean equals(Object obj) {
487        if (!(obj instanceof Metric)) {
488          return false;
489        }
490        if (this == obj) {
491          return true;
492        }
493        Metric other = (Metric) obj;
494        return key.equals(other.getKey());
495      }
496    
497      @Override
498      public String toString() {
499        return new ToStringBuilder(this)
500            .append("key", key)
501            .append("name", name)
502            .append("type", type)
503            .append("enabled", enabled)
504            .append("qualitative", qualitative)
505            .append("direction", direction)
506            .append("domain", domain)
507            .append("worstValue", worstValue)
508            .append("bestValue", bestValue)
509            .append("optimizedBestValue", optimizedBestValue)
510            .append("hidden", hidden)
511            .toString();
512      }
513    
514      /**
515       * Merge with fields from other metric. All fields are copied, except the id.
516       * @return this
517       */
518      public Metric merge(final Metric with) {
519        this.description = with.description;
520        this.domain = with.domain;
521        this.enabled = with.enabled;
522        this.qualitative = with.qualitative;
523        this.worstValue = with.worstValue;
524        this.bestValue = with.bestValue;
525        this.optimizedBestValue = with.optimizedBestValue;
526        this.direction = with.direction;
527        this.key = with.key;
528        this.type = with.type;
529        this.name = with.name;
530        this.userManaged = with.userManaged;
531        this.origin = with.origin;
532        this.hidden = with.hidden;
533        return this;
534      }
535    }