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.oapi;
018
019import java.lang.annotation.*;
020import java.nio.charset.*;
021import java.util.*;
022import java.util.concurrent.*;
023
024import org.apache.juneau.*;
025import org.apache.juneau.annotation.*;
026import org.apache.juneau.commons.collections.*;
027import org.apache.juneau.commons.function.*;
028import org.apache.juneau.commons.reflect.*;
029import org.apache.juneau.httppart.*;
030import org.apache.juneau.uon.*;
031
032/**
033 * OpenAPI part parser.
034 *
035 * <h5 class='section'>Notes:</h5><ul>
036 *    <li class='note'>This class is thread safe and reusable.
037 * </ul>
038 *
039 * <h5 class='section'>See Also:</h5><ul>
040 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/OpenApiBasics">OpenApi Basics</a>
041
042 * </ul>
043 */
044public class OpenApiParser extends UonParser implements OpenApiMetaProvider {
045   /**
046    * Builder class.
047    */
048   public static class Builder extends UonParser.Builder {
049
050      private static final Cache<HashKey,OpenApiParser> CACHE = Cache.of(HashKey.class, OpenApiParser.class).build();
051
052      HttpPartFormat format;
053      HttpPartCollectionFormat collectionFormat;
054
055      /**
056       * Constructor, default settings.
057       */
058      protected Builder() {
059         consumes("text/openapi");
060         format = HttpPartFormat.NO_FORMAT;
061         collectionFormat = HttpPartCollectionFormat.NO_COLLECTION_FORMAT;
062      }
063
064      /**
065       * Copy constructor.
066       *
067       * @param copyFrom The builder to copy from.
068       */
069      protected Builder(Builder copyFrom) {
070         super(copyFrom);
071         format = copyFrom.format;
072         collectionFormat = copyFrom.collectionFormat;
073      }
074
075      /**
076       * Copy constructor.
077       *
078       * @param copyFrom The bean to copy from.
079       */
080      protected Builder(OpenApiParser copyFrom) {
081         super(copyFrom);
082         format = copyFrom.format;
083         collectionFormat = copyFrom.collectionFormat;
084      }
085
086      @Override /* Overridden from Builder */
087      public Builder annotations(Annotation...values) {
088         super.annotations(values);
089         return this;
090      }
091
092      @Override /* Overridden from Builder */
093      public Builder apply(AnnotationWorkList work) {
094         super.apply(work);
095         return this;
096      }
097
098      @Override /* Overridden from Builder */
099      public Builder applyAnnotations(Class<?>...from) {
100         super.applyAnnotations(from);
101         return this;
102      }
103
104      @Override /* Overridden from Builder */
105      public Builder applyAnnotations(Object...from) {
106         super.applyAnnotations(from);
107         return this;
108      }
109
110      @Override /* Overridden from Builder */
111      public Builder autoCloseStreams() {
112         super.autoCloseStreams();
113         return this;
114      }
115
116      @Override /* Overridden from Builder */
117      public Builder autoCloseStreams(boolean value) {
118         super.autoCloseStreams(value);
119         return this;
120      }
121
122      @Override /* Overridden from Builder */
123      public Builder beanClassVisibility(Visibility value) {
124         super.beanClassVisibility(value);
125         return this;
126      }
127
128      @Override /* Overridden from Builder */
129      public Builder beanConstructorVisibility(Visibility value) {
130         super.beanConstructorVisibility(value);
131         return this;
132      }
133
134      @Override /* Overridden from Builder */
135      public Builder beanContext(BeanContext value) {
136         super.beanContext(value);
137         return this;
138      }
139
140      @Override /* Overridden from Builder */
141      public Builder beanContext(BeanContext.Builder value) {
142         super.beanContext(value);
143         return this;
144      }
145
146      @Override /* Overridden from Builder */
147      public Builder beanDictionary(java.lang.Class<?>...values) {
148         super.beanDictionary(values);
149         return this;
150      }
151
152      @Override /* Overridden from Builder */
153      public Builder beanFieldVisibility(Visibility value) {
154         super.beanFieldVisibility(value);
155         return this;
156      }
157
158      @Override /* Overridden from Builder */
159      public Builder beanInterceptor(Class<?> on, Class<? extends org.apache.juneau.swap.BeanInterceptor<?>> value) {
160         super.beanInterceptor(on, value);
161         return this;
162      }
163
164      @Override /* Overridden from Builder */
165      public Builder beanMapPutReturnsOldValue() {
166         super.beanMapPutReturnsOldValue();
167         return this;
168      }
169
170      @Override /* Overridden from Builder */
171      public Builder beanMethodVisibility(Visibility value) {
172         super.beanMethodVisibility(value);
173         return this;
174      }
175
176      @Override /* Overridden from Builder */
177      public Builder beanProperties(Class<?> beanClass, String properties) {
178         super.beanProperties(beanClass, properties);
179         return this;
180      }
181
182      @Override /* Overridden from Builder */
183      public Builder beanProperties(Map<String,Object> values) {
184         super.beanProperties(values);
185         return this;
186      }
187
188      @Override /* Overridden from Builder */
189      public Builder beanProperties(String beanClassName, String properties) {
190         super.beanProperties(beanClassName, properties);
191         return this;
192      }
193
194      @Override /* Overridden from Builder */
195      public Builder beanPropertiesExcludes(Class<?> beanClass, String properties) {
196         super.beanPropertiesExcludes(beanClass, properties);
197         return this;
198      }
199
200      @Override /* Overridden from Builder */
201      public Builder beanPropertiesExcludes(Map<String,Object> values) {
202         super.beanPropertiesExcludes(values);
203         return this;
204      }
205
206      @Override /* Overridden from Builder */
207      public Builder beanPropertiesExcludes(String beanClassName, String properties) {
208         super.beanPropertiesExcludes(beanClassName, properties);
209         return this;
210      }
211
212      @Override /* Overridden from Builder */
213      public Builder beanPropertiesReadOnly(Class<?> beanClass, String properties) {
214         super.beanPropertiesReadOnly(beanClass, properties);
215         return this;
216      }
217
218      @Override /* Overridden from Builder */
219      public Builder beanPropertiesReadOnly(Map<String,Object> values) {
220         super.beanPropertiesReadOnly(values);
221         return this;
222      }
223
224      @Override /* Overridden from Builder */
225      public Builder beanPropertiesReadOnly(String beanClassName, String properties) {
226         super.beanPropertiesReadOnly(beanClassName, properties);
227         return this;
228      }
229
230      @Override /* Overridden from Builder */
231      public Builder beanPropertiesWriteOnly(Class<?> beanClass, String properties) {
232         super.beanPropertiesWriteOnly(beanClass, properties);
233         return this;
234      }
235
236      @Override /* Overridden from Builder */
237      public Builder beanPropertiesWriteOnly(Map<String,Object> values) {
238         super.beanPropertiesWriteOnly(values);
239         return this;
240      }
241
242      @Override /* Overridden from Builder */
243      public Builder beanPropertiesWriteOnly(String beanClassName, String properties) {
244         super.beanPropertiesWriteOnly(beanClassName, properties);
245         return this;
246      }
247
248      @Override /* Overridden from Builder */
249      public Builder beansRequireDefaultConstructor() {
250         super.beansRequireDefaultConstructor();
251         return this;
252      }
253
254      @Override /* Overridden from Builder */
255      public Builder beansRequireSerializable() {
256         super.beansRequireSerializable();
257         return this;
258      }
259
260      @Override /* Overridden from Builder */
261      public Builder beansRequireSettersForGetters() {
262         super.beansRequireSettersForGetters();
263         return this;
264      }
265
266      @Override /* Overridden from Context.Builder */
267      public OpenApiParser build() {
268         return cache(CACHE).build(OpenApiParser.class);
269      }
270
271      @Override /* Overridden from Builder */
272      public Builder cache(Cache<HashKey,? extends org.apache.juneau.Context> value) {
273         super.cache(value);
274         return this;
275      }
276
277      /**
278       * <i><l>OpenApiCommon</l> configuration property:&emsp;</i>  Default collection format for HTTP parts.
279       *
280       * <p>
281       * Specifies the collection format to use for HTTP parts when not otherwise specified via {@link org.apache.juneau.annotation.Schema#collectionFormat()}.
282       *
283       * <h5 class='section'>Example:</h5>
284       * <p class='bjava'>
285       *    <jc>// Create a parser using CSV for collections.</jc>
286       *    OpenApiParser <jv>parser1</jv> = OpenApiParser
287       *       .<jsm>create</jsm>()
288       *       .collectionFormat(<jsf>CSV</jsf>)
289       *       .build();
290       *
291       *    <jc>// Create a serializer using UON for collections.</jc>
292       *    OpenApiParser <jv>parser2</jv> = OpenApiParser
293       *       .<jsm>create</jsm>()
294       *       .collectionFormat(<jsf>UON</jsf>)
295       *       .build();
296       *
297       *    <jc>// Parse CSV.</jc>
298       *    JsonList <jv>list1</jv> = <jv>parser1</jv>.parse(<js>"foo=bar,baz=qux\,true\,123"</js>, JsonList.<jk>class</jk>)
299       *
300       *    <jc>// Parse UON.</jc>
301       *    JsonList <jv>list2</jv> = <jv>parser2</jv>.parse(<js>"(foo=bar,baz=@(qux,true,123))"</js>, JsonList.<jk>class</jk>)
302       * </p>
303       *
304       * <ul class='values javatree'>
305       *    <li class='jc'>{@link org.apache.juneau.httppart.HttpPartFormat}
306       *    <ul>
307       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartCollectionFormat#CSV CSV} - (default) Comma-separated values (e.g. <js>"foo,bar"</js>).
308       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartCollectionFormat#SSV SSV} - Space-separated values (e.g. <js>"foo bar"</js>).
309       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartCollectionFormat#TSV TSV} - Tab-separated values (e.g. <js>"foo\tbar"</js>).
310       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartCollectionFormat#PIPES PIPES} - Pipe-separated values (e.g. <js>"foo|bar"</js>).
311       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartCollectionFormat#MULTI MULTI} - Corresponds to multiple parameter instances instead of multiple values for a single instance (e.g. <js>"foo=bar&amp;foo=baz"</js>).
312       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartCollectionFormat#UONC UONC} - UON collection notation (e.g. <js>"@(foo,bar)"</js>).
313       *    </ul>
314       * </ul>
315       *
316       * @param value The new value for this property.
317       * @return This object.
318       */
319      public Builder collectionFormat(HttpPartCollectionFormat value) {
320         collectionFormat = value;
321         return this;
322      }
323
324      @Override /* Overridden from Builder */
325      public Builder consumes(String value) {
326         super.consumes(value);
327         return this;
328      }
329
330      @Override /* Overridden from Context.Builder */
331      public Builder copy() {
332         return new Builder(this);
333      }
334
335      @Override /* Overridden from Builder */
336      public Builder debug() {
337         super.debug();
338         return this;
339      }
340
341      @Override /* Overridden from Builder */
342      public Builder debug(boolean value) {
343         super.debug(value);
344         return this;
345      }
346
347      @Override /* Overridden from Builder */
348      public Builder debugOutputLines(int value) {
349         super.debugOutputLines(value);
350         return this;
351      }
352
353      @Override /* Overridden from Builder */
354      public Builder decoding() {
355         super.decoding();
356         return this;
357      }
358
359      @Override /* Overridden from Builder */
360      public Builder decoding(boolean value) {
361         super.decoding(value);
362         return this;
363      }
364
365      @Override /* Overridden from Builder */
366      public Builder dictionaryOn(Class<?> on, java.lang.Class<?>...values) {
367         super.dictionaryOn(on, values);
368         return this;
369      }
370
371      @Override /* Overridden from Builder */
372      public Builder disableBeansRequireSomeProperties() {
373         super.disableBeansRequireSomeProperties();
374         return this;
375      }
376
377      @Override /* Overridden from Builder */
378      public Builder disableIgnoreMissingSetters() {
379         super.disableIgnoreMissingSetters();
380         return this;
381      }
382
383      @Override /* Overridden from Builder */
384      public Builder disableIgnoreTransientFields() {
385         super.disableIgnoreTransientFields();
386         return this;
387      }
388
389      @Override /* Overridden from Builder */
390      public Builder disableIgnoreUnknownNullBeanProperties() {
391         super.disableIgnoreUnknownNullBeanProperties();
392         return this;
393      }
394
395      @Override /* Overridden from Builder */
396      public Builder disableInterfaceProxies() {
397         super.disableInterfaceProxies();
398         return this;
399      }
400
401      @Override /* Overridden from Builder */
402      public <T> Builder example(Class<T> pojoClass, String json) {
403         super.example(pojoClass, json);
404         return this;
405      }
406
407      @Override /* Overridden from Builder */
408      public <T> Builder example(Class<T> pojoClass, T o) {
409         super.example(pojoClass, o);
410         return this;
411      }
412
413      @Override /* Overridden from Builder */
414      public Builder fileCharset(Charset value) {
415         super.fileCharset(value);
416         return this;
417      }
418
419      @Override /* Overridden from Builder */
420      public Builder findFluentSetters() {
421         super.findFluentSetters();
422         return this;
423      }
424
425      @Override /* Overridden from Builder */
426      public Builder findFluentSetters(Class<?> on) {
427         super.findFluentSetters(on);
428         return this;
429      }
430
431      /**
432       * <i><l>OpenApiCommon</l> configuration property:&emsp;</i>  Default format for HTTP parts.
433       *
434       * <p>
435       * Specifies the format to use for HTTP parts when not otherwise specified via {@link org.apache.juneau.annotation.Schema#format()}.
436       *
437       * <h5 class='section'>Example:</h5>
438       * <p class='bjava'>
439       *    <jc>// Create a plain-text parser.</jc>
440       *    OpenApiParser <jv>parser1</jv> = OpenApiParser
441       *       .<jsm>create</jsm>()
442       *       .build();
443       *
444       *    <jc>// Create a UON parser.</jc>
445       *    OpenApiParser <jv>parser2</jv> = OpenApiParser
446       *       .<jsm>create</jsm>()
447       *       .format(<jsf>UON</jsf>)
448       *       .build();
449       *
450       *    <jc>// Parse a plain-text string.</jc>
451       *    String <jv>value1</jv> = <jv>parser1</jv>.parse(<js>"foo bar"</js>);
452       *
453       *    <jc>// Parse a UON string.</jc>
454       *    String <jv>value2</jv> = <jv>parser1</jv>.parse(<js>"'foo bar'"</js>);
455       * </p>
456       *
457       * <ul class='values javatree'>
458       *    <li class='jc'>{@link org.apache.juneau.httppart.HttpPartFormat}
459       *    <ul>
460       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#UON UON} - UON notation (e.g. <js>"'foo bar'"</js>).
461       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#INT32 INT32} - Signed 32 bits.
462       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#INT64 INT64} - Signed 64 bits.
463       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#FLOAT FLOAT} - 32-bit floating point number.
464       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#DOUBLE DOUBLE} - 64-bit floating point number.
465       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#BYTE BYTE} - BASE-64 encoded characters.
466       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#BINARY BINARY} - Hexadecimal encoded octets (e.g. <js>"00FF"</js>).
467       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#BINARY_SPACED BINARY_SPACED} - Spaced-separated hexadecimal encoded octets (e.g. <js>"00 FF"</js>).
468       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#DATE DATE} - An <a href='http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14'>RFC3339 full-date</a>.
469       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#DATE_TIME DATE_TIME} - An <a href='http://xml2rfc.ietf.org/public/rfc/html/rfc3339.html#anchor14'>RFC3339 date-time</a>.
470       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#PASSWORD PASSWORD} - Used to hint UIs the input needs to be obscured.
471       *       <li class='jf'>{@link org.apache.juneau.httppart.HttpPartFormat#NO_FORMAT NO_FORMAT} - (default) Not specified.
472       *    </ul>
473       * </ul>
474       *
475       * @param value The new value for this property.
476       * @return This object.
477       */
478      public Builder format(HttpPartFormat value) {
479         format = value;
480         return this;
481      }
482
483      @Override /* Overridden from Context.Builder */
484      public HashKey hashKey() {
485         // @formatter:off
486         return HashKey.of(
487            super.hashKey(),
488            format,
489            collectionFormat
490         );
491         // @formatter:on
492      }
493
494      @Override /* Overridden from Builder */
495      public Builder ignoreInvocationExceptionsOnGetters() {
496         super.ignoreInvocationExceptionsOnGetters();
497         return this;
498      }
499
500      @Override /* Overridden from Builder */
501      public Builder ignoreInvocationExceptionsOnSetters() {
502         super.ignoreInvocationExceptionsOnSetters();
503         return this;
504      }
505
506      @Override /* Overridden from Builder */
507      public Builder ignoreUnknownBeanProperties() {
508         super.ignoreUnknownBeanProperties();
509         return this;
510      }
511
512      @Override /* Overridden from Builder */
513      public Builder ignoreUnknownEnumValues() {
514         super.ignoreUnknownEnumValues();
515         return this;
516      }
517
518      @Override /* Overridden from Builder */
519      public Builder impl(Context value) {
520         super.impl(value);
521         return this;
522      }
523
524      @Override /* Overridden from Builder */
525      public Builder implClass(Class<?> interfaceClass, Class<?> implClass) {
526         super.implClass(interfaceClass, implClass);
527         return this;
528      }
529
530      @Override /* Overridden from Builder */
531      public Builder implClasses(Map<Class<?>,Class<?>> values) {
532         super.implClasses(values);
533         return this;
534      }
535
536      @Override /* Overridden from Builder */
537      public Builder interfaceClass(Class<?> on, Class<?> value) {
538         super.interfaceClass(on, value);
539         return this;
540      }
541
542      @Override /* Overridden from Builder */
543      public Builder interfaces(java.lang.Class<?>...value) {
544         super.interfaces(value);
545         return this;
546      }
547
548      @Override /* Overridden from Builder */
549      public Builder listener(Class<? extends org.apache.juneau.parser.ParserListener> value) {
550         super.listener(value);
551         return this;
552      }
553
554      @Override /* Overridden from Builder */
555      public Builder locale(Locale value) {
556         super.locale(value);
557         return this;
558      }
559
560      @Override /* Overridden from Builder */
561      public Builder mediaType(MediaType value) {
562         super.mediaType(value);
563         return this;
564      }
565
566      @Override /* Overridden from Builder */
567      public Builder notBeanClasses(java.lang.Class<?>...values) {
568         super.notBeanClasses(values);
569         return this;
570      }
571
572      @Override /* Overridden from Builder */
573      public Builder notBeanPackages(String...values) {
574         super.notBeanPackages(values);
575         return this;
576      }
577
578      @Override /* Overridden from Builder */
579      public Builder propertyNamer(Class<?> on, Class<? extends org.apache.juneau.PropertyNamer> value) {
580         super.propertyNamer(on, value);
581         return this;
582      }
583
584      @Override /* Overridden from Builder */
585      public Builder propertyNamer(Class<? extends org.apache.juneau.PropertyNamer> value) {
586         super.propertyNamer(value);
587         return this;
588      }
589
590      @Override /* Overridden from Builder */
591      public Builder sortProperties() {
592         super.sortProperties();
593         return this;
594      }
595
596      @Override /* Overridden from Builder */
597      public Builder sortProperties(java.lang.Class<?>...on) {
598         super.sortProperties(on);
599         return this;
600      }
601
602      @Override /* Overridden from Builder */
603      public Builder stopClass(Class<?> on, Class<?> value) {
604         super.stopClass(on, value);
605         return this;
606      }
607
608      @Override /* Overridden from Builder */
609      public Builder streamCharset(Charset value) {
610         super.streamCharset(value);
611         return this;
612      }
613
614      @Override /* Overridden from Builder */
615      public Builder strict() {
616         super.strict();
617         return this;
618      }
619
620      @Override /* Overridden from Builder */
621      public Builder strict(boolean value) {
622         super.strict(value);
623         return this;
624      }
625
626      @Override /* Overridden from Builder */
627      public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction) {
628         super.swap(normalClass, swappedClass, swapFunction);
629         return this;
630      }
631
632      @Override /* Overridden from Builder */
633      public <T,S> Builder swap(Class<T> normalClass, Class<S> swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) {
634         super.swap(normalClass, swappedClass, swapFunction, unswapFunction);
635         return this;
636      }
637
638      @Override /* Overridden from Builder */
639      public Builder swaps(Class<?>...values) {
640         super.swaps(values);
641         return this;
642      }
643
644      @Override /* Overridden from Builder */
645      public Builder swaps(Object...values) {
646         super.swaps(values);
647         return this;
648      }
649
650      @Override /* Overridden from Builder */
651      public Builder timeZone(TimeZone value) {
652         super.timeZone(value);
653         return this;
654      }
655
656      @Override /* Overridden from Builder */
657      public Builder trimStrings() {
658         super.trimStrings();
659         return this;
660      }
661
662      @Override /* Overridden from Builder */
663      public Builder trimStrings(boolean value) {
664         super.trimStrings(value);
665         return this;
666      }
667
668      @Override /* Overridden from Builder */
669      public Builder type(Class<? extends org.apache.juneau.Context> value) {
670         super.type(value);
671         return this;
672      }
673
674      @Override /* Overridden from Builder */
675      public Builder typeName(Class<?> on, String value) {
676         super.typeName(on, value);
677         return this;
678      }
679
680      @Override /* Overridden from Builder */
681      public Builder typePropertyName(Class<?> on, String value) {
682         super.typePropertyName(on, value);
683         return this;
684      }
685
686      @Override /* Overridden from Builder */
687      public Builder typePropertyName(String value) {
688         super.typePropertyName(value);
689         return this;
690      }
691
692      @Override /* Overridden from Builder */
693      public Builder unbuffered() {
694         super.unbuffered();
695         return this;
696      }
697
698      @Override /* Overridden from Builder */
699      public Builder unbuffered(boolean value) {
700         super.unbuffered(value);
701         return this;
702      }
703
704      @Override /* Overridden from Builder */
705      public Builder useEnumNames() {
706         super.useEnumNames();
707         return this;
708      }
709
710      @Override /* Overridden from Builder */
711      public Builder useJavaBeanIntrospector() {
712         super.useJavaBeanIntrospector();
713         return this;
714      }
715
716      @Override /* Overridden from Builder */
717      public Builder validateEnd() {
718         super.validateEnd();
719         return this;
720      }
721
722      @Override /* Overridden from Builder */
723      public Builder validateEnd(boolean value) {
724         super.validateEnd(value);
725         return this;
726      }
727   }
728
729   /** Reusable instance of {@link OpenApiParser}. */
730   public static final OpenApiParser DEFAULT = new OpenApiParser(create());
731
732   /**
733    * Creates a new builder for this object.
734    *
735    * @return A new builder.
736    */
737   public static Builder create() {
738      return new Builder();
739   }
740
741   final HttpPartFormat format;
742   final HttpPartCollectionFormat collectionFormat;
743
744   private final Map<ClassMeta<?>,OpenApiClassMeta> openApiClassMetas = new ConcurrentHashMap<>();
745   private final Map<BeanPropertyMeta,OpenApiBeanPropertyMeta> openApiBeanPropertyMetas = new ConcurrentHashMap<>();
746
747   /**
748    * Constructor.
749    *
750    * @param builder The builder for this object.
751    */
752   public OpenApiParser(Builder builder) {
753      super(builder);
754      format = builder.format;
755      collectionFormat = builder.collectionFormat;
756   }
757
758   @Override /* Overridden from Context */
759   public Builder copy() {
760      return new Builder(this);
761   }
762
763   @Override /* Overridden from Context */
764   public OpenApiParserSession.Builder createSession() {
765      return OpenApiParserSession.create(this);
766   }
767
768   @Override /* Overridden from OpenApiMetaProvider */
769   public OpenApiBeanPropertyMeta getOpenApiBeanPropertyMeta(BeanPropertyMeta bpm) {
770      if (bpm == null)
771         return OpenApiBeanPropertyMeta.DEFAULT;
772      OpenApiBeanPropertyMeta m = openApiBeanPropertyMetas.get(bpm);
773      if (m == null) {
774         m = new OpenApiBeanPropertyMeta(bpm.getDelegateFor(), this);
775         openApiBeanPropertyMetas.put(bpm, m);
776      }
777      return m;
778   }
779
780   @Override /* Overridden from OpenApiMetaProvider */
781   public OpenApiClassMeta getOpenApiClassMeta(ClassMeta<?> cm) {
782      OpenApiClassMeta m = openApiClassMetas.get(cm);
783      if (m == null) {
784         m = new OpenApiClassMeta(cm, this);
785         openApiClassMetas.put(cm, m);
786      }
787      return m;
788   }
789
790   @Override /* Overridden from HttpPartParser */
791   public OpenApiParserSession getPartSession() { return OpenApiParserSession.create(this).build(); }
792
793   @Override /* Overridden from Context */
794   public OpenApiParserSession getSession() { return createSession().build(); }
795
796   /**
797    * Returns the default collection format to use when not otherwise specified via {@link Schema#collectionFormat()}
798    *
799    * @return The default collection format to use when not otherwise specified via {@link Schema#collectionFormat()}
800    */
801   protected final HttpPartCollectionFormat getCollectionFormat() { return collectionFormat; }
802
803   /**
804    * Returns the default format to use when not otherwise specified via {@link Schema#format()}
805    *
806    * @return The default format to use when not otherwise specified via {@link Schema#format()}
807    */
808   protected final HttpPartFormat getFormat() { return format; }
809}