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