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