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.database.model; 021 022 import org.apache.commons.lang.builder.ToStringBuilder; 023 import org.hibernate.annotations.Cache; 024 import org.hibernate.annotations.CacheConcurrencyStrategy; 025 import org.sonar.api.database.BaseIdentifiable; 026 import org.sonar.api.database.DatabaseSession; 027 import org.sonar.api.measures.Measure; 028 import org.sonar.api.measures.Metric; 029 import org.sonar.api.measures.RuleMeasure; 030 import org.sonar.api.rules.Rule; 031 import org.sonar.api.rules.RulePriority; 032 033 import java.util.ArrayList; 034 import java.util.Date; 035 import java.util.List; 036 import javax.persistence.*; 037 038 @Entity 039 @Table(name = "project_measures") 040 public class MeasureModel extends BaseIdentifiable implements Cloneable { 041 042 public static final int TEXT_VALUE_LENGTH = 96; 043 044 @Column(name = "value", updatable = true, nullable = true, precision = 30, scale = 20) 045 private Double value = 0.0; 046 047 @Column(name = "text_value", updatable = true, nullable = true, length = TEXT_VALUE_LENGTH) 048 private String textValue; 049 050 @Column(name = "tendency", updatable = true, nullable = true) 051 private Integer tendency; 052 053 @ManyToOne(fetch = FetchType.EAGER) 054 @JoinColumn(name = "metric_id") 055 @Cache(usage = CacheConcurrencyStrategy.READ_ONLY) 056 private Metric metric; 057 058 @Column(name = "snapshot_id", updatable = true, nullable = true) 059 private Integer snapshotId; 060 061 @Column(name = "project_id", updatable = true, nullable = true) 062 private Integer projectId; 063 064 @Column(name = "description", updatable = true, nullable = true, length = 4000) 065 private String description; 066 067 @Temporal(TemporalType.TIMESTAMP) 068 @Column(name = "measure_date", updatable = true, nullable = true) 069 private Date measureDate; 070 071 @ManyToOne(fetch = FetchType.LAZY) 072 @JoinColumn(name = "rule_id") 073 @Cache(usage = CacheConcurrencyStrategy.READ_ONLY) 074 private Rule rule; 075 076 @Column(name = "rules_category_id") 077 private Integer rulesCategoryId; 078 079 @Column(name = "rule_priority", updatable = false, nullable = true) 080 @Enumerated(EnumType.ORDINAL) 081 private RulePriority rulePriority; 082 083 @Column(name = "alert_status", updatable = true, nullable = true, length = 5) 084 private String alertStatus; 085 086 @Column(name = "alert_text", updatable = true, nullable = true, length = 4000) 087 private String alertText; 088 089 @Column(name = "diff_value_1", updatable = true, nullable = true) 090 private Double diffValue1; 091 092 @Column(name = "diff_value_2", updatable = true, nullable = true) 093 private Double diffValue2; 094 095 @Column(name = "diff_value_3", updatable = true, nullable = true) 096 private Double diffValue3; 097 098 @Column(name = "url", updatable = true, nullable = true, length = 2000) 099 private String url; 100 101 @OneToMany(mappedBy = "measure", fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}) 102 private List<MeasureData> measureData = new ArrayList<MeasureData>(); 103 104 public MeasureModel(Metric metric, Double val) { 105 if (val.isNaN() || val.isInfinite()) { 106 throw new IllegalArgumentException("Measure value is NaN. Metric=" + metric); 107 } 108 this.metric = metric; 109 this.value = val; 110 } 111 112 public MeasureModel(Metric metric, Metric.Level level) { 113 this.metric = metric; 114 if (level != null) { 115 this.textValue = level.toString(); 116 } 117 } 118 119 public MeasureModel(Metric metric, String val) { 120 this.metric = metric; 121 setData(val); 122 } 123 124 public MeasureModel() { 125 } 126 127 public Double getValue() { 128 return value; 129 } 130 131 public String getDescription() { 132 return description; 133 } 134 135 public void setDescription(String description) { 136 this.description = description; 137 } 138 139 public MeasureModel setValue(Double value) throws IllegalArgumentException { 140 if (value != null && (value.isNaN() || value.isInfinite())) { 141 throw new IllegalArgumentException(); 142 } 143 this.value = value; 144 return this; 145 } 146 147 public Metric.Level getLevelValue() { 148 if (textValue != null) { 149 return Metric.Level.valueOf(textValue); 150 } 151 return null; 152 } 153 154 /** 155 * Use getData() instead 156 */ 157 public String getTextValue() { 158 return textValue; 159 } 160 161 /** 162 * Use setData() instead 163 */ 164 public void setTextValue(String textValue) { 165 this.textValue = textValue; 166 } 167 168 public Integer getTendency() { 169 return tendency; 170 } 171 172 public boolean isRuleMeasure() { 173 return rule != null || rulePriority != null || rulesCategoryId != null; 174 } 175 176 public MeasureModel setTendency(Integer tendency) { 177 this.tendency = tendency; 178 return this; 179 } 180 181 public Metric getMetric() { 182 return metric; 183 } 184 185 public void setMetric(Metric metric) { 186 this.metric = metric; 187 } 188 189 public Integer getSnapshotId() { 190 return snapshotId; 191 } 192 193 public MeasureModel setSnapshotId(Integer snapshotId) { 194 this.snapshotId = snapshotId; 195 return this; 196 } 197 198 public Rule getRule() { 199 return rule; 200 } 201 202 public MeasureModel setRule(Rule rule) { 203 this.rule = rule; 204 return this; 205 } 206 207 public Integer getRulesCategoryId() { 208 return rulesCategoryId; 209 } 210 211 public MeasureModel setRulesCategoryId(Integer id) { 212 this.rulesCategoryId = id; 213 return this; 214 } 215 216 public RulePriority getRulePriority() { 217 return rulePriority; 218 } 219 220 public void setRulePriority(RulePriority rulePriority) { 221 this.rulePriority = rulePriority; 222 } 223 224 public Integer getProjectId() { 225 return projectId; 226 } 227 228 public void setProjectId(Integer projectId) { 229 this.projectId = projectId; 230 } 231 232 public Date getMeasureDate() { 233 return measureDate; 234 } 235 236 public MeasureModel setMeasureDate(Date measureDate) { 237 this.measureDate = measureDate; 238 return this; 239 } 240 241 public Metric.Level getAlertStatus() { 242 if (alertStatus == null) { 243 return null; 244 } 245 return Metric.Level.valueOf(alertStatus); 246 } 247 248 public MeasureModel setAlertStatus(Metric.Level level) { 249 if (level != null) { 250 this.alertStatus = level.toString(); 251 } else { 252 this.alertStatus = null; 253 } 254 return this; 255 } 256 257 public String getData() { 258 if (this.textValue != null) { 259 return this.textValue; 260 } 261 if (metric.isDataType() && !measureData.isEmpty()) { 262 return measureData.get(0).getText(); 263 } 264 return null; 265 } 266 267 public void setData(String data) { 268 if (data == null) { 269 this.textValue = null; 270 measureData.clear(); 271 272 } else { 273 if (data.length() > TEXT_VALUE_LENGTH) { 274 measureData.clear(); 275 measureData.add(new MeasureData(this, data)); 276 277 } else { 278 this.textValue = data; 279 } 280 } 281 } 282 283 /** 284 * Use getData() instead 285 */ 286 public MeasureData getMeasureData() { 287 if (!measureData.isEmpty()) { 288 return measureData.get(0); 289 } 290 return null; 291 } 292 293 /** 294 * Use setData() instead 295 */ 296 //@Deprecated 297 public void setMeasureData(MeasureData data) { 298 measureData.clear(); 299 if (data != null) { 300 this.measureData.add(data); 301 } 302 } 303 304 public String getAlertText() { 305 return alertText; 306 } 307 308 public void setAlertText(String alertText) { 309 this.alertText = alertText; 310 } 311 312 public String getUrl() { 313 return url; 314 } 315 316 public void setUrl(String url) { 317 this.url = url; 318 } 319 320 @Override 321 public String toString() { 322 return new ToStringBuilder(this). 323 append("value", value). 324 append("metric", metric). 325 toString(); 326 } 327 328 public Integer getRuleId() { 329 if (getRule() != null) { 330 return getRule().getId(); 331 } 332 return null; 333 } 334 335 public Double getDiffValue1() { 336 return diffValue1; 337 } 338 339 public void setDiffValue1(Double diffValue1) { 340 this.diffValue1 = diffValue1; 341 } 342 343 public Double getDiffValue2() { 344 return diffValue2; 345 } 346 347 public void setDiffValue2(Double diffValue2) { 348 this.diffValue2 = diffValue2; 349 } 350 351 public Double getDiffValue3() { 352 return diffValue3; 353 } 354 355 public void setDiffValue3(Double diffValue3) { 356 this.diffValue3 = diffValue3; 357 } 358 359 public MeasureModel save(DatabaseSession session) { 360 this.metric = session.reattach(Metric.class, metric.getId()); 361 MeasureData data = getMeasureData(); 362 setMeasureData(null); 363 session.save(this); 364 365 if (data != null) { 366 data.setMeasure(session.getEntity(MeasureModel.class, getId())); 367 data.setSnapshotId(snapshotId); 368 session.save(data); 369 setMeasureData(data); 370 } 371 return this; 372 } 373 374 @Override 375 public Object clone() { 376 MeasureModel clone = new MeasureModel(); 377 clone.setMetric(getMetric()); 378 clone.setDescription(getDescription()); 379 clone.setTextValue(getTextValue()); 380 clone.setAlertStatus(getAlertStatus()); 381 clone.setAlertText(getAlertText()); 382 clone.setTendency(getTendency()); 383 clone.setDiffValue1(getDiffValue1()); 384 clone.setDiffValue2(getDiffValue2()); 385 clone.setDiffValue3(getDiffValue3()); 386 clone.setValue(getValue()); 387 clone.setRulesCategoryId(getRulesCategoryId()); 388 clone.setRulePriority(getRulePriority()); 389 clone.setRule(getRule()); 390 clone.setSnapshotId(getSnapshotId()); 391 clone.setMeasureDate(getMeasureDate()); 392 clone.setUrl(getUrl()); 393 return clone; 394 } 395 396 public static MeasureModel build(Measure measure) { 397 return build(measure, new MeasureModel()); 398 } 399 400 public static MeasureModel build(Measure measure, MeasureModel merge) { 401 merge.setMetric(measure.getMetric()); 402 merge.setDescription(measure.getDescription()); 403 merge.setData(measure.getData()); 404 merge.setAlertStatus(measure.getAlertStatus()); 405 merge.setAlertText(measure.getAlertText()); 406 merge.setTendency(measure.getTendency()); 407 merge.setDiffValue1(measure.getDiffValue1()); 408 merge.setDiffValue2(measure.getDiffValue2()); 409 merge.setDiffValue3(measure.getDiffValue3()); 410 merge.setUrl(measure.getUrl()); 411 if (measure.getValue() != null) { 412 merge.setValue(measure.getValue().doubleValue()); 413 } else { 414 merge.setValue(null); 415 } 416 if (measure instanceof RuleMeasure) { 417 RuleMeasure ruleMeasure = (RuleMeasure) measure; 418 merge.setRulesCategoryId(ruleMeasure.getRuleCategory()); 419 merge.setRulePriority(ruleMeasure.getRulePriority()); 420 merge.setRule(ruleMeasure.getRule()); 421 } 422 return merge; 423 } 424 425 public Measure toMeasure() { 426 Measure measure; 427 if (isRuleMeasure()) { 428 measure = new RuleMeasure(getMetric(), getRule(), getRulePriority(), getRulesCategoryId()); 429 } else { 430 measure = new Measure(getMetric()); 431 } 432 measure.setId(getId()); 433 measure.setDescription(getDescription()); 434 measure.setValue(getValue()); 435 measure.setData(getData()); 436 measure.setAlertStatus(getAlertStatus()); 437 measure.setAlertText(getAlertText()); 438 measure.setTendency(getTendency()); 439 measure.setDiffValue1(getDiffValue1()); 440 measure.setDiffValue2(getDiffValue2()); 441 measure.setDiffValue3(getDiffValue3()); 442 measure.setUrl(getUrl()); 443 return measure; 444 } 445 446 public static List<Measure> toMeasures(List<MeasureModel> models) { 447 List<Measure> result = new ArrayList<Measure>(); 448 for (MeasureModel model : models) { 449 if (model != null) { 450 result.add(model.toMeasure()); 451 } 452 } 453 return result; 454 } 455 }