001// ***************************************************************************************************************************
002// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
003// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
004// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
005// * with the License.  You may obtain a copy of the License at                                                              *
006// *                                                                                                                         *
007// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
008// *                                                                                                                         *
009// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
010// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
011// * specific language governing permissions and limitations under the License.                                              *
012// ***************************************************************************************************************************
013package org.apache.juneau.jsonschema;
014
015import static org.apache.juneau.internal.StringUtils.*;
016
017import java.util.*;
018import java.util.concurrent.*;
019import java.util.regex.*;
020
021import org.apache.juneau.*;
022import org.apache.juneau.annotation.*;
023import org.apache.juneau.json.*;
024
025/**
026 * Generates JSON-schema metadata about POJOs.
027 */
028@ConfigurableContext
029public class JsonSchemaGenerator extends BeanTraverseContext implements JsonSchemaMetaProvider {
030
031   //-------------------------------------------------------------------------------------------------------------------
032   // Configurable properties
033   //-------------------------------------------------------------------------------------------------------------------
034
035   static final String PREFIX = "JsonSchemaGenerator";
036
037   /**
038    * Configuration property:  Add descriptions to types.
039    *
040    * <h5 class='section'>Property:</h5>
041    * <ul class='spaced-list'>
042    *    <li><b>ID:</b>  {@link org.apache.juneau.jsonschema.JsonSchemaGenerator#JSONSCHEMA_addDescriptionsTo JSONSCHEMA_addDescriptionsTo}
043    *    <li><b>Name:</b>  <js>"JsonSchemaGenerator.addDescriptionsTo.s"</js>
044    *    <li><b>Data type:</b>  <c>String</c>
045    *    <li><b>System property:</b>  <c>JsonSchemaGenerator.addDescriptionsTo</c>
046    *    <li><b>Environment variable:</b>  <c>JSONSCHEMAGENERATOR_ADDDESCRIPTIONSTO</c>
047    *    <li><b>Default:</b>  Empty string.
048    *    <li><b>Session property:</b>  <jk>false</jk>
049    *    <li><b>Annotations:</b>
050    *       <ul>
051    *          <li class='ja'>{@link org.apache.juneau.jsonschema.annotation.JsonSchemaConfig#addDescriptionsTo()}
052    *       </ul>
053    *    <li><b>Methods:</b>
054    *       <ul>
055    *          <li class='jm'>{@link org.apache.juneau.jsonschema.JsonSchemaGeneratorBuilder#addDescriptionsTo(String)}
056    *       </ul>
057    * </ul>
058    *
059    * <h5 class='section'>Description:</h5>
060    * <p>
061    * Identifies which categories of types that descriptions should be automatically added to generated schemas.
062    * <p>
063    * The description is the result of calling {@link ClassMeta#getFullName()}.
064    * <p>
065    * The format is a comma-delimited list of any of the following values:
066    *
067    * <ul class='javatree'>
068    *    <li class='jf'>{@link TypeCategory#BEAN BEAN}
069    *    <li class='jf'>{@link TypeCategory#COLLECTION COLLECTION}
070    *    <li class='jf'>{@link TypeCategory#ARRAY ARRAY}
071    *    <li class='jf'>{@link TypeCategory#MAP MAP}
072    *    <li class='jf'>{@link TypeCategory#STRING STRING}
073    *    <li class='jf'>{@link TypeCategory#NUMBER NUMBER}
074    *    <li class='jf'>{@link TypeCategory#BOOLEAN BOOLEAN}
075    *    <li class='jf'>{@link TypeCategory#ANY ANY}
076    *    <li class='jf'>{@link TypeCategory#OTHER OTHER}
077    * </ul>
078    */
079   public static final String JSONSCHEMA_addDescriptionsTo = PREFIX + ".addDescriptionsTo.s";
080
081   /**
082    * Configuration property:  Add examples.
083    *
084    * <h5 class='section'>Property:</h5>
085    * <ul class='spaced-list'>
086    *    <li><b>ID:</b>  {@link org.apache.juneau.jsonschema.JsonSchemaGenerator#JSONSCHEMA_addExamplesTo JSONSCHEMA_addExamplesTo}
087    *    <li><b>Name:</b>  <js>"JsonSchemaGenerator.addExamplesTo.s"</js>
088    *    <li><b>Data type:</b>  <c>String</c>
089    *    <li><b>System property:</b>  <c>JsonSchemaGenerator.addExamplesTo</c>
090    *    <li><b>Environment variable:</b>  <c>JSONSCHEMAGENERATOR_ADDEXAMPLESTO</c>
091    *    <li><b>Default:</b>  Empty string.
092    *    <li><b>Session property:</b>  <jk>false</jk>
093    *    <li><b>Annotations:</b>
094    *       <ul>
095    *          <li class='ja'>{@link org.apache.juneau.jsonschema.annotation.JsonSchemaConfig#addExamplesTo()}
096    *       </ul>
097    *    <li><b>Methods:</b>
098    *       <ul>
099    *          <li class='jm'>{@link org.apache.juneau.jsonschema.JsonSchemaGeneratorBuilder#addExamplesTo(String)}
100    *       </ul>
101    * </ul>
102    *
103    * <h5 class='section'>Description:</h5>
104    * <p>
105    * Identifies which categories of types that examples should be automatically added to generated schemas.
106    * <p>
107    * The examples come from calling {@link ClassMeta#getExample(BeanSession)} which in turn gets examples
108    * from the following:
109    * <ul class='javatree'>
110    *    <li class='ja'>{@link Example}
111    *    <li class='jf'>{@link BeanContext#BEAN_examples}
112    * </ul>
113    *
114    * <p>
115    * The format is a comma-delimited list of any of the following values:
116    *
117    * <ul class='javatree'>
118    *    <li class='jf'>{@link TypeCategory#BEAN BEAN}
119    *    <li class='jf'>{@link TypeCategory#COLLECTION COLLECTION}
120    *    <li class='jf'>{@link TypeCategory#ARRAY ARRAY}
121    *    <li class='jf'>{@link TypeCategory#MAP MAP}
122    *    <li class='jf'>{@link TypeCategory#STRING STRING}
123    *    <li class='jf'>{@link TypeCategory#NUMBER NUMBER}
124    *    <li class='jf'>{@link TypeCategory#BOOLEAN BOOLEAN}
125    *    <li class='jf'>{@link TypeCategory#ANY ANY}
126    *    <li class='jf'>{@link TypeCategory#OTHER OTHER}
127    * </ul>
128    */
129   public static final String JSONSCHEMA_addExamplesTo = PREFIX + ".addExamplesTo.s";
130
131   /**
132    * Configuration property:  Allow nested descriptions.
133    *
134    * <h5 class='section'>Property:</h5>
135    * <ul class='spaced-list'>
136    *    <li><b>ID:</b>  {@link org.apache.juneau.jsonschema.JsonSchemaGenerator#JSONSCHEMA_allowNestedDescriptions JSONSCHEMA_allowNestedDescriptions}
137    *    <li><b>Name:</b>  <js>"JsonSchemaGenerator.allowNestedDescriptions.b"</js>
138    *    <li><b>Data type:</b>  <jk>boolean</jk>
139    *    <li><b>System property:</b>  <c>JsonSchemaGenerator.allowNestedDescriptions</c>
140    *    <li><b>Environment variable:</b>  <c>JSONSCHEMAGENERATOR_ALLOWNESTEDDESCRIPTIONS</c>
141    *    <li><b>Default:</b>  <jk>false</jk>
142    *    <li><b>Session property:</b>  <jk>false</jk>
143    *    <li><b>Annotations:</b>
144    *       <ul>
145    *          <li class='ja'>{@link org.apache.juneau.jsonschema.annotation.JsonSchemaConfig#allowNestedDescriptions()}
146    *       </ul>
147    *    <li><b>Methods:</b>
148    *       <ul>
149    *          <li class='jm'>{@link org.apache.juneau.jsonschema.JsonSchemaGeneratorBuilder#allowNestedDescriptions()}
150    *       </ul>
151    * </ul>
152    *
153    * <h5 class='section'>Description:</h5>
154    * <p>
155    * Identifies whether nested descriptions are allowed in schema definitions.
156    */
157   public static final String JSONSCHEMA_allowNestedDescriptions = PREFIX + ".allowNestedDescriptions.b";
158
159   /**
160    * Configuration property:  Allow nested examples.
161    *
162    * <h5 class='section'>Property:</h5>
163    * <ul class='spaced-list'>
164    *    <li><b>ID:</b>  {@link org.apache.juneau.jsonschema.JsonSchemaGenerator#JSONSCHEMA_allowNestedExamples JSONSCHEMA_allowNestedExamples}
165    *    <li><b>Name:</b>  <js>"JsonSchemaGenerator.allowNestedExamples.b"</js>
166    *    <li><b>Data type:</b>  <jk>boolean</jk>
167    *    <li><b>System property:</b>  <c>JsonSchemaGenerator.allowNestedExamples</c>
168    *    <li><b>Environment variable:</b>  <c>JSONSCHEMAGENERATOR_ALLOWNESTEDEXAMPLES</c>
169    *    <li><b>Default:</b>  <jk>false</jk>
170    *    <li><b>Session property:</b>  <jk>false</jk>
171    *    <li><b>Annotations:</b>
172    *       <ul>
173    *          <li class='ja'>{@link org.apache.juneau.jsonschema.annotation.JsonSchemaConfig#allowNestedExamples()}
174    *       </ul>
175    *    <li><b>Methods:</b>
176    *       <ul>
177    *          <li class='jm'>{@link org.apache.juneau.jsonschema.JsonSchemaGeneratorBuilder#allowNestedExamples()}
178    *       </ul>
179    * </ul>
180    *
181    * <h5 class='section'>Description:</h5>
182    * <p>
183    * Identifies whether nested examples are allowed in schema definitions.
184    */
185   public static final String JSONSCHEMA_allowNestedExamples = PREFIX + ".allowNestedExamples.b";
186
187   /**
188    * Configuration property:  Bean schema definition mapper.
189    *
190    * <h5 class='section'>Property:</h5>
191    * <ul class='spaced-list'>
192    *    <li><b>ID:</b>  {@link org.apache.juneau.jsonschema.JsonSchemaGenerator#JSONSCHEMA_beanDefMapper JSONSCHEMA_beanDefMapper}
193    *    <li><b>Name:</b>  <js>"JsonSchemaGenerator.beanDefMapper.o"</js>
194    *    <li><b>Data type:</b>  {@link org.apache.juneau.jsonschema.BeanDefMapper}
195    *    <li><b>Default:</b>  {@link org.apache.juneau.jsonschema.BasicBeanDefMapper}
196    *    <li><b>Session property:</b>  <jk>false</jk>
197    *    <li><b>Annotations:</b>
198    *       <ul>
199    *          <li class='ja'>{@link org.apache.juneau.jsonschema.annotation.JsonSchemaConfig#beanDefMapper()}
200    *       </ul>
201    *    <li><b>Methods:</b>
202    *       <ul>
203    *          <li class='jm'>{@link org.apache.juneau.jsonschema.JsonSchemaGeneratorBuilder#beanDefMapper(Class)}
204    *          <li class='jm'>{@link org.apache.juneau.jsonschema.JsonSchemaGeneratorBuilder#beanDefMapper(BeanDefMapper)}
205    *       </ul>
206    * </ul>
207    *
208    * <h5 class='section'>Description:</h5>
209    * <p>
210    * Interface to use for converting Bean classes to definition IDs and URIs.
211    * <p>
212    * Used primarily for defining common definition sections for beans in Swagger JSON.
213    * <p>
214    * This setting is ignored if {@link #JSONSCHEMA_useBeanDefs} is not enabled.
215    */
216   public static final String JSONSCHEMA_beanDefMapper = PREFIX + ".beanDefMapper.o";
217
218   /**
219    * Configuration property:  Default schemas.
220    *
221    * <h5 class='section'>Property:</h5>
222    * <ul class='spaced-list'>
223    *    <li><b>ID:</b>  {@link org.apache.juneau.jsonschema.JsonSchemaGenerator#JSONSCHEMA_defaultSchemas JSONSCHEMA_defaultSchemas}
224    *    <li><b>Name:</b>  <js>"JsonSchemaGenerator.defaultSchema.smo"</js>
225    *    <li><b>Data type:</b>  <c>Map&lt;String,{@link org.apache.juneau.ObjectMap}&gt;</c>
226    *    <li><b>System property:</b>  <c>JsonSchemaGenerator.defaultSchema</c>
227    *    <li><b>Environment variable:</b>  <c>JSONSCHEMAGENERATOR_DEFAULTSCHEMA</c>
228    *    <li><b>Default:</b>  Empty map.
229    *    <li><b>Session property:</b>  <jk>false</jk>
230    *    <li><b>Annotations:</b>
231    *       <ul>
232    *          <li class='ja'>{@link org.apache.juneau.jsonschema.annotation.JsonSchemaConfig#defaultSchemas()}
233    *       </ul>
234    *    <li><b>Methods:</b>
235    *       <ul>
236    *          <li class='jm'>{@link org.apache.juneau.jsonschema.JsonSchemaGeneratorBuilder#defaultSchema(Class,ObjectMap)}
237    *       </ul>
238    * </ul>
239    *
240    * <h5 class='section'>Description:</h5>
241    * <p>
242    * Allows you to override or provide custom schema information for particular class types.
243    * <p>
244    * Keys are full class names.
245    */
246   public static final String JSONSCHEMA_defaultSchemas = PREFIX + ".defaultSchemas.smo";
247
248   /**
249    * Configuration property:  Ignore types from schema definitions.
250    *
251    * <h5 class='section'>Property:</h5>
252    * <ul class='spaced-list'>
253    *    <li><b>ID:</b>  {@link org.apache.juneau.jsonschema.JsonSchemaGenerator#JSONSCHEMA_ignoreTypes JSONSCHEMA_ignoreTypes}
254    *    <li><b>Name:</b>  <js>"JsonSchemaGenerator.ignoreTypes.s"</js>
255    *    <li><b>Data type:</b>  <c>String</c> (comma-delimited)
256    *    <li><b>System property:</b>  <c>JsonSchemaGenerator.ignoreTypes</c>
257    *    <li><b>Environment variable:</b>  <c>JSONSCHEMAGENERATOR_IGNORETYPES</c>
258    *    <li><b>Default:</b>  <jk>null</jk>.
259    *    <li><b>Session property:</b>  <jk>false</jk>
260    *    <li><b>Annotations:</b>
261    *       <ul>
262    *          <li class='ja'>{@link org.apache.juneau.jsonschema.annotation.JsonSchemaConfig#ignoreTypes()}
263    *       </ul>
264    * </ul>
265    *
266    * <h5 class='section'>Description:</h5>
267    * <p>
268    * Defines class name patterns that should be ignored when generating schema definitions in the generated
269    * Swagger documentation.
270    *
271    * <h5 class='section'>Example:</h5>
272    * <p class='bcode w800'>
273    *    <jc>// Don't generate schema for any prototype packages or the class named 'Swagger'.</jc>
274    *    <ja>@Rest</ja>(
275    *          properties={
276    *             <ja>@Property</ja>(name=<jsf>JSONSCHEMA_ignoreTypes</jsf>, value=<js>"Swagger,*.proto.*"</js>)
277    *          }
278    *    <jk>public class</jk> MyResource {...}
279    * </p>
280    */
281   public static final String JSONSCHEMA_ignoreTypes = PREFIX + ".ignoreTypes.s";
282
283   /**
284    * Configuration property:  Use bean definitions.
285    *
286    * <h5 class='section'>Property:</h5>
287    * <ul class='spaced-list'>
288    *    <li><b>ID:</b>  {@link org.apache.juneau.jsonschema.JsonSchemaGenerator#JSONSCHEMA_useBeanDefs JSONSCHEMA_useBeanDefs}
289    *    <li><b>Name:</b>  <js>"JsonSchemaGenerator.useBeanDefs.b"</js>
290    *    <li><b>Data type:</b>  <jk>boolean</jk>
291    *    <li><b>System property:</b>  <c>JsonSchemaGenerator.useBeanDefs</c>
292    *    <li><b>Environment variable:</b>  <c>JSONSCHEMAGENERATOR_USEBEANDEFS</c>
293    *    <li><b>Default:</b>  <jk>false</jk>
294    *    <li><b>Annotations:</b>
295    *       <ul>
296    *          <li class='ja'>{@link org.apache.juneau.jsonschema.annotation.JsonSchemaConfig#useBeanDefs()}
297    *       </ul>
298    *    <li><b>Methods:</b>
299    *       <ul>
300    *          <li class='jm'>{@link org.apache.juneau.jsonschema.JsonSchemaGeneratorBuilder#useBeanDefs()}
301    *       </ul>
302    * </ul>
303    *
304    * <h5 class='section'>Description:</h5>
305    * <p>
306    * When enabled, schemas on beans will be serialized as the following:
307    * <p class='bcode w800'>
308    *    {
309    *       type: <js>'object'</js>,
310    *       <js>'$ref'</js>: <js>'#/definitions/TypeId'</js>
311    *    }
312    * </p>
313    *
314    * <p>
315    * The definitions can then be retrieved from the session using {@link JsonSchemaGeneratorSession#getBeanDefs()}.
316    * <p>
317    * Definitions can also be added programmatically using {@link JsonSchemaGeneratorSession#addBeanDef(String, ObjectMap)}.
318    */
319   public static final String JSONSCHEMA_useBeanDefs = PREFIX + ".useBeanDefs.b";
320
321
322   //-------------------------------------------------------------------------------------------------------------------
323   // Predefined instances
324   //-------------------------------------------------------------------------------------------------------------------
325
326   /** Default serializer, all default settings.*/
327   public static final JsonSchemaGenerator DEFAULT = new JsonSchemaGenerator(PropertyStore.DEFAULT);
328
329
330   //-------------------------------------------------------------------------------------------------------------------
331   // Instance
332   //-------------------------------------------------------------------------------------------------------------------
333
334   private final boolean useBeanDefs, allowNestedExamples, allowNestedDescriptions;
335   private final BeanDefMapper beanDefMapper;
336   private final Set<TypeCategory> addExamplesTo, addDescriptionsTo;
337   private final Map<String,ObjectMap> defaultSchemas;
338   private final JsonSerializer jsonSerializer;
339   private final Set<Pattern> ignoreTypes;
340   private final Map<ClassMeta<?>,JsonSchemaClassMeta> jsonSchemaClassMetas = new ConcurrentHashMap<>();
341   private final Map<BeanPropertyMeta,JsonSchemaBeanPropertyMeta> jsonSchemaBeanPropertyMetas = new ConcurrentHashMap<>();
342
343   /**
344    * Constructor.
345    *
346    * @param ps Initialize with the specified config property store.
347    */
348   public JsonSchemaGenerator(PropertyStore ps) {
349      super(ps.builder().set(BEANTRAVERSE_detectRecursions, true).set(BEANTRAVERSE_ignoreRecursions, true).build());
350
351      useBeanDefs = getBooleanProperty(JSONSCHEMA_useBeanDefs, false);
352      allowNestedExamples = getBooleanProperty(JSONSCHEMA_allowNestedExamples, false);
353      allowNestedDescriptions = getBooleanProperty(JSONSCHEMA_allowNestedDescriptions, false);
354      beanDefMapper = getInstanceProperty(JSONSCHEMA_beanDefMapper, BeanDefMapper.class, BasicBeanDefMapper.class);
355      addExamplesTo = TypeCategory.parse(getStringProperty(JSONSCHEMA_addExamplesTo, null));
356      addDescriptionsTo = TypeCategory.parse(getStringProperty(JSONSCHEMA_addDescriptionsTo, null));
357      defaultSchemas = getMapProperty(JSONSCHEMA_defaultSchemas, ObjectMap.class);
358
359      Set<Pattern> ignoreTypes = new LinkedHashSet<>();
360      for (String s : split(ps.getProperty(JSONSCHEMA_ignoreTypes, String.class, "")))
361         ignoreTypes.add(Pattern.compile(s.replace(".", "\\.").replace("*", ".*")));
362      this.ignoreTypes = ignoreTypes;
363
364      jsonSerializer = new JsonSerializer(ps);
365   }
366
367   @Override /* Context */
368   public JsonSchemaGeneratorBuilder builder() {
369      return new JsonSchemaGeneratorBuilder(getPropertyStore());
370   }
371
372   /**
373    * Instantiates a new clean-slate {@link JsonSerializerBuilder} object.
374    *
375    * <p>
376    * This is equivalent to simply calling <code><jk>new</jk> JsonSerializerBuilder()</code>.
377    *
378    * @return A new {@link JsonSerializerBuilder} object.
379    */
380   public static JsonSchemaGeneratorBuilder create() {
381      return new JsonSchemaGeneratorBuilder();
382   }
383
384   @Override /* Context */
385   public JsonSchemaGeneratorSession createSession() {
386      return createSession(createDefaultSessionArgs());
387   }
388
389   @Override
390   public JsonSchemaGeneratorSession createSession(BeanSessionArgs args) {
391      return new JsonSchemaGeneratorSession(this, args);
392   }
393
394   JsonSerializer getJsonSerializer() {
395      return jsonSerializer;
396   }
397
398   //-----------------------------------------------------------------------------------------------------------------
399   // Properties
400   //-----------------------------------------------------------------------------------------------------------------
401
402   /**
403    * Configuration property:  Add descriptions to types.
404    *
405    * @see #JSONSCHEMA_addDescriptionsTo
406    * @return
407    *    Set of categories of types that descriptions should be automatically added to generated schemas.
408    */
409   protected final Set<TypeCategory> getAddDescriptionsTo() {
410      return addDescriptionsTo;
411   }
412
413   /**
414    * Configuration property:  Add examples.
415    *
416    * @see #JSONSCHEMA_addExamplesTo
417    * @return
418    *    Set of categories of types that examples should be automatically added to generated schemas.
419    */
420   protected final Set<TypeCategory> getAddExamplesTo() {
421      return addExamplesTo;
422   }
423
424   /**
425    * Configuration property:  Allow nested descriptions.
426    *
427    * @see #JSONSCHEMA_allowNestedDescriptions
428    * @return
429    *    <jk>true</jk> if nested descriptions are allowed in schema definitions.
430    */
431   protected final boolean isAllowNestedDescriptions() {
432      return allowNestedDescriptions;
433   }
434
435   /**
436    * Configuration property:  Allow nested examples.
437    *
438    * @see #JSONSCHEMA_allowNestedExamples
439    * @return
440    *    <jk>true</jk> if nested examples are allowed in schema definitions.
441    */
442   protected final boolean isAllowNestedExamples() {
443      return allowNestedExamples;
444   }
445
446   /**
447    * Configuration property:  Bean schema definition mapper.
448    *
449    * @see #JSONSCHEMA_beanDefMapper
450    * @return
451    *    Interface to use for converting Bean classes to definition IDs and URIs.
452    */
453   protected final BeanDefMapper getBeanDefMapper() {
454      return beanDefMapper;
455   }
456
457   /**
458    * Configuration property:  Default schemas.
459    *
460    * @see #JSONSCHEMA_defaultSchemas
461    * @return
462    *    Custom schema information for particular class types.
463    */
464   protected final Map<String,ObjectMap> getDefaultSchemas() {
465      return defaultSchemas;
466   }
467
468   /**
469    * Configuration property:  Ignore types from schema definitions.
470    *
471    * @see JsonSchemaGenerator#JSONSCHEMA_ignoreTypes
472    * @return
473    *    Custom schema information for particular class types.
474    */
475   public Set<Pattern> getIgnoreTypes() {
476      return ignoreTypes;
477   }
478
479   /**
480    * Configuration property:  Use bean definitions.
481    *
482    * @see #JSONSCHEMA_useBeanDefs
483    * @return
484    *    <jk>true</jk> if schemas on beans will be serialized with <js>'$ref'</js> tags.
485    */
486   protected final boolean isUseBeanDefs() {
487      return useBeanDefs;
488   }
489
490   //-----------------------------------------------------------------------------------------------------------------
491   // Extended metadata
492   //-----------------------------------------------------------------------------------------------------------------
493
494   @Override
495   public JsonSchemaClassMeta getJsonSchemaClassMeta(ClassMeta<?> cm) {
496      JsonSchemaClassMeta m = jsonSchemaClassMetas.get(cm);
497      if (m == null) {
498         m = new JsonSchemaClassMeta(cm, this);
499         jsonSchemaClassMetas.put(cm, m);
500      }
501      return m;
502   }
503
504   @Override
505   public JsonSchemaBeanPropertyMeta getJsonSchemaBeanPropertyMeta(BeanPropertyMeta bpm) {
506      JsonSchemaBeanPropertyMeta m = jsonSchemaBeanPropertyMetas.get(bpm);
507      if (m == null) {
508         m = new JsonSchemaBeanPropertyMeta(bpm, this);
509         jsonSchemaBeanPropertyMetas.put(bpm, m);
510      }
511      return m;
512   }
513
514   //-----------------------------------------------------------------------------------------------------------------
515   // Other methods
516   //-----------------------------------------------------------------------------------------------------------------
517
518   /**
519    * Returns <jk>true</jk> if the specified type is ignored.
520    *
521    * <p>
522    * The type is ignored if it's specified in the {@link #JSONSCHEMA_ignoreTypes} setting.
523    * <br>Ignored types return <jk>null</jk> on the call to {@link JsonSchemaGeneratorSession#getSchema(ClassMeta)}.
524    *
525    * @param cm The type to check.
526    * @return <jk>true</jk> if the specified type is ignored.
527    */
528   public boolean isIgnoredType(ClassMeta<?> cm) {
529      for (Pattern p : ignoreTypes)
530         if (p.matcher(cm.getSimpleName()).matches() || p.matcher(cm.getName()).matches())
531            return true;
532      return false;
533   }
534
535   //-----------------------------------------------------------------------------------------------------------------
536   // Other methods
537   //-----------------------------------------------------------------------------------------------------------------
538
539   @Override /* Context */
540   public ObjectMap toMap() {
541      return super.toMap()
542         .append("JsonSchemaGenerator", new DefaultFilteringObjectMap()
543            .append("useBeanDefs", useBeanDefs)
544            .append("allowNestedExamples", allowNestedExamples)
545            .append("allowNestedDescriptions", allowNestedDescriptions)
546            .append("beanDefMapper", beanDefMapper)
547            .append("addExamplesTo", addExamplesTo)
548            .append("addDescriptionsTo", addDescriptionsTo)
549            .append("defaultSchemas", defaultSchemas)
550            .append("ignoreTypes", ignoreTypes)
551         );
552   }
553}