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

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

import org.eclipse.persistence.queries.*;
import org.eclipse.persistence.expressions.*;

import org.eclipse.persistence.testing.framework.*;
import org.eclipse.persistence.testing.models.employee.domain.*;

public class MemoryQueryAcrossOneToManyMapping2 extends TestCase {
    protected Employee employee;
    protected ReadAllQuery queryAll;
    protected ReadObjectQuery queryObject;
    protected java.util.Vector allEmployees;
    protected java.util.Vector employees;
    protected java.util.Vector phones;
    protected java.util.Vector verifyEmp;
    protected java.util.Vector verifyPhone;

    public MemoryQueryAcrossOneToManyMapping2() {
        super();
    }

    @Override
    public void reset() {
        //clear the cache.
        getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
    }

    /**
     * This is  still in the works.
     */
    @Override
    public void setup() {
        allEmployees = new Vector();
        employees = new Vector();
        phones = new Vector();
        Vector anotherVector = new Vector();
        Vector phone = new Vector();
        Vector managedEmp = new Vector();
        Vector managedEmpVector = new Vector();
        Vector allPhones = new Vector();
        Vector allEmps = new Vector();
        queryAll = new ReadAllQuery();
        queryAll.setReferenceClass(Employee.class);
        queryAll.setSelectionCriteria(new ExpressionBuilder().anyOf("managedEmployees").anyOf("phoneNumbers").get("areaCode").equal("613"));
        getSession().removeQuery("getAllEmployees");
        getSession().addQuery("getAllEmployees", queryAll);
        allEmployees = (Vector)getSession().executeQuery("getAllEmployees");
        for (Enumeration enumtr = allEmployees.elements(); enumtr.hasMoreElements();) {
            employees = ((Employee)enumtr.nextElement()).getManagedEmployees();
            allEmps.addAll(employees);
            //trigger all the value holders of employees who have managedEmployees
        }
        verifyEmp = allEmps;
        for (Enumeration enum2 = allEmployees.elements(); enum2.hasMoreElements();) {
            anotherVector = ((Employee)enum2.nextElement()).getPhoneNumbers();
            phones.addAll(anotherVector);
            //trigger all the value holders of managers' phonenumbers
        }

        for (Enumeration enum3 = allEmps.elements(); enum3.hasMoreElements();) {
            managedEmpVector = ((Employee)enum3.nextElement()).getManagedEmployees();
            managedEmp.addAll(managedEmpVector);

            //trigger all the value holders of managed employees' managed employees
        }
        for (Enumeration enum4 = allEmps.elements(); enum4.hasMoreElements();) {
            phone = ((Employee)enum4.nextElement()).getPhoneNumbers();
            allPhones.addAll(phone);

            //trigger all the value holders of managed employees' phonenumbers
        }
        verifyPhone = allPhones;

    }

    @Override
    public void test() {
        //all the employees with work type phonenumbers should be
        //in the cache right now.
        queryObject = new ReadObjectQuery();
        queryObject.setReferenceClass(Employee.class);
        queryObject.checkCacheOnly(); //read from cache only

        ExpressionBuilder bldr = new ExpressionBuilder();
        Expression exp1 = bldr.anyOf("managedEmployees").get("lastName").equal("Way");
        Expression exp2 = bldr.anyOf("phoneNumbers").get("areaCode").equal("613");
        Expression exp = exp1.and(exp2);
        queryObject.setSelectionCriteria(exp);
        employee = (Employee)getSession().executeQuery(queryObject);

    }

    @Override
    public void verify() {
        for (Enumeration check = verifyEmp.elements(); check.hasMoreElements(); ) {
            if ((employee.getManagedEmployees()).contains(check.nextElement())) {
                for (Enumeration phoneCheck = verifyPhone.elements(); phoneCheck.hasMoreElements(); ) {

                    if ((employee.getPhoneNumbers()).contains(phoneCheck.nextElement())) {
                        //?
                    }
                }
            }
        }
    }
}
