/*
 * Copyright (c) 1998, 2021 Oracle and/or its affiliates. All rights reserved.
 *
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-2.0,
 * or the Eclipse Distribution License v. 1.0 which is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
 */

// Contributors:
//     Oracle - initial API and implementation from Oracle TopLink
package org.eclipse.persistence.testing.tests.conversion;

import java.util.List;
import java.util.Vector;
import java.util.Calendar;
import java.sql.*;
import java.math.*;
import java.lang.reflect.Field;
import org.eclipse.persistence.internal.helper.ConversionManager;
import org.eclipse.persistence.testing.framework.AutoVerifyTestCase;
import org.eclipse.persistence.testing.framework.TestErrorException;
import org.eclipse.persistence.testing.models.conversion.ConversionDataObjectForSupportedTypes;

//This test retrieves all the classes that can be converted to a given class by
//calling getDataTypesConvertedTo() in ConversionManager.  It then converts the
//underlying objects of all the retrieved classes to the given class.
//The underlying objects are obtained from ConversionDataObjectForSupportedTypes.example().
//Blob and Clob are not included in the retrieved classes for conversion.
public class DataTypesConvertedToAClassTest extends AutoVerifyTestCase {
    protected Object cm;
    protected Exception exception1;
    protected Exception exception2;
    protected Class sourceClass;
    protected Class targetClass;
    protected Class[] convertedToClasses = new Class[] { BigDecimal.class, BigInteger.class, Boolean.class, Byte.class, byte[].class, Byte[].class, Calendar.class, Character.class, Character[].class, char[].class, java.sql.Date.class, Double.class, Float.class, Integer.class, Long.class, Number.class, Short.class, String.class, Timestamp.class, Time.class, java.util.Date.class };

    public DataTypesConvertedToAClassTest() {
        setDescription("Test getDataTypesConvertedTo() in ConversionManager.");
    }

    @Override
    public void setup() {
        cm = ConversionManager.getDefaultManager();
    }

    @Override
    public void test() {
        List vec;
        int x;
        int y;
        int z;
        Object obj;
        Class type;
        CMAndPlatformWrapper wrapper = new CMAndPlatformWrapper(cm);

        ConversionDataObjectForSupportedTypes example = ConversionDataObjectForSupportedTypes.example();
        Field[] fields = ConversionDataObjectForSupportedTypes.class.getFields();
        for (x = 0; x < convertedToClasses.length; x++) {
            vec = wrapper.getDataTypesConvertedTo(convertedToClasses[x]);
            for (y = 0; y < vec.size(); y++) {
                for (z = 0; z < fields.length; z++) {
                    type = fields[z].getType();
                    if (vec.get(y) == type) {
                        try {
                            obj = fields[z].get(example);
                        } catch (IllegalAccessException e) {
                            exception1 = e;
                            break;
                        }
                        if ((obj == null) || (type == Blob.class) || (type == Clob.class) || (fields[z].getName().equals("stringToInt") && !isNumber(convertedToClasses[x])) || (fields[z].getName().equals("stringToTimestamp") && !isTimestamp(convertedToClasses[x])) || (fields[z].getName().equals("aString") && !isChar(convertedToClasses[x]))) {
                            continue;
                        }
                        try {
                            wrapper.convertObject(obj, convertedToClasses[x]);
                        } catch (Exception e) {
                            exception2 = e;
                            sourceClass = type;
                            targetClass = convertedToClasses[x];
                        }
                    }
                }
            }
        }
    }

    @Override
    public void verify() {
        if (exception1 != null) {
            throw (new TestErrorException(exception1.toString()));
        }
        if (exception2 != null) {
            throw (new TestErrorException("Conversion of '" + sourceClass + "' to '" + targetClass + "' falied."));
        }
    }

    protected boolean isNumber(Class aClass) {
        return Number.class.isAssignableFrom(aClass);
    }

    protected boolean isTimestamp(Class aClass) {
        return (aClass == java.util.Date.class) || (aClass == Timestamp.class) || (aClass == Calendar.class);
    }

    protected boolean isChar(Class aClass) {
        return (aClass == Character.class) || (aClass == Character[].class) || (aClass == char[].class) || (aClass == String.class) || (aClass == java.sql.Clob.class);
    }
}
