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.marshaller;
014
015import java.io.*;
016import java.lang.reflect.*;
017import java.nio.charset.*;
018
019import org.apache.juneau.*;
020import org.apache.juneau.httppart.*;
021import org.apache.juneau.oapi.*;
022import org.apache.juneau.parser.*;
023import org.apache.juneau.serializer.*;
024
025/**
026 * A pairing of a {@link OpenApiSerializer} and {@link OpenApiParser} into a single class with convenience read/write methods.
027 *
028 * <p>
029 *    The general idea is to combine a single serializer and parser inside a simplified API for reading and writing POJOs.
030 *
031 * <h5 class='figure'>Examples:</h5>
032 * <p class='bjava'>
033 *    <jc>// Using instance.</jc>
034 *    OpenApi <jv>oapi</jv> = <jk>new</jk> OpenApi();
035 *    MyPojo <jv>myPojo</jv> = <jv>oapi</jv>.read(<jv>string</jv>, MyPojo.<jk>class</jk>);
036 *    String <jv>string</jv> = <jv>oapi</jv>.write(<jv>myPojo</jv>);
037 * </p>
038 * <p class='bjava'>
039 * <jc>// Using DEFAULT instance.</jc>
040 *    MyPojo <jv>myPojo</jv> = OpenApi.<jsf>DEFAULT</jsf>.read(<jv>string</jv>, MyPojo.<jk>class</jk>);
041 *    String <jv>string</jv> = OpenApi.<jsf>DEFAULT</jsf>.write(<jv>myPojo</jv>);
042 * </p>
043 *
044 * <h5 class='section'>See Also:</h5><ul>
045 *    <li class='link'><a class="doclink" href="../../../../index.html#jm.Marshallers">Marshallers</a>
046 * </ul>
047 */
048public class OpenApi extends CharMarshaller {
049
050   //-----------------------------------------------------------------------------------------------------------------
051   // Static
052   //-----------------------------------------------------------------------------------------------------------------
053
054   /**
055    * Default reusable instance.
056    */
057   public static final OpenApi DEFAULT = new OpenApi();
058
059   //-----------------------------------------------------------------------------------------------------------------
060   // Instance
061   //-----------------------------------------------------------------------------------------------------------------
062
063   private final OpenApiSerializer s;
064   private final OpenApiParser p;
065
066   /**
067    * Constructor.
068    *
069    * @param s
070    *    The serializer to use for serializing output.
071    *    <br>Must not be <jk>null</jk>.
072    * @param p
073    *    The parser to use for parsing input.
074    *    <br>Must not be <jk>null</jk>.
075    */
076   public OpenApi(OpenApiSerializer s, OpenApiParser p) {
077      super(s, p);
078      this.s = s;
079      this.p = p;
080   }
081
082   /**
083    * Constructor.
084    *
085    * <p>
086    * Uses {@link OpenApiSerializer#DEFAULT} and {@link OpenApiParser#DEFAULT}.
087    */
088   public OpenApi() {
089      this(OpenApiSerializer.DEFAULT, OpenApiParser.DEFAULT);
090   }
091
092   /**
093    * Parses an OpenApi input string to the specified type.
094    *
095    * <p>
096    * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>)</c>.
097    *
098    * @param <T> The class type of the object being created.
099    * @param input The input.
100    * @param type The object type to create.
101    * @return The parsed object.
102    * @throws ParseException Malformed input encountered.
103    */
104   public static <T> T to(String input, Class<T> type) throws ParseException {
105      return DEFAULT.read(input, type);
106   }
107
108   /**
109    * Parses an OpenApi input object to the specified Java type.
110    *
111    * <p>
112    * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>)</c>.
113    *
114    * @param <T> The class type of the object being created.
115    * @param input
116    *    The input.
117    *    <br>Can be any of the following types:
118    *    <ul>
119    *       <li><jk>null</jk>
120    *       <li>{@link Reader}
121    *       <li>{@link CharSequence}
122    *       <li>{@link InputStream} containing UTF-8 encoded text (or charset defined by
123    *          {@link org.apache.juneau.parser.ReaderParser.Builder#streamCharset(Charset)} property value).
124    *       <li><code><jk>byte</jk>[]</code> containing UTF-8 encoded text (or charset defined by
125    *          {@link org.apache.juneau.parser.ReaderParser.Builder#streamCharset(Charset)} property value).
126    *       <li>{@link File} containing system encoded text (or charset defined by
127    *          {@link org.apache.juneau.parser.ReaderParser.Builder#fileCharset(Charset)} property value).
128    *    </ul>
129    * @param type The object type to create.
130    * @return The parsed object.
131    * @throws ParseException Malformed input encountered.
132    * @throws IOException Thrown by underlying stream.
133    */
134   public static <T> T to(Object input, Class<T> type) throws ParseException, IOException {
135      return DEFAULT.read(input, type);
136   }
137
138   /**
139    * Parses an OpenApi input object to the specified Java type.
140    *
141    * <p>
142    * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>)</c>.
143    *
144    * @param <T> The class type of the object being created.
145    * @param schema The part type schema.  Can be <jk>null</jk>.
146    * @param input
147    *    The input.
148    * @param type The object type to create.
149    * @return The parsed object.
150    * @throws ParseException Malformed input encountered.
151    * @throws IOException Thrown by underlying stream.
152    */
153   public static <T> T to(HttpPartSchema schema, String input, Class<T> type) throws ParseException, IOException {
154      return DEFAULT.p.parse(HttpPartType.ANY, schema, input, type);
155   }
156
157   /**
158    * Parses an OpenApi input string to the specified Java type.
159    *
160    * <p>
161    * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>, <jv>args</jv>)</c>.
162    *
163    * @param <T> The class type of the object to create.
164    * @param input The input.
165    * @param type
166    *    The object type to create.
167    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
168    * @param args
169    *    The type arguments of the class if it's a collection or map.
170    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
171    *    <br>Ignored if the main type is not a map or collection.
172    * @return The parsed object.
173    * @throws ParseException Malformed input encountered.
174    * @see BeanSession#getClassMeta(Type,Type...) for argument syntax for maps and collections.
175    */
176   public static <T> T to(String input, Type type, Type...args) throws ParseException {
177      return DEFAULT.read(input, type, args);
178   }
179
180   /**
181    * Parses an OpenApi input object to the specified Java type.
182    *
183    * <p>
184    * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>, <jv>args</jv>)</c>.
185    *
186    * @param <T> The class type of the object to create.
187    * @param input
188    *    The input.
189    *    <br>Can be any of the following types:
190    *    <ul>
191    *       <li><jk>null</jk>
192    *       <li>{@link Reader}
193    *       <li>{@link CharSequence}
194    *       <li>{@link InputStream} containing UTF-8 encoded text (or charset defined by
195    *          {@link org.apache.juneau.parser.ReaderParser.Builder#streamCharset(Charset)} property value).
196    *       <li><code><jk>byte</jk>[]</code> containing UTF-8 encoded text (or charset defined by
197    *          {@link org.apache.juneau.parser.ReaderParser.Builder#streamCharset(Charset)} property value).
198    *       <li>{@link File} containing system encoded text (or charset defined by
199    *          {@link org.apache.juneau.parser.ReaderParser.Builder#fileCharset(Charset)} property value).
200    *    </ul>
201    * @param type
202    *    The object type to create.
203    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
204    * @param args
205    *    The type arguments of the class if it's a collection or map.
206    *    <br>Can be any of the following: {@link ClassMeta}, {@link Class}, {@link ParameterizedType}, {@link GenericArrayType}
207    *    <br>Ignored if the main type is not a map or collection.
208    * @return The parsed object.
209    * @throws ParseException Malformed input encountered.
210    * @throws IOException Thrown by underlying stream.
211    * @see BeanSession#getClassMeta(Type,Type...) for argument syntax for maps and collections.
212    */
213   public static <T> T to(Object input, Type type, Type...args) throws ParseException, IOException {
214      return DEFAULT.read(input, type, args);
215   }
216
217   /**
218    * Serializes a Java object to an OpenApi string.
219    *
220    * <p>
221    * A shortcut for calling <c><jsf>DEFAULT</jsf>.write(<jv>object</jv>)</c>.
222    *
223    * @param object The object to serialize.
224    * @return
225    *    The serialized object.
226    * @throws SerializeException If a problem occurred trying to convert the output.
227    */
228   public static String of(Object object) throws SerializeException {
229      return DEFAULT.write(object);
230   }
231
232   /**
233    * Serializes a Java object to an OpenApi output.
234    *
235    * <p>
236    * A shortcut for calling <c><jsf>DEFAULT</jsf>.write(<jv>output</jv>)</c>.
237    *
238    * @param object The object to serialize.
239    * @param output
240    *    The output object.
241    *    <br>Can be any of the following types:
242    *    <ul>
243    *       <li>{@link Writer}
244    *       <li>{@link OutputStream} - Output will be written as UTF-8 encoded stream.
245    *       <li>{@link File} - Output will be written as system-default encoded stream.
246    *       <li>{@link StringBuilder} - Output will be written to the specified string builder.
247    *    </ul>
248    * @return The output object.
249    * @throws SerializeException If a problem occurred trying to convert the output.
250    * @throws IOException Thrown by underlying stream.
251    */
252   public static Object of(Object object, Object output) throws SerializeException, IOException {
253      DEFAULT.write(object, output);
254      return output;
255   }
256
257   /**
258    * Serializes a Java object to an OpenApi output.
259    *
260    * <p>
261    * A shortcut for calling <c><jsf>DEFAULT</jsf>.write(<jv>output</jv>)</c>.
262    * @param schema The part schema.  Can be <jk>null</jk>.
263    * @param object The object to serialize.
264    * @return The output object.
265    * @throws SerializeException If a problem occurred trying to convert the output.
266    */
267   public static String of(HttpPartSchema schema, Object object) throws SerializeException {
268      return DEFAULT.s.serialize(HttpPartType.ANY, schema, object);
269   }
270}