1   /*
2    * Copyright 2018 LINE Corporation
3    *
4    * LINE Corporation licenses this file to you under the Apache License,
5    * version 2.0 (the "License"); you may not use this file except in compliance
6    * with the License. You may obtain a copy of the License at:
7    *
8    *   https://www.apache.org/licenses/LICENSE-2.0
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12   * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13   * License for the specific language governing permissions and limitations
14   * under the License.
15   */
16  package com.linecorp.centraldogma.common;
17  
18  import static java.util.Objects.requireNonNull;
19  
20  import com.google.common.base.MoreObjects;
21  
22  /**
23   * A class which contains {@link Revision}s of {@code from} and {@code to}.
24   */
25  public class RevisionRange {
26  
27      private final Revision from;
28  
29      private final Revision to;
30  
31      /**
32       * Creates a new instance with the specified integer value of {@code from} and {@code to}.
33       */
34      public RevisionRange(int from, int to) {
35          this(new Revision(from), new Revision(to));
36      }
37  
38      /**
39       * Creates a new instance with the specified {@code from} {@link Revision} and {@code to} {@link Revision}.
40       */
41      public RevisionRange(Revision from, Revision to) {
42          this.from = requireNonNull(from, "from");
43          this.to = requireNonNull(to, "to");
44      }
45  
46      /**
47       * Returns the {@code from} {@link Revision}.
48       */
49      public Revision from() {
50          return from;
51      }
52  
53      /**
54       * Returns the {@code to} {@link Revision}.
55       */
56      public Revision to() {
57          return to;
58      }
59  
60      /**
61       * Returns the {@link RevisionRange} whose major value of {@code from} {@link Revision} is lower than
62       * or equal to the major value of {@code to} {@link Revision}.
63       *
64       * @throws IllegalStateException if the {@code from} and {@code to} {@link Revision}s are in the
65       *                               different state. They should be either absolute or relative.
66       */
67      public RevisionRange toAscending() {
68          if (isAscending() || from.equals(to)) {
69              return this;
70          }
71  
72          return new RevisionRange(to, from);
73      }
74  
75      /**
76       * Returns the {@link RevisionRange} whose major value of {@code from} {@link Revision} is greater than
77       * or equal to the major value of {@code to} {@link Revision}.
78       *
79       * @throws IllegalStateException if the {@code from} and {@code to} {@link Revision}s are in the
80       *                               different state. They should be either absolute or relative.
81       */
82      public RevisionRange toDescending() {
83          if (isAscending()) {
84              return new RevisionRange(to, from);
85          }
86  
87          return this;
88      }
89  
90      /**
91       * Returns {@code true} if the major value of {@code from} {@link Revision} is lower than the major
92       * value of {@code to} {@link Revision}.
93       *
94       * @throws IllegalStateException if the {@code from} and {@code to} {@link Revision}s are in the
95       *                               different state. They should be either absolute or relative.
96       */
97      public boolean isAscending() {
98          if (from.isRelative() != to.isRelative()) {
99              throw new IllegalStateException("both of from: '" + from + "' and to: '" + to +
100                                             "' should be absolute or relative.");
101         }
102 
103         return from.compareTo(to) < 0;
104     }
105 
106     /**
107      * Returns {@code true} if the major value of {@code from} {@link Revision} or {@code to} {@link Revision}
108      * is a negative integer.
109      */
110     public boolean isRelative() {
111         return from.isRelative() || to.isRelative();
112     }
113 
114     @Override
115     public int hashCode() {
116         return from.hashCode() * 31 + to.hashCode();
117     }
118 
119     @Override
120     public boolean equals(Object o) {
121         if (this == o) {
122             return true;
123         }
124 
125         if (o == null || getClass() != o.getClass()) {
126             return false;
127         }
128 
129         final RevisionRange that = (RevisionRange) o;
130         return from.equals(that.from) && to.equals(that.to);
131     }
132 
133     @Override
134     public String toString() {
135         return MoreObjects.toStringHelper(this)
136                           .add("from", from)
137                           .add("to", to)
138                           .toString();
139     }
140 }