/*
 * 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
 *
 *     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
 * limitations under the License.
 */
package org.apache.jdo.tck.api.converter;

import java.lang.reflect.InvocationTargetException;
import java.util.List;
import javax.jdo.JDOHelper;
import javax.jdo.Query;
import javax.jdo.Transaction;
import org.apache.jdo.tck.JDO_Test;
import org.apache.jdo.tck.pc.converter.IPCPoint;
import org.apache.jdo.tck.pc.converter.PCPoint;
import org.apache.jdo.tck.pc.converter.PCPointAnnotated;
import org.apache.jdo.tck.pc.converter.PCPointProp;
import org.apache.jdo.tck.pc.converter.PCPointPropAnnotated;
import org.apache.jdo.tck.util.BatchTestRunner;
import org.apache.jdo.tck.util.IntegerToStringConverter;

/**
 * <B>Title:</B>IntAttributeConverterTest <br>
 * <B>Keywords:</B> mapping <br>
 * <B>Assertion ID:</B> [not identified] <br>
 * <B>Assertion Description: </B> A IPCPoint instance has an int and an Integer field, that are
 * stored as strings in the datastore. The int / Integer fields are converted using an
 * AttributeConverter.
 */
public class IntAttributeConverterTest extends JDO_Test {

  private static final int MIN_X = 1;
  private static final int MIN_Y = 5;

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

  /**
   * @see JDO_Test#localSetUp()
   */
  @Override
  protected void localSetUp() {
    addTearDownClass(PCPoint.class);
    addTearDownClass(PCPointAnnotated.class);
    addTearDownClass(PCPointProp.class);
    addTearDownClass(PCPointPropAnnotated.class);
  }

  /** Test method creating and storing a PCPoint instance. */
  public void testStorePCPointInstance() {
    runStoreIPCPointInstance(PCPoint.class);
  }

  /** Test method reading a PCPoint instance from the datastore. */
  public void testReadPCPointInstance() {
    runReadIPCPointInstance(PCPoint.class);
  }

  /** Test method modifying a PCPoint instance and storing in the datastore. */
  public void testModifyPCPointInstance() {
    runModifyIPCPointInstance(PCPoint.class);
  }

  /** Test method running a PCPoint query with a query parameter of type Point. */
  public void testPCPointQueryWithPointParam() {
    runQueryWithIntParameter(PCPoint.class);
  }

  /** Test method running a PCPoint query with a query parameter of type String. */
  public void testPCPointQueryWithStringParam() throws Exception {
    runQueryWithStringParameter(PCPoint.class);
  }

  /** Test method creating and storing a PCPointAnnotated instance. */
  public void testStorePCPointAnnotatedInstance() {
    runStoreIPCPointInstance(PCPointAnnotated.class);
  }

  /** Test method reading a PCPointAnnotated instance from the datastore. */
  public void testReadPCPointAnnotatedInstance() {
    runReadIPCPointInstance(PCPointAnnotated.class);
  }

  /** Test method modifying a PCPointAnnotated instance and storing in the datastore. */
  public void testModifyPCPointAnnotatedInstance() {
    runModifyIPCPointInstance(PCPointAnnotated.class);
  }

  /** Test method running a PCPointAnnotated query with a query parameter of type String. */
  public void testPCPointAnnotatedQueryWithPointParam() {
    runQueryWithIntParameter(PCPointAnnotated.class);
  }

  /** Test method running a PCPointAnnotated query with a query parameter of type Point. */
  public void testPCPointAnnotatedQueryWithStringParam() throws Exception {
    runQueryWithStringParameter(PCPointAnnotated.class);
  }

  /** Test method creating and storing a PCPoint instance. */
  public void testStorePCPointPropInstance() {
    runStoreIPCPointInstance(PCPointProp.class);
  }

  /** Test method reading a PCPoint instance from the datastore. */
  public void testReadPCPointPropInstance() {
    runReadIPCPointInstance(PCPointProp.class);
  }

  /** Test method modifying a PCPoint instance and storing in the datastore. */
  public void testModifyPCPointPropInstance() {
    runModifyIPCPointInstance(PCPointProp.class);
  }

  /** Test method running a PCPoint query with a query parameter of type Point. */
  public void testPCPointPropQueryWithPointParam() {
    runQueryWithIntParameter(PCPointProp.class);
  }

  /** Test method running a PCPoint query with a query parameter of type String. */
  public void testPCPointPropQueryWithStringParam() throws Exception {
    runQueryWithStringParameter(PCPointProp.class);
  }

  /** Test method creating and storing a PCPointAnnotated instance. */
  public void testStorePCPointPropAnnotatedInstance() {
    runStoreIPCPointInstance(PCPointPropAnnotated.class);
  }

  /** Test method reading a PCPointAnnotated instance from the datastore. */
  public void testReadPCPointPropAnnotatedInstance() {
    runReadIPCPointInstance(PCPointPropAnnotated.class);
  }

  /** Test method modifying a PCPointAnnotated instance and storing in the datastore. */
  public void testModifyPCPointPropAnnotatedInstance() {
    runModifyIPCPointInstance(PCPointPropAnnotated.class);
  }

  /** Test method running a PCPointAnnotated query with a query parameter of type String. */
  public void testPCPointPropAnnotatedQueryWithPointParam() {
    runQueryWithIntParameter(PCPointPropAnnotated.class);
  }

  /** Test method running a PCPointAnnotated query with a query parameter of type Point. */
  public void testPCPointPropAnnotatedQueryWithStringParam() throws Exception {
    runQueryWithStringParameter(PCPointPropAnnotated.class);
  }

  // Helper methods

  /**
   * Helper method creating a IPCPoint instance. It should call AttributeConverter method
   * convertToDatastore.
   */
  private <T extends IPCPoint> void runStoreIPCPointInstance(Class<T> pcPointClass) {
    int nrOfDbCalls = IntegerToStringConverter.getNrOfConvertToDatastoreCalls();
    int nrOfAttrCalls = IntegerToStringConverter.getNrOfConvertToAttributeCalls();

    // Create a persistent IPCPoint instance and store its oid
    // AttributeConverter method convertToDatastore is called when persisting instance
    createIPCPointInstances(pcPointClass, 1);

    // convertToDatastore should be called twice
    assertEquals(2, IntegerToStringConverter.getNrOfConvertToDatastoreCalls() - nrOfDbCalls);
    // convertToAttribute should not be called
    assertEquals(0, IntegerToStringConverter.getNrOfConvertToAttributeCalls() - nrOfAttrCalls);
  }

  /**
   * Helper method reading a IPCPoint instance from the datastore. It should call AttributeConverter
   * method convertToAttribute.
   */
  private <T extends IPCPoint> void runReadIPCPointInstance(Class<T> pcPointClass) {
    IPCPoint point;
    Object oid;
    int nrOfDbCalls;
    int nrOfAttrCalls;

    // Create a persistent IPCPoint instance and store its oid
    oid = createIPCPointInstances(pcPointClass, 1);

    // Cleanup the 2nd-level cache and close the pm to make sure PCPoint instances are not cached
    pm.getPersistenceManagerFactory().getDataStoreCache().evictAll(false, pcPointClass);
    pm.close();
    pm = null;

    nrOfDbCalls = IntegerToStringConverter.getNrOfConvertToDatastoreCalls();
    nrOfAttrCalls = IntegerToStringConverter.getNrOfConvertToAttributeCalls();
    pm = getPM();
    pm.currentTransaction().begin();
    // Read the IPCPoint instance from the datastore, this should call convertToAttribute
    point = (IPCPoint) pm.getObjectById(oid);
    int x = point.getX();
    Integer y = point.getY();
    pm.currentTransaction().commit();

    // convertToDatastore should not be called
    assertEquals(0, IntegerToStringConverter.getNrOfConvertToDatastoreCalls() - nrOfDbCalls);
    // convertToAttribute should be called twice
    assertEquals(2, IntegerToStringConverter.getNrOfConvertToAttributeCalls() - nrOfAttrCalls);
    // Check the values of the associated Point instances
    assertEquals(MIN_X, x);
    assertEquals(MIN_Y, y == null ? 0 : y.intValue());
  }

  /**
   * Helper method modifying a IPCPoint instance. It should call AttributeConverter method
   * convertToDatastore.
   */
  private <T extends IPCPoint> void runModifyIPCPointInstance(Class<T> pcPointClass) {
    Transaction tx;
    IPCPoint point;
    Object oid;
    int nrOfDbCalls;
    int nrOfAttrCalls;

    // Create a persistent IPCPoint instance and store its oid
    oid = createIPCPointInstances(pcPointClass, 1);

    // Cleanup the 2nd-level cache and close the pm to make sure PCPoint instances are not cached
    pm.getPersistenceManagerFactory().getDataStoreCache().evictAll(false, pcPointClass);
    pm.close();
    pm = null;

    nrOfDbCalls = IntegerToStringConverter.getNrOfConvertToDatastoreCalls();
    nrOfAttrCalls = IntegerToStringConverter.getNrOfConvertToAttributeCalls();
    pm = getPM();
    tx = pm.currentTransaction();
    tx.begin();
    // Load the PCPoint instance, this should call convertToAttribute
    point = (IPCPoint) pm.getObjectById(oid);
    // Update IPCPoint instance, this should call convertToDatastore
    point.setX(MIN_X + 1);
    point.setY(Integer.valueOf(MIN_Y + 1));
    // IPCPoint instance should be dirty
    assertTrue(JDOHelper.isDirty(point));
    tx.commit();

    // convertToDatastore should be called twice
    assertEquals(2, IntegerToStringConverter.getNrOfConvertToDatastoreCalls() - nrOfDbCalls);
    // convertToAttribute should be called twice
    assertEquals(2, IntegerToStringConverter.getNrOfConvertToAttributeCalls() - nrOfAttrCalls);
  }

  /**
   * Helper method running a query with an int parameter. The parameter value is converted using the
   * AttributeConverter.
   *
   * @throws Exception
   */
  private <T extends IPCPoint> void runQueryWithIntParameter(Class<T> pcPointClass) {
    int nrOfDbCalls;
    int nrOfAttrCalls;

    nrOfDbCalls = IntegerToStringConverter.getNrOfConvertToDatastoreCalls();
    nrOfAttrCalls = IntegerToStringConverter.getNrOfConvertToAttributeCalls();
    createIPCPointInstances(pcPointClass, 5);
    // convertToDatastore should be called twice per instance = 10 times
    assertEquals(10, IntegerToStringConverter.getNrOfConvertToDatastoreCalls() - nrOfDbCalls);
    // convertToAttribute should not be called
    assertEquals(0, IntegerToStringConverter.getNrOfConvertToAttributeCalls() - nrOfAttrCalls);

    // Cleanup the 2nd-level cache and close the pm to make sure PCPoint instances are not cached
    pm.getPersistenceManagerFactory().getDataStoreCache().evictAll(false, pcPointClass);
    pm.close();
    pm = null;

    nrOfDbCalls = IntegerToStringConverter.getNrOfConvertToDatastoreCalls();
    nrOfAttrCalls = IntegerToStringConverter.getNrOfConvertToAttributeCalls();
    pm = getPM();
    pm.currentTransaction().begin();
    try (Query<T> q = pm.newQuery(pcPointClass, "this.x == :param")) {
      q.setParameters(MIN_X + 1);
      // AttributeConverter method convertToAttribute is called when loading instance from the
      // datastore
      List<T> res = q.executeList();
      assertEquals(1, res.size());
      IPCPoint point = res.get(0);

      // Check the coordinates of the associated Point instances
      assertEquals(MIN_X + 1, point.getX());
      assertEquals(MIN_Y + 1, point.getY() == null ? 0 : point.getY().intValue());
    } catch (Exception e) {
      fail(e.getMessage());
    } finally {
      pm.currentTransaction().commit();
    }

    // convertToDatastore should be called to handle the query parameter
    assertTrue(IntegerToStringConverter.getNrOfConvertToDatastoreCalls() - nrOfDbCalls >= 1);
    // convertToAttribute should be called at least twice
    assertTrue(IntegerToStringConverter.getNrOfConvertToAttributeCalls() - nrOfAttrCalls >= 2);
  }

  /**
   * Helper method running a query with a Point parameter. The string parameter is compared to the
   * converted int field.
   *
   * @throws Exception
   */
  private <T extends IPCPoint> void runQueryWithStringParameter(Class<T> pcPointClass)
      throws Exception {
    int nrOfDbCalls;
    int nrOfAttrCalls;

    nrOfDbCalls = IntegerToStringConverter.getNrOfConvertToDatastoreCalls();
    nrOfAttrCalls = IntegerToStringConverter.getNrOfConvertToAttributeCalls();
    createIPCPointInstances(pcPointClass, 5);
    // convertToDatastore should be called twice per instance = 10 times
    assertEquals(10, IntegerToStringConverter.getNrOfConvertToDatastoreCalls() - nrOfDbCalls);
    // convertToAttribute should not be called
    assertEquals(0, IntegerToStringConverter.getNrOfConvertToAttributeCalls() - nrOfAttrCalls);

    // Cleanup the 2nd-level cache and close the pm to make sure PCPoint instances are not cached
    pm.getPersistenceManagerFactory().getDataStoreCache().evictAll(false, pcPointClass);
    pm.close();
    pm = null;

    nrOfDbCalls = IntegerToStringConverter.getNrOfConvertToDatastoreCalls();
    nrOfAttrCalls = IntegerToStringConverter.getNrOfConvertToAttributeCalls();
    pm = getPM();
    pm.currentTransaction().begin();
    try (Query<T> q = pm.newQuery(pcPointClass, "this.x == param")) {
      q.declareParameters("String param");
      q.setParameters("3");
      // AttributeConverter method convertToAttribute is called when loading instance from the
      // datastore
      List<T> res = q.executeList();
      assertEquals(1, res.size());
      IPCPoint point = res.get(0);

      assertEquals(MIN_X + 2, point.getX());
      assertEquals(MIN_Y + 2, point.getY() == null ? 0 : point.getY().intValue());
    } finally {
      pm.currentTransaction().commit();
    }

    // convertToDatastore should not be called
    assertTrue(IntegerToStringConverter.getNrOfConvertToDatastoreCalls() - nrOfDbCalls == 0);
    // convertToAttribute should be called at least twice
    assertTrue(IntegerToStringConverter.getNrOfConvertToAttributeCalls() - nrOfAttrCalls >= 2);
  }

  /**
   * Helper method to create IPCPoint instances.
   *
   * @param pcPointClass class instance of the IPCPoint implementation class to be created
   * @param nrOfObjects number of IPCPoint instances to be created
   * @return ObjectId of the first IPCPoint instance
   */
  private <T extends IPCPoint> Object createIPCPointInstances(
      Class<T> pcPointClass, int nrOfObjects) {
    IPCPoint point;
    Object oid = null;

    if (nrOfObjects < 1) {
      return null;
    }

    pm = getPM();
    try {
      pm.currentTransaction().begin();
      point = pcPointClass.getConstructor().newInstance();
      point.setX(MIN_X);
      point.setY(Integer.valueOf(MIN_Y));
      pm.makePersistent(point);
      oid = pm.getObjectId(point);
      for (int i = 1; i < nrOfObjects; i++) {
        point = pcPointClass.getConstructor().newInstance();
        point.setX(MIN_X + i);
        point.setY(Integer.valueOf(MIN_Y + i));
        pm.makePersistent(point);
      }
      pm.currentTransaction().commit();
    } catch (NoSuchMethodException
        | SecurityException
        | InstantiationException
        | IllegalAccessException
        | IllegalArgumentException
        | InvocationTargetException ex) {
      fail("Error creating IPCPoint instance: " + ex.getMessage());
    } finally {
      if (pm.currentTransaction().isActive()) {
        pm.currentTransaction().rollback();
      }
    }
    return oid;
  }
}
