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 org.apache.commons.lang.StringUtils; 023 import org.apache.commons.lang.builder.ToStringBuilder; 024 import org.apache.commons.lang.builder.ToStringStyle; 025 import org.hibernate.annotations.Sort; 026 import org.hibernate.annotations.SortType; 027 import org.sonar.api.rules.Rule; 028 029 import java.util.*; 030 import javax.persistence.*; 031 032 /** 033 * @since 2.3 034 */ 035 @Entity 036 @Table(name = "characteristics") 037 public final class Characteristic implements Comparable<Characteristic> { 038 039 public static final int ROOT_DEPTH = 1; 040 041 @Id 042 @Column(name = "id") 043 @GeneratedValue 044 private Integer id; 045 046 @Column(name = "kee", nullable = true, length = 100) 047 private String key; 048 049 @Column(name = "name", nullable = true, length = 100) 050 private String name; 051 052 @Column(name = "depth") 053 private int depth=ROOT_DEPTH; 054 055 @Column(name = "characteristic_order") 056 private int order=0; 057 058 @ManyToOne(fetch = FetchType.EAGER) 059 @JoinColumn(name = "quality_model_id") 060 private Model model; 061 062 @ManyToOne(fetch = FetchType.EAGER) 063 @JoinColumn(name = "rule_id") 064 private Rule rule; 065 066 067 @ManyToMany 068 @JoinTable( 069 name = "characteristic_edges", 070 joinColumns = @JoinColumn(name = "child_id", referencedColumnName = "id"), 071 inverseJoinColumns = @JoinColumn(name = "parent_id", 072 referencedColumnName = "id") 073 ) 074 private List<Characteristic> parents = new ArrayList<Characteristic>(); 075 076 @Sort(type = SortType.NATURAL) 077 @ManyToMany(mappedBy = "parents", cascade = CascadeType.ALL) 078 private List<Characteristic> children = new ArrayList<Characteristic>(); 079 080 Characteristic() { 081 } 082 083 public Integer getId() { 084 return id; 085 } 086 087 Characteristic setId(Integer id) { 088 this.id = id; 089 return this; 090 } 091 092 public String getKey() { 093 return key; 094 } 095 096 Characteristic setKey(String s) { 097 this.key = StringUtils.trimToEmpty(s); 098 return this; 099 } 100 101 public String getName() { 102 return name; 103 } 104 105 Characteristic setName(String s, boolean asKey) { 106 this.name = StringUtils.trimToEmpty(s); 107 if (asKey) { 108 this.key = StringUtils.upperCase(this.name); 109 this.key = StringUtils.replaceChars(this.key, ' ', '_'); 110 } 111 return this; 112 } 113 114 public Model getModel() { 115 return model; 116 } 117 118 Characteristic setModel(Model model) { 119 this.model = model; 120 return this; 121 } 122 123 public Rule getRule() { 124 return rule; 125 } 126 127 public Characteristic setRule(Rule r) { 128 this.rule = r; 129 return this; 130 } 131 132 public Characteristic addChildren(Characteristic... list) { 133 if (list != null) { 134 for (Characteristic c : list) { 135 addChild(c); 136 } 137 } 138 return this; 139 } 140 141 public Characteristic addChild(Characteristic child) { 142 propagateDepth(child, depth+1); 143 child.addParents(this); 144 child.setModel(model); 145 children.add(child); 146 return this; 147 } 148 149 private static void propagateDepth(Characteristic characteristic, int depth) { 150 characteristic.setDepth(depth); 151 for (Characteristic child : characteristic.getChildren()) { 152 propagateDepth(child, depth+1); 153 } 154 } 155 156 Characteristic addParents(Characteristic... pc) { 157 if (pc!=null) { 158 Collections.addAll(this.parents, pc); 159 } 160 return this; 161 } 162 163 public List<Characteristic> getParents() { 164 return parents; 165 } 166 167 public Characteristic getParent(String name) { 168 for (Characteristic parent : parents) { 169 if (StringUtils.equals(parent.getName(), name)) { 170 return parent; 171 } 172 } 173 return null; 174 } 175 176 /** 177 * Children sorted by insertion order 178 */ 179 public List<Characteristic> getChildren() { 180 return children; 181 } 182 183 public Characteristic getChild(String name) { 184 for (Characteristic child : children) { 185 if (StringUtils.equals(child.getName(), name)) { 186 return child; 187 } 188 } 189 return null; 190 } 191 192 public int getDepth() { 193 return depth; 194 } 195 196 public boolean isRoot() { 197 return depth==ROOT_DEPTH; 198 } 199 200 Characteristic setDepth(int i) { 201 this.depth = i; 202 return this; 203 } 204 205 public int getOrder() { 206 return order; 207 } 208 209 Characteristic setOrder(int i) { 210 this.order = i; 211 return this; 212 } 213 214 @Override 215 public boolean equals(Object o) { 216 if (this == o) { 217 return true; 218 } 219 if (o == null || getClass() != o.getClass()) { 220 return false; 221 } 222 223 Characteristic that = (Characteristic) o; 224 if (key != null ? !key.equals(that.key) : that.key != null) { 225 return false; 226 } 227 if (rule != null ? !rule.equals(that.rule) : that.rule != null) { 228 return false; 229 } 230 return true; 231 } 232 233 @Override 234 public int hashCode() { 235 int result = key != null ? key.hashCode() : 0; 236 result = 31 * result + (rule != null ? rule.hashCode() : 0); 237 return result; 238 } 239 240 @Override 241 public String toString() { 242 return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE) 243 .append("key", key) 244 .append("name", name) 245 .append("rule", rule) 246 .toString(); 247 } 248 249 public int compareTo(Characteristic o) { 250 if (equals(o)) { 251 return 0; 252 } 253 return order - o.order; 254 } 255 }