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.EqualsBuilder;
023 import org.apache.commons.lang.builder.HashCodeBuilder;
024 import org.apache.commons.lang.builder.ToStringBuilder;
025 import org.sonar.api.database.BaseIdentifiable;
026 import org.sonar.api.database.DatabaseSession;
027
028 import java.util.Date;
029 import javax.persistence.*;
030
031 /**
032 * A class to map a snapshot with its hibernate model
033 */
034 @Entity
035 @Table(name = "snapshots")
036 public class Snapshot extends BaseIdentifiable {
037
038 /**
039 * This status is set on the snapshot at the beginning of the batch
040 */
041 public final static String STATUS_UNPROCESSED = "U";
042
043 /**
044 * This status is set on the snapshot at the end of the batch
045 */
046 public final static String STATUS_PROCESSED = "P";
047
048 @Column(name = "project_id", updatable = true, nullable = true)
049 private Integer resourceId;
050
051 @Temporal(TemporalType.TIMESTAMP)
052 @Column(name = "created_at", updatable = true, nullable = true)
053 private Date createdAt;
054
055 @Column(name = "version", updatable = true, nullable = true, length = 60)
056 private String version;
057
058 @Column(name = "islast")
059 private Boolean last = Boolean.FALSE;
060
061 @Column(name = "status")
062 private String status = STATUS_UNPROCESSED;
063
064 @Column(name = "scope", updatable = true, nullable = true, length = 3)
065 private String scope;
066
067 @Column(name = "path", updatable = true, nullable = true, length = 96)
068 private String path;
069
070 @Column(name = "depth", updatable = true, nullable = true)
071 private Integer depth;
072
073 @Column(name = "qualifier", updatable = true, nullable = true, length = 3)
074 private String qualifier;
075
076 @Column(name = "root_snapshot_id", updatable = true, nullable = true)
077 private Integer rootId;
078
079 @Column(name = "parent_snapshot_id", updatable = true, nullable = true)
080 private Integer parentId;
081
082 @Column(name = "root_project_id", updatable = true, nullable = true)
083 private Integer rootProjectId;
084
085 public Snapshot() {
086
087 }
088
089 public Snapshot(ResourceModel resource, Snapshot parent) {
090 this.resourceId = resource.getId();
091 this.qualifier = resource.getQualifier();
092 this.scope = resource.getScope();
093
094 if (parent == null) {
095 path = "";
096 depth = 0;
097 this.createdAt = new Date();
098
099 } else {
100 this.parentId = parent.getId();
101 this.rootId = (parent.getRootId() == null ? parent.getId() : parent.getRootId());
102 this.createdAt = parent.getCreatedAt();
103 this.depth = parent.getDepth() + 1;
104 this.path = new StringBuilder()
105 .append(parent.getPath())
106 .append(parent.getId())
107 .append(".")
108 .toString();
109 }
110 this.rootProjectId = guessRootProjectId(resource, parent);
111 }
112
113 private static Integer guessRootProjectId(ResourceModel resource, Snapshot parent) {
114 Integer result;
115
116 // design problem : constants are defined in the Resource class, that should not be used by this class...
117 if ("TRK".equals(resource.getQualifier()) || "VW".equals(resource.getQualifier()) || "SVW".equals(resource.getQualifier())) {
118 result = resource.getCopyResourceId() != null ? resource.getCopyResourceId() : resource.getId();
119
120 } else if (parent == null) {
121 result = resource.getCopyResourceId() != null ? resource.getCopyResourceId() : resource.getId();
122
123 } else {
124 result = (parent.getRootProjectId() == null ? parent.getResourceId() : parent.getRootProjectId());
125 }
126 return result;
127 }
128
129 public Snapshot save(DatabaseSession session) {
130 return session.save(this);
131 }
132
133 public Snapshot(ResourceModel resource, boolean last, String status, Date date) {
134 this();
135 setResource(resource);
136 this.status = status;
137 this.last = last;
138 this.createdAt = date;
139 }
140
141 public Date getCreatedAt() {
142 return createdAt;
143 }
144
145 public void setCreatedAt(Date createdAt) {
146 this.createdAt = createdAt;
147 }
148
149 public Integer getResourceId() {
150 return resourceId;
151 }
152
153 public void setResourceId(Integer resourceId) {
154 this.resourceId = resourceId;
155 }
156
157 public final void setResource(ResourceModel resource) {
158 this.resourceId = resource.getId();
159 this.scope = resource.getScope();
160 this.qualifier = resource.getQualifier();
161 }
162
163 public String getVersion() {
164 return version;
165 }
166
167 public void setVersion(String version) {
168 this.version = version;
169 }
170
171 public Integer getParentId() {
172 return parentId;
173 }
174
175 public void setParentId(Integer i) {
176 this.parentId = i;
177 }
178
179 public Boolean getLast() {
180 return last;
181 }
182
183 public void setLast(Boolean last) {
184 this.last = last;
185 }
186
187 public String getStatus() {
188 return status;
189 }
190
191 public void setStatus(String status) {
192 this.status = status;
193 }
194
195 public String getScope() {
196 return scope;
197 }
198
199 public void setScope(String scope) {
200 this.scope = scope;
201 }
202
203 public String getQualifier() {
204 return qualifier;
205 }
206
207 public void setQualifier(String qualifier) {
208 this.qualifier = qualifier;
209 }
210
211 public Integer getRootId() {
212 return rootId;
213 }
214
215 public void setRootId(Integer i) {
216 this.rootId = i;
217 }
218
219 public String getPath() {
220 return path;
221 }
222
223 public void setPath(String path) {
224 this.path = path;
225 }
226
227 public Integer getDepth() {
228 return depth;
229 }
230
231 public Integer getRootProjectId() {
232 return rootProjectId;
233 }
234
235 public void setRootProjectId(Integer rootProjectId) {
236 this.rootProjectId = rootProjectId;
237 }
238
239 /**
240 * Sets the depth of the snapshot
241 *
242 * @throws IllegalArgumentException when depth is negative
243 */
244 public void setDepth(Integer depth) {
245 if (depth != null && depth < 0) {
246 throw new IllegalArgumentException("depth can not be negative : " + depth);
247 }
248 this.depth = depth;
249 }
250
251
252 @Override
253 public boolean equals(Object obj) {
254 if (!(obj instanceof Snapshot)) {
255 return false;
256 }
257 if (this == obj) {
258 return true;
259 }
260 Snapshot other = (Snapshot) obj;
261 return new EqualsBuilder()
262 .append(resourceId, other.getResourceId())
263 .append(createdAt, other.getCreatedAt())
264 .isEquals();
265 }
266
267 @Override
268 public int hashCode() {
269 return new HashCodeBuilder(17, 37)
270 .append(resourceId)
271 .append(createdAt)
272 .toHashCode();
273 }
274
275 @Override
276 public String toString() {
277 return new ToStringBuilder(this)
278 .append("id", getId())
279 .append("resourceId", resourceId)
280 .append("scope", scope)
281 .append("qualifier", qualifier)
282 .append("version", version)
283 .append("last", last)
284 .append("createdAt", createdAt)
285 .append("status", status)
286 .append("path", path)
287 .append("rootId", rootId)
288 .append("rootProjectId", rootProjectId)
289 .append("parentId", parentId)
290 .toString();
291 }
292 }