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 }