blob: 6f24164829e65d9cd9b71625a3063d11707267f0 [file] [log] [blame]
/*
* 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 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. <code>SELECT FROM Person WHERE personid == 1</code>) or
* as an API query using methods on class {@link Query}.<p>
*
* 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)}.<p>
*
* 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 <code>null</code> as a value
* for JDOQL querys elements. Such elements are not transfered into a
* JDO {@link javax.jdo.Query} instance.
* Instead, the default of JDO {@link javax.jdo.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 String fromString;
private String toString;
private Long fromLong;
private Long toLong;
/**
* 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 <code>null</code> as a value
* for JDOQL querys elements. Such elements are not transfered into a
* JDO {@link javax.jdo.Query} instance.
* Instead, the default of JDO {@link javax.jdo.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, String from, String to) {
if (from == null ^ to == null) {
throw new IllegalArgumentException(
"Arguments from and to must both be null, " +
"or must not be null both.");
}
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.fromString = from;
this.toString = 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 <code>null</code> as a value
* for JDOQL querys elements. Such elements are not transfered into a
* JDO {@link javax.jdo.Query} instance.
* Instead, the default of JDO {@link javax.jdo.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 from query element
* @param to the JDOQL 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.fromLong = new Long(from);
this.toLong = new Long(to);
}
/**
* Returns the single string JDOQL representation.
* @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(this.imports) +
toString("GROUP BY", this.grouping) +
toString("ORDER BY", this.ordering) +
rangeToString();
}
/**
* Creates a JDO {@link javax.jdo.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. <code>SELECT FROM Person WHERE personid == 1</code>.
* @param pm the persistence manager
* @return the JDO query instance
*/
public Query getSingleStringQuery(PersistenceManager pm) {
return pm.newQuery(toString());
}
/**
* Creates a JDO {@link javax.jdo.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 using API methods like
* {@link javax.jdo.Query#setFilter(java.lang.String)} etc.
* @param pm the persistence manager
* @return the JDO query instance
*/
public Query getAPIQuery(PersistenceManager pm) {
Extent extent = this.excludeSubClasses != null ?
pm.getExtent(this.candidateClass,
!this.excludeSubClasses.booleanValue()) :
pm.getExtent(this.candidateClass);
Query query = pm.newQuery(extent);
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);
}
rangeToAPI(query);
return query;
}
/**
* Returns the unique JDOQL query element.
* @return the unique JDOQL query element.
*/
public boolean isUnique() {
return this.unique != null && this.unique.booleanValue();
}
/**
* Returns the unique JDOQL query element.
* @return the unique JDOQL query element.
*/
public boolean hasOrdering() {
return this.ordering != null;
}
/**
* Returns the candtidate class JDOQL query element.
* @return the candtidate class JDOQL query element.
*/
public Class getCandidateClass() {
return this.candidateClass;
}
/**
* Delegates to {@link QueryElementHolder#toString(String, String)
* if argument <code>clazz</code> does not equal <code>null</code>,
* 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 <code>prefix</code> and
* suffixed by the string representation of argument <code>bool</code>,
* if argument <code>bool</code> does not equal <code>null</code>.
* 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 <code>prefix</code> and
* suffixed by argument <code>suffix</code>,
* if argument <code>suffix</code> does not equal <code>null</code>.
* 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 <code>prefix</code>,
* if argument <code>prefix</code> does not equal <code>null</code>.
* 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 <i>range</i>.
* If that element is <code>null</code>,
* then an empty string is returned.
* @return the single string representation
* of the JDOQL query element <i>range</i> or <code>null</code>,
*/
private String rangeToString() {
String result = "";
if (this.fromString != null && this.toString != null) {
result = "RANGE " + this.fromString + ',' + this.toString;
}
else if (this.fromLong != null && this.toLong != null) {
result = "RANGE " + this.fromLong + ',' + this.toLong;
}
return result;
}
/**
* Calls API method {@link javax.jdo.Query#setRange(String)} or
* {@link javax.jdo.Query#setRange(long, long)} depending on
* which of the from/to fields are set.
* @param query the query instance
*/
private void rangeToAPI(Query query) {
if (this.fromString != null && this.toString != null) {
query.setRange(this.fromString + ',' + this.toString);
}
else if (this.fromLong != null && this.toLong != null) {
query.setRange(this.fromLong.longValue(), this.toLong.longValue());
}
}
}