Skip to content

Commit

Permalink
Implement x-reusable-definitions-only (#49)
Browse files Browse the repository at this point in the history
  • Loading branch information
smals-mavh authored Jan 9, 2025
1 parent a8292c6 commit 2d167ab
Show file tree
Hide file tree
Showing 14 changed files with 475 additions and 3 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,15 @@ public class PathDefinition extends OpenApiDefinition<PathItem> {

public PathDefinition(PathItem model, PathsDefinition parent, String identifier) {
super(model, parent, identifier, JsonPointer.relative(identifier));
this.isDirectPath = parent.isInMainFile();
this.isDirectPath = parent.isInMainFile() && !hasReusableDefinitionsOnly();
}

@Override
public PathItem getModel() {
return super.getModel();
}

private boolean hasReusableDefinitionsOnly() {
return this.getResult().getSrc().get(this.getOpenApiFile().getAbsolutePath()).hasReusableDefinitionsOnly();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -564,7 +564,8 @@ private void constructExamples(OpenApiDefinition<?> definition, ParserResult res

private static List<String> getLines(File file) throws IOException {
var lines = Files.readAllLines(file.toPath());
if (lines.size() < 1) throw new RuntimeException("[Internal error] File: " + file.getName() + " appears to be empty!");
if (lines.isEmpty())
throw new RuntimeException("[Internal error] File: " + file.getName() + " appears to be empty!");
// lines > 1 then is a yaml or a pretty json file
if (lines.size() > 1) return lines;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,22 +9,38 @@

@Getter
public class SourceDefinition {
private static final String REF_ONLY_KEY = "x-reusable-definitions-only";

private final String fileName;
private final File file;
private final String src;
private final boolean isYaml;
private final OpenAPI openApi;
private final boolean hasReusableDefinitionsOnly;

public SourceDefinition(File file, OpenAPI openApi) throws IOException {
this.file = file;
this.fileName = file.getName();
this.src = Files.readString(file.toPath());
this.isYaml = checkIsYaml(this.fileName);
this.openApi = openApi;
this.hasReusableDefinitionsOnly = findHasReusableDefinitionsOnly(openApi);
}

public static boolean checkIsYaml(String fileName) {
return fileName.endsWith("yaml") || fileName.endsWith("yml");
}

public boolean hasReusableDefinitionsOnly() {
return hasReusableDefinitionsOnly;
}

private static boolean findHasReusableDefinitionsOnly(OpenAPI openApi) {
if (openApi.getExtensions() != null &&
openApi.getExtensions().containsKey(REF_ONLY_KEY) &&
openApi.getExtensions().get(REF_ONLY_KEY) instanceof Boolean) {
return ((Boolean) openApi.getExtensions().get(REF_ONLY_KEY));
}
return false;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -288,4 +288,33 @@ void testNonValidExampleIsParsed() {
Parser.ParserResult result = new Parser(file).parse(oas);
assertEquals(2, result.getExamples().size());
}

@Test
void testRefOnly() {
var oas = new ViolationReport();
var file = new File(Objects.requireNonNull(getClass().getResource("../rules/referenceOnly/refOnly.yaml")).getFile());

Parser.ParserResult result = new Parser(file).parse(oas);
assertFalse(result.getPathDefinitions().stream().findFirst().get().isDirectPath());
}

@Test
void testRefOnlyFalse() {
var oas = new ViolationReport();
var file = new File(Objects.requireNonNull(getClass().getResource("../rules/referenceOnly/refOnlyFalse.yaml")).getFile());

Parser.ParserResult result = new Parser(file).parse(oas);
assertEquals(1, result.getServers().size());
assertTrue(result.getPathDefinitions().stream().findFirst().get().isDirectPath());
}

@Test
void testRefOnlyRandomString() {
var oas = new ViolationReport();
var file = new File(Objects.requireNonNull(getClass().getResource("../rules/referenceOnly/refOnlyRandomString.yaml")).getFile());

Parser.ParserResult result = new Parser(file).parse(oas);
assertEquals(1, result.getServers().size());
assertTrue(result.getPathDefinitions().stream().findFirst().get().isDirectPath());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
openapi: 3.0.0
x-reusable-definitions-only: true
info:
title: test
description: test
version: "1.0"
servers:
- url: https://myserver.com
paths:
/myPath:
get:
responses:
default:
content:
application/json:
schema:
type: object
description: myDescription
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
openapi: 3.0.0
x-reusable-definitions-only: false
info:
title: test
description: test
version: "1.0"
servers:
- url: https://myserver.com
paths:
/myPath:
get:
responses:
default:
content:
application/json:
schema:
type: object
description: myDescription
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
openapi: 3.0.0
x-reusable-definitions-only: "random string"
info:
title: test
description: test
version: "1.0"
servers:
- url: https://myserver.com
paths:
/myPath:
get:
responses:
default:
content:
application/json:
schema:
type: object
description: myDescription
170 changes: 170 additions & 0 deletions integrationtest/src/it/reusableDefinitionsOnly/common.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
openapi: 3.0.0
x-reusable-definitions-only: true
info:
title: common technical data types
version: ${project.version}
license:
name: Apache 2.0
url: https://www.apache.org/licenses/LICENSE-2.0.html
paths:
/health: # Operation may be secured, but access should be allowed to all clients. In order to add a security scheme, copy this definition instead of referencing it.
get:
tags:
- Monitoring
summary: Check health of the service
operationId: checkHealth
externalDocs:
url: "https://www.belgif.be/specification/rest/api-guide/#health"
security: []
responses:
"200":
"$ref": "#/components/responses/HealthUpOrDegradedResponse"
"503":
"$ref": "#/components/responses/HealthDownResponse"
default:
$ref: "problem.yaml#/components/responses/ProblemResponse"
components:
parameters:
LangQueryParameter:
in: query
name: lang
schema:
$ref: "#/components/schemas/BelgianLanguage"
PageQueryParameter:
description: Number of requested page in a paged resource collection. Page numbers are 1-based.
in: query
name: page
schema:
type: integer
minimum: 1
SelectQueryParameter:
description: Only return selected parts of resource's representation. Parameter value is in BNF-notation.
in: query
name: select
schema:
type: string
responses:
HealthUpOrDegradedResponse:
description: The service is UP or DEGRADED
content:
application/json:
schema:
$ref: "#/components/schemas/HealthStatus"
examples:
responseUp:
description: API is available
value:
{
"status": "UP"
}
responseDegraded:
description: API is available, but with reduced functionality
value:
{
"status": "DEGRADED"
}
HealthDownResponse:
description: The service is DOWN
content:
application/json:
schema:
$ref: "#/components/schemas/HealthStatus"
examples:
responseDown:
value:
{
"status": "DOWN"
}
schemas:
BelgianLanguage:
description: One of the official Belgian languages represented by an ISO-639-1 code
type: string
enum:
- fr
- nl
- de
Language:
description: A language represented by an ISO-639-1 code
type: string
pattern: "^[a-z]{2}$"
example: "en"
LongRunningTaskStatus:
description: status of a long running task
type: object
properties:
state:
type: string
enum:
- processing
- failed
- done
pollAfter:
description: hint when to check the status again
type: string
format: date-time
completed:
description: when the task has completed (in case state is done or failed)
type: string
format: date-time
problem:
$ref: "problem.yaml#/components/schemas/Problem"
required: [state]
example:
{
"state": "failed",
"completed": "2018-09-13T02:10:00.000Z",
"problem": {
"instance": "urn:uuid:d9e35127-e9b1-4201-a211-2b52e52508df",
"title": "Bad Request",
"status": 400,
"type": "urn:problem-type:example:invalidImageFormat",
"detail": "Invalid image format"
}
}
HttpLink:
description: A base type of objects representing links to resources.
type: object
properties:
href:
description: Any absolute URI that is using http or https protocol
type: string
format: uri
readOnly: true
LocalizedString:
description: A description specified in multiple languages
type: object
properties:
#nl, fr, de are predefined, but additional languages can be added
nl:
type: string
fr:
type: string
de:
type: string
MergePatch:
deprecated: true # Define a specific schema for JSON Merge patch request body instead of using this marker type (see [doc-patch] rule)
description: JSON Merge Patch (RFC 7386) request body
type: object
additionalProperties: true
SelfLink:
description: A base type representing a link to the resource's own location within its representation
type: object
properties:
self:
description: Any absolute URI that is using http or https protocol
type: string
format: uri
readOnly: true
Uuid:
description: Universally Unique Identifier, as standardized in RFC 4122 and ISO/IEC 9834-8
type: string
pattern: '^[\da-f]{8}-[\da-f]{4}-[\da-f]{4}-[\da-f]{4}-[\da-f]{12}$'
HealthStatus:
description: Response message for the API health
type: object
properties:
status:
description: "Level indicating the health status of the service: UP (functioning as expected), DOWN (suffering unexpected failures), DEGRADED (partly unavailable but service can be continued with reduced functionality), or a custom status value"
type: string
required:
- status
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
invoker.goals = prepare-package
invoker.buildResult = success
37 changes: 37 additions & 0 deletions integrationtest/src/it/reusableDefinitionsOnly/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>io.github.belgif.rest.guide.validator</groupId>
<artifactId>plugin-test</artifactId>
<version>1.0.0-SNAPSHOT</version>

<properties>
<!-- Overwritten in maven-invoker-plugin -->
<pluginVersion>latest</pluginVersion>
</properties>

<build>
<plugins>
<plugin>
<groupId>io.github.belgif.rest.guide.validator</groupId>
<artifactId>belgif-rest-guide-validator-maven-plugin</artifactId>
<version>${pluginVersion}</version>
<executions>
<execution>
<goals>
<goal>validate</goal>
</goals>
</execution>
</executions>
<configuration>
<files>
<file>common.yaml</file>
</files>
</configuration>
</plugin>
</plugins>
</build>

</project>
Loading

0 comments on commit 2d167ab

Please sign in to comment.