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.csv.*;
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 a {@link CsvSerializer} and {@link CsvParser} into a single class with convenience to/of methods.
028 *
029 * <h5 class='figure'>Examples:</h5>
030 * <p class='bjava'>
031 *    <jc>// Serialize a list of beans to CSV</jc>
032 *    List&lt;Person&gt; <jv>people</jv> = List.of(<jk>new</jk> Person(<js>"Alice"</js>, 30), <jk>new</jk> Person(<js>"Bob"</js>, 25));
033 *    String <jv>csv</jv> = Csv.<jsm>of</jsm>(<jv>people</jv>);
034 *
035 *    <jc>// Parse CSV into a list of beans</jc>
036 *    List&lt;Person&gt; <jv>parsed</jv> = Csv.<jsm>to</jsm>(<jv>csv</jv>, List.<jk>class</jk>, Person.<jk>class</jk>);
037 *
038 *    <jc>// Parse CSV into a list of maps</jc>
039 *    List&lt;Map&lt;String,String&gt;&gt; <jv>rows</jv> = Csv.<jsm>to</jsm>(<jv>csv</jv>, List.<jk>class</jk>, Map.<jk>class</jk>, String.<jk>class</jk>, String.<jk>class</jk>);
040 * </p>
041 * <p class='bjava'>
042 *    <jc>// Using instance methods</jc>
043 *    Csv <jv>m</jv> = Csv.<jsf>DEFAULT</jsf>;
044 *    <jv>csv</jv> = <jv>m</jv>.write(<jv>people</jv>);
045 *    <jv>parsed</jv> = <jv>m</jv>.read(<jv>csv</jv>, List.<jk>class</jk>, Person.<jk>class</jk>);
046 * </p>
047 *
048 * <h5 class='figure'>Example output (list of maps with a,b):</h5>
049 * <p class='bcode'>
050 *    a,b
051 *    foo,bar
052 * </p>
053 *
054 * <h5 class='figure'>Complex (list of beans with nested address, flattened):</h5>
055 * <p class='bcode'>
056 *    name,age,address_street,address_city,address_state,tags
057 *    Alice,30,123 Main St,Boston,MA,"a,b,c"
058 * </p>
059 *
060 * <p class='bjava'>
061 * <jc>// Using static shortcuts.</jc>
062 *    MyPojo <jv>myPojo</jv> = Csv.<jsm>to</jsm>(<jv>string</jv>, MyPojo.<jk>class</jk>);
063 *    String <jv>string</jv> = Csv.<jsm>of</jsm>(<jv>myPojo</jv>);
064 * </p>
065 *
066 * <h5 class='section'>See Also:</h5><ul>
067 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshallers">Marshallers</a>
068 * </ul>
069 */
070@SuppressWarnings({
071   "resource" // Cursor shortcut methods return Closeables owned by the caller; Eclipse JDT @Owning warning is by design.
072})
073public class Csv extends CharMarshaller {
074
075   /**
076    * Default reusable instance.
077    */
078   public static final Csv DEFAULT = new Csv();
079
080   /**
081    * Serializes a POJO to a <c>String</c> using the {@link #DEFAULT} marshaller.
082    *
083    * <p>
084    * A shortcut for calling <c><jsf>DEFAULT</jsf>.write(<jv>object</jv>)</c>.
085    *
086    * @param object The object to serialize.
087    * @return The serialized object.
088    * @throws SerializeException If a problem occurred trying to convert the output.
089    */
090   public static String of(Object object) throws SerializeException {
091      return DEFAULT.write(object);
092   }
093
094   /**
095    * Parses an input into the specified object type using the {@link #DEFAULT} marshaller.
096    *
097    * <p>
098    * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>)</c>.
099    *
100    * @param <T> The class type of the object being created.
101    * @param input The input.
102    * @param type The object type to create.
103    * @return The parsed object.
104    * @throws ParseException Malformed input encountered.
105    */
106   public static <T> T to(String input, Class<T> type) throws ParseException {
107      return DEFAULT.read(input, type);
108   }
109
110   /**
111    * Parses an input into the specified parameterized object type using the {@link #DEFAULT} marshaller.
112    *
113    * <p>
114    * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>, <jv>args</jv>)</c>.
115    *
116    * @param <T> The class type of the object to create.
117    * @param input The input.
118    * @param type The object type to create.
119    * @param args The type arguments of the class if it's a collection or map.
120    * @return The parsed object.
121    * @throws ParseException Malformed input encountered.
122    */
123   public static <T> T to(String input, Type type, Type... args) throws ParseException {
124      return DEFAULT.read(input, type, args);
125   }
126
127   /**
128    * Parses the contents of a {@link Reader} into the specified object type using the {@link #DEFAULT} marshaller.
129    *
130    * <p>
131    * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>)</c> that catches any
132    * {@link IOException} from the underlying stream and rethrows it as an unchecked {@link ParseException}, so the
133    * caller is not burdened with a checked exception.
134    *
135    * @param <T> The class type of the object being created.
136    * @param input The input reader.
137    * @param type The object type to create.
138    * @return The parsed object.
139    * @throws ParseException Malformed input encountered or an I/O error occurred on the underlying stream.
140    */
141   public static <T> T to(Reader input, Class<T> type) throws ParseException {
142      try {
143         return DEFAULT.read(input, type);
144      } catch (IOException e) {
145         throw new ParseException(e);
146      }
147   }
148
149   /**
150    * Parses the contents of a {@link Reader} into the specified parameterized object type using the {@link #DEFAULT} marshaller.
151    *
152    * <p>
153    * A shortcut for calling <c><jsf>DEFAULT</jsf>.read(<jv>input</jv>, <jv>type</jv>, <jv>args</jv>)</c> that catches any
154    * {@link IOException} from the underlying stream and rethrows it as an unchecked {@link ParseException}, so the
155    * caller is not burdened with a checked exception.
156    *
157    * @param <T> The class type of the object to create.
158    * @param input The input reader.
159    * @param type The object type to create.
160    * @param args The type arguments of the class if it's a collection or map.
161    * @return The parsed object.
162    * @throws ParseException Malformed input encountered or an I/O error occurred on the underlying stream.
163    */
164   public static <T> T to(Reader input, Type type, Type... args) throws ParseException {
165      try {
166         return DEFAULT.read(input, type, args);
167      } catch (IOException e) {
168         throw new ParseException(e);
169      }
170   }
171
172   /**
173    * Serializes a POJO to the specified {@link Writer} using the {@link #DEFAULT} marshaller.
174    *
175    * <p>
176    * A shortcut for calling <c><jsf>DEFAULT</jsf>.write(<jv>object</jv>, <jv>output</jv>)</c> that catches any
177    * {@link IOException} from the underlying stream and rethrows it as an unchecked {@link SerializeException}, so the
178    * caller is not burdened with a checked exception.
179    *
180    * @param object The object to serialize.
181    * @param output The writer to serialize to.
182    * @throws SerializeException If a problem occurred trying to convert the output or an I/O error occurred on the underlying stream.
183    */
184   public static void of(Object object, Writer output) throws SerializeException {
185      try {
186         DEFAULT.write(object, output);
187      } catch (IOException e) {
188         throw new SerializeException(e);
189      }
190   }
191
192   /**
193    * Opens a low-level {@link RecordReader} cursor over the specified input using the {@link #DEFAULT} marshaller.
194    *
195    * <p>
196    * A shortcut for calling <c><jsf>DEFAULT</jsf>.readRecords(<jv>input</jv>)</c>.
197    *
198    * @param input The input.
199    * @return A new {@link RecordReader}.
200    * @throws IOException If a problem occurred opening the underlying input.
201    */
202   public static RecordReader toRecords(Object input) throws IOException {
203      return DEFAULT.readRecords(input);
204   }
205
206   /**
207    * Opens a low-level {@link RecordWriter} cursor over the specified output using the {@link #DEFAULT} marshaller.
208    *
209    * <p>
210    * A shortcut for calling <c><jsf>DEFAULT</jsf>.writeRecords(<jv>output</jv>)</c>.
211    *
212    * @param output The output.
213    * @return A new {@link RecordWriter}.
214    * @throws IOException If a problem occurred opening the underlying output.
215    */
216   public static RecordWriter ofRecords(Object output) throws IOException {
217      return DEFAULT.writeRecords(output);
218   }
219
220
221   /**
222    * Constructor.
223    *
224    * <p>
225    * Uses {@link CsvSerializer#DEFAULT} and {@link CsvParser#DEFAULT}.
226    */
227   public Csv() {
228      this(CsvSerializer.DEFAULT, CsvParser.DEFAULT);
229   }
230
231   /**
232    * Constructor.
233    *
234    * @param s
235    *    The serializer to use for serializing output.
236    *    <br>Must not be <jk>null</jk>.
237    * @param p
238    *    The parser to use for parsing input.
239    *    <br>Must not be <jk>null</jk>.
240    */
241   public Csv(CsvSerializer s, CsvParser p) {
242      super(s, p);
243   }
244}