1 package org.eclipse.aether.internal.test.util;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import org.eclipse.aether.version.InvalidVersionSpecificationException;
23 import org.eclipse.aether.version.Version;
24 import org.eclipse.aether.version.VersionRange;
25
26
27
28
29 final class TestVersionRange
30 implements VersionRange
31 {
32
33 private final Version lowerBound;
34
35 private final boolean lowerBoundInclusive;
36
37 private final Version upperBound;
38
39 private final boolean upperBoundInclusive;
40
41
42
43
44
45
46
47 TestVersionRange( String range )
48 throws InvalidVersionSpecificationException
49 {
50 String process = range;
51
52 if ( range.startsWith( "[" ) )
53 {
54 lowerBoundInclusive = true;
55 }
56 else if ( range.startsWith( "(" ) )
57 {
58 lowerBoundInclusive = false;
59 }
60 else
61 {
62 throw new InvalidVersionSpecificationException( range, "Invalid version range " + range
63 + ", a range must start with either [ or (" );
64 }
65
66 if ( range.endsWith( "]" ) )
67 {
68 upperBoundInclusive = true;
69 }
70 else if ( range.endsWith( ")" ) )
71 {
72 upperBoundInclusive = false;
73 }
74 else
75 {
76 throw new InvalidVersionSpecificationException( range, "Invalid version range " + range
77 + ", a range must end with either [ or (" );
78 }
79
80 process = process.substring( 1, process.length() - 1 );
81
82 int index = process.indexOf( "," );
83
84 if ( index < 0 )
85 {
86 if ( !lowerBoundInclusive || !upperBoundInclusive )
87 {
88 throw new InvalidVersionSpecificationException( range, "Invalid version range " + range
89 + ", single version must be surrounded by []" );
90 }
91
92 lowerBound = upperBound = new TestVersion( process.trim() );
93 }
94 else
95 {
96 String parsedLowerBound = process.substring( 0, index ).trim();
97 String parsedUpperBound = process.substring( index + 1 ).trim();
98
99
100 if ( parsedUpperBound.contains( "," ) )
101 {
102 throw new InvalidVersionSpecificationException( range, "Invalid version range " + range
103 + ", bounds may not contain additional ','" );
104 }
105
106 lowerBound = parsedLowerBound.length() > 0 ? new TestVersion( parsedLowerBound ) : null;
107 upperBound = parsedUpperBound.length() > 0 ? new TestVersion( parsedUpperBound ) : null;
108
109 if ( upperBound != null && lowerBound != null )
110 {
111 if ( upperBound.compareTo( lowerBound ) < 0 )
112 {
113 throw new InvalidVersionSpecificationException( range, "Invalid version range " + range
114 + ", lower bound must not be greater than upper bound" );
115 }
116 }
117 }
118 }
119
120 public Bound getLowerBound()
121 {
122 return new Bound( lowerBound, lowerBoundInclusive );
123 }
124
125 public Bound getUpperBound()
126 {
127 return new Bound( upperBound, upperBoundInclusive );
128 }
129
130 public boolean acceptsSnapshots()
131 {
132 return isSnapshot( lowerBound ) || isSnapshot( upperBound );
133 }
134
135 public boolean containsVersion( Version version )
136 {
137 boolean snapshot = isSnapshot( version );
138
139 if ( lowerBound != null )
140 {
141 int comparison = lowerBound.compareTo( version );
142
143 if ( snapshot && comparison == 0 )
144 {
145 return true;
146 }
147
148 if ( comparison == 0 && !lowerBoundInclusive )
149 {
150 return false;
151 }
152 if ( comparison > 0 )
153 {
154 return false;
155 }
156 }
157
158 if ( upperBound != null )
159 {
160 int comparison = upperBound.compareTo( version );
161
162 if ( snapshot && comparison == 0 )
163 {
164 return true;
165 }
166
167 if ( comparison == 0 && !upperBoundInclusive )
168 {
169 return false;
170 }
171 if ( comparison < 0 )
172 {
173 return false;
174 }
175 }
176
177 if ( lowerBound != null || upperBound != null )
178 {
179 return !snapshot;
180 }
181
182 return true;
183 }
184
185 private boolean isSnapshot( Version version )
186 {
187 return version != null && version.toString().endsWith( "SNAPSHOT" );
188 }
189
190 @Override
191 public boolean equals( Object obj )
192 {
193 if ( obj == this )
194 {
195 return true;
196 }
197 else if ( obj == null || !getClass().equals( obj.getClass() ) )
198 {
199 return false;
200 }
201
202 TestVersionRange that = (TestVersionRange) obj;
203
204 return upperBoundInclusive == that.upperBoundInclusive && lowerBoundInclusive == that.lowerBoundInclusive
205 && eq( upperBound, that.upperBound ) && eq( lowerBound, that.lowerBound );
206 }
207
208 private static <T> boolean eq( T s1, T s2 )
209 {
210 return s1 != null ? s1.equals( s2 ) : s2 == null;
211 }
212
213 @Override
214 public int hashCode()
215 {
216 int hash = 17;
217 hash = hash * 31 + hash( upperBound );
218 hash = hash * 31 + ( upperBoundInclusive ? 1 : 0 );
219 hash = hash * 31 + hash( lowerBound );
220 hash = hash * 31 + ( lowerBoundInclusive ? 1 : 0 );
221 return hash;
222 }
223
224 private static int hash( Object obj )
225 {
226 return obj != null ? obj.hashCode() : 0;
227 }
228
229 @Override
230 public String toString()
231 {
232 StringBuilder buffer = new StringBuilder( 64 );
233 buffer.append( lowerBoundInclusive ? '[' : '(' );
234 if ( lowerBound != null )
235 {
236 buffer.append( lowerBound );
237 }
238 buffer.append( ',' );
239 if ( upperBound != null )
240 {
241 buffer.append( upperBound );
242 }
243 buffer.append( upperBoundInclusive ? ']' : ')' );
244 return buffer.toString();
245 }
246
247 }