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