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.html; 018 019import org.apache.juneau.marshall.*; 020import org.apache.juneau.marshall.json.*; 021import org.apache.juneau.marshall.jsonschema.*; 022 023/** 024 * Serializes POJO metamodels to HTML. 025 * 026 * <h5 class='topic'>Media types</h5> 027 * 028 * Handles <c>Accept</c> types: <bc>text/html+schema</bc> 029 * <p> 030 * Produces <c>Content-Type</c> types: <bc>text/html</bc> 031 * 032 * <h5 class='topic'>Description</h5> 033 * 034 * Essentially the same as {@link HtmlDocSerializer}, except serializes the POJO metamodel instead of the model itself. 035 * 036 * <p> 037 * Produces output that describes the POJO metamodel similar to an XML schema document. 038 * 039 * <p> 040 * The easiest way to create instances of this class is through the {@link HtmlSerializer#getSchemaSerializer()}, 041 * which will create a schema serializer with the same settings as the originating serializer. 042 * 043 * <h5 class='section'>Notes:</h5><ul> 044 * <li class='note'>This class is thread safe and reusable. 045 * </ul> 046 * 047 * <h5 class='section'>See Also:</h5><ul> 048 * <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/HtmlSupport">HTML</a> 049 050 * </ul> 051 */ 052@SuppressWarnings({ 053 "java:S110", // Inheritance depth acceptable for HtmlSchemaDocSerializer hierarchy 054 "java:S9149" // Per-format static factories intentionally shadow the parent's. 055}) 056public class HtmlSchemaDocSerializer extends HtmlDocSerializer { 057 058 /** 059 * Builder class. 060 */ 061 public static class Builder extends HtmlDocSerializer.Builder<Builder> { 062 063 JsonSchemaGenerator.Builder generatorBuilder; 064 065 /** 066 * Constructor, default settings. 067 */ 068 protected Builder() { 069 produces("text/html"); 070 accept("text/html+schema"); 071 generatorBuilder = JsonSchemaGenerator.create().marshallingContext(marshallingContext()); 072 } 073 074 /** 075 * Copy constructor. 076 * 077 * @param copyFrom The builder to copy from. 078 */ 079 protected Builder(Builder copyFrom) { 080 super(copyFrom); 081 generatorBuilder = copyFrom.generatorBuilder.copy().marshallingContext(marshallingContext()); 082 } 083 084 /** 085 * Copy constructor. 086 * 087 * @param copyFrom The bean to copy from. 088 */ 089 protected Builder(HtmlSchemaDocSerializer copyFrom) { 090 super(copyFrom); 091 generatorBuilder = copyFrom.generator.copy().marshallingContext(marshallingContext()); 092 } 093 094 /** 095 * <i><l>HtmlSchemaSerializer</l> configuration property: </i> Add descriptions. 096 * 097 * <p> 098 * Identifies which categories of types that descriptions should be automatically added to generated schemas. 099 * <p> 100 * The description is the result of calling {@link ClassMeta#getName()}. 101 * 102 * <h5 class='section'>See Also:</h5><ul> 103 * <li class='jm'>{@link org.apache.juneau.marshall.jsonschema.JsonSchemaGenerator.Builder#addDescriptionsTo(TypeCategory...) JsonSchemaGenerator.Builder#addDescriptionsTo(TypeCategory...)} 104 * </ul> 105 * 106 * @param values 107 * The values to add to this setting. 108 * <br>The default is an empty string. 109 * @return This object. 110 */ 111 public Builder addDescriptionsTo(TypeCategory...values) { 112 generatorBuilder.addDescriptionsTo(values); 113 return this; 114 } 115 116 /** 117 * <i><l>HtmlSchemaSerializer</l> configuration property: </i> Add examples. 118 * 119 * <p> 120 * Identifies which categories of types that examples should be automatically added to generated schemas. 121 * <p> 122 * The examples come from calling {@link ClassMeta#getExample(MarshallingSession,JsonParserSession)} which in turn gets examples 123 * from the following: 124 * <ul class='javatree'> 125 * <li class='ja'>{@link Example} 126 * <li class='ja'>{@link Marshalled#example() Marshalled(example)} 127 * </ul> 128 * 129 * <h5 class='section'>See Also:</h5><ul> 130 * <li class='jm'>{@link org.apache.juneau.marshall.jsonschema.JsonSchemaGenerator.Builder#addExamplesTo(TypeCategory...) JsonSchemaGenerator.Builder#addExamplesTo(TypeCategory...)} 131 * </ul> 132 * 133 * @param values 134 * The values to add to this setting. 135 * <br>The default is an empty string. 136 * @return This object. 137 */ 138 public Builder addExamplesTo(TypeCategory...values) { 139 generatorBuilder.addExamplesTo(values); 140 return this; 141 } 142 143 /** 144 * <i><l>HtmlSchemaSerializer</l> configuration property: </i> Allow nested descriptions. 145 * 146 * <p> 147 * Identifies whether nested descriptions are allowed in schema definitions. 148 * 149 * <h5 class='section'>See Also:</h5><ul> 150 * <li class='jm'>{@link org.apache.juneau.marshall.jsonschema.JsonSchemaGenerator.Builder#allowNestedDescriptions() JsonSchemaGenerator.Builder#allowNestedDescriptions()} 151 * </ul> 152 * 153 * @return This object. 154 */ 155 public Builder allowNestedDescriptions() { 156 generatorBuilder.allowNestedDescriptions(); 157 return this; 158 } 159 160 /** 161 * <i><l>HtmlSchemaSerializer</l> configuration property: </i> Allow nested examples. 162 * 163 * <p> 164 * Identifies whether nested examples are allowed in schema definitions. 165 * 166 * <h5 class='section'>See Also:</h5><ul> 167 * <li class='jm'>{@link org.apache.juneau.marshall.jsonschema.JsonSchemaGenerator.Builder#allowNestedExamples() JsonSchemaGenerator.Builder#allowNestedExamples()} 168 * </ul> 169 * 170 * @return This object. 171 */ 172 public Builder allowNestedExamples() { 173 generatorBuilder.allowNestedExamples(); 174 return this; 175 } 176 177 /** 178 * <i><l>HtmlSchemaSerializer</l> configuration property: </i> Schema definition mapper. 179 * 180 * <p> 181 * Interface to use for converting Bean classes to definition IDs and URIs. 182 * <p> 183 * Used primarily for defining common definition sections for beans in Swagger JSON. 184 * <p> 185 * This setting is ignored if {@link org.apache.juneau.marshall.jsonschema.JsonSchemaGenerator.Builder#useBeanDefs() JsonSchemaGenerator.Builder#useBeanDefs()} is not enabled. 186 * 187 * <h5 class='section'>See Also:</h5><ul> 188 * <li class='jm'>{@link org.apache.juneau.marshall.jsonschema.JsonSchemaGenerator.Builder#beanDefMapper(Class) JsonSchemaGenerator.Builder#beanDefMapper(Class)} 189 * </ul> 190 * 191 * @param value 192 * The new value for this property. 193 * <br>The default is {@link BasicBeanDefMapper}. 194 * @return This object. 195 */ 196 public Builder beanDefMapper(Class<? extends MarshallingDefMapper> value) { 197 generatorBuilder.beanDefMapper(value); 198 return this; 199 } 200 201 @Override /* Overridden from Context.Builder<?> */ 202 public HtmlSchemaDocSerializer build() { 203 return build(HtmlSchemaDocSerializer.class); 204 } 205 206 @Override /* Overridden from Context.Builder<?> */ 207 public Builder copy() { 208 return new Builder(this); 209 } 210 211 /** 212 * <i><l>HtmlSchemaSerializer</l> configuration property: </i> Use bean definitions. 213 * 214 * <p> 215 * When enabled, schemas on beans will be serialized as the following: 216 * <p class='bjson'> 217 * { 218 * type: <js>'object'</js>, 219 * <js>'$ref'</js>: <js>'#/definitions/TypeId'</js> 220 * } 221 * </p> 222 * 223 * @return This object. 224 */ 225 public Builder useBeanDefs() { 226 generatorBuilder.useBeanDefs(); 227 return this; 228 } 229 230 231 @Override /* Overridden from Builder */ 232 @SuppressWarnings({ 233 "unchecked" // Varargs method requires unchecked cast 234 }) 235 public Builder widgets(Class<? extends HtmlWidget>...values) { 236 super.widgets(values); 237 return this; 238 } 239 240 } 241 242 /** 243 * Creates a new builder for this object. 244 * 245 * @return A new builder. 246 */ 247 public static Builder create() { 248 return new Builder(); 249 } 250 251 final JsonSchemaGenerator generator; 252 253 /** 254 * Constructor. 255 * 256 * @param builder 257 * The builder for this object. 258 */ 259 public HtmlSchemaDocSerializer(HtmlDocSerializer.Builder<?> builder) { 260 super(builder.detectRecursions().ignoreRecursions()); 261 262 generator = JsonSchemaGenerator.create().marshallingContext(getMarshallingContext()).build(); 263 } 264 265 @Override /* Overridden from Context */ 266 public Builder copy() { 267 return new Builder(this); 268 } 269 270 @Override /* Overridden from Context */ 271 public HtmlSchemaDocSerializerSession.Builder createSession() { 272 return HtmlSchemaDocSerializerSession.create(this); 273 } 274 275 @Override /* Overridden from Context */ 276 public HtmlSchemaDocSerializerSession getSession() { return createSession().build(); } 277 278 JsonSchemaGenerator getGenerator() { return generator; } 279}