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

import java.math.BigDecimal;
import java.math.BigInteger;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import javax.jdo.JDOException;
import javax.jdo.JDOFatalInternalException;
import javax.jdo.JDOQLTypedQuery;
import javax.jdo.JDOUserException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.Transaction;
import org.apache.jdo.tck.AbstractReaderTest;
import org.apache.jdo.tck.pc.company.CompanyModelReader;
import org.apache.jdo.tck.pc.mylib.MylibReader;
import org.apache.jdo.tck.pc.mylib.PCPoint;
import org.apache.jdo.tck.pc.mylib.PrimitiveTypes;
import org.apache.jdo.tck.util.ConversionHelper;
import org.apache.jdo.tck.util.EqualityHelper;

public abstract class QueryTest extends AbstractReaderTest {

  /** */
  public static final String SERIALZED_QUERY = "query.ser";

  /** */
  public static final String COMPANY_TESTDATA =
      "org/apache/jdo/tck/pc/company/companyForQueryTests.xml";

  /** */
  public static final String MYLIB_TESTDATA = "org/apache/jdo/tck/pc/mylib/mylibForQueryTests.xml";

  /** List of inserted instances (see methods insertPCPoints and getFromInserted). */
  protected final List<PCPoint> inserted = new ArrayList<>();

  /**
   * The company model reader is used to read company model instances from an XML file. Instances
   * refered by this reader are made persistent by {@link
   * QueryTest#loadAndPersistCompanyModel(PersistenceManager)}.
   */
  private CompanyModelReader companyModelReaderForPersistentInstances;

  /**
   * The company model reader is used to read company model instances from an XML file. Instances
   * refered by this reader remain transient.
   */
  private CompanyModelReader companyModelReaderForTransientInstances;

  /**
   * The mylib reader is used to read mylib instances from an XML file. Instances refered by this
   * reader are made persistent by {@link QueryTest#loadAndPersistMylib(PersistenceManager)}.
   */
  private MylibReader mylibReaderForPersistentInstances;

  /**
   * The mylib reader is used to read mylib instances from an XML file. Instances refered by this
   * reader are made persistent by
   */
  private MylibReader mylibReaderForTransientInstances;

  // Helper methods to create persistent PCPoint instances

  /**
   * @param pm the PersistenceManager
   */
  public void loadAndPersistPCPoints(PersistenceManager pm) {
    insertPCPoints(pm, 5);
  }

  /**
   * @param pm the PersistenceManager
   * @param numInsert number of instances to be inserted
   */
  protected void insertPCPoints(PersistenceManager pm, int numInsert) {
    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();
      for (int i = 0; i < numInsert; i++) {
        PCPoint pc = new PCPoint(i, i);
        pm.makePersistent(pc);
        inserted.add(pc);
      }
      tx.commit();
      tx = null;
      if (debug) logger.debug("Total objects inserted : " + numInsert);
    } finally {
      if ((tx != null) && tx.isActive()) tx.rollback();
    }
  }

  /**
   * @param list list
   * @return list
   */
  public List<PCPoint> getFromInserted(List<PCPoint> list) {
    if (list == null) return null;

    List<PCPoint> result = new ArrayList<>();
    for (PCPoint pc : list) {
      for (PCPoint pci : inserted) {
        if (pc.getX() == pci.getX()) {
          result.add(pci);
          break;
        }
      }
    }
    return result;
  }

  // Company model and mylib helper methods

  /**
   * Returns the name of the company test data resource.
   *
   * @return name of the company test data resource.
   */
  protected String getCompanyTestDataResource() {
    return COMPANY_TESTDATA;
  }

  /**
   * Initializes and returns the company model reader for persistent instances.
   *
   * @return the company model reader for persistent instances.
   */
  private CompanyModelReader getCompanyModelReaderForPersistentInstances() {
    if (companyModelReaderForPersistentInstances == null) {
      companyModelReaderForPersistentInstances =
          new CompanyModelReader(getCompanyTestDataResource());
    }
    return companyModelReaderForPersistentInstances;
  }

  /**
   * Initializes and returns the company model reader for transient instances.
   *
   * @return the company model reader for transient instances.
   */
  private CompanyModelReader getCompanyModelReaderForTransientInstances() {
    if (companyModelReaderForTransientInstances == null) {
      companyModelReaderForTransientInstances =
          new CompanyModelReader(getCompanyTestDataResource());
    }
    return companyModelReaderForTransientInstances;
  }

  /**
   * Initializes and returns the mylib reader for persistent instances.
   *
   * @return the mylib reader for persistent instances.
   */
  private MylibReader getMylibReaderForPersistentInstances() {
    if (mylibReaderForPersistentInstances == null) {
      mylibReaderForPersistentInstances = new MylibReader(MYLIB_TESTDATA);
    }
    return mylibReaderForPersistentInstances;
  }

  /**
   * Initializes and returns the mylib reader for transient instances.
   *
   * @return the mylib reader for transient instances.
   */
  private MylibReader getMylibReaderForTransientInstances() {
    if (mylibReaderForTransientInstances == null) {
      mylibReaderForTransientInstances = new MylibReader(MYLIB_TESTDATA);
    }
    return mylibReaderForTransientInstances;
  }

  /**
   * Reads a graph of company model objects from the internal reader. This methods explictly calls
   * makePersistent for all named instances using the specified PersistenceManager. The method
   * returns the CompanyModelReader instance allowing to access a compay model instance by name.
   *
   * @param pm the PersistenceManager
   * @return the company model reader
   */
  public CompanyModelReader loadAndPersistCompanyModel(PersistenceManager pm) {
    makePersistentAll(pm, getRootList(getCompanyModelReaderForPersistentInstances()));
    return getCompanyModelReaderForPersistentInstances();
  }

  /**
   * Reads a graph of mylib objects from the internal reader. This methods explictly calls
   * makePersistent for all named instances using the specified PersistenceManager. The method
   * returns the CompanyModelReader instance allowing to access a compay model instance by name.
   *
   * @param pm the PersistenceManager
   * @return mylib reader
   */
  public MylibReader loadAndPersistMylib(PersistenceManager pm) {
    makePersistentAll(pm, getRootList(getMylibReaderForPersistentInstances()));
    return getMylibReaderForPersistentInstances();
  }

  /**
   * Persists the given pc instances.
   *
   * @param pm the PersistenceManager
   * @param pcInstances the pc instances to persist
   */
  private void makePersistentAll(PersistenceManager pm, List<?> pcInstances) {
    Transaction tx = pm.currentTransaction();
    tx.begin();
    try {
      pm.makePersistentAll(pcInstances);
      if (debug) logger.debug("inserted " + pcInstances);
      tx.commit();
    } finally {
      if (tx.isActive()) {
        tx.rollback();
      }
    }
  }

  /**
   * Returns a persistent company model instance for the given bean name.
   *
   * @param clazz class of the returned instance
   * @param beanName the bean name.
   * @return the persistent company model instance.
   */
  protected <T> T getPersistentCompanyModelInstance(Class<T> clazz, String beanName) {
    return beanName == null
        ? null
        : getBean(getCompanyModelReaderForPersistentInstances(), clazz, beanName);
  }

  /**
   * Returns a transient company model instance for the given bean name.
   *
   * @param clazz the class of teh returned instance
   * @param beanName the bean name.
   * @return the transient company model instance.
   */
  protected <T> T getTransientCompanyModelInstance(Class<T> clazz, String beanName) {
    return beanName == null
        ? null
        : getBean(getCompanyModelReaderForTransientInstances(), clazz, beanName);
  }

  /**
   * Returns a list of persistent company model instances for beans names in the given argument.
   *
   * @param elementType the element type of the returned list
   * @param beanNames the bean names of company model instances.
   * @return the list of persistent company model instances.
   */
  protected <T> List<T> getPersistentCompanyModelInstancesAsList(
      Class<T> elementType, String... beanNames) {
    List<T> result = new ArrayList<>(beanNames.length);
    for (String beanName : beanNames) {
      result.add(getPersistentCompanyModelInstance(elementType, beanName));
    }
    return result;
  }
  /**
   * Returns a list of transient company model instances for beans names in the given argument.
   *
   * @param elementType the element type of the returned list
   * @param beanNames the bean names of company model instances.
   * @return the list of transient company model instances.
   */
  protected <T> List<T> getTransientCompanyModelInstancesAsList(
      Class<T> elementType, String... beanNames) {
    List<T> result = new ArrayList<>(beanNames.length);
    for (String beanName : beanNames) {
      result.add(getTransientCompanyModelInstance(elementType, beanName));
    }
    return result;
  }

  /**
   * Returns a persistent mylib instance for the given bean name.
   *
   * @param beanName the bean name.
   * @return the persistent mylib instance.
   */
  protected Object getPersistentMylibInstance(String beanName) {
    return beanName == null ? null : getBean(getMylibReaderForPersistentInstances(), beanName);
  }

  /**
   * Returns a transient mylib instance for the given bean name.
   *
   * @param beanName the bean name.
   * @return the transient mylib instance.
   */
  protected Object getTransientMylibInstance(String beanName) {
    return beanName == null ? null : getBean(getMylibReaderForTransientInstances(), beanName);
  }

  /**
   * Returns an array of persistent mylib instances for beans names in the given argument.
   *
   * @param beanNames the bean names of mylib instances.
   * @return the array of persistent mylib instances.
   */
  protected Object[] getPersistentMylibInstances(String... beanNames) {
    Object[] result = new Object[beanNames.length];
    for (int i = 0; i < beanNames.length; i++) {
      result[i] = getPersistentMylibInstance(beanNames[i]);
    }
    return result;
  }

  /**
   * Returns an array of transient mylib instances for beans names in the given argument.
   *
   * @param beanNames the bean names of mylib instances.
   * @return the array of transient mylib instances.
   */
  protected Object[] getTransientMylibInstances(String... beanNames) {
    Object[] result = new Object[beanNames.length];
    for (int i = 0; i < beanNames.length; i++) {
      result[i] = getTransientMylibInstance(beanNames[i]);
    }
    return result;
  }

  /**
   * Returns a list of persistent mylib instances for beans names in the given argument.
   *
   * @param beanNames the bean names of mylib instances.
   * @return the list of persistent mylib instances.
   */
  protected List<Object> getPersistentMylibInstancesAsList(String... beanNames) {
    return Arrays.asList(getPersistentMylibInstances(beanNames));
  }

  /**
   * Returns a list of transient mylib instances for beans names in the given argument.
   *
   * @param beanNames the bean names of mylib instances.
   * @return the list of transient mylib instances.
   */
  protected List<Object> getTransientMylibInstancesAsList(String... beanNames) {
    return Arrays.asList(getTransientMylibInstances(beanNames));
  }

  // PrimitiveTypes helper methods (creation and query)

  /**
   * @param pm the PersistenceManager
   */
  public void loadAndPersistPrimitiveTypes(PersistenceManager pm) {
    insertPrimitiveTypes(pm);
  }

  /**
   * @param pm the PersistenceManager
   */
  protected void insertPrimitiveTypes(PersistenceManager pm) {
    boolean bFlag = false;
    String strValue = "";
    char charValue = '\u0000';
    int numInsert = 10;

    Transaction tx = pm.currentTransaction();
    try {
      tx.begin();
      for (int i = 1; i <= numInsert; i++) {
        if (i % 2 == 1) {
          bFlag = true;
          strValue = "Odd" + i;
          charValue = 'O';
        } else {
          bFlag = false;
          strValue = "Even" + i;
          charValue = 'E';
        }
        PrimitiveTypes primitiveObject =
            new PrimitiveTypes(
                i,
                bFlag,
                Boolean.valueOf(bFlag),
                (byte) i,
                Byte.valueOf((byte) i),
                (short) i,
                Short.valueOf((short) i),
                i,
                Integer.valueOf(i),
                i,
                Long.valueOf(i),
                i,
                Float.valueOf(i),
                i,
                Double.valueOf(i),
                charValue,
                Character.valueOf(charValue),
                Calendar.getInstance().getTime(),
                strValue,
                new BigDecimal(String.valueOf(i)),
                new BigInteger(String.valueOf(i)),
                Long.valueOf(i));
        pm.makePersistent(primitiveObject);
      }
      tx.commit();
      tx = null;
      if (debug) logger.debug("Total objects inserted : " + numInsert);
    } finally {
      if ((tx != null) && tx.isActive()) tx.rollback();
    }
  }

  /**
   * Creates and executes a PrimitiveTypes query with the specified filter. The method checks
   * whether the query returns the expected result.
   *
   * @param filter the filter
   * @param pm the PersistenceManager
   * @param expected expected
   * @param assertion assertion
   */
  protected void runSimplePrimitiveTypesQuery(
      String filter, PersistenceManager pm, Collection<PrimitiveTypes> expected, String assertion) {
    Query<PrimitiveTypes> q = pm.newQuery(PrimitiveTypes.class);
    q.setFilter(filter);
    List<PrimitiveTypes> results = q.executeList();
    if (debug) logger.debug("execute '" + filter + "' returns " + results.size() + " instance(s)");
    checkQueryResultWithoutOrder(assertion, filter, results, expected);
  }

  /**
   * Creates and executes a PrimitiveTypes query with the specified filter, parameter declarations
   * and parameter values. The method checks whether the query returns the expected result.
   *
   * @param filter the filter
   * @param paramDecl the parameter declaration
   * @param paramValue the parameter values
   * @param pm the PersistenceManager
   * @param expected expected
   * @param assertion assertion
   */
  protected void runParameterPrimitiveTypesQuery(
      String filter,
      String paramDecl,
      Object paramValue,
      PersistenceManager pm,
      Collection<PrimitiveTypes> expected,
      String assertion) {
    Query<PrimitiveTypes> q = pm.newQuery(PrimitiveTypes.class);
    q.setFilter(filter);
    q.declareParameters(paramDecl);
    q.setParameters(paramValue);
    List<PrimitiveTypes> results = q.executeList();
    if (debug)
      logger.debug(
          "execute '"
              + filter
              + "' with param '"
              + paramValue
              + "' returns "
              + results.size()
              + " instance(s)");
    checkQueryResultWithoutOrder(assertion, filter, results, expected);
  }

  // Helper methods to check query result

  /**
   * Verify that expected equals result, including the order of the elements. If not equal, fail the
   * test. If there is a filter != null, do not use this method. Use the method of the same name
   * that takes a String as the second argument.
   *
   * @param assertion assertion
   * @param result the result
   * @param expected the expected
   */
  protected void checkQueryResultWithOrder(String assertion, Object result, Object expected) {
    if (!equals(result, expected)) {
      queryFailed(assertion, "null", result, expected);
    }
  }

  /**
   * Verify that expected equals result, ignoring the order of the elements. If not equal, fail the
   * test. If there is a filter != null, do not use this method. Use the method of the same name
   * that takes a String as the second argument.
   *
   * @param assertion assertion
   * @param result the result
   * @param expected the expected
   */
  protected void checkQueryResultWithoutOrder(String assertion, Object result, Object expected) {
    // We need to explicitly check on collections passed as parameters
    // because equals(Object, Object) checks on lists and afterwards
    // on collections. This ensures, lists are compared without order
    // for queries without an ordering specification.
    if (result instanceof Collection && expected instanceof Collection) {
      if (!equalsCollection((Collection<?>) result, (Collection<?>) expected)) {
        queryFailed(assertion, "null", result, expected);
      }
    } else {
      if (!equals(result, expected)) {
        queryFailed(assertion, "null", result, expected);
      }
    }
  }

  private void queryFailed(String assertion, String query, Object result, Object expected) {
    String lf = System.getProperty("line.separator");
    result = ConversionHelper.convertObjectArrayElements(result);
    expected = ConversionHelper.convertObjectArrayElements(expected);
    fail(
        assertion,
        "Wrong query result: "
            + lf
            + "query: "
            + query
            + lf
            + "expected: "
            + expected.getClass().getName()
            + " of size "
            + size(expected)
            + lf
            + expected
            + lf
            + "got:      "
            + result.getClass().getName()
            + " of size "
            + size(result)
            + lf
            + result);
  }

  /**
   * @param assertion assertion
   * @param query the query
   * @param result the result
   * @param expected expected
   */
  protected void checkQueryResultWithOrder(
      String assertion, String query, Object result, Object expected) {
    if (!equals(result, expected)) {
      queryFailed(assertion, query, result, expected);
    }
  }

  /**
   * @param assertion assertion
   * @param query the query
   * @param result the result
   * @param expected expected
   */
  protected void checkQueryResultWithoutOrder(
      String assertion, String query, Object result, Object expected) {
    // We need to explicitly check on collections passed as parameters
    // because equals(Object, Object) checks on lists and afterwards
    // on collections. This ensures, lists are compared without order
    // for queries without an ordering specification.
    if (result instanceof Collection && expected instanceof Collection) {
      if (!equalsCollection((Collection<?>) result, (Collection<?>) expected)) {
        queryFailed(assertion, query, result, expected);
      }
    } else {
      if (!equals(result, expected)) {
        queryFailed(assertion, query, result, expected);
      }
    }
  }

  /**
   * Returns <code>true</code> if <code>o1</code> and <code>o2</code> equal. This method is capable
   * to compare object arrays, collections of object arrays, maps of object arrays. This method
   * implements a narrowing in case of floating point values. In case of big decimals it calls
   * {@link BigDecimal#compareTo(java.math.BigDecimal)}. It allows <code>o1</code> and/or <code>o2
   * </code> to be <code>null</code>.
   *
   * @param o1 the first object
   * @param o2 the second object
   * @return <code>true</code> if <code>o1</code> and <code>o2</code> equal.
   */
  protected boolean equals(Object o1, Object o2) {
    boolean result;
    if (o1 == o2) {
      result = true;
    } else if ((o1 instanceof Object[]) && (o2 instanceof Object[])) {
      result = equalsObjectArray((Object[]) o1, (Object[]) o2);
    } else if ((o1 instanceof List) && (o2 instanceof List)) {
      result = equalsList((List<?>) o1, (List<?>) o2);
    } else if ((o1 instanceof Collection) && (o2 instanceof Collection)) {
      result = equalsCollection((Collection<?>) o1, (Collection<?>) o2);
    } else if ((o1 instanceof Map) && (o2 instanceof Map)) {
      result = equalsMap((Map<?, ?>) o1, (Map<?, ?>) o2);
    } else if ((o1 instanceof Float) && (o2 instanceof Float)) {
      result = closeEnough(((Float) o1).floatValue(), ((Float) o2).floatValue());
    } else if ((o1 instanceof Double) && (o2 instanceof Double)) {
      result = closeEnough(((Double) o1).floatValue(), ((Double) o2).floatValue());
    } else if ((o1 instanceof BigDecimal) && (o2 instanceof BigDecimal)) {
      result = ((BigDecimal) o1).compareTo((BigDecimal) o2) == 0;
    } else if (o1 != null) {
      result = o1.equals(o2);
    } else {
      // Due to the first if and due to the last if, we have:
      // o1 == null && o2 != null
      result = false;
    }
    return result;
  }

  /**
   * Returns <code>true</code> if <code>o1</code> and <code>o2</code> equal. This method iterates
   * over both object arrays and calls {@link QueryTest#equals(Object, Object)} passing
   * corresponding instances. {@link QueryTest#equals(Object, Object)} is called rather than {@link
   * Object#equals(java.lang.Object)} because object arrays having equal elements cannot be compared
   * calling {@link Object#equals(java.lang.Object)}. This method does not allow <code>o1</code> and
   * <code>o2</code> to be <code>null</code> both.
   *
   * @param o1 the first object array
   * @param o2 the second object array
   * @return <code>true</code> if <code>o1</code> and <code>o2</code> equal.
   */
  protected boolean equalsObjectArray(Object[] o1, Object[] o2) {
    boolean result = true;
    if (o1 != o2) {
      if (o1.length != o2.length) {
        result = false;
      } else {
        for (int i = 0; i < o1.length; i++) {
          if (!equals(o1[i], o2[i])) {
            result = false;
            break;
          }
        }
      }
    }
    return result;
  }

  /**
   * Returns <code>true</code> if <code>o1</code> and <code>o2</code> equal. This method iterates
   * both lists and calls {@link QueryTest#equals(Object, Object)} on corresponding elements. {@link
   * QueryTest#equals(Object, Object)} is called rather than {@link Object#equals(java.lang.Object)}
   * because object arrays having equal elements cannot be compared calling {@link
   * Object#equals(java.lang.Object)}. This method does not allow <code>o1</code> and <code>o2
   * </code> to be <code>null</code> both.
   *
   * @param o1 the first list
   * @param o2 the second list
   * @return <code>true</code> if <code>o1</code> and <code>o2</code> equal.
   */
  protected <S, T> boolean equalsList(List<S> o1, List<T> o2) {
    boolean result = true;
    if (o1 != o2) {
      if (o1.size() != o2.size()) {
        result = false;
      } else {
        Iterator<S> i = o1.iterator();
        Iterator<T> ii = o2.iterator();
        while (i.hasNext()) {
          Object firstObject = i.next();
          Object secondObject = ii.next();
          if (!equals(firstObject, secondObject)) {
            result = false;
            break;
          }
        }
      }
    }
    return result;
  }

  /**
   * Returns <code>true</code> if <code>o1</code> and <code>o2</code> equal. This method iterates
   * over the first collection and checks if each instance is contained in the second collection by
   * calling remove(Collection, Object). This guarantees that the cardinality of each instance in
   * the first collection matches the cardinality of each instance in the second collection. This
   * method does not allow <code>o1</code> and <code>o2</code> to be <code>null</code> both.
   *
   * @param o1 the first collection
   * @param o2 the second collection
   * @return <code>true</code> if <code>o1</code> and <code>o2</code> equal.
   */
  protected <S, T> boolean equalsCollection(Collection<S> o1, Collection<T> o2) {
    // make a copy of o2 so we can destroy it
    Collection<T> o2copy = new ArrayList<>();
    for (T t : o2) {
      o2copy.add(t);
    }
    boolean result = true;
    if (o1 != o2) {
      if (o1.size() != o2.size()) {
        result = false;
      } else {
        for (S oo1 : o1) {
          if (!remove(o2copy, oo1)) {
            result = false;
            break;
          }
        }
      }
    }
    return result;
  }

  /**
   * Returns <code>true</code> if <code>o1</code> and <code>o2</code> equal. This method checks if
   * the key sets and the value sets of both maps equal calling equalsCollection(Collection,
   * Collection). This method does not allow <code>o1</code> and <code>o2</code> to be <code>null
   * </code> both.
   *
   * @param o1 the first map
   * @param o2 the second map
   * @return <code>true</code> if <code>o1</code> and <code>o2</code> equal.
   */
  protected <K1, V1, K2, V2> boolean equalsMap(Map<K1, V1> o1, Map<K2, V2> o2) {
    boolean result = true;
    if (o1 != o2) {
      if (o1.size() != o2.size()) {
        result = false;
      } else {
        for (Map.Entry<K1, V1> entry : o1.entrySet()) {
          K1 key = entry.getKey();
          V1 value = entry.getValue();
          V2 value2 = o2.get(key);
          if (!equals(value, value2)) {
            result = false;
            break;
          }
        }
      }
    }
    return result;
  }

  /**
   * Returns <code>true</code> if <code>o</code> is contained in the given collection. This method
   * iterates the given collection and calls {@link QueryTest#equals(Object, Object)} for each
   * instance. {@link QueryTest#equals(Object, Object)} is called rather than {@link
   * Object#equals(java.lang.Object)} because object arrays having equal elements cannot be compared
   * calling {@link Object#equals(java.lang.Object)}.
   *
   * @param col the collection
   * @param o the object
   * @return <code>true</code> if <code>o</code> is contained in the given collection.
   */
  private boolean contains(Collection<Object> col, Object o) {
    for (Object value : col) {
      if (equals(o, value)) {
        return true;
      }
    }
    return false;
  }

  /**
   * Returns <code>true</code> if <code>o</code> is contained in the given collection and was
   * removed. This method iterates the given collection and calls {@link QueryTest#equals(Object,
   * Object)} for each instance. {@link QueryTest#equals(Object, Object)} is called rather than
   * {@link Object#equals(java.lang.Object)} because object arrays having equal elements cannot be
   * compared calling {@link Object#equals(java.lang.Object)}.
   *
   * @param col the collection
   * @param o the object
   * @return <code>true</code> if <code>o</code> is contained in the given collection and was
   *     removed.
   */
  private <T> boolean remove(Collection<T> col, Object o) {
    for (Iterator<T> i = col.iterator(); i.hasNext(); ) {
      if (equals(o, i.next())) {
        i.remove();
        return true;
      }
    }
    return false;
  }

  /**
   * Returns <code>true</code> if the specified float values are close enough to be considered to be
   * equal for a deep equals comparison. Floating point values are not exact, so comparing them
   * using <code>==</code> might not return useful results. This method checks that both double
   * values are within some percent of each other.
   *
   * @param d1 one double to be tested for close enough
   * @param d2 the other double to be tested for close enough
   * @return <code>true</code> if the specified values are close enough.
   */
  public boolean closeEnough(double d1, double d2) {
    if (d1 == d2) return true;

    double diff = Math.abs(d1 - d2);
    return diff < Math.abs((d1 + d2) * EqualityHelper.DOUBLE_EPSILON);
  }

  /**
   * Returns <code>true</code> if the specified float values are close enough to be considered to be
   * equal for a deep equals comparison. Floating point values are not exact, so comparing them
   * using <code>==</code> might not return useful results. This method checks that both float
   * values are within some percent of each other.
   *
   * @param f1 one float to be tested for close enough
   * @param f2 the other float to be tested for close enough
   * @return <code>true</code> if the specified values are close enough.
   */
  public boolean closeEnough(float f1, float f2) {
    if (f1 == f2) return true;

    float diff = Math.abs(f1 - f2);
    return diff < Math.abs((f1 + f2) * EqualityHelper.FLOAT_EPSILON);
  }

  /**
   * Returns the size of the object. If it is a multivalued object (Collection, Map, or array)
   * return the number of elements. If not, return 1.
   *
   * @param o the object
   * @return size
   */
  protected int size(Object o) {
    if (o instanceof Collection) {
      return ((Collection<?>) o).size();
    }
    if (o instanceof Object[]) {
      return ((Object[]) o).length;
    }
    if (o instanceof Map) {
      return ((Map<?, ?>) o).size();
    }
    return 1;
  }

  // Debugging helper methods

  /**
   * @param results the results
   * @param expected expected values
   */
  protected void printOutput(Object results, Collection<?> expected) {
    if (!debug) return;

    Iterator<?> iter = null;
    PCPoint pcp = null;
    if (results == null) {
      logger.debug("Query returns null");
      return;
    }
    if (!(results instanceof Collection)) {
      logger.debug(
          "Query result is not a collection: "
              + (results == null ? "null" : results.getClass().getName()));
    }
    logger.debug("Retrived Objects are:");
    iter = ((Collection<?>) results).iterator();
    while (iter.hasNext()) {
      pcp = (PCPoint) iter.next();
      logger.debug("X = " + pcp.getX() + "\tY = " + pcp.getY());
    }

    logger.debug("Expected Objects are:");
    iter = expected.iterator();
    while (iter.hasNext()) {
      pcp = (PCPoint) iter.next();
      logger.debug("X = " + pcp.getX() + "\tY = " + pcp.getY());
    }
  }

  // compile query methods

  /**
   * Compiles the given query element holder instance as a JDO API query. Argument <code>positive
   * </code> determines if the compilation is supposed to succeed or to fail. If <code>true</code>
   * and the compilation fails, then the test case fails prompting argument <code>assertion</code>.
   * If <code>false</code> and the compilation succeeds, then the test case fails prompting argument
   * <code>assertion</code>. Otherwise the test case succeeds.
   *
   * @param assertion the assertion to prompt if the test case fails.
   * @param queryElementHolder the query to execute.
   * @param positive determines if the compilation is supposed to succeed or to fail.
   */
  protected void compileAPIQuery(
      String assertion, QueryElementHolder<?> queryElementHolder, boolean positive) {
    if (logger.isDebugEnabled()) {
      logger.debug("Compiling API query: " + queryElementHolder);
    }
    compile(assertion, queryElementHolder, false, queryElementHolder.toString(), positive);
  }

  /**
   * Compiles the given query element holder instance as a JDO single string query. Argument <code>
   * positive</code> determines if the compilation is supposed to succeed or to fail. If <code>true
   * </code> and the compilation fails, then the test case fails prompting argument <code>assertion
   * </code>. If <code>false</code> and the compilation succeeds, then the test case fails prompting
   * argument <code>assertion</code>. Otherwise the test case succeeds.
   *
   * @param assertion the assertion to prompt if the test case fails.
   * @param queryElementHolder the query to execute.
   * @param positive determines if the compilation is supposed to succeed or to fail.
   */
  protected void compileSingleStringQuery(
      String assertion, QueryElementHolder<?> queryElementHolder, boolean positive) {
    if (logger.isDebugEnabled())
      logger.debug("Compiling single string query: " + queryElementHolder);
    compile(assertion, queryElementHolder, true, queryElementHolder.toString(), positive);
  }

  /**
   * Compiles the given single string query. Argument <code>positive</code> determines if the
   * compilation is supposed to succeed or to fail. If <code>true</code> and the compilation fails,
   * then the test case fails prompting argument <code>assertion</code>. If <code>false</code> and
   * the compilation succeeds, then the test case fails prompting argument <code>assertion</code>.
   * Otherwise the test case succeeds.
   *
   * @param assertion the assertion to prompt if the test case fails.
   * @param singleStringQuery the single string query
   * @param positive determines if the compilation is supposed to succeed or to fail.
   */
  protected void compileSingleStringQuery(
      String assertion, String singleStringQuery, boolean positive) {
    if (logger.isDebugEnabled())
      logger.debug("Compiling single string query: " + singleStringQuery);
    compile(assertion, null, true, singleStringQuery, positive);
  }

  /**
   * Compiles the given query element holder instance as a JDO API query or single string query,
   * depending on argument <code>asSingleString</code>. Argument <code>singleStringQuery</code> is
   * used to support queries which cannot be expressed as query element holder instances. That
   * argument is ignored if argument <code>queryElementHolder</code> is set. Argument <code>positive
   * </code> determines if the compilation is supposed to succeed or to fail. If <code>true</code>
   * and the compilation fails, then the test case fails prompting argument <code>assertion</code>.
   * If <code>false</code> and the compilation succeeds, then the test case fails prompting argument
   * <code>assertion</code>. Otherwise the test case succeeds.
   *
   * @param assertion the assertion to prompt if the test case fails.
   * @param queryElementHolder the query to compile.
   * @param asSingleString determines if the query specified by <code>queryElementHolder</code> is
   *     compiled as single string query or as API query.
   * @param singleStringQuery the query to compile as a JDO single string query if there is no query
   *     element holder.
   * @param positive determines if the compilation is supposed to succeed or to fail.
   */
  private void compile(
      String assertion,
      QueryElementHolder<?> queryElementHolder,
      boolean asSingleString,
      String singleStringQuery,
      boolean positive) {
    getPM();
    try {
      Query<?> query;
      if (queryElementHolder != null) {
        if (asSingleString) {
          query = queryElementHolder.getSingleStringQuery(pm);
        } else {
          query = queryElementHolder.getAPIQuery(pm);
        }
      } else {
        query = getPM().newQuery(singleStringQuery);
      }
      compile(assertion, query, singleStringQuery, positive);
    } catch (JDOUserException e) {
      // This exception handler considers a JDOUserException
      // to be thrown in newQuery methods.
      // A JDOUserException may be expected in case of negative tests.
      if (positive) {
        fail(
            assertion
                + "Query '"
                + queryElementHolder
                + "' must be compilable. The exception message is: "
                + e.getMessage());
      }
    }
  }

  /**
   * Compiles the given query instance. Argument <code>positive</code> determines if the compilation
   * is supposed to succeed or to fail. If <code>true</code> and the compilation fails, then the
   * test case fails prompting arguments <code>assertion</code> and <code>queryText</code>. If
   * <code>false</code> and the compilation succeeds, then the test case fails prompting argument
   * <code>assertion</code> and <code>queryText</code>. Otherwise the test case succeeds.
   *
   * @param assertion asserting text
   * @param query the query instance
   * @param queryText the text representation of the query
   * @param positive positive test
   */
  protected void compile(String assertion, Query<?> query, String queryText, boolean positive) {
    getPM();
    Transaction tx = pm.currentTransaction();
    tx.begin();
    try {
      query.compile();
      if (!positive) {
        fail(assertion, "Query compilation must throw JDOUserException: " + queryText);
      }
    } catch (JDOUserException e) {
      if (positive) {
        fail(
            assertion,
            "Query '"
                + queryText
                + "' must be compilable. The exception message is: "
                + e.getMessage());
      }
    } finally {
      if (tx.isActive()) {
        tx.rollback();
      }
    }
  }

  // execute query methods

  /**
   * Executes the given query element holder instance as a JDO API query. The result of that query
   * is compared against the given argument <code>expectedResult</code>. If the expected result does
   * not match the returned query result, then the test case fails prompting argument <code>
   * assertion</code>.
   *
   * @param assertion the assertion to prompt if the test case fails.
   * @param queryElementHolder the query to execute.
   * @param expectedResult the expected query result.
   */
  protected void executeAPIQuery(
      String assertion, QueryElementHolder<?> queryElementHolder, Object expectedResult) {
    if (logger.isDebugEnabled()) {
      logger.debug("Executing API query: " + queryElementHolder);
    }
    execute(assertion, queryElementHolder, false, expectedResult);
  }

  /**
   * Executes the given query element holder instance as a JDO single string query. The result of
   * that query is compared against the given argument <code>expectedResult</code>. If the expected
   * result does not match the returned query result, then the test case fails prompting argument
   * <code>assertion</code>.
   *
   * @param assertion the assertion to prompt if the test case fails.
   * @param queryElementHolder the query to execute.
   * @param expectedResult the expected query result.
   */
  protected void executeSingleStringQuery(
      String assertion, QueryElementHolder<?> queryElementHolder, Object expectedResult) {
    if (logger.isDebugEnabled())
      logger.debug("Executing single string query: " + queryElementHolder);
    execute(assertion, queryElementHolder, true, expectedResult);
  }

  /**
   * @param assertion assertion text
   * @param queryElementHolder query elements
   * @param expectedResult expected query result
   */
  protected void executeJDOQLTypedQuery(
      String assertion, QueryElementHolder<?> queryElementHolder, Object expectedResult) {
    executeJDOQLTypedQuery(assertion, queryElementHolder, null, false, expectedResult);
  }

  /**
   * @param assertion assertion text
   * @param queryElementHolder query elements
   * @param resultClass result class object
   * @param resultClauseSpecified flag whether result clause is specified
   * @param expectedResult the expected query result
   */
  protected void executeJDOQLTypedQuery(
      String assertion,
      QueryElementHolder<?> queryElementHolder,
      Class<?> resultClass,
      boolean resultClauseSpecified,
      Object expectedResult) {
    String singleStringQuery = queryElementHolder.toString();
    getPM();
    Transaction tx = pm.currentTransaction();
    tx.begin();
    try {
      JDOQLTypedQuery<?> query = queryElementHolder.getJDOQLTypedQuery();
      if (query == null) {
        throw new JDOFatalInternalException("Missing JDOQLTyped instance");
      }
      Object result = null;
      try {
        Map<String, ?> paramValues = queryElementHolder.getParamValues();
        if (paramValues != null) {
          query.setParameters(paramValues);
        }

        if (resultClass != null) {
          if (queryElementHolder.isUnique()) {
            // result class specified and unique result
            result = query.executeResultUnique(resultClass);
          } else {
            // result class specified and list result
            result = query.executeResultList(resultClass);
          }
        } else if (resultClauseSpecified) {
          if (queryElementHolder.isUnique()) {
            // result class specified and unique result
            result = query.executeResultUnique();
          } else {
            // result class specified and list result
            result = query.executeResultList();
          }
        } else {
          if (queryElementHolder.isUnique()) {
            // no result class and unique result
            result = query.executeUnique();
          } else {
            // no result class and list result
            result = query.executeList();
          }
        }

        if (logger.isDebugEnabled()) {
          logger.debug("Query result: " + ConversionHelper.convertObjectArrayElements(result));
        }

        checkResult(
            assertion,
            singleStringQuery,
            queryElementHolder.hasOrdering(),
            result,
            expectedResult,
            true);
      } finally {
        query.close(result);
      }
    } catch (JDOUserException e) {
      String msg = "JDOUserException thrown while executing query:\n" + singleStringQuery;
      throw new JDOException(msg, e);
    } catch (JDOException e) {
      String msg = "JDOException thrown while executing query:\n" + singleStringQuery;
      throw new JDOException(msg, e);
    } finally {
      if (tx.isActive()) {
        tx.rollback();
      }
    }
  }

  /**
   * Converts the given query element holder instance to a JDO query instance, based on argument
   * <code>asSingleString</code>. Afterwards, delegates to method {@link QueryTest#execute(String,
   * Query, String, boolean, Object, Object, boolean)}.
   *
   * @param assertion the assertion to prompt if the test case fails.
   * @param queryElementHolder the query to execute.
   * @param asSingleString determines if the query is executed as single string query or as API
   *     query.
   * @param expectedResult the expected query result.
   * @return the query result
   */
  private Object execute(
      String assertion,
      QueryElementHolder<?> queryElementHolder,
      boolean asSingleString,
      Object expectedResult) {
    getPM();
    Query<?> query =
        asSingleString
            ? queryElementHolder.getSingleStringQuery(pm)
            : queryElementHolder.getAPIQuery(pm);
    Object result =
        execute(
            assertion,
            query,
            queryElementHolder.toString(),
            queryElementHolder.hasOrdering(),
            queryElementHolder.getParamValues(),
            expectedResult,
            true);
    return result;
  }

  /**
   * Executes the given query instance delegating to execute(String, Query, String, boolean, Object,
   * Object, boolean). Logs argument <code>singleStringQuery</code> if debug logging is enabled.
   *
   * @param assertion the assertion to prompt if the test case fails.
   * @param query the query to execute.
   * @param singleStringQuery the single string representation of the query. This parameter is only
   *     used as part of the falure message.
   * @param hasOrdering indicates if the query has an ordering clause.
   * @param parameters the parmaters of the query.
   * @param expectedResult the expected query result.
   * @param positive indicates if query execution is supposed to fail
   * @return the query result
   */
  protected Object executeJDOQuery(
      String assertion,
      Query<?> query,
      String singleStringQuery,
      boolean hasOrdering,
      Object[] parameters,
      Object expectedResult,
      boolean positive) {
    if (logger.isDebugEnabled()) {
      logger.debug("Executing JDO query: " + singleStringQuery);
    }
    return execute(
        assertion, query, singleStringQuery, hasOrdering, parameters, expectedResult, positive);
  }

  /**
   * Executes the given SQL string as a JDO SQL query. The result of that query is compared against
   * the given argument <code>expectedResult</code>. If the expected result does not match the
   * returned query result, then the test case fails prompting argument <code>assertion</code>.
   * Argument <code>unique</code> indicates, if the query is supposed to return a single result.
   * Argument <code>sql</code> may contain the substring <code>"{0}"</code>. All occurences of this
   * substring are replaced by the value of PMF property <code>"javax.jdo.mapping.Schema"</code>.
   *
   * @param assertion the assertion to prompt if the test case fails.
   * @param sql the SQL string.
   * @param candidateClass the candidate class.
   * @param resultClass the result class.
   * @param positive positive option
   * @param parameters the parameters of the query.
   * @param expectedResult the expected query result.
   * @param unique indicates, if the query is supposed to return a single result.
   */
  @SuppressWarnings("unchecked")
  protected <T> void executeSQLQuery(
      String assertion,
      String sql,
      Class<T> candidateClass,
      Class<?> resultClass,
      boolean positive,
      Object parameters,
      Object expectedResult,
      boolean unique) {
    String schema = getPMFProperty("javax.jdo.mapping.Schema");
    sql = MessageFormat.format(sql, new Object[] {schema});
    if (logger.isDebugEnabled()) logger.debug("Executing SQL query: " + sql);
    Query<T> query = getPM().newQuery("javax.jdo.query.SQL", sql);
    if (unique) {
      query.setUnique(unique);
    }
    if (candidateClass != null) {
      query.setClass(candidateClass);
    }
    if (resultClass != null) {
      query.setResultClass(resultClass);
    }
    execute(assertion, query, sql, false, parameters, expectedResult, positive);
  }

  /**
   * Executes the given query instance. If argument <code>parameters</code> is an object array, then
   * it is passed as an argument to the method {@link Query#executeWithArray(java.lang.Object[])}.
   * If argument <code>parameters</code> is a map, then it is passed as an argument to the method
   * {@link Query#executeWithMap(java.util.Map)}. If argument <code>parameters</code> is a list,
   * then the list elements are passed as arguments to the execute methods taking actual parameter
   * values. If argument <code>parameters</code> is <code>null</code>, then method {@link
   * Query#execute()} is called on the given query instance instead.
   *
   * <p>The result of query execution is compared against the argument <code>expectedResult</code>.
   * If the two values differ, then this method throws an {@link
   * junit.framework.AssertionFailedError} and the calling test case fails prompting argument <code>
   * assertion</code>.
   *
   * <p>If argument <code>positive</code> is <code>false</code>, then the test case invoking this
   * method is considered to be a negative test case. Then, query execution is expected to throw a
   * {@link JDOUserException}. If query execution succeeds in this case, then this method throws an
   * {@link junit.framework.AssertionFailedError} and the calling test case fails prompting argument
   * <code>assertion</code>.
   *
   * <p>
   *
   * @param assertion the assertion to prompt if the test case fails.
   * @param query the query to execute.
   * @param singleStringQuery the single string representation of the query. This parameter is only
   *     used as part of the falure message.
   * @param hasOrdering indicates if the query has an ordering clause.
   * @param parameters the parmaters of the query.
   * @param expectedResult the expected query result.
   * @param positive indicates if query execution is supposed to fail
   * @return the query result
   */
  @SuppressWarnings("unchecked")
  private Object execute(
      String assertion,
      Query<?> query,
      String singleStringQuery,
      boolean hasOrdering,
      Object parameters,
      Object expectedResult,
      boolean positive) {
    Object result = null;
    getPM();
    Transaction tx = pm.currentTransaction();
    tx.begin();
    try {
      try {
        if (parameters == null) {
          result = query.execute();
        } else if (parameters instanceof Object[]) {
          result = query.executeWithArray((Object[]) parameters);
        } else if (parameters instanceof Map) {
          result = query.executeWithMap((Map<String, Object>) parameters);
        } else if (parameters instanceof List) {
          List<?> list = (List<?>) parameters;
          switch (list.size()) {
            case 1:
              result = query.execute(list.get(0));
              break;
            case 2:
              result = query.execute(list.get(0), list.get(1));
              break;
            case 3:
              result = query.execute(list.get(0), list.get(1), list.get(2));
              break;
            default:
              throw new IllegalArgumentException(
                  "Argument parameters is a list " + "and must have 1, 2, or 3 elements.");
          }
        } else {
          throw new IllegalArgumentException(
              "Argument parameters " + "must be instance of List, Map, Object[], or null.");
        }

        if (logger.isDebugEnabled()) {
          logger.debug("Query result: " + ConversionHelper.convertObjectArrayElements(result));
        }

        checkResult(assertion, singleStringQuery, hasOrdering, result, expectedResult, positive);

      } finally {
        query.close(result);
      }
    } catch (JDOUserException e) {
      if (positive) {
        String msg = "JDOUserException thrown while executing query:\n" + singleStringQuery;
        throw new JDOException(msg, e);
      }
    } catch (JDOException e) {
      String msg = "JDOException thrown while executing query:\n" + singleStringQuery;
      throw new JDOException(msg, e);
    } finally {
      if (tx.isActive()) {
        tx.rollback();
      }
    }
    return result;
  }

  /**
   * @param assertion the assertion to prompt if the test case fails.
   * @param singleStringQuery the single string representation of the query. This parameter is only
   *     used as part of the falure message.
   * @param hasOrdering indicates if the query has an ordering clause.
   * @param positive indicates if query execution is supposed to fail
   * @param result the query result.
   * @param expectedResult the expected query result.
   */
  private void checkResult(
      String assertion,
      String singleStringQuery,
      boolean hasOrdering,
      Object result,
      Object expectedResult,
      boolean positive) {
    if (positive) {
      if (hasOrdering) {
        checkQueryResultWithOrder(assertion, singleStringQuery, result, expectedResult);
      } else {
        checkQueryResultWithoutOrder(assertion, singleStringQuery, result, expectedResult);
      }
    } else {
      fail(assertion, "Query must throw JDOUserException: " + singleStringQuery);
    }
  }

  /**
   * Converts the given query element holder instance to a JDO query instance. Calls {@link
   * Query#deletePersistentAll()}, or {@link Query#deletePersistentAll(java.util.Map)}, or {@link
   * Query#deletePersistentAll(java.lang.Object[])} depending on the type of argument <code>
   * parameters</code>. If the number of deleted objects does not match <code>
   * expectedNrOfDeletedObjects</code>, then the test case fails prompting argument <code>assertion
   * </code>.
   *
   * @param assertion the assertion to prompt if the test case fails.
   * @param queryElementHolder the query to execute.
   * @param expectedNrOfDeletedObjects the expected number of deleted objects.
   */
  protected void deletePersistentAllByAPIQuery(
      String assertion, QueryElementHolder<?> queryElementHolder, long expectedNrOfDeletedObjects) {
    if (logger.isDebugEnabled()) {
      logger.debug("Deleting persistent by API query: " + queryElementHolder);
    }
    delete(assertion, queryElementHolder, false, expectedNrOfDeletedObjects);
  }

  /**
   * Converts the given query element holder instance to a JDO query instance. Calls {@link
   * Query#deletePersistentAll()}, or {@link Query#deletePersistentAll(java.util.Map)}, or {@link
   * Query#deletePersistentAll(java.lang.Object[])} depending on the type of argument <code>
   * parameters</code>. If the number of deleted objects does not match <code>
   * expectedNrOfDeletedObjects</code>, then the test case fails prompting argument <code>assertion
   * </code>.
   *
   * @param assertion the assertion to prompt if the test case fails.
   * @param queryElementHolder the query to execute.
   * @param expectedNrOfDeletedObjects the expected number of deleted objects.
   */
  protected void deletePersistentAllBySingleStringQuery(
      String assertion, QueryElementHolder<?> queryElementHolder, long expectedNrOfDeletedObjects) {
    if (logger.isDebugEnabled()) {
      logger.debug("Deleting persistent by single string query: " + queryElementHolder);
    }
    delete(assertion, queryElementHolder, true, expectedNrOfDeletedObjects);
  }

  /**
   * Converts the given query element holder instance to a
   * JDO query based on argument <code>asSingleString</code>.
   * Calls {@link Query#deletePersistentAll()}, or
   * {@link Query#deletePersistentAll(java.util.Map), or
   * {@link Query#deletePersistentAll(java.lang.Object[])
   * depending on the type of argument <code>parameters</code>.
   * If the number of deleted objects does not
   * match <code>expectedNrOfDeletedObjects</code>,
   * then the test case fails prompting argument <code>assertion</code>.
   * @param assertion the assertion to prompt if the test case fails.
   * @param queryElementHolder the query to execute.
   * @param asSingleString determines if the query is executed as
   * single string query or as API query.
   * @param parameters the parmaters of the query.
   * @param expectedNrOfDeletedObjects the expected number of deleted objects.
   */
  private void delete(
      String assertion,
      QueryElementHolder<?> queryElementHolder,
      boolean asSingleString,
      long expectedNrOfDeletedObjects) {
    getPM();
    Query<?> query =
        asSingleString
            ? queryElementHolder.getSingleStringQuery(pm)
            : queryElementHolder.getAPIQuery(pm);
    delete(
        assertion,
        query,
        queryElementHolder.toString(),
        queryElementHolder.getParamValues(),
        expectedNrOfDeletedObjects);
    boolean positive = expectedNrOfDeletedObjects >= 0;
    if (positive) {
      execute(
          assertion,
          queryElementHolder,
          asSingleString,
          queryElementHolder.isUnique() ? null : Collections.emptyList());
    }
  }

  /**
   * Calls {@link Query#deletePersistentAll()}, or
   * {@link Query#deletePersistentAll(java.util.Map), or
   * {@link Query#deletePersistentAll(java.lang.Object[])
   * depending on the type of argument <code>parameters</code>.
   * If the number of deleted objects does not
   * match <code>expectedNrOfDeletedObjects</code>,
   * then the test case fails prompting argument <code>assertion</code>.
   * Argument <code>singleStringQuery</code> is only used as part
   * of the failure message.
   * @param assertion the assertion to prompt if the test case fails.
   * @param query the query to execute.
   * @param singleStringQuery the single string representation of the query.
   * @param parameters the parmaters of the query.
   * @param expectedNrOfDeletedObjects the expected number of deleted objects.
   */
  @SuppressWarnings("unchecked")
  private void delete(
      String assertion,
      Query<?> query,
      String singleStringQuery,
      Object parameters,
      long expectedNrOfDeletedObjects) {
    boolean positive = expectedNrOfDeletedObjects >= 0;
    getPM();
    Transaction tx = pm.currentTransaction();
    tx.begin();
    try {
      try {
        long nr;
        if (parameters == null) {
          nr = query.deletePersistentAll();
        } else if (parameters instanceof Object[]) {
          nr = query.deletePersistentAll((Object[]) parameters);
        } else if (parameters instanceof Map) {
          nr = query.deletePersistentAll((Map<String, Object>) parameters);
        } else {
          throw new IllegalArgumentException(
              "Argument parameters " + "must be instance of Object[], Map, or null.");
        }
        if (logger.isDebugEnabled()) {
          logger.debug(nr + " objects deleted.");
        }

        if (positive) {
          if (nr != expectedNrOfDeletedObjects) {
            fail(
                assertion,
                "deletePersistentAll returned "
                    + nr
                    + ", expected is "
                    + expectedNrOfDeletedObjects
                    + ". Query: "
                    + singleStringQuery);
          }
        } else {
          fail(assertion, "deletePersistentAll must throw JDOUserException: " + singleStringQuery);
        }
      } finally {
        query.closeAll();
      }
      tx.commit();
    } catch (JDOUserException e) {
      if (positive) {
        String msg = "JDOUserException thrown while executing query:\n" + singleStringQuery;
        throw new JDOException(msg, e);
      }
    } catch (JDOException e) {
      String msg = "JDOException thrown while executing query:\n" + singleStringQuery;
      throw new JDOException(msg, e);
    } finally {
      if (tx.isActive()) {
        tx.rollback();
      }
    }
  }
}
