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.qualitymodel; 021 022 import com.google.common.collect.Lists; 023 import org.apache.commons.lang.StringUtils; 024 import org.apache.commons.lang.builder.ToStringBuilder; 025 import org.apache.commons.lang.builder.ToStringStyle; 026 import org.hibernate.annotations.Sort; 027 import org.hibernate.annotations.SortType; 028 import org.sonar.api.rules.Rule; 029 030 import javax.persistence.*; 031 import java.util.Collections; 032 import java.util.List; 033 034 /** 035 * @since 2.3 036 */ 037 @Entity 038 @Table(name = "characteristics") 039 public final class Characteristic implements Comparable<Characteristic> { 040 041 public static final int ROOT_DEPTH = 1; 042 043 @Id 044 @Column(name = "id") 045 @GeneratedValue 046 private Integer id; 047 048 @Column(name = "kee", nullable = true, length = 100) 049 private String key; 050 051 @Column(name = "name", nullable = true, length = 100) 052 private String name; 053 054 @Column(name = "depth") 055 private int depth = ROOT_DEPTH; 056 057 @Column(name = "characteristic_order") 058 private int order = 0; 059 060 @ManyToOne(fetch = FetchType.EAGER) 061 @JoinColumn(name = "quality_model_id") 062 private Model model; 063 064 @ManyToOne(fetch = FetchType.EAGER) 065 @JoinColumn(name = "rule_id") 066 private Rule rule; 067 068 @Column(name = "description", nullable = true, length = 4000) 069 private String description; 070 071 @Column(name = "enabled", updatable = true, nullable = true) 072 private Boolean enabled = Boolean.TRUE; 073 074 @ManyToMany 075 @JoinTable( 076 name = "characteristic_edges", 077 joinColumns = @JoinColumn(name = "child_id", referencedColumnName = "id"), 078 inverseJoinColumns = @JoinColumn(name = "parent_id", 079 referencedColumnName = "id") 080 ) 081 private List<Characteristic> parents = Lists.newArrayList(); 082 083 @Sort(type = SortType.NATURAL) 084 @ManyToMany(mappedBy = "parents", cascade = CascadeType.ALL) 085 private List<Characteristic> children = Lists.newArrayList(); 086 087 @OneToMany(mappedBy = "characteristic", fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE}) 088 private List<CharacteristicProperty> properties = Lists.newArrayList(); 089 090 Characteristic() { 091 } 092 093 public Integer getId() { 094 return id; 095 } 096 097 Characteristic setId(Integer id) { 098 this.id = id; 099 return this; 100 } 101 102 public String getKey() { 103 return key; 104 } 105 106 public Characteristic setKey(String s) { 107 this.key = StringUtils.trimToNull(s); 108 return this; 109 } 110 111 public String getName() { 112 return name; 113 } 114 115 public Characteristic setName(String s) { 116 return setName(s, false); 117 } 118 public Characteristic setName(String s, boolean asKey) { 119 this.name = StringUtils.trimToNull(s); 120 if (asKey) { 121 this.key = StringUtils.upperCase(this.name); 122 this.key = StringUtils.replaceChars(this.key, ' ', '_'); 123 } 124 return this; 125 } 126 127 public Model getModel() { 128 return model; 129 } 130 131 Characteristic setModel(Model model) { 132 this.model = model; 133 return this; 134 } 135 136 public Rule getRule() { 137 return rule; 138 } 139 140 public boolean hasRule() { 141 return rule!=null; 142 } 143 144 public Characteristic setRule(Rule r) { 145 this.rule = r; 146 return this; 147 } 148 149 public Boolean getEnabled() { 150 return enabled; 151 } 152 153 public Characteristic setEnabled(Boolean b) { 154 this.enabled = b; 155 return this; 156 } 157 158 public Characteristic addChildren(Characteristic... list) { 159 if (list != null) { 160 for (Characteristic c : list) { 161 addChild(c); 162 } 163 } 164 return this; 165 } 166 167 public Characteristic addChild(Characteristic child) { 168 propagateDepth(child, depth + 1); 169 child.addParents(this); 170 child.setModel(model); 171 children.add(child); 172 return this; 173 } 174 175 Characteristic removeChild(Characteristic child) { 176 children.remove(child); 177 return this; 178 } 179 180 private static void propagateDepth(Characteristic characteristic, int depth) { 181 characteristic.setDepth(depth); 182 for (Characteristic child : characteristic.getChildren()) { 183 propagateDepth(child, depth + 1); 184 } 185 } 186 187 Characteristic addParents(Characteristic... pc) { 188 if (pc != null) { 189 Collections.addAll(this.parents, pc); 190 } 191 return this; 192 } 193 194 public List<Characteristic> getParents() { 195 return parents; 196 } 197 198 public Characteristic getParent(String name) { 199 for (Characteristic parent : parents) { 200 if (StringUtils.equals(parent.getName(), name)) { 201 return parent; 202 } 203 } 204 return null; 205 } 206 207 /** 208 * Children sorted by insertion order 209 */ 210 public List<Characteristic> getChildren() { 211 return children; 212 } 213 214 public Characteristic getChild(String name) { 215 for (Characteristic child : children) { 216 if (StringUtils.equals(child.getName(), name)) { 217 return child; 218 } 219 } 220 return null; 221 } 222 223 public int getDepth() { 224 return depth; 225 } 226 227 public boolean isRoot() { 228 return depth == ROOT_DEPTH; 229 } 230 231 Characteristic setDepth(int i) { 232 this.depth = i; 233 return this; 234 } 235 236 public int getOrder() { 237 return order; 238 } 239 240 Characteristic setOrder(int i) { 241 this.order = i; 242 return this; 243 } 244 245 public String getDescription() { 246 return description; 247 } 248 249 public Characteristic setDescription(String s) { 250 this.description = s; 251 return this; 252 } 253 254 public CharacteristicProperty setProperty(String key, String value) { 255 return addProperty(CharacteristicProperty.create(key).setTextValue(value)); 256 } 257 258 public CharacteristicProperty setProperty(String key, Double value) { 259 return addProperty(CharacteristicProperty.create(key).setValue(value)); 260 } 261 262 public CharacteristicProperty addProperty(CharacteristicProperty property) { 263 property.setCharacteristic(this); 264 properties.add(property); 265 return property; 266 } 267 268 public CharacteristicProperty getProperty(String key) { 269 for (CharacteristicProperty property : properties) { 270 if (StringUtils.equals(key, property.getKey())) { 271 return property; 272 } 273 } 274 return null; 275 } 276 277 public String getPropertyTextValue(String key, String defaultValue) { 278 CharacteristicProperty property = getProperty(key); 279 String value = property != null ? property.getTextValue() : null; 280 return StringUtils.defaultIfEmpty(value, defaultValue); 281 } 282 283 public Double getPropertyValue(String key, Double defaultValue) { 284 CharacteristicProperty property = getProperty(key); 285 Double value = (property != null ? property.getValue() : null); 286 return value==null ? defaultValue : value; 287 } 288 289 public List<CharacteristicProperty> getProperties() { 290 return properties; 291 } 292 293 @Override 294 public boolean equals(Object o) { 295 if (this == o) { 296 return true; 297 } 298 if (o == null || getClass() != o.getClass()) { 299 return false; 300 } 301 302 Characteristic that = (Characteristic) o; 303 if (key != null ? !key.equals(that.key) : that.key != null) { 304 return false; 305 } 306 if (rule != null ? !rule.equals(that.rule) : that.rule != null) { 307 return false; 308 } 309 return true; 310 } 311 312 @Override 313 public int hashCode() { 314 int result = key != null ? key.hashCode() : 0; 315 result = 31 * result + (rule != null ? rule.hashCode() : 0); 316 return result; 317 } 318 319 @Override 320 public String toString() { 321 return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) 322 .append("key", key) 323 .append("name", name) 324 .append("rule", rule) 325 .append("description", description) 326 .toString(); 327 } 328 329 public int compareTo(Characteristic o) { 330 if (equals(o)) { 331 return 0; 332 } 333 return order - o.order; 334 } 335 336 public static Characteristic create() { 337 return new Characteristic(); 338 } 339 340 public static Characteristic createByName(String name) { 341 return new Characteristic().setName(name, true); 342 } 343 344 public static Characteristic createByKey(String key, String name) { 345 return new Characteristic().setKey(key).setName(name, false); 346 } 347 348 public static Characteristic createByRule(Rule rule) { 349 return new Characteristic().setRule(rule); 350 } 351 }