Skip to content

Commit 35c1593

Browse files
authored
Merge branch 'master' into bugFix2
2 parents 577c8e6 + 918c0cb commit 35c1593

File tree

19 files changed

+499
-34
lines changed

19 files changed

+499
-34
lines changed

README.md

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,8 @@
11
# Swagger Parser
22

3-
[![Build Status](https://img.shields.io/jenkins/s/https/jenkins.swagger.io/view/OSS%20-%20Java/job/oss-swagger-parser-2.0.svg)](https://jenkins.swagger.io/view/OSS%20-%20Java/job/oss-swagger-parser-2.0)
3+
**NOTE:** If you're looking for `swagger-parser` 1.X and OpenApi 2.0, please refer to [v1 branch](https://github.com/swagger-api/swagger-parser/tree/v1)
4+
5+
[![Build Status](https://img.shields.io/jenkins/s/https/jenkins.swagger.io/view/OSS%20-%20Java/job/oss-swagger-parser-v2.svg)](https://jenkins.swagger.io/view/OSS%20-%20Java/job/oss-swagger-parser-v2)
46

57
## Overview
68
This is the swagger parser project, which reads OpenAPI Specifications into current Java POJOs. It also provides a simple framework to add additional converters from different formats into the Swagger objects, making the entire toolchain available.
@@ -97,7 +99,7 @@ You can include this library from Sonatype OSS for SNAPSHOTS, or Maven central f
9799
<dependency>
98100
<groupId>io.swagger.parser.v3</groupId>
99101
<artifactId>swagger-parser</artifactId>
100-
<version>2.0.5</version>
102+
<version>2.0.6-SNAPSHOT</version>
101103
</dependency>
102104

103105
```
@@ -108,7 +110,7 @@ or
108110
<dependency>
109111
<groupId>io.swagger.parser.v3</groupId>
110112
<artifactId>swagger-parser</artifactId>
111-
<version>2.0.5</version>
113+
<version>2.0.6-SNAPSHOT</version>
112114
</dependency>
113115

114116
```

modules/swagger-parser-core/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<parent>
44
<groupId>io.swagger.parser.v3</groupId>
55
<artifactId>swagger-parser-project</artifactId>
6-
<version>2.0.5</version>
6+
<version>2.0.6-SNAPSHOT</version>
77
<relativePath>../..</relativePath>
88
</parent>
99
<modelVersion>4.0.0</modelVersion>

modules/swagger-parser-v2-converter/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<parent>
44
<groupId>io.swagger.parser.v3</groupId>
55
<artifactId>swagger-parser-project</artifactId>
6-
<version>2.0.5</version>
6+
<version>2.0.6-SNAPSHOT</version>
77
<relativePath>../..</relativePath>
88
</parent>
99
<modelVersion>4.0.0</modelVersion>

modules/swagger-parser-v3/pom.xml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
<parent>
44
<groupId>io.swagger.parser.v3</groupId>
55
<artifactId>swagger-parser-project</artifactId>
6-
<version>2.0.5</version>
6+
<version>2.0.6-SNAPSHOT</version>
77
<relativePath>../..</relativePath>
88
</parent>
99
<modelVersion>4.0.0</modelVersion>

modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,7 @@ private void processRefSchema(Schema subRef, String externalFile) {
674674
RefFormat format = computeRefFormat(subRef.get$ref());
675675

676676
if (!isAnExternalRefFormat(format)) {
677-
processRefToExternalSchema(externalFile + subRef.get$ref(), RefFormat.RELATIVE);
677+
subRef.set$ref(processRefToExternalSchema(externalFile + subRef.get$ref(), RefFormat.RELATIVE));
678678
return;
679679
}
680680
String $ref = subRef.get$ref();
@@ -723,4 +723,4 @@ else if("".equals(uri.getPath()) && !fragment.startsWith("/")) {
723723
}
724724

725725

726-
}
726+
}

modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/OpenAPIDeserializer.java

Lines changed: 32 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -52,15 +52,7 @@
5252
import java.net.URI;
5353
import java.net.URISyntaxException;
5454
import java.net.URL;
55-
import java.util.ArrayList;
56-
import java.util.Arrays;
57-
import java.util.Iterator;
58-
import java.util.LinkedHashMap;
59-
import java.util.LinkedHashSet;
60-
import java.util.List;
61-
import java.util.Map;
62-
import java.util.Optional;
63-
import java.util.Set;
55+
import java.util.*;
6456
import java.util.stream.Collectors;
6557
import java.util.stream.Stream;
6658

@@ -98,6 +90,7 @@ public class OpenAPIDeserializer {
9890
private static final String PATH_PARAMETER = "path";
9991
private static final String HEADER_PARAMETER = "header";
10092

93+
private final Set<String> operationIDs = new HashSet<>();
10194

10295
public SwaggerParseResult deserialize(JsonNode rootNode) {
10396
return deserialize(rootNode, null);
@@ -690,7 +683,7 @@ public ExternalDocumentation getExternalDocs(ObjectNode node, String location, P
690683
}
691684

692685

693-
public String getString(String key, ObjectNode node, boolean required, String location, ParseResult result) {
686+
public String getString(String key, ObjectNode node, boolean required, String location, ParseResult result, Set<String> uniqueValues) {
694687
String value = null;
695688
JsonNode v = node.get(key);
696689
if (node == null || v == null) {
@@ -702,10 +695,18 @@ public String getString(String key, ObjectNode node, boolean required, String lo
702695
result.invalidType(location, key, "string", node);
703696
} else {
704697
value = v.asText();
698+
if (uniqueValues != null && !uniqueValues.add(value)) {
699+
result.unique(location, "operationId");
700+
result.invalid();
701+
}
705702
}
706703
return value;
707704
}
708705

706+
public String getString(String key, ObjectNode node, boolean required, String location, ParseResult result) {
707+
return getString(key, node, required, location, result, null);
708+
}
709+
709710
public Set<String> getKeys(ObjectNode node) {
710711
Set<String> keys = new LinkedHashSet<>();
711712
if (node == null) {
@@ -1053,6 +1054,11 @@ public Link getLink(ObjectNode linkNode, String location, ParseResult result) {
10531054
link.setParameters(getLinkParameters(parametersObject, location, result));
10541055
}
10551056

1057+
String requestBody = getString("requestBody",linkNode,false,location,result);
1058+
if (requestBody!= null) {
1059+
link.setRequestBody(requestBody);
1060+
}
1061+
10561062
ObjectNode headerObject = getObject("headers",linkNode,false,location,result);
10571063
if (headerObject!= null) {
10581064
link.setHeaders(getHeaders(headerObject, location, result));
@@ -1125,14 +1131,13 @@ public Callback getCallback(ObjectNode node,String location, ParseResult result)
11251131
JsonNode ref = node.get("$ref");
11261132
if (ref != null) {
11271133
if (ref.getNodeType().equals(JsonNodeType.STRING)) {
1128-
PathItem pathItem = new PathItem();
11291134
String mungedRef = mungedRef(ref.textValue());
11301135
if (mungedRef != null) {
1131-
pathItem.set$ref(mungedRef);
1136+
callback.set$ref(mungedRef);
11321137
}else{
1133-
pathItem.set$ref(ref.textValue());
1138+
callback.set$ref(ref.textValue());
11341139
}
1135-
return callback.addPathItem(name,pathItem);
1140+
return callback;
11361141
} else {
11371142
result.invalidType(location, "$ref", "string", node);
11381143
return null;
@@ -2458,7 +2463,7 @@ public Operation getOperation(ObjectNode obj, String location, ParseResult resul
24582463
if(docs != null) {
24592464
operation.setExternalDocs(docs);
24602465
}
2461-
value = getString("operationId", obj, false, location, result);
2466+
value = getString("operationId", obj, false, location, result, operationIDs);
24622467
if (StringUtils.isNotBlank(value)) {
24632468
operation.operationId(value);
24642469
}
@@ -2674,6 +2679,7 @@ protected static class ParseResult {
26742679
private Map<Location, String> invalidType = new LinkedHashMap<>();
26752680
private List<Location> missing = new ArrayList<>();
26762681
private List<Location> warnings = new ArrayList<>();
2682+
private List<Location> unique = new ArrayList<>();
26772683

26782684
public ParseResult() {
26792685
}
@@ -2689,10 +2695,15 @@ public void extra(String location, String key, JsonNode value) {
26892695
public void missing(String location, String key) {
26902696
missing.add(new Location(location, key));
26912697
}
2692-
2698+
26932699
public void warning(String location, String key) {
26942700
warnings.add(new Location(location, key));
26952701
}
2702+
2703+
public void unique(String location, String key) {
2704+
unique.add(new Location(location, key));
2705+
2706+
}
26962707

26972708
public void invalidType(String location, String key, String expectedType, JsonNode value) {
26982709
invalidType.put(new Location(location, key), expectedType);
@@ -2733,6 +2744,11 @@ public List<String> getMessages() {
27332744
String message = "attribute " + location + l.key + " is unsupported";
27342745
messages.add(message);
27352746
}
2747+
for (Location l : unique) {
2748+
String location = l.location.equals("") ? "" : l.location + ".";
2749+
String message = "attribute " + location + l.key + " is repeated";
2750+
messages.add(message);
2751+
}
27362752
return messages;
27372753
}
27382754
}

modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/ResolverFully.java

Lines changed: 56 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import io.swagger.v3.oas.models.PathItem;
66
import io.swagger.v3.oas.models.callbacks.Callback;
77
import io.swagger.v3.oas.models.examples.Example;
8+
import io.swagger.v3.oas.models.links.Link;
89
import io.swagger.v3.oas.models.media.ArraySchema;
910
import io.swagger.v3.oas.models.media.ComposedSchema;
1011
import io.swagger.v3.oas.models.media.MediaType;
@@ -13,6 +14,7 @@
1314
import io.swagger.v3.oas.models.parameters.Parameter;
1415
import io.swagger.v3.oas.models.parameters.RequestBody;
1516
import io.swagger.v3.oas.models.responses.ApiResponse;
17+
import io.swagger.v3.oas.models.responses.ApiResponses;
1618
import io.swagger.v3.parser.models.RefFormat;
1719
import org.slf4j.Logger;
1820
import org.slf4j.LoggerFactory;
@@ -47,8 +49,9 @@ public ResolverFully(boolean aggregateCombinators) {
4749
private Map<String, Schema> schemas;
4850
private Map<String, Schema> resolvedModels = new HashMap<>();
4951
private Map<String, Example> examples;
52+
private Map<String, Parameter> parameters;
5053
private Map<String, RequestBody> requestBodies;
51-
54+
private Map<String, Link> links;
5255

5356
public void resolveFully(OpenAPI openAPI) {
5457
if (openAPI.getComponents() != null && openAPI.getComponents().getRequestBodies() != null) {
@@ -72,6 +75,21 @@ public void resolveFully(OpenAPI openAPI) {
7275
}
7376
}
7477

78+
79+
if (openAPI.getComponents() != null && openAPI.getComponents().getParameters() != null) {
80+
parameters = openAPI.getComponents().getParameters();
81+
if (parameters == null) {
82+
parameters = new HashMap<>();
83+
}
84+
}
85+
if (openAPI.getComponents() != null && openAPI.getComponents().getLinks() != null) {
86+
links = openAPI.getComponents().getLinks();
87+
if (links == null) {
88+
links = new HashMap<>();
89+
90+
}
91+
}
92+
7593
if(openAPI.getPaths() != null) {
7694
for (String pathname : openAPI.getPaths().keySet()) {
7795
PathItem pathItem = openAPI.getPaths().get(pathname);
@@ -85,6 +103,7 @@ public void resolvePath(PathItem pathItem){
85103
// inputs
86104
if (op.getParameters() != null) {
87105
for (Parameter parameter : op.getParameters()) {
106+
parameter = parameter.get$ref() != null ? resolveParameter(parameter) : parameter;
88107
if (parameter.getSchema() != null) {
89108
Schema resolved = resolveSchema(parameter.getSchema());
90109
if (resolved != null) {
@@ -138,9 +157,10 @@ public void resolvePath(PathItem pathItem){
138157
}
139158
}
140159
// responses
141-
if(op.getResponses() != null) {
142-
for(String code : op.getResponses().keySet()) {
143-
ApiResponse response = op.getResponses().get(code);
160+
ApiResponses responses = op.getResponses();
161+
if(responses != null) {
162+
for(String code : responses.keySet()) {
163+
ApiResponse response = responses.get(code);
144164
if (response.getContent() != null) {
145165
Map<String, MediaType> content = response.getContent();
146166
for(String mediaType: content.keySet()){
@@ -155,11 +175,31 @@ public void resolvePath(PathItem pathItem){
155175
}
156176
}
157177
}
178+
Map<String, Link> links = response.getLinks();
179+
if (links != null) {
180+
for (Map.Entry<String, Link> link : links.entrySet()) {
181+
Link value = link.getValue();
182+
Link resolvedValue = value.get$ref() != null ? resolveLink(value) : value;
183+
link.setValue(resolvedValue);
184+
}
185+
}
158186
}
159187
}
160188
}
161189
}
162190

191+
public Link resolveLink(Link link){
192+
RefFormat refFormat = computeRefFormat(link.get$ref());
193+
String $ref = link.get$ref();
194+
if (!isAnExternalRefFormat(refFormat)){
195+
if (links != null && !links.isEmpty()) {
196+
String referenceKey = computeDefinitionName($ref);
197+
return links.getOrDefault(referenceKey, link);
198+
}
199+
}
200+
return link;
201+
}
202+
163203
public RequestBody resolveRequestBody(RequestBody requestBody){
164204
RefFormat refFormat = computeRefFormat(requestBody.get$ref());
165205
String $ref = requestBody.get$ref();
@@ -172,6 +212,18 @@ public RequestBody resolveRequestBody(RequestBody requestBody){
172212
return requestBody;
173213
}
174214

215+
public Parameter resolveParameter(Parameter parameter){
216+
String $ref = parameter.get$ref();
217+
RefFormat refFormat = computeRefFormat($ref);
218+
if (!isAnExternalRefFormat(refFormat)){
219+
if (parameters != null && !parameters.isEmpty()) {
220+
String referenceKey = computeDefinitionName($ref);
221+
return parameters.getOrDefault(referenceKey, parameter);
222+
}
223+
}
224+
return parameter;
225+
}
226+
175227
public Schema resolveSchema(Schema schema) {
176228
if(schema.get$ref() != null) {
177229
String ref= schema.get$ref();

modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java

Lines changed: 18 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -339,11 +339,11 @@ public void componentsResolver() throws Exception {
339339

340340
Map<String, Callback> callbacks = openAPI.getComponents().getCallbacks();
341341
// internal callback reference
342-
assertEquals(callbacks.get("referenced").get("$ref").get$ref(),"#/components/callbacks/failed");
342+
assertEquals(callbacks.get("referenced").get$ref(),"#/components/callbacks/failed");
343343
//callback pathItem -> operation ->requestBody
344344
assertEquals(callbacks.get("heartbeat").get("$request.query.heartbeat-url").getPost().getRequestBody().get$ref(),"#/components/requestBodies/requestBody3");
345345
//remote callback ref
346-
assertEquals(callbacks.get("remoteCallback").get("$ref").get$ref(),"#/components/callbacks/callback");
346+
assertEquals(callbacks.get("remoteCallback").get$ref(),"http://localhost:" + serverPort + "/remote/callback");
347347

348348
}
349349

@@ -1102,6 +1102,21 @@ public void testSettingsAddParametersToEachOperationDisabled() {
11021102
assertEquals(qp.getName(), "page");
11031103
}
11041104

1105+
@Test(description = "update internal references of external files")
1106+
public void testUpdateInternalReferencesOfExternalFiles() {
1107+
ParseOptions options = new ParseOptions();
1108+
options.setResolve(true);
1109+
1110+
OpenAPI openAPI = new OpenAPIV3Parser().read("internal-references-in-external-files/main.yaml", null, options);
1111+
1112+
ComposedSchema commonSchema = (ComposedSchema) openAPI.getComponents().getSchemas().get("common");
1113+
1114+
assertEquals(commonSchema.getAllOf().get(0).get$ref(), "#/components/schemas/core");
1115+
assertEquals(((Schema) commonSchema.getAllOf().get(1).getProperties().get("direct")).get$ref(), "#/components/schemas/core");
1116+
assertEquals(((ArraySchema) commonSchema.getAllOf().get(1).getProperties().get("referenced")).getItems().get$ref(), "#/components/schemas/core");
1117+
Schema coreSchema = openAPI.getComponents().getSchemas().get("core");
1118+
assertEquals(((Schema) coreSchema.getProperties().get("inner")).get$ref(), "#/components/schemas/innerCore");
1119+
}
11051120

11061121
public String replacePort(String url){
11071122
String pathFile = url.replace("${dynamicPort}", String.valueOf(this.serverPort));
@@ -1112,4 +1127,4 @@ private static int getDynamicPort() {
11121127
return new Random().ints(50000, 60000).findFirst().getAsInt();
11131128
}
11141129

1115-
}
1130+
}

0 commit comments

Comments
 (0)