Skip to content

Commit 7f53027

Browse files
Merge pull request #49 from apiaddicts/fix/41/oar006_009
fixing show mime types into post,put or patch verbs
2 parents f796367 + 60e8856 commit 7f53027

35 files changed

+140
-107
lines changed

src/main/java/apiaddicts/sonar/openapi/checks/format/AbstractDefaultMediaTypeCheck.java

Lines changed: 41 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,21 @@
11
package apiaddicts.sonar.openapi.checks.format;
22

3+
import apiaddicts.sonar.openapi.checks.BaseCheck;
4+
import apiaddicts.sonar.openapi.utils.MediaTypeUtils;
5+
36
import com.google.common.collect.ImmutableSet;
47
import com.sonar.sslr.api.AstNode;
58
import com.sonar.sslr.api.AstNodeType;
6-
import org.sonar.check.RuleProperty;
7-
import org.apiaddicts.apitools.dosonarapi.api.v2.OpenApi2Grammar;
8-
import org.apiaddicts.apitools.dosonarapi.api.v3.OpenApi3Grammar;
9-
import org.apiaddicts.apitools.dosonarapi.api.v31.OpenApi31Grammar;
10-
import apiaddicts.sonar.openapi.checks.BaseCheck;
11-
import org.apiaddicts.apitools.dosonarapi.sslr.yaml.grammar.JsonNode;
12-
139
import java.util.List;
1410
import java.util.Map;
1511
import java.util.Set;
1612
import java.util.stream.Collectors;
1713
import java.util.stream.Stream;
18-
19-
import static apiaddicts.sonar.openapi.utils.JsonNodeUtils.*;
14+
import org.apiaddicts.apitools.dosonarapi.api.v2.OpenApi2Grammar;
15+
import org.apiaddicts.apitools.dosonarapi.api.v3.OpenApi3Grammar;
16+
import org.apiaddicts.apitools.dosonarapi.api.v31.OpenApi31Grammar;
17+
import org.apiaddicts.apitools.dosonarapi.sslr.yaml.grammar.JsonNode;
18+
import org.sonar.check.RuleProperty;
2019

2120
public abstract class AbstractDefaultMediaTypeCheck extends BaseCheck {
2221

@@ -74,58 +73,58 @@ public void visitNode(JsonNode node) {
7473
}
7574

7675
private void visitV2Node(JsonNode node) {
76+
if (node.getType() != OpenApi2Grammar.OPERATION) return;
77+
78+
String operation = node.key().getTokenValue().toLowerCase();
79+
if (!(operation.equals("post") || operation.equals("put") || operation.equals("patch"))) return;
80+
7781
JsonNode sectionNode = node.get(section);
7882
boolean definesMimeTypes = !sectionNode.isMissing();
7983

8084
if (definesMimeTypes) {
8185
if (!supportsDefaultMimeTypeV2(node)) {
8286
addIssue(key, message, sectionNode.key());
8387
}
84-
} else {
85-
if (!globalSupportsDefaultMimeType) {
86-
addIssue(key, message, node.key());
87-
}
88+
return;
89+
}
90+
91+
if (!globalSupportsDefaultMimeType) {
92+
addIssue(key, message, node.key());
8893
}
8994
}
9095

9196
private void visitV3Node(JsonNode node) {
97+
9298
if (node.getType() == OpenApi3Grammar.OPERATION && section.equals("consumes")) {
93-
String operation = node.key().getTokenValue().toLowerCase();
94-
if (operation.equals("post") || operation.equals("put") || operation.equals("patch")) {
95-
visitContentNode(node);
96-
} else {
97-
JsonNode requestBodyNode = node.at("/requestBody");
98-
if (!requestBodyNode.isMissing()) {
99-
addIssue(key, translate("OAR010.error-request-body-not-allowed", operation.toUpperCase()), node.key());
100-
}
101-
}
99+
handleConsumesOperation(node);
100+
return;
102101
}
103102

104103
if (node.getType() == OpenApi3Grammar.RESPONSES && section.equals("produces")) {
105-
List<JsonNode> responseCodes = node.properties().stream().collect(Collectors.toList());
106-
for (JsonNode jsonNode : responseCodes) {
107-
if (!jsonNode.key().getTokenValue().equals("204")) {
108-
boolean externalRefManagement = false;
109-
if (isExternalRef(jsonNode) && externalRefNode == null) {
110-
externalRefNode = jsonNode;
111-
externalRefManagement = true;
112-
}
113-
jsonNode = resolve(jsonNode);
114-
visitContentNode(jsonNode);
115-
if (externalRefManagement) externalRefNode = null;
116-
}
117-
}
104+
MediaTypeUtils.handleProducesResponses(node, externalRefNode, this::visitContentNode);
118105
}
119106
}
120107

121-
private void visitContentNode(JsonNode node) {
122-
JsonNode contentNode;
123-
if (section.equals("consumes")) {
124-
JsonNode requestBodyNode = node.at("/requestBody");
125-
contentNode = resolve(requestBodyNode).at("/content");
126-
} else {
127-
contentNode = node.at("/content");
108+
private void handleConsumesOperation(JsonNode node) {
109+
String operation = node.key().getTokenValue().toLowerCase();
110+
boolean allowsBody = operation.equals("post") || operation.equals("put") || operation.equals("patch");
111+
112+
if (allowsBody) {
113+
visitContentNode(node);
114+
return;
115+
}
116+
117+
JsonNode requestBodyNode = node.at("/requestBody");
118+
if (!requestBodyNode.isMissing()) {
119+
addIssue(key,
120+
translate("OAR010.error-request-body-not-allowed", operation.toUpperCase()),
121+
node.key());
128122
}
123+
}
124+
125+
private void visitContentNode(JsonNode node) {
126+
JsonNode contentNode = MediaTypeUtils.getContentNode(node, section);
127+
129128
boolean definesMimeTypes = !contentNode.isMissing();
130129
if (definesMimeTypes) {
131130
if (!supportsDefaultMimeTypeV3(contentNode)) {

src/main/java/apiaddicts/sonar/openapi/checks/format/AbstractUndefinedMediaTypeCheck.java

Lines changed: 28 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,17 @@
11
package apiaddicts.sonar.openapi.checks.format;
22

3+
import apiaddicts.sonar.openapi.checks.BaseCheck;
4+
import apiaddicts.sonar.openapi.utils.MediaTypeUtils;
5+
36
import com.google.common.collect.ImmutableSet;
47
import com.sonar.sslr.api.AstNodeType;
8+
import java.util.Map;
9+
import java.util.Set;
510
import org.apiaddicts.apitools.dosonarapi.api.v2.OpenApi2Grammar;
611
import org.apiaddicts.apitools.dosonarapi.api.v3.OpenApi3Grammar;
712
import org.apiaddicts.apitools.dosonarapi.api.v31.OpenApi31Grammar;
8-
import apiaddicts.sonar.openapi.checks.BaseCheck;
913
import org.apiaddicts.apitools.dosonarapi.sslr.yaml.grammar.JsonNode;
1014

11-
import java.util.List;
12-
import java.util.Map;
13-
import java.util.Set;
14-
import java.util.stream.Collectors;
15-
16-
import static apiaddicts.sonar.openapi.utils.JsonNodeUtils.*;
17-
1815
public abstract class AbstractUndefinedMediaTypeCheck extends BaseCheck {
1916

2017
private static final String MESSAGE = "generic.section";
@@ -49,47 +46,49 @@ public void visitNode(JsonNode node) {
4946
}
5047

5148
private void visitV2Node(JsonNode node) {
52-
if (!globalDefinesMediaTypes && !definesMimeTypesV2(node)) {
53-
addIssue(key, translate(MESSAGE, section), node.key());
49+
if (node.getType() == OpenApi2Grammar.OPERATION) {
50+
String operation = node.key().getTokenValue().toLowerCase();
51+
52+
if ((operation.equals("post") || operation.equals("put") || operation.equals("patch"))
53+
&& !globalDefinesMediaTypes
54+
&& !definesMimeTypesV2(node)) {
55+
56+
addIssue(key, translate(MESSAGE, section), node.key());
57+
}
5458
}
5559
}
5660

5761
private void visitV3Node(JsonNode node) {
5862
if (node.getType() == OpenApi3Grammar.OPERATION && section.equals("consumes")) {
59-
String operation = node.key().getTokenValue().toLowerCase();
60-
if (operation.equals("post") || operation.equals("put") || operation.equals("patch")) {
61-
visitContentNode(node);
62-
}
63+
handleConsumesOperation(node);
64+
return;
6365
}
6466

6567
if (node.getType() == OpenApi3Grammar.RESPONSES && section.equals("produces")) {
66-
List<JsonNode> responseCodes = node.properties().stream().collect(Collectors.toList());
67-
for (JsonNode jsonNode : responseCodes) {
68-
if (!jsonNode.key().getTokenValue().equals("204")) {
69-
boolean externalRefManagement = false;
70-
if (isExternalRef(jsonNode) && externalRefNode == null) {
71-
externalRefNode = jsonNode;
72-
externalRefManagement = true;
73-
}
74-
jsonNode = resolve(jsonNode);
75-
visitContentNode(jsonNode);
76-
if (externalRefManagement) externalRefNode = null;
77-
}
78-
}
68+
MediaTypeUtils.handleProducesResponses(node, externalRefNode, this::visitContentNode);
69+
}
70+
}
71+
72+
private void handleConsumesOperation(JsonNode node) {
73+
String operation = node.key().getTokenValue().toLowerCase();
74+
75+
if (operation.equals("post") || operation.equals("put") || operation.equals("patch")) {
76+
visitContentNode(node);
7977
}
8078
}
8179

8280
private void visitContentNode(JsonNode node) {
8381
JsonNode contentNode;
82+
8483
if (section.equals("consumes")) {
8584
JsonNode requestBodyNode = node.at("/requestBody");
8685
if (requestBodyNode.isMissing() || requestBodyNode.isNull()) {
8786
addIssue(key, translate(MESSAGE, "requestBody"), node.key());
8887
return;
8988
}
90-
contentNode = resolve(requestBodyNode).at("/content");
89+
contentNode = MediaTypeUtils.getContentNode(node, section);
9190
} else {
92-
contentNode = node.at("/content");
91+
contentNode = MediaTypeUtils.getContentNode(node, section);
9392
}
9493

9594
if (!globalDefinesMediaTypes && !definesMimeTypesV3(contentNode)) {
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package apiaddicts.sonar.openapi.utils;
2+
3+
import org.apiaddicts.apitools.dosonarapi.sslr.yaml.grammar.JsonNode;
4+
import java.util.function.Consumer;
5+
import static apiaddicts.sonar.openapi.utils.JsonNodeUtils.isExternalRef;
6+
import static apiaddicts.sonar.openapi.utils.JsonNodeUtils.resolve;
7+
8+
public class MediaTypeUtils {
9+
10+
private MediaTypeUtils() {
11+
}
12+
13+
public static void handleProducesResponses(JsonNode node, JsonNode externalRefNode, Consumer<JsonNode> visitContentNode) {
14+
for (JsonNode jsonNode : node.properties()) {
15+
if (jsonNode.key().getTokenValue().equals("204")) continue;
16+
17+
boolean manageExternal = isExternalRef(jsonNode) && externalRefNode == null;
18+
if (manageExternal) externalRefNode = jsonNode;
19+
20+
JsonNode resolved = resolve(jsonNode);
21+
visitContentNode.accept(resolved);
22+
23+
if (manageExternal) externalRefNode = null;
24+
}
25+
}
26+
27+
public static JsonNode getContentNode(JsonNode node, String section) {
28+
if ("consumes".equals(section)) {
29+
JsonNode requestBodyNode = node.at("/requestBody");
30+
return resolve(requestBodyNode).at("/content");
31+
} else {
32+
return node.at("/content");
33+
}
34+
}
35+
}

src/test/resources/checks/v2/format/OAR006/with-default-and-specific.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
],
1010
"paths": {
1111
"/pets": {
12-
"get": {
12+
"post": {
1313
"consumes": [
1414
"application/xml"
1515
],

src/test/resources/checks/v2/format/OAR006/with-default-and-specific.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ consumes:
66
- application/json
77
paths:
88
/pets:
9-
get:
9+
post:
1010
consumes:
1111
- application/xml
1212
responses:

src/test/resources/checks/v2/format/OAR006/with-default.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
],
1010
"paths": {
1111
"/pets": {
12-
"get": {
12+
"post": {
1313
"responses": {
1414
"200": {
1515
"description": "Ok"

src/test/resources/checks/v2/format/OAR006/with-default.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ consumes:
66
- application/json
77
paths:
88
/pets:
9-
get:
9+
post:
1010
responses:
1111
200:
1212
description: Ok

src/test/resources/checks/v2/format/OAR006/with-specific.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
},
77
"paths": {
88
"/pets": {
9-
"get": {
9+
"post": {
1010
"consumes": [
1111
"application/json"
1212
],

src/test/resources/checks/v2/format/OAR006/with-specific.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ info:
55

66
paths:
77
/pets:
8-
get:
8+
post:
99
consumes:
1010
- application/json
1111
responses:

src/test/resources/checks/v2/format/OAR006/without-anything.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
},
77
"paths": {
88
"/pets": {
9-
"get": { # Noncompliant {{OAR006: Section consumes is mandatory}}
9+
"post": { # Noncompliant {{OAR006: Section consumes is mandatory}}
1010
"responses": {
1111
"200": {
1212
"description": "Ok"

0 commit comments

Comments
 (0)