/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
<<<<<<< Updated upstream
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
=======
 * 
 *     https://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software 
 * distributed under the License is distributed on an "AS IS" BASIS, 
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 * See the License for the specific language governing permissions and 
>>>>>>> Stashed changes
 * limitations under the License.
 */

package org.apache.jdo.tck.query.jdoql.subqueries;

import java.util.List;
import javax.jdo.JDOQLTypedQuery;
import javax.jdo.JDOQLTypedSubquery;
import javax.jdo.Query;
import javax.jdo.Transaction;
import javax.jdo.query.NumericExpression;
import org.apache.jdo.tck.pc.company.CompanyModelReader;
import org.apache.jdo.tck.pc.company.Employee;
import org.apache.jdo.tck.pc.company.MeetingRoom;
import org.apache.jdo.tck.pc.company.QEmployee;
import org.apache.jdo.tck.pc.company.QMeetingRoom;
import org.apache.jdo.tck.util.BatchTestRunner;

/**
 * <B>Title:</B> Correlated Subqueries Without Parameters <br>
 * <B>Keywords:</B> query <br>
 * <B>Assertion ID:</B> A14.6.2-56 <br>
 * <B>Assertion Description: </B> A correlated subquery is a subquery which contains references to
 * expressions in the outer query. If the correlation can be expressed as a restriction of the
 * candidate collection of the subquery, no parameters are needed.
 */
public class CorrelatedSubqueries extends SubqueriesTest {

  /** */
  private static final String ASSERTION_FAILED =
      "Assertion A14.6.2-56 (CorrelatedSubqueries) failed: ";

  // Select employees who work more than the average of their department employees.
  private static final String SINGLE_STRING_QUERY_COLLECTION_SUBQUERY =
      "SELECT FROM "
          + Employee.class.getName()
          + " WHERE this.weeklyhours > (SELECT AVG(e.weeklyhours) FROM this.department.employees e)";

  // Select employees who work in a department having a meeting room with the maximum roomid.
  private static final String SINGLE_STRING_QUERY_LIST_SUBQUERY =
      "SELECT FROM "
          + Employee.class.getName()
          + " WHERE (SELECT max(r.roomid) FROM this.department.meetingRooms r) == 3";

  /**
   * The <code>main</code> is called when the class is directly executed from the command line.
   *
   * @param args The arguments passed to the program.
   */
  public static void main(String[] args) {
    BatchTestRunner.run(CorrelatedSubqueries.class);
  }

  /** */
  public void testCollectionApiQuery() {
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();
      List<Employee> expected =
          getTransientCompanyModelInstancesAsList(
              Employee.class, "emp1", "emp2", "emp4", "emp6", "emp7", "emp10");

      // API query
      try (Query<Employee> apiQuery = pm.newQuery(Employee.class)) {
        Query<Employee> sub = pm.newQuery(Employee.class);
        sub.setResult("avg(this.weeklyhours)");
        apiQuery.setFilter("this.weeklyhours> averageWeeklyhours");
        apiQuery.addSubquery(sub, "double averageWeeklyhours", "this.department.employees");
        List<Employee> emps = apiQuery.executeList();
        checkQueryResultWithoutOrder(
            ASSERTION_FAILED, SINGLE_STRING_QUERY_COLLECTION_SUBQUERY, emps, expected);

        // API query against memory model
        List<Employee> allEmployees = pm.newQuery(Employee.class).executeList();
        apiQuery.setCandidates(allEmployees);
        emps = apiQuery.executeList();
        checkQueryResultWithoutOrder(
            ASSERTION_FAILED, SINGLE_STRING_QUERY_COLLECTION_SUBQUERY, emps, expected);
      } catch (Exception ex) {
        fail(ASSERTION_FAILED, ex.getLocalizedMessage());
      }
      tx.commit();
    } finally {
      if (tx.isActive()) {
        tx.rollback();
      }
    }
  }

  /** */
  @SuppressWarnings("unchecked")
  public void testCollectionSingleStringQuery() {
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();
      List<Employee> expected =
          getTransientCompanyModelInstancesAsList(
              Employee.class, "emp1", "emp2", "emp4", "emp6", "emp7", "emp10");
      // single String JDOQL
      try (Query<Employee> singleStringQuery =
          pm.newQuery(SINGLE_STRING_QUERY_COLLECTION_SUBQUERY)) {
        List<Employee> emps = singleStringQuery.executeList();
        checkQueryResultWithoutOrder(
            ASSERTION_FAILED, SINGLE_STRING_QUERY_COLLECTION_SUBQUERY, emps, expected);
      } catch (Exception ex) {
        fail(ASSERTION_FAILED, ex.getLocalizedMessage());
      }
      tx.commit();
    } finally {
      if (tx.isActive()) {
        tx.rollback();
      }
    }
  }

  /** */
  @SuppressWarnings("unchecked")
  public void testCollectionJDOQLTypedQuery() {
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();
      List<Employee> expected =
          getTransientCompanyModelInstancesAsList(
              Employee.class, "emp1", "emp2", "emp4", "emp6", "emp7", "emp10");
      try (JDOQLTypedQuery<Employee> q = pm.newJDOQLTypedQuery(Employee.class)) {
        QEmployee cand = QEmployee.candidate();
        JDOQLTypedSubquery<Employee> subquery =
            q.subquery(cand.department.employees, Employee.class, "e");
        QEmployee candsub = QEmployee.candidate("e");
        q.filter(cand.weeklyhours.gt(subquery.selectUnique(candsub.weeklyhours.avg())));
        List<Employee> emps = q.executeList();
        checkQueryResultWithoutOrder(
            ASSERTION_FAILED, SINGLE_STRING_QUERY_COLLECTION_SUBQUERY, emps, expected);
      } catch (Exception ex) {
        fail(ASSERTION_FAILED, ex.getLocalizedMessage());
      }
      tx.commit();
    } finally {
      if (tx.isActive()) {
        tx.rollback();
      }
    }
  }

  /** */
  public void testListApiQuery() {
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();
      List<Employee> expected =
          getTransientCompanyModelInstancesAsList(Employee.class, "emp7", "emp8", "emp9", "emp10");

      // API query
      try (Query<Employee> apiQuery = pm.newQuery(Employee.class)) {
        Query<MeetingRoom> sub = pm.newQuery(MeetingRoom.class);
        sub.setResult("max(roomid)");
        apiQuery.setFilter("maxNumber == 3");
        apiQuery.addSubquery(sub, "long maxNumber", "this.department.meetingRooms");
        List<Employee> emps = apiQuery.executeList();
        checkQueryResultWithoutOrder(
            ASSERTION_FAILED, SINGLE_STRING_QUERY_LIST_SUBQUERY, emps, expected);

        // API query against memory model
        List<Employee> allEmployees = pm.newQuery(Employee.class).executeList();
        apiQuery.setCandidates(allEmployees);
        emps = apiQuery.executeList();
        checkQueryResultWithoutOrder(
            ASSERTION_FAILED, SINGLE_STRING_QUERY_LIST_SUBQUERY, emps, expected);
      } catch (Exception ex) {
        fail(ASSERTION_FAILED, ex.getLocalizedMessage());
      }
      tx.commit();
    } finally {
      if (tx.isActive()) {
        tx.rollback();
      }
    }
  }

  /** */
  @SuppressWarnings("unchecked")
  public void testListSingleStringQuery() {
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();
      List<Employee> expected =
          getTransientCompanyModelInstancesAsList(Employee.class, "emp7", "emp8", "emp9", "emp10");
      // single String JDOQL
      try (Query<Employee> singleStringQuery = pm.newQuery(SINGLE_STRING_QUERY_LIST_SUBQUERY)) {
        List<Employee> emps = singleStringQuery.executeList();
        checkQueryResultWithoutOrder(
            ASSERTION_FAILED, SINGLE_STRING_QUERY_LIST_SUBQUERY, emps, expected);
      } catch (Exception ex) {
        fail(ASSERTION_FAILED, ex.getLocalizedMessage());
      }
      tx.commit();
    } finally {
      if (tx.isActive()) {
        tx.rollback();
      }
    }
  }

  /** */
  @SuppressWarnings("unchecked")
  public void testListJDOQLTypedQuery() {
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();
      List<Employee> expected =
          getTransientCompanyModelInstancesAsList(Employee.class, "emp7", "emp8", "emp9", "emp10");
      try (JDOQLTypedQuery<Employee> q = pm.newJDOQLTypedQuery(Employee.class)) {
        QEmployee cand = QEmployee.candidate();
        JDOQLTypedSubquery<MeetingRoom> subquery =
            q.subquery(cand.department.meetingRooms, MeetingRoom.class, "r");
        QMeetingRoom candsub = QMeetingRoom.candidate("r");
        q.filter(subquery.selectUnique((NumericExpression<Long>) candsub.roomid.max()).eq(3l));
        List<Employee> emps = q.executeList();
        checkQueryResultWithoutOrder(
            ASSERTION_FAILED, SINGLE_STRING_QUERY_COLLECTION_SUBQUERY, emps, expected);
      } catch (Exception ex) {
        fail(ASSERTION_FAILED, ex.getLocalizedMessage());
      }
      tx.commit();
    } finally {
      if (tx.isActive()) {
        tx.rollback();
      }
    }
  }

  /**
   * @see org.apache.jdo.tck.JDO_Test#localSetUp()
   */
  @Override
  protected void localSetUp() {
    addTearDownClass(CompanyModelReader.getTearDownClasses());
    loadAndPersistCompanyModel(getPM());
  }
}
