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

import java.util.Arrays;
import javax.jdo.JDOQLTypedQuery;
import org.apache.jdo.tck.pc.company.CompanyModelReader;
import org.apache.jdo.tck.pc.company.Department;
import org.apache.jdo.tck.pc.company.Employee;
import org.apache.jdo.tck.pc.company.Project;
import org.apache.jdo.tck.pc.company.QDepartment;
import org.apache.jdo.tck.pc.company.QEmployee;
import org.apache.jdo.tck.pc.company.QProject;
import org.apache.jdo.tck.query.QueryElementHolder;
import org.apache.jdo.tck.query.QueryTest;
import org.apache.jdo.tck.util.BatchTestRunner;

/**
 * <B>Title:</B> Variable in Result. <br>
 * <B>Keywords:</B> query <br>
 * <B>Assertion ID:</B> A14.6.9-3. <br>
 * <B>Assertion Description: </B> If a variable or a field of a variable is included in the result,
 * either directly or via navigation through the variable, then the semantics of the contains clause
 * that include the variable change. In this case, all values of the variable that satisfy the
 * filter are included in the result. Result expressions begin with either an instance of the
 * candidate class (with an explicit or implicit "this") or an instance of a variable (using the
 * variable name). The candidate tuples are the cartesian product of the candidate class and all
 * variables used in the result. The result tuples are the tuples of the candidate class and all
 * variables used in the result that satisfy the filter. The result is the collection of result
 * expressions projected from the result tuples.
 *
 * <p>This test differs from VariableInResult by extending the navigation of variables. It navigates
 * from the candidate Department class to include fields in the corresponding Company. It navigates
 * from the candidate Company class to Department, Employee, and Project.
 */
public class VariableInResultNavigation extends QueryTest {

  /** */
  private static final String ASSERTION_FAILED = "Assertion A14.6.9-3 (VariableInResult) failed: ";

  /** The expected results of valid queries. */
  private final Object emp1 = getTransientCompanyModelInstance(Employee.class, "emp1");

  private final Object emp2 = getTransientCompanyModelInstance(Employee.class, "emp2");
  private final Object emp3 = getTransientCompanyModelInstance(Employee.class, "emp3");
  private final Object emp4 = getTransientCompanyModelInstance(Employee.class, "emp4");
  private final Object emp5 = getTransientCompanyModelInstance(Employee.class, "emp5");
  private final Object proj1 = getTransientCompanyModelInstance(Project.class, "proj1");
  private final Object proj2 = getTransientCompanyModelInstance(Project.class, "proj2");
  private final Object proj3 = getTransientCompanyModelInstance(Project.class, "proj3");
  private final Object dept1 = getTransientCompanyModelInstance(Department.class, "dept1");
  private final Object dept2 = getTransientCompanyModelInstance(Department.class, "dept2");

  /**
   * 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(VariableInResult.class);
  }

  /** */
  @SuppressWarnings("unchecked")
  public void testNavigationWithConstraint() {
    Object expected =
        Arrays.asList(
            new Object[] {emp1, proj1}, new Object[] {emp2, proj1}, new Object[] {emp3, proj1});

    JDOQLTypedQuery<Department> query = getPM().newJDOQLTypedQuery(Department.class);
    QDepartment cand = QDepartment.candidate();
    QEmployee e = QEmployee.variable("e");
    QProject p = QProject.variable("p");
    query.filter(cand.employees.contains(e).and(e.projects.contains(p)).and(p.name.eq("orange")));
    query.result(false, e, p);

    QueryElementHolder<Department> holder =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ "e, p",
            /*INTO*/ null,
            /*FROM*/ Department.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ "employees.contains(e) && e.projects.contains(p) && p.name == 'orange'",
            /*VARIABLES*/ "Employee e; Project p",
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ null,
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ query,
            /*paramValues*/ null);

    executeAPIQuery(ASSERTION_FAILED, holder, expected);
    executeSingleStringQuery(ASSERTION_FAILED, holder, expected);
    executeJDOQLTypedQuery(ASSERTION_FAILED, holder, null, true, expected);
  }

  /** */
  @SuppressWarnings("unchecked")
  public void testNavigationWithoutConstraint() {
    Object expected =
        Arrays.asList(
            new Object[] {emp1, proj1},
            new Object[] {emp2, proj1},
            new Object[] {emp3, proj1},
            new Object[] {emp2, proj2},
            new Object[] {emp3, proj2},
            new Object[] {emp4, proj3},
            new Object[] {emp5, proj3});

    JDOQLTypedQuery<Department> query = getPM().newJDOQLTypedQuery(Department.class);
    QDepartment cand = QDepartment.candidate();
    QEmployee e = QEmployee.variable("e");
    QProject p = QProject.variable("p");
    query.filter(cand.employees.contains(e).and(e.projects.contains(p)));
    query.result(false, e, p);

    QueryElementHolder<Department> holder =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ "e, p",
            /*INTO*/ null,
            /*FROM*/ Department.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ "employees.contains(e) && e.projects.contains(p)",
            /*VARIABLES*/ "Employee e; Project p",
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ null,
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ query,
            /*paramValues*/ null);

    executeAPIQuery(ASSERTION_FAILED, holder, expected);
    executeSingleStringQuery(ASSERTION_FAILED, holder, expected);
    executeJDOQLTypedQuery(ASSERTION_FAILED, holder, null, true, expected);
  }

  /** */
  @SuppressWarnings("unchecked")
  public void testNavigationWithThis() {
    Object expected =
        Arrays.asList(
            new Object[] {dept1, emp1, proj1},
            new Object[] {dept1, emp2, proj1},
            new Object[] {dept1, emp3, proj1},
            new Object[] {dept1, emp2, proj2},
            new Object[] {dept1, emp3, proj2},
            new Object[] {dept2, emp4, proj3},
            new Object[] {dept2, emp5, proj3});

    JDOQLTypedQuery<Department> query = getPM().newJDOQLTypedQuery(Department.class);
    QDepartment cand = QDepartment.candidate();
    QEmployee e = QEmployee.variable("e");
    QProject p = QProject.variable("p");
    query.filter(cand.employees.contains(e).and(e.projects.contains(p)));
    query.result(false, cand, e, p);

    QueryElementHolder<Department> holder =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ "this, e, p",
            /*INTO*/ null,
            /*FROM*/ Department.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ "employees.contains(e) && e.projects.contains(p)",
            /*VARIABLES*/ "Employee e; Project p",
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ null,
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ query,
            /*paramValues*/ null);

    executeAPIQuery(ASSERTION_FAILED, holder, expected);
    executeSingleStringQuery(ASSERTION_FAILED, holder, expected);
    executeJDOQLTypedQuery(ASSERTION_FAILED, holder, null, true, expected);
  }

  /** */
  @SuppressWarnings("unchecked")
  public void testNavigationWithThisConstraint() {
    Object expected =
        Arrays.asList(
            new Object[] {emp1, proj1},
            new Object[] {emp2, proj1},
            new Object[] {emp3, proj1},
            new Object[] {emp2, proj2},
            new Object[] {emp3, proj2});

    JDOQLTypedQuery<Department> query = getPM().newJDOQLTypedQuery(Department.class);
    QDepartment cand = QDepartment.candidate();
    QEmployee e = QEmployee.variable("e");
    QProject p = QProject.variable("p");
    query.filter(cand.deptid.eq(1l).and(cand.employees.contains(e)).and(e.projects.contains(p)));
    query.result(false, e, p);

    QueryElementHolder<Department> holder =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ "e, p",
            /*INTO*/ null,
            /*FROM*/ Department.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ "deptid == 1 && employees.contains(e) && e.projects.contains(p)",
            /*VARIABLES*/ "Employee e; Project p",
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ null,
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ query,
            /*paramValues*/ null);

    executeAPIQuery(ASSERTION_FAILED, holder, expected);
    executeSingleStringQuery(ASSERTION_FAILED, holder, expected);
    executeJDOQLTypedQuery(ASSERTION_FAILED, holder, null, true, expected);
  }

  /** */
  @SuppressWarnings("unchecked")
  public void testNavigationWithCompanyConstraint() {
    Object expected =
        Arrays.asList(
            new Object[] {emp1, proj1},
            new Object[] {emp2, proj1},
            new Object[] {emp3, proj1},
            new Object[] {emp2, proj2},
            new Object[] {emp3, proj2},
            new Object[] {emp4, proj3},
            new Object[] {emp5, proj3});

    JDOQLTypedQuery<Department> query = getPM().newJDOQLTypedQuery(Department.class);
    QDepartment cand = QDepartment.candidate();
    QEmployee e = QEmployee.variable("e");
    QProject p = QProject.variable("p");
    query.filter(
        cand.company
            .name
            .eq("Sun Microsystems, Inc.")
            .and(cand.employees.contains(e))
            .and(e.projects.contains(p)));
    query.result(false, e, p);

    QueryElementHolder<Department> holder =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ "e, p",
            /*INTO*/ null,
            /*FROM*/ Department.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ "company.name == \"Sun Microsystems, Inc.\" && employees.contains(e) && e.projects.contains(p)",
            /*VARIABLES*/ "Employee e; Project p",
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ null,
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ query,
            /*paramValues*/ null);

    executeAPIQuery(ASSERTION_FAILED, holder, expected);
    executeSingleStringQuery(ASSERTION_FAILED, holder, expected);
    executeJDOQLTypedQuery(ASSERTION_FAILED, holder, null, true, expected);
  }

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