/*
 * Copyright 2002-2016 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.taobao.arthas.core.env;

/**
 * A service interface for type conversion. This is the entry point into the
 * convert system. Call {@link #convert(Object, Class)} to perform a thread-safe
 * type conversion using this system.
 *
 * @author Keith Donald
 * @author Phillip Webb
 * @since 3.0
 */
public interface ConversionService {

    /**
     * Return {@code true} if objects of {@code sourceType} can be converted to the
     * {@code targetType}.
     * <p>
     * If this method returns {@code true}, it means {@link #convert(Object, Class)}
     * is capable of converting an instance of {@code sourceType} to
     * {@code targetType}.
     * <p>
     * Special note on collections, arrays, and maps types: For conversion between
     * collection, array, and map types, this method will return {@code true} even
     * though a convert invocation may still generate a {@link ConversionException}
     * if the underlying elements are not convertible. Callers are expected to
     * handle this exceptional case when working with collections and maps.
     * 
     * @param sourceType the source type to convert from (may be {@code null} if
     *                   source is {@code null})
     * @param targetType the target type to convert to (required)
     * @return {@code true} if a conversion can be performed, {@code false} if not
     * @throws IllegalArgumentException if {@code targetType} is {@code null}
     */
    boolean canConvert(Class<?> sourceType, Class<?> targetType);

    /**
     * Convert the given {@code source} to the specified {@code targetType}.
     * 
     * @param source     the source object to convert (may be {@code null})
     * @param targetType the target type to convert to (required)
     * @return the converted object, an instance of targetType
     * @throws ConversionException      if a conversion exception occurred
     * @throws IllegalArgumentException if targetType is {@code null}
     */
    <T> T convert(Object source, Class<T> targetType);

}
