/*
 * 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.interfaces;

import java.util.Vector;
import java.util.Enumeration;

import org.eclipse.persistence.testing.framework.*;
import org.eclipse.persistence.sessions.Session;
import org.eclipse.persistence.internal.helper.Helper;
import org.eclipse.persistence.internal.helper.DatabaseField;
import org.eclipse.persistence.internal.sessions.AbstractSession;
import org.eclipse.persistence.mappings.Association;
import org.eclipse.persistence.mappings.TypedAssociation;
import org.eclipse.persistence.mappings.VariableOneToOneMapping;
import org.eclipse.persistence.testing.models.interfaces.*;

public class VariableOneToOneCodeCoverageTest extends TestCase {
    VariableOneToOneMapping mapping;
    private String testFailures;

    @Override
    public void setup() {
        mapping = new VariableOneToOneMapping();
        testFailures = "";
    }

    @Override
    public void verify() {
        if (testFailures.length() > 0) {
            throw new TestErrorException("Tests failures from VariableOneToOneMapping: " + testFailures);
        }
    }

    @Override
    public void test() {
        runTests();
    }

    public void runTests() {
        /**************************************************************************/
        mapping.addClassIndicator(Employee.class, null);

        if (mapping.getClassIndicatorAssociations().isEmpty()) {
            testFailures += "addClassIndicator = null did not add a null wrapper type indicator";
        } else {
            Enumeration e = mapping.getClassIndicatorAssociations().elements();

            while (e.hasMoreElements()) {
                TypedAssociation association = (TypedAssociation)e.nextElement();

                if (association.getKey() == Employee.class) {
                    if (!(association.getValue() instanceof Helper)) {
                        testFailures += "addClassIndicator = null, type indicator does not = Helper class";
                    }
                }
            }
        }

        /**************************************************************************/
        Vector vectorIn = new Vector();
        vectorIn.add(new Association(Actor.class, new String("ASHLEY JUDD")));
        vectorIn.add(new Association(Secretary.class, new String("DARTH VADER")));
        vectorIn.add(new Association(Broadcastor.class, new String("RED KELLY")));

        mapping.setClassIndicatorAssociations(vectorIn);

        Vector vectorOut = mapping.getClassIndicatorAssociations();

        if (vectorOut.size() != 3) {
            testFailures += "setClassIndicatorAssociations - the set failed";
        } else {
            int foundCount = 0;

            for (int i = 0; i < vectorOut.size(); i++) {
                Association ass = (Association)vectorOut.elementAt(i);

                if (ass.getKey() == Actor.class.getName() && ass.getValue().equals("ASHLEY JUDD")) {
                    foundCount++;
                }
                if (ass.getKey() == Secretary.class.getName() && ass.getValue().equals("DARTH VADER")) {
                    foundCount++;
                }
                if (ass.getKey() == Broadcastor.class.getName() && ass.getValue().equals("RED KELLY")) {
                    foundCount++;
                }
            }

            if (foundCount != 3) {
                testFailures += "setClassIndicatorAssociations - association values not found";
            }
        }

        /**************************************************************************/
        Association assoc = new Association(new String("key"), new String("value"));
        Vector in = new Vector();
        in.add(assoc);
        mapping.setSourceToTargetQueryKeyFieldAssociations(in);
        Vector out = mapping.getSourceToTargetQueryKeyFieldAssociations();

        if (out.size() != 1) {
            testFailures += "setSourceToTargetQueryFieldAssociations - the set failed";
        } else {
            Association a = (Association)out.elementAt(0);

            if (!(a.getKey().equals("key") && a.getValue().equals("value"))) {
                testFailures += "setSourceToTargetQueryFieldAssociations - value in the set failed";
            }
        }

        /**************************************************************************/
        Vector foreignKeyNames = new Vector();
        foreignKeyNames.add("fkey1");
        foreignKeyNames.add("fkey2");
        foreignKeyNames.add("fkey3");
        mapping.setForeignKeyFieldNames(foreignKeyNames);

        Vector fieldNames = mapping.getForeignKeyFieldNames();

        if (!(mapping.getForeignKeyFieldNames().contains("fkey1"))) {
            testFailures += "addForeignQueryKeyName - fkey1";
        }

        if (!(mapping.getForeignKeyFieldNames().contains("fkey2"))) {
            testFailures += "addForeignQueryKeyName - fkey2";
        }

        if (!(mapping.getForeignKeyFieldNames().contains("fkey3"))) {
            testFailures += "addForeignQueryKeyName - fkey3";
        }

        /**************************************************************************/
        mapping.setTypeFieldName("doesNotExist");

        if (!mapping.getTypeFieldName().equals("doesNotExist")) {
            testFailures += "setTypeFieldName failed";
        }

        /**************************************************************************/
        // tests done through the wrapper
        /**************************************************************************/

        /**************************************************************************/
        VariableOneToOneMapping2 wrappedMapping = new VariableOneToOneMapping2();
        wrappedMapping.setTypeField(null);

        if (wrappedMapping.getTypeFieldName() != null) {
            testFailures += "setTypeField - set to null failed";
        }

        /**************************************************************************/
        wrappedMapping.addClassIndicator(Employee.class, null);

        if (wrappedMapping.getTypeForImplementor(Employee.class) != null) {
            testFailures += "getTypeForImplementor failed";
        }

        if (wrappedMapping.getImplementorForType(null, getSession()) != Employee.class) {
            testFailures += "getImplementorForType failed";
        }
    }
}

class VariableOneToOneMapping2 extends VariableOneToOneMapping {
    @Override
    public void setTypeField(DatabaseField typeField) {
        super.setTypeField(typeField);
    }

    @Override
    public Object getTypeForImplementor(Class<?> implementor) {
        return super.getTypeForImplementor(implementor);
    }

    public Object getImplementorForType(Object type, Session session) {
        return super.getImplementorForType(type, (AbstractSession)session);
    }
}
