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