Skip to content

Commit 01cb153

Browse files
tjquinnotimon-sbr
authored andcommitted
Fix bug in common path prefix calculation (OpenAPITools#20310)
Signed-off-by: Tim Quinn <tim.quinn@oracle.com>
1 parent 1bb7764 commit 01cb153

File tree

2 files changed

+97
-4
lines changed

2 files changed

+97
-4
lines changed

modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/JavaHelidonCommonCodegen.java

Lines changed: 45 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
import java.util.Map;
3838
import java.util.Scanner;
3939
import java.util.Set;
40+
import java.util.StringJoiner;
4041
import java.util.TreeMap;
4142
import java.util.concurrent.locks.ReentrantLock;
4243
import java.util.prefs.BackingStoreException;
@@ -352,7 +353,7 @@ public OperationsMap postProcessOperationsWithModels(OperationsMap objs, List<Mo
352353
Scan the paths of all the operations, computing the longest common prefix. Then compute and set the path suffix
353354
for each operation.
354355
*/
355-
String commonPathPrefixForApi = StringUtils.getCommonPrefix(objs.getOperations().getOperation()
356+
String commonPathPrefixForApi = commonPathPrefix(objs.getOperations().getOperation()
356357
.stream()
357358
.map(op -> op.path)
358359
.map(path -> path.charAt(0) != '/' ? "/" + path : path )
@@ -450,6 +451,46 @@ protected String rootJavaEEPackage() {
450451
return rootJavaEEPackage;
451452
}
452453

454+
static String commonPathPrefix(String[] paths) {
455+
456+
if (paths.length == 0) {
457+
return "/";
458+
}
459+
460+
// Start out with the first path as the longest common prefix. The eventual longest common
461+
// prefix can be no longer than the first path, so as we check other paths we simply
462+
// revise the number of matching segments we have.
463+
String[] commonSegments = stripAnyLeadingSlash(paths[0]).split("/");
464+
int commonSegmentsCount = commonSegments.length;
465+
466+
// Examine the remaining paths.
467+
for (int i = 1; i < paths.length; i++) {
468+
String[] segments = stripAnyLeadingSlash(paths[i]).split("/");
469+
470+
// Check each segment of this next path against the common segments we have so far.
471+
int segmentIndex = 0;
472+
while (segmentIndex < Math.min(commonSegmentsCount, segments.length)
473+
&& commonSegments[segmentIndex].equals(segments[segmentIndex])) {
474+
segmentIndex++;
475+
}
476+
commonSegmentsCount = segmentIndex;
477+
if (commonSegmentsCount == 0) {
478+
break;
479+
}
480+
}
481+
StringJoiner commonPath = new StringJoiner("/", "/", "");
482+
commonPath.setEmptyValue("/");
483+
484+
for (int i = 0; i < commonSegmentsCount; i++) {
485+
commonPath.add(commonSegments[i]);
486+
}
487+
return commonPath.toString();
488+
}
489+
490+
private static String stripAnyLeadingSlash(String path) {
491+
return path.startsWith("/") ? path.substring(1) : path;
492+
}
493+
453494
/**
454495
* Prepares a map of predefined HTTP status code constants.
455496
* <p>
@@ -716,9 +757,9 @@ static class VersionUtil {
716757

717758
private static final String DEFAULT_VERSIONS = "<data>\n" +
718759
" <archetypes>\n" +
719-
" <version>2.6.5</version>\n" +
720-
" <version>3.2.7</version>\n" +
721-
" <version>4.0.9</version>\n" +
760+
" <version>2.6.10</version>\n" +
761+
" <version>3.2.11</version>\n" +
762+
" <version>4.1.4</version>\n" +
722763
" </archetypes>\n" +
723764
"</data>";
724765

modules/openapi-generator/src/test/java/org/openapitools/codegen/languages/HelidonCommonCodegenTest.java

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,56 @@ void testVersionNotInDefaultListWithNoNetwork() {
5454
List.of("4.0.10", "3.2.1", "3.2.0", "2.0.4", "1.2.3", "1.2.2", "1.1.0")))
5555
.isEqualTo("4.0.11-SNAPSHOT");
5656
}
57+
58+
@Test
59+
void checkCommonPathWithPathParams() {
60+
String[] paths = List.of("/users/{userId}/profile",
61+
"/users/{userId}/problems",
62+
"/users/{userEmail}",
63+
"/users/{username}")
64+
.toArray(new String[0]);
65+
66+
String commonPrefix = JavaHelidonCommonCodegen.commonPathPrefix(paths);
67+
assertThat(commonPrefix).isEqualTo("/users");
68+
}
69+
70+
@Test
71+
void checkCommonPathWithMultipleCommonLevels() {
72+
String[] paths = List.of("/users/a/x",
73+
"/users/a/y",
74+
"/users/a/z")
75+
.toArray(new String[0]);
76+
77+
String commonPrefix = JavaHelidonCommonCodegen.commonPathPrefix(paths);
78+
assertThat(commonPrefix).isEqualTo("/users/a");
79+
}
80+
81+
@Test
82+
void checkNoCommonSegments() {
83+
String[] paths = List.of("/a/x",
84+
"/b/y",
85+
"/c")
86+
.toArray(new String[0]);
87+
88+
String commonPrefix = JavaHelidonCommonCodegen.commonPathPrefix(paths);
89+
assertThat(commonPrefix).isEqualTo("/");
90+
}
91+
92+
@Test
93+
void checkSinglePathCommonSegments() {
94+
String commonPrefix = JavaHelidonCommonCodegen.commonPathPrefix(new String[0]);
95+
assertThat(commonPrefix).isEqualTo("/");
96+
}
97+
98+
@Test
99+
void checkMixedWithPathParam() {
100+
String[] paths = List.of("/store/order/{order_id}",
101+
"/store/inventory",
102+
"/store/order/{order_id}",
103+
"/store/order")
104+
.toArray(new String[0]);
105+
106+
String commonPrefix = JavaHelidonCommonCodegen.commonPathPrefix(paths);
107+
assertThat(commonPrefix).isEqualTo("/store");
108+
}
57109
}

0 commit comments

Comments
 (0)