001 /* 002 * Sonar, open source software quality management tool. 003 * Copyright (C) 2009 SonarSource SA 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.EqualsBuilder; 023 import org.apache.commons.lang.builder.ToStringBuilder; 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 * <p/> 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 Integer id; // for internal use 043 protected Metric metric; 044 protected Double value; 045 protected String data; 046 protected String description; 047 protected Metric.Level alertStatus; 048 protected String alertText; 049 protected Integer tendency; 050 protected Date date; 051 protected Double diff1, diff2, diff3; 052 protected String url; 053 protected PersistenceMode persistenceMode = PersistenceMode.FULL; 054 055 /** 056 * Creates a measure with a metric 057 * 058 * @param metric the metric 059 */ 060 public Measure(Metric metric) { 061 this.metric = metric; 062 } 063 064 /** 065 * Creates a measure with a metric and a value 066 * 067 * @param metric the metric 068 * @param value its value 069 */ 070 public Measure(Metric metric, Double value) { 071 this.metric = metric; 072 setValue(value); 073 } 074 075 /** 076 * Creates a measure with a metric, a value and a precision for the value 077 * 078 * @param metric the metric 079 * @param value its value 080 * @param precision the value precision 081 */ 082 public Measure(Metric metric, Double value, int precision) { 083 this.metric = metric; 084 setValue(value, precision); 085 } 086 087 /** 088 * Creates a measure with a metric, a value and a data field 089 * 090 * @param metric the metric 091 * @param value the value 092 * @param data the data field 093 */ 094 public Measure(Metric metric, Double value, String data) { 095 this.metric = metric; 096 setValue(value); 097 setData(data); 098 } 099 100 /** 101 * * Creates a measure with a metric and a data field 102 * 103 * @param metric the metric 104 * @param data the data field 105 */ 106 public Measure(Metric metric, String data) { 107 this.metric = metric; 108 setData(data); 109 } 110 111 /** 112 * Creates a measure with a metric and an alert level 113 * 114 * @param metric the metric 115 * @param level the alert level 116 */ 117 public Measure(Metric metric, Metric.Level level) { 118 this.metric = metric; 119 if (level != null) { 120 this.data = level.toString(); 121 } 122 } 123 124 /** 125 * Creates an empty measure 126 */ 127 public Measure() { 128 } 129 130 /** 131 * Gets the persistence mode of the measure. Default persistence mode is FULL, 132 * except when instantiating the measure with a String parameter. 133 */ 134 public PersistenceMode getPersistenceMode() { 135 return persistenceMode; 136 } 137 138 /** 139 * <p>Sets the persistence mode of a measure.</p> 140 * <p><b>WARNING : </b>Being able to reuse measures saved in memory is only possible within the same tree. 141 * In a multi-module project for example, a measure save in memory at the module level will not be accessible by 142 * the root project. In that case, database should be used. 143 * </p> 144 * 145 * @param mode the mode 146 * @return the measure object instance 147 */ 148 public Measure setPersistenceMode(PersistenceMode mode) { 149 this.persistenceMode = mode; 150 return this; 151 } 152 153 /** 154 * @return return the measures underlying metric 155 */ 156 public Metric getMetric() { 157 return metric; 158 } 159 160 /** 161 * Set the underlying metric 162 * 163 * @param metric the metric 164 * @return the measure object instance 165 */ 166 public Measure setMetric(Metric metric) { 167 this.metric = metric; 168 return this; 169 } 170 171 /** 172 * @return transforms and returns the data fields as a level of alert 173 */ 174 public Metric.Level getDataAsLevel() { 175 if (data != null) { 176 return Metric.Level.valueOf(data); 177 } 178 return null; 179 } 180 181 /** 182 * @return the date of the measure, i.e. the date the measure was taken. Used only in TimeMachine queries 183 */ 184 public Date getDate() { 185 return date; 186 } 187 188 /** 189 * Sets the date of the measure - Used only in TimeMachine queries 190 * 191 * @param date the date 192 * @return the measure object instance 193 */ 194 public Measure setDate(Date date) { 195 this.date = date; 196 return this; 197 } 198 199 /** 200 * @return the value of the measure as a double 201 */ 202 public Double getValue() { 203 return value; 204 } 205 206 /** 207 * @return the value of the measure as an int 208 */ 209 public Integer getIntValue() { 210 if (value == null) { 211 return null; 212 } 213 return value.intValue(); 214 } 215 216 /** 217 * Sets the measure value with the default precision of 1 218 * 219 * @param v the measure value 220 * @return the measure object instance 221 */ 222 public Measure setValue(Double v) { 223 return setValue(v, DEFAULT_PRECISION); 224 } 225 226 /** 227 * Sets the measure value as an int 228 * 229 * @param i the value 230 * @return the measure object instance 231 */ 232 public Measure setIntValue(Integer i) { 233 if (i == null) { 234 this.value = null; 235 } else { 236 this.value = Double.valueOf(i); 237 } 238 return this; 239 } 240 241 /** 242 * Sets the measure value with a given precision 243 * 244 * @param v the measure value 245 * @param precision the measure value precision 246 * @return the measure object instance 247 */ 248 public Measure setValue(Double v, int precision) { 249 if (v != null) { 250 if (Double.isNaN(v)) { 251 throw new IllegalArgumentException("Measure value can not be NaN"); 252 } 253 this.value = scaleValue(v, precision); 254 } else { 255 this.value = null; 256 } 257 return this; 258 } 259 260 private double scaleValue(double value, int scale) { 261 BigDecimal bd = BigDecimal.valueOf(value); 262 return bd.setScale(scale, RoundingMode.HALF_UP).doubleValue(); 263 } 264 265 /** 266 * @return the data field of the measure 267 */ 268 public String getData() { 269 return data; 270 } 271 272 /** 273 * Sets the data field of the measure. 274 * @param s the data 275 * @return the measure object instance 276 */ 277 public Measure setData(String s) { 278 if (s != null && s.length() >= MAX_TEXT_SIZE && !metric.isDataType()) { 279 throw new IllegalArgumentException("Data is too long for non-data metric : size=" + s.length() + ", max=" + MAX_TEXT_SIZE); 280 } 281 this.data = s; 282 return this; 283 } 284 285 /** 286 * Sets an alert level as the data field 287 * 288 * @param level the alert level 289 * @return the measure object instance 290 */ 291 public Measure setData(Metric.Level level) { 292 if (level == null) { 293 this.data = null; 294 } else { 295 this.data = level.toString(); 296 } 297 return this; 298 } 299 300 /** 301 * @return the description of the measure 302 */ 303 public String getDescription() { 304 return description; 305 } 306 307 /** 308 * Sets the measure description 309 * 310 * @param description the description 311 * @return the measure object instance 312 */ 313 public Measure setDescription(String description) { 314 this.description = description; 315 return this; 316 } 317 318 /** 319 * @return the alert status of the measure 320 */ 321 public Metric.Level getAlertStatus() { 322 return alertStatus; 323 } 324 325 /** 326 * Set the alert status of the measure 327 * 328 * @param status the status 329 * @return the measure object instance 330 */ 331 public Measure setAlertStatus(Metric.Level status) { 332 this.alertStatus = status; 333 return this; 334 } 335 336 /** 337 * @return the text associated to the alert on the measure 338 */ 339 public String getAlertText() { 340 return alertText; 341 } 342 343 /** 344 * Sets the text associated to the alert on the measure 345 * 346 * @param alertText the text 347 * @return the measure object instance 348 */ 349 public Measure setAlertText(String alertText) { 350 this.alertText = alertText; 351 return this; 352 } 353 354 /** 355 * Gets the measure tendency 356 * 357 * @return the tendency 358 */ 359 public Integer getTendency() { 360 return tendency; 361 } 362 363 /** 364 * Sets the tendency for the measure 365 * 366 * @param tendency the tendency 367 * @return the measure object instance 368 */ 369 public Measure setTendency(Integer tendency) { 370 this.tendency = tendency; 371 return this; 372 } 373 374 /** 375 * @return the measure id - Internal use only 376 */ 377 public Integer getId() { 378 return id; 379 } 380 381 /** 382 * Sets the measure id - Internal use only 383 * 384 * @param id the id 385 * @return the measure object instance 386 */ 387 public Measure setId(Integer id) { 388 this.id = id; 389 return this; 390 } 391 392 /** 393 * @return the first differential value of the measure 394 */ 395 public Double getDiffValue1() { 396 return diff1; 397 } 398 399 /** 400 * Sets the first differential value of the measure 401 * 402 * @param diff1 the diff 403 * @return the measure object instance 404 */ 405 public Measure setDiffValue1(Double diff1) { 406 this.diff1 = diff1; 407 return this; 408 } 409 410 /** 411 * @return the second differential value of the measure 412 */ 413 public Double getDiffValue2() { 414 return diff2; 415 } 416 417 /** 418 * Sets the second differential value of the measure 419 * 420 * @param diff2 the diff 421 * @return the measure object instance 422 */ 423 public Measure setDiffValue2(Double diff2) { 424 this.diff2 = diff2; 425 return this; 426 } 427 428 /** 429 * @return the third differential value of the measure 430 */ 431 public Double getDiffValue3() { 432 return diff3; 433 } 434 435 /** 436 * Sets the third differential value of the measure 437 * 438 * @param diff3 the diff 439 * @return the measure object instance 440 */ 441 public Measure setDiffValue3(Double diff3) { 442 this.diff3 = diff3; 443 return this; 444 } 445 446 /** 447 * @return the url of the measure 448 */ 449 public String getUrl() { 450 return url; 451 } 452 453 /** 454 * Sets the URL of the measure 455 * 456 * @param url the url 457 * @return the measure object instance 458 */ 459 public Measure setUrl(String url) { 460 this.url = url; 461 return this; 462 } 463 464 @Override 465 public boolean equals(Object obj) { 466 if (!(obj instanceof Measure)) { 467 return false; 468 } 469 if (this == obj) { 470 return true; 471 } 472 Measure rhs = (Measure) obj; 473 return new EqualsBuilder() 474 .append(metric, rhs.getMetric()) 475 .isEquals(); 476 } 477 478 @Override 479 public int hashCode() { 480 return (metric != null ? metric.hashCode() : 0); 481 } 482 483 @Override 484 public String toString() { 485 return new ToStringBuilder(this). 486 append("id", id). 487 append("metric", metric). 488 append("value", value). 489 append("data", data). 490 append("description", description). 491 append("alertStatus", alertStatus). 492 append("alertText", alertText). 493 append("tendency", tendency). 494 append("diff1", diff1). 495 append("diff2", diff2). 496 append("diff3", diff3). 497 toString(); 498 } 499 500 }