1212import java .net .http .HttpRequest ;
1313import java .net .http .HttpResponse ;
1414import java .util .ArrayList ;
15+ import java .util .Comparator ;
1516import java .util .List ;
1617import java .util .Locale ;
1718import java .util .Map ;
@@ -32,11 +33,11 @@ public final class JavaDocsCrawler {
3233 // latest periodically to avoid crawling artifacts that stopped being published.
3334 private static final Map <String , String > GROUPS_AND_MIN_VERSION =
3435 Map .of (
35- "io.opentelemetry" , "1.49.0 " ,
36- "io.opentelemetry.instrumentation" , "2.15 .0" ,
37- "io.opentelemetry.contrib" , "1.46 .0" ,
38- "io.opentelemetry.semconv" , "1.32 .0" ,
39- "io.opentelemetry.proto" , "1.3.2 " );
36+ "io.opentelemetry" , "1.60.1 " ,
37+ "io.opentelemetry.instrumentation" , "2.25 .0" ,
38+ "io.opentelemetry.contrib" , "1.54 .0" ,
39+ "io.opentelemetry.semconv" , "1.40 .0" ,
40+ "io.opentelemetry.proto" , "1.10.0 " );
4041
4142 private static final String MAVEN_CENTRAL_BASE_URL =
4243 "https://search.maven.org/solrsearch/select?q=g:" ;
@@ -159,9 +160,10 @@ static List<Artifact> crawlJavaDocs(
159160 HttpClient client , String minVersion , List <Artifact > artifacts )
160161 throws IOException , InterruptedException {
161162 List <Artifact > updatedArtifacts = new ArrayList <>();
163+ SemanticVersion minSemanticVersion = SemanticVersion .parse (minVersion );
162164
163165 for (Artifact artifact : artifacts ) {
164- if (artifact .getVersion ().compareTo (minVersion ) < 0 ) {
166+ if (SemanticVersion . parse ( artifact .getVersion ()) .compareTo (minSemanticVersion ) < 0 ) {
165167 logger .info (
166168 String .format (
167169 "Skipping crawling %s due to version %s being less than minVersion %s" ,
@@ -209,5 +211,103 @@ static List<Artifact> crawlJavaDocs(
209211 return updatedArtifacts ;
210212 }
211213
214+ static final class SemanticVersion implements Comparable <SemanticVersion > {
215+ private static final Comparator <List <Integer >> CORE_VERSION_COMPARATOR =
216+ (left , right ) -> {
217+ for (int i = 0 ; i < Math .max (left .size (), right .size ()); i ++) {
218+ int leftPart = i < left .size () ? left .get (i ) : 0 ;
219+ int rightPart = i < right .size () ? right .get (i ) : 0 ;
220+ int result = Integer .compare (leftPart , rightPart );
221+ if (result != 0 ) {
222+ return result ;
223+ }
224+ }
225+ return 0 ;
226+ };
227+
228+ private final List <Integer > coreVersionParts ;
229+ private final String qualifier ;
230+
231+ private SemanticVersion (List <Integer > coreVersionParts , String qualifier ) {
232+ this .coreVersionParts = coreVersionParts ;
233+ this .qualifier = qualifier ;
234+ }
235+
236+ static SemanticVersion parse (String version ) {
237+ String [] versionParts = version .split ("-" , 2 );
238+ List <Integer > coreVersionParts = new ArrayList <>();
239+ for (String part : versionParts [0 ].split ("\\ ." )) {
240+ coreVersionParts .add (Integer .parseInt (part ));
241+ }
242+ String qualifier = versionParts .length == 2 ? versionParts [1 ] : "" ;
243+ return new SemanticVersion (coreVersionParts , qualifier );
244+ }
245+
246+ @ Override
247+ public int compareTo (SemanticVersion other ) {
248+ int coreVersionResult =
249+ CORE_VERSION_COMPARATOR .compare (coreVersionParts , other .coreVersionParts );
250+ if (coreVersionResult != 0 ) {
251+ return coreVersionResult ;
252+ }
253+ if (qualifier .isEmpty () && other .qualifier .isEmpty ()) {
254+ return 0 ;
255+ }
256+ if (qualifier .isEmpty ()) {
257+ return 1 ;
258+ }
259+ if (other .qualifier .isEmpty ()) {
260+ return -1 ;
261+ }
262+ return compareQualifier (qualifier , other .qualifier );
263+ }
264+
265+ private static int compareQualifier (String leftQualifier , String rightQualifier ) {
266+ String [] leftParts = leftQualifier .split ("\\ ." );
267+ String [] rightParts = rightQualifier .split ("\\ ." );
268+
269+ for (int i = 0 ; i < Math .max (leftParts .length , rightParts .length ); i ++) {
270+ if (i >= leftParts .length ) {
271+ return -1 ;
272+ }
273+ if (i >= rightParts .length ) {
274+ return 1 ;
275+ }
276+
277+ String leftIdentifier = leftParts [i ];
278+ String rightIdentifier = rightParts [i ];
279+ if (leftIdentifier .equals (rightIdentifier )) {
280+ continue ;
281+ }
282+
283+ boolean leftNumeric = isNumericIdentifier (leftIdentifier );
284+ boolean rightNumeric = isNumericIdentifier (rightIdentifier );
285+ if (leftNumeric && rightNumeric ) {
286+ if (leftIdentifier .length () != rightIdentifier .length ()) {
287+ return Integer .compare (leftIdentifier .length (), rightIdentifier .length ());
288+ }
289+ return leftIdentifier .compareTo (rightIdentifier );
290+ }
291+ if (leftNumeric != rightNumeric ) {
292+ return leftNumeric ? -1 : 1 ;
293+ }
294+ return leftIdentifier .compareTo (rightIdentifier );
295+ }
296+ return 0 ;
297+ }
298+
299+ private static boolean isNumericIdentifier (String identifier ) {
300+ if (identifier .isEmpty ()) {
301+ return false ;
302+ }
303+ for (int i = 0 ; i < identifier .length (); i ++) {
304+ if (!Character .isDigit (identifier .charAt (i ))) {
305+ return false ;
306+ }
307+ }
308+ return true ;
309+ }
310+ }
311+
212312 private JavaDocsCrawler () {}
213313}
0 commit comments