001 /* 002 * SonarQube, open source software quality management tool. 003 * Copyright (C) 2008-2014 SonarSource 004 * mailto:contact AT sonarsource DOT com 005 * 006 * SonarQube 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 * SonarQube 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 License 017 * along with this program; if not, write to the Free Software Foundation, 018 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 019 */ 020 package org.sonar.api.database.model; 021 022 import com.google.common.base.Charsets; 023 import com.google.common.base.Throwables; 024 import org.apache.commons.lang.builder.ReflectionToStringBuilder; 025 import org.apache.commons.lang.builder.ToStringStyle; 026 import org.sonar.api.database.DatabaseSession; 027 import org.sonar.api.measures.Metric; 028 import org.sonar.api.rules.RulePriority; 029 030 import javax.persistence.Column; 031 import javax.persistence.Entity; 032 import javax.persistence.EnumType; 033 import javax.persistence.Enumerated; 034 import javax.persistence.GeneratedValue; 035 import javax.persistence.Id; 036 import javax.persistence.Table; 037 import javax.persistence.Temporal; 038 import javax.persistence.TemporalType; 039 040 import java.io.UnsupportedEncodingException; 041 import java.util.Date; 042 043 /** 044 * This class is the Hibernate model to store a measure in the DB 045 */ 046 @Entity 047 @Table(name = "project_measures") 048 public class MeasureModel implements Cloneable { 049 050 public static final int TEXT_VALUE_LENGTH = 4000; 051 052 @Id 053 @Column(name = "id") 054 @GeneratedValue 055 private Long id; 056 057 @Column(name = "value", updatable = true, nullable = true, precision = 30, scale = 20) 058 private Double value = 0.0; 059 060 @Column(name = "text_value", updatable = true, nullable = true, length = TEXT_VALUE_LENGTH) 061 private String textValue; 062 063 @Column(name = "tendency", updatable = true, nullable = true) 064 private Integer tendency; 065 066 @Column(name = "metric_id", updatable = false, nullable = false) 067 private Integer metricId; 068 069 @Column(name = "snapshot_id", updatable = true, nullable = true) 070 private Integer snapshotId; 071 072 @Column(name = "project_id", updatable = true, nullable = true) 073 private Integer projectId; 074 075 @Column(name = "description", updatable = true, nullable = true, length = 4000) 076 private String description; 077 078 @Temporal(TemporalType.TIMESTAMP) 079 @Column(name = "measure_date", updatable = true, nullable = true) 080 private Date measureDate; 081 082 @Column(name = "rule_id", updatable = true, nullable = true) 083 private Integer ruleId; 084 085 @Column(name = "rule_priority", updatable = false, nullable = true) 086 @Enumerated(EnumType.ORDINAL) 087 private RulePriority rulePriority; 088 089 @Column(name = "alert_status", updatable = true, nullable = true, length = 5) 090 private String alertStatus; 091 092 @Column(name = "alert_text", updatable = true, nullable = true, length = 4000) 093 private String alertText; 094 095 @Column(name = "variation_value_1", updatable = true, nullable = true) 096 private Double variationValue1; 097 098 @Column(name = "variation_value_2", updatable = true, nullable = true) 099 private Double variationValue2; 100 101 @Column(name = "variation_value_3", updatable = true, nullable = true) 102 private Double variationValue3; 103 104 @Column(name = "variation_value_4", updatable = true, nullable = true) 105 private Double variationValue4; 106 107 @Column(name = "variation_value_5", updatable = true, nullable = true) 108 private Double variationValue5; 109 110 @Column(name = "url", updatable = true, nullable = true, length = 2000) 111 private String url; 112 113 @Column(name = "characteristic_id", nullable = true) 114 private Integer characteristicId; 115 116 @Column(name = "person_id", updatable = true, nullable = true) 117 private Integer personId; 118 119 @Column(name = "measure_data", updatable = true, nullable = true, length = 167772150) 120 private byte[] data; 121 122 public Long getId() { 123 return id; 124 } 125 126 public void setId(Long id) { 127 this.id = id; 128 } 129 130 /** 131 * Creates a measure based on a metric and a double value 132 */ 133 public MeasureModel(int metricId, Double val) { 134 if (val.isNaN() || val.isInfinite()) { 135 throw new IllegalArgumentException("Measure value is NaN. Metric=" + metricId); 136 } 137 this.metricId = metricId; 138 this.value = val; 139 } 140 141 /** 142 * Creates a measure based on a metric and an alert level 143 */ 144 public MeasureModel(int metricId, Metric.Level level) { 145 this.metricId = metricId; 146 if (level != null) { 147 this.textValue = level.toString(); 148 } 149 } 150 151 /** 152 * Creates a measure based on a metric and a string value 153 */ 154 public MeasureModel(int metricId, String val) { 155 this.metricId = metricId; 156 setData(val); 157 } 158 159 /** 160 * Creates an empty measure 161 */ 162 public MeasureModel() { 163 } 164 165 /** 166 * @return the measure double value 167 */ 168 public Double getValue() { 169 return value; 170 } 171 172 /** 173 * @return the measure description 174 */ 175 public String getDescription() { 176 return description; 177 } 178 179 /** 180 * Sets the measure description 181 */ 182 public void setDescription(String description) { 183 this.description = description; 184 } 185 186 /** 187 * Sets the measure value 188 * 189 * @throws IllegalArgumentException in case value is not a valid double 190 */ 191 public MeasureModel setValue(Double value) { 192 if (value != null && (value.isNaN() || value.isInfinite())) { 193 throw new IllegalArgumentException(); 194 } 195 this.value = value; 196 return this; 197 } 198 199 /** 200 * @return the measure alert level 201 */ 202 public Metric.Level getLevelValue() { 203 if (textValue != null) { 204 return Metric.Level.valueOf(textValue); 205 } 206 return null; 207 } 208 209 /** 210 * Use getData() instead 211 */ 212 public String getTextValue() { 213 return textValue; 214 } 215 216 /** 217 * Use setData() instead 218 */ 219 public void setTextValue(String textValue) { 220 this.textValue = textValue; 221 } 222 223 /** 224 * @return the measure tendency 225 */ 226 public Integer getTendency() { 227 return tendency; 228 } 229 230 /** 231 * @return whether the measure is about rule 232 */ 233 public boolean isRuleMeasure() { 234 return ruleId != null || rulePriority != null; 235 } 236 237 /** 238 * Sets the measure tendency 239 * 240 * @return the current object 241 */ 242 public MeasureModel setTendency(Integer tendency) { 243 this.tendency = tendency; 244 return this; 245 } 246 247 public Integer getMetricId() { 248 return metricId; 249 } 250 251 public void setMetricId(Integer metricId) { 252 this.metricId = metricId; 253 } 254 255 /** 256 * @return the snapshot id the measure is attached to 257 */ 258 public Integer getSnapshotId() { 259 return snapshotId; 260 } 261 262 /** 263 * Sets the snapshot id 264 * 265 * @return the current object 266 */ 267 public MeasureModel setSnapshotId(Integer snapshotId) { 268 this.snapshotId = snapshotId; 269 return this; 270 } 271 272 public Integer getRuleId() { 273 return ruleId; 274 } 275 276 /** 277 * Sets the rule for the measure 278 * 279 * @return the current object 280 */ 281 public MeasureModel setRuleId(Integer ruleId) { 282 this.ruleId = ruleId; 283 return this; 284 } 285 286 /** 287 * @return the rule priority 288 */ 289 public RulePriority getRulePriority() { 290 return rulePriority; 291 } 292 293 /** 294 * Sets the rule priority 295 */ 296 public void setRulePriority(RulePriority rulePriority) { 297 this.rulePriority = rulePriority; 298 } 299 300 /** 301 * @return the project id 302 */ 303 public Integer getProjectId() { 304 return projectId; 305 } 306 307 /** 308 * Sets the project id 309 */ 310 public void setProjectId(Integer projectId) { 311 this.projectId = projectId; 312 } 313 314 /** 315 * @return the date of the measure 316 */ 317 public Date getMeasureDate() { 318 return measureDate; 319 } 320 321 /** 322 * Sets the date for the measure 323 * 324 * @return the current object 325 */ 326 public MeasureModel setMeasureDate(Date measureDate) { 327 this.measureDate = measureDate; 328 return this; 329 } 330 331 /** 332 * @return the alert status if there is one, null otherwise 333 */ 334 public Metric.Level getAlertStatus() { 335 if (alertStatus == null) { 336 return null; 337 } 338 return Metric.Level.valueOf(alertStatus); 339 } 340 341 /** 342 * Sets the measure alert status 343 * 344 * @return the current object 345 */ 346 public MeasureModel setAlertStatus(Metric.Level level) { 347 if (level != null) { 348 this.alertStatus = level.toString(); 349 } else { 350 this.alertStatus = null; 351 } 352 return this; 353 } 354 355 /** 356 * @return the measure data 357 */ 358 public String getData(Metric metric) { 359 if (this.textValue != null) { 360 return this.textValue; 361 } 362 if (metric.isDataType() && data != null) { 363 try { 364 return new String(data, Charsets.UTF_8.name()); 365 } catch (UnsupportedEncodingException e) { 366 // how is it possible to not support UTF-8 ? 367 Throwables.propagate(e); 368 } 369 } 370 return null; 371 } 372 373 /** 374 * Sets the measure data 375 */ 376 public final void setData(String data) { 377 if (data == null) { 378 this.textValue = null; 379 this.data = null; 380 381 } else { 382 if (data.length() > TEXT_VALUE_LENGTH) { 383 this.textValue = null; 384 this.data = data.getBytes(Charsets.UTF_8); 385 } else { 386 this.textValue = data; 387 this.data = null; 388 } 389 } 390 } 391 392 /** 393 * @return the text of the alert 394 */ 395 public String getAlertText() { 396 return alertText; 397 } 398 399 /** 400 * Sets the text for the alert 401 */ 402 public void setAlertText(String alertText) { 403 this.alertText = alertText; 404 } 405 406 /** 407 * @return the measure URL 408 */ 409 public String getUrl() { 410 return url; 411 } 412 413 /** 414 * Sets the measure URL 415 */ 416 public void setUrl(String url) { 417 this.url = url; 418 } 419 420 @Override 421 public String toString() { 422 return new ReflectionToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).toString(); 423 } 424 425 public Double getVariationValue1() { 426 return variationValue1; 427 } 428 429 public void setVariationValue1(Double d) { 430 this.variationValue1 = d; 431 } 432 433 public Double getVariationValue2() { 434 return variationValue2; 435 } 436 437 public void setVariationValue2(Double d) { 438 this.variationValue2 = d; 439 } 440 441 public Double getVariationValue3() { 442 return variationValue3; 443 } 444 445 public void setVariationValue3(Double d) { 446 this.variationValue3 = d; 447 } 448 449 public Double getVariationValue4() { 450 return variationValue4; 451 } 452 453 public void setVariationValue4(Double d) { 454 this.variationValue4 = d; 455 } 456 457 public Double getVariationValue5() { 458 return variationValue5; 459 } 460 461 public void setVariationValue5(Double d) { 462 this.variationValue5 = d; 463 } 464 465 /** 466 * Saves the current object to database 467 * 468 * @return the current object 469 */ 470 public MeasureModel save(DatabaseSession session) { 471 session.save(this); 472 return this; 473 } 474 475 public Integer getCharacteristicId() { 476 return characteristicId; 477 } 478 479 public MeasureModel setCharacteristicId(Integer characteristicId) { 480 this.characteristicId = characteristicId; 481 return this; 482 } 483 484 public Integer getPersonId() { 485 return personId; 486 } 487 488 public MeasureModel setPersonId(Integer i) { 489 this.personId = i; 490 return this; 491 } 492 493 @Override 494 public Object clone() { 495 MeasureModel clone = new MeasureModel(); 496 clone.setMetricId(getMetricId()); 497 clone.setDescription(getDescription()); 498 clone.setTextValue(getTextValue()); 499 clone.setAlertStatus(getAlertStatus()); 500 clone.setAlertText(getAlertText()); 501 clone.setTendency(getTendency()); 502 clone.setVariationValue1(getVariationValue1()); 503 clone.setVariationValue2(getVariationValue2()); 504 clone.setVariationValue3(getVariationValue3()); 505 clone.setVariationValue4(getVariationValue4()); 506 clone.setVariationValue5(getVariationValue5()); 507 clone.setValue(getValue()); 508 clone.setRulePriority(getRulePriority()); 509 clone.setRuleId(getRuleId()); 510 clone.setSnapshotId(getSnapshotId()); 511 clone.setMeasureDate(getMeasureDate()); 512 clone.setUrl(getUrl()); 513 clone.setCharacteristicId(getCharacteristicId()); 514 clone.setPersonId(getPersonId()); 515 return clone; 516 } 517 518 }