001 /* 002 * SonarQube, open source software quality management tool. 003 * Copyright (C) 2008-2013 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 org.apache.commons.lang.StringUtils; 023 import org.apache.commons.lang.builder.EqualsBuilder; 024 import org.apache.commons.lang.builder.HashCodeBuilder; 025 import org.apache.commons.lang.builder.ToStringBuilder; 026 import org.hibernate.annotations.BatchSize; 027 import org.sonar.api.database.BaseIdentifiable; 028 import org.sonar.api.resources.ProjectLink; 029 import org.sonar.api.resources.Resource; 030 031 import javax.persistence.CascadeType; 032 import javax.persistence.Column; 033 import javax.persistence.Entity; 034 import javax.persistence.FetchType; 035 import javax.persistence.OneToMany; 036 import javax.persistence.Table; 037 import javax.persistence.Temporal; 038 import javax.persistence.TemporalType; 039 040 import java.util.ArrayList; 041 import java.util.Date; 042 import java.util.List; 043 044 /** 045 * Class to map resource with hibernate model 046 */ 047 @Entity 048 @Table(name = "projects") 049 public class ResourceModel extends BaseIdentifiable implements Cloneable { 050 051 public static final String SCOPE_PROJECT = "PRJ"; 052 public static final String QUALIFIER_PROJECT_TRUNK = "TRK"; 053 054 public static final int DESCRIPTION_COLUMN_SIZE = 2000; 055 public static final int NAME_COLUMN_SIZE = 256; 056 public static final int KEY_SIZE = 400; 057 058 @Column(name = "name", updatable = true, nullable = true, length = NAME_COLUMN_SIZE) 059 private String name; 060 061 @Column(name = "long_name", updatable = true, nullable = true, length = NAME_COLUMN_SIZE) 062 private String longName; 063 064 @Column(name = "description", updatable = true, nullable = true, length = DESCRIPTION_COLUMN_SIZE) 065 private String description; 066 067 @Column(name = "enabled", updatable = true, nullable = false) 068 private Boolean enabled = Boolean.TRUE; 069 070 @Column(name = "scope", updatable = true, nullable = false, length = 3) 071 private String scope; 072 073 @Column(name = "qualifier", updatable = true, nullable = false, length = 10) 074 private String qualifier; 075 076 @Column(name = "kee", updatable = false, nullable = false, length = KEY_SIZE) 077 private String key; 078 079 @Column(name = "language", updatable = true, nullable = true, length = 20) 080 private String languageKey; 081 082 @Column(name = "root_id", updatable = true, nullable = true) 083 private Integer rootId; 084 085 @Column(name = "copy_resource_id", updatable = true, nullable = true) 086 private Integer copyResourceId; 087 088 @Column(name = "person_id", updatable = true, nullable = true) 089 private Integer personId; 090 091 @Temporal(TemporalType.TIMESTAMP) 092 @Column(name = "created_at", updatable = true, nullable = true) 093 private Date createdAt; 094 095 @OneToMany(mappedBy = "resource", fetch = FetchType.LAZY, cascade = {CascadeType.MERGE, CascadeType.PERSIST, CascadeType.REMOVE}) 096 @BatchSize(size = 8) 097 private List<ProjectLink> projectLinks = new ArrayList<ProjectLink>(); 098 099 /** 100 * Default constructor 101 */ 102 public ResourceModel() { 103 this.createdAt = new Date(); 104 } 105 106 /** 107 * <p>Creates a resource model</p> 108 * 109 * @param scope the scope the rule will apply on 110 * @param key the rule key. This is the name of the resource, including the path 111 * @param qualifier the resource qualifier 112 * @param rootId the rootId for the resource 113 * @param name the short name of the resource 114 */ 115 public ResourceModel(String scope, String key, String qualifier, Integer rootId, String name) { 116 // call this to have the "createdAt" field initialized 117 this(); 118 this.scope = scope; 119 this.key = key; 120 this.rootId = rootId; 121 this.name = name; 122 this.qualifier = qualifier; 123 } 124 125 /** 126 * Only available at project level. 127 */ 128 public List<ProjectLink> getProjectLinks() { 129 return projectLinks; 130 } 131 132 public void setProjectLinks(List<ProjectLink> projectLinks) { 133 this.projectLinks = projectLinks; 134 } 135 136 /** 137 * @return a project link given its key if exists, null otherwise 138 */ 139 public ProjectLink getProjectLink(String key) { 140 for (ProjectLink projectLink : projectLinks) { 141 if (key.equals(projectLink.getKey())) { 142 return projectLink; 143 } 144 } 145 return null; 146 } 147 148 /** 149 * Only available at project level. 150 */ 151 public String getDescription() { 152 return description; 153 } 154 155 /** 156 * Sets the resource description, truncated to DESCRIPTION_COLUMN_SIZE 157 */ 158 public void setDescription(String description) { 159 this.description = StringUtils.abbreviate(description, DESCRIPTION_COLUMN_SIZE); 160 } 161 162 public String getName() { 163 return name; 164 } 165 166 /** 167 * Sets the resource name, truncated to NAME_COLUMN_SIZE 168 */ 169 public void setName(String name) { 170 this.name = StringUtils.abbreviate(name, NAME_COLUMN_SIZE); 171 if (this.longName == null) { 172 this.longName = this.name; 173 } 174 } 175 176 public String getLongName() { 177 return longName; 178 } 179 180 /** 181 * Sets the long name of the resource, truncated to NAME_COLUMN_SIZE 182 */ 183 public void setLongName(String s) { 184 if (StringUtils.isBlank(s)) { 185 this.longName = name; 186 } else { 187 this.longName = StringUtils.abbreviate(s, NAME_COLUMN_SIZE); 188 } 189 } 190 191 public Boolean getEnabled() { 192 return enabled; 193 } 194 195 public void setEnabled(Boolean enabled) { 196 this.enabled = enabled; 197 } 198 199 public String getScope() { 200 return scope; 201 } 202 203 public void setScope(String scope) { 204 this.scope = scope; 205 } 206 207 public String getKey() { 208 return key; 209 } 210 211 public String getLanguageKey() { 212 return languageKey; 213 } 214 215 public void setLanguageKey(String lang) { 216 this.languageKey = lang; 217 } 218 219 public Integer getCopyResourceId() { 220 return copyResourceId; 221 } 222 223 public void setCopyResourceId(Integer i) { 224 this.copyResourceId = i; 225 } 226 227 /** 228 * @since 2.14 229 */ 230 public Integer getPersonId() { 231 return personId; 232 } 233 234 /** 235 * @since 2.14 236 */ 237 public ResourceModel setPersonId(Integer i) { 238 this.personId = i; 239 return this; 240 } 241 242 /** 243 * @throws IllegalArgumentException if the key is longer than KEY_SIZE 244 */ 245 public void setKey(String key) { 246 if (key.length() > KEY_SIZE) { 247 throw new IllegalArgumentException("Resource key is too long, max is " + KEY_SIZE + " characters. Got : " + key); 248 } 249 this.key = key; 250 } 251 252 public Integer getRootId() { 253 return rootId; 254 } 255 256 public void setRootId(Integer rootId) { 257 this.rootId = rootId; 258 } 259 260 public String getQualifier() { 261 return qualifier; 262 } 263 264 public void setQualifier(String qualifier) { 265 this.qualifier = qualifier; 266 } 267 268 public Date getCreatedAt() { 269 return createdAt; // NOSONAR May expose internal representation by returning reference to mutable object 270 } 271 272 public void setCreatedAt(Date createdAt) { 273 this.createdAt = createdAt; // NOSONAR May expose internal representation by returning reference to mutable object 274 } 275 276 @Override 277 public boolean equals(Object obj) { 278 if (!(obj instanceof ResourceModel)) { 279 return false; 280 } 281 if (this == obj) { 282 return true; 283 } 284 ResourceModel other = (ResourceModel) obj; 285 return new EqualsBuilder() 286 .append(key, other.key) 287 .append(enabled, other.enabled) 288 .append(rootId, other.rootId) 289 .isEquals(); 290 } 291 292 @Override 293 public int hashCode() { 294 return new HashCodeBuilder(17, 37) 295 .append(key) 296 .append(enabled) 297 .append(rootId) 298 .toHashCode(); 299 } 300 301 @Override 302 public String toString() { 303 return new ToStringBuilder(this) 304 .append("id", getId()) 305 .append("key", key) 306 .append("scope", scope) 307 .append("qualifier", qualifier) 308 .append("name", name) 309 .append("longName", longName) 310 .append("lang", languageKey) 311 .append("enabled", enabled) 312 .append("rootId", rootId) 313 .append("copyResourceId", copyResourceId) 314 .append("personId", personId) 315 .append("createdAt", createdAt) 316 .toString(); 317 } 318 319 @Override 320 public Object clone() { 321 ResourceModel clone = new ResourceModel(getScope(), getKey(), getQualifier(), getRootId(), getName()); 322 clone.setDescription(getDescription()); 323 clone.setEnabled(getEnabled()); 324 clone.setProjectLinks(getProjectLinks()); 325 clone.setLanguageKey(getLanguageKey()); 326 clone.setCopyResourceId(getCopyResourceId()); 327 clone.setLongName(getLongName()); 328 clone.setPersonId(getPersonId()); 329 clone.setCreatedAt(getCreatedAt()); 330 return clone; 331 } 332 333 /** 334 * Maps a resource to a resource model and returns the resource 335 */ 336 public static ResourceModel build(Resource resource) { 337 ResourceModel model = new ResourceModel(); 338 model.setEnabled(Boolean.TRUE); 339 model.setDescription(resource.getDescription()); 340 model.setKey(resource.getKey()); 341 if (resource.getLanguage() != null) { 342 model.setLanguageKey(resource.getLanguage().getKey()); 343 } 344 if (StringUtils.isNotBlank(resource.getName())) { 345 model.setName(resource.getName()); 346 } else { 347 model.setName(resource.getKey()); 348 } 349 model.setLongName(resource.getLongName()); 350 model.setQualifier(resource.getQualifier()); 351 model.setScope(resource.getScope()); 352 return model; 353 } 354 355 }