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.marshall.marshaller;
018
019import org.apache.juneau.marshall.parquet.*;
020import java.io.*;
021import java.lang.reflect.*;
022import org.apache.juneau.marshall.parser.*;
023import org.apache.juneau.marshall.serializer.*;
024import org.apache.juneau.marshall.stream.*;
025
026/**
027 * A pairing of {@link ParquetSerializer} and {@link ParquetParser} for Apache Parquet binary format.
028 *
029 * <h5 class='figure'>Examples:</h5>
030 * <p class='bjava'>
031 *    <jc>// Serialize a list of beans to Parquet bytes</jc>
032 *    List&lt;MyBean&gt; <jv>beans</jv> = List.<jsm>of</jsm>(new MyBean(...), new MyBean(...));
033 *    byte[] <jv>bytes</jv> = Parquet.<jsm>of</jsm>(<jv>beans</jv>);
034 *
035 *    <jc>// Parse Parquet bytes back into a list of beans</jc>
036 *    List&lt;MyBean&gt; <jv>parsed</jv> = Parquet.<jsm>to</jsm>(<jv>bytes</jv>, MyBean.<jk>class</jk>);
037 * </p>
038 * <p class='bjava'>
039 *    <jc>// Using instance methods</jc>
040 *    Parquet <jv>m</jv> = Parquet.<jsf>DEFAULT</jsf>;
041 *    <jv>bytes</jv> = <jv>m</jv>.write(<jv>beans</jv>);
042 *    <jv>parsed</jv> = <jv>m</jv>.read(<jv>bytes</jv>, MyBean.<jk>class</jk>);
043 * </p>
044 *
045 * <p>Output is binary (<jk>byte</jk>[]), Apache Parquet columnar format.</p>
046 *
047 * <p class='warnbox'>
048 *    <b>Note:</b> Parquet is <b>collection-oriented</b>. The serializer accepts a
049 *    {@link java.util.Collection} or array of beans (each bean is one row). A single
050 *    bean is automatically wrapped in a one-element list. The parser <em>always</em>
051 *    returns a {@code List<T>}, never a bare {@code T}.
052 * </p>
053 *
054 * <p class='bjava'>
055 * <jc>// Using static shortcuts.</jc>
056 *    MyPojo <jv>myPojo</jv> = Parquet.<jsm>to</jsm>(<jv>bytes</jv>, MyPojo.<jk>class</jk>);
057 *    <jk>byte</jk>[] <jv>bytes</jv> = Parquet.<jsm>of</jsm>(<jv>myPojo</jv>);
058 * </p>
059 *
060 * <h5 class='section'>See Also:</h5><ul>
061 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Parquet">Parquet Basics</a>
062 *    <li class='link'>{doc jm.Marshallers}
063 * </ul>
064 */
065@SuppressWarnings({
066   "resource" // Cursor shortcut methods return Closeables owned by the caller; Eclipse JDT @Owning warning is by design.
067})
068public class Parquet extends StreamMarshaller {
069
070   /** Default reusable instance. */
071   public static final Parquet DEFAULT = new Parquet();
072
073   /**
074    * Serializes a POJO to a <code><jk>byte</jk>[]</code> using the {@link #DEFAULT} marshaller.
075    *
076    * <p>
077    * A shortcut for calling <c><jsf>DEFAULT</jsf>.write(<jv>object</jv>)</c>.
078    *
079    * @param object The object to serialize.
080    * @return The serialized object.
081    * @throws SerializeException If a problem occurred trying to convert the output.
082    */
083   public static byte[] of(Object object) throws SerializeException {
084      return DEFAULT.write(object);
085   }
086
087   /**
088    * Parses an input into the specified object type using the {@link #DEFAULT} marshaller.
089    *
090    * <p>
091    * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>)</c>.
092    *
093    * @param <T> The class type of the object being created.
094    * @param input The input.
095    * @param type The object type to create.
096    * @return The parsed object.
097    * @throws ParseException Malformed input encountered.
098    */
099   public static <T> T to(byte[] input, Class<T> type) throws ParseException {
100      return DEFAULT.read(input, type);
101   }
102
103   /**
104    * Parses an input into the specified parameterized object type using the {@link #DEFAULT} marshaller.
105    *
106    * <p>
107    * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>, <jv>args</jv>)</c>.
108    *
109    * @param <T> The class type of the object to create.
110    * @param input The input.
111    * @param type The object type to create.
112    * @param args The type arguments of the class if it's a collection or map.
113    * @return The parsed object.
114    * @throws ParseException Malformed input encountered.
115    */
116   public static <T> T to(byte[] input, Type type, Type... args) throws ParseException {
117      return DEFAULT.read(input, type, args);
118   }
119
120   /**
121    * Parses the contents of an {@link InputStream} into the specified object type using the {@link #DEFAULT} marshaller.
122    *
123    * <p>
124    * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>)</c> that catches any
125    * {@link IOException} from the underlying stream and rethrows it as an unchecked {@link ParseException}, so the
126    * caller is not burdened with a checked exception.
127    *
128    * @param <T> The class type of the object being created.
129    * @param input The input stream.
130    * @param type The object type to create.
131    * @return The parsed object.
132    * @throws ParseException Malformed input encountered or an I/O error occurred on the underlying stream.
133    */
134   public static <T> T to(InputStream input, Class<T> type) throws ParseException {
135      try {
136         return DEFAULT.read(input, type);
137      } catch (IOException e) {
138         throw new ParseException(e);
139      }
140   }
141
142   /**
143    * Parses the contents of an {@link InputStream} into the specified parameterized object type using the {@link #DEFAULT} marshaller.
144    *
145    * <p>
146    * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>, <jv>args</jv>)</c> that catches any
147    * {@link IOException} from the underlying stream and rethrows it as an unchecked {@link ParseException}, so the
148    * caller is not burdened with a checked exception.
149    *
150    * @param <T> The class type of the object to create.
151    * @param input The input stream.
152    * @param type The object type to create.
153    * @param args The type arguments of the class if it's a collection or map.
154    * @return The parsed object.
155    * @throws ParseException Malformed input encountered or an I/O error occurred on the underlying stream.
156    */
157   public static <T> T to(InputStream input, Type type, Type... args) throws ParseException {
158      try {
159         return DEFAULT.read(input, type, args);
160      } catch (IOException e) {
161         throw new ParseException(e);
162      }
163   }
164
165   /**
166    * Serializes a POJO to the specified {@link OutputStream} using the {@link #DEFAULT} marshaller.
167    *
168    * <p>
169    * A shortcut for calling <c><jsf>DEFAULT</jsf>.write(<jv>object</jv>, <jv>output</jv>)</c> that catches any
170    * {@link IOException} from the underlying stream and rethrows it as an unchecked {@link SerializeException}, so the
171    * caller is not burdened with a checked exception.
172    *
173    * @param object The object to serialize.
174    * @param output The output stream to serialize to.
175    * @throws SerializeException If a problem occurred trying to convert the output or an I/O error occurred on the underlying stream.
176    */
177   public static void of(Object object, OutputStream output) throws SerializeException {
178      try {
179         DEFAULT.write(object, output);
180      } catch (IOException e) {
181         throw new SerializeException(e);
182      }
183   }
184
185   /**
186    * Opens a low-level {@link RecordReader} cursor over the specified input using the {@link #DEFAULT} marshaller.
187    *
188    * <p>
189    * A shortcut for calling <c><jsf>DEFAULT</jsf>.readRecords(<jv>input</jv>)</c>.
190    *
191    * @param input The input.
192    * @return A new {@link RecordReader}.
193    * @throws IOException If a problem occurred opening the underlying input.
194    */
195   public static RecordReader toRecords(Object input) throws IOException {
196      return DEFAULT.readRecords(input);
197   }
198
199   /**
200    * Opens a low-level {@link RecordWriter} cursor over the specified output using the {@link #DEFAULT} marshaller.
201    *
202    * <p>
203    * A shortcut for calling <c><jsf>DEFAULT</jsf>.writeRecords(<jv>output</jv>)</c>.
204    *
205    * @param output The output.
206    * @return A new {@link RecordWriter}.
207    * @throws IOException If a problem occurred opening the underlying output.
208    */
209   public static RecordWriter ofRecords(Object output) throws IOException {
210      return DEFAULT.writeRecords(output);
211   }
212
213   /**
214    * Opens a {@link RecordReader} that yields each element of a top-level wire array using the {@link #DEFAULT} marshaller.
215    *
216    * <p>
217    * A shortcut for calling <c><jsf>DEFAULT</jsf>.readArrayRecords(<jv>input</jv>)</c>.
218    *
219    * @param input The input.
220    * @return A new {@link RecordReader}.
221    * @throws IOException If a problem occurred opening the underlying input.
222    */
223   public static RecordReader toArrayRecords(Object input) throws IOException {
224      return DEFAULT.readArrayRecords(input);
225   }
226
227   /**
228    * Opens a {@link RecordWriter} that wraps each written value as one element of a top-level wire array using the {@link #DEFAULT} marshaller.
229    *
230    * <p>
231    * A shortcut for calling <c><jsf>DEFAULT</jsf>.writeArrayRecords(<jv>output</jv>)</c>.
232    *
233    * @param output The output.
234    * @return A new {@link RecordWriter}.
235    * @throws IOException If a problem occurred opening the underlying output.
236    */
237   public static RecordWriter ofArrayRecords(Object output) throws IOException {
238      return DEFAULT.writeArrayRecords(output);
239   }
240
241   /**
242    * Constructor using default serializer and parser.
243    */
244   public Parquet() {
245      this(ParquetSerializer.DEFAULT, ParquetParser.DEFAULT);
246   }
247
248   /**
249    * Constructor.
250    *
251    * @param s The serializer.
252    * @param p The parser.
253    */
254   public Parquet(ParquetSerializer s, ParquetParser p) {
255      super(s, p);
256   }
257}