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