/*
 * 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.IPCRect;
import org.apache.jdo.tck.pc.converter.PCRect;
import org.apache.jdo.tck.pc.converter.PCRectAnnotated;
import org.apache.jdo.tck.pc.mylib.Point;
import org.apache.jdo.tck.util.BatchTestRunner;
import org.apache.jdo.tck.util.PointToStringConverter;

/**
 * <B>Title:</B>PointAttributeConverterTest <br>
 * <B>Keywords:</B> mapping <br>
 * <B>Assertion ID:</B> [not identified] <br>
 * <B>Assertion Description: </B> A IPCRect instance refers two Point instances, that are stored as
 * strings in the datastore. A Point instance is converted using an AttributeConverter.
 */
public class PointAttributeConverterTest extends JDO_Test {

  private static final int UL_X = 1;
  private static final int UL_Y = 10;
  private static final int LR_X = 10;
  private static final int LR_Y = 1;

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

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

  /** Test method creating and storing a PCRectString instance. */
  public void testStorePCRectStringInstance() {
    runStoreIPCRectInstance(PCRect.class);
  }

  /** Test method reading a PCRectString instance from the datastore. */
  public void testReadPCRectStringInstance() {
    runReadIPCRectInstance(PCRect.class);
  }

  /** Test method modifying a PCRectString instance and storing in the datastore. */
  public void testModifyPCRectStringInstance() {
    runModifyIPCRectInstance(PCRect.class);
  }

  /** Test method running a PCRectString query with a query parameter of type Point. */
  public void testPCRectStringQueryWithPointParam() {
    runQueryWithPointParameter(PCRect.class);
  }

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

  /** Test method creating and storing a PCRectStringAnnotated instance. */
  public void testStorePCRectStringAnnotatedInstance() {
    runStoreIPCRectInstance(PCRectAnnotated.class);
  }

  /** Test method reading a PCRectStringAnnotated instance from the datastore. */
  public void testReadPCRectStringAnnotatedInstance() {
    runReadIPCRectInstance(PCRectAnnotated.class);
  }

  /** Test method modifying a PCRectStringAnnotated instance and storing in the datastore. */
  public void testModifyPCRectStringAnnotatedInstance() {
    runModifyIPCRectInstance(PCRectAnnotated.class);
  }

  /** Test method running a PCRectStringAnnotated query with a query parameter of type String. */
  public void testPCRectStringAnnotatedQueryWithPointParam() {
    runQueryWithPointParameter(PCRectAnnotated.class);
  }

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

  // Helper methods

  /**
   * Helper method creating a IPCRect instance. It should call AttributeConverter method
   * convertToDatastore.
   */
  private <T extends IPCRect> void runStoreIPCRectInstance(Class<T> pcrectClass) {
    int nrOfDbCalls = PointToStringConverter.getNrOfConvertToDatastoreCalls();
    int nrOfAttrCalls = PointToStringConverter.getNrOfConvertToAttributeCalls();

    // Create a persistent IPCRect instance and store its oid
    // AttributeConverter method convertToDatastore is called when persisting instance
    createIPCRectInstances(pcrectClass, 1);

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

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

    // Create a persistent IPCRect instance and store its oid
    oid = createIPCRectInstances(pcrectClass, 1);

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

    nrOfDbCalls = PointToStringConverter.getNrOfConvertToDatastoreCalls();
    nrOfAttrCalls = PointToStringConverter.getNrOfConvertToAttributeCalls();
    pm = getPM();
    pm.currentTransaction().begin();
    // Read the IPCRect instance from the datastore, this should call convertToAttribute
    rect = (IPCRect) pm.getObjectById(oid);
    Point ul = rect.getUpperLeft();
    Point lr = rect.getLowerRight();
    pm.currentTransaction().commit();

    // convertToDatastore should not be called
    assertEquals(0, PointToStringConverter.getNrOfConvertToDatastoreCalls() - nrOfDbCalls);
    // convertToAttribute should be called twice
    assertEquals(2, PointToStringConverter.getNrOfConvertToAttributeCalls() - nrOfAttrCalls);
    // Check the values of the associated Point instances
    assertEquals(UL_X, ul.getX());
    assertEquals(UL_Y, ul.getY() == null ? 0 : ul.getY().intValue());
    assertEquals(LR_X, lr.getX());
    assertEquals(LR_Y, lr.getY() == null ? 0 : lr.getY().intValue());
  }

  /**
   * Helper method modifying a IPCRect instance. It should call AttributeConverter method
   * convertToDatastore.
   */
  private <T extends IPCRect> void runModifyIPCRectInstance(Class<T> pcrectClass) {
    Transaction tx;
    IPCRect rect;
    Object oid;
    int nrOfDbCalls;
    int nrOfAttrCalls;

    // Create a persistent IPCRect instance and store its oid
    oid = createIPCRectInstances(pcrectClass, 1);

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

    nrOfDbCalls = PointToStringConverter.getNrOfConvertToDatastoreCalls();
    nrOfAttrCalls = PointToStringConverter.getNrOfConvertToAttributeCalls();
    pm = getPM();
    tx = pm.currentTransaction();
    tx.begin();
    rect = (IPCRect) pm.getObjectById(oid);
    // should trigger convertToAttribute
    rect.getLowerRight();
    rect.getUpperLeft();
    // Update IPCRect instance, this should call convertToDatastore
    rect.setUpperLeft(new Point(UL_X + 1, UL_Y + 1));
    rect.setLowerRight(new Point(LR_X + 1, LR_Y + 1));
    // IPCRect instance should be dirty
    assertTrue(JDOHelper.isDirty(rect));
    tx.commit();

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

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

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

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

    nrOfDbCalls = PointToStringConverter.getNrOfConvertToDatastoreCalls();
    nrOfAttrCalls = PointToStringConverter.getNrOfConvertToAttributeCalls();
    pm = getPM();
    pm.currentTransaction().begin();
    try (Query<T> q = pm.newQuery(pcrectClass, "this.upperLeft == :point")) {
      q.setParameters(new Point(UL_X + 1, UL_Y + 1));
      // AttributeConverter method convertToAttribute is called when loading instance from the
      // datastore
      List<T> res = q.executeList();
      assertEquals(1, res.size());
      IPCRect rect = res.get(0);
      Point ul = rect.getUpperLeft();
      Point lr = rect.getLowerRight();

      // Check the coordinates of the associated Point instances
      assertEquals(UL_X + 1, ul.getX());
      assertEquals(UL_Y + 1, ul.getY() == null ? 0 : ul.getY().intValue());
      assertEquals(LR_X + 1, lr.getX());
      assertEquals(LR_Y + 1, lr.getY() == null ? 0 : lr.getY().intValue());
    } catch (Exception e) {
      fail(e.getMessage());
    } finally {
      pm.currentTransaction().commit();
    }

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

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

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

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

    nrOfDbCalls = PointToStringConverter.getNrOfConvertToDatastoreCalls();
    nrOfAttrCalls = PointToStringConverter.getNrOfConvertToAttributeCalls();
    pm = getPM();
    pm.currentTransaction().begin();
    try (Query<T> q = pm.newQuery(pcrectClass, "this.upperLeft == str")) {
      q.declareParameters("String str");
      q.setParameters("3:12");
      // AttributeConverter method convertToAttribute is called when loading instance from the
      // datastore
      List<T> res = q.executeList();
      assertEquals(1, res.size());
      IPCRect rect = res.get(0);
      Point ul = rect.getUpperLeft();
      Point lr = rect.getLowerRight();

      // Check the coordinates of the associated Point instances
      assertEquals(UL_X + 2, ul.getX());
      assertEquals(UL_Y + 2, ul.getY() == null ? 0 : ul.getY().intValue());
      assertEquals(LR_X + 2, lr.getX());
      assertEquals(LR_Y + 2, lr.getY() == null ? 0 : lr.getY().intValue());
    } finally {
      pm.currentTransaction().commit();
    }

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

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

    if (nrOfObjects < 1) {
      return null;
    }

    pm = getPM();
    try {
      pm.currentTransaction().begin();
      rect = pcrectClass.getConstructor().newInstance();
      rect.setUpperLeft(new Point(UL_X, UL_Y));
      rect.setLowerRight(new Point(LR_X, LR_Y));
      pm.makePersistent(rect);
      oid = pm.getObjectId(rect);
      for (int i = 1; i < nrOfObjects; i++) {
        rect = pcrectClass.getConstructor().newInstance();
        rect.setUpperLeft(new Point(UL_X + i, UL_Y + i));
        rect.setLowerRight(new Point(LR_X + i, LR_Y + i));
        pm.makePersistent(rect);
      }
      pm.currentTransaction().commit();
    } catch (NoSuchMethodException
        | SecurityException
        | InstantiationException
        | IllegalAccessException
        | IllegalArgumentException
        | InvocationTargetException ex) {
      fail("Error creating IPCRect instance: " + ex.getMessage());
    } finally {
      if (pm.currentTransaction().isActive()) {
        pm.currentTransaction().rollback();
      }
    }
    return oid;
  }
}
