diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java index b30f168487..2e51151d1d 100644 --- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java +++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/processors/ExternalRefProcessor.java @@ -36,6 +36,11 @@ public ExternalRefProcessor(ResolverCache cache, OpenAPI openAPI) { } public String processRefToExternalSchema(String $ref, RefFormat refFormat) { + String renamedRef = cache.getRenamedRef($ref); + if(renamedRef != null) { + return renamedRef; + } + final Schema schema = cache.loadRef($ref, refFormat, Schema.class); if(schema == null) { @@ -52,7 +57,7 @@ public String processRefToExternalSchema(String $ref, RefFormat refFormat) { schemas = new LinkedHashMap<>(); } - final String possiblyConflictingDefinitionName = computeDefinitionName($ref); + final String possiblyConflictingDefinitionName = computeDefinitionName($ref, schemas.keySet()); Schema existingModel = schemas.get(possiblyConflictingDefinitionName); @@ -111,6 +116,11 @@ public String processRefToExternalSchema(String $ref, RefFormat refFormat) { } public String processRefToExternalResponse(String $ref, RefFormat refFormat) { + String renamedRef = cache.getRenamedRef($ref); + if(renamedRef != null) { + return renamedRef; + } + final ApiResponse response = cache.loadRef($ref, refFormat, ApiResponse.class); if(response == null) { @@ -127,7 +137,7 @@ public String processRefToExternalResponse(String $ref, RefFormat refFormat) { responses = new LinkedHashMap<>(); } - final String possiblyConflictingDefinitionName = computeDefinitionName($ref); + final String possiblyConflictingDefinitionName = computeDefinitionName($ref, responses.keySet()); ApiResponse existingResponse = responses.get(possiblyConflictingDefinitionName); @@ -161,6 +171,11 @@ public String processRefToExternalResponse(String $ref, RefFormat refFormat) { } public String processRefToExternalRequestBody(String $ref, RefFormat refFormat) { + String renamedRef = cache.getRenamedRef($ref); + if(renamedRef != null) { + return renamedRef; + } + final RequestBody body = cache.loadRef($ref, refFormat, RequestBody.class); if(body == null) { @@ -177,7 +192,7 @@ public String processRefToExternalRequestBody(String $ref, RefFormat refFormat) bodies = new LinkedHashMap<>(); } - final String possiblyConflictingDefinitionName = computeDefinitionName($ref); + final String possiblyConflictingDefinitionName = computeDefinitionName($ref, bodies.keySet()); RequestBody existingBody= bodies.get(possiblyConflictingDefinitionName); @@ -211,6 +226,11 @@ public String processRefToExternalRequestBody(String $ref, RefFormat refFormat) } public String processRefToExternalHeader(String $ref, RefFormat refFormat) { + String renamedRef = cache.getRenamedRef($ref); + if(renamedRef != null) { + return renamedRef; + } + final Header header = cache.loadRef($ref, refFormat, Header.class); if(header == null) { @@ -227,7 +247,7 @@ public String processRefToExternalHeader(String $ref, RefFormat refFormat) { headers = new LinkedHashMap<>(); } - final String possiblyConflictingDefinitionName = computeDefinitionName($ref); + final String possiblyConflictingDefinitionName = computeDefinitionName($ref, headers.keySet()); Header existingHeader = headers.get(possiblyConflictingDefinitionName); @@ -261,6 +281,11 @@ public String processRefToExternalHeader(String $ref, RefFormat refFormat) { } public String processRefToExternalSecurityScheme(String $ref, RefFormat refFormat) { + String renamedRef = cache.getRenamedRef($ref); + if(renamedRef != null) { + return renamedRef; + } + final SecurityScheme securityScheme = cache.loadRef($ref, refFormat, SecurityScheme.class); if(securityScheme == null) { @@ -277,7 +302,7 @@ public String processRefToExternalSecurityScheme(String $ref, RefFormat refForma securitySchemeMap = new LinkedHashMap<>(); } - final String possiblyConflictingDefinitionName = computeDefinitionName($ref); + final String possiblyConflictingDefinitionName = computeDefinitionName($ref, securitySchemeMap.keySet()); SecurityScheme existingSecurityScheme = securitySchemeMap.get(possiblyConflictingDefinitionName); @@ -311,6 +336,11 @@ public String processRefToExternalSecurityScheme(String $ref, RefFormat refForma } public String processRefToExternalLink(String $ref, RefFormat refFormat) { + String renamedRef = cache.getRenamedRef($ref); + if(renamedRef != null) { + return renamedRef; + } + final Link link = cache.loadRef($ref, refFormat, Link.class); if(link == null) { @@ -327,7 +357,7 @@ public String processRefToExternalLink(String $ref, RefFormat refFormat) { links = new LinkedHashMap<>(); } - final String possiblyConflictingDefinitionName = computeDefinitionName($ref); + final String possiblyConflictingDefinitionName = computeDefinitionName($ref, links.keySet()); Link existingLink = links.get(possiblyConflictingDefinitionName); @@ -361,6 +391,11 @@ public String processRefToExternalLink(String $ref, RefFormat refFormat) { } public String processRefToExternalExample(String $ref, RefFormat refFormat) { + String renamedRef = cache.getRenamedRef($ref); + if(renamedRef != null) { + return renamedRef; + } + final Example example = cache.loadRef($ref, refFormat, Example.class); if(example == null) { @@ -377,7 +412,7 @@ public String processRefToExternalExample(String $ref, RefFormat refFormat) { examples = new LinkedHashMap<>(); } - final String possiblyConflictingDefinitionName = computeDefinitionName($ref); + final String possiblyConflictingDefinitionName = computeDefinitionName($ref, examples.keySet()); Example existingExample = examples.get(possiblyConflictingDefinitionName); @@ -411,6 +446,11 @@ public String processRefToExternalExample(String $ref, RefFormat refFormat) { } public String processRefToExternalParameter(String $ref, RefFormat refFormat) { + String renamedRef = cache.getRenamedRef($ref); + if(renamedRef != null) { + return renamedRef; + } + final Parameter parameter = cache.loadRef($ref, refFormat, Parameter.class); if(parameter == null) { @@ -427,7 +467,7 @@ public String processRefToExternalParameter(String $ref, RefFormat refFormat) { parameters = new LinkedHashMap<>(); } - final String possiblyConflictingDefinitionName = computeDefinitionName($ref); + final String possiblyConflictingDefinitionName = computeDefinitionName($ref, parameters.keySet()); Parameter existingParameters = parameters.get(possiblyConflictingDefinitionName); @@ -461,6 +501,11 @@ public String processRefToExternalParameter(String $ref, RefFormat refFormat) { } public String processRefToExternalCallback(String $ref, RefFormat refFormat) { + String renamedRef = cache.getRenamedRef($ref); + if(renamedRef != null) { + return renamedRef; + } + final Callback callback = cache.loadRef($ref, refFormat, Callback.class); if(callback == null) { @@ -477,7 +522,7 @@ public String processRefToExternalCallback(String $ref, RefFormat refFormat) { callbacks = new LinkedHashMap<>(); } - final String possiblyConflictingDefinitionName = computeDefinitionName($ref); + final String possiblyConflictingDefinitionName = computeDefinitionName($ref, callback.keySet()); Callback existingCallback = callbacks.get(possiblyConflictingDefinitionName); diff --git a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/RefUtils.java b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/RefUtils.java index da4ba5fb25..cc45250096 100644 --- a/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/RefUtils.java +++ b/modules/swagger-parser-v3/src/main/java/io/swagger/v3/parser/util/RefUtils.java @@ -11,10 +11,11 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.List; +import java.util.Set; public class RefUtils { - public static String computeDefinitionName(String ref) { + public static String computeDefinitionName(String ref, Set reserved) { final String[] refParts = ref.split("#/"); @@ -38,8 +39,13 @@ public static String computeDefinitionName(String ref) { final String[] split = plausibleName.split("\\."); plausibleName = split[0]; } + String tryName = plausibleName; - return plausibleName; + for (int i = 2; reserved.contains(tryName); i++) { + tryName = plausibleName + "_" + i; + } + + return tryName; } public static boolean isAnExternalRefFormat(RefFormat refFormat) { diff --git a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java index 159d56c49c..304c8f117a 100644 --- a/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java +++ b/modules/swagger-parser-v3/src/test/java/io/swagger/v3/parser/test/OpenAPIResolverTest.java @@ -33,6 +33,7 @@ import org.apache.commons.io.FileUtils; import org.testng.Assert; +import org.testng.AssertJUnit; import org.testng.annotations.AfterClass; import org.testng.annotations.BeforeClass; import org.testng.annotations.Test; @@ -187,7 +188,7 @@ public void componentsResolver(@Injectable final List auths) //remote url schema Schema user = (Schema) pet.getProperties().get("user"); - assertEquals(user.get$ref(),"#/components/schemas/User"); + assertEquals(user.get$ref(),"#/components/schemas/User_3"); //ArraySchema items @@ -200,7 +201,7 @@ public void componentsResolver(@Injectable final List auths) assertEquals(schemas.get("OrderRef").getNot().get$ref(), "#/components/schemas/Category"); //Schema additionalProperties - assertEquals(schemas.get("OrderRef").getAdditionalProperties().get$ref(), "#/components/schemas/User"); + assertEquals(schemas.get("OrderRef").getAdditionalProperties().get$ref(), "#/components/schemas/User_3"); //AllOfSchema ComposedSchema extended = (ComposedSchema) schemas.get("ExtendedErrorModel"); @@ -265,7 +266,7 @@ public void componentsResolver(@Injectable final List auths) //internal Schema header Map headers = openAPI.getComponents().getHeaders(); //header remote schema ref - assertEquals(headers.get("X-Rate-Limit-Remaining").getSchema().get$ref(),"#/components/schemas/User"); + assertEquals(headers.get("X-Rate-Limit-Remaining").getSchema().get$ref(),"#/components/schemas/User_3"); //header examples assertEquals(headers.get("X-Rate-Limit-Reset").getExamples().get("headerExample").get$ref(), "#/components/examples/dog" ); @@ -603,6 +604,19 @@ public void resolveComposedSchema(@Injectable final List aut } + @Test + public void testRefNameConflicts() throws Exception { + ParseOptions options = new ParseOptions(); + options.setResolveFully(true); + OpenAPI openAPI = new OpenAPIV3Parser().readLocation("src/test/resources/refs-name-conflict/a.yaml",null, options).getOpenAPI(); + + AssertJUnit.assertEquals("local", ((Schema) openAPI.getPaths().get("/newPerson").getPost().getResponses().get("200").getContent().get("*/*").getSchema().getProperties().get("location")).getExample()); + AssertJUnit.assertEquals("referred", ((Schema)openAPI.getPaths().get("/oldPerson").getPost().getResponses().get("200").getContent().get("*/*").getSchema().getProperties().get("location")).getExample()); + AssertJUnit.assertEquals("referred", ((Schema)openAPI.getPaths().get("/yetAnotherPerson").getPost().getResponses().get("200").getContent().get("*/*").getSchema().getProperties().get("location")).getExample()); + AssertJUnit.assertEquals("local", ((Schema) openAPI.getComponents().getSchemas().get("PersonObj").getProperties().get("location")).getExample()); + AssertJUnit.assertEquals("referred", ((Schema) openAPI.getComponents().getSchemas().get("PersonObj_2").getProperties().get("location")).getExample()); + } + private static int getDynamicPort() { return new Random().ints(50000, 60000).findFirst().getAsInt(); } diff --git a/modules/swagger-parser-v3/src/test/resources/refs-name-conflict/a.yaml b/modules/swagger-parser-v3/src/test/resources/refs-name-conflict/a.yaml new file mode 100644 index 0000000000..106b095786 --- /dev/null +++ b/modules/swagger-parser-v3/src/test/resources/refs-name-conflict/a.yaml @@ -0,0 +1,47 @@ +openapi: 3.0.0 +servers: [] +info: + version: 1.0.0 + title: Person + description: Maintain Person data +paths: + /newPerson: + post: + summary: Create new person + description: Create new person + responses: + '200': + description: OK + content: + '*/*': + schema: + $ref: '#/components/schemas/PersonObj' + /oldPerson: + post: + summary: Create old person + description: Create old person + responses: + '200': + description: OK + content: + '*/*': + schema: + $ref: './src/test/resources/refs-name-conflict/b.yaml#/components/schemas/PersonObj' + /yetAnotherPerson: + post: + summary: Create yet another person + description: Create yet another person + responses: + '200': + description: OK + content: + '*/*': + schema: + $ref: './src/test/resources/refs-name-conflict/b.yaml#/components/schemas/PersonObj' +components: + schemas: + PersonObj: + properties: + location: + type: string + example: local \ No newline at end of file diff --git a/modules/swagger-parser-v3/src/test/resources/refs-name-conflict/b.yaml b/modules/swagger-parser-v3/src/test/resources/refs-name-conflict/b.yaml new file mode 100644 index 0000000000..0d1376854f --- /dev/null +++ b/modules/swagger-parser-v3/src/test/resources/refs-name-conflict/b.yaml @@ -0,0 +1,13 @@ +openapi: 3.0.0 +servers: [] +info: + version: '' + title: '' +paths: {} +components: + schemas: + PersonObj: + properties: + location: + type: string + example: referred \ No newline at end of file