blob: 274cba90880d326fcf37da9c3c7efc7d85cc27bf [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
<<<<<<< Updated upstream
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
=======
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
>>>>>>> Stashed changes
* limitations under the License.
*/
package org.apache.jdo.tck.query;
import java.util.Map;
import javax.jdo.Extent;
import javax.jdo.JDOQLTypedQuery;
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<T> {
// fields holding JDOQL query elements
private final Boolean unique;
private final String result;
private final Class<?> resultClass;
private final Class<T> candidateClass;
private final Boolean excludeSubClasses;
private final String filter;
private final String variables;
private final String parameters;
private final String imports;
private final String grouping;
private final String ordering;
private String fromString;
private String toString;
private Long fromLong;
private Long toLong;
private JDOQLTypedQuery<T> jdoqlTypedQuery;
private Map<String, Object> paramValues;
/**
* 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<T> 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 range from query element
* @param to the JDOQL range to query element
* @param jdoqlTypedQuery the query instance
* @param paramValues the parameter values
*/
public QueryElementHolder(
Boolean unique,
String result,
Class<?> resultClass,
Class<T> candidateClass,
Boolean excludeSubClasses,
String filter,
String variables,
String parameters,
String imports,
String grouping,
String ordering,
String from,
String to,
JDOQLTypedQuery<T> jdoqlTypedQuery,
Map<String, Object> paramValues) {
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;
this.jdoqlTypedQuery = jdoqlTypedQuery;
this.paramValues = paramValues;
}
/**
* 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
* @param jdoqlTypedQuery the query instance
* @param paramValues the parameter values
*/
public QueryElementHolder(
Boolean unique,
String result,
Class<?> resultClass,
Class<T> candidateClass,
Boolean excludeSubClasses,
String filter,
String variables,
String parameters,
String imports,
String grouping,
String ordering,
long from,
long to,
JDOQLTypedQuery<T> jdoqlTypedQuery,
Map<String, Object> paramValues) {
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 = Long.valueOf(from);
this.toLong = Long.valueOf(to);
this.jdoqlTypedQuery = jdoqlTypedQuery;
this.paramValues = paramValues;
}
/**
* 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
*/
@SuppressWarnings("unchecked")
public Query<T> 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<T> getAPIQuery(PersistenceManager pm) {
Extent<T> extent =
this.excludeSubClasses != null
? pm.getExtent(this.candidateClass, !this.excludeSubClasses.booleanValue())
: pm.getExtent(this.candidateClass);
Query<T> 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 JDOQLTypedQuery instance.
*
* @return the JDOQLTypedQuery instance
*/
public JDOQLTypedQuery<T> getJDOQLTypedQuery() {
if (this.jdoqlTypedQuery != null) {
this.rangeToJDOQLTypedQuery(this.jdoqlTypedQuery);
}
return this.jdoqlTypedQuery;
}
/**
* 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;
}
/**
* Returns the map of parameter values.
*
* @return the map of parameter values
*/
public Map<String, Object> getParamValues() {
return this.paramValues;
}
/**
* 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 res = "";
if (this.fromString != null && this.toString != null) {
res = "RANGE " + this.fromString + ',' + this.toString;
} else if (this.fromLong != null && this.toLong != null) {
res = "RANGE " + this.fromLong + ',' + this.toLong;
}
return res;
}
/**
* 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());
}
}
/**
* Call JDOQLTypedQuery API method {@link javax.jdo.JDOQLTypedQuery#range(long, long)}.
*
* @param query the JDOQLTypedQuery instance
*/
private void rangeToJDOQLTypedQuery(JDOQLTypedQuery<?> query) {
if (this.fromString != null && this.toString != null) {
query.range(Long.parseLong(this.fromString), Long.parseLong(this.toString));
} else if (this.fromLong != null && this.toLong != null) {
query.range(this.fromLong.longValue(), this.toLong.longValue());
}
}
}