001/*
002 * Sonar, open source software quality management tool.
003 * Copyright (C) 2008-2012 SonarSource
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 */
020package org.sonar.api.database.model;
021
022import org.apache.commons.lang.builder.EqualsBuilder;
023import org.apache.commons.lang.builder.HashCodeBuilder;
024import org.apache.commons.lang.builder.ReflectionToStringBuilder;
025import org.apache.commons.lang.builder.ToStringStyle;
026import org.sonar.api.database.BaseIdentifiable;
027import org.sonar.api.database.DatabaseSession;
028
029import javax.persistence.*;
030
031import java.util.Date;
032
033/**
034 * A class to map a snapshot with its hibernate model
035 */
036@Entity
037@Table(name = "snapshots")
038public class Snapshot extends BaseIdentifiable {
039
040  /**
041   * This status is set on the snapshot at the beginning of the batch
042   */
043  public static final String STATUS_UNPROCESSED = "U";
044
045  /**
046   * This status is set on the snapshot at the end of the batch
047   */
048  public static final String STATUS_PROCESSED = "P";
049
050  @Column(name = "project_id", updatable = true, nullable = true)
051  private Integer resourceId;
052
053  @Temporal(TemporalType.TIMESTAMP)
054  @Column(name = "build_date", updatable = true, nullable = true)
055  private Date buildDate;
056
057  @Temporal(TemporalType.TIMESTAMP)
058  @Column(name = "created_at", updatable = true, nullable = true)
059  private Date createdAt;
060
061  @Column(name = "version", updatable = true, nullable = true, length = 500)
062  private String version;
063
064  @Column(name = "islast")
065  private Boolean last = Boolean.FALSE;
066
067  @Column(name = "status")
068  private String status = STATUS_UNPROCESSED;
069
070  @Column(name = "purge_status", updatable = true, nullable = true)
071  private Integer purgeStatus;
072
073  @Column(name = "scope", updatable = true, nullable = true, length = 3)
074  private String scope;
075
076  @Column(name = "path", updatable = true, nullable = true, length = 500)
077  private String path;
078
079  @Column(name = "depth", updatable = true, nullable = true)
080  private Integer depth;
081
082  @Column(name = "qualifier", updatable = true, nullable = true, length = 10)
083  private String qualifier;
084
085  @Column(name = "root_snapshot_id", updatable = true, nullable = true)
086  private Integer rootId;
087
088  @Column(name = "parent_snapshot_id", updatable = true, nullable = true)
089  private Integer parentId;
090
091  @Column(name = "root_project_id", updatable = true, nullable = true)
092  private Integer rootProjectId;
093
094  @Column(name = "period1_mode", updatable = true, nullable = true, length = 100)
095  private String period1Mode;
096
097  @Column(name = "period2_mode", updatable = true, nullable = true, length = 100)
098  private String period2Mode;
099
100  @Column(name = "period3_mode", updatable = true, nullable = true, length = 100)
101  private String period3Mode;
102
103  @Column(name = "period4_mode", updatable = true, nullable = true, length = 100)
104  private String period4Mode;
105
106  @Column(name = "period5_mode", updatable = true, nullable = true, length = 100)
107  private String period5Mode;
108
109  @Column(name = "period1_param", updatable = true, nullable = true, length = 100)
110  private String period1Param;
111
112  @Column(name = "period2_param", updatable = true, nullable = true, length = 100)
113  private String period2Param;
114
115  @Column(name = "period3_param", updatable = true, nullable = true, length = 100)
116  private String period3Param;
117
118  @Column(name = "period4_param", updatable = true, nullable = true, length = 100)
119  private String period4Param;
120
121  @Column(name = "period5_param", updatable = true, nullable = true, length = 100)
122  private String period5Param;
123
124  @Column(name = "period1_date", updatable = true, nullable = true)
125  private Date period1Date;
126
127  @Column(name = "period2_date", updatable = true, nullable = true)
128  private Date period2Date;
129
130  @Column(name = "period3_date", updatable = true, nullable = true)
131  private Date period3Date;
132
133  @Column(name = "period4_date", updatable = true, nullable = true)
134  private Date period4Date;
135
136  @Column(name = "period5_date", updatable = true, nullable = true)
137  private Date period5Date;
138
139  public Snapshot() {
140
141  }
142
143  public Snapshot(ResourceModel resource, Snapshot parent) {
144    this.resourceId = resource.getId();
145    this.qualifier = resource.getQualifier();
146    this.scope = resource.getScope();
147
148    if (parent == null) {
149      path = "";
150      depth = 0;
151      this.createdAt = new Date();
152
153    } else {
154      this.parentId = parent.getId();
155      this.rootId = (parent.getRootId() == null ? parent.getId() : parent.getRootId());
156      this.createdAt = parent.getCreatedAt();
157      this.depth = parent.getDepth() + 1;
158      this.path = new StringBuilder()
159        .append(parent.getPath())
160        .append(parent.getId())
161        .append(".")
162        .toString();
163    }
164    this.rootProjectId = guessRootProjectId(resource, parent);
165  }
166
167  private static Integer guessRootProjectId(ResourceModel resource, Snapshot parent) {
168    Integer result;
169
170    // design problem : constants are defined in the Resource class, that should not be used by this class...
171    if ("TRK".equals(resource.getQualifier()) || "VW".equals(resource.getQualifier()) || "SVW".equals(resource.getQualifier())) {
172      result = resource.getCopyResourceId() != null ? resource.getCopyResourceId() : resource.getId();
173
174    } else if (parent == null) {
175      result = resource.getCopyResourceId() != null ? resource.getCopyResourceId() : resource.getId();
176
177    } else {
178      result = (parent.getRootProjectId() == null ? parent.getResourceId() : parent.getRootProjectId());
179    }
180    return result;
181  }
182
183  public Snapshot save(DatabaseSession session) {
184    return session.save(this);
185  }
186
187  public Snapshot(ResourceModel resource, boolean last, String status, Date date) {
188    this();
189    setResource(resource);
190    this.status = status;
191    this.last = last;
192    this.createdAt = date;
193  }
194
195  /**
196   * Insertion date (technical)
197   *
198   * @since 2.14
199   */
200  public Date getBuildDate() {
201    return buildDate;
202  }
203
204  /**
205   * Insertion date (technical)
206   *
207   * @since 2.14
208   */
209  public Snapshot setBuildDate(Date d) {
210    this.buildDate = d;
211    return this;
212  }
213
214  public Date getCreatedAt() {
215    return createdAt;
216  }
217
218  public Snapshot setCreatedAt(Date createdAt) {
219    this.createdAt = createdAt;
220    return this;
221  }
222
223  public Integer getResourceId() {
224    return resourceId;
225  }
226
227  public Snapshot setResourceId(Integer resourceId) {
228    this.resourceId = resourceId;
229    return this;
230  }
231
232  public final Snapshot setResource(ResourceModel resource) {
233    this.resourceId = resource.getId();
234    this.scope = resource.getScope();
235    this.qualifier = resource.getQualifier();
236    return this;
237  }
238
239  public String getVersion() {
240    return version;
241  }
242
243  public Snapshot setVersion(String version) {
244    this.version = version;
245    return this;
246  }
247
248  public Integer getParentId() {
249    return parentId;
250  }
251
252  public Snapshot setParentId(Integer i) {
253    this.parentId = i;
254    return this;
255  }
256
257  public Boolean getLast() {
258    return last;
259  }
260
261  public Snapshot setLast(Boolean last) {
262    this.last = last;
263    return this;
264  }
265
266  public String getStatus() {
267    return status;
268  }
269
270  public Snapshot setStatus(String status) {
271    this.status = status;
272    return this;
273  }
274
275  /**
276   * @since 2.14
277   */
278  public Integer getPurgeStatus() {
279    return purgeStatus;
280  }
281
282  /**
283     * @since 2.14
284     */
285  public Snapshot setPurgeStatus(Integer i) {
286    this.purgeStatus = i;
287    return this;
288  }
289
290  public String getScope() {
291    return scope;
292  }
293
294  public Snapshot setScope(String scope) {
295    this.scope = scope;
296    return this;
297  }
298
299  public String getQualifier() {
300    return qualifier;
301  }
302
303  public Snapshot setQualifier(String qualifier) {
304    this.qualifier = qualifier;
305    return this;
306  }
307
308  public Integer getRootId() {
309    return rootId;
310  }
311
312  public Snapshot setRootId(Integer i) {
313    this.rootId = i;
314    return this;
315  }
316
317  public String getPath() {
318    return path;
319  }
320
321  public Snapshot setPath(String path) {
322    this.path = path;
323    return this;
324  }
325
326  public Integer getDepth() {
327    return depth;
328  }
329
330  public Integer getRootProjectId() {
331    return rootProjectId;
332  }
333
334  public Snapshot setRootProjectId(Integer rootProjectId) {
335    this.rootProjectId = rootProjectId;
336    return this;
337  }
338
339  /**
340   * Sets the depth of the snapshot
341   *
342   * @throws IllegalArgumentException when depth is negative
343   */
344  public void setDepth(Integer depth) {
345    if (depth != null && depth < 0) {
346      throw new IllegalArgumentException("depth can not be negative : " + depth);
347    }
348    this.depth = depth;
349  }
350
351  public String getPeriod1Mode() {
352    return period1Mode;
353  }
354
355  /**
356   * For internal use.
357   *
358   * @since 2.5
359   */
360  public Snapshot setPeriod1Mode(String s) {
361    this.period1Mode = s;
362    return this;
363  }
364
365  public String getPeriod2Mode() {
366    return period2Mode;
367  }
368
369  /**
370   * For internal use.
371   *
372   * @since 2.5
373   */
374  public Snapshot setPeriod2Mode(String s) {
375    this.period2Mode = s;
376    return this;
377  }
378
379  public String getPeriod3Mode() {
380    return period3Mode;
381  }
382
383  /**
384   * For internal use.
385   *
386   * @since 2.5
387   */
388  public Snapshot setPeriod3Mode(String s) {
389    this.period3Mode = s;
390    return this;
391  }
392
393  public String getPeriod4Mode() {
394    return period4Mode;
395  }
396
397  /**
398   * For internal use.
399   *
400   * @since 2.5
401   */
402  public Snapshot setPeriod4Mode(String s) {
403    this.period4Mode = s;
404    return this;
405  }
406
407  public String getPeriod5Mode() {
408    return period5Mode;
409  }
410
411  /**
412   * For internal use.
413   *
414   * @since 2.5
415   */
416  public Snapshot setPeriod5Mode(String s) {
417    this.period5Mode = s;
418    return this;
419  }
420
421  public String getPeriod1Param() {
422    return period1Param;
423  }
424
425  /**
426   * For internal use.
427   *
428   * @since 2.5
429   */
430  public Snapshot setPeriod1Param(String s) {
431    this.period1Param = s;
432    return this;
433  }
434
435  public String getPeriod2Param() {
436    return period2Param;
437  }
438
439  /**
440   * For internal use.
441   *
442   * @since 2.5
443   */
444  public Snapshot setPeriod2Param(String s) {
445    this.period2Param = s;
446    return this;
447  }
448
449  public String getPeriod3Param() {
450    return period3Param;
451  }
452
453  /**
454   * For internal use.
455   *
456   * @since 2.5
457   */
458  public Snapshot setPeriod3Param(String s) {
459    this.period3Param = s;
460    return this;
461  }
462
463  public String getPeriod4Param() {
464    return period4Param;
465  }
466
467  /**
468   * For internal use.
469   *
470   * @since 2.5
471   */
472  public Snapshot setPeriod4Param(String s) {
473    this.period4Param = s;
474    return this;
475  }
476
477  public String getPeriod5Param() {
478    return period5Param;
479  }
480
481  /**
482   * For internal use.
483   *
484   * @since 2.5
485   */
486  public Snapshot setPeriod5Param(String s) {
487    this.period5Param = s;
488    return this;
489  }
490
491  public Date getPeriod1Date() {
492    return period1Date;
493  }
494
495  /**
496   * For internal use.
497   *
498   * @since 2.5
499   */
500  public Snapshot setPeriod1Date(Date period1Date) {
501    this.period1Date = period1Date;
502    return this;
503  }
504
505  public Date getPeriod2Date() {
506    return period2Date;
507  }
508
509  /**
510   * For internal use.
511   *
512   * @since 2.5
513   */
514  public Snapshot setPeriod2Date(Date period2Date) {
515    this.period2Date = period2Date;
516    return this;
517  }
518
519  public Date getPeriod3Date() {
520    return period3Date;
521  }
522
523  /**
524   * For internal use.
525   *
526   * @since 2.5
527   */
528  public Snapshot setPeriod3Date(Date period3Date) {
529    this.period3Date = period3Date;
530    return this;
531  }
532
533  public Date getPeriod4Date() {
534    return period4Date;
535  }
536
537  /**
538   * For internal use.
539   *
540   * @since 2.5
541   */
542  public Snapshot setPeriod4Date(Date period4Date) {
543    this.period4Date = period4Date;
544    return this;
545  }
546
547  public Date getPeriod5Date() {
548    return period5Date;
549  }
550
551  /**
552   * For internal use.
553   *
554   * @since 2.5
555   */
556  public Snapshot setPeriod5Date(Date period5Date) {
557    this.period5Date = period5Date;
558    return this;
559  }
560
561  /**
562   * For internal use.
563   *
564   * @since 2.5
565   */
566  public Snapshot setPeriodMode(int periodIndex, String s) {
567    switch (periodIndex) {
568      case 1:
569        period1Mode = s;
570        break;
571      case 2:
572        period2Mode = s;
573        break;
574      case 3:
575        period3Mode = s;
576        break;
577      case 4:
578        period4Mode = s;
579        break;
580      case 5:
581        period5Mode = s;
582        break;
583      default:
584        throw new IndexOutOfBoundsException("Index of Snapshot.periodMode is between 1 and 5");
585    }
586    return this;
587  }
588
589  public String getPeriodMode(int index) {
590    switch (index) {
591      case 1:
592        return period1Mode;
593      case 2:
594        return period2Mode;
595      case 3:
596        return period3Mode;
597      case 4:
598        return period4Mode;
599      case 5:
600        return period5Mode;
601      default:
602        throw new IndexOutOfBoundsException("Index of Snapshot.periodMode is between 1 and 5");
603    }
604  }
605
606  /**
607   * For internal use.
608   *
609   * @since 2.5
610   */
611  public Snapshot setPeriodModeParameter(int periodIndex, String s) {
612    switch (periodIndex) {
613      case 1:
614        period1Param = s;
615        break;
616      case 2:
617        period2Param = s;
618        break;
619      case 3:
620        period3Param = s;
621        break;
622      case 4:
623        period4Param = s;
624        break;
625      case 5:
626        period5Param = s;
627        break;
628      default:
629        throw new IndexOutOfBoundsException("Index of Snapshot.periodModeParameter is between 1 and 5");
630    }
631    return this;
632  }
633
634  public String getPeriodModeParameter(int periodIndex) {
635    switch (periodIndex) {
636      case 1:
637        return period1Param;
638      case 2:
639        return period2Param;
640      case 3:
641        return period3Param;
642      case 4:
643        return period4Param;
644      case 5:
645        return period5Param;
646      default:
647        throw new IndexOutOfBoundsException("Index of Snapshot.periodModeParameter is between 1 and 5");
648    }
649  }
650
651  /**
652   * For internal use.
653   *
654   * @since 2.5
655   */
656  public Snapshot setPeriodDate(int periodIndex, Date d) {
657    switch (periodIndex) {
658      case 1:
659        period1Date = d;
660        break;
661      case 2:
662        period2Date = d;
663        break;
664      case 3:
665        period3Date = d;
666        break;
667      case 4:
668        period4Date = d;
669        break;
670      case 5:
671        period5Date = d;
672        break;
673      default:
674        throw new IndexOutOfBoundsException("Index of Snapshot.periodDate is between 1 and 5");
675    }
676    return this;
677  }
678
679  public Date getPeriodDate(int periodIndex) {
680    switch (periodIndex) {
681      case 1:
682        return period1Date;
683      case 2:
684        return period2Date;
685      case 3:
686        return period3Date;
687      case 4:
688        return period4Date;
689      case 5:
690        return period5Date;
691      default:
692        throw new IndexOutOfBoundsException("Index of Snapshot.periodDate is between 1 and 5");
693    }
694  }
695
696  @Override
697  public boolean equals(Object obj) {
698    if (!(obj instanceof Snapshot)) {
699      return false;
700    }
701    if (this == obj) {
702      return true;
703    }
704    Snapshot other = (Snapshot) obj;
705    return new EqualsBuilder()
706      .append(resourceId, other.getResourceId())
707      .append(createdAt, other.getCreatedAt())
708      .isEquals();
709  }
710
711  @Override
712  public int hashCode() {
713    return new HashCodeBuilder(17, 37)
714      .append(resourceId)
715      .append(createdAt)
716      .toHashCode();
717  }
718
719  @Override
720  public String toString() {
721    return new ReflectionToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE).toString();
722  }
723}