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.utils;
018
019import java.lang.reflect.*;
020
021import org.apache.juneau.commons.conversion.*;
022import org.apache.juneau.marshall.*;
023
024/**
025 * Generic object converter implementation.
026 *
027 * <p>
028 * A simple implementation of the {@link Converter} interface that delegates to the default
029 * {@link MarshallingContext} session for type conversion.
030 *
031 * <p>
032 * This converter provides a convenient way to convert objects between different types using
033 * the same conversion logic that's used throughout the Juneau framework.
034 *
035 * <h5 class='section'>Example:</h5>
036 * <p class='bjava'>
037 *    <jc>// Convert a string to an integer</jc>
038 *    Integer <jv>result</jv> = GenericConverter.INSTANCE.convertTo(Integer.<jk>class</jk>, <js>"123"</js>);
039 *    <jc>// result = 123</jc>
040 *
041 *    <jc>// Convert a map to a bean</jc>
042 *    MyBean <jv>bean</jv> = GenericConverter.INSTANCE.convertTo(MyBean.<jk>class</jk>, <jv>map</jv>);
043 * </p>
044 *
045 * <h5 class='section'>Thread Safety:</h5>
046 * <p>
047 * This class is thread-safe. The singleton instance can be safely shared across multiple threads.
048 *
049 * <h5 class='section'>See Also:</h5><ul>
050 *    <li class='jm'>{@link Converter}
051 *    <li class='jm'>{@link MarshallingContext#DEFAULT_SESSION}
052 *    <li class='jm'>{@link MarshallingSession#convertToType(Object, Class)}
053 * </ul>
054 */
055@SuppressWarnings({
056   "java:S6541", // Stateless converter, singleton for convenience
057   "java:S6548" // Singleton pattern is intentional; INSTANCE is a stateless, thread-safe shared converter
058})
059public class MarshallingContextConverter implements Converter {
060
061   /**
062    * Singleton instance of the generic converter.
063    *
064    * <p>
065    * This instance can be safely shared across multiple threads and reused for all conversion operations.
066    */
067   public static final MarshallingContextConverter INSTANCE = new MarshallingContextConverter();
068
069   /**
070    * Constructor.
071    */
072   private MarshallingContextConverter() {}
073
074   /**
075    * Converts the specified object to the specified type.
076    *
077    * <p>
078    * This method delegates to the default {@link MarshallingContext} session for the actual conversion logic.
079    * It supports all the same conversion types that are supported by the framework's bean conversion system.
080    *
081    * <p>
082    * Supported conversions include:
083    * <ul>
084    *    <li>Primitive types and their wrapper classes
085    *    <li>String to Number conversions
086    *    <li>Map to Bean conversions
087    *    <li>Collection to Array conversions
088    *    <li>Enum conversions
089    *    <li>Object swap conversions
090    *    <li>And many more...
091    * </ul>
092    * @param o The object to convert.
093    * @param type The target class type.
094    *
095    * @param <T> The target type to convert to.
096    * @return The converted object, or <jk>null</jk> if the input object is <jk>null</jk>.
097    * @throws InvalidDataConversionException If the object cannot be converted to the specified type.
098    */
099   @Override
100   public <T> T to(Object o, Class<T> type) {
101      return MarshallingContext.DEFAULT_SESSION.convertToType(o, type);
102   }
103
104   /**
105    * Converts the specified object to the specified parameterized type.
106    *
107    * <p>
108    * This method delegates to the default {@link MarshallingContext} session for the actual conversion logic,
109    * supporting complex parameterized types such as collections and maps.
110    *
111    * @param o The object to convert.
112    * @param mainType The main type to convert to.
113    * @param args The type parameters of the main type.
114    * @param <T> The target type to convert to.
115    * @return The converted object, or <jk>null</jk> if the input object is <jk>null</jk>.
116    * @throws InvalidDataConversionException If the object cannot be converted to the specified type.
117    */
118   @Override
119   public <T> T to(Object o, Type mainType, Type... args) {
120      return MarshallingContext.DEFAULT_SESSION.convertToType(o, mainType, args);
121   }
122
123   /**
124    * Converts the specified object to the specified type, using the given outer instance for
125    * non-static inner class construction.
126    *
127    * @param o The object to convert.
128    * @param memberOf The outer instance for non-static inner class construction, or <jk>null</jk> if the target is
129    *    not a non-static inner member class.
130    * @param session The converter session, or <jk>null</jk> (ignored either way; this implementation does not use a
131    *    converter session).
132    * @param type The target class type.
133    * @param <T> The target type to convert to.
134    * @return The converted object, or <jk>null</jk> if the input object is <jk>null</jk>.
135    * @throws InvalidDataConversionException If the object cannot be converted to the specified type.
136    */
137   @Override
138   public <T> T to(Object o, Object memberOf, ConverterSession session, Class<T> type) {
139      return MarshallingContext.DEFAULT_SESSION.convertToMemberType(memberOf, o, type);
140   }
141
142   /**
143    * Converts the specified object to the specified parameterized type, using the given outer instance for
144    * non-static inner class construction.
145    *
146    * @param o The object to convert.
147    * @param memberOf The outer instance for non-static inner class construction, or <jk>null</jk> if the target is
148    *    not a non-static inner member class.
149    * @param session The converter session, or <jk>null</jk> (ignored either way; this implementation does not use a
150    *    converter session).
151    * @param mainType The main type to convert to.
152    * @param args The type parameters of the main type.
153    * @param <T> The target type to convert to.
154    * @return The converted object, or <jk>null</jk> if the input object is <jk>null</jk>.
155    * @throws InvalidDataConversionException If the object cannot be converted to the specified type.
156    */
157   @SuppressWarnings({
158      "unchecked" // Cast is safe: type parameter verified by caller context.
159   })
160   @Override
161   public <T> T to(Object o, Object memberOf, ConverterSession session, Type mainType, Type... args) {
162      var rawType = (Class<T>) (mainType instanceof ParameterizedType mainType2 ? mainType2.getRawType() : (Class<?>) mainType);
163      return MarshallingContext.DEFAULT_SESSION.convertToMemberType(memberOf, o, rawType);
164   }
165}