org.iris_events.asyncapi.runtime.client.ClientDefinitionParser Maven / Gradle / Ivy
package org.iris_events.asyncapi.runtime.client;
import java.util.EnumSet;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.Spliterator;
import java.util.Spliterators;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import org.iris_events.annotations.Scope;
import org.iris_events.asyncapi.api.AsyncApiConstants;
import org.iris_events.asyncapi.runtime.io.channel.operation.OperationConstant;
import org.iris_events.asyncapi.runtime.scanner.model.ClientDefinitions;
import com.fasterxml.jackson.databind.JsonNode;
public class ClientDefinitionParser {
public ClientDefinitions parse(JsonNode asyncapiRootNode) {
EnumSet scopes = EnumSet.of(Scope.FRONTEND, Scope.USER, Scope.SESSION, Scope.BROADCAST);
Map feScopeChannels = getChannelsInScope(asyncapiRootNode.get(AsyncApiConstants.CHANNELS_NODE),
scopes);
Map schemasNodes = getTopLevelSchemaNodes(asyncapiRootNode.get(AsyncApiConstants.COMPONENTS_NODE).get(
AsyncApiConstants.SCHEMAS_NODE),
feScopeChannels);
schemasNodes.putAll(getSchemaNodes(getReferencedSchemaNodes(schemasNodes, asyncapiRootNode), asyncapiRootNode));
return new ClientDefinitions(asyncapiRootNode.findValue(AsyncApiConstants.INFO_NODE).findValue(
AsyncApiConstants.TITLE_NODE).asText(), feScopeChannels,
schemasNodes);
}
private Map getSchemaNodes(Set referencedSchemaNodes, JsonNode rootNode) {
JsonNode schemas = rootNode.findPath(AsyncApiConstants.COMPONENTS_NODE).findPath(AsyncApiConstants.SCHEMAS_NODE);
return referencedSchemaNodes.stream().collect(Collectors.toMap(s -> s, schemas::findPath));
}
private Set getReferencedSchemaNodes(Map rootSchemaNodes, JsonNode rootNode) {
Set refsOfInterest = rootSchemaNodes.values().stream()
.filter(schemaNode -> schemaNode != null && !schemaNode.findPath(AsyncApiConstants.PROPERTIES_NODE).isEmpty()
&& !schemaNode.findPath(AsyncApiConstants.PROPERTIES_NODE).findValues(AsyncApiConstants.REF_NODE)
.isEmpty())
.map(nodeOfInterest -> nodeOfInterest.findValues(AsyncApiConstants.REF_NODE))
.flatMap(List::stream)
.map(jsonNode -> jsonNode.asText().replace(AsyncApiConstants.COMPONENT_SCHEMAS_PREFIX, ""))
.collect(Collectors.toSet());
JsonNode componentSchemas = rootNode.findPath(AsyncApiConstants.COMPONENTS_NODE)
.findPath(AsyncApiConstants.SCHEMAS_NODE);
Map newRootSchemaNodes = refsOfInterest.stream()
.map(ref -> ref.replace(AsyncApiConstants.COMPONENT_SCHEMAS_PREFIX, ""))
.collect(Collectors.toMap(s -> s, componentSchemas::findPath));
if (newRootSchemaNodes.isEmpty()) {
return new HashSet<>();
}
refsOfInterest.addAll(getReferencedSchemaNodes(newRootSchemaNodes, rootNode));
return refsOfInterest;
}
private Map getTopLevelSchemaNodes(JsonNode schemasNode, Map feScopeChannels) {
return feScopeChannels.values().stream()
.map(scopeChannelNode -> extractRefValue(scopeChannelNode).replace(AsyncApiConstants.COMPONENT_SCHEMAS_PREFIX,
""))
.collect(Collectors.toMap(s -> s, schemasNode::get, (s1, s2) -> s1));
}
private String extractRefValue(JsonNode scopeChannelNode) {
JsonNode operationNode = Optional.ofNullable(scopeChannelNode.get(OperationConstant.PROP_PUBLISH))
.orElse(scopeChannelNode.get(OperationConstant.PROP_SUBSCRIBE));
return operationNode.get(OperationConstant.PROP_MESSAGE).get(AsyncApiConstants.PAYLOAD_NODE).get(
AsyncApiConstants.REF_NODE).asText();
}
private Stream> fieldsToStream(Iterator> fields) {
return StreamSupport.stream(Spliterators.spliteratorUnknownSize(fields, Spliterator.ORDERED), false);
}
private Map getChannelsInScope(JsonNode channelsNode, EnumSet scopes) {
return fieldsToStream(channelsNode.fields()).filter(channelNode -> {
JsonNode operationNode = Optional.ofNullable(channelNode.getValue().get(OperationConstant.PROP_PUBLISH))
.orElse(channelNode.getValue().get(OperationConstant.PROP_SUBSCRIBE));
String scopeValue = operationNode.get(OperationConstant.PROP_MESSAGE).get(AsyncApiConstants.HEADERS_NODE).get(
AsyncApiConstants.PROPERTIES_NODE)
.get(AsyncApiConstants.X_SCOPE_NODE).get(AsyncApiConstants.VALUE_NODE)
.asText();
return scopes.contains(Scope.valueOf(scopeValue.toUpperCase()));
}).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
}
}