• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

devonfw / IDEasy / 13332186768

14 Feb 2025 03:23PM UTC coverage: 68.473% (+0.004%) from 68.469%
13332186768

push

github

web-flow
#1034: proper fix of VersionRange.contains for version patterns (#1036)

2864 of 4597 branches covered (62.3%)

Branch coverage included in aggregate %.

7396 of 10387 relevant lines covered (71.2%)

3.1 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

86.19
cli/src/main/java/com/devonfw/tools/ide/version/VersionRange.java
1
package com.devonfw.tools.ide.version;
2

3
import java.util.Objects;
4

5
/**
6
 * Container for a range of versions. The lower and upper bounds can be exclusive or inclusive. If a bound is null, it means that this direction is unbounded.
7
 * The boolean defining whether this bound is inclusive or exclusive is ignored in this case.
8
 */
9
public final class VersionRange implements Comparable<VersionRange>, GenericVersionRange {
10

11
  /** The unbounded {@link VersionRange} instance. */
12
  public static final VersionRange UNBOUNDED = new VersionRange(null, null, BoundaryType.OPEN);
8✔
13

14
  private final VersionIdentifier min;
15

16
  private final VersionIdentifier max;
17

18
  private final BoundaryType boundaryType;
19

20
  private static final String VERSION_SEPARATOR = ",";
21

22
  /**
23
   * The constructor.
24
   *
25
   * @param min the {@link #getMin() minimum}.
26
   * @param max the {@link #getMax() maximum}.
27
   * @param boundaryType the {@link BoundaryType} defining whether the boundaries of the range are inclusive or exclusive.
28
   */
29
  private VersionRange(VersionIdentifier min, VersionIdentifier max, BoundaryType boundaryType) {
30

31
    super();
2✔
32
    Objects.requireNonNull(boundaryType);
3✔
33
    this.min = min;
3✔
34
    this.max = max;
3✔
35
    this.boundaryType = boundaryType;
3✔
36
    if ((min != null) && (max != null) && min.isGreater(max)) {
8✔
37
      throw new IllegalArgumentException(toString());
6✔
38
    } else if ((min == null) && !boundaryType.isLeftExclusive()) {
5✔
39
      throw new IllegalArgumentException(toString());
6✔
40
    } else if ((max == null) && !boundaryType.isRightExclusive()) {
5✔
41
      throw new IllegalArgumentException(toString());
6✔
42
    }
43

44
  }
1✔
45

46
  @Override
47
  public VersionIdentifier getMin() {
48

49
    return this.min;
3✔
50
  }
51

52
  @Override
53
  public VersionIdentifier getMax() {
54

55
    return this.max;
3✔
56
  }
57

58
  @Override
59
  public BoundaryType getBoundaryType() {
60

61
    return this.boundaryType;
3✔
62
  }
63

64
  @Override
65
  public boolean isPattern() {
66

67
    return true;
2✔
68
  }
69

70
  @Override
71
  public boolean contains(VersionIdentifier version) {
72

73
    VersionSegment start = version.getStart();
3✔
74
    if ((start.getNumber() == -1) && start.isPattern()) {
7!
75
      return true; // * and *! are always contained
2✔
76
    }
77
    if (this.min != null) {
3!
78
      VersionComparisonResult compareMin = version.compareVersion(this.min);
5✔
79
      if (compareMin.isLess()) {
3✔
80
        return false;
2✔
81
      } else if (compareMin.isEqual() && this.boundaryType.isLeftExclusive() && !version.isPattern()) {
10✔
82
        return false;
2✔
83
      }
84
    }
85
    if (this.max != null) {
3✔
86
      VersionComparisonResult compareMax = version.compareVersion(this.max);
5✔
87
      if (compareMax.isGreater()) {
3✔
88
        return false;
2✔
89
      } else if (compareMax.isEqual() && this.boundaryType.isRightExclusive()) {
7✔
90
        return false;
2✔
91
      }
92
    }
93
    return true;
2✔
94
  }
95

96
  @Override
97
  public int compareTo(VersionRange o) {
98

99
    if (this.min == null) {
3!
100
      if (o == null) {
×
101
        return 1; // should never happen
×
102
      } else if (o.min == null) {
×
103
        return 0;
×
104
      }
105
      return -1;
×
106
    }
107
    int compareMins = this.min.compareTo(o.min);
6✔
108
    if (compareMins == 0) {
2✔
109
      return this.boundaryType.isLeftExclusive() == o.boundaryType.isLeftExclusive() ? 0
10✔
110
          : this.boundaryType.isLeftExclusive() ? 1 : -1;
7✔
111
    } else {
112
      return compareMins;
2✔
113
    }
114
  }
115

116
  @Override
117
  public boolean equals(Object obj) {
118

119
    if (this == obj) {
3✔
120
      return true;
2✔
121
    } else if ((obj == null) || (getClass() != obj.getClass())) {
7!
122
      return false;
2✔
123
    }
124
    VersionRange o = (VersionRange) obj;
3✔
125
    if (this.boundaryType != o.boundaryType) {
5✔
126
      return false;
2✔
127
    } else if (!Objects.equals(this.min, o.min)) {
6✔
128
      return false;
2✔
129
    } else if (!Objects.equals(this.max, o.max)) {
6✔
130
      return false;
2✔
131
    }
132
    return true;
2✔
133
  }
134

135
  @Override
136
  public String toString() {
137

138
    StringBuilder sb = new StringBuilder();
4✔
139
    sb.append(this.boundaryType.getPrefix());
6✔
140
    if (this.min != null) {
3✔
141
      sb.append(this.min);
5✔
142
    }
143
    sb.append(VERSION_SEPARATOR);
4✔
144
    if (this.max != null) {
3✔
145
      sb.append(this.max);
5✔
146
    }
147
    sb.append(this.boundaryType.getSuffix());
6✔
148
    return sb.toString();
3✔
149
  }
150

151
  /**
152
   * @param value the {@link #toString() string representation} of a {@link VersionRange} to parse.
153
   * @return the parsed {@link VersionRange}.
154
   */
155
  public static VersionRange of(String value) {
156

157
    Boolean isleftExclusive = null;
2✔
158
    Boolean isRightExclusive = null;
2✔
159
    if (value.startsWith(BoundaryType.START_EXCLUDING_PREFIX)) {
4✔
160
      isleftExclusive = Boolean.TRUE;
2✔
161
      value = value.substring(BoundaryType.START_EXCLUDING_PREFIX.length());
6✔
162
    } else if (value.startsWith(BoundaryType.START_INCLUDING_PREFIX)) {
4✔
163
      isleftExclusive = Boolean.FALSE;
2✔
164
      value = value.substring(BoundaryType.START_INCLUDING_PREFIX.length());
5✔
165
    }
166
    if (value.endsWith(BoundaryType.END_EXCLUDING_SUFFIX)) {
4✔
167
      isRightExclusive = Boolean.TRUE;
2✔
168
      value = value.substring(0, value.length() - BoundaryType.END_EXCLUDING_SUFFIX.length());
10✔
169
    } else if (value.endsWith(BoundaryType.END_INCLUDING_SUFFIX)) {
4✔
170
      isRightExclusive = Boolean.FALSE;
2✔
171
      value = value.substring(0, value.length() - BoundaryType.END_INCLUDING_SUFFIX.length());
9✔
172
    }
173
    VersionIdentifier min = null;
2✔
174
    VersionIdentifier max = null;
2✔
175
    int index = value.indexOf(VERSION_SEPARATOR);
4✔
176
    if (index < 0) {
2!
177
      min = VersionIdentifier.of(value);
×
178
      max = min;
×
179
    } else {
180
      String minString = value.substring(0, index);
5✔
181
      if (!minString.isBlank()) {
3✔
182
        min = VersionIdentifier.of(minString);
3✔
183
      }
184
      String maxString = value.substring(index + 1);
6✔
185
      if (!maxString.isBlank()) {
3✔
186
        max = VersionIdentifier.of(maxString);
3✔
187
      }
188
    }
189
    if (isleftExclusive == null) {
2✔
190
      isleftExclusive = Boolean.valueOf(min == null);
7✔
191
    }
192
    if (isRightExclusive == null) {
2✔
193
      isRightExclusive = Boolean.valueOf(max == null);
7✔
194
    }
195
    if ((min == null) && (max == null) && isleftExclusive && isRightExclusive) {
10✔
196
      return UNBOUNDED;
2✔
197
    }
198
    return new VersionRange(min, max, BoundaryType.of(isleftExclusive.booleanValue(), isRightExclusive.booleanValue()));
11✔
199
  }
200

201
  /**
202
   * @param min the {@link #getMin() minimum}.
203
   * @param max the {@link #getMax() maximum}.
204
   * @param type the {@link BoundaryType} defining whether the boundaries of the range are inclusive or exclusive.
205
   * @return the {@link VersionRange} created from the given values.
206
   */
207
  public static VersionRange of(VersionIdentifier min, VersionIdentifier max, BoundaryType type) {
208

209
    if (type == null) {
2!
210
      type = BoundaryType.of(min == null, max == null);
×
211
    }
212
    if ((min == null) && (max == null)) {
2!
213
      assert (type == BoundaryType.OPEN);
×
214
      return UNBOUNDED;
×
215
    }
216
    return new VersionRange(min, max, type);
7✔
217
  }
218

219
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc