dev.fitko.fitconnect.core.schema.SchemaResourceProvider Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of client Show documentation
Show all versions of client Show documentation
Library that provides client access to the FIT-Connect api-endpoints for sending, subscribing and
routing
package dev.fitko.fitconnect.core.schema;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import dev.fitko.fitconnect.api.config.defaults.SchemaConfig;
import dev.fitko.fitconnect.api.domain.schema.SchemaResources;
import dev.fitko.fitconnect.api.exceptions.client.FitConnectInitialisationException;
import dev.fitko.fitconnect.api.exceptions.internal.SchemaNotFoundException;
import dev.fitko.fitconnect.api.services.http.HttpClient;
import dev.fitko.fitconnect.api.services.schema.SchemaProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.io.InputStream;
import java.net.URI;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.regex.Pattern;
public class SchemaResourceProvider implements SchemaProvider {
private static final Logger LOGGER = LoggerFactory.getLogger(SchemaResourceProvider.class);
private static final Pattern ALLOWED_SCHEMA_PATTERN = Pattern.compile("1.\\d+.\\d+");
private static final ObjectMapper MAPPER = new ObjectMapper();
private final Map setSchemas = new HashMap<>();
private final Map metadataSchemas = new HashMap<>();
private final Map destinationSchemas = new HashMap<>();
private final Map submissionDataSchemas = new HashMap<>();
private final HttpClient httpClient;
public SchemaResourceProvider(final HttpClient httpClient, final SchemaResources schemaResources) {
this.httpClient = httpClient;
schemaResources.getSetSchemas().forEach(this::addSetSchema);
schemaResources.getMetadataSchemas().forEach(this::addMetadataSchema);
schemaResources.getDestinationSchemas().forEach(this::addDestinationSchema);
addCustomDataSchemas(schemaResources.getSubmissionDataSchemas());
addDefaultDataSchemas();
LOGGER.info("Initialised SDK schemas");
}
@Override
public boolean isAllowedSetSchema(final URI schemaUri) {
return schemaVersionMatchesPattern(schemaUri, ALLOWED_SCHEMA_PATTERN);
}
@Override
public boolean isAllowedMetadataSchema(final URI schemaUri) {
return metadataSchemas.containsKey(schemaUri);
}
@Override
public String loadSetSchema(URI schemaUri) throws SchemaNotFoundException {
final String schema = setSchemas.get(schemaUri);
if (schema == null) {
throw new SchemaNotFoundException("SET schema " + schemaUri.toString() + " is not available.");
}
return schema;
}
@Override
public String loadMetadataSchema(final URI schemaUri) throws SchemaNotFoundException {
final String schema = metadataSchemas.get(schemaUri);
if (schema == null) {
throw new SchemaNotFoundException("Metadata schema " + schemaUri.toString() + " is not available.");
}
return schema;
}
@Override
public String loadDestinationSchema(final URI schemaUri) throws SchemaNotFoundException {
final String schema = destinationSchemas.get(schemaUri);
if (schema == null) {
throw new SchemaNotFoundException("Destination schema " + schemaUri.toString() + " is not available.");
}
return schema;
}
@Override
public String loadSubmissionDataSchema(final URI schemaUri) throws SchemaNotFoundException {
final String schema = submissionDataSchemas.get(schemaUri);
if (schema != null) {
return schema;
}
LOGGER.debug("Schema " + schemaUri + " is not available as local file, loading remote version.");
if (!schemaUri.getScheme().equals("https")) {
throw new SchemaNotFoundException("Fetching schema " + schemaUri + " from remote was skipped, since the URI does not support HTTPS.");
}
try {
return httpClient.get(schemaUri.toString(), Map.of(), String.class).getBody();
} catch (final Exception exception) {
throw new SchemaNotFoundException("Submission data schema " + schemaUri + " is not available.", exception);
}
}
private void addSetSchema(final String schema) {
readIdFromSchema(schema).ifPresentOrElse(id -> setSchemas.put(id, schema), () -> LOGGER.warn("File '" + schema + "' does not provide a valid set schema and will be ignored."));
}
private void addMetadataSchema(final String schema) {
readIdFromSchema(schema).ifPresentOrElse(id -> metadataSchemas.put(id, schema), () -> LOGGER.warn("File '" + schema + "' does not provide a valid metadata schema and will be ignored."));
}
private void addDestinationSchema(final String schema) {
readIdFromSchema(schema).ifPresentOrElse(id -> destinationSchemas.put(id, schema), () -> LOGGER.warn("File '" + schema + "' does not provide a valid destination schema and will be ignored."));
}
private void addDefaultDataSchemas() {
submissionDataSchemas.put(SchemaConfig.ZBP_ADAPTER_SCHEMA.getSchemaUri(), readPathToString(SchemaConfig.ZBP_ADAPTER_SCHEMA.getFileName()));
}
private void addCustomDataSchemas(Map dataSchemas) {
dataSchemas.forEach((schemaKey, schemaPath) -> submissionDataSchemas.putIfAbsent(getUriFromKey(schemaKey), readPathToString(schemaPath)));
}
private Optional readIdFromSchema(final String schema) {
try {
return Optional.of(URI.create(MAPPER.readTree(schema).get("$id").asText()));
} catch (final JsonProcessingException | IllegalArgumentException | NullPointerException e) {
return Optional.empty();
}
}
private static String readPathToString(final String schemaPath) {
try {
return Files.readString(Path.of(schemaPath));
} catch (final IOException | NullPointerException e) {
try {
return readResourceToString(schemaPath);
} catch (Exception ex) {
throw new FitConnectInitialisationException("Reading data schema " + schemaPath + " failed", ex);
}
}
}
private boolean schemaVersionMatchesPattern(final URI schemaUri, final Pattern pattern) {
final String schemaVersion = schemaUri.getPath().split("/")[3];
return pattern.matcher(schemaVersion).matches();
}
private static URI getUriFromKey(final String schemaKey) {
try {
return URI.create(schemaKey);
} catch (final Exception e) {
LOGGER.error("Could not map data schema {} to a valid URI", schemaKey);
throw new FitConnectInitialisationException(e.getMessage(), e);
}
}
public static String readResourceToString(final String resourcePath) throws IOException {
try (final InputStream in = SchemaResourceProvider.class.getResourceAsStream(resourcePath)) {
return new String(Objects.requireNonNull(in).readAllBytes(), StandardCharsets.UTF_8);
}
}
}