001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache License, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the License for the specific language governing permissions and 015 * limitations under the License. 016 */ 017package org.apache.juneau.marshall.json; 018 019import java.io.*; 020 021import org.apache.juneau.commons.bean.*; 022import org.apache.juneau.marshall.*; 023import org.apache.juneau.marshall.jsonschema.*; 024import org.apache.juneau.marshall.serializer.*; 025import org.apache.juneau.marshall.stream.*; 026 027/** 028 * Session object that lives for the duration of a single use of {@link JsonSchemaSerializer}. 029 * 030 * <h5 class='section'>Notes:</h5><ul> 031 * <li class='warn'>This class is not thread safe and is typically discarded after one use. 032 * </ul> 033 * 034 * <h5 class='section'>See Also:</h5><ul> 035 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/JsonSupport">JSON</a> 036 * </ul> 037 */ 038@SuppressWarnings({ 039 "java:S110", // Inheritance depth acceptable for JsonSchemaSerializerSession hierarchy 040 "resource" // Closeable resources are owned by the caller's serializer session; Eclipse JDT @Owning warning is by design. 041}) 042public class JsonSchemaSerializerSession extends JsonSerializerSession { 043 044 /** 045 * Builder class. 046 */ 047 public static class Builder extends JsonSerializerSession.Builder<Builder> { 048 049 private final JsonSchemaSerializer ctx; 050 051 /** 052 * Constructor 053 * 054 * @param ctx The context creating this session. 055 */ 056 protected Builder(JsonSchemaSerializer ctx) { 057 super(ctx); 058 this.ctx = ctx; 059 } 060 061 @Override 062 public JsonSchemaSerializerSession build() { 063 return new JsonSchemaSerializerSession(this); 064 } 065 066 } 067 068 /** 069 * Creates a new builder for this object. 070 * 071 * @param ctx The context creating this session. 072 * @return A new builder. 073 */ 074 public static Builder create(JsonSchemaSerializer ctx) { 075 return new Builder(ctx); 076 } 077 078 private final JsonSchemaGeneratorSession genSession; 079 private final JsonSchemaSerializer ctx; 080 081 /** 082 * Constructor. 083 * 084 * @param builder The builder for this object. 085 */ 086 protected JsonSchemaSerializerSession(Builder builder) { 087 super(builder); 088 ctx = builder.ctx; 089 genSession = ctx.getGenerator().getSession(); 090 } 091 092 @Override /* Overridden from SerializerSession */ 093 protected void doWrite(SerializerPipe out, Object o) throws IOException, SerializeException { 094 try { 095 super.doWrite(out, genSession.getSchema(o)); 096 } catch (MarshallingRecursionException e) { 097 throw new SerializeException(e); 098 } 099 } 100 101 /** 102 * Opens a low-level push generator that emits raw JSON (NOT schema) one structural event at a 103 * time, with the {@link TokenWriter#object(Object)} POJO bridge disabled (the walker would 104 * emit the bean's own JSON, not its JSON Schema). Use {@link #writeRecords(Object)} or 105 * {@link #write(Object, Object)} for schema generation. 106 * 107 * @param output The output. 108 * @return A new {@link JsonTokenWriter} with {@code object(...)} disabled. 109 * @throws IOException If the output type is not supported or could not be opened. 110 */ 111 @Override /* TokenWritable */ 112 public TokenWriter writeTokens(Object output) throws IOException { 113 var walk = new PojoWalker.Options( 114 isKeepNullProperties(), 115 isTrimEmptyMaps(), 116 isTrimEmptyCollections(), 117 isSortMaps(), 118 isSortCollections(), 119 isTrimStrings(), 120 getMarshallingContext()); 121 var settings = new JsonTokenWriter.Settings( 122 isUseWhitespace(), 123 getMaxIndent(), 124 getQuoteChar(), 125 isEscapeSolidus(), 126 isTrimStrings(), 127 false /* simpleAttrs */, 128 walk, 129 true /* disableObject — schema-generation can't be expressed via the POJO walker */); 130 return JsonTokenWriter.forOutput(output, settings); 131 } 132 133 /** 134 * Returns a record writer that emits the JSON Schema for each value passed to 135 * {@link RecordWriter#write(Object) write(...)} (delegates to this session's 136 * {@link #write(Object, Object)}). 137 * 138 * @param output The output. 139 * @return A new {@link RecordWriter}. 140 * @throws IOException If the output type is not supported or could not be opened. 141 */ 142 @Override /* RecordWritable */ 143 public RecordWriter writeRecords(Object output) throws IOException { 144 return RecordAdapter.writer(this, output); 145 } 146 147 @Override /* RecordWritable */ 148 public boolean isRecordStreaming() { return false; } 149 150 /** 151 * Returns the language-specific metadata on the specified bean property. 152 * 153 * @param bpm The bean property to return the metadata on. 154 * @return The metadata. 155 */ 156 protected JsonSchemaBeanPropertyMeta getJsonSchemaBeanPropertyMeta(BeanPropertyMeta bpm) { 157 return ctx.getJsonSchemaBeanPropertyMeta(bpm); 158 } 159 160 /** 161 * Returns the language-specific metadata on the specified class. 162 * 163 * @param cm The class to return the metadata on. 164 * @return The metadata. 165 */ 166 protected JsonSchemaClassMeta getJsonSchemaClassMeta(ClassMeta<?> cm) { 167 return ctx.getJsonSchemaClassMeta(cm); 168 } 169}