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