Skip to content

Commit d53d6e4

Browse files
committed
bundle 3.1 path items to component
1 parent 7dad4dc commit d53d6e4

2 files changed

Lines changed: 85 additions & 12 deletions

File tree

openapi-parser/src/main/java/io/openapiparser/OpenApiBundler.java

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,9 @@ public class OpenApiBundler {
2424
private final DocumentStore documents;
2525
private final Bucket root;
2626
private final URI rootDocumentUri;
27+
private final Object rootDocument;
28+
private final OpenApiVersion version;
29+
2730

2831
private final Map<String, @Nullable Object> schemas = new LinkedHashMap<> ();
2932
private final Map<String, @Nullable Object> responses = new LinkedHashMap<> ();
@@ -34,20 +37,20 @@ public class OpenApiBundler {
3437
private final Map<String, @Nullable Object> securitySchemes = new LinkedHashMap<> ();
3538
private final Map<String, @Nullable Object> links = new LinkedHashMap<> ();
3639
private final Map<String, @Nullable Object> callbacks = new LinkedHashMap<> ();
37-
private final Map<String, @Nullable Object> paths = new LinkedHashMap<> ();
40+
private final Map<String, @Nullable Object> pathItems = new LinkedHashMap<> ();
3841

3942
public OpenApiBundler (Context context, DocumentStore documents, Bucket root) {
4043
this.context = context;
4144
this.documents = documents.copy ();
4245
this.root = root;
4346
this.rootDocumentUri = root.getScope ().getDocumentUri ();
47+
this.rootDocument = documents.get (rootDocumentUri);
48+
this.version = OpenApiVersionParser.parseVersion(rootDocument);
4449
}
4550

46-
public Map<String, @Nullable Object> bundle () {
47-
URI documentUri = root.getScope ().getDocumentUri ();
48-
Object document = documents.get (documentUri);
4951

50-
Bucket bundled = createBucket(root.getScope(), document, root.getLocation());
52+
public Map<String, @Nullable Object> bundle () {
53+
Bucket bundled = createBucket(root.getScope(), rootDocument, root.getLocation());
5154
walkBucket (bundled);
5255

5356
Map<String, @Nullable Object> rawValues = bundled.getRawValues ();
@@ -80,7 +83,7 @@ private void mergeMaps (Map<String, @Nullable Object> components) {
8083
mergeMap (components, "securitySchemes", securitySchemes);
8184
mergeMap (components, "links", links);
8285
mergeMap (components, "callbacks", callbacks);
83-
mergeMap (components, "paths", paths);
86+
mergeMap (components, "pathItems", pathItems);
8487
}
8588

8689
private void mergeMap (
@@ -160,6 +163,9 @@ private boolean isExternalDocument (URI documentUri) {
160163

161164
JsonPointer refPointer = reference.getPointer ();
162165
String refName = refPointer.tail ();
166+
if (refName.isEmpty()) {
167+
refName = documentUri.getPath();
168+
}
163169
RawValue refValue = getRefValue (documentBucket, refPointer);
164170
Bucket refBucket = getRefBucket (refPointer, refValue);
165171

@@ -192,7 +198,11 @@ private boolean isExternalDocument (URI documentUri) {
192198
bundleCallback (bucketValues, refName, refValue);
193199

194200
} else if (isPathRef (location) && external) {
195-
result = bundlePath30 (bucketValues, refValue);
201+
if(version == OpenApiVersion.V30) {
202+
result = bundlePathItem30(bucketValues, refValue);
203+
} else {
204+
bundlePathItem(bucketValues, refName, refValue);
205+
}
196206
}
197207

198208
// walk unseen ref
@@ -259,7 +269,12 @@ private void bundleCallback (Map<String, @Nullable Object> rawValues, String ref
259269
rawValues.put (Keywords.REF, createRefPointer ("callbacks", refName));
260270
}
261271

262-
private Runnable bundlePath30 (Map<String, @Nullable Object> rawValues, RawValue refValue) {
272+
private void bundlePathItem (Map<String, @Nullable Object> rawValues, String refName, RawValue refValue) {
273+
pathItems.put (refName, refValue.getValue ());
274+
rawValues.put (Keywords.REF, createRefPointer ("pathItems", refName));
275+
}
276+
277+
private Runnable bundlePathItem30(Map<String, @Nullable Object> rawValues, RawValue refValue) {
263278
// OpenAPI 3.0 has no /components/paths => inline it
264279

265280
Map<String, @Nullable Object> replacement = asObject (refValue.getValue ());
@@ -312,7 +327,7 @@ private Bucket createBucket(Scope scope, @Nullable Object source, JsonPointer lo
312327
}
313328

314329
private String createRefPointer (String type, String refName) {
315-
return String.format ("#/components/%s/%s", type, refName);
330+
return String.format ("#/components/%s/%s", type, JsonPointerSupport.encode(refName));
316331
}
317332

318333
private void walkSchema (Scope currentScope, Object value, JsonPointer location) {

openapi-parser/src/test/kotlin/io/openapiparser/OpenApiBundlerSpec.kt

Lines changed: 61 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ import io.openapiprocessor.jsonschema.reader.UriReader
1616
import io.openapiprocessor.jsonschema.schema.JsonPointer.from
1717
import io.openapiprocessor.snakeyaml.SnakeYamlConverter
1818
import io.openapiprocessor.jsonschema.schema.*
19+
import io.openapiprocessor.snakeyaml.SnakeYamlWriter
20+
import java.io.StringWriter
1921

2022
class OpenApiBundlerSpec : FreeSpec({
2123

@@ -216,26 +218,52 @@ class OpenApiBundlerSpec : FreeSpec({
216218
withData(
217219
mapOf(
218220
$$"bundle path $ref, 30" to Data("/bundle-ref-path-item/openapi30.yaml", ::bundle30),
219-
$$"bundle path $ref, 31" to Data("/bundle-ref-path-item/openapi31.yaml", ::bundle31)
220221
)
221222
) { (api, bundle) ->
222223
val result = resolve(api)
223224
val bundled = bundle(result)
224225

226+
val out = StringWriter()
227+
val writer = SnakeYamlWriter(out)
228+
writer.write(bundled.rawValues)
229+
225230
val pathItem = getObject(bundled, "/paths/~1foo")
226231
pathItem.containsKey(Keywords.REF).shouldBeFalse()
227232
pathItem.containsKey("get").shouldBeTrue()
228233
}
229234

230235
withData(
231236
mapOf(
232-
$$"bundle nested $ref, 30" to Data("/bundle-ref-nested/openapi30.yaml", ::bundle30),
233-
$$"bundle nested $ref, 31" to Data("/bundle-ref-nested/openapi31.yaml", ::bundle31)
237+
$$"bundle path $ref, 31" to Data("/bundle-ref-path-item/openapi31.yaml", ::bundle31)
234238
)
235239
) { (api, bundle) ->
236240
val result = resolve(api)
237241
val bundled = bundle(result)
238242

243+
val out = StringWriter()
244+
val writer = SnakeYamlWriter(out)
245+
writer.write(bundled.rawValues)
246+
247+
val ref = getObject(bundled, "/paths/~1foo")
248+
ref.size shouldBe 1
249+
ref[$$"$ref"].shouldBe("#/components/pathItems/~1bundle-ref-path-item~1foo.api.yaml")
250+
251+
val component = getObject(bundled, "/components/pathItems/~1bundle-ref-path-item~1foo.api.yaml")
252+
component.shouldNotBeNull()
253+
}
254+
255+
withData(
256+
mapOf(
257+
$$"bundle nested $ref, 30" to Data("/bundle-ref-nested/openapi30.yaml", ::bundle30)
258+
)
259+
) { (api, bundle) ->
260+
val result = resolve(api)
261+
val bundled = bundle(result)
262+
263+
val out = StringWriter()
264+
val writer = SnakeYamlWriter(out)
265+
writer.write(bundled.rawValues)
266+
239267
val pathItem = getObject(bundled, "/paths/~1foo")
240268
pathItem.containsKey(Keywords.REF).shouldBeFalse()
241269
pathItem.containsKey("get").shouldBeTrue()
@@ -251,6 +279,36 @@ class OpenApiBundlerSpec : FreeSpec({
251279
componentNested.shouldNotBeNull()
252280
}
253281

282+
withData(
283+
mapOf(
284+
$$"bundle nested $ref, 31" to Data("/bundle-ref-nested/openapi31.yaml", ::bundle31)
285+
)
286+
) { (api, bundle) ->
287+
val result = resolve(api)
288+
val bundled = bundle(result)
289+
290+
val out = StringWriter()
291+
val writer = SnakeYamlWriter(out)
292+
writer.write(bundled.rawValues)
293+
294+
val ref = getObject(bundled, "/paths/~1foo")
295+
ref.size shouldBe 1
296+
ref[$$"$ref"].shouldBe("#/components/pathItems/~1bundle-ref-nested~1foo.api.yaml")
297+
298+
val component = getObject(bundled, "/components/pathItems/~1bundle-ref-nested~1foo.api.yaml")
299+
component.shouldNotBeNull()
300+
301+
val barRef = getObject(bundled, "/components/pathItems/~1bundle-ref-nested~1foo.api.yaml/get/responses/200/content/application~1json/schema")
302+
barRef[$$"$ref"].shouldBe("#/components/schemas/Bar")
303+
val barComponent = bundled.getRawValue(from("/components/schemas/Bar"))
304+
barComponent.shouldNotBeNull()
305+
306+
val refNested = getObject(bundled, "/components/schemas/Bar/properties/bar")
307+
refNested[$$"$ref"].shouldBe("#/components/schemas/Bar2")
308+
val componentNested = bundled.getRawValue(from("/components/schemas/Bar2"))
309+
componentNested.shouldNotBeNull()
310+
}
311+
254312
withData(
255313
mapOf(
256314
"does not override existing component, 30" to Data("/bundle-ref-components/openapi30.yaml", ::bundle30),

0 commit comments

Comments
 (0)