/*
 * 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.Timestamp;
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 from a given class by
//calling getDataTypesConvertedFrom() in ConversionManager.  It then converts the underlying
//object of the given class to all the returned classes from getDataTypesConvertedFrom().
//The given objects are obtained from ConversionDataObjectForSupportedTypes.example().
//Blob and Clob are not included as source object.
public class DataTypesConvertedFromAClassTest extends AutoVerifyTestCase {
    protected Object cm;
    protected Exception exception1;
    protected Exception exception2;
    protected Class sourceClass;
    protected Class targetClass;

    public DataTypesConvertedFromAClassTest() {
        setDescription("Test getDataTypesConvertedFrom() in ConversionManager.");
    }

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

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

        ConversionDataObjectForSupportedTypes example = ConversionDataObjectForSupportedTypes.example();
        Field[] fields = ConversionDataObjectForSupportedTypes.class.getFields();
        for (x = 0; x < fields.length; x++) {
            try {
                obj = fields[x].get(example);
            } catch (IllegalAccessException e) {
                exception1 = e;
                break;
            }
            type = fields[x].getType();
            if ((obj != null) && !type.isPrimitive()) {
                vec = wrapper.getDataTypesConvertedFrom(type);
                for (y = 0; y < vec.size(); y++) {
                    //Different string formats are required for number, date and other types
                    if ((fields[x].getName().equals("stringToInt") && !isNumber((Class)vec.get(y))) || (fields[x].getName().equals("stringToTimestamp") && !isTimestamp((Class)vec.get(y))) || (fields[x].getName().equals("aString") && !isChar((Class)vec.get(y)))) {
                        continue;
                    }
                    try {
                        wrapper.convertObject(obj, (Class)vec.get(y));
                    } catch (Exception e) {
                        exception2 = e;
                        sourceClass = fields[x].getType();
                        targetClass = (Class)vec.get(y);
                    }
                }
            }
        }
    }

    @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 ConversionManager getCm() {
        return (ConversionManager)cm;
    }

    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);
    }
}
