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

devonfw / IDEasy / 13038836781

29 Jan 2025 07:22PM UTC coverage: 68.163% (-0.3%) from 68.45%
13038836781

Pull #957

github

web-flow
Merge cc3109b40 into 5300a96fe
Pull Request #957: #786: Upgrade commandlet

2833 of 4553 branches covered (62.22%)

Branch coverage included in aggregate %.

7324 of 10348 relevant lines covered (70.78%)

3.08 hits per line

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

87.42
cli/src/main/java/com/devonfw/tools/ide/version/VersionIdentifier.java
1
package com.devonfw.tools.ide.version;
2

3
import java.util.Objects;
4

5
/**
6
 * Data-type to represent a {@link VersionIdentifier} in a structured way and allowing {@link #compareVersion(VersionIdentifier) comparison} of
7
 * {@link VersionIdentifier}s.
8
 */
9
public final class VersionIdentifier implements VersionObject<VersionIdentifier>, GenericVersionRange {
10

11
  /** {@link VersionIdentifier} "*" that will resolve to the latest stable version. */
12
  public static final VersionIdentifier LATEST = VersionIdentifier.of("*");
3✔
13

14
  /** {@link VersionIdentifier} "*!" that will resolve to the latest snapshot. */
15
  public static final VersionIdentifier LATEST_UNSTABLE = VersionIdentifier.of("*!");
4✔
16

17
  private final VersionSegment start;
18

19
  private final VersionLetters developmentPhase;
20

21
  private final boolean valid;
22

23
  private VersionIdentifier(VersionSegment start) {
24

25
    super();
2✔
26
    Objects.requireNonNull(start);
3✔
27
    this.start = start;
3✔
28
    boolean isValid = this.start.getSeparator().isEmpty() && this.start.getLettersString().isEmpty();
14✔
29
    boolean hasPositiveNumber = false;
2✔
30
    VersionLetters dev = VersionLetters.EMPTY;
2✔
31
    VersionSegment segment = this.start;
3✔
32
    while (segment != null) {
2✔
33
      if (!segment.isValid()) {
3✔
34
        isValid = false;
3✔
35
      } else if (segment.getNumber() > 0) {
3✔
36
        hasPositiveNumber = true;
2✔
37
      }
38
      VersionLetters segmentLetters = segment.getLetters();
3✔
39
      if (segmentLetters.isDevelopmentPhase()) {
3✔
40
        if (dev.isEmpty()) {
3✔
41
          dev = segmentLetters;
3✔
42
        } else {
43
          dev = VersionLetters.UNDEFINED;
2✔
44
          isValid = false;
2✔
45
        }
46
      }
47
      segment = segment.getNextOrNull();
3✔
48
    }
1✔
49
    this.developmentPhase = dev;
3✔
50
    this.valid = isValid && hasPositiveNumber;
9✔
51
  }
1✔
52

53
  /**
54
   * @return the first {@link VersionSegment} of this {@link VersionIdentifier}. To get other segments use {@link VersionSegment#getNextOrEmpty()} or
55
   *     {@link VersionSegment#getNextOrNull()}.
56
   */
57
  public VersionSegment getStart() {
58

59
    return this.start;
3✔
60
  }
61

62
  /**
63
   * A valid {@link VersionIdentifier} has to meet the following requirements:
64
   * <ul>
65
   * <li>All {@link VersionSegment segments} themselves are {@link VersionSegment#isValid() valid}.</li>
66
   * <li>The {@link #getStart() start} {@link VersionSegment segment} shall have an {@link String#isEmpty() empty}
67
   * {@link VersionSegment#getSeparator() separator} (e.g. ".1.0" or "-1-2" are not considered valid).</li>
68
   * <li>The {@link #getStart() start} {@link VersionSegment segment} shall have an {@link String#isEmpty() empty}
69
   * {@link VersionSegment#getLettersString() letter-sequence} (e.g. "RC1" or "beta" are not considered valid).</li>
70
   * <li>Have at least one {@link VersionSegment segment} with a positive {@link VersionSegment#getNumber() number}
71
   * (e.g. "0.0.0" or "0.alpha" are not considered valid).</li>
72
   * <li>Have at max one {@link VersionSegment segment} with a {@link VersionSegment#getPhase() phase} that is a real
73
   * {@link VersionPhase#isDevelopmentPhase() development phase} (e.g. "1.alpha1.beta2" or "1.0.rc1-milestone2" are not
74
   * considered valid).</li>
75
   * <li>It is NOT a {@link #isPattern() pattern}.</li>
76
   * </ul>
77
   */
78
  @Override
79
  public boolean isValid() {
80

81
    return this.valid;
3✔
82
  }
83

84
  @Override
85
  public boolean isPattern() {
86

87
    VersionSegment segment = this.start;
3✔
88
    while (segment != null) {
2✔
89
      if (segment.isPattern()) {
3✔
90
        return true;
2✔
91
      }
92
      segment = segment.getNextOrNull();
4✔
93
    }
94
    return false;
2✔
95
  }
96

97
  /**
98
   * @return the {@link VersionLetters#isDevelopmentPhase() development phase} of this {@link VersionIdentifier}. Will be {@link VersionLetters#EMPTY} if no
99
   *     development phase is specified in any {@link VersionSegment} and will be {@link VersionLetters#UNDEFINED} if more than one
100
   *     {@link VersionLetters#isDevelopmentPhase() development phase} is specified (e.g. "1.0-alpha1.rc2").
101
   */
102
  public VersionLetters getDevelopmentPhase() {
103

104
    return this.developmentPhase;
3✔
105
  }
106

107
  @Override
108
  public VersionComparisonResult compareVersion(VersionIdentifier other) {
109

110
    if (other == null) {
2!
111
      return VersionComparisonResult.GREATER_UNSAFE;
×
112
    }
113
    VersionSegment thisSegment = this.start;
3✔
114
    VersionSegment otherSegment = other.start;
3✔
115
    VersionComparisonResult result = null;
2✔
116
    boolean unsafe = false;
2✔
117
    boolean todo = true;
2✔
118
    do {
119
      result = thisSegment.compareVersion(otherSegment);
4✔
120
      if (result.isEqual()) {
3✔
121
        if (thisSegment.isEmpty() && otherSegment.isEmpty()) {
6!
122
          todo = false;
3✔
123
        } else if (result.isUnsafe()) {
3!
124
          unsafe = true;
×
125
        }
126
      } else {
127
        todo = false;
2✔
128
      }
129
      thisSegment = thisSegment.getNextOrEmpty();
3✔
130
      otherSegment = otherSegment.getNextOrEmpty();
3✔
131
    } while (todo);
2✔
132
    if (unsafe) {
2!
133
      return result.withUnsafe();
×
134
    }
135
    return result;
2✔
136
  }
137

138
  /**
139
   * @param other the {@link VersionIdentifier} to be matched.
140
   * @return {@code true} if this {@link VersionIdentifier} is equal to the given {@link VersionIdentifier} or this {@link VersionIdentifier} is a pattern
141
   *     version (e.g. "17*" or "17.*") and the given {@link VersionIdentifier} matches to that pattern.
142
   */
143
  public boolean matches(VersionIdentifier other) {
144

145
    if (other == null) {
2✔
146
      return false;
2✔
147
    }
148
    VersionSegment thisSegment = this.start;
3✔
149
    VersionSegment otherSegment = other.start;
3✔
150
    while (true) {
151
      VersionMatchResult matchResult = thisSegment.matches(otherSegment);
4✔
152
      if (matchResult == VersionMatchResult.MATCH) {
3✔
153
        return true;
2✔
154
      } else if (matchResult == VersionMatchResult.MISMATCH) {
3✔
155
        return false;
2✔
156
      }
157
      thisSegment = thisSegment.getNextOrEmpty();
3✔
158
      otherSegment = otherSegment.getNextOrEmpty();
3✔
159
    }
1✔
160
  }
161

162
  @Override
163
  public VersionIdentifier getMin() {
164

165
    return this;
×
166
  }
167

168
  @Override
169
  public VersionIdentifier getMax() {
170

171
    return this;
×
172
  }
173

174
  @Override
175
  public boolean contains(VersionIdentifier version) {
176

177
    return matches(version);
4✔
178
  }
179

180
  @Override
181
  public int hashCode() {
182

183
    VersionSegment segment = this.start;
×
184
    int hash = 1;
×
185
    while (segment != null) {
×
186
      hash = hash * 31 + segment.hashCode();
×
187
      segment = segment.getNextOrNull();
×
188
    }
189
    return hash;
×
190
  }
191

192
  @Override
193
  public boolean equals(Object obj) {
194

195
    if (obj == this) {
3✔
196
      return true;
2✔
197
    } else if (!(obj instanceof VersionIdentifier)) {
3✔
198
      return false;
2✔
199
    }
200
    VersionIdentifier other = (VersionIdentifier) obj;
3✔
201
    return Objects.equals(this.start, other.start);
6✔
202
  }
203

204
  @Override
205
  public String toString() {
206

207
    StringBuilder sb = new StringBuilder();
4✔
208
    VersionSegment segment = this.start;
3✔
209
    while (segment != null) {
2✔
210
      sb.append(segment.toString());
5✔
211
      segment = segment.getNextOrNull();
4✔
212
    }
213
    return sb.toString();
3✔
214
  }
215

216
  /**
217
   * @param version the {@link #toString() string representation} of the {@link VersionIdentifier} to parse.
218
   * @return the parsed {@link VersionIdentifier}.
219
   */
220
  public static VersionIdentifier of(String version) {
221

222
    if (version == null) {
2✔
223
      return null;
2✔
224
    } else if (version.equals("latest")) {
4!
225
      return VersionIdentifier.LATEST;
×
226
    }
227
    VersionSegment startSegment = VersionSegment.of(version);
3✔
228
    if (startSegment == null) {
2✔
229
      return null;
2✔
230
    }
231
    return new VersionIdentifier(startSegment);
5✔
232
  }
233

234
}
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