001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2008-2012 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 com.google.common.annotations.Beta; 023 import org.apache.commons.lang.builder.ReflectionToStringBuilder; 024 import org.sonar.api.qualitymodel.Characteristic; 025 026 import java.math.BigDecimal; 027 import java.math.RoundingMode; 028 import java.util.Date; 029 030 /** 031 * A class to handle measures. 032 * 033 * @since 1.10 034 */ 035 public class Measure { 036 protected static final int MAX_TEXT_SIZE = 96; 037 038 /** 039 * Default precision when saving a float type metric 040 */ 041 public static final int DEFAULT_PRECISION = 1; 042 043 private Long id; // for internal use 044 protected String metricKey; 045 protected Metric metric; 046 protected Double value; 047 protected String data; 048 protected String description; 049 protected Metric.Level alertStatus; 050 protected String alertText; 051 protected Integer tendency; 052 protected Date date; 053 protected Double variation1, variation2, variation3, variation4, variation5; 054 protected String url; 055 protected Characteristic characteristic; 056 protected Integer personId; 057 protected PersistenceMode persistenceMode = PersistenceMode.FULL; 058 059 public Measure(String metricKey) { 060 this.metricKey = metricKey; 061 } 062 063 /** 064 * Creates a measure with a metric 065 * 066 * @param metric the metric 067 */ 068 public Measure(Metric metric) { 069 this.metric = metric; 070 this.metricKey = metric.getKey(); 071 } 072 073 /** 074 * Creates a measure with a metric and a value 075 * 076 * @param metric the metric 077 * @param value its value 078 */ 079 public Measure(Metric metric, Double value) { 080 this.metric = metric; 081 this.metricKey = metric.getKey(); 082 setValue(value); 083 } 084 085 /** 086 * Creates a measure with a metric, a value and a precision for the value 087 * 088 * @param metric the metric 089 * @param value its value 090 * @param precision the value precision 091 */ 092 public Measure(Metric metric, Double value, int precision) { 093 this.metric = metric; 094 this.metricKey = metric.getKey(); 095 setValue(value, precision); 096 } 097 098 /** 099 * Creates a measure with a metric, a value and a data field 100 * 101 * @param metric the metric 102 * @param value the value 103 * @param data the data field 104 */ 105 public Measure(Metric metric, Double value, String data) { 106 this.metric = metric; 107 this.metricKey = metric.getKey(); 108 setValue(value); 109 setData(data); 110 } 111 112 /** 113 * * Creates a measure with a metric and a data field 114 * 115 * @param metric the metric 116 * @param data the data field 117 */ 118 public Measure(Metric metric, String data) { 119 this.metric = metric; 120 this.metricKey = metric.getKey(); 121 setData(data); 122 } 123 124 /** 125 * Creates a measure with a metric and an alert level 126 * 127 * @param metric the metric 128 * @param level the alert level 129 */ 130 public Measure(Metric metric, Metric.Level level) { 131 this.metric = metric; 132 this.metricKey = metric.getKey(); 133 if (level != null) { 134 this.data = level.toString(); 135 } 136 } 137 138 /** 139 * Creates an empty measure 140 */ 141 public Measure() { 142 } 143 144 /** 145 * Gets the persistence mode of the measure. Default persistence mode is FULL, except when instantiating the measure with a String 146 * parameter. 147 */ 148 public PersistenceMode getPersistenceMode() { 149 return persistenceMode; 150 } 151 152 /** 153 * <p> 154 * Sets the persistence mode of a measure. 155 * </p> 156 * <p> 157 * <b>WARNING : </b>Being able to reuse measures saved in memory is only possible within the same tree. In a multi-module project for 158 * example, a measure save in memory at the module level will not be accessible by the root project. In that case, database should be 159 * used. 160 * </p> 161 * 162 * @param mode the mode 163 * @return the measure object instance 164 */ 165 public Measure setPersistenceMode(PersistenceMode mode) { 166 this.persistenceMode = mode; 167 return this; 168 } 169 170 /** 171 * @return return the measures underlying metric 172 */ 173 public Metric getMetric() { 174 return metric; 175 } 176 177 public String getMetricKey() { 178 return metricKey; 179 } 180 181 /** 182 * Set the underlying metric 183 * 184 * @param metric the metric 185 * @return the measure object instance 186 */ 187 public Measure setMetric(Metric metric) { 188 this.metric = metric; 189 this.metricKey = metric.getKey(); 190 return this; 191 } 192 193 /** 194 * @return transforms and returns the data fields as a level of alert 195 */ 196 public Metric.Level getDataAsLevel() { 197 if (data != null) { 198 return Metric.Level.valueOf(data); 199 } 200 return null; 201 } 202 203 public boolean hasData() { 204 return data != null; 205 } 206 207 /** 208 * @return the date of the measure, i.e. the date the measure was taken. Used only in TimeMachine queries 209 */ 210 public Date getDate() { 211 return date; 212 } 213 214 /** 215 * Sets the date of the measure - Used only in TimeMachine queries 216 * 217 * @param date the date 218 * @return the measure object instance 219 */ 220 public Measure setDate(Date date) { 221 this.date = date; 222 return this; 223 } 224 225 /** 226 * @return the value of the measure as a double 227 */ 228 public Double getValue() { 229 return value; 230 } 231 232 /** 233 * @return the value of the measure as an int 234 */ 235 public Integer getIntValue() { 236 if (value == null) { 237 return null; 238 } 239 return value.intValue(); 240 } 241 242 /** 243 * Sets the measure value with the default precision of 1 244 * 245 * @param v the measure value 246 * @return the measure object instance 247 */ 248 public Measure setValue(Double v) { 249 return setValue(v, DEFAULT_PRECISION); 250 } 251 252 /** 253 * Sets the measure value as an int 254 * 255 * @param i the value 256 * @return the measure object instance 257 */ 258 public Measure setIntValue(Integer i) { 259 if (i == null) { 260 this.value = null; 261 } else { 262 this.value = Double.valueOf(i); 263 } 264 return this; 265 } 266 267 /** 268 * Sets the measure value with a given precision 269 * 270 * @param v the measure value 271 * @param precision the measure value precision 272 * @return the measure object instance 273 */ 274 public Measure setValue(Double v, int precision) { 275 if (v != null) { 276 if (Double.isNaN(v)) { 277 throw new IllegalArgumentException("Measure value can not be NaN"); 278 } 279 this.value = scaleValue(v, precision); 280 } else { 281 this.value = null; 282 } 283 return this; 284 } 285 286 private double scaleValue(double value, int scale) { 287 BigDecimal bd = BigDecimal.valueOf(value); 288 return bd.setScale(scale, RoundingMode.HALF_UP).doubleValue(); 289 } 290 291 /** 292 * @return the data field of the measure 293 */ 294 public String getData() { 295 return data; 296 } 297 298 /** 299 * Sets the data field of the measure. 300 * 301 * @param s the data 302 * @return the measure object instance 303 */ 304 public Measure setData(String s) { 305 this.data = s; 306 return this; 307 } 308 309 /** 310 * Sets an alert level as the data field 311 * 312 * @param level the alert level 313 * @return the measure object instance 314 */ 315 public Measure setData(Metric.Level level) { 316 if (level == null) { 317 this.data = null; 318 } else { 319 this.data = level.toString(); 320 } 321 return this; 322 } 323 324 /** 325 * @since 2.7 326 */ 327 public Measure unsetData() { 328 this.data = null; 329 return this; 330 } 331 332 /** 333 * @return the description of the measure 334 */ 335 public String getDescription() { 336 return description; 337 } 338 339 /** 340 * Sets the measure description 341 * 342 * @param description the description 343 * @return the measure object instance 344 */ 345 public Measure setDescription(String description) { 346 this.description = description; 347 return this; 348 } 349 350 /** 351 * @return the alert status of the measure 352 */ 353 public Metric.Level getAlertStatus() { 354 return alertStatus; 355 } 356 357 /** 358 * Set the alert status of the measure 359 * 360 * @param status the status 361 * @return the measure object instance 362 */ 363 public Measure setAlertStatus(Metric.Level status) { 364 this.alertStatus = status; 365 return this; 366 } 367 368 /** 369 * @return the text associated to the alert on the measure 370 */ 371 public String getAlertText() { 372 return alertText; 373 } 374 375 /** 376 * Sets the text associated to the alert on the measure 377 * 378 * @param alertText the text 379 * @return the measure object instance 380 */ 381 public Measure setAlertText(String alertText) { 382 this.alertText = alertText; 383 return this; 384 } 385 386 /** 387 * Gets the measure tendency 388 * 389 * @return the tendency 390 */ 391 public Integer getTendency() { 392 return tendency; 393 } 394 395 /** 396 * Sets the tendency for the measure - Internal use only 397 * 398 * @param tendency the tendency 399 * @return the measure object instance 400 */ 401 public Measure setTendency(Integer tendency) { 402 this.tendency = tendency; 403 return this; 404 } 405 406 /** 407 * @return the measure id - Internal use only 408 */ 409 public Long getId() { 410 return id; 411 } 412 413 /** 414 * Sets the measure id - Internal use only 415 * 416 * @param id the id 417 * @return the measure object instance 418 */ 419 public Measure setId(Long id) { 420 this.id = id; 421 return this; 422 } 423 424 /** 425 * @return the first variation value 426 * @since 2.5 427 */ 428 public Double getVariation1() { 429 return variation1; 430 } 431 432 /** 433 * Internal use only 434 * 435 * @since 2.5 436 */ 437 public Measure setVariation1(Double d) { 438 this.variation1 = d; 439 return this; 440 } 441 442 /** 443 * @return the second variation value 444 * @since 2.5 445 */ 446 public Double getVariation2() { 447 return variation2; 448 } 449 450 /** 451 * Internal use only 452 * 453 * @since 2.5 454 */ 455 public Measure setVariation2(Double d) { 456 this.variation2 = d; 457 return this; 458 } 459 460 /** 461 * @return the third variation value 462 * @since 2.5 463 */ 464 public Double getVariation3() { 465 return variation3; 466 } 467 468 /** 469 * Internal use only 470 * 471 * @since 2.5 472 */ 473 public Measure setVariation3(Double d) { 474 this.variation3 = d; 475 return this; 476 } 477 478 /** 479 * @return the third variation value 480 * @since 2.5 481 */ 482 public Double getVariation4() { 483 return variation4; 484 } 485 486 /** 487 * Internal use only 488 * 489 * @since 2.5 490 */ 491 public Measure setVariation4(Double d) { 492 this.variation4 = d; 493 return this; 494 } 495 496 /** 497 * @return the third variation value 498 * @since 2.5 499 */ 500 public Double getVariation5() { 501 return variation5; 502 } 503 504 /** 505 * Internal use only 506 * 507 * @since 2.5 508 */ 509 public Measure setVariation5(Double d) { 510 this.variation5 = d; 511 return this; 512 } 513 514 /** 515 * @since 2.5 516 */ 517 public Double getVariation(int index) { 518 switch (index) { 519 case 1: 520 return variation1; 521 case 2: 522 return variation2; 523 case 3: 524 return variation3; 525 case 4: 526 return variation4; 527 case 5: 528 return variation5; 529 default: 530 throw new IndexOutOfBoundsException("Index should be in range from 1 to 5"); 531 } 532 } 533 534 /** 535 * Internal use only 536 * 537 * @since 2.5 538 */ 539 public Measure setVariation(int index, Double d) { 540 switch (index) { 541 case 1: 542 variation1 = d; 543 break; 544 case 2: 545 variation2 = d; 546 break; 547 case 3: 548 variation3 = d; 549 break; 550 case 4: 551 variation4 = d; 552 break; 553 case 5: 554 variation5 = d; 555 break; 556 default: 557 throw new IndexOutOfBoundsException("Index should be in range from 1 to 5"); 558 } 559 return this; 560 } 561 562 /** 563 * @return the url of the measure 564 */ 565 public String getUrl() { 566 return url; 567 } 568 569 /** 570 * Sets the URL of the measure 571 * 572 * @param url the url 573 * @return the measure object instance 574 */ 575 public Measure setUrl(String url) { 576 this.url = url; 577 return this; 578 } 579 580 /** 581 * @since 2.3 582 */ 583 public final Characteristic getCharacteristic() { 584 return characteristic; 585 } 586 587 /** 588 * @since 2.3 589 */ 590 public final Measure setCharacteristic(Characteristic characteristic) { 591 this.characteristic = characteristic; 592 return this; 593 } 594 595 /** 596 * @since 2.14 597 */ 598 @Beta 599 public Integer getPersonId() { 600 return personId; 601 } 602 603 /** 604 * @since 2.14 605 */ 606 @Beta 607 public Measure setPersonId(Integer i) { 608 this.personId = i; 609 return this; 610 } 611 612 @Override 613 public boolean equals(Object o) { 614 if (this == o) { 615 return true; 616 } 617 if (o == null || getClass() != o.getClass()) { 618 return false; 619 } 620 621 Measure measure = (Measure) o; 622 if (metricKey != null ? !metricKey.equals(measure.metricKey) : measure.metricKey != null) { 623 return false; 624 } 625 if (characteristic != null ? !characteristic.equals(measure.characteristic) : measure.characteristic != null) { 626 return false; 627 } 628 if (personId != null ? !personId.equals(measure.personId) : measure.personId != null) { 629 return false; 630 } 631 return true; 632 } 633 634 @Override 635 public int hashCode() { 636 int result = metricKey != null ? metricKey.hashCode() : 0; 637 result = 31 * result + (characteristic != null ? characteristic.hashCode() : 0); 638 result = 31 * result + (personId != null ? personId.hashCode() : 0); 639 return result; 640 } 641 642 @Override 643 public String toString() { 644 return ReflectionToStringBuilder.toString(this); 645 } 646 }