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.internal;
018
019import static org.apache.juneau.commons.utils.Shorts.*;
020import static org.apache.juneau.commons.utils.StringUtils.*;
021import static org.apache.juneau.commons.utils.ThrowableUtils.*;
022
023import java.util.*;
024
025import org.apache.juneau.commons.collections.*;
026import org.apache.juneau.commons.conversion.*;
027import org.apache.juneau.marshall.parser.*;
028import org.apache.juneau.marshall.utils.*;
029
030/**
031 * Utility class for common type conversions and building typed collections and maps.
032 */
033public class ConverterUtils {
034
035   /**
036    * Prevents instantiation.
037    */
038   private ConverterUtils() {}
039
040   /**
041    * Converts an object to a Boolean.
042    *
043    * @param o The object to convert.
044    * @return The converted object.
045    */
046   public static Boolean toBoolean(Object o) {
047      return BasicConverter.INSTANCE.to(o, Boolean.class);
048   }
049
050   /**
051    * Converts an object to an Integer.
052    *
053    * @param o The object to convert.
054    * @return The converted object.
055    */
056   public static Integer toInteger(Object o) {
057      return BasicConverter.INSTANCE.to(o, Integer.class);
058   }
059
060   /**
061    * Converts an object to a Number.
062    *
063    * @param o The object to convert.
064    * @return The converted object.
065    */
066   public static Number toNumber(Object o) {
067      if (o == null)
068         return null;
069      if (o instanceof Number o2)
070         return o2;
071      try {
072         return parseNumber(o.toString(), null);
073      } catch (ParseException e) {
074         throw toRex(e);
075      }
076   }
077
078   /**
079    * Converts the specified object to the specified type.
080    *
081    * <p>
082    * Uses the full {@link MarshallingContextConverter} to support bean-aware conversions such as
083    * {@link Map} to bean, bean to bean, and {@link org.apache.juneau.marshall.swap.spi.ObjectSwap} transforms.
084    *
085    * @param <T> The class type to convert the value to.
086    * @param value The value to convert.
087    * @param type The class type to convert the value to.
088    * @return The converted value.
089    */
090   public static <T> T toType(Object value, Class<T> type) {
091      return MarshallingContextConverter.INSTANCE.to(value, type);
092   }
093
094   /**
095    * Converts the specified object to a {@link Lists} with elements of the specified type.
096    *
097    * <p>
098    * The input value can be any of the following:
099    * <ul>
100    *    <li>An array of objects convertible to the element type
101    *    <li>A {@link Collection} of objects convertible to the element type
102    *    <li>A single object convertible to the element type (creates a list with one element)
103    *    <li>A JSON array string that can be parsed into objects of the element type
104    * </ul>
105    *
106    * @param <T> The element type.
107    * @param value The value to convert. Can be <jk>null</jk> (no elements are added; an empty builder is returned).
108    * @param type The element type class.
109    * @return A new {@link Lists} containing the converted elements.
110    */
111   public static <T> Lists<T> toListBuilder(Object value, Class<T> type) {
112      return lb(type).elementFunction(o -> MarshallingContextConverter.INSTANCE.to(o, type)).addAny(value);
113   }
114
115   /**
116    * Converts the specified object to a {@link Maps} with keys and values of the specified types.
117    *
118    * <p>
119    * The input value can be any of the following:
120    * <ul>
121    *    <li>A {@link Map Map} with entries convertible to the key/value types
122    *    <li>A JSON object string that can be parsed into a map with the specified key/value types
123    *    <li>An object with bean properties that can be converted to map entries
124    * </ul>
125    *
126    * @param <K> The key type.
127    * @param <V> The value type.
128    * @param value The value to convert. Can be <jk>null</jk> (no entries are added; an empty builder is returned).
129    * @param keyType The key type class.
130    * @param valueType The value type class.
131    * @return A new {@link Maps} containing the converted entries.
132    */
133   public static <K,V> Maps<K,V> toMapBuilder(Object value, Class<K> keyType, Class<V> valueType) {
134      return mb(keyType, valueType)
135         .keyFunction(o -> MarshallingContextConverter.INSTANCE.to(o, keyType))
136         .valueFunction(o -> MarshallingContextConverter.INSTANCE.to(o, valueType))
137         .addAny(value);
138   }
139
140   /**
141    * Converts the specified object to a {@link Sets} with elements of the specified type.
142    *
143    * <p>
144    * The input value can be any of the following:
145    * <ul>
146    *    <li>An array of objects convertible to the element type
147    *    <li>A {@link Collection} of objects convertible to the element type
148    *    <li>A single object convertible to the element type (creates a set with one element)
149    *    <li>A JSON array string that can be parsed into objects of the element type
150    * </ul>
151    *
152    * <p>
153    * Duplicate elements (after conversion) will be automatically removed as per {@link Set Set} semantics.
154    *
155    * @param <T> The element type.
156    * @param value The value to convert. Can be <jk>null</jk> (no elements are added; an empty builder is returned).
157    * @param type The element type class.
158    * @return A new {@link Sets} containing the converted elements.
159    */
160   public static <T> Sets<T> toSetBuilder(Object value, Class<T> type) {
161      return stb(type).elementFunction(o -> MarshallingContextConverter.INSTANCE.to(o, type)).addAny(value);
162   }
163}