Index: test/java/org/apache/jdo/tck/query/QueryTest.java
===================================================================
--- test/java/org/apache/jdo/tck/query/QueryTest.java (Revision 294784)
+++ test/java/org/apache/jdo/tck/query/QueryTest.java (Arbeitskopie)
@@ -19,14 +19,16 @@
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Iterator;
+import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
import javax.jdo.Extent;
import javax.jdo.JDOFatalInternalException;
+import javax.jdo.JDOUserException;
import javax.jdo.PersistenceManager;
import javax.jdo.Query;
import javax.jdo.Transaction;
@@ -381,4 +383,277 @@
logger.debug("X = " + pcp.getX() + "\tY = " + pcp.getY());
}
}
+
+ // company model helper methods
+
+ /**
+ * Returns an array of company mode instances for beans names
+ * in the given argument.
+ * @param beanNames the bean names of company mode instances.
+ * @return the array of company model instances.
+ */
+ protected Object[] getCompanyModelInstances(String[] beanNames) {
+ CompanyModelReader reader = new CompanyModelReader(COMPANY_TESTDATA);
+ Object[] result = new Object[beanNames.length];
+ for (int i = 0; i < beanNames.length; i++) {
+ result[i] = reader.getBean(beanNames[i]);
+ }
+ return result;
+ }
+
+ // compile query methods
+
+ /**
+ * Compiles the given query element holder instance as a JDO API query.
+ * Argument positive determines if the compilation is supposed
+ * to succeed or to fail. If true and the compilation fails,
+ * then the test case fails prompting argument assertion.
+ * If false and the compilation succeeds,
+ * then the test case fails prompting argument assertion.
+ * 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,
+ queryElementHolder.toString(), positive);
+ }
+
+ /**
+ * Compiles the given query element holder instance
+ * as a JDO single string query.
+ * Argument positive determines if the compilation is supposed
+ * to succeed or to fail. If true and the compilation fails,
+ * then the test case fails prompting argument assertion.
+ * If false and the compilation succeeds,
+ * then the test case fails prompting argument assertion.
+ * 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) {
+ compileSingleStringQuery(assertion,
+ queryElementHolder.toString(), positive);
+ }
+
+ /**
+ * Compiles the given single string query.
+ * Argument positive determines if the compilation is supposed
+ * to succeed or to fail. If true and the compilation fails,
+ * then the test case fails prompting argument assertion.
+ * If false and the compilation succeeds,
+ * then the test case fails prompting argument assertion.
+ * 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, singleStringQuery, positive);
+ }
+
+ /**
+ * Compiles the given query element holder instance
+ * as a JDO API query or single string query,
+ * depending if argument queryElementHolder
+ * is null.
+ * Argument positive determines if the compilation is supposed
+ * to succeed or to fail. If true and the compilation fails,
+ * then the test case fails prompting argument assertion.
+ * If false and the compilation succeeds,
+ * then the test case fails prompting argument assertion.
+ * Otherwise the test case succeeds.
+ * @param assertion the assertion to prompt if the test case fails.
+ * @param queryElementHolder the query to execute as a JDO API query.
+ * @param singleStringQuery the query to execute
+ * as a JDO single string query.
+ * @param positive determines if the compilation is supposed
+ * to succeed or to fail.
+ */
+ private void compile(String assertion,
+ QueryElementHolder queryElementHolder,
+ String singleStringQuery, boolean positive) {
+ PersistenceManager pm = getPM();
+ Transaction tx = pm.currentTransaction();
+ tx.begin();
+ try {
+ Query query;
+ if (queryElementHolder != null) {
+ query = queryElementHolder.getAPIQuery(pm);
+ } else {
+ query = getPM().newQuery(singleStringQuery);
+ }
+ query.compile();
+ if (!positive) {
+ fail(assertion +
+ "Query compilation must throw JDOUserException: " +
+ singleStringQuery);
+ }
+ } catch (JDOUserException e) {
+ if (positive) {
+ fail(assertion + "Query '" + singleStringQuery +
+ "' 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
+ * expectedResult. The array elements of that argument
+ * must match the content of the result collection
+ * returned by {@link Query#execute()}.
+ * If the expected result does not match the returned query result,
+ * then the test case fails prompting argument assertion.
+ * @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
+ * expectedResult. The array elements of that argument
+ * must match the content of the result collection
+ * returned by {@link Query#executeWithArray(java.lang.Object[])}.
+ * Argument parameters is passed as the parameter
+ * to that method.
+ * If the expected result does not match the returned query result,
+ * then the test case fails prompting argument assertion.
+ * @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
+ * expectedResult. The array elements of that argument
+ * must match the content of the result collection
+ * returned by {@link Query#execute()}.
+ * If the expected result does not match the returned query result,
+ * then the test case fails prompting argument assertion.
+ * @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
+ * expectedResult. The array elements of that argument
+ * must match the content of the result collection
+ * returned by {@link Query#executeWithArray(java.lang.Object[])}.
+ * Argument parameters is passed as the parameter
+ * to that method.
+ * If the expected result does not match the returned query result,
+ * then the test case fails prompting argument assertion.
+ * @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);
+ }
+
+ /**
+ * Executes the given query element holder instance
+ * as a JDO API query of a single string query,
+ * depending on argument asSingleString.
+ * The result of that query is compared against the given argument
+ * expectedResult. The array elements of that argument
+ * must match the content of the result collection
+ * returned by {@link Query#executeWithArray(java.lang.Object[])}.
+ * Argument parameters is passed as the parameter
+ * to that method.
+ * If the expected result does not match the returned query result,
+ * then the test case fails prompting argument assertion.
+ * @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
+ * singole string query or as API query.
+ * @param parameters the parmaters of the query.
+ * @param expectedResult the expected query result.
+ * @return
+ */
+ private Object execute(String assertion,
+ QueryElementHolder queryElementHolder, boolean asSingleString,
+ Object[] parameters, Object[] expectedResult) {
+ Object result;
+ PersistenceManager pm = getPM();
+ Transaction tx = pm.currentTransaction();
+ tx.begin();
+ try {
+ Query query = asSingleString ?
+ queryElementHolder.getSingleStringQuery(pm) :
+ queryElementHolder.getAPIQuery(pm);
+ result = parameters != null ?
+ query.executeWithArray(parameters) : query.execute();
+
+ if (queryElementHolder.isUnique()) {
+ Collection resultCollection = new LinkedList();
+ resultCollection.add(result);
+ result = resultCollection;
+ }
+
+ Collection expectedResultCollection =
+ Arrays.asList(expectedResult);
+ checkQueryResultWithoutOrder(assertion, result,
+ expectedResultCollection);
+ } finally {
+ if (tx.isActive()) {
+ tx.rollback();
+ }
+ }
+ return result;
+ }
}
Index: test/java/org/apache/jdo/tck/query/QueryElementHolder.java
===================================================================
--- test/java/org/apache/jdo/tck/query/QueryElementHolder.java (Revision 0)
+++ test/java/org/apache/jdo/tck/query/QueryElementHolder.java (Revision 0)
@@ -0,0 +1,252 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed 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 javax.jdo.Extent;
+import javax.jdo.PersistenceManager;
+import javax.jdo.Query;
+
+/**
+ * This class is an abstraction of a JDOQL query,
+ * which may be represented as a single string
+ * (e.g. SELECT FROM Person WHERE personid == 1) or
+ * as an API query using methods on class {@link Query}.
+ * + * The class may be used as the factory of a JDO {@link Query} instance + * using method {@link QueryElementHolder#getAPIQuery(PersistenceManager)} or + * method {@link QueryElementHolder#getSingleStringQuery(PersistenceManager).
+ *
+ * Instances of this class are capable to hold all elements of a JDOQL query,
+ * e.g. the candidate class, the filter, etc. These elements are passed
+ * calling the constructor. It is valid to pass null as a value
+ * for JDOQL querys elements. Such elements are not transfered into a
+ * JDO {@link Query} instance.
+ * Instead, the default of JDO {@link Query} instance is taken.
+ */
+public class QueryElementHolder {
+
+ // fields holding JDOQL query elements
+ private Boolean unique;
+ private String result;
+ private Class resultClass;
+ private Class candidateClass;
+ private Boolean excludeSubClasses;
+ private String filter;
+ private String variables;
+ private String parameters;
+ private String imports;
+ private String grouping;
+ private String ordering;
+ private Long from;
+ private Long to;
+
+ /**
+ * Returns an instance of this class holding the given arguments
+ * such as the candidate class, the filter, etc.
+ * The given arguments represent JDOQL query elements.
+ * It is valid to pass null as a value
+ * for JDOQL querys elements. Such elements are not transfered into a
+ * JDO {@link Query} instance.
+ * Instead, the default of JDO {@link Query} instance is taken.
+ * @param unique the JDOQL unique query element
+ * @param result the JDOQL result query element
+ * @param resultClass the JDOQL result class query element
+ * @param candidateClass the JDOQL candidate class query element
+ * @param excludeSubClasses the JDOQL exclude subclasses query element
+ * @param filter the JDOQL filter query element
+ * @param variables the JDOQL variables query element
+ * @param parameters the JDOQL parameters query element
+ * @param imports the JDOQL imports query element
+ * @param grouping the JDOQL grouping query element
+ * @param ordering the JDOQL ordering query element
+ * @param from the JDOQL range from query element
+ * @param to the JDOQL range to query element
+ */
+ public QueryElementHolder(Boolean unique, String result,
+ Class resultClass, Class candidateClass,
+ Boolean excludeSubClasses, String filter,
+ String variables, String parameters, String imports,
+ String grouping, String ordering, Long from, Long to) {
+ this.unique = unique;
+ this.result = result;
+ this.resultClass = resultClass;
+ this.candidateClass = candidateClass;
+ this.excludeSubClasses = excludeSubClasses;
+ this.filter = filter;
+ this.variables = variables;
+ this.parameters = parameters;
+ this.imports = imports;
+ this.grouping = grouping;
+ this.ordering = ordering;
+ this.from = from;
+ this.to = to;
+ }
+
+ /**
+ * @see Object#toString()
+ */
+ public String toString() {
+ return "SELECT " +
+ toString("UNIQUE", this.unique) +
+ toString(this.result) +
+ toString("INTO", this.resultClass) +
+ toString("FROM", this.candidateClass) +
+ toString("EXCLUDE SUBCLASSES", this.excludeSubClasses) +
+ toString("WHERE", this.filter) +
+ toString("VARIABLES", this.variables) +
+ toString("PARAMETERS", this.parameters) +
+ toString("IMPORTS", this.imports) +
+ toString("GROUP BY", this.grouping) +
+ toString("ORDER BY", this.ordering) +
+ rangeToString();
+ }
+
+ /**
+ * Creates a JDO {@link Query} instance using the JDOQL query elements
+ * of this instance. The returned instance is created calling
+ * {@link PersistenceManager#newQuery(String)}.
+ * The passed {@link String} instance is the
+ * single string representation of this,
+ * e.g. SELECT FROM Person WHERE personid == 1.
+ * @param pm the persistence manager
+ * @return the JDO query instance
+ */
+ public Query getSingleStringQuery(PersistenceManager pm) {
+ return pm.newQuery(toString());
+ }
+
+ /**
+ * Creates a JDO {@link Query} instance using the JDOQL query elements
+ * of this instance. The returned instance is created calling
+ * {@link PersistenceManager#newQuery(Extent)}.
+ * Afterwards, all query elements of this are transfered
+ * into that instance.
+ * @param pm the persistence manager
+ * @return the JDO query instance
+ */
+ public Query getAPIQuery(PersistenceManager pm) {
+ Query query = this.excludeSubClasses != null ?
+ pm.newQuery(pm.getExtent(this.candidateClass,
+ !this.excludeSubClasses.booleanValue())) :
+ pm.newQuery(pm.getExtent(this.candidateClass));
+ if (this.unique != null) {
+ query.setUnique(this.unique.booleanValue());
+ }
+ if (this.result != null ) {
+ query.setResult(this.result);
+ }
+ if (this.resultClass != null) {
+ query.setResultClass(this.resultClass);
+ }
+ if (this.filter != null) {
+ query.setFilter(this.filter);
+ }
+ if (this.variables != null) {
+ query.declareVariables(this.variables);
+ }
+ if (this.parameters != null) {
+ query.declareParameters(this.parameters);
+ }
+ if (this.imports != null ) {
+ query.declareImports(this.imports);
+ }
+ if (this.grouping != null) {
+ query.setGrouping(this.grouping);
+ }
+ if (this.ordering != null) {
+ query.setOrdering(this.ordering);
+ }
+ if (this.from != null && this.to != null &&
+ this.from.longValue() >= 0 && this.to.longValue() >= 0) {
+ query.setRange(this.from.longValue(), this.to.longValue());
+ }
+ return query;
+ }
+
+ /**
+ * Returns the unique JDOQL query element.
+ * @return the unique JDOQL query element.
+ */
+ protected boolean isUnique() {
+ return this.unique != null && this.unique.booleanValue();
+ }
+
+ /**
+ * Delegates to {@link QueryElementHolder#toString(String, String)
+ * if argument clazz does not equal null,
+ * otherwise returns an empty string.
+ * @param prefix the prefix of the returned string.
+ * @param clazz the returned string has the class name as a suffix.
+ * @return the string.
+ */
+ private String toString(String prefix, Class clazz) {
+ return (clazz != null? toString(prefix, clazz.getName()) : "");
+ }
+
+ /**
+ * Returns a string prefixed by argument prefix and
+ * suffixed by the string representation of argument bool,
+ * if argument bool does not equal null.
+ * Otherwise, an empty string is returned.
+ * @param prefix the prefix of the returned string.
+ * @param bool the returned string has the string representation
+ * of the value as a suffix.
+ * @return the string.
+ */
+ private String toString(String prefix, Boolean bool) {
+ return bool!=null && bool.booleanValue() ? prefix + ' ' : "";
+ }
+
+ /**
+ * Returns a string prefixed by argument prefix and
+ * suffixed by argument suffix,
+ * if argument suffix does not equal null.
+ * Otherwise, an empty string is returned.
+ * @param prefix the prefix of the returned string.
+ * @param suffix the suffix of the returned string.
+ * @return the string.
+ */
+ private String toString(String prefix, String suffix) {
+ return (suffix != null ? prefix + ' ' + suffix + ' ' : "");
+ }
+
+ /**
+ * Returns a string prefixed by argument prefix,
+ * if argument prefix does not equal null.
+ * Otherwise, an empty string is returned.
+ * @param prefix the prefix of the returned string.
+ * @return the string.
+ */
+ private String toString(String prefix) {
+ return (prefix != null ? prefix + ' ' : "");
+ }
+
+ /**
+ * Returns the single string representation
+ * of the JDOQL query element range.
+ * If that element is null,
+ * then an empty string is returned.
+ * @return the single string representation
+ * of the JDOQL query element range or null,
+ */
+ private String rangeToString() {
+ return (this.from != null && this.to != null &&
+ this.from.longValue() >= 0 && this.to.longValue() >= 0 ?
+ "RANGE " + this.from + " TO " + this.to: "");
+ }
+
+}