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