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

devonfw / IDEasy / 19868191669

02 Dec 2025 05:46PM UTC coverage: 69.852% (+0.07%) from 69.787%
19868191669

push

github

web-flow
#1633: fix CVE check to only suggest unstable versions if the requested version was unstable (#1635)

3835 of 6021 branches covered (63.69%)

Branch coverage included in aggregate %.

9812 of 13516 relevant lines covered (72.6%)

3.16 hits per line

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

72.66
cli/src/main/java/com/devonfw/tools/ide/version/VersionLetters.java
1
package com.devonfw.tools.ide.version;
2

3
import java.util.Locale;
4
import java.util.Objects;
5

6
/**
7
 * Value type for the letters of a {@link VersionSegment}.
8
 *
9
 * @see VersionSegment#getLettersString()
10
 */
11
public final class VersionLetters implements AbstractVersionPhase, VersionObject<VersionLetters> {
12

13
  /** The empty {@link VersionLetters} instance. */
14
  public static final VersionLetters EMPTY = new VersionLetters("");
5✔
15

16
  /** The unstable {@link VersionLetters} instance - see {@link VersionSegment#PATTERN_MATCH_ANY_VERSION}. */
17
  public static final VersionLetters UNSTABLE = new VersionLetters(VersionPhase.UNSTABLE);
5✔
18

19
  /** The undefined {@link VersionLetters} instance. */
20
  public static final VersionLetters UNDEFINED = new VersionLetters("undefined");
6✔
21

22
  private final String letters;
23

24
  private final String lettersLowerCase;
25

26
  private final VersionPhase phase;
27

28
  private final boolean prePhase;
29

30
  /**
31
   * The constructor.
32
   *
33
   * @param letters the {@link #getLetters() letters}.
34
   */
35
  private VersionLetters(String letters) {
36

37
    super();
2✔
38
    this.letters = letters;
3✔
39
    this.lettersLowerCase = letters.toLowerCase(Locale.ROOT);
5✔
40
    String phaseLetters = this.lettersLowerCase.replace('_', '-');
6✔
41
    if (phaseLetters.startsWith("pre")) {
4✔
42
      this.prePhase = true;
3✔
43
      int preLength = 3;
2✔
44
      if (phaseLetters.startsWith("pre-")) {
4✔
45
        preLength = 4;
2✔
46
      }
47
      phaseLetters = phaseLetters.substring(preLength);
4✔
48
    } else {
1✔
49
      this.prePhase = false;
3✔
50
    }
51
    this.phase = VersionPhase.of(phaseLetters);
4✔
52
  }
1✔
53

54
  private VersionLetters(VersionPhase phase) {
55

56
    super();
2✔
57
    this.letters = "";
3✔
58
    this.lettersLowerCase = "";
3✔
59
    this.prePhase = false;
3✔
60
    this.phase = phase;
3✔
61
  }
1✔
62

63
  /**
64
   * @return the letters or the empty {@link String} ("") for none. In canonical {@link VersionIdentifier}s letters indicate the development phase (e.g. "pre",
65
   *     "rc", "alpha", "beta", "milestone", "test", "dev", "SNAPSHOT", etc.). However, letters are technically any
66
   *     {@link Character#isLetter(char) letter characters} and may also be something like a code-name (e.g. "Cupcake", "Donut", "Eclair", "Froyo",
67
   *     "Gingerbread", "Honeycomb", "Ice Cream Sandwich", "Jelly Bean" in case of Android internals). Please note that in such case it is impossible to
68
   *     properly decide which version is greater than another versions. To avoid mistakes, the comparison supports a strict mode that will let the comparison
69
   *     fail in such case. However, by default (e.g. for {@link Comparable#compareTo(Object)}) the default {@link String#compareTo(String) string comparison}
70
   *     (lexicographical) is used to ensure a natural order.
71
   * @see #getPhase()
72
   */
73
  public String getLetters() {
74

75
    return this.letters;
3✔
76
  }
77

78
  /**
79
   * @return the {@link VersionPhase} for the {@link #getLetters() letters}. Will be {@link VersionPhase#UNDEFINED} if unknown and hence never {@code null}.
80
   * @see #isPrePhase()
81
   * @see #getLetters()
82
   */
83
  public VersionPhase getPhase() {
84

85
    return this.phase;
3✔
86
  }
87

88
  /**
89
   * @return {@code true} if the {@link #getLetters() letters} and a potential {@link #getPhase() phase} are prefixed with "pre" (e.g. in "pre-alpha"),
90
   *     {@code false} otherwise.
91
   */
92
  public boolean isPrePhase() {
93

94
    return this.prePhase;
3✔
95
  }
96

97
  @Override
98
  public boolean isDevelopmentPhase() {
99

100
    return this.phase.isDevelopmentPhase() || isPrePhase();
11✔
101
  }
102

103
  @Override
104
  public boolean isUnstable() {
105

106
    return this.prePhase || this.phase.isUnstable();
11✔
107
  }
108

109
  @Override
110
  public boolean isStable() {
111

112
    return !this.prePhase && this.phase.isStable();
11!
113
  }
114

115
  /**
116
   * @return {@code true} if empty, {@code false} otherwise.
117
   */
118
  public boolean isEmpty() {
119

120
    return this.letters.isEmpty();
4✔
121
  }
122

123
  @Override
124
  public boolean isValid() {
125

126
    return true;
×
127
  }
128

129
  @Override
130
  public VersionComparisonResult compareVersion(VersionLetters other) {
131

132
    if (!this.lettersLowerCase.equals(other.lettersLowerCase)) {
6✔
133
      if ((this.phase == VersionPhase.UNDEFINED) || (other.phase == VersionPhase.UNDEFINED)) {
8!
134
        if (this.lettersLowerCase.compareTo(other.lettersLowerCase) < 0) {
6!
135
          return VersionComparisonResult.LESS_UNSAFE;
×
136
        } else {
137
          return VersionComparisonResult.GREATER_UNSAFE;
2✔
138
        }
139
      }
140
      if (this.phase != other.phase) {
5✔
141
        if (this.phase.ordinal() < other.phase.ordinal()) {
7✔
142
          return VersionComparisonResult.LESS;
2✔
143
        } else {
144
          return VersionComparisonResult.GREATER;
2✔
145
        }
146
      } else if (this.prePhase != other.prePhase) {
5!
147
        if (this.prePhase) {
×
148
          return VersionComparisonResult.LESS;
×
149
        } else {
150
          return VersionComparisonResult.GREATER;
×
151
        }
152
      }
153
    }
154
    return VersionComparisonResult.EQUAL;
2✔
155
  }
156

157
  /**
158
   * @param other the other {@link VersionLetters} to match against.
159
   * @param pattern - {@code true} if the owning {@link VersionSegment} {@link VersionSegment#isPattern() is a pattern}, {@code false} otherwise.
160
   * @return the {@link VersionMatchResult}.
161
   * @see VersionSegment#matches(VersionSegment)
162
   */
163
  public VersionMatchResult matches(VersionLetters other, boolean pattern) {
164

165
    if (other == null) {
2!
166
      return VersionMatchResult.MISMATCH;
×
167
    }
168
    if (isEmpty() && other.isEmpty()) {
6!
169
      return VersionMatchResult.EQUAL;
2✔
170
    }
171
    if (pattern) {
2!
172
      if (this.phase != VersionPhase.NONE) {
4!
173
        if (this.phase != other.phase) {
×
174
          return VersionMatchResult.MISMATCH;
×
175
        }
176
      }
177
      if (!other.lettersLowerCase.startsWith(this.lettersLowerCase)) {
6!
178
        return VersionMatchResult.MISMATCH;
×
179
      }
180
      return VersionMatchResult.MATCH;
2✔
181
    } else {
182
      if ((this.phase != other.phase) || !this.lettersLowerCase.equals(other.lettersLowerCase)) {
×
183
        return VersionMatchResult.MISMATCH;
×
184
      }
185
      return VersionMatchResult.EQUAL;
×
186
    }
187
  }
188

189
  @Override
190
  public int hashCode() {
191

192
    return this.letters.hashCode();
×
193
  }
194

195
  @Override
196
  public boolean equals(Object obj) {
197

198
    if (obj == this) {
3!
199
      return true;
×
200
    } else if (!(obj instanceof VersionLetters)) {
3!
201
      return false;
×
202
    }
203
    VersionLetters other = (VersionLetters) obj;
3✔
204
    return Objects.equals(this.letters, other.letters);
6✔
205
  }
206

207
  @Override
208
  public String toString() {
209

210
    return this.letters;
3✔
211
  }
212

213
  /**
214
   * @param letters the letters as {@link String}.
215
   * @return the parsed {@link VersionLetters}.
216
   */
217
  public static VersionLetters of(String letters) {
218

219
    if ((letters == null) || letters.isEmpty()) {
5!
220
      return EMPTY;
2✔
221
    }
222
    return new VersionLetters(letters);
5✔
223
  }
224

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

© 2026 Coveralls, Inc