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