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

com.nedap.archie.json.JsonSchemaValidator Maven / Gradle / Ivy

Go to download

tools that operate on the archie reference models and archetype object model

The newest version!
package com.nedap.archie.json;

import com.google.common.base.Charsets;
import org.leadpony.justify.api.JsonSchema;
import org.leadpony.justify.api.JsonSchemaReader;
import org.leadpony.justify.api.JsonSchemaReaderFactory;
import org.leadpony.justify.api.JsonValidationService;
import org.leadpony.justify.api.Problem;
import org.leadpony.justify.api.ProblemHandler;
import org.openehr.bmm.core.BmmModel;

import jakarta.json.JsonObject;
import jakarta.json.JsonReader;
import jakarta.json.JsonStructure;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;


/**
 * Validates JSON files against a schema automatically created from a BMM repository.
 *
 * 

* This is a Convenience API, you can easily manually do the same with the JsonSchemaCreator. *

* * Note that currently the root JSON element must have a '_type' property for the schema validator to know which type to validate */ public class JsonSchemaValidator { /** The generated json schema files, in memory */ private final Map schemaFiles; /** a cache of earlier resolved schemas, to not cause too many performance problems */ private final Map resolvedSchemas = new LinkedHashMap<>(); /** the single resolved schema */ JsonSchema schema; private JsonSchemaReaderFactory readerFactory; private JsonValidationService service; /** * Creates a JsonSchemaValidator that validates against the json schema created from the given Bmm Model * The JSON Schema complies to the JSON format that the OpenEHR project uses. This may very well be different from * the serialization rules corresponding to your own different BMM file, if it is not an OpenEHR model. * * @param bmmModel the model to create the JSON Schema for * @param allowAdditionalProperties whether to allow additional properties in the JSON */ public JsonSchemaValidator(BmmModel bmmModel, boolean allowAdditionalProperties) { schemaFiles = new LinkedHashMap<>(); new OpenEHRRmJSONSchemaCreator() .allowAdditionalProperties(allowAdditionalProperties) .withBaseUri("http://something/") //the validator can actually handle a schema split in multiple files, but //Justify's implementation is not perfect, causing some extra memory use that might be better to avoid. .splitInMultipleFiles(false) .withFullReferences(true) .create(bmmModel) .forEach( (uri, schema) -> schemaFiles.put(uri.getId(), schema)); //The first entry in schemaFiles is guaranteed to be the main schema by the JSONSchemaCreator. JsonObject schemaJson = schemaFiles.values().iterator().next(); service = JsonValidationService.newInstance(); //the following is for multi-file validation only, and can be skipped altogether to validate just a single-file //schema readerFactory = service .createSchemaReaderFactoryBuilder() .withSchemaResolver(this::resolveSchema) .build(); try (JsonSchemaReader schemaReader = readerFactory .createSchemaReader(createByteArrayInputStream(schemaJson.toString()))) { schema = schemaReader.read(); } } /** * Resolves the referenced JSON schema. * * @param uri the identifier of the referenced JSON schema. * @return referenced JSON schema. */ private JsonSchema resolveSchema(URI uri) { String filename = uri.toString().split("#")[0]; JsonSchema resolvedSchema = resolvedSchemas.get(filename); if(resolvedSchema != null) { return resolvedSchema; } JsonObject schema = schemaFiles.get(filename); if ( schema == null ) { return null; } try (JsonSchemaReader reader = readerFactory.createSchemaReader(createByteArrayInputStream(schema.toString()))) { resolvedSchema = reader.read(); //this caching approach is not perfect: as part of reader.read(), it will call this same function again to //resolve any referenced schemas, before returning frmo reader.read(). //this can mean the result is not yet cached, and will be generated twice. Not something that can be easily fixed // however if no cache is used at all, there will be OutOfMemoryExceptions or very long runtime. resolvedSchemas.put(filename, resolvedSchema); return resolvedSchema; } } private ByteArrayInputStream createByteArrayInputStream(String json) { return new ByteArrayInputStream(json.getBytes(Charsets.UTF_8)); } /** * Validate the given json against the schema * @param json the json * @return the list of problems found during validation, or an empty list if the json validated * @throws IOException */ public List validate(String json) throws IOException { List allProblems = new ArrayList<>(); ProblemHandler problemHandler = new ProblemHandler() { @Override public void handleProblems(List problems) { allProblems.addAll(problems); } }; try (JsonReader reader = service.createReader(createByteArrayInputStream(json), schema, problemHandler)) { JsonStructure structure = reader.read(); return allProblems; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy