Skip to content
Open
Original file line number Diff line number Diff line change
Expand Up @@ -79,11 +79,12 @@ public static AsyncApiDocument parseFromText(String schemaText) {
on AsyncApiDocument.getWarnings(), and where those warnings go is the caller's decision.
*/
private static AsyncApiDocument parse(String schemaText, DocumentLocation location) {
return AsyncApiParser.parse(schemaText, location);
return AsyncApiParser.parse(schemaText, location, AsyncApiAccess::fetch);
}

/**
* Read the text of a document, wherever it lives.
* Read the text of a document, wherever it lives. Also used to follow references to other
* documents, which is why it takes the kind of location explicitly.
*/
private static String fetch(String location, DocumentLocationType type) {

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.webfuzzing.asyncapi.models;

import java.util.Locale;
import java.util.Objects;

/**
Expand All @@ -17,6 +18,11 @@ public class DocumentLocation {
*/
public static final DocumentLocation MEMORY = new DocumentLocation("", DocumentLocationType.MEMORY);

/**
* How a file on disk looks when written as a URL rather than as a path.
*/
private static final String FILE_URL_PREFIX = "file:";

private final String location;

private final DocumentLocationType type;
Expand Down Expand Up @@ -46,6 +52,17 @@ public DocumentLocationType getType() {
return type;
}

/**
* Whether this is a path on the file system written as a path, rather than as a
* {@code file:} URL. Both are read from disk, but only the former is not a URI, so a
* relative reference is resolved against it through the file system rather than per
* RFC 3986.
*/
public boolean isPlainFilePath() {
return type == DocumentLocationType.LOCAL
&& !location.toLowerCase(Locale.ENGLISH).startsWith(FILE_URL_PREFIX);
}

@Override
public boolean equals(Object other) {
if (this == other) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import com.webfuzzing.asyncapi.models.AsyncApiOperation;
import com.webfuzzing.asyncapi.models.AsyncApiReply;
import com.webfuzzing.asyncapi.models.DocumentLocation;
import com.webfuzzing.asyncapi.resolver.AsyncApiDocumentFetcher;
import com.webfuzzing.asyncapi.resolver.AsyncApiRefResolver;

import java.util.ArrayDeque;
Expand Down Expand Up @@ -75,9 +76,12 @@ private AsyncApiParser() {
}

/**
* Parse {@code schemaText}, which was retrieved from {@code location}.
* Parse {@code schemaText}, reaching for any document it refers to with {@code fetch}.
*/
public static AsyncApiDocument parse(String schemaText, DocumentLocation location) {
public static AsyncApiDocument parse(
String schemaText,
DocumentLocation location,
AsyncApiDocumentFetcher fetch) {

JsonNode root;
try {
Expand Down Expand Up @@ -107,6 +111,9 @@ public static AsyncApiDocument parse(String schemaText, DocumentLocation locatio

List<String> warnings = new ArrayList<>();

AsyncApiRefResolver.inlineExternalDocuments(
(ObjectNode) root, location, warnings, fetch, AsyncApiMapper::readTree);

String defaultContentType = scalarOf(root.get("defaultContentType"));
if (defaultContentType == null) {
defaultContentType = AsyncApiDocument.DEFAULT_CONTENT_TYPE;
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.webfuzzing.asyncapi.resolver;

import com.webfuzzing.asyncapi.models.DocumentLocationType;

/**
* How the parser gets hold of a document it does not already have: given an absolute location
* and how to read it, hand back the text.
*
* Kept as an interface so that the resolver does not depend on the retrieval code, and so tests
* can supply documents without any I/O.
*/
@FunctionalInterface
public interface AsyncApiDocumentFetcher {

/**
* @param location an absolute location, already resolved against the referring document
* @param type how that location is to be read
* @return the text of the document
* @throws RuntimeException if the document cannot be retrieved. The caller turns that into
* a warning rather than letting it escape, as one unreachable
* document costs only what refers to it.
*/
String fetch(String location, DocumentLocationType type);
}
Loading
Loading