All Downloads are FREE. Search and download functionalities are using the official Maven repository.

dev.fitko.fitconnect.core.schema.SchemaResourceProvider Maven / Gradle / Ivy

Go to download

Library that provides client access to the FIT-Connect api-endpoints for sending, subscribing and routing

There is a newer version: 2.3.5
Show newest version
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);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy