/*
 * 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.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.Iterator;
import java.util.List;
import java.util.Map;

import javax.jdo.JDOException;
import javax.jdo.JDOUserException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.Transaction;

import junit.framework.AssertionFailedError;

import org.apache.jdo.tck.JDO_Test;
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 JDO_Test {

    /** */
    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 List 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
    
    /** */
    public void loadAndPersistPCPoints(PersistenceManager pm) {
        insertPCPoints(pm, 5);
    }

    /** */
    protected void insertPCPoints(PersistenceManager pm, int numInsert) {
        Transaction tx = pm.currentTransaction();
        try {
            tx.begin();
            for(int i = 0; i<numInsert; i++) {
                Object 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();
        }
    }
       
    /** */
    public List getFromInserted(List list) {
        if (list == null)
            return null;
        
        List result = new ArrayList();
        for (Iterator iter = list.iterator(); iter.hasNext();) {
            Object pc = iter.next();
            for (Iterator iteri = inserted.iterator(); iteri.hasNext();) {
                Object pci = iteri.next();
                if (((PCPoint)pc).getX() == ((PCPoint)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.
     */
    public CompanyModelReader loadAndPersistCompanyModel(PersistenceManager pm) {
        makePersistentAll(
            pm, getCompanyModelReaderForPersistentInstances().getRootList());
        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.
     */
    public MylibReader loadAndPersistMylib(PersistenceManager pm) {
        makePersistentAll(
            pm, getMylibReaderForPersistentInstances().getRootList());
        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 beanName the bean name.
     * @return the persistent company model instance. 
     */
    protected Object getPersistentCompanyModelInstance(String beanName) {
        return beanName == null ? null :
            getCompanyModelReaderForPersistentInstances().getBean(beanName);
    }
    
    /**
     * Returns a transient company model instance for the given bean name.
     * @param beanName the bean name.
     * @return the transient company model instance. 
     */
    protected Object getTransientCompanyModelInstance(String beanName) {
        return beanName == null ? null :
            getCompanyModelReaderForTransientInstances().getBean(beanName);
    }
    
    /**
     * Returns an array of persistent company model instances for bean names 
     * in the given argument.
     * @param beanNames the bean names of company mode instances.
     * @return the array of persistent company model instances. 
     */
    protected Object[] getPersistentCompanyModelInstances(String[] beanNames) {
        Object[] result = new Object[beanNames.length];
        for (int i = 0; i < beanNames.length; i++) {
            result[i] = getPersistentCompanyModelInstance(beanNames[i]);
        }
        return result;
    }
    
    /**
     * Returns an array of transient company model instances for bean names 
     * in the given argument.
     * @param beanNames the bean names of company mode instances.
     * @return the array of transient company model instances. 
     */
    protected Object[] getTransientCompanyModelInstances(String[] beanNames) {
        Object[] result = new Object[beanNames.length];
        for (int i = 0; i < beanNames.length; i++) {
            result[i] = getTransientCompanyModelInstance(beanNames[i]);
        }
        return result;
    }
    
    /**
     * Returns a list of persistent company model instances instances 
     * for beans names in the given argument.
     * @param beanNames the bean names of company model instances.
     * @return the list of persistent company model instances. 
     */
    protected List getPersistentCompanyModelInstancesAsList(
            String[] beanNames) {
        return new ArrayList(
                Arrays.asList(getPersistentCompanyModelInstances(beanNames)));
    }
    
    /**
     * Returns a list of transient company model instances instances 
     * for beans names in the given argument.
     * @param beanNames the bean names of company model instances.
     * @return the list of transient company model instances. 
     */
    protected List getTransientCompanyModelInstancesAsList(
            String[] beanNames) {
        return new ArrayList(
                Arrays.asList(getTransientCompanyModelInstances(beanNames)));
    }
    
    /**
     * 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 : getMylibReaderForPersistentInstances().getBean(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 : getMylibReaderForTransientInstances().getBean(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 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 getTransientMylibInstancesAsList(String[] beanNames) {
        return Arrays.asList(getTransientMylibInstances(beanNames));
    }
    
    // PrimitiveTypes helper methods (creation and query)

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

    /** */
    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(
                    (long)i, bFlag, new Boolean(bFlag), (byte)i, new Byte((byte)i),
                    (short)i, new Short((short)i), (int) i, new Integer(i),
                    (long)i, new Long(i), (float)i, new Float(i), 
                    (double)i, new Double(i), charValue, new Character(charValue),
                    Calendar.getInstance().getTime(), strValue,
                    new BigDecimal(String.valueOf(i)), 
                    new BigInteger(String.valueOf(i)),
                    new Long(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.
     */
    protected void runSimplePrimitiveTypesQuery(String filter, 
                                                PersistenceManager pm,
                                                Collection expected,
                                                String assertion) {
        Query q = pm.newQuery();
        q.setClass(PrimitiveTypes.class);
        q.setFilter(filter);
        Collection results = (Collection)q.execute();
        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.
     */
    protected void runParameterPrimitiveTypesQuery(String filter,
                                                   String paramDecl,
                                                   Object paramValue,
                                                   PersistenceManager pm,
                                                   Collection expected,
                                                   String assertion) {
        Query q = pm.newQuery();
        q.setClass(PrimitiveTypes.class);
        q.setFilter(filter);
        q.declareParameters(paramDecl);
        Collection results = (Collection)q.execute(paramValue);
        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.
     */
    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.
     */
    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);
    }

    /** */
    protected void checkQueryResultWithOrder(String assertion, 
                                             String query,
                                             Object result, 
                                             Object expected) {
        if (!equals(result, expected)) {
            queryFailed(assertion, query, result, 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.lang.Object)}.
     * 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 boolean equalsList(List o1, List o2) {
        boolean result = true;
        if (o1 != o2) {
            if (o1.size() != o2.size()) {
                result = false;
            } else {
                Iterator i = o1.iterator();
                Iterator 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 boolean equalsCollection(Collection o1, Collection o2) {
        // make a copy of o2 so we can destroy it
        Collection o2copy = new ArrayList();
        Iterator i2 = o2.iterator();
        while (i2.hasNext()) {
            o2copy.add(i2.next());
        }
        boolean result = true;
        if (o1 != o2) {
            if (o1.size() != o2.size()) {
                result = false;
            } else {
                for (Iterator i = o1.iterator(); i.hasNext(); ) {
                    Object oo1 = i.next();
                    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 boolean equalsMap(Map o1, Map o2) {
        boolean result = true;
        if (o1 != o2) {
            if (o1.size() != o2.size()) {
                result = false;
            } else {
                for (Iterator i = o1.entrySet().iterator(); i.hasNext(); ) {
                    Map.Entry entry = (Map.Entry) i.next();
                    Object key = entry.getKey();
                    Object value = entry.getValue();
                    Object 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 col, Object o) {
        for (Iterator i = col.iterator(); i.hasNext(); ) {
            if (equals(o, i.next())) {
                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 boolean remove(Collection col, Object o) {
        for (Iterator 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.
     */
    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
     
    /** */
    protected void printOutput(Object results, Collection expected) {
        if (!debug)
            return;

        Iterator iter = null;
        PCPoint pcp = null;
        if (results == null) {
            logger.debug("Query returns null");
        }
        if (!(results instanceof Collection)) {
            logger.debug("Query result is not a collection: " +
                         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 = ((Collection)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) {
        PersistenceManager pm = 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
     * @param query
     * @param queryText
     * @param positive
     */
    protected void compile(String assertion, 
            Query query, String queryText, boolean positive) {
        PersistenceManager pm = 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) {
        executeAPIQuery(assertion, queryElementHolder, null, expectedResult);
    }

    /**
     * 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 parameters the parmaters of the query.
     * @param expectedResult the expected query result.
     */
    protected void executeAPIQuery(String assertion,
            QueryElementHolder queryElementHolder, 
            Object[] parameters, Object expectedResult) {
        if (logger.isDebugEnabled()) {
            logger.debug("Executing API query: " + queryElementHolder);
        }
        execute(assertion, queryElementHolder, false, 
                parameters, 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) {
        executeSingleStringQuery(assertion, queryElementHolder, 
                null, 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 parameters the parmaters of the query.
     * @param expectedResult the expected query result.
     */
    protected void executeSingleStringQuery(String assertion,
            QueryElementHolder queryElementHolder, 
            Object[] parameters, Object expectedResult) {
        if (logger.isDebugEnabled())
            logger.debug("Executing single string query: " + 
                    queryElementHolder);
        execute(assertion, queryElementHolder, true, 
                parameters, expectedResult);
    }

    /**
     * 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 parameters the parmaters of the query.
     * @param expectedResult the expected query result.
     * @return the query result
     */
    private Object execute(String assertion, 
            QueryElementHolder queryElementHolder, boolean asSingleString,
            Object parameters, Object expectedResult) {
        PersistenceManager pm = getPM();
        Query query = asSingleString ?
                queryElementHolder.getSingleStringQuery(pm) :
                    queryElementHolder.getAPIQuery(pm);
        Object result = execute(assertion, query, 
                queryElementHolder.toString(), 
                queryElementHolder.hasOrdering(), parameters, 
                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 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.
     */
    protected void executeSQLQuery(String assertion, String sql, 
            Class 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 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 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 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
     */
    private Object execute(String assertion, Query query, 
            String singleStringQuery, boolean hasOrdering,
            Object parameters, Object expectedResult, boolean positive) {
        Object result = null;
        PersistenceManager pm = 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)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));
                }
    
                if (positive) {
                    if (hasOrdering) {
                        checkQueryResultWithOrder(assertion, singleStringQuery, result, 
                                expectedResult);
                    } else {
                        checkQueryResultWithoutOrder(assertion, singleStringQuery, result, 
                                expectedResult);
                    }
                } else {
                    fail(assertion, "Query must throw JDOUserException: " + 
                            singleStringQuery);
                }
            } 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;
    }

    /**
     * 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 parameters the parmaters of the query.
     * @param expectedNrOfDeletedObjects the expected number of deleted objects.
     */
    protected void deletePersistentAllByAPIQuery(String assertion,
            QueryElementHolder queryElementHolder, 
            Object parameters, long expectedNrOfDeletedObjects) {
        if (logger.isDebugEnabled()) {
            logger.debug("Deleting persistent by API query: " + 
                    queryElementHolder);
        }
        delete(assertion, queryElementHolder, false, 
                parameters, 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 parameters the parmaters of the query.
     * @param expectedNrOfDeletedObjects the expected number of deleted objects.
     */
    protected void deletePersistentAllBySingleStringQuery(String assertion,
            QueryElementHolder queryElementHolder, 
            Object parameters, long expectedNrOfDeletedObjects) {
        if (logger.isDebugEnabled()) {
            logger.debug("Deleting persistent by single string query: " + 
                    queryElementHolder);
        }
        delete(assertion, queryElementHolder, true, 
                parameters, 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,
            Object parameters, long expectedNrOfDeletedObjects) {
        PersistenceManager pm = getPM();
        Query query = asSingleString ?
                queryElementHolder.getSingleStringQuery(pm) :
                    queryElementHolder.getAPIQuery(pm);
        delete(assertion, query, queryElementHolder.toString(), 
                parameters, expectedNrOfDeletedObjects);
        boolean positive = expectedNrOfDeletedObjects >= 0;
        if (positive) {
            execute(assertion, queryElementHolder, asSingleString, parameters, 
                    queryElementHolder.isUnique() ? null : new ArrayList());
        }
    }

    /**
     * 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.
     */
    private void delete(String assertion, Query query, 
            String singleStringQuery, Object parameters, 
            long expectedNrOfDeletedObjects) {
        boolean positive = expectedNrOfDeletedObjects >= 0;
        PersistenceManager pm = 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)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();
            }
        }
    }
}
