/*
 * 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:
//     dminsky - initial API and implementation
package org.eclipse.persistence.testing.tests.queries;

import org.eclipse.persistence.testing.framework.*;
import org.eclipse.persistence.testing.models.insurance.*;

import org.eclipse.persistence.descriptors.invalidation.*;
import org.eclipse.persistence.internal.helper.*;
import org.eclipse.persistence.descriptors.*;
import org.eclipse.persistence.expressions.*;
import org.eclipse.persistence.mappings.*;
import org.eclipse.persistence.sessions.*;

/**
 * EL Bug 245448 - Add regression tests for querying across  relationships using
 * nested joining and DailyCacheInvalidationPolicy
 * - testing nested joining
 * - no indirection throughout
 * - daily expiration policy for cache invalidation
 * - foreign reference relationship on 1:M with batching + private owned
 * - 1:1 back-pointer for above not private owned, no batching, no joining
 */
public class QueryExecutionTimeSetOnBuildObjectTest extends TransactionalTestCase {

    protected QuerySQLTracker sqlTracker;

    private CacheInvalidationPolicy oldHolderCacheInvalidationPolicy;

    private boolean oldPoliciesShouldBatchRead;
    private boolean oldPoliciesShouldBePrivateOwned;

    private boolean oldPolicyHolderShouldBeBatchRead;
    private boolean oldPolicyHolderShouldBePrivateOwned;
    private int oldPolicyHolderJoining;

    private boolean oldAddressShouldBeBatchRead;
    private boolean oldAddressShouldBePrivateOwned;
    private int oldAddressJoining;

    public QueryExecutionTimeSetOnBuildObjectTest() {
        super();
        setDescription("Test that no duplicate sql is generated for nested join queries without indirection");
    }

    @Override
    public void setup() {
        super.setup();
        getSession().getIdentityMapAccessor().initializeAllIdentityMaps();

        ClassDescriptor holderDescriptor = getSession().getDescriptor(PolicyHolder.class);
        ClassDescriptor policyDescriptor = getSession().getDescriptor(Policy.class);
        ClassDescriptor addressDescriptor = getSession().getDescriptor(Address.class);

        // cache invalidation
        oldHolderCacheInvalidationPolicy = holderDescriptor.getCacheInvalidationPolicy();
        holderDescriptor.setCacheInvalidationPolicy(new DailyCacheInvalidationPolicy(0, 0, 0, 0));

        // PolicyHolder -> Policies batch reading
        OneToManyMapping policyHolderToPoliciesMapping = (OneToManyMapping) holderDescriptor.getMappingForAttributeName("policies");
        oldPoliciesShouldBatchRead = policyHolderToPoliciesMapping.shouldUseBatchReading();
        policyHolderToPoliciesMapping.setUsesBatchReading(true);

        // PolicyHolder -> Policies private owned
        oldPoliciesShouldBePrivateOwned = policyHolderToPoliciesMapping.isPrivateOwned();
        policyHolderToPoliciesMapping.setIsPrivateOwned(true);

        // Policy -> PolicyHolder batch reading
        OneToOneMapping policyToPolicyHolderMapping = (OneToOneMapping) policyDescriptor.getMappingForAttributeName("policyHolder");
        oldPolicyHolderShouldBeBatchRead = policyToPolicyHolderMapping.shouldUseBatchReading();
        policyToPolicyHolderMapping.setUsesBatchReading(false);

        // Policy -> PolicyHolder private owned
        oldPolicyHolderShouldBePrivateOwned = policyToPolicyHolderMapping.isPrivateOwned();
        policyToPolicyHolderMapping.setIsPrivateOwned(false);

        // Policy -> PolicyHolder joining
        oldPolicyHolderJoining = policyToPolicyHolderMapping.getJoinFetch();
        policyToPolicyHolderMapping.setJoinFetch(ForeignReferenceMapping.NONE);
        policyToPolicyHolderMapping.getDescriptor().reInitializeJoinedAttributes();

        // Address -> PolicyHolder batch reading
        OneToOneMapping addressToPolicyHolderMapping = (OneToOneMapping)addressDescriptor.getMappingForAttributeName("policyHolder");
        oldAddressShouldBeBatchRead = addressToPolicyHolderMapping.shouldUseBatchReading();
        addressToPolicyHolderMapping.setUsesBatchReading(false);

        // Address -> PolicyHolder joining
        oldAddressJoining = addressToPolicyHolderMapping.getJoinFetch();
        addressToPolicyHolderMapping.setJoinFetch(ForeignReferenceMapping.INNER_JOIN); // joining must be enabled on Address -> PolicyHolder
        addressToPolicyHolderMapping.getDescriptor().reInitializeJoinedAttributes();

        // Address -> PolicyHolder private owned
        oldAddressShouldBePrivateOwned = addressToPolicyHolderMapping.isPrivateOwned();
        addressToPolicyHolderMapping.setIsPrivateOwned(false);

        PolicyHolder holder = new PolicyHolder();
        holder.setFirstName("David");
        holder.setLastName("Minkoff");
        holder.setMale();
        holder.setSsn(515376);
        holder.setBirthDate(Helper.dateFromString("1979/03/25"));
        holder.setOccupation("Electrician");

        Address address = new Address();
        address.setCity("Calgary");
        address.setCountry("Canada");
        address.setState("AB");
        address.setStreet("Suite 840, 401 - 9th Avenue SW");
        address.setZipCode("T2P3C5");

        HealthPolicy healthPolicy1 = new HealthPolicy();
        healthPolicy1.setPolicyNumber(515377);
        healthPolicy1.setDescription("policy 1");
        healthPolicy1.setCoverageRate((float)1.5);
        healthPolicy1.setMaxCoverage(50000);

        HealthPolicy healthPolicy2 = new HealthPolicy();
        healthPolicy2.setPolicyNumber(515378);
        healthPolicy2.setDescription("policy 2");
        healthPolicy2.setCoverageRate((float)1.5);
        healthPolicy2.setMaxCoverage(50000);

        HealthPolicy healthPolicy3 = new HealthPolicy();
        healthPolicy3.setPolicyNumber(515379);
        healthPolicy3.setDescription("policy 3");
        healthPolicy3.setCoverageRate((float)1.5);
        healthPolicy3.setMaxCoverage(50000);

        holder.setAddress(address);
        holder.addPolicy(healthPolicy1);
        holder.addPolicy(healthPolicy2);
        holder.addPolicy(healthPolicy3);

        UnitOfWork uow = getSession().acquireUnitOfWork();
        uow.registerObject(holder);
        uow.commit();

        // create tracker object for query sql
        sqlTracker = new QuerySQLTracker(getSession());
        getSession().getIdentityMapAccessor().initializeAllIdentityMaps();
    }

    @Override
    public void test() {
        // query from address -> policyHolder -> Policy to trigger nested joins (no indirection)
        UnitOfWork uow = getSession().acquireUnitOfWork();
        Expression expression = new ExpressionBuilder().get("zipCode").equal("T2P3C5");
        uow.readObject(Address.class, expression);
        uow.release();
    }

    @Override
    public void verify() {
        // Insurance model expected SQL with configured adjustments in setup()
        // 1 x main select with joining from address -> policyholder
        // SELECT t1.CITY, t1.ZIPCODE, t1.STATE, t1.COUNTRY, t1.STREET, t1.SSN, t0.SSN, t0.L_NAME, t0.OCC, t0.BDATE, t0.F_NAME, t0.SEX FROM HOLDER t0, INS_ADDR t1 WHERE ((t1.ZIPCODE = T2P3C5) AND (t0.SSN = t1.SSN))
        // 1x policy type inheritance query
        // SELECT DISTINCT POL_TYPE FROM POLICY WHERE (SSN = 515376)
        // 1 x policy select based on type from policy inheritance query and policyholder pk
        // SELECT POL_ID, POL_TYPE, MAX_COV, DESCRIPT, SSN, COV_RATE FROM POLICY WHERE ((SSN = 515376) AND (POL_TYPE = 2))
        // 3 x claim selects from 3 policies read previously (no joining or batch reading configured)
        // SELECT DISTINCT CLM_TYPE FROM CLAIM WHERE (POL_ID = 515378)
        // SELECT DISTINCT CLM_TYPE FROM CLAIM WHERE (POL_ID = 515379)
        // SELECT DISTINCT CLM_TYPE FROM CLAIM WHERE (POL_ID = 515377)
        // 1 x PolicyHolder -> Child select (as mapped)
        // SELECT t0.CHILD_NAME FROM CHILDNAM t0 WHERE (t0.HOLDER_ID = 515376)
        // 1 x PolicyHolder -> Phone select (as mapped)
        // SELECT TYPE, PHONE_NUMBER, AREACODE FROM INS_PHONE WHERE (HOLDER_SSN = 515376)
        // = 8 statements expected

        int expectedNumberOfStatements = 8;
        int actualNumberOfSQLStatements = sqlTracker.getSqlStatements().size();

        if (expectedNumberOfStatements != actualNumberOfSQLStatements) {
            throw new TestErrorException("Expected " + expectedNumberOfStatements + " SQL statements - got " + actualNumberOfSQLStatements);
        }
    }

    @Override
    public void reset() {
        super.reset();

        ClassDescriptor holderDescriptor = getSession().getDescriptor(PolicyHolder.class);
        ClassDescriptor policyDescriptor = getSession().getDescriptor(Policy.class);
        ClassDescriptor addressDescriptor = getSession().getDescriptor(Address.class);

        // cache invalidation
        oldHolderCacheInvalidationPolicy = holderDescriptor.getCacheInvalidationPolicy();
        holderDescriptor.setCacheInvalidationPolicy(oldHolderCacheInvalidationPolicy);

        // PolicyHolder -> Policies batch reading
        OneToManyMapping policiesMapping = (OneToManyMapping) holderDescriptor.getMappingForAttributeName("policies");
        policiesMapping.setUsesBatchReading(oldPoliciesShouldBatchRead);

        // PolicyHolder -> Policies private owned
        policiesMapping.setIsPrivateOwned(oldPoliciesShouldBePrivateOwned);

        // Policy -> PolicyHolder batch reading
        OneToOneMapping policyHolderMapping = (OneToOneMapping) policyDescriptor.getMappingForAttributeName("policyHolder");
        policyHolderMapping.setUsesBatchReading(oldPolicyHolderShouldBeBatchRead);

        // Policy -> PolicyHolder private owned
        policyHolderMapping.setIsPrivateOwned(oldPolicyHolderShouldBePrivateOwned);

        // Policy -> PolicyHolder joining
        policyHolderMapping.setJoinFetch(oldPolicyHolderJoining);
        policyHolderMapping.getDescriptor().reInitializeJoinedAttributes();

        // Address -> PolicyHolder batch reading
        OneToOneMapping addressToPolicyHolderMapping = (OneToOneMapping)addressDescriptor.getMappingForAttributeName("policyHolder");
        addressToPolicyHolderMapping.setUsesBatchReading(oldAddressShouldBeBatchRead);

        // Address -> PolicyHolder joining
        addressToPolicyHolderMapping.setJoinFetch(oldAddressJoining);
        addressToPolicyHolderMapping.getDescriptor().reInitializeJoinedAttributes();

        // Address -> PolicyHolder private owned
        addressToPolicyHolderMapping.setIsPrivateOwned(oldAddressShouldBePrivateOwned);

        sqlTracker.remove();
    }

}
