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

import java.util.ArrayList;
import java.util.List;
import java.util.ListIterator;
import javax.jdo.JDOQLTypedQuery;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.Transaction;
import org.apache.jdo.tck.pc.company.CompanyModelReader;
import org.apache.jdo.tck.pc.company.DentalInsurance;
import org.apache.jdo.tck.pc.company.QDentalInsurance;
import org.apache.jdo.tck.pc.fieldtypes.AllTypes;
import org.apache.jdo.tck.pc.mylib.PCPoint;
import org.apache.jdo.tck.query.QueryElementHolder;
import org.apache.jdo.tck.query.QueryTest;
import org.apache.jdo.tck.util.BatchTestRunner;

/**
 * <B>Title:</B> Ordering Specification <br>
 * <B>Keywords:</B> query <br>
 * <B>Assertion ID:</B> A14.6.6-1. <br>
 * <B>Assertion Description: </B> The <code>Query</code> ordering specification includes a list of
 * one or more ordering declarations separated by commas. Each ordering declaration includes an
 * expression whose type is one of:
 *
 * <UL>
 *   <LI>primitive types except <code>boolean</code>
 *   <LI>wrapper types except <code>Boolean</code>
 *   <LI><code>BigDecimal</code>
 *   <LI><code>BigInteger</code>
 *   <LI><code>String</code>
 *   <LI><code>Date</code>
 * </UL>
 *
 * followed by one of the following words: <code>&quot;ascending</code>&quot; or <code>
 * &quot;descending</code>&quot; which indicates the ordering of the values for that expression.
 * Ordering might be specified including navigation. The name of the field to be used in ordering
 * via navigation through single-valued fields is specified by the Java language syntax of <code>
 * field_name.field_name....field_name</code>.
 */
public class OrderingSpecification extends QueryTest {

  /** */
  private static final String ASSERTION_FAILED =
      "Assertion A14.6.6-1 (OrderingSpecification) failed: ";

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

  /** */
  public void testPositiveCompanyQueries0() {
    // nulls first
    List<DentalInsurance> expected =
        getTransientCompanyModelInstancesAsList(
            DentalInsurance.class,
            "dentalIns99",
            "dentalIns1",
            "dentalIns2",
            "dentalIns3",
            "dentalIns4",
            "dentalIns5");

    JDOQLTypedQuery<DentalInsurance> query = getPM().newJDOQLTypedQuery(DentalInsurance.class);
    QDentalInsurance cand = QDentalInsurance.candidate();
    query.orderBy(cand.lifetimeOrthoBenefit.asc().nullsFirst());

    QueryElementHolder<DentalInsurance> holder =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ null,
            /*INTO*/ null,
            /*FROM*/ DentalInsurance.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ null,
            /*VARIABLES*/ null,
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ "this.lifetimeOrthoBenefit ascending nulls first",
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ query,
            /*paramValues*/ null);

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

  /** */
  public void testPositiveCompanyQueries1() {
    // nulls last
    List<DentalInsurance> expected =
        getTransientCompanyModelInstancesAsList(
            DentalInsurance.class,
            "dentalIns1",
            "dentalIns2",
            "dentalIns3",
            "dentalIns4",
            "dentalIns5",
            "dentalIns99");

    JDOQLTypedQuery<DentalInsurance> query = getPM().newJDOQLTypedQuery(DentalInsurance.class);
    QDentalInsurance cand = QDentalInsurance.candidate();
    query.orderBy(cand.lifetimeOrthoBenefit.asc().nullsLast());

    QueryElementHolder<DentalInsurance> holder =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ null,
            /*INTO*/ null,
            /*FROM*/ DentalInsurance.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ null,
            /*VARIABLES*/ null,
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ "this.lifetimeOrthoBenefit ascending nulls last",
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ query,
            /*paramValues*/ null);

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

  /** */
  public void testPositive() {
    PersistenceManager pm = getPM();

    runTestOrderingSpecification01(pm);
    runTestOrderingSpecification02(pm);
    checkOrderingTypes(pm);
  }

  /** */
  void runTestOrderingSpecification01(PersistenceManager pm) {
    if (debug) logger.debug("\nExecuting test OrderingSpecification01() ...");

    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();

      Query<PCPoint> query = pm.newQuery(PCPoint.class);
      query.setCandidates(pm.getExtent(PCPoint.class, false));
      query.setOrdering("x ascending");
      Object results = query.execute();

      // check query result
      printOutput(results, inserted);
      checkQueryResultWithOrder(ASSERTION_FAILED, "null", results, inserted);
      if (debug) logger.debug("Test OrderingSpecification01(): Passed");

      tx.commit();
      tx = null;
    } finally {
      if ((tx != null) && tx.isActive()) tx.rollback();
    }
  }

  /** */
  void runTestOrderingSpecification02(PersistenceManager pm) {
    if (debug) logger.debug("\nExecuting test OrderingSpecification02() ...");

    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();

      Query<PCPoint> query = pm.newQuery(PCPoint.class);
      query.setCandidates(pm.getExtent(PCPoint.class, false));
      query.setOrdering("x descending");
      Object results = query.execute();

      // check query result
      List<PCPoint> expected = new ArrayList<>();
      ListIterator<PCPoint> li = inserted.listIterator(inserted.size());
      // construct expected results by iterating inserted objects backwards
      while (li.hasPrevious()) {
        PCPoint obj = li.previous();
        expected.add(obj);
      }
      expected = getFromInserted(expected);
      printOutput(results, expected);
      checkQueryResultWithOrder(ASSERTION_FAILED, "null", results, expected);
      if (debug) logger.debug("Test OrderingSpecification02(): Passed");

      tx.commit();
      tx = null;
    } finally {
      if ((tx != null) && tx.isActive()) tx.rollback();
    }
  }

  /** */
  void checkOrderingTypes(PersistenceManager pm) {
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();

      Query<AllTypes> query = pm.newQuery(AllTypes.class);
      query.setCandidates(pm.getExtent(AllTypes.class, false));

      StringBuilder buffer = new StringBuilder();
      buffer.append("  fld_byte ascending");
      buffer.append(", fld_char ascending");
      buffer.append(", fld_double ascending");
      buffer.append(", fld_float ascending");
      buffer.append(", fld_int ascending");
      buffer.append(", fld_long ascending");
      buffer.append(", fld_short ascending");
      buffer.append(", fld_Byte descending");
      buffer.append(", fld_Character descending");
      buffer.append(", fld_Double descending");
      buffer.append(", fld_Float ascending");
      buffer.append(", fld_Integer descending");
      buffer.append(", fld_Long descending");
      buffer.append(", fld_Short descending");
      buffer.append(", fld_String descending");
      buffer.append(", fld_Date descending");
      buffer.append(", fld_BigDecimal descending");
      buffer.append(", fld_BigInteger ascending");
      query.setOrdering(buffer.toString());
      Object results = query.execute();

      // Just check whether query compiles

      tx.commit();
      tx = null;
    } finally {
      if ((tx != null) && tx.isActive()) tx.rollback();
    }
  }

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