Skip to content

Commit de07b70

Browse files
authored
Feature/java doc fix (#8175)
1 parent 923098b commit de07b70

File tree

2 files changed

+134
-6
lines changed

2 files changed

+134
-6
lines changed

javadoc-crawler/src/main/java/io/opentelemetry/javadocs/JavaDocsCrawler.java

Lines changed: 106 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.net.http.HttpRequest;
1313
import java.net.http.HttpResponse;
1414
import java.util.ArrayList;
15+
import java.util.Comparator;
1516
import java.util.List;
1617
import java.util.Locale;
1718
import 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
}

javadoc-crawler/src/test/java/io/opentelemetry/javadocs/JavaDocsCrawlerTest.java

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
import static io.opentelemetry.javadocs.JavaDocsCrawler.JAVA_DOC_DOWNLOADED_TEXT;
99
import static org.assertj.core.api.Assertions.assertThat;
1010
import static org.mockito.ArgumentMatchers.any;
11+
import static org.mockito.Mockito.never;
1112
import static org.mockito.Mockito.times;
1213
import static org.mockito.Mockito.verify;
1314
import static org.mockito.Mockito.when;
@@ -91,4 +92,31 @@ void testCrawler() throws IOException, InterruptedException {
9192
"https://javadoc.io/doc/io.opentelemetry/opentelemetry-context/1.49.0/opentelemetry/context/package-summary.html");
9293
assertThat(updated).containsExactly(artifact);
9394
}
95+
96+
@Test
97+
void compareVersionsUsesSemanticOrdering() {
98+
assertThat(compareVersions("1.9.0", "1.49.0")).isLessThan(0);
99+
assertThat(compareVersions("1.49.0", "1.49.0")).isZero();
100+
assertThat(compareVersions("1.60.0", "1.49.0")).isGreaterThan(0);
101+
assertThat(compareVersions("1.60.0-alpha", "1.60.0")).isLessThan(0);
102+
assertThat(compareVersions("1.0.0-rc.2", "1.0.0-rc.10")).isLessThan(0);
103+
assertThat(compareVersions("1.0.0-rc.10", "1.0.0")).isLessThan(0);
104+
}
105+
106+
@Test
107+
void crawlSkipsArtifactsBelowMinVersionUsingSemanticComparison()
108+
throws IOException, InterruptedException {
109+
Artifact oldArtifact = new Artifact("io.opentelemetry", "opentelemetry-context", "1.9.0");
110+
111+
List<Artifact> updated =
112+
JavaDocsCrawler.crawlJavaDocs(mockClient, "1.49.0", List.of(oldArtifact));
113+
114+
verify(mockClient, never()).send(any(HttpRequest.class), any());
115+
assertThat(updated).isEmpty();
116+
}
117+
118+
private static int compareVersions(String left, String right) {
119+
return JavaDocsCrawler.SemanticVersion.parse(left)
120+
.compareTo(JavaDocsCrawler.SemanticVersion.parse(right));
121+
}
94122
}

0 commit comments

Comments
 (0)