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

import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.Transaction;
import org.apache.jdo.tck.pc.query.OptionalSample;
import org.apache.jdo.tck.query.QueryElementHolder;
import org.apache.jdo.tck.query.QueryTest;
import org.apache.jdo.tck.util.BatchTestRunner;

/**
 * <B>Title:</B> Optional Fields. <br>
 * <B>Keywords:</B> query <br>
 * <B>Assertion ID:</B> A14.6.2-9 <br>
 * <B>Assertion Description: </B> Queries on fields of type java.util.Optional .
 */
public class SupportedOptionalMethods extends QueryTest {

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

  private static final int PC_ID = 1;
  private static final int PC_EMPTY_ID = 3;
  private static final int PC_NULL_ID = 4;
  private static final int REFERENCED_PC1_ID = 88;
  private static final int REFERENCED_PC2_ID = 99;
  private static final String STRING = "Hello JDO";
  private static final Integer INTEGER = 2016;
  private static final Date DATE = new Date(1000000000);
  private Object oidReferencedPC1;
  private Object oidReferencedPC2;
  private Object oidPC;
  private Object oidEmpty;
  private Object oidNull;

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

  /** */
  public void testQueriesWithPresence() {
    // Matches 'optionalPC.isPresent() == true'
    checkQuery("optionalPC != null", oidPC, oidReferencedPC1);

    // matches !isPresent() but does NOT match Java 'optionalPC==null'
    checkQuery("optionalPC == null", oidEmpty, oidNull, oidReferencedPC2);

    // matches isPresent()
    checkQuery("!(optionalPC == null)", oidReferencedPC1, oidPC);

    // matches !isPresent()
    checkQuery("!(optionalPC != null)", oidReferencedPC2, oidEmpty, oidNull);

    checkQuery("optionalPC.get() != null", oidPC, oidReferencedPC1);
    checkQuery("optionalPC.get() == null", oidEmpty, oidNull, oidReferencedPC2);
    checkQuery("optionalPC.isPresent()", oidPC, oidReferencedPC1);
    checkQuery("!optionalPC.isPresent()", oidReferencedPC2, oidEmpty, oidNull);

    // querying non-PC 'Optional' fields
    checkOptionalForPresence("optionalString");
    checkOptionalForPresence("optionalDate");
    checkOptionalForPresence("optionalInteger");
  }

  private void checkOptionalForPresence(String fieldName) {
    checkQuery(fieldName + " != null", oidPC);
    checkQuery(fieldName + " == null", oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2);
    checkQuery("!(" + fieldName + " == null)", oidPC);
    checkQuery(
        "!(" + fieldName + " != null)", oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2);

    checkQuery(fieldName + ".get() != null", oidPC);
    checkQuery(fieldName + ".get() == null", oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2);
    checkQuery(fieldName + ".isPresent()", oidPC);
    checkQuery(
        "!" + fieldName + ".isPresent()", oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2);
  }

  public void testQueriesWithNavigation() {
    checkQuery("optionalPC.id == " + REFERENCED_PC1_ID, oidPC);
    checkQuery("optionalPC.id != " + REFERENCED_PC1_ID, oidReferencedPC1);
    checkQuery("!(optionalPC.id == " + REFERENCED_PC1_ID + ")", oidReferencedPC1);
    checkQuery("optionalPC.get().id == " + REFERENCED_PC1_ID, oidPC);
    checkQuery("optionalPC.get().id != " + REFERENCED_PC1_ID, oidReferencedPC1);
    checkQuery("!(optionalPC.get().id == " + REFERENCED_PC1_ID + ")", oidReferencedPC1);
    checkQuery("optionalPC.optionalPC.isPresent()", oidPC);

    // The following reflects the changed behavior in JDO 3.2 in  the sense that
    // all instances are returned where either 'optionalPC.optionalPC==null' (not present)
    // or 'optionalPC==null' (the 'null' evaluates to 'null', which is followed until it is
    // evaluated in the 'isPresent()'). In other words, the query also returns all
    // objects that match '!(optionalPC.isPresent())'.
    checkQuery(
        "!(optionalPC.optionalPC.isPresent())",
        oidReferencedPC1,
        oidReferencedPC2,
        oidEmpty,
        oidNull);

    // A query where 'optionalPC!=null' and 'optionalPC.optionalPC==null;
    // can be done as follows:
    checkQuery("optionalPC.isPresent() && !(optionalPC.optionalPC.isPresent())", oidReferencedPC1);

    checkQuery("optionalPC.optionalPC.id == " + REFERENCED_PC2_ID, oidPC);
    checkQuery("optionalPC.get().optionalPC.get().id == " + REFERENCED_PC2_ID, oidPC);

    // test with && operator
    checkQuery(
        "!(optionalPC.isPresent() && optionalPC.id == " + REFERENCED_PC1_ID + ")",
        oidReferencedPC1,
        oidReferencedPC2,
        oidEmpty,
        oidNull);
  }

  private void checkQuery(String filter, Object... resultOids) {
    QueryElementHolder<OptionalSample> qeh =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ null,
            /*INTO*/ null,
            /*FROM*/ OptionalSample.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ filter,
            /*VARIABLES*/ null,
            /*PARAMETERS*/ null,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ null,
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ null,
            /*paramValues*/ null);

    ArrayList<Object> expectedResults = new ArrayList<>();
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();
      for (Object resultOid : resultOids) {
        expectedResults.add(pm.getObjectById(resultOid));
      }
    } finally {
      if (tx.isActive()) {
        tx.rollback();
      }
    }

    executeAPIQuery(ASSERTION_FAILED, qeh, expectedResults);
    executeSingleStringQuery(ASSERTION_FAILED, qeh, expectedResults);
  }

  /** This methods tests Optional fields and parameters. */
  public void testParameterOptional() {
    OptionalSample osReferencedPC1 = getOptionalSampleById(oidReferencedPC1);
    String paramDecl = "java.util.Optional op";
    Map<String, Object> paramValues = new HashMap<>();

    paramValues.put("op", Optional.of(osReferencedPC1));
    checkQuery("this.optionalPC == op", paramDecl, paramValues, new Object[] {oidPC});

    paramValues.put("op", Optional.of(DATE));
    checkQuery("this.optionalDate == op", paramDecl, paramValues, new Object[] {oidPC});

    paramValues.put("op", Optional.of(INTEGER));
    checkQuery("this.optionalInteger == op", paramDecl, paramValues, new Object[] {oidPC});

    paramValues.put("op", Optional.of(STRING));
    checkQuery("this.optionalString == op", paramDecl, paramValues, new Object[] {oidPC});
  }

  /** This methods tests Optional fields and parameters with auto de-referencing. */
  public void testParameterOptionalAutoDeref() {
    OptionalSample osReferencedPC1 = getOptionalSampleById(oidReferencedPC1);
    Map<String, Object> paramValues = new HashMap<>();

    paramValues.put("op", osReferencedPC1);
    checkQuery(
        "this.optionalPC == op",
        OptionalSample.class.getName() + " op",
        paramValues,
        new Object[] {oidPC});

    paramValues.put("op", DATE);
    checkQuery("this.optionalDate == op", "java.util.Date op", paramValues, new Object[] {oidPC});

    paramValues.put("op", INTEGER);
    checkQuery("this.optionalInteger == op", "Integer op", paramValues, new Object[] {oidPC});

    paramValues.put("op", STRING);
    checkQuery("this.optionalString == op", "String op", paramValues, new Object[] {oidPC});
  }

  private OptionalSample getOptionalSampleById(Object id) {
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();
      return (OptionalSample) pm.getObjectById(id);
    } finally {
      if (tx.isActive()) {
        tx.rollback();
      }
    }
  }

  /** This methods tests that empty Optional fields and parameters matches with Optional.empty(). */
  public void testParameterOptionalWithEmptyFields() {
    String paramDecl = "java.util.Optional op";
    Map<String, Object> paramValues = new HashMap<>();
    paramValues.put("op", Optional.empty());
    checkQuery(
        "this.optionalPC == op",
        paramDecl,
        paramValues,
        new Object[] {oidEmpty, oidNull, oidReferencedPC2});
    checkQuery(
        "this.optionalDate == op",
        paramDecl,
        paramValues,
        new Object[] {oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2});
    checkQuery(
        "this.optionalInteger == op",
        paramDecl,
        paramValues,
        new Object[] {oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2});
    checkQuery(
        "this.optionalString == op",
        paramDecl,
        paramValues,
        new Object[] {oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2});
  }

  /** This methods tests that Optional fields and parameters matches with (Optional)null. */
  public void testParameterOptionalWithNull() {
    String paramDecl = "java.util.Optional op";
    Map<String, Object> paramValues = new HashMap<>();
    paramValues.put("op", null);
    checkQuery(
        "this.optionalPC == op",
        paramDecl,
        paramValues,
        new Object[] {oidEmpty, oidNull, oidReferencedPC2});
    checkQuery(
        "this.optionalDate == op",
        paramDecl,
        paramValues,
        new Object[] {oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2});
    checkQuery(
        "this.optionalInteger == op",
        paramDecl,
        paramValues,
        new Object[] {oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2});
    checkQuery(
        "this.optionalString == op",
        paramDecl,
        paramValues,
        new Object[] {oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2});
  }

  /** This methods tests that Optional fields and parameters matches with (Object)null. */
  public void testParameterOptionalNull() {
    Map<String, Object> paramValues = new HashMap<>();
    paramValues.put("op", null);
    checkQuery(
        "this.optionalPC == op",
        OptionalSample.class.getName() + " op",
        paramValues,
        new Object[] {oidEmpty, oidNull, oidReferencedPC2});
    checkQuery(
        "this.optionalDate == op",
        "java.util.Date op",
        paramValues,
        new Object[] {oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2});
    checkQuery(
        "this.optionalInteger == op",
        "java.lang.Integer op",
        paramValues,
        new Object[] {oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2});
    checkQuery(
        "this.optionalString == op",
        "java.lang.String op",
        paramValues,
        new Object[] {oidEmpty, oidNull, oidReferencedPC1, oidReferencedPC2});
  }

  /** This methods tests that Optional fields can be accessed in subqueries. */
  public void testSubqueries() {
    String queryStr1 =
        "SELECT FROM "
            + OptionalSample.class.getName()
            + " WHERE "
            + "(select max(a.id) from "
            + OptionalSample.class.getName()
            + " a "
            + "where a.optionalPC.isPresent() ) == id";
    Object[] expectedResult1 = new Object[] {oidReferencedPC1};
    checkSingleStringQuery(queryStr1, expectedResult1);

    String queryStr2 =
        "SELECT FROM "
            + OptionalSample.class.getName()
            + " WHERE "
            + "(select max(a.id) from "
            + OptionalSample.class.getName()
            + " a "
            + "where a.optionalPC.get() != null) == id";
    Object[] expectedResult2 = new Object[] {oidReferencedPC1};
    checkSingleStringQuery(queryStr2, expectedResult2);
  }

  /** This methods tests that Optional fields can be accessed in subqueries. */
  public void testOptionalAggregation() {
    String clsName = OptionalSample.class.getName();

    String queryStr1 = "SELECT AVG(optionalInteger) FROM " + clsName;
    Query<?> q1 = pm.newQuery(queryStr1);
    executeJDOQuery(ASSERTION_FAILED, q1, queryStr1, false, null, (double) INTEGER, true);

    String queryStr2 = "SELECT AVG(optionalInteger.get()) FROM " + clsName;
    Query<?> q2 = pm.newQuery(queryStr2);
    executeJDOQuery(ASSERTION_FAILED, q2, queryStr2, false, null, (double) INTEGER, true);

    // return the object whose Integer is the same as the AVG of all
    // objects that have the Integer present.
    String queryStrSub1 =
        "SELECT FROM "
            + clsName
            + " WHERE "
            + "(select avg(a.optionalInteger) from "
            + clsName
            + " a "
            + "where a.optionalInteger.isPresent() ) == optionalInteger";
    Object[] expectedResult1 = new Object[] {oidPC};
    checkSingleStringQuery(queryStrSub1, expectedResult1);

    String queryStrSub2 =
        "SELECT FROM "
            + clsName
            + " WHERE "
            + "(select avg(a.optionalInteger.get()) from "
            + clsName
            + " a "
            + "where a.optionalInteger.isPresent() ) == optionalInteger";
    Object[] expectedResult2 = new Object[] {oidPC};
    checkSingleStringQuery(queryStrSub2, expectedResult2);

    // Find all where the average is the same as the integer value itself.
    // This returns ALL objects!!!
    String queryStrSub3 =
        "SELECT FROM "
            + clsName
            + " WHERE "
            + "(select avg(a.optionalInteger) from "
            + clsName
            + " a "
            + " ) == optionalInteger";
    Object[] expectedResult3 = new Object[] {oidPC};
    checkSingleStringQuery(queryStrSub3, expectedResult3);
  }

  private void checkSingleStringQuery(String singleStringJDOQL, Object... resultOids) {
    ArrayList<Object> expectedResults = new ArrayList<>();
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();
      for (Object resultOid : resultOids) {
        expectedResults.add(pm.getObjectById(resultOid));
      }
    } finally {
      if (tx.isActive()) tx.rollback();
    }

    Query<?> singleStringQuery = pm.newQuery(singleStringJDOQL);
    executeJDOQuery(
        ASSERTION_FAILED, singleStringQuery, singleStringJDOQL, false, null, expectedResults, true);
  }

  private void checkQuery(
      String filter, String paramDecl, Map<String, Object> paramValues, Object[] result) {
    QueryElementHolder<OptionalSample> qeh =
        new QueryElementHolder<>(
            /*UNIQUE*/ null,
            /*RESULT*/ null,
            /*INTO*/ null,
            /*FROM*/ OptionalSample.class,
            /*EXCLUDE*/ null,
            /*WHERE*/ filter,
            /*VARIABLES*/ null,
            /*PARAMETERS*/ paramDecl,
            /*IMPORTS*/ null,
            /*GROUP BY*/ null,
            /*ORDER BY*/ null,
            /*FROM*/ null,
            /*TO*/ null,
            /*JDOQLTyped*/ null,
            /*paramValues*/ paramValues);

    ArrayList<Object> expectedResults = new ArrayList<>();
    PersistenceManager pm = getPM();
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();
      for (Object o : result) {
        if (o instanceof String || o instanceof Date || o instanceof Integer) {
          expectedResults.add(o);
        } else {
          expectedResults.add(pm.getObjectById(o));
        }
      }
    } finally {
      if (tx.isActive()) {
        tx.rollback();
      }
    }

    executeAPIQuery(ASSERTION_FAILED, qeh, expectedResults);
    executeSingleStringQuery(ASSERTION_FAILED, qeh, expectedResults);
  }

  /** Result class for queries on OptionalSample. */
  public static class ResultInfo {
    public long id;
    public String optionalString;

    public ResultInfo() {}

    public ResultInfo(long id, String optionalString) {
      this.id = id;
      this.optionalString = optionalString;
    }
  }

  /** Test Optional.orElse() in the SELECT clause of JDOQL queries. */
  @SuppressWarnings("unchecked")
  public void testOrElseInSELECT() {
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();
      Query<?> q =
          pm.newQuery(
              "SELECT id, optionalString.orElse('NotPresent') FROM "
                  + OptionalSample.class.getName());
      q.setResultClass(ResultInfo.class);
      Collection<ResultInfo> c = (Collection<ResultInfo>) q.execute();
      if (c.size() != 5) {
        fail(ASSERTION_FAILED, "Wrong result count: " + c.size());
      }
      for (ResultInfo i : c) {
        switch ((int) i.id) {
          case PC_ID:
            if (!STRING.equals(i.optionalString)) {
              fail(ASSERTION_FAILED, "Wrong string value: " + i.optionalString);
            }
            break;
          case PC_EMPTY_ID:
          case PC_NULL_ID:
          case REFERENCED_PC1_ID:
          case REFERENCED_PC2_ID:
            assertEquals("NotPresent", i.optionalString);
            break;
          default:
            fail(ASSERTION_FAILED, "Wrong object id: " + i.id);
        }
      }
    } finally {
      if (tx.isActive()) {
        tx.rollback();
      }
    }
  }

  /**
   * This test assert that null-references are converted to Optional.empty() when loaded from the
   * database.
   */
  public void testPersistenceNotNull() {
    OptionalSample osNotNull = getOptionalSampleById(oidNull);

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

      if (osNotNull.getOptionalDate() == null) {
        fail(ASSERTION_FAILED, "Date field was 'null'");
      }
      if (osNotNull.getOptionalInteger() == null) {
        fail(ASSERTION_FAILED, "Integer field was 'null'");
      }
      if (osNotNull.getOptionalPC() == null) {
        fail(ASSERTION_FAILED, "optionalPC field was 'null'");
      }
      if (osNotNull.getOptionalString() == null) {
        fail(ASSERTION_FAILED, "String field was 'null'");
      }

      if (osNotNull.getOptionalDate().isPresent()) {
        fail(ASSERTION_FAILED, "Date field was present");
      }
      if (osNotNull.getOptionalInteger().isPresent()) {
        fail(ASSERTION_FAILED, "Integer field was present");
      }
      if (osNotNull.getOptionalPC().isPresent()) {
        fail(ASSERTION_FAILED, "optionalPC field was present");
      }
      if (osNotNull.getOptionalString().isPresent()) {
        fail(ASSERTION_FAILED, "String field was present");
      }
    } finally {
      if (tx.isActive()) {
        tx.rollback();
      }
    }
  }

  /**
   * @see org.apache.jdo.tck.JDO_Test#localSetUp()
   */
  @Override
  protected void localSetUp() {
    addTearDownClass(OptionalSample.class);
    insertOptionalSample(getPM());
  }

  private void insertOptionalSample(PersistenceManager pm) {
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();

      // Create two objects that are referenced by other objects, this allows
      // testing of navigation in queries.
      // The referencedPC1 will be referenced by 'osPC',
      // The referencedPC2 will be referenced by referencedPC1.
      OptionalSample referencedPC1 = new OptionalSample();
      referencedPC1.setId(REFERENCED_PC1_ID);
      pm.makePersistent(referencedPC1);
      oidReferencedPC1 = pm.getObjectId(referencedPC1);

      OptionalSample referencedPC2 = new OptionalSample();
      referencedPC2.setId(REFERENCED_PC2_ID);
      pm.makePersistent(referencedPC2);
      oidReferencedPC2 = pm.getObjectId(referencedPC2);

      referencedPC1.setOptionalPC(Optional.of(referencedPC2));

      OptionalSample osPC = new OptionalSample();
      osPC.setId(PC_ID);
      osPC.setOptionalPC(Optional.of(referencedPC1));
      osPC.setOptionalDate(Optional.of(DATE));
      osPC.setOptionalInteger(Optional.of(INTEGER));
      osPC.setOptionalString(Optional.of(STRING));
      pm.makePersistent(osPC);
      oidPC = pm.getObjectId(osPC);

      // use empty optionals
      OptionalSample osEmpty = new OptionalSample();
      osEmpty.setId(PC_EMPTY_ID);
      osEmpty.setOptionalPC(Optional.empty());
      osEmpty.setOptionalDate(Optional.empty());
      osEmpty.setOptionalInteger(Optional.empty());
      osEmpty.setOptionalString(Optional.empty());
      pm.makePersistent(osEmpty);
      oidEmpty = pm.getObjectId(osEmpty);

      // use null for optional fields
      OptionalSample osNull = new OptionalSample();
      osNull.setId(PC_NULL_ID);
      osNull.setOptionalPC(null);
      osNull.setOptionalDate(null);
      osNull.setOptionalInteger(null);
      osNull.setOptionalString(null);
      pm.makePersistent(osNull);
      oidNull = pm.getObjectId(osNull);

      tx.commit();
    } finally {
      if (tx.isActive()) {
        tx.rollback();
      }
    }
  }

  @Override
  protected void localTearDown() {
    // set all references to null to allow deletion of (otherwise) referenced objects
    Transaction tx = getPM().currentTransaction();
    tx.begin();
    Query<OptionalSample> q = pm.newQuery(OptionalSample.class);
    for (OptionalSample os : q.executeList()) {
      os.setOptionalPC(Optional.empty());
    }
    tx.commit();

    super.localTearDown();
  }
}
