001/* 002 * SPDX-FileCopyrightText: none 003 * SPDX-License-Identifier: CC0-1.0 004 */ 005 006package dev.metaschema.schemagen.json; 007 008import com.fasterxml.jackson.core.JsonFactory; 009import com.fasterxml.jackson.core.JsonGenerator; 010import com.fasterxml.jackson.core.JsonGenerator.Feature; 011import com.fasterxml.jackson.databind.ObjectMapper; 012import com.fasterxml.jackson.databind.node.ObjectNode; 013 014import java.io.IOException; 015import java.io.Writer; 016 017import dev.metaschema.core.configuration.IConfiguration; 018import dev.metaschema.core.model.IModule; 019import dev.metaschema.core.util.ObjectUtils; 020import dev.metaschema.schemagen.AbstractSchemaGenerator; 021import dev.metaschema.schemagen.SchemaGenerationException; 022import dev.metaschema.schemagen.SchemaGenerationFeature; 023import dev.metaschema.schemagen.json.impl.IJsonSchema; 024import dev.metaschema.schemagen.json.impl.JsonDatatypeManager; 025import dev.metaschema.schemagen.json.impl.JsonGenerationState; 026import dev.metaschema.schemagen.json.impl.JsonSchemaModule; 027import edu.umd.cs.findbugs.annotations.NonNull; 028 029/** 030 * Generates JSON Schema documents from Metaschema modules. 031 * <p> 032 * This generator produces JSON Schema draft-07 compatible schemas that can be 033 * used to validate JSON and YAML content conforming to the Metaschema model. 034 */ 035public class JsonSchemaGenerator 036 extends AbstractSchemaGenerator<JsonGenerator, JsonDatatypeManager, JsonGenerationState> { 037 @NonNull 038 private final JsonFactory jsonFactory; 039 040 /** 041 * Constructs a new JSON schema generator using a default JSON factory. 042 */ 043 public JsonSchemaGenerator() { 044 this(new JsonFactory()); 045 } 046 047 /** 048 * Constructs a new JSON schema generator using the specified JSON factory. 049 * 050 * @param jsonFactory 051 * the Jackson JSON factory to use for creating JSON generators 052 */ 053 public JsonSchemaGenerator(@NonNull JsonFactory jsonFactory) { 054 this.jsonFactory = jsonFactory; 055 } 056 057 /** 058 * Retrieves the JSON factory used by this generator. 059 * 060 * @return the JSON factory instance 061 */ 062 @NonNull 063 public JsonFactory getJsonFactory() { 064 return jsonFactory; 065 } 066 067 @SuppressWarnings("resource") 068 @Override 069 protected JsonGenerator newWriter(Writer out) { 070 try { 071 return ObjectUtils.notNull(getJsonFactory().createGenerator(out) 072 .setCodec(new ObjectMapper()) 073 .useDefaultPrettyPrinter() 074 .disable(Feature.AUTO_CLOSE_TARGET)); 075 } catch (IOException ex) { 076 throw new SchemaGenerationException(ex); 077 } 078 } 079 080 @Override 081 protected JsonGenerationState newGenerationState( 082 IModule module, 083 JsonGenerator schemaWriter, 084 IConfiguration<SchemaGenerationFeature<?>> configuration) { 085 return new JsonGenerationState(module, schemaWriter, configuration); 086 } 087 088 @Override 089 protected void generateSchema(JsonGenerationState state) { 090 IModule module = state.getModule(); 091 092 IJsonSchema moduleSchema = new JsonSchemaModule(module, state); 093 ObjectNode schemaNode = ObjectUtils.notNull(state.getJsonNodeFactory().objectNode()); 094 moduleSchema.generateInlineJsonSchema(schemaNode, state); 095 096 try { 097 state.writeObject(schemaNode); 098 } catch (IOException ex) { 099 throw new SchemaGenerationException(ex); 100 } 101 } 102}