Skip to content

Commit 37004ef

Browse files
timur27joschi
andauthored
Equivalent paths with overloaded parameters are supported (#306)
Co-authored-by: Jochen Schalanda <jochen@schalanda.name>
1 parent e9e848f commit 37004ef

File tree

4 files changed

+163
-3
lines changed

4 files changed

+163
-3
lines changed

core/src/main/java/org/openapitools/openapidiff/core/compare/PathsDiff.java

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
package org.openapitools.openapidiff.core.compare;
22

3+
import io.swagger.v3.oas.models.Operation;
34
import io.swagger.v3.oas.models.PathItem;
45
import io.swagger.v3.oas.models.Paths;
56
import java.util.*;
67
import java.util.regex.Matcher;
78
import java.util.regex.Pattern;
9+
import java.util.stream.IntStream;
10+
import io.swagger.v3.oas.models.parameters.Parameter;
811
import org.openapitools.openapidiff.core.model.Changed;
912
import org.openapitools.openapidiff.core.model.ChangedPaths;
1013
import org.openapitools.openapidiff.core.model.DiffContext;
@@ -50,7 +53,7 @@ public DeferredChanged<ChangedPaths> diff(
5053
.filter(item -> normalizePath(item.getKey()).equals(template))
5154
.min(
5255
(a, b) -> {
53-
if (methodsIntersect(a.getValue(), b.getValue())) {
56+
if (methodsAndParametersIntersect(a.getValue(), b.getValue())) {
5457
throw new IllegalArgumentException(
5558
"Two path items have the same signature: " + template);
5659
}
@@ -99,13 +102,40 @@ public static Paths valOrEmpty(Paths path) {
99102
return path;
100103
}
101104

102-
private static boolean methodsIntersect(PathItem a, PathItem b) {
105+
/**
106+
*
107+
* @param a a path form the open api spec
108+
* @param b another path from the same open api spec
109+
* @return <code>true</code> in case both paths are of the same method AND their templated parameters are of the same type;
110+
* <code>false</code> otherwise
111+
*
112+
*/
113+
private static boolean methodsAndParametersIntersect(PathItem a, PathItem b) {
103114
Set<PathItem.HttpMethod> methodsA = a.readOperationsMap().keySet();
104115
for (PathItem.HttpMethod method : b.readOperationsMap().keySet()) {
105116
if (methodsA.contains(method)) {
106-
return true;
117+
Operation left = a.readOperationsMap().get(method);
118+
Operation right = b.readOperationsMap().get(method);
119+
if (left.getParameters().size() == right.getParameters().size()) {
120+
return parametersIntersect(left.getParameters(), right.getParameters());
121+
}
122+
return false;
107123
}
108124
}
109125
return false;
110126
}
127+
128+
/**
129+
*
130+
* @param left parameters from the first compared method
131+
* @param right parameters from the second compared method
132+
* @return <code>true</code> in case each parameter pair is of the same type; <code>false</code> otherwise
133+
*/
134+
private static boolean parametersIntersect(List<Parameter> left, List<Parameter> right) {;
135+
int parametersSize = left.size();
136+
long intersectedParameters = IntStream.range(0, left.size())
137+
.filter(i -> left.get(i).getSchema().getType().equals(right.get(i).getSchema().getType()))
138+
.count();
139+
return parametersSize == intersectedParameters;
140+
}
111141
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
package org.openapitools.openapidiff.core;
2+
3+
import org.junit.jupiter.api.Test;
4+
5+
import static org.junit.jupiter.api.Assertions.*;
6+
import static org.openapitools.openapidiff.core.TestUtils.assertOpenApiAreEquals;
7+
8+
class ParametersOverloadingTest {
9+
10+
private final String OVERLOADED_PARAMETERS = "parameters_overloading.yaml";
11+
private final String DUPLICATED_PARAMETER_TYPES = "parameters_overloading_2.yaml";
12+
13+
@Test
14+
void testDiffWithOverloadedParameterTypes() {
15+
assertDoesNotThrow(() -> OpenApiCompare.fromLocations(OVERLOADED_PARAMETERS, OVERLOADED_PARAMETERS));
16+
assertOpenApiAreEquals(OVERLOADED_PARAMETERS, OVERLOADED_PARAMETERS);
17+
}
18+
19+
@Test
20+
void testDiffWithDuplicatedParameterTypes() {
21+
assertThrows(
22+
IllegalArgumentException.class,
23+
() -> OpenApiCompare.fromLocations(DUPLICATED_PARAMETER_TYPES, DUPLICATED_PARAMETER_TYPES),
24+
"Two path items have the same signature: /projects/{}");
25+
}
26+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
openapi: 3.0.2
2+
info:
3+
title: Projects API
4+
version: 1.0.0
5+
paths:
6+
/projects/{id}:
7+
get:
8+
parameters:
9+
- in: path
10+
name: id
11+
required: true
12+
schema:
13+
type: integer
14+
format: int64
15+
responses:
16+
'200':
17+
description: 'Success'
18+
content:
19+
application/json:
20+
schema:
21+
$ref: '#/components/schemas/SampleResponse'
22+
/projects/{uid}:
23+
get:
24+
parameters:
25+
- in: path
26+
name: uid
27+
required: true
28+
schema:
29+
type: string
30+
format: uuid
31+
responses:
32+
'200':
33+
description: 'Success'
34+
content:
35+
application/json:
36+
schema:
37+
$ref: '#/components/schemas/SampleResponse'
38+
components:
39+
schemas:
40+
SampleResponse:
41+
type: object
42+
properties:
43+
id:
44+
type: integer
45+
uid:
46+
type: string
47+
name:
48+
type: string
49+
required:
50+
- id
51+
- uid
52+
- name
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
openapi: 3.0.2
2+
info:
3+
title: Projects API
4+
version: 1.0.0
5+
paths:
6+
/projects/{id}:
7+
get:
8+
parameters:
9+
- in: path
10+
name: id
11+
required: true
12+
schema:
13+
type: integer
14+
format: int64
15+
responses:
16+
'200':
17+
description: 'Success'
18+
content:
19+
application/json:
20+
schema:
21+
$ref: '#/components/schemas/SampleResponse'
22+
/projects/{uid}:
23+
get:
24+
parameters:
25+
- in: path
26+
name: uid
27+
required: true
28+
schema:
29+
type: integer
30+
format: int64
31+
responses:
32+
'200':
33+
description: 'Success'
34+
content:
35+
application/json:
36+
schema:
37+
$ref: '#/components/schemas/SampleResponse'
38+
components:
39+
schemas:
40+
SampleResponse:
41+
type: object
42+
properties:
43+
id:
44+
type: integer
45+
uid:
46+
type: string
47+
name:
48+
type: string
49+
required:
50+
- id
51+
- uid
52+
- name

0 commit comments

Comments
 (0)