001 /*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2011 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 org.apache.commons.lang.StringUtils;
023 import org.apache.commons.lang.builder.ToStringBuilder;
024 import org.sonar.api.BatchExtension;
025 import org.sonar.api.ServerExtension;
026
027 import javax.persistence.*;
028
029 /**
030 * @since 1.10
031 */
032 @Table(name = "metrics")
033 @Entity(name = "Metric")
034 public class Metric 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 @Id
072 @Column(name = "id")
073 @GeneratedValue
074 private Integer id;
075
076 @Transient
077 private Formula formula;
078
079 @Column(name = "name", updatable = false, nullable = false, length = 64)
080 private String key;
081
082 @Column(name = "description", updatable = true, nullable = true, length = 255)
083 private String description;
084
085 @Column(name = "val_type", updatable = true, nullable = true)
086 @Enumerated(EnumType.STRING)
087 private ValueType type;
088
089 @Column(name = "direction", updatable = true, nullable = true)
090 private Integer direction;
091
092 @Column(name = "domain", updatable = true, nullable = true, length = 60)
093 private String domain;
094
095 @Column(name = "short_name", updatable = true, nullable = true, length = 64)
096 private String name;
097
098 @Column(name = "qualitative", updatable = true, nullable = true)
099 private Boolean qualitative = Boolean.FALSE;
100
101 @Column(name = "user_managed", updatable = true, nullable = true)
102 private Boolean userManaged = Boolean.FALSE;
103
104 @Column(name = "enabled", updatable = true, nullable = true)
105 private Boolean enabled = Boolean.TRUE;
106
107 @Column(name = "origin", updatable = true, nullable = true, length = 3)
108 @Enumerated(EnumType.STRING)
109 private Origin origin = Origin.JAV;
110
111 @Column(name = "worst_value", updatable = true, nullable = true, precision = 30, scale = 20)
112 private Double worstValue;
113
114 @Column(name = "best_value", updatable = true, nullable = true, precision = 30, scale = 20)
115 private Double bestValue;
116
117 @Column(name = "optimized_best_value", updatable = true, nullable = true)
118 private Boolean optimizedBestValue;
119
120 @Column(name = "hidden", updatable = true, nullable = true)
121 private Boolean hidden = Boolean.FALSE;
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 * @deprecated since 2.7 use the Builder factory.
135 */
136 @Deprecated
137 public Metric(String key) {
138 this(key, ValueType.INT);
139 }
140
141 /**
142 * Creates a metric based on a key and a type. Shortcut to
143 * Metric(key, key, key, type, -1, Boolean.FALSE, null, false)
144 *
145 * @param key the key
146 * @param type the type
147 * @deprecated since 2.7 use the Builder factory.
148 */
149 @Deprecated
150 public Metric(String key, ValueType type) {
151 this(key, key, key, type, -1, Boolean.FALSE, null, false);
152 }
153
154 /**
155 * @deprecated since 2.7 use the Builder factory.
156 */
157 @Deprecated
158 public Metric(String key, String name, String description, ValueType type, Integer direction, Boolean qualitative, String domain) {
159 this(key, name, description, type, direction, qualitative, domain, false);
160 }
161
162 /**
163 * Creates a fully qualified metric. This defaults some values:
164 * <ul>
165 * <li>origin : Origin.JAV</li>
166 * </ul>
167 *
168 * @param key the metric key
169 * @param name the metric name
170 * @param description the metric description
171 * @param type the metric type
172 * @param direction the metric direction
173 * @param qualitative whether the metric is qualitative
174 * @param domain the metric domain
175 * @param userManaged whether the metric is user managed
176 * @deprecated since 2.7 use the Builder factory.
177 */
178 @Deprecated
179 public Metric(String key, String name, String description, ValueType type, Integer direction, Boolean qualitative, String domain, boolean userManaged) {
180 this.key = key;
181 this.description = description;
182 this.type = type;
183 this.direction = direction;
184 this.domain = domain;
185 this.name = name;
186 this.qualitative = qualitative;
187 this.userManaged = userManaged;
188 this.origin = Origin.JAV;
189 if (ValueType.PERCENT.equals(this.type)) {
190 this.bestValue = (direction == DIRECTION_BETTER ? 100.0 : 0.0);
191 this.worstValue = (direction == DIRECTION_BETTER ? 0.0 : 100.0);
192 }
193 }
194
195 /**
196 * Creates a fully qualified metric. This defaults some values:
197 * <ul>
198 * <li>origin : Origin.JAV</li>
199 * <li>enabled : true</li>
200 * <li>userManaged : true</li>
201 * </ul>
202 *
203 * @param key the metric key
204 * @param name the metric name
205 * @param type the metric type
206 * @param direction the metric direction
207 * @param qualitative whether the metric is qualitative
208 * @param domain the metric domain
209 * @param formula the metric formula
210 * @deprecated since 2.7 use the Builder factory.
211 */
212 @Deprecated
213 public Metric(String key, String name, ValueType type, Integer direction, Boolean qualitative, String domain, Formula formula) {
214 this.key = key;
215 this.name = name;
216 this.type = type;
217 this.direction = direction;
218 this.domain = domain;
219 this.qualitative = qualitative;
220 this.origin = Origin.JAV;
221 this.enabled = true;
222 this.userManaged = false;
223 this.formula = formula;
224 if (ValueType.PERCENT.equals(this.type)) {
225 this.bestValue = (direction == DIRECTION_BETTER ? 100.0 : 0.0);
226 this.worstValue = (direction == DIRECTION_BETTER ? 0.0 : 100.0);
227 }
228 }
229
230 private Metric(String key, String name, ValueType type, String description, Integer direction, String domain, Boolean qualitative, Double worstValue, Double bestValue, Boolean optimizedBestValue, Boolean hidden, Formula formula) {
231 this.key = key;
232 this.name = name;
233 this.description = description;
234 this.type = type;
235 this.direction = direction;
236 this.domain = domain;
237 this.qualitative = qualitative;
238 this.userManaged = Boolean.FALSE;
239 this.enabled = Boolean.TRUE;
240 this.worstValue = worstValue;
241 this.optimizedBestValue = optimizedBestValue;
242 this.bestValue = bestValue;
243 this.hidden = hidden;
244 this.formula = formula;
245 }
246
247 /**
248 * For internal use only
249 */
250 public Integer getId() {
251 return id;
252 }
253
254 /**
255 * For internal use only
256 */
257 public Metric setId(Integer id) {
258 this.id = id;
259 return this;
260 }
261
262
263 /**
264 * @return the metric formula
265 */
266 public Formula getFormula() {
267 return formula;
268 }
269
270 /**
271 * Sets the metric formula
272 *
273 * @param formula the formula
274 * @return this
275 */
276 public Metric setFormula(Formula formula) {
277 this.formula = formula;
278 return this;
279 }
280
281 /**
282 * @return wether the metric is qualitative
283 */
284 public Boolean getQualitative() {
285 return qualitative;
286 }
287
288 /**
289 * Sets whether the metric is qualitative
290 *
291 * @param qualitative whether the metric is qualitative
292 * @return this
293 */
294 public Metric setQualitative(Boolean qualitative) {
295 this.qualitative = qualitative;
296 return this;
297 }
298
299 /**
300 * @return the metric key
301 */
302 public String getKey() {
303 return key;
304 }
305
306 /**
307 * Sets the metric key
308 *
309 * @param key the key
310 * @return this
311 */
312 public Metric setKey(String key) {
313 this.key = key;
314 return this;
315 }
316
317 /**
318 * @return the metric type
319 */
320 public ValueType getType() {
321 return type;
322 }
323
324 /**
325 * Sets the metric type
326 *
327 * @param type the type
328 * @return this
329 */
330 public Metric setType(ValueType type) {
331 this.type = type;
332 return this;
333 }
334
335 /**
336 * @return the metric description
337 */
338 public String getDescription() {
339 return description;
340 }
341
342 /**
343 * Sets the metric description
344 *
345 * @param description the description
346 * @return this
347 */
348 public Metric setDescription(String description) {
349 this.description = description;
350 return this;
351 }
352
353 /**
354 * @return whether the metric is a managed by the users (manual metric)
355 */
356 public Boolean getUserManaged() {
357 return userManaged;
358 }
359
360 /**
361 * Sets whether the metric is user managed
362 *
363 * @param userManaged whether the metric is user managed
364 * @return this
365 */
366 public Metric setUserManaged(Boolean userManaged) {
367 this.userManaged = userManaged;
368 return this;
369 }
370
371 /**
372 * @return whether the metric is enabled
373 */
374 public Boolean getEnabled() {
375 return enabled;
376 }
377
378 /**
379 * Sets whether the metric is enabled
380 *
381 * @param enabled whether the metric is enabled
382 * @return this
383 */
384 public Metric setEnabled(Boolean enabled) {
385 this.enabled = enabled;
386 return this;
387 }
388
389 /**
390 * @return the metric direction
391 */
392 public Integer getDirection() {
393 return direction;
394 }
395
396 /**
397 * Sets the metric direction.
398 *
399 * @param direction the direction
400 */
401 public Metric setDirection(Integer direction) {
402 this.direction = direction;
403 return this;
404 }
405
406 /**
407 * @return the domain of the metric
408 */
409 public String getDomain() {
410 return domain;
411 }
412
413 /**
414 * Sets the domain for the metric (General, Complexity...)
415 *
416 * @param domain the domain
417 * @return this
418 */
419 public Metric setDomain(String domain) {
420 this.domain = domain;
421 return this;
422 }
423
424 /**
425 * @return the metric name
426 */
427 public String getName() {
428 return name;
429 }
430
431 /**
432 * Sets the metric name
433 *
434 * @param name the name
435 * @return this
436 */
437 public Metric setName(String name) {
438 this.name = name;
439 return this;
440 }
441
442 /**
443 * @return the origin of the metric - Internal use only
444 */
445 public Origin getOrigin() {
446 return origin;
447 }
448
449 /**
450 * Set the origin of the metric - Internal use only
451 *
452 * @param origin the origin
453 * @return this
454 */
455 public Metric setOrigin(Origin origin) {
456 this.origin = origin;
457 return this;
458 }
459
460 public Double getWorstValue() {
461 return worstValue;
462 }
463
464 public Double getBestValue() {
465 return bestValue;
466 }
467
468 /**
469 * @return this
470 */
471 public Metric setWorstValue(Double d) {
472 this.worstValue = d;
473 return this;
474 }
475
476 /**
477 * @param bestValue the best value. It can be null.
478 * @return this
479 */
480 public Metric setBestValue(Double bestValue) {
481 this.bestValue = bestValue;
482 return this;
483 }
484
485 /**
486 * @return whether the metric is of a numeric type (int, percentage...)
487 */
488 public boolean isNumericType() {
489 return ValueType.INT.equals(type)
490 || ValueType.FLOAT.equals(type)
491 || ValueType.PERCENT.equals(type)
492 || ValueType.BOOL.equals(type)
493 || ValueType.MILLISEC.equals(type)
494 || ValueType.RATING.equals(type);
495 }
496
497 /**
498 * @return whether the metric is of type data
499 */
500 public boolean isDataType() {
501 return ValueType.DATA.equals(type) || ValueType.DISTRIB.equals(type);
502 }
503
504 /**
505 * @return whether the metric is of type percentage
506 */
507 public boolean isPercentageType() {
508 return ValueType.PERCENT.equals(type);
509 }
510
511 public Metric setOptimizedBestValue(Boolean b) {
512 this.optimizedBestValue = b;
513 return this;
514 }
515
516 public Boolean isOptimizedBestValue() {
517 return optimizedBestValue;
518 }
519
520 public Boolean isHidden() {
521 return hidden;
522 }
523
524 public Metric setHidden(Boolean hidden) {
525 this.hidden = hidden;
526 return this;
527 }
528
529 @Override
530 public int hashCode() {
531 return key.hashCode();
532 }
533
534 @Override
535 public boolean equals(Object obj) {
536 if (!(obj instanceof Metric)) {
537 return false;
538 }
539 if (this == obj) {
540 return true;
541 }
542 Metric other = (Metric) obj;
543 return key.equals(other.getKey());
544 }
545
546 @Override
547 public String toString() {
548 return new ToStringBuilder(this)
549 .append("key", key)
550 .append("name", name)
551 .append("type", type)
552 .append("enabled", enabled)
553 .append("qualitative", qualitative)
554 .append("direction", direction)
555 .append("domain", domain)
556 .append("worstValue", worstValue)
557 .append("bestValue", bestValue)
558 .append("optimizedBestValue", optimizedBestValue)
559 .append("hidden", hidden)
560 .toString();
561 }
562
563 /**
564 * Merge with fields from other metric. All fields are copied, except the id.
565 *
566 * @return this
567 */
568 public Metric merge(final Metric with) {
569 this.description = with.description;
570 this.domain = with.domain;
571 this.enabled = with.enabled;
572 this.qualitative = with.qualitative;
573 this.worstValue = with.worstValue;
574 this.bestValue = with.bestValue;
575 this.optimizedBestValue = with.optimizedBestValue;
576 this.direction = with.direction;
577 this.key = with.key;
578 this.type = with.type;
579 this.name = with.name;
580 this.userManaged = with.userManaged;
581 this.origin = with.origin;
582 this.hidden = with.hidden;
583 return this;
584 }
585
586 public static final class Builder {
587 private String key;
588 private Metric.ValueType type;
589 private String name;
590 private String description;
591 private Integer direction = DIRECTION_NONE;
592 private Boolean qualitative = Boolean.FALSE;
593 private String domain = null;
594 private Formula formula;
595 private Double worstValue;
596 private Double bestValue;
597 private boolean optimizedBestValue = false;
598 private boolean hidden = false;
599
600 public Builder(String key, String name, ValueType type) {
601 if (StringUtils.isBlank(key)) {
602 throw new IllegalArgumentException("Metric key can not be blank");
603 }
604 if (StringUtils.isBlank(name)) {
605 throw new IllegalArgumentException("Metric name can not be blank");
606 }
607 if (type==null) {
608 throw new IllegalArgumentException("Metric type can not be null");
609 }
610 this.key = key;
611 this.name = name;
612 this.type = type;
613 }
614
615 public Builder setDescription(String s) {
616 this.description = s;
617 return this;
618 }
619
620 /**
621 * Used for numeric values only
622 */
623 public Builder setDirection(Integer i) {
624 this.direction = i;
625 return this;
626 }
627
628 public Builder setQualitative(Boolean b) {
629 this.qualitative = b;
630 return this;
631 }
632
633 public Builder setDomain(String s) {
634 this.domain = s;
635 return this;
636 }
637
638 public Builder setFormula(Formula f) {
639 this.formula = f;
640 return this;
641 }
642
643 public Builder setWorstValue(Double d) {
644 this.worstValue = d;
645 return this;
646 }
647
648 public Builder setBestValue(Double d) {
649 this.bestValue = d;
650 return this;
651 }
652
653 public Builder setOptimizedBestValue(boolean b) {
654 this.optimizedBestValue = b;
655 return this;
656 }
657
658 public Builder setHidden(boolean b) {
659 this.hidden = b;
660 return this;
661 }
662
663 public Metric create() {
664 return new Metric(key, name, type, description, direction, domain, qualitative, worstValue, bestValue, optimizedBestValue, hidden, formula);
665 }
666 }
667 }