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
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    
116      /**
117       * Creates an empty metric
118       */
119      @Deprecated public Metric() {
120      }
121    
122      /**
123       * Creates a metric based on its key. Shortcut to Metric(key, ValueType.INT)
124       *
125       * @param key the metric key
126       */
127      public Metric(String key) {
128        this(key, ValueType.INT);
129      }
130    
131      /**
132       * Creates a metric based on a key and a type. Shortcut to
133       * Metric(key, key, key, type, -1, Boolean.FALSE, null, false)
134       *
135       * @param key  the key
136       * @param type the type
137       */
138      public Metric(String key, ValueType type) {
139        this(key, key, key, type, -1, Boolean.FALSE, null, false);
140      }
141    
142      public Metric(String key, String name, String description, ValueType type, Integer direction, Boolean qualitative, String domain) {
143        this(key, name, description, type, direction, qualitative, domain, false);
144      }
145    
146      /**
147       * Creates a fully qualified metric. This defaults some values:
148       * <ul>
149       * <li>origin : Origin.JAV</li>
150       * </ul>
151       *
152       * @param key         the metric key
153       * @param name        the metric name
154       * @param description the metric description
155       * @param type        the metric type
156       * @param direction   the metric direction
157       * @param qualitative whether the metric is qualitative
158       * @param domain      the metric domain
159       * @param userManaged whether the metric is user managed
160       */
161      @Deprecated
162      public Metric(String key, String name, String description, ValueType type, Integer direction, Boolean qualitative, String domain, boolean userManaged) {
163        this.key = key;
164        this.description = description;
165        this.type = type;
166        this.direction = direction;
167        this.domain = domain;
168        this.name = name;
169        this.qualitative = qualitative;
170        this.userManaged = userManaged;
171        this.origin = Origin.JAV;
172        if (ValueType.PERCENT.equals(this.type)) {
173          this.bestValue = (direction==DIRECTION_BETTER ? 100.0 : 0.0);
174          this.worstValue = (direction==DIRECTION_BETTER ? 0.0 : 100.0);
175        }
176      }
177    
178      /**
179       * Creates a fully qualified metric. This defaults some values:
180       * <ul>
181       * <li>origin : Origin.JAV</li>
182       * <li>enabled : true</li>
183       * <li>userManaged : true</li>
184       * </ul>
185       *
186       * @param key         the metric key
187       * @param name        the metric name
188       * @param type        the metric type
189       * @param direction   the metric direction
190       * @param qualitative whether the metric is qualitative
191       * @param domain      the metric domain
192       * @param formula     the metric formula
193       */
194      public Metric(String key, String name, ValueType type, Integer direction, Boolean qualitative, String domain, Formula formula) {
195        this.key = key;
196        this.name = name;
197        this.type = type;
198        this.direction = direction;
199        this.domain = domain;
200        this.qualitative = qualitative;
201        this.origin = Origin.JAV;
202        this.enabled = true;
203        this.userManaged = false;
204        this.formula = formula;
205        if (ValueType.PERCENT.equals(this.type)) {
206          this.bestValue = (direction==DIRECTION_BETTER ? 100.0 : 0.0);
207          this.worstValue = (direction==DIRECTION_BETTER ? 0.0 : 100.0);
208        }
209      }
210    
211      /**
212       * @return the metric formula
213       */
214      public Formula getFormula() {
215        return formula;
216      }
217    
218      /**
219       * Sets the metric formula
220       *
221       * @param formula the formula
222       * @return this
223       */
224      public Metric setFormula(Formula formula) {
225        this.formula = formula;
226        return this;
227      }
228    
229      /**
230       * @return wether the metric is qualitative
231       */
232      public Boolean getQualitative() {
233        return qualitative;
234      }
235    
236      /**
237       * Sets whether the metric is qualitative
238       *
239       * @param qualitative whether the metric is qualitative
240       * @return this
241       */
242      public Metric setQualitative(Boolean qualitative) {
243        this.qualitative = qualitative;
244        return this;
245      }
246    
247      /**
248       * @return the metric key
249       */
250      public String getKey() {
251        return key;
252      }
253    
254      /**
255       * Sets the metric key
256       *
257       * @param key the key
258       * @return this
259       */
260      public Metric setKey(String key) {
261        this.key = key;
262        return this;
263      }
264    
265      /**
266       * @return the metric type
267       */
268      public ValueType getType() {
269        return type;
270      }
271    
272      /**
273       * Sets the metric type
274       *
275       * @param type the type
276       * @return this
277       */
278      public Metric setType(ValueType type) {
279        this.type = type;
280        return this;
281      }
282    
283      /**
284       * @return the metric description
285       */
286      public String getDescription() {
287        return description;
288      }
289    
290      /**
291       * Sets the metric description
292       *
293       * @param description the description
294       * @return this
295       */
296      public Metric setDescription(String description) {
297        this.description = description;
298        return this;
299      }
300    
301      /**
302       * @return whether the metric is a managed by the users (manual metric)
303       */
304      public Boolean getUserManaged() {
305        return userManaged;
306      }
307    
308      /**
309       * Sets whether the metric is user managed
310       *
311       * @param userManaged whether the metric is user managed
312       * @return this
313       */
314      public Metric setUserManaged(Boolean userManaged) {
315        this.userManaged = userManaged;
316        return this;
317      }
318    
319      /**
320       * @return whether the metric is enabled
321       */
322      public Boolean getEnabled() {
323        return enabled;
324      }
325    
326      /**
327       * Sets whether the metric is enabled
328       *
329       * @param enabled whether the metric is enabled
330       * @return this
331       */
332      public Metric setEnabled(Boolean enabled) {
333        this.enabled = enabled;
334        return this;
335      }
336    
337      /**
338       * @return the metric direction
339       */
340      public Integer getDirection() {
341        return direction;
342      }
343    
344      /**
345       * Sets the metric direction.
346       *
347       * @param direction the direction
348       */
349      public Metric setDirection(Integer direction) {
350        this.direction = direction;
351        return this;
352      }
353    
354      /**
355       * @return the domain of the metric
356       */
357      public String getDomain() {
358        return domain;
359      }
360    
361      /**
362       * Sets the domain for the metric (General, Complexity...)
363       *
364       * @param domain the domain
365       * @return this
366       */
367      public Metric setDomain(String domain) {
368        this.domain = domain;
369        return this;
370      }
371    
372      /**
373       * @return the metric name
374       */
375      public String getName() {
376        return name;
377      }
378    
379      /**
380       * Sets the metric name
381       *
382       * @param name the name
383       * @return this
384       */
385      public Metric setName(String name) {
386        this.name = name;
387        return this;
388      }
389    
390      /**
391       * @return the origin of the metric - Internal use only
392       */
393      public Origin getOrigin() {
394        return origin;
395      }
396    
397      /**
398       * Set the origin of the metric - Internal use only
399       *
400       * @param origin the origin
401       * @return this
402       */
403      public Metric setOrigin(Origin origin) {
404        this.origin = origin;
405        return this;
406      }
407    
408      public Double getWorstValue() {
409        return worstValue;
410      }
411    
412      public Double getBestValue() {
413        return bestValue;
414      }
415    
416      /**
417       * @return this
418       */
419      public Metric setWorstValue(Double d) {
420        this.worstValue = d;
421        return this;
422      }
423    
424      /**
425       * @param bestValue the best value. It can be null.
426       * @return this
427       */
428      public Metric setBestValue(Double bestValue) {
429        this.bestValue = bestValue;
430        return this;
431      }
432    
433      /**
434       * @return whether the metric is of a numeric type (int, percentage...)
435       */
436      public boolean isNumericType() {
437        return ValueType.INT.equals(type)
438            || ValueType.FLOAT.equals(type)
439            || ValueType.PERCENT.equals(type)
440            || ValueType.BOOL.equals(type)
441            || ValueType.MILLISEC.equals(type);
442      }
443    
444      /**
445       * @return whether the metric is of type data
446       */
447      public boolean isDataType() {
448        return ValueType.DATA.equals(type) || ValueType.DISTRIB.equals(type);
449      }
450    
451      /**
452       * @return whether the metric is of type percentage
453       */
454      public boolean isPercentageType() {
455        return ValueType.PERCENT.equals(type);
456      }
457    
458      public Metric setOptimizedBestValue(Boolean b) {
459        this.optimizedBestValue = b;
460        return this;
461      }
462    
463      public Boolean isOptimizedBestValue() {
464        return optimizedBestValue;
465      }
466    
467    
468      @Override
469      public int hashCode() {
470        return key.hashCode();
471      }
472    
473      @Override
474      public boolean equals(Object obj) {
475        if (!(obj instanceof Metric)) {
476          return false;
477        }
478        if (this == obj) {
479          return true;
480        }
481        Metric other = (Metric) obj;
482        return key.equals(other.getKey());
483      }
484    
485      @Override
486      public String toString() {
487        return new ToStringBuilder(this)
488            .append("key", key)
489            .append("name", name)
490            .append("type", type)
491            .append("enabled", enabled)
492            .append("qualitative", qualitative)
493            .append("direction", direction)
494            .append("domain", domain)
495            .append("worstValue", worstValue)
496            .append("bestValue", bestValue)
497            .append("optimizedBestValue", optimizedBestValue)
498            .toString();
499      }
500    
501      /**
502       * Merge with fields from other metric. All fields are copied, except the id.
503       * @return this
504       */
505      public Metric merge(final Metric with) {
506        this.description = with.description;
507        this.domain = with.domain;
508        this.enabled = with.enabled;
509        this.qualitative = with.qualitative;
510        this.worstValue = with.worstValue;
511        this.bestValue = with.bestValue;
512        this.optimizedBestValue = with.optimizedBestValue;
513        this.direction = with.direction;
514        this.key = with.key;
515        this.type = with.type;
516        this.name = with.name;
517        this.userManaged = with.userManaged;
518        this.origin = with.origin;
519        return this;
520      }
521    }