/**
* Example license header for Java files
*
* http://andromda.sourceforge.net/
*/
//
// Attention: Generated code! Do not modify by hand!
// Generated by hibernate/HibernateSearch.vsl in andromda-spring-cartridge on 09/18/2014 17:02:26-0400. Do not modify by hand!.
//
package org.andromda.spring;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Criteria;
import org.hibernate.FetchMode;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.criterion.Conjunction;
import org.hibernate.criterion.CriteriaSpecification;
import org.hibernate.criterion.Criterion;
import org.hibernate.criterion.Disjunction;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Restrictions;
import org.hibernate.criterion.SimpleExpression;
/**
* Implements a generic search mechanism based on the Hibernate Criteria API. The
* CriteriaSearch
allows adding parameters which function as where clause. The
* parameters are analyzed whether they should be considered or not. This depends both on the actual
* value of the parameter and on the configuration.
* The CriteriaSearch
is expected to be a general solution for a basic search with
* parameters connected by logical and . This search does not provide grouping.
*
* @author Stefan Reichert
* @author Peter Friese
* @author Chad Brandon
* @see Criteria
* @see Restrictions
*/
public class CriteriaSearch
{
private CriteriaSearchConfiguration configuration;
private Criteria rootCriteria;
private Map childCriteriaMap;
private List orderList;
@SuppressWarnings("rawtypes")
private Class resultType;
private static final class ParameterComparator
implements Comparator
{
@Override
public int compare(final Object object1, final Object object2)
{
final CriteriaSearchParameter parameter1 = (CriteriaSearchParameter)object1;
final CriteriaSearchParameter parameter2 = (CriteriaSearchParameter)object2;
final int relevance1 = parameter1.getOrderRelevance();
final int relevance2 = parameter2.getOrderRelevance();
int result = 0;
if (relevance1 > relevance2)
{
result = 1;
}
else if (relevance1 < relevance2)
{
result = -1;
}
return result;
}
}
/**
* Exposes the root criteria to subclasses.
* @return rootCriteria
*/
protected Criteria getRootCriteria()
{
return this.rootCriteria;
}
/**
* Constructor for CriteriaSearch. Creates a CriteriaSearch
with a default
* CriteriaSearchConfiguration
.
*
* @param session The Hibernate session.
* @param resultTypeIn The Class
of the result.
*/
public CriteriaSearch(Session session,@SuppressWarnings("rawtypes") Class resultTypeIn)
{
this.configuration = new CriteriaSearchConfiguration();
this.resultType = resultTypeIn;
this.rootCriteria = session.createCriteria(this.resultType);
this.childCriteriaMap = new HashMap();
this.orderList = new ArrayList();
}
/**
* Executes a HibernateQuery
using the currently defined
* CriteriaSearchParameter
s, and returns a java.util.Set
* containing the query results.
*
* @return result The result of the query.
* @throws HibernateException
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
public Set> executeAsSet()
throws HibernateException
{
return new LinkedHashSet(this.executeAsList());
}
/**
* Executes a HibernateQuery
using the currently defined
* CriteriaSearchParameter
s, and returns a java.util.List
* containing the query results.
*
* @return result The result of the query as a List
* @throws HibernateException
*/
@SuppressWarnings({ "rawtypes", "synthetic-access" })
public List executeAsList()
throws HibernateException
{
// add ordering
if (this.orderList.size() > 0)
{
Collections.sort(this.orderList, new ParameterComparator());
for (final CriteriaSearchParameter parameter : this.orderList)
{
int direction = parameter.getOrderDirection();
if (direction == SearchParameter.ORDER_ASC)
{
this.getParameterCriteria(parameter).addOrder(Order.asc(this.getParameterName(parameter)));
}
else
{
this.getParameterCriteria(parameter).addOrder(Order.desc(this.getParameterName(parameter)));
}
}
}
// set the first result if configured
if (this.configuration.getFirstResult() != null)
{
this.rootCriteria.setFirstResult(this.configuration.getFirstResult().intValue());
}
// set the fetch size if configured
if (this.configuration.getFetchSize() != null)
{
this.rootCriteria.setFetchSize(this.configuration.getFetchSize().intValue());
}
// limit the maximum result if configured
if (this.configuration.getMaximumResultSize() != null)
{
this.rootCriteria.setMaxResults(this.configuration.getMaximumResultSize().intValue());
}
return this.rootCriteria.list();
}
/**
* Adds a CriteriaSearchParameter
to this search. The parameter is connected to
* the search by logical and . It is not considered if the value is null
.
* If the value is not null
it is compared using the
* CriteriaSearchParameter.EQUALS_COMPARATOR
.
*
* @param parameterValue The value of the parameter.
* @param parameterPattern The pattern of the parameter (dot-separated path e.g. person.address.street).
* @throws HibernateException
*/
public void addParameter(Object parameterValue, String parameterPattern)
throws HibernateException
{
addParameter(new CriteriaSearchParameter(parameterValue, parameterPattern));
}
/**
* Adds a CriteriaSearchParameter
to this search. The parameter is connected to
* the search by logical and . It is not considered if the value is null
or
* if the String
empty. If the value is not null
it is compared
* using the CriteriaSearchParameter.LIKE_COMPARATOR
.
*
* @param parameterValue The value of the parameter.
* @param parameterPattern The pattern of the parameter (dot-separated path e.g. person.address.street).
* @throws HibernateException
*/
public void addParameter(String parameterValue, String parameterPattern)
throws HibernateException
{
addParameter(new CriteriaSearchParameter(parameterValue, parameterPattern));
}
/**
* Adds a CriteriaSearchParameter
to this search. The parameter is connected to
* the search by logical and .
*
* @param parameter The CriteriaSearchParameter
to add.
* @throws HibernateException
*/
public void addParameter(CriteriaSearchParameter parameter)
throws HibernateException
{
if (considerParameter(parameter))
{
final Criteria parameterCriteria = this.getParameterCriteria(parameter);
final String parameterName = this.getParameterName(parameter);
// check the type parameter value to add
if(parameter.getParameterValue() instanceof Object[])
{
addExpression(
parameterCriteria,
parameterName,
(Object[])parameter.getParameterValue(),
parameter.getComparator(),
parameter.getMatchMode());
}
else
{
addExpression(
parameterCriteria,
parameterName,
parameter.getParameterValue(),
parameter.getComparator(),
parameter.getMatchMode());
}
}
// if the parameter is to be ordered, add it to the order list
if (parameter.getOrderDirection() != SearchParameter.ORDER_UNSET)
{
this.orderList.add(parameter);
}
}
/**
* Retrieves the appropriate criteria object for the given parameter
.
*
* @param parameter the parameter for which to retrieve the criteria.
* @return the retrieved criteria.
*/
private Criteria getParameterCriteria(final CriteriaSearchParameter parameter)
throws HibernateException
{
String[] path = CriteriaSearchParameter.PATTERN.split(parameter.getParameterPattern());
Criteria parameterCriteria = this.rootCriteria;
Criteria childEntityCriteria;
if (path.length > 1)
{
// We have a parameter affecting an attribute of an inner childEntity object so we need
// to traverse to get the right criteria object
childEntityCriteria = this.rootCriteria;
// Evaluating the proper criteria object for the defined parameter
@SuppressWarnings("rawtypes")
Class type = this.resultType;
for (int index = 0; index < (path.length - 1); index++)
{
final String childEntityName = path[index];
final Collection embeddedValues = CriteriaSearchProperties.getEmbeddedValues(type);
if (embeddedValues != null && embeddedValues.contains(childEntityName))
{
// - use the rest of the path as the parameter name
final int number = path.length - index;
final String[] restOfPath = new String[path.length - index];
System.arraycopy(path, index, restOfPath, 0, number);
break;
}
type = CriteriaSearchProperties.getNavigableAssociationEndType(type, childEntityName);
childEntityCriteria = locateCriteria(childEntityName, childEntityCriteria);
}
if (childEntityCriteria != null)
{
// We now have the right criteria object
parameterCriteria = childEntityCriteria;
}
}
return parameterCriteria;
}
/**
* Retrieves the appropriate nested parameter name for the given parameter
.
*
* @param parameter the parameter for which to retrieve the parameter name.
* @return the parameter name.
*/
private String getParameterName(final CriteriaSearchParameter parameter)
{
// parsing the pattern of the parameter
String[] path = CriteriaSearchParameter.PATTERN.split(parameter.getParameterPattern());
String parameterName = path[path.length - 1];
if (path.length > 1)
{
// We have a parameter affecting an attribute of an inner childEntity object so we need
// to traverse to get the correct parameter name
// Evaluating the proper criteria object for the defined parameter
@SuppressWarnings("rawtypes")
Class type = this.resultType;
for (int index = 0; index < (path.length - 1); index++)
{
final String childEntityName = path[index];
final Collection embeddedValues = CriteriaSearchProperties.getEmbeddedValues(type);
if (embeddedValues != null && embeddedValues.contains(childEntityName))
{
// - use the rest of the path as the parameter name
final int number = path.length - index;
final String[] restOfPath = new String[path.length - index];
System.arraycopy(path, index, restOfPath, 0, number);
parameterName = StringUtils.join(restOfPath, ".");
break;
}
type = CriteriaSearchProperties.getNavigableAssociationEndType(type, childEntityName);
}
}
return parameterName;
}
/**
* Decides whether a paramter is considered as a criteria for a search depending on the type and
* value of the parameterValue
and searchIfIsNull
. A
* parameterValue
of the type String
is considered
* null
if being a NullPointer
or empty.
*
* @param parameter The parameter to check.
*/
private boolean considerParameter(CriteriaSearchParameter parameter)
{
if (parameter.getParameterValue() instanceof String)
{
String stringParameterValue = (String) parameter.getParameterValue();
return (parameter.isSearchIfNull()
|| (stringParameterValue != null && stringParameterValue.length() > 0));
}
if (parameter.getParameterValue() instanceof Object[])
{
Object[] parameterValues = (Object[]) parameter.getParameterValue();
return (parameter.isSearchIfNull()
|| (parameterValues != null && parameterValues.length > 0));
}
final int comparator = parameter.getComparator();
return (parameter.isSearchIfNull() ||
SearchParameter.NOT_NULL_COMPARATOR == comparator ||
SearchParameter.NULL_COMPARATOR == comparator ||
SearchParameter.EMPTY_COMPARATOR == comparator ||
SearchParameter.NOT_EMPTY_COMPARATOR == comparator) ||
(parameter.getParameterValue() != null);
}
/**
* Adds an Restrictions
to a Criteria
.
*
* @param criteria
* @param parameterName
* @param parameterValue
* @param comparator
* @param matchMode
*/
private void addExpression(
Criteria criteria,
String parameterName,
Object parameterValue,
int comparator,
MatchMode matchMode)
{
switch (comparator)
{
case SearchParameter.NOT_NULL_COMPARATOR:
{
criteria.add(Restrictions.isNotNull(parameterName));
break;
}
case SearchParameter.NULL_COMPARATOR:
{
criteria.add(Restrictions.isNull(parameterName));
break;
}
case SearchParameter.EMPTY_COMPARATOR:
{
criteria.add(Restrictions.isEmpty(parameterName));
break;
}
case SearchParameter.NOT_EMPTY_COMPARATOR:
{
criteria.add(Restrictions.isNotEmpty(parameterName));
break;
}
default:
{
if (parameterValue != null)
{
switch (comparator)
{
case SearchParameter.LIKE_COMPARATOR:
{
if ((matchMode != null) && (parameterValue instanceof String))
{
criteria.add(Restrictions.like(
parameterName,
(String)parameterValue,
matchMode));
}
else
{
criteria.add(Restrictions.like(parameterName, parameterValue));
}
break;
}
case SearchParameter.NOT_LIKE_COMPARATOR:
{
SimpleExpression expression;
if ((matchMode != null) && (parameterValue instanceof String))
{
expression = Restrictions.like(
parameterName,
(String)parameterValue,
matchMode);
}
else
{
expression = Restrictions.like(parameterName, parameterValue);
}
criteria.add(Restrictions.not(expression));
break;
}
case SearchParameter.INSENSITIVE_LIKE_COMPARATOR:
{
if ((matchMode != null) && (parameterValue instanceof String))
{
criteria.add(Restrictions.ilike(
parameterName,
(String)parameterValue,
matchMode));
}
else
{
criteria.add(Restrictions.ilike(parameterName, parameterValue));
}
break;
}
case SearchParameter.NOT_INSENSITIVE_LIKE_COMPARATOR:
{
Criterion criterion;
if ((matchMode != null) && (parameterValue instanceof String))
{
criterion = Restrictions.ilike(
parameterName,
(String)parameterValue,
matchMode);
}
else
{
criterion = Restrictions.ilike(parameterName, parameterValue);
}
criteria.add(Restrictions.not(criterion));
break;
}
case SearchParameter.EQUAL_COMPARATOR:
{
criteria.add(Restrictions.eq(parameterName, parameterValue));
break;
}
case SearchParameter.GREATER_THAN_OR_EQUAL_COMPARATOR:
{
criteria.add(Restrictions.ge(parameterName, parameterValue));
break;
}
case SearchParameter.GREATER_THAN_COMPARATOR:
{
criteria.add(Restrictions.gt(parameterName, parameterValue));
break;
}
case SearchParameter.LESS_THAN_OR_EQUAL_COMPARATOR:
{
criteria.add(Restrictions.le(parameterName, parameterValue));
break;
}
case SearchParameter.LESS_THAN_COMPARATOR:
{
criteria.add(Restrictions.lt(parameterName, parameterValue));
break;
}
case SearchParameter.IN_COMPARATOR:
{
if (parameterValue instanceof Collection)
{
criteria.add(Restrictions.in(parameterName, (Collection)parameterValue));
}
break;
}
case SearchParameter.NOT_IN_COMPARATOR:
{
if (parameterValue instanceof Collection)
{
criteria.add(Restrictions.not(Restrictions.in(parameterName, (Collection)parameterValue)));
}
break;
}
case SearchParameter.NOT_EQUAL_COMPARATOR:
{
criteria.add(Restrictions.ne(parameterName, parameterValue));
break;
}
default:
break;
}
}
else
{
criteria.add(Restrictions.isNull(parameterName));
}
}
}
}
/**
* Adds an Restrictions
to a Criteria
. The given parameterValues
* represents either an array of String
or another object. The different values in the
* array are added to a disjunction or conjunction which is connected with logical and to the other criteria of the
* search.
*
* @param criteria
* @param parameterName
* @param parameterValues
* @param searchIfNull
* @param comparator
* @param matchMode
*/
private void addExpression(
Criteria criteria,
String parameterName,
Object[] parameterValues,
int comparator,
MatchMode matchMode)
{
if (parameterValues != null)
{
Disjunction disjunction = null;
Conjunction conjunction = null;
switch (comparator)
{
case SearchParameter.LIKE_COMPARATOR:
{
disjunction = Restrictions.disjunction();
if ((matchMode != null) && (parameterValues instanceof String[]))
{
String[] stringParameterValues = (String[]) parameterValues;
for (int index = 0; index < parameterValues.length; index++)
{
if (stringParameterValues[index] != null)
{
disjunction.add(Restrictions.like(
parameterName, stringParameterValues[index], matchMode));
}
else
{
disjunction.add(Restrictions
.isNull(parameterName));
}
}
}
else
{
for (int index = 0; index < parameterValues.length; index++)
{
if (parameterValues[index] != null)
{
disjunction.add(Restrictions.like(
parameterName, parameterValues[index]));
}
else
{
disjunction.add(Restrictions
.isNull(parameterName));
}
}
}
break;
}
case SearchParameter.INSENSITIVE_LIKE_COMPARATOR:
{
disjunction = Restrictions.disjunction();
if ((matchMode != null) && (parameterValues instanceof String[]))
{
String[] stringParameterValues = (String[]) parameterValues;
for (int index = 0; index < parameterValues.length; index++)
{
if (stringParameterValues[index] != null) {
disjunction.add(Restrictions.ilike(
parameterName, stringParameterValues[index], matchMode));
}
else {
disjunction.add(Restrictions
.isNull(parameterName));
}
}
}
else
{
for (int index = 0; index < parameterValues.length; index++)
{
if (parameterValues[index] != null)
{
disjunction.add(Restrictions.ilike(
parameterName, parameterValues[index]));
}
else
{
disjunction.add(Restrictions
.isNull(parameterName));
}
}
}
break;
}
case SearchParameter.EQUAL_COMPARATOR:
{
disjunction = Restrictions.disjunction();
for (int index = 0; index < parameterValues.length; index++)
{
if (parameterValues[index] != null)
{
disjunction.add(Restrictions.eq(parameterName,
parameterValues[index]));
}
else {
disjunction.add(Restrictions.isNull(parameterName));
}
}
break;
}
case SearchParameter.GREATER_THAN_OR_EQUAL_COMPARATOR:
{
disjunction = Restrictions.disjunction();
for (int index = 0; index < parameterValues.length; index++)
{
if (parameterValues[index] != null)
{
disjunction.add(Restrictions.ge(parameterName,
parameterValues[index]));
}
else
{
disjunction.add(Restrictions.isNull(parameterName));
}
}
break;
}
case SearchParameter.GREATER_THAN_COMPARATOR:
{
disjunction = Restrictions.disjunction();
for (int index = 0; index < parameterValues.length; index++)
{
if (parameterValues[index] != null)
{
disjunction.add(Restrictions.gt(parameterName,
parameterValues[index]));
}
else
{
disjunction.add(Restrictions.isNull(parameterName));
}
}
break;
}
case SearchParameter.LESS_THAN_OR_EQUAL_COMPARATOR:
{
disjunction = Restrictions.disjunction();
for (int index = 0; index < parameterValues.length; index++)
{
if (parameterValues[index] != null)
{
disjunction.add(Restrictions.le(parameterName,
parameterValues[index]));
}
else
{
disjunction.add(Restrictions.isNull(parameterName));
}
}
break;
}
case SearchParameter.LESS_THAN_COMPARATOR:
{
disjunction = Restrictions.disjunction();
for (int index = 0; index < parameterValues.length; index++)
{
if (parameterValues[index] != null)
{
disjunction.add(Restrictions.lt(parameterName,
parameterValues[index]));
}
else
{
disjunction.add(Restrictions.isNull(parameterName));
}
}
break;
}
case SearchParameter.IN_COMPARATOR:
{
criteria.add(Restrictions.in(parameterName, parameterValues));
break;
}
case SearchParameter.NOT_IN_COMPARATOR:
{
criteria.add(Restrictions.not(Restrictions.in(parameterName, parameterValues)));
break;
}
case SearchParameter.NOT_EQUAL_COMPARATOR:
{
conjunction = Restrictions.conjunction();
for (int index = 0; index < parameterValues.length; index++)
{
if (parameterValues[index] != null)
{
conjunction.add(Restrictions.ne(parameterName,
parameterValues[index]));
}
else
{
conjunction.add(Restrictions.isNotNull(parameterName));
}
}
break;
}
default:
break;
}
if (disjunction != null)
{
criteria.add(disjunction);
}
if (conjunction != null)
{
criteria.add(conjunction);
}
}
else
{
switch (comparator)
{
case SearchParameter.EMPTY_COMPARATOR:
{
criteria.add(Restrictions.isEmpty(parameterName));
break;
}
case SearchParameter.NOT_EMPTY_COMPARATOR:
{
criteria.add(Restrictions.isNotEmpty(parameterName));
break;
}
default:
{
criteria.add(Restrictions.isNull(parameterName));
}
}
}
}
/**
* Locates a Criteria
for a childEntityName
. If a
* Criteria
exists for the childEntityName
, it is returned. If
* not, one is created and referenced in the childCriteriaMap
under the
* childEntityName
.
*
* @param childEntityName
* @param parentCriteria
* @return criteria The Criteria for the childEntityName.
* @throws HibernateException
*/
private Criteria locateCriteria(String childEntityName, Criteria parentCriteria) throws HibernateException
{
if (this.childCriteriaMap.containsKey(childEntityName))
{
return this.childCriteriaMap.get(childEntityName);
}
Criteria childCriteria = parentCriteria.createCriteria(childEntityName);
if (this.configuration.isForceEagerLoading())
{
parentCriteria.setFetchMode(childEntityName, FetchMode.JOIN);
}
// Hibernate does not support a 'unique' identifier. As a search may contain outer joins,
// duplicates in the resultList are possible. We eliminate any duplicates here, creating a
// distinctified resultSet (Suggestion from Hibernate itself; see www.hibernate.org's FAQ's).
parentCriteria.setResultTransformer(CriteriaSpecification.DISTINCT_ROOT_ENTITY);
this.childCriteriaMap.put(childEntityName, childCriteria);
return childCriteria;
}
/**
* Returns the configuration of this search.
*
* @return configuration
*/
public CriteriaSearchConfiguration getConfiguration()
{
return this.configuration;
}
}