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.markdown.*;
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 MarkdownSerializer} and {@link MarkdownParser} into a single class with convenience to/of methods.
028 *
029 * <p>
030 * The general idea is to combine a single serializer and parser inside a simplified API for serializing and parsing POJOs.
031 *
032 * <h5 class='figure'>Examples:</h5>
033 * <p class='bjava'>
034 *    <jc>// Using instance.</jc>
035 *    Markdown <jv>md</jv> = <jk>new</jk> Markdown();
036 *    MyPojo <jv>myPojo</jv> = <jv>md</jv>.read(<jv>string</jv>, MyPojo.<jk>class</jk>);
037 *    String <jv>string</jv> = <jv>md</jv>.write(<jv>myPojo</jv>);
038 * </p>
039 * <p class='bjava'>
040 *    <jc>// Using DEFAULT instance.</jc>
041 *    MyPojo <jv>myPojo</jv> = Markdown.<jsf>DEFAULT</jsf>.read(<jv>string</jv>, MyPojo.<jk>class</jk>);
042 *    String <jv>string</jv> = Markdown.<jsf>DEFAULT</jsf>.write(<jv>myPojo</jv>);
043 * </p>
044 *
045 * <h5 class='figure'>Example output (bean with name/age):</h5>
046 * <p class='bcode'>
047 *    | Property | Value |
048 *    |---|---|
049 *    | name | Alice |
050 *    | age | 30 |
051 * </p>
052 *
053 * <p class='bjava'>
054 * <jc>// Using static shortcuts.</jc>
055 *    MyPojo <jv>myPojo</jv> = Markdown.<jsm>to</jsm>(<jv>string</jv>, MyPojo.<jk>class</jk>);
056 *    String <jv>string</jv> = Markdown.<jsm>of</jsm>(<jv>myPojo</jv>);
057 * </p>
058 *
059 * <h5 class='section'>See Also:</h5><ul>
060 *    <li class='link'><a class="doclink" href="https://juneau.apache.org/docs/topics/Marshallers">Marshallers</a>
061 * </ul>
062 */
063@SuppressWarnings({
064   "resource" // Cursor shortcut methods return Closeables owned by the caller; Eclipse JDT @Owning warning is by design.
065})
066public class Markdown extends CharMarshaller {
067
068   /**
069    * Default reusable instance using fragment-mode serializer and parser.
070    */
071   public static final Markdown DEFAULT = new Markdown();
072
073   /**
074    * Serializes a POJO to a <c>String</c> 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 String 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(String 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(String input, Type type, Type... args) throws ParseException {
117      return DEFAULT.read(input, type, args);
118   }
119
120   /**
121    * Parses the contents of a {@link Reader} 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 reader.
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(Reader 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 a {@link Reader} 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 reader.
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(Reader 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 Writer} 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 writer 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, Writer 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    * Constructor.
215    *
216    * <p>
217    * Uses {@link MarkdownSerializer#DEFAULT} and {@link MarkdownParser#DEFAULT}.
218    */
219   public Markdown() {
220      this(MarkdownSerializer.DEFAULT, MarkdownParser.DEFAULT);
221   }
222
223   /**
224    * Constructor.
225    *
226    * @param s
227    *    The serializer to use for serializing output.
228    *    <br>Must not be <jk>null</jk>.
229    * @param p
230    *    The parser to use for parsing input.
231    *    <br>Must not be <jk>null</jk>.
232    */
233   public Markdown(MarkdownSerializer s, MarkdownParser p) {
234      super(s, p);
235   }
236}