/*
 * 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.api.persistencemanager.nullargs;

import java.util.Arrays;
import java.util.Collection;
import java.util.Iterator;
import javax.jdo.PersistenceManager;
import javax.jdo.Transaction;
import org.apache.jdo.tck.JDO_Test;
import org.apache.jdo.tck.pc.mylib.PCPoint;

/**
 * The superclass for the tests of null arguments to pm methods.
 *
 * <p>Null arguments to APIs that take an Object parameter cause the API to have no effect. Null
 * arguments to APIs that take Object[] or Collection will cause the API to throw
 * NullPointerException. Non-null Object[] or Collection arguments that contain null elements will
 * have the documented behavior for non-null elements, and the null elements will be ignored.
 */
public class PersistenceManagerNullsTest extends JDO_Test {

  /** */
  public static class MethodUnderTest {
    public void pmApi(PersistenceManager pm, Object obj) {
      throw new UnsupportedOperationException("Test must implement this method");
    }

    public <T> void pmApi(PersistenceManager pm, Collection<T> coll) {
      throw new UnsupportedOperationException("Test must implement this method");
    }

    public void pmApi(PersistenceManager pm, Object[] objs) {
      throw new UnsupportedOperationException("Test must implement this method");
    }

    public Object pmApiReturn(PersistenceManager pm, Object obj) {
      throw new UnsupportedOperationException("Test must implement this method");
    }

    public <T> Collection<T> pmApiReturn(PersistenceManager pm, Collection<T> coll) {
      throw new UnsupportedOperationException("Test must implement this method");
    }

    public Object[] pmApiReturn(PersistenceManager pm, Object[] objs) {
      throw new UnsupportedOperationException("Test must implement this method");
    }
  }

  private static final String ASSERTION3_FAILED = "Assertion A12.6-3 failed: ";

  private static final String ASSERTION4_FAILED = "Assertion A12.6-4 failed: ";

  private static final String ASSERTION5_FAILED = "Assertion A12.6-5 failed: ";

  protected PCPoint pNotNull = null;
  protected Collection<?> collNullElem = null;
  protected Collection<?> expectedCollection = null;
  protected final Object[] arrayNullElem = new Object[] {null, null};
  protected final Object[] expectedArray = new Object[] {null, null};
  protected Collection<?> testInstances = null;

  /** */
  protected PersistenceManagerNullsTest() {}

  /**
   * @see org.apache.jdo.tck.JDO_Test#localSetUp()
   */
  @Override
  protected void localSetUp() {
    // The order of addTearDownClass calls is significant
    // as it takes into account database FKs.
    addTearDownClass(PCPoint.class);

    // Initialize test objects and expected values
    pNotNull = new PCPoint(3, 5);
    arrayNullElem[1] = pNotNull;
    expectedArray[1] = pNotNull;
    collNullElem = Arrays.asList(arrayNullElem);

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

      tx.begin();
      try {
        pm.makePersistent(pNotNull);
      } catch (Exception e) {
        e.printStackTrace();
      }
      tx.commit();

      logger.debug(" \nSetup committed in DeletePersistentNullArgs()");
    } finally {
      if (tx.isActive()) {
        tx.rollback();
      }
    }
    expectedCollection = Arrays.asList(arrayNullElem);
  }

  protected static String toString(Object[] objs) {
    StringBuilder out = new StringBuilder();
    for (int i = 0; i < objs.length; i++) {
      out.append("[" + i + "]: ");
      if (objs[i] == null) out.append("null");
      else out.append(objs[i].toString());
      out.append(",  ");
    }
    return out.toString();
  }

  protected static <T> String toString(Collection<T> objs) {
    return toString(objs.toArray());
  }

  /**
   * Checks if expected and actual arguments match for null/non-null value
   *
   * @return true if arguments match
   * @param expected Collection
   * @param actual Collection
   */
  protected <S, T> boolean checkReturn(Collection<S> expected, Collection<T> actual) {
    S eElem = null;
    T aElem = null;
    if (expected.size() != actual.size()) return false;
    Iterator<S> eIt = expected.iterator();
    Iterator<T> aIt = actual.iterator();
    while (eIt.hasNext()) {
      eElem = eIt.next();
      aElem = aIt.next();
      if ((eElem == null && aElem != null) || (aElem == null && eElem != null)) return false;
    }
    return true;
  }

  /**
   * Checks if expected and actual arguments match for null/non-null value
   *
   * @return true if arguments match
   * @param expected Object[]
   * @param actual Object[]
   */
  protected boolean checkReturn(Object[] expected, Object[] actual) {
    Object eElem = null;
    Object aElem = null;
    if (expected.length != actual.length) return false;
    for (int i = 0; i < expected.length; i++) {
      eElem = expected[i];
      aElem = actual[i];
      if ((eElem == null && aElem != null) || (aElem == null && eElem != null)) return false;
    }
    return true;
  }

  /**
   * Test that method under test with null valued argument does nothing.
   *
   * @param mut method under test
   * @param method method name
   */
  public void executeNullObjectParameter(MethodUnderTest mut, String method) {

    Transaction tx = pm.currentTransaction();
    Object obj = null;
    try {
      tx = pm.currentTransaction();

      tx.begin();
      try {
        mut.pmApi(pm, obj);
      } catch (Exception e) {
        fail(
            ASSERTION3_FAILED,
            method + " on a null object should do nothing." + " Instead we get: " + e);
      }
      tx.commit();

      logger.debug(" \nPASSED in executeNullObjectParameter() on " + method);
    } finally {
      if (tx.isActive()) tx.rollback();
    }
  }

  /**
   * Test that the method under test with null valued Collection argument throws
   * NullPointerException.
   *
   * @param mut method under test
   * @param method method name
   */
  public void executeNullCollectionParameter(MethodUnderTest mut, String method) {

    Collection<?> coll = null;
    Transaction tx = pm.currentTransaction();

    try {
      tx.begin();
      try {
        mut.pmApi(pm, coll);
        fail(ASSERTION4_FAILED, method + " with null Collection argument should throw NPE.");
      } catch (NullPointerException npe) {
        // this is what we want
      } catch (Exception e) {
        fail(
            ASSERTION4_FAILED,
            method + " with null Collection argument should throw NPE." + " Instead we get: " + e);
        e.printStackTrace();
      }
      tx.commit();

      logger.debug(" \nPASSED in executeNullCollectionParameter()");
    } finally {
      if (tx.isActive()) tx.rollback();
    }
  }

  /**
   * Test that the method under test with null valued array argument throws NullPointerException.
   *
   * @param mut method under test
   * @param method method name
   */
  public void executeNullArrayParameter(MethodUnderTest mut, String method) {

    Object[] array = null;
    Transaction tx = pm.currentTransaction();

    try {
      tx.begin();
      try {
        mut.pmApi(pm, array);
        fail(ASSERTION4_FAILED, method + " with null array argument should throw NPE.");
      } catch (NullPointerException npe) {
        // this is what we want
      } catch (Exception e) {
        fail(
            ASSERTION4_FAILED,
            method + " with null array argument should throw NPE." + " Instead we get: " + e);
        e.printStackTrace();
      }
      tx.commit();

      logger.debug(" \nPASSED in executeNullArrayParameter()");
    } finally {
      if (tx.isActive()) tx.rollback();
    }
  }

  /**
   * Test that the method under test with a null element of a Collection argument ignores the null
   * element.
   *
   * @param coll collection argument
   * @param mut method under test
   * @param method method name
   */
  public <T> void executeCollectionNullElement(
      Collection<T> coll, MethodUnderTest mut, String method) {

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

      tx.begin();
      try {
        mut.pmApi(pm, coll);
      } catch (Exception e) {
        fail(
            ASSERTION5_FAILED,
            method + " on a null Collection element should" + " do nothing. Instead we get: " + e);
        e.printStackTrace();
      }

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

  /**
   * Test that the method under test with a null element of a array argument ignores the null
   * element.
   *
   * @param array argument
   * @param mut method under test
   * @param method method name
   */
  public void executeArrayNullElement(Object[] array, MethodUnderTest mut, String method) {

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

      tx.begin();
      try {
        mut.pmApi(pm, array);
      } catch (Exception e) {
        fail(
            ASSERTION5_FAILED,
            method + " on a null array element should " + "do nothing. Instead we get: " + e);
        e.printStackTrace();
      }

      tx.commit();

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

  /**
   * Test that method under test with null valued argument does nothing.
   *
   * @param mut method under test
   * @param method method name
   */
  public void executeNullObjectParameterReturn(MethodUnderTest mut, String method) {

    Object returnVal = null;
    Object obj = null;
    Transaction tx = pm.currentTransaction();
    try {
      tx = pm.currentTransaction();

      tx.begin();
      try {
        returnVal = mut.pmApiReturn(pm, obj);
      } catch (Exception e) {
        fail(
            ASSERTION3_FAILED,
            method + " on a null object should do nothing." + " Instead we get: " + e);
        e.printStackTrace();
      }
      if (returnVal != null)
        fail(ASSERTION3_FAILED, method + " returns non-null Object; expected null.");

      tx.commit();

      logger.debug(" \nPASSED in executeNullObjectParameter() on " + method);
    } finally {
      if (tx.isActive()) tx.rollback();
    }
  }

  /**
   * Test that the method under test with null valued Collection argument throws
   * NullPointerException.
   *
   * @param mut method under test
   * @param method method name
   */
  public void executeNullCollectionParameterReturn(MethodUnderTest mut, String method) {

    Collection<?> returnVal = null;
    Collection<?> coll = null;
    Transaction tx = pm.currentTransaction();

    try {
      tx.begin();
      try {
        returnVal = mut.pmApiReturn(pm, coll);
        fail(ASSERTION4_FAILED, method + " with null Collection argument should throw NPE.");
      } catch (NullPointerException npe) {
        // this is what we want
      } catch (Exception e) {
        fail(
            ASSERTION4_FAILED,
            method + " with null Collection argument should throw NPE." + " Instead we get: " + e);
        e.printStackTrace();
      }
      if (returnVal != null) fail(ASSERTION4_FAILED, method + " returns non-null Object. ");
      tx.commit();

      logger.debug(" \nPASSED in executeNullCollectionParameter()");
    } finally {
      if (tx.isActive()) tx.rollback();
    }
  }

  /**
   * Test that the method under test with null valued array argument throws NullPointerException.
   *
   * @param mut method under test
   * @param method method name
   */
  public void executeNullArrayParameterReturn(MethodUnderTest mut, String method) {

    Object[] returnVal = null;
    Object[] array = null;
    Transaction tx = pm.currentTransaction();

    try {
      tx.begin();
      try {
        returnVal = mut.pmApiReturn(pm, array);
        fail(ASSERTION4_FAILED, method + " with null array argument should throw NPE.");
      } catch (NullPointerException npe) {
        // this is what we want
      } catch (Exception e) {
        fail(
            ASSERTION4_FAILED,
            method + " with null array argument should throw NPE." + " Instead we get: " + e);
        e.printStackTrace();
      }
      if (returnVal != null) fail(ASSERTION4_FAILED, method + " returns non-null Object.");
      tx.commit();

      logger.debug(" \nPASSED in executeNullArrayParameter()");
    } finally {
      if (tx.isActive()) tx.rollback();
    }
  }

  /**
   * Test that the method under test with a null element of a Collection argument ignores the null
   * element.
   *
   * @param coll argument
   * @param mut method under test
   * @param method method name
   */
  public <T> void executeCollectionNullElementReturn(
      Collection<T> coll, MethodUnderTest mut, String method) {

    Collection<T> returnVal = null;
    Transaction tx = pm.currentTransaction();
    try {
      tx = pm.currentTransaction();

      tx.begin();
      try {
        returnVal = mut.pmApiReturn(pm, coll);
      } catch (Exception e) {
        fail(
            ASSERTION5_FAILED,
            method + " on a null Collection element should" + " do nothing. Instead we get: " + e);
        e.printStackTrace();
      }

      if (!checkReturn(expectedCollection, returnVal))
        fail(
            ASSERTION5_FAILED,
            method
                + " returns incorrect Object. Expected "
                + expectedCollection.toString()
                + " actual was "
                + returnVal);
      tx.commit();
    } finally {
      if (tx.isActive()) tx.rollback();
    }
  }

  /**
   * Test that the method under test with a null element of a array argument ignores the null
   * element.
   *
   * @param obj argument
   * @param mut method under test
   * @param method method name
   */
  public void executeArrayNullElementReturn(Object[] obj, MethodUnderTest mut, String method) {

    Object[] returnVal = null;
    Transaction tx = pm.currentTransaction();
    try {
      tx = pm.currentTransaction();

      tx.begin();
      try {
        returnVal = mut.pmApiReturn(pm, obj);
      } catch (Exception e) {
        fail(
            ASSERTION5_FAILED,
            method + " on a null array element should " + "do nothing. Instead we get: " + e);
        e.printStackTrace();
      }

      if (!checkReturn(expectedArray, returnVal))
        fail(
            ASSERTION5_FAILED,
            method
                + " returns incorrect Object. Expected "
                + Arrays.asList(expectedArray)
                + " actual was "
                + Arrays.asList(returnVal));
      tx.commit();

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