/*******************************************************************************
 * Copyright (c) 1998, 2015 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 v1.0 and Eclipse Distribution License v. 1.0
 * which accompanies this distribution.
 * The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
 * and the Eclipse Distribution License is available at
 * http://www.eclipse.org/org/documents/edl-v10.php.
 *
 * Contributors:
 *     Oracle - initial API and implementation from Oracle TopLink
 ******************************************************************************/
package org.eclipse.persistence.testing.tests.jpa.advanced;

import java.util.*;
import org.eclipse.persistence.testing.models.jpa.advanced.*;
import org.eclipse.persistence.internal.jpa.EntityManagerImpl;
import org.eclipse.persistence.testing.framework.TestErrorException;
import org.eclipse.persistence.testing.tests.jpa.EntityContainerTestBase;

/**
 * CRUD tests for an entity that has a PK class (PhoneNumber). Test looks for
 * exceptions on any of the CRUD operations of an employee with multiple
 * phone numbers.
 *
 * @author Guy Pelletier
 */
public class PrimaryKeyClassTest extends EntityContainerTestBase  {
    protected boolean reset = false;    // reset gets called twice on error
    protected Exception m_createException;
    protected Exception m_readException;
    protected Exception m_updateException;
    protected Exception m_deleteException;

    public void setup () {
        super.setup();
        this.reset = true;

        // Clear the cache so we are working from scratch.
        ((EntityManagerImpl)getEntityManager()).getActiveSession().getIdentityMapAccessor().initializeAllIdentityMaps();
    }

    public void reset () {
        if (reset) {
            reset = false;
        }
        super.reset();
    }

    public void test() throws Exception {
        int empId = createTest();
        readTest(empId);
        updateTest(empId);
        deleteTest(empId);
    }

    /**
     * Create an employee with multiple phone numbers.
     */
    private int createTest() {
        Vector phoneNumbers = new Vector();
        Employee employee  = new Employee();

        try {
            beginTransaction();
            employee.setFirstName("Guy");
            employee.setLastName("Pelletier");

            PhoneNumber homeNumber = new PhoneNumber();
            homeNumber.setAreaCode("61x");
            homeNumber.setNumber("823-6262");
            homeNumber.setOwner(employee);
            homeNumber.setType("Home");
            phoneNumbers.add(homeNumber);

            PhoneNumber cellNumber = new PhoneNumber();
            cellNumber.setAreaCode("61x");
            cellNumber.setNumber("299-6747");
            cellNumber.setOwner(employee);
            cellNumber.setType("Cell");
            phoneNumbers.add(cellNumber);

            PhoneNumber workNumber = new PhoneNumber();
            workNumber.setAreaCode("61x");
            workNumber.setNumber("288-4639");
            workNumber.setOwner(employee);
            workNumber.setType("Work");
            phoneNumbers.add(workNumber);

            employee.setPhoneNumbers(phoneNumbers);

            getEntityManager().persist(employee);

            commitTransaction();
        } catch (Exception e) {
            rollbackTransaction();
            m_createException = e;
        }

        return employee.getId();
    }

    /**
     * Read the employee with multiple phone numbers.
     */
    private void readTest(int empId) {
        try {
            getEntityManager().find(Employee.class, empId);
        } catch (Exception e) {
            m_readException = e;
        }
    }

    /**
     * Update the phone numbers on the employee with multiple phone numbers.
     */
    private void updateTest(int empId) {
        try {
            beginTransaction();

            Employee employee = getEntityManager().find(Employee.class, empId);
            Vector phones = (Vector) employee.getPhoneNumbers();
            Enumeration e = phones.elements();


            while (e.hasMoreElements()) {
                PhoneNumber phone = (PhoneNumber) e.nextElement();
                phone.setAreaCode("613");
            }

            getEntityManager().persist(employee);

            commitTransaction();
        } catch (Exception e) {
            rollbackTransaction();
            m_updateException = e;
        }
    }

    /**
     * Delete the first phone number on the employee with multiple phone numbers.
     */
    private void deleteTest(int empId) {
        try {
            beginTransaction();
            Employee employee = getEntityManager().find(Employee.class, empId);
            getEntityManager().remove(((Vector) employee.getPhoneNumbers()).firstElement());
            commitTransaction();
        } catch (Exception e) {
            rollbackTransaction();
            m_deleteException = e;
        }
    }

    public void verify() {
        if (m_createException != null) {
            throw new TestErrorException("Create exception was caught. " + m_createException);
        }

        if (m_readException != null) {
            throw new TestErrorException("Read exception was caught. " + m_readException);
        }

        if (m_updateException != null) {
            throw new TestErrorException("Update exception was caught. " + m_updateException);
        }

        if (m_deleteException != null) {
            throw new TestErrorException("Delete exception was caught. " + m_deleteException);
        }
    }
}
