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 }