Skip to content

Commit

Permalink
fix: support multiple nested allOf (multiple-allOf.yml)
Browse files Browse the repository at this point in the history
closes #7
  • Loading branch information
ivangsa committed Jul 3, 2024
1 parent 26db505 commit d5c1b23
Show file tree
Hide file tree
Showing 3 changed files with 116 additions and 31 deletions.
81 changes: 50 additions & 31 deletions src/main/java/io/zenwave360/jsonrefparser/$RefParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,9 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

public class $RefParser {
Expand Down Expand Up @@ -148,45 +146,28 @@ private void mergeAllOf(Object value, String[] paths, URI currentFileURL) {
// visited.add(value);
if(paths.length > 0 && "allOf".equals(paths[paths.length -1])) {
List allOf = (List) value;
List<String> required = new ArrayList<>();
Map<String, Object> properties = new LinkedHashMap<>();
Map<String, Object> mergedAllOfObject = new LinkedHashMap<>();
// List<String> required = new ArrayList<>();
// Map<String, Object> properties = new LinkedHashMap<>();
// Map<String, Object> mergedAllOfObject = new LinkedHashMap<>();
AllOfObject allOfObject = new AllOfObject();
for (int i = 0; i < allOf.size(); i++) {
if(allOf.get(i) instanceof Map) {
Map<String, Object> item = (Map<String, Object>) allOf.get(i);
if(item.keySet().size() == 1 && item.containsKey("allOf")) {
List<Map<String, Object>> items = (List) item.get("allOf");
for (Map<String, Object> innerItem : items) {
mergedAllOfObject.putAll(innerItem);
if(innerItem.containsKey("properties")) {
properties.putAll((Map) innerItem.get("properties"));
}
if(innerItem.containsKey("required")) {
required.addAll((List) innerItem.get("required"));
}
}
} else {
mergedAllOfObject.putAll(item);
if(item.containsKey("properties")) {
properties.putAll((Map) item.get("properties"));
}
if(item.containsKey("required")) {
required.addAll((List) item.get("required"));
}
}
merge(allOfObject, item);
} else {
throw new RuntimeException("Could not understand allOf: " + allOf.get(i));
}
}
if(!required.isEmpty()) {
mergedAllOfObject.put("required", required);
}
if(!properties.isEmpty()) {
mergedAllOfObject.put("properties", properties);
}
// if(!required.isEmpty()) {
// mergedAllOfObject.put("required", required);
// }
// if(!properties.isEmpty()) {
// mergedAllOfObject.put("properties", properties);
// }
String[] jsonPaths = Arrays.copyOf(paths, paths.length -1);
String jsonPath = jsonPath(jsonPaths);
try {
var mergedAllOfObject = allOfObject.buildAllOfObject();
refs.jsonContext.set(jsonPath, mergedAllOfObject);
refs.saveOriginalAllOf(mergedAllOfObject, allOf);
} catch (Exception e){
Expand All @@ -207,6 +188,44 @@ private void mergeAllOf(Object value, String[] paths, URI currentFileURL) {
}
}

private void merge(AllOfObject allOfObject, List<Map<String, Object>> items) {
for (Map<String, Object> innerItem : items) {
merge(allOfObject, innerItem);
}
}

private void merge(AllOfObject allOfObject, Map<String, Object> item) {
if(item.keySet().size() == 1 && item.containsKey("allOf")) {
List<Map<String, Object>> items = (List) item.get("allOf");
merge(allOfObject, items);
} else {
allOfObject.allOf.putAll(item);
if(item.containsKey("properties")) {
allOfObject.properties.putAll((Map) item.get("properties"));
}
if(item.containsKey("required")) {
allOfObject.required.addAll((List) item.get("required"));
}
}
}

private static class AllOfObject {
Map<String, Object> allOf = new HashMap<>();
Map<String, Object> properties = new HashMap<>();
List<String> required = new ArrayList<>();

Map<String, Object> buildAllOfObject() {
Map<String, Object> allOfObject = new LinkedHashMap<>(allOf);
if(!required.isEmpty()) {
allOfObject.put("required", required);
}
if(!properties.isEmpty()) {
allOfObject.put("properties", properties);
}
return allOfObject;
}
}

private List<Object> visited = new ArrayList<>();
private List<String> indent = new ArrayList<>();
private String indent() {
Expand Down
12 changes: 12 additions & 0 deletions src/test/java/io/zenwave360/jsonrefparser/ParserTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -175,6 +175,18 @@ public void testDereferenceAndMerge_MultipleAllOf() throws IOException {
Assert.assertEquals(4, properties.size());
}

@Test
public void testDereferenceAndMerge_MultipleAllOf2() throws IOException {
File file = new File("src/test/resources/asyncapi/multiple-allOf2.yml");
$RefParser parser = new $RefParser(file).parse();
$Refs refs = parser.dereference().mergeAllOf().getRefs();

assertNoRefs(refs.schema());
var properties = (Map) refs.get("$.components.schemas.Test.properties");
Assert.assertEquals(5, properties.size());
}


@Test
public void testDereference() throws IOException {
File file = new File("src/test/resources/openapi/allOf.yml");
Expand Down
54 changes: 54 additions & 0 deletions src/test/resources/asyncapi/multiple-allOf2.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
asyncapi: 3.0.0
info:
title: Test Event-API
version: '1.0'
description: Test
channels:
testTopic:
messages:
test:
name: Test
payload:
$ref: '#/components/schemas/Test'
operations:
publishTest:
action: send
summary: publish events
channel:
$ref: '#/channels/testTopic'
messages:
- $ref: '#/channels/testTopic/messages/test'
components:
schemas:
Test1:
allOf:
- type: object
properties:
test1a:
type: string
- $ref: '#/components/schemas/Test1b'
Test2:
allOf:
- type: object
properties:
test2a:
type: string
- type: object
properties:
test2b:
type: string
Test1b:
allOf:
- type: object
properties:
test1b:
type: string
- type: object
properties:
test1c:
type: string
Test:
type: object
allOf:
- $ref: '#/components/schemas/Test1'
- $ref: '#/components/schemas/Test2'

0 comments on commit d5c1b23

Please sign in to comment.