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.oapi;
014
015import java.util.*;
016import java.util.concurrent.*;
017
018import org.apache.juneau.*;
019import org.apache.juneau.annotation.*;
020import org.apache.juneau.collections.*;
021import org.apache.juneau.httppart.*;
022import org.apache.juneau.jsonschema.annotation.*;
023import org.apache.juneau.parser.*;
024import org.apache.juneau.uon.*;
025
026/**
027 * OpenAPI part parser.
028 *
029 * <ul class='seealso'>
030 *    <li class='link'>{@doc OpenApiParsers}
031 * </ul>
032 */
033@ConfigurableContext
034public class OpenApiParser extends UonParser implements OpenApiMetaProvider, OpenApiCommon {
035
036   //-------------------------------------------------------------------------------------------------------------------
037   // Configurable properties
038   //-------------------------------------------------------------------------------------------------------------------
039
040   static final String PREFIX = "OpenApiParser";
041
042   //-------------------------------------------------------------------------------------------------------------------
043   // Predefined instances
044   //-------------------------------------------------------------------------------------------------------------------
045
046   /** Reusable instance of {@link OpenApiParser}. */
047   public static final OpenApiParser DEFAULT = new OpenApiParser(PropertyStore.DEFAULT);
048
049
050   //-------------------------------------------------------------------------------------------------------------------
051   // Instance
052   //-------------------------------------------------------------------------------------------------------------------
053
054   private final Map<ClassMeta<?>,OpenApiClassMeta> openApiClassMetas = new ConcurrentHashMap<>();
055   private final Map<BeanPropertyMeta,OpenApiBeanPropertyMeta> openApiBeanPropertyMetas = new ConcurrentHashMap<>();
056   private final HttpPartFormat format;
057   private final HttpPartCollectionFormat collectionFormat;
058
059   /**
060    * Constructor.
061    *
062    * @param ps The property store containing all the settings for this object.
063    */
064   public OpenApiParser(PropertyStore ps) {
065      this(ps, "text/openapi");
066   }
067
068   /**
069    * Constructor.
070    *
071    * @param ps
072    *    The property store containing all the settings for this object.
073    * @param consumes
074    *    The list of media types that this parser consumes (e.g. <js>"application/json"</js>, <js>"*&#8203;/json"</js>).
075    */
076   public OpenApiParser(PropertyStore ps, String...consumes) {
077      super(ps, consumes);
078      format = getProperty(OAPI_format, HttpPartFormat.class, HttpPartFormat.NO_FORMAT);
079      collectionFormat = getProperty(OAPI_collectionFormat, HttpPartCollectionFormat.class, HttpPartCollectionFormat.NO_COLLECTION_FORMAT);
080   }
081
082   @Override /* Context */
083   public OpenApiParserBuilder builder() {
084      return new OpenApiParserBuilder(getPropertyStore());
085   }
086
087   /**
088    * Instantiates a new clean-slate {@link OpenApiParserBuilder} object.
089    *
090    * <p>
091    * This is equivalent to simply calling <code><jk>new</jk> UonPartParserBuilder()</code>.
092    *
093    * <p>
094    * Note that this method creates a builder initialized to all default settings, whereas {@link #builder()} copies
095    * the settings of the object called on.
096    *
097    * @return A new {@link OpenApiParserBuilder} object.
098    */
099   public static OpenApiParserBuilder create() {
100      return new OpenApiParserBuilder();
101   }
102
103   //-------------------------------------------------------------------------------------------------------------------
104   // Entry point methods
105   //-------------------------------------------------------------------------------------------------------------------
106
107   @Override
108   public OpenApiParserSession createSession() {
109      return new OpenApiParserSession(this, ParserSessionArgs.DEFAULT);
110   }
111
112   @Override
113   public OpenApiParserSession createSession(ParserSessionArgs args) {
114      return new OpenApiParserSession(this, args);
115   }
116
117   @Override
118   public OpenApiParserSession createPartSession(ParserSessionArgs args) {
119      return new OpenApiParserSession(this, args);
120   }
121
122   //-----------------------------------------------------------------------------------------------------------------
123   // Extended metadata
124   //-----------------------------------------------------------------------------------------------------------------
125
126   @Override /* OpenApiMetaProvider */
127   public OpenApiClassMeta getOpenApiClassMeta(ClassMeta<?> cm) {
128      OpenApiClassMeta m = openApiClassMetas.get(cm);
129      if (m == null) {
130         m = new OpenApiClassMeta(cm, this);
131         openApiClassMetas.put(cm, m);
132      }
133      return m;
134   }
135
136   @Override /* OpenApiMetaProvider */
137   public OpenApiBeanPropertyMeta getOpenApiBeanPropertyMeta(BeanPropertyMeta bpm) {
138      if (bpm == null)
139         return OpenApiBeanPropertyMeta.DEFAULT;
140      OpenApiBeanPropertyMeta m = openApiBeanPropertyMetas.get(bpm);
141      if (m == null) {
142         m = new OpenApiBeanPropertyMeta(bpm.getDelegateFor(), this);
143         openApiBeanPropertyMetas.put(bpm, m);
144      }
145      return m;
146   }
147
148   //-----------------------------------------------------------------------------------------------------------------
149   // Properties
150   //-----------------------------------------------------------------------------------------------------------------
151
152   /**
153    * Returns the default format to use when not otherwise specified via {@link Schema#format()}
154    *
155    * @return The default format to use when not otherwise specified via {@link Schema#format()}
156    */
157   protected final HttpPartFormat getFormat() {
158      return format;
159   }
160
161   /**
162    * Returns the default collection format to use when not otherwise specified via {@link Schema#collectionFormat()}
163    *
164    * @return The default collection format to use when not otherwise specified via {@link Schema#collectionFormat()}
165    */
166   protected final HttpPartCollectionFormat getCollectionFormat() {
167      return collectionFormat;
168   }
169
170   //-----------------------------------------------------------------------------------------------------------------
171   // Other methods
172   //-----------------------------------------------------------------------------------------------------------------
173
174   @Override /* Context */
175   public OMap toMap() {
176      return super.toMap()
177         .a("OpenApiParser", new DefaultFilteringOMap()
178         );
179   }
180}