Skip to content

Commit d5c1b23

Browse files
committed
fix: support multiple nested allOf (multiple-allOf.yml)
closes #7
1 parent 26db505 commit d5c1b23

File tree

3 files changed

+116
-31
lines changed

3 files changed

+116
-31
lines changed

src/main/java/io/zenwave360/jsonrefparser/$RefParser.java

+50-31
Original file line numberDiff line numberDiff line change
@@ -20,11 +20,9 @@
2020
import java.util.ArrayList;
2121
import java.util.Arrays;
2222
import java.util.HashMap;
23-
import java.util.HashSet;
2423
import java.util.LinkedHashMap;
2524
import java.util.List;
2625
import java.util.Map;
27-
import java.util.Set;
2826
import java.util.stream.Collectors;
2927

3028
public class $RefParser {
@@ -148,45 +146,28 @@ private void mergeAllOf(Object value, String[] paths, URI currentFileURL) {
148146
// visited.add(value);
149147
if(paths.length > 0 && "allOf".equals(paths[paths.length -1])) {
150148
List allOf = (List) value;
151-
List<String> required = new ArrayList<>();
152-
Map<String, Object> properties = new LinkedHashMap<>();
153-
Map<String, Object> mergedAllOfObject = new LinkedHashMap<>();
149+
// List<String> required = new ArrayList<>();
150+
// Map<String, Object> properties = new LinkedHashMap<>();
151+
// Map<String, Object> mergedAllOfObject = new LinkedHashMap<>();
152+
AllOfObject allOfObject = new AllOfObject();
154153
for (int i = 0; i < allOf.size(); i++) {
155154
if(allOf.get(i) instanceof Map) {
156155
Map<String, Object> item = (Map<String, Object>) allOf.get(i);
157-
if(item.keySet().size() == 1 && item.containsKey("allOf")) {
158-
List<Map<String, Object>> items = (List) item.get("allOf");
159-
for (Map<String, Object> innerItem : items) {
160-
mergedAllOfObject.putAll(innerItem);
161-
if(innerItem.containsKey("properties")) {
162-
properties.putAll((Map) innerItem.get("properties"));
163-
}
164-
if(innerItem.containsKey("required")) {
165-
required.addAll((List) innerItem.get("required"));
166-
}
167-
}
168-
} else {
169-
mergedAllOfObject.putAll(item);
170-
if(item.containsKey("properties")) {
171-
properties.putAll((Map) item.get("properties"));
172-
}
173-
if(item.containsKey("required")) {
174-
required.addAll((List) item.get("required"));
175-
}
176-
}
156+
merge(allOfObject, item);
177157
} else {
178158
throw new RuntimeException("Could not understand allOf: " + allOf.get(i));
179159
}
180160
}
181-
if(!required.isEmpty()) {
182-
mergedAllOfObject.put("required", required);
183-
}
184-
if(!properties.isEmpty()) {
185-
mergedAllOfObject.put("properties", properties);
186-
}
161+
// if(!required.isEmpty()) {
162+
// mergedAllOfObject.put("required", required);
163+
// }
164+
// if(!properties.isEmpty()) {
165+
// mergedAllOfObject.put("properties", properties);
166+
// }
187167
String[] jsonPaths = Arrays.copyOf(paths, paths.length -1);
188168
String jsonPath = jsonPath(jsonPaths);
189169
try {
170+
var mergedAllOfObject = allOfObject.buildAllOfObject();
190171
refs.jsonContext.set(jsonPath, mergedAllOfObject);
191172
refs.saveOriginalAllOf(mergedAllOfObject, allOf);
192173
} catch (Exception e){
@@ -207,6 +188,44 @@ private void mergeAllOf(Object value, String[] paths, URI currentFileURL) {
207188
}
208189
}
209190

191+
private void merge(AllOfObject allOfObject, List<Map<String, Object>> items) {
192+
for (Map<String, Object> innerItem : items) {
193+
merge(allOfObject, innerItem);
194+
}
195+
}
196+
197+
private void merge(AllOfObject allOfObject, Map<String, Object> item) {
198+
if(item.keySet().size() == 1 && item.containsKey("allOf")) {
199+
List<Map<String, Object>> items = (List) item.get("allOf");
200+
merge(allOfObject, items);
201+
} else {
202+
allOfObject.allOf.putAll(item);
203+
if(item.containsKey("properties")) {
204+
allOfObject.properties.putAll((Map) item.get("properties"));
205+
}
206+
if(item.containsKey("required")) {
207+
allOfObject.required.addAll((List) item.get("required"));
208+
}
209+
}
210+
}
211+
212+
private static class AllOfObject {
213+
Map<String, Object> allOf = new HashMap<>();
214+
Map<String, Object> properties = new HashMap<>();
215+
List<String> required = new ArrayList<>();
216+
217+
Map<String, Object> buildAllOfObject() {
218+
Map<String, Object> allOfObject = new LinkedHashMap<>(allOf);
219+
if(!required.isEmpty()) {
220+
allOfObject.put("required", required);
221+
}
222+
if(!properties.isEmpty()) {
223+
allOfObject.put("properties", properties);
224+
}
225+
return allOfObject;
226+
}
227+
}
228+
210229
private List<Object> visited = new ArrayList<>();
211230
private List<String> indent = new ArrayList<>();
212231
private String indent() {

src/test/java/io/zenwave360/jsonrefparser/ParserTest.java

+12
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,18 @@ public void testDereferenceAndMerge_MultipleAllOf() throws IOException {
175175
Assert.assertEquals(4, properties.size());
176176
}
177177

178+
@Test
179+
public void testDereferenceAndMerge_MultipleAllOf2() throws IOException {
180+
File file = new File("src/test/resources/asyncapi/multiple-allOf2.yml");
181+
$RefParser parser = new $RefParser(file).parse();
182+
$Refs refs = parser.dereference().mergeAllOf().getRefs();
183+
184+
assertNoRefs(refs.schema());
185+
var properties = (Map) refs.get("$.components.schemas.Test.properties");
186+
Assert.assertEquals(5, properties.size());
187+
}
188+
189+
178190
@Test
179191
public void testDereference() throws IOException {
180192
File file = new File("src/test/resources/openapi/allOf.yml");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
asyncapi: 3.0.0
2+
info:
3+
title: Test Event-API
4+
version: '1.0'
5+
description: Test
6+
channels:
7+
testTopic:
8+
messages:
9+
test:
10+
name: Test
11+
payload:
12+
$ref: '#/components/schemas/Test'
13+
operations:
14+
publishTest:
15+
action: send
16+
summary: publish events
17+
channel:
18+
$ref: '#/channels/testTopic'
19+
messages:
20+
- $ref: '#/channels/testTopic/messages/test'
21+
components:
22+
schemas:
23+
Test1:
24+
allOf:
25+
- type: object
26+
properties:
27+
test1a:
28+
type: string
29+
- $ref: '#/components/schemas/Test1b'
30+
Test2:
31+
allOf:
32+
- type: object
33+
properties:
34+
test2a:
35+
type: string
36+
- type: object
37+
properties:
38+
test2b:
39+
type: string
40+
Test1b:
41+
allOf:
42+
- type: object
43+
properties:
44+
test1b:
45+
type: string
46+
- type: object
47+
properties:
48+
test1c:
49+
type: string
50+
Test:
51+
type: object
52+
allOf:
53+
- $ref: '#/components/schemas/Test1'
54+
- $ref: '#/components/schemas/Test2'

0 commit comments

Comments
 (0)