com.impetus.kundera.query.KunderaQuery Maven / Gradle / Ivy
/*******************************************************************************
* * Copyright 2012 Impetus Infotech.
* *
* * 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 com.impetus.kundera.query;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Queue;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.persistence.Parameter;
import javax.persistence.PersistenceException;
import javax.persistence.metamodel.Attribute;
import javax.persistence.metamodel.EntityType;
import javax.persistence.metamodel.Metamodel;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.builder.HashCodeBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.impetus.kundera.KunderaException;
import com.impetus.kundera.metadata.KunderaMetadataManager;
import com.impetus.kundera.metadata.MetadataUtils;
import com.impetus.kundera.metadata.model.EntityMetadata;
import com.impetus.kundera.metadata.model.KunderaMetadata;
import com.impetus.kundera.metadata.model.MetamodelImpl;
import com.impetus.kundera.metadata.model.attributes.AbstractAttribute;
import com.impetus.kundera.metadata.model.type.AbstractManagedType;
/**
* The Class KunderaQuery.
*/
public class KunderaQuery
{
/** The Constant SINGLE_STRING_KEYWORDS. */
public static final String[] SINGLE_STRING_KEYWORDS = { "SELECT", "UPDATE", "SET", "DELETE", "UNIQUE", "FROM",
"WHERE", "GROUP BY", "HAVING", "ORDER BY" };
/** The Constant INTER_CLAUSE_OPERATORS. */
public static final String[] INTER_CLAUSE_OPERATORS = { "AND", "OR", "BETWEEN" };
/** The Constant INTRA_CLAUSE_OPERATORS. */
public static final String[] INTRA_CLAUSE_OPERATORS = { "=", "LIKE", "IN", ">", ">=", "<", "<=" };
/** The INTER pattern. */
private static final Pattern INTER_CLAUSE_PATTERN = Pattern.compile(
"\\s\\band\\b\\s|\\s\\bor\\b\\s|\\s\\bbetween\\b\\s", Pattern.CASE_INSENSITIVE);
/** The INTRA pattern. */
private static final Pattern INTRA_CLAUSE_PATTERN = Pattern.compile(
"=|\\s\\blike\\b|\\bin\\b|>=|>|<=|<|\\s\\bset", Pattern.CASE_INSENSITIVE);
/** The logger. */
private static Logger logger = LoggerFactory.getLogger(KunderaQuery.class);
/** The result. */
private String[] result;
/** The from. */
private String from;
/** The filter. */
private String filter;
/** The ordering. */
private String ordering;
/** The entity name. */
private String entityName;
/** The entity alias. */
private String entityAlias;
/** The entity class. */
private Class> entityClass;
/** The sort orders. */
private List sortOrders;
/** Persistence Unit(s). */
private String persistenceUnit;
// contains a Queue of alternate FilterClause object and Logical Strings
// (AND, OR etc.)
/** The filters queue. */
private Queue filtersQueue = new LinkedList();
private boolean isDeleteUpdate;
private Queue updateClauseQueue = new LinkedList();
private TypedParameter typedParameter;
boolean isNativeQuery;
/**
* Instantiates a new kundera query.
*
* @param persistenceUnits
* the persistence units
*/
public KunderaQuery()
{
}
/**
* Sets the grouping.
*
* @param groupingClause
* the new grouping
*/
public void setGrouping(String groupingClause)
{
}
/**
* Sets the result.
*
* @param result
* the new result
*/
public final void setResult(String... result)
{
this.result = result;
}
/**
* Sets the from.
*
* @param from
* the new from
*/
public final void setFrom(String from)
{
this.from = from;
}
/**
* Sets the filter.
*
* @param filter
* the new filter
*/
public final void setFilter(String filter)
{
this.filter = filter;
}
/**
* Sets the ordering.
*
* @param ordering
* the new ordering
*/
public final void setOrdering(String ordering)
{
this.ordering = ordering;
parseOrdering(this.ordering);
}
/**
* Gets the filter.
*
* @return the filter
*/
public final String getFilter()
{
return filter;
}
/**
* Gets the from.
*
* @return the from
*/
public final String getFrom()
{
return from;
}
/**
* Gets the ordering.
*
* @return the ordering
*/
public final List getOrdering()
{
return sortOrders;
}
/**
* Gets the result.
*
* @return the result
*/
public final String[] getResult()
{
return result;
}
/**
* Method to check if required result is to get complete entity or a select
* scalar value.
*
* @return true, if it result is for complete alias.
*
*/
public final boolean isAliasOnly()
{
// TODO
return result != null && (result[0].indexOf(".") == -1);
}
/**
* Returns set of parameters.
*
* @return jpaParameters
*/
public Set> getParameters()
{
return typedParameter.jpaParameters;
}
/**
* Parameter is bound if it holds any value, else will return false
*
* @param param
* @return
*/
public boolean isBound(Parameter param)
{
return getClauseValue(param) != null;
}
/**
* Returns clause value for supplied parameter.
*
* @param paramString
* @return
*/
public Object getClauseValue(String paramString)
{
if (typedParameter != null && typedParameter.getParameters() != null)
{
FilterClause clause = typedParameter.getParameters().get(paramString);
if (clause != null)
{
return clause.getValue();
}
else
{
throw new IllegalArgumentException("parameter is not a parameter of the query");
}
}
logger.error("parameter{} is not a parameter of the query", paramString);
throw new IllegalArgumentException("parameter is not a parameter of the query");
}
/**
* Returns specific clause value.
*
* @param param
* parameter
*
* @return clause value.
*/
public Object getClauseValue(Parameter param)
{
Parameter match = null;
if (typedParameter != null && typedParameter.jpaParameters != null)
{
for (Parameter p : typedParameter.jpaParameters)
{
if (p.equals(param))
{
match = p;
if (typedParameter.getType().equals(Type.NAMED))
{
FilterClause clause = typedParameter.getParameters().get(":" + p.getName());
if (clause != null)
{
return clause.getValue();
}
}
else
{
FilterClause clause = typedParameter.getParameters().get("?" + p.getPosition());
if (clause != null)
{
return clause.getValue();
}
else
{
UpdateClause updateClause = typedParameter.getUpdateParameters().get("?" + p.getPosition());
if (updateClause != null)
{
return updateClause.getValue();
}
}
}
break;
}
}
if (match == null)
{
throw new IllegalArgumentException("parameter is not a parameter of the query");
}
}
logger.error("parameter{} is not a parameter of the query", param);
throw new IllegalArgumentException("parameter is not a parameter of the query");
}
// must be executed after parse(). it verifies and populated the query
// predicates.
/**
* Post parsing init.
*/
protected void postParsingInit()
{
initEntityClass();
initFilter();
initUpdateClause();
}
/**
*
*/
private void initUpdateClause()
{
for (UpdateClause updateClause : updateClauseQueue)
{
onTypedParameter(updateClause.getValue(), updateClause, updateClause.getProperty().trim());
}
}
/**
* Inits the entity class.
*/
private void initEntityClass()
{
if (from == null)
{
throw new JPQLParseException("Bad query format FROM clause is mandatory for SELECT queries");
}
String fromArray[] = from.split(" ");
if (!this.isDeleteUpdate)
{
if (fromArray.length != 2)
{
throw new JPQLParseException("Bad query format: " + from
+ ". Identification variable is mandatory in FROM clause for SELECT queries");
}
// TODO
StringTokenizer tokenizer = new StringTokenizer(getResult()[0], ",");
while (tokenizer.hasMoreTokens())
{
String token = tokenizer.nextToken();
if (!StringUtils.containsAny(fromArray[1] + ".", token))
{
throw new QueryHandlerException("bad query format with invalid alias:" + token);
}
}
}
this.entityName = fromArray[0];
if (fromArray.length == 2)
this.entityAlias = fromArray[1];
persistenceUnit = KunderaMetadata.INSTANCE.getApplicationMetadata().getMappedPersistenceUnit(entityName);
// Get specific metamodel.
MetamodelImpl model = getMetamodel(persistenceUnit);
if (model != null)
{
entityClass = model.getEntityClass(entityName);
}
if (null == entityClass)
{
logger.error("No entity {} found, please verify it is properly annotated with @Entity and not a mapped Super class",entityName);
throw new QueryHandlerException("No entity found by the name: " + entityName);
}
EntityMetadata metadata = model.getEntityMetadata(entityClass);
if (metadata != null && !metadata.isIndexable())
{
throw new QueryHandlerException(entityClass + " is not indexed. Not possible to run a query on it."
+ " Check whether it was properly annotated for indexing.");
}
}
/**
* Inits the filter.
*/
private void initFilter()
{
EntityMetadata metadata = KunderaMetadataManager.getEntityMetadata(entityClass);
// String indexName = metadata.getIndexName();
// String filter = getFilter();
Metamodel metaModel = KunderaMetadata.INSTANCE.getApplicationMetadata().getMetamodel(
getPersistenceUnit());
EntityType entityType = metaModel.entity(entityClass);
if (null == filter)
{
List clauses = new ArrayList();
addDiscriminatorClause(clauses, entityType);
return;
}
List clauses = tokenize(filter, INTER_CLAUSE_PATTERN);
// parse and structure for "between" clause , if present, else it will
// return original clause
clauses = parseFilterForBetweenClause(clauses/* , indexName */);
// clauses = parseFilterForInClause(clauses, indexName);
// clauses must be alternate Inter and Intra combination, starting with
// Intra.
boolean newClause = true;
/* if(((AbstractManagedType)entityType).isInherited())
{
String discrColumn = ((AbstractManagedType)entityType).getDiscriminatorColumn();
String discrValue = ((AbstractManagedType)entityType).getDiscriminatorValue();
if(discrColumn != null && discrValue != null)
{
if(!clauses.isEmpty())
{
clauses.add(" AND ");
}
clauses.add(entityAlias+"."+discrColumn+ "= " + discrValue );
}
}
*/// entityAlias
// entityType
for (String clause : clauses)
{
if (newClause)
{
List tokens = tokenize(clause, INTRA_CLAUSE_PATTERN);
if (tokens.size() != 3)
{
throw new PersistenceException("bad jpa query: " + clause);
}
// strip alias from property name
String property = tokens.get(0);
if (property.indexOf(".") > 0)
{
property = property.substring((entityAlias + ".").length());
}
// String columnName = getColumnNameFromFieldName(metadata,
// property);
String columnName = null;
try
{
// String columnName = metadata.getColumnName(property);
columnName = ((AbstractAttribute) entityType.getAttribute(property))
.getJPAColumnName();
}
catch (IllegalArgumentException iaex)
{
logger.info("No column found by this name : " + property + " checking for embeddedfield");
}
// where condition may be for search within embedded object
if (columnName == null && property.indexOf(".") > 0)
{
String enclosingEmbeddedField = MetadataUtils.getEnclosingEmbeddedFieldName(metadata, property,
true);
if (enclosingEmbeddedField != null)
{
columnName = property;
}
}
String condition = tokens.get(1);
if (!Arrays.asList(INTRA_CLAUSE_OPERATORS).contains(condition.toUpperCase().trim()))
{
throw new JPQLParseException("Bad JPA query: " + clause);
}
FilterClause filterClause = new FilterClause(
/*
* MetadataUtils.useSecondryIndex(persistenceUnit) ? columnName
* : indexName + "." +
*/columnName, condition, tokens.get(2));
filtersQueue.add(filterClause);
onTypedParameter(tokens, filterClause, property);
newClause = false;
}
else
{
if (Arrays.asList(INTER_CLAUSE_OPERATORS).contains(clause.toUpperCase().trim()))
{
filtersQueue.add(clause.toUpperCase());
newClause = true;
}
else
{
throw new JPQLParseException("bad jpa query: " + clause);
}
}
}
addDiscriminatorClause(clauses, entityType);
// appendDiscriminator();
}
private void addDiscriminatorClause(List clauses, EntityType entityType)
{
if(((AbstractManagedType)entityType).isInherited())
{
String discrColumn = ((AbstractManagedType)entityType).getDiscriminatorColumn();
String discrValue = ((AbstractManagedType)entityType).getDiscriminatorValue();
if(discrColumn != null && discrValue != null)
{
if(!clauses.isEmpty())
{
filtersQueue.add("AND");
}
FilterClause filterClause = new FilterClause(discrColumn,"=",discrValue);
filtersQueue.add(filterClause);
}
}
}
/**
* Depending upon filter value, if it starts with ":" then it is NAMED
* parameter, else if starts with "?", it will be INDEXED parameter.
*
* @param tokens
* tokens
* @param filterClause
* filter clauses.
*/
private void onTypedParameter(Object value, UpdateClause updateClause, String fieldName)
{
String token = value.toString();
if (token != null && token.startsWith(":"))
{
addTypedParameter(Type.NAMED, token, updateClause);
filterJPAParameterInfo(Type.NAMED, token.substring(1), fieldName);
}
else if (token != null && token.startsWith("?"))
{
addTypedParameter(Type.INDEXED, token, updateClause);
filterJPAParameterInfo(Type.INDEXED, token.substring(1), fieldName);
}
}
/**
* Depending upon filter value, if it starts with ":" then it is NAMED
* parameter, else if starts with "?", it will be INDEXED parameter.
*
* @param tokens
* tokens
* @param filterClause
* filter clauses.
*/
private void onTypedParameter(List tokens, FilterClause filterClause, String fieldName)
{
if (tokens.get(2) != null && tokens.get(2).startsWith(":"))
{
addTypedParameter(Type.NAMED, tokens.get(2), filterClause);
filterJPAParameterInfo(Type.NAMED, tokens.get(2).substring(1), fieldName);
}
else if (tokens.get(2) != null && tokens.get(2).startsWith("?"))
{
addTypedParameter(Type.INDEXED, tokens.get(2), filterClause);
filterJPAParameterInfo(Type.INDEXED, tokens.get(2).substring(1), fieldName);
}
}
/**
* Adds typed parameter to {@link TypedParameter}
*
* @param type
* type of parameter(e.g. NAMED/INDEXED)
* @param parameter
* parameter name.
* @param clause
* filter clause.
*/
private void addTypedParameter(Type type, String parameter, FilterClause clause)
{
if (typedParameter == null)
{
typedParameter = new TypedParameter(type);
}
if (typedParameter.getType().equals(type))
{
typedParameter.addParameters(parameter, clause);
}
else
{
logger.warn("Invalid type provided, it can either be name or indexes!");
}
}
/**
* Adds typed parameter to {@link TypedParameter}
*
* @param type
* type of parameter(e.g. NAMED/INDEXED)
* @param parameter
* parameter name.
* @param clause
* filter clause.
*/
private void addTypedParameter(Type type, String parameter, UpdateClause clause)
{
if (type != null)
{
if (typedParameter == null)
{
typedParameter = new TypedParameter(type);
}
if (typedParameter.getType().equals(type))
{
typedParameter.addParameters(parameter, clause);
}
else
{
logger.warn("Invalid type provided, it can either be name or indexes!");
}
}
}
private void filterJPAParameterInfo(Type type, String name, String fieldName)
{
String attributeName = getAttributeName(fieldName);
Attribute entityAttribute = ((MetamodelImpl) KunderaMetadata.INSTANCE.getApplicationMetadata().getMetamodel(
persistenceUnit)).getEntityAttribute(entityClass, attributeName);
Class fieldType = entityAttribute.getJavaType();
if (type.equals(Type.INDEXED))
{
typedParameter.addJPAParameter(new JPAParameter(null, Integer.valueOf(name), fieldType));
}
else
{
typedParameter.addJPAParameter(new JPAParameter(name, null, fieldType));
}
}
private String getAttributeName(String fieldName)
{
String attributeName = fieldName;
if (fieldName.indexOf(".") != -1)
{
attributeName = fieldName.substring(0, fieldName.indexOf("."));
}
return attributeName;
}
/**
* Sets the parameter.
*
* @param name
* the name
* @param value
* the value
*/
public final void setParameter(String name, Object value)
{
setParameterValue(":" + name, value);
}
public final void setParameter(int position, Object value)
{
setParameterValue("?" + position, value);
}
/**
* Sets parameter value into filterClause, depending upon {@link Type}
*
* @param name
* parameter name.
* @param value
* parameter value.
*/
private void setParameterValue(String name, Object value)
{
if (typedParameter != null)
{
FilterClause clause = typedParameter.getParameters() != null ? typedParameter.getParameters().get(name)
: null;
if (clause != null)
{
clause.setValue(value);
}
else
{
if (typedParameter.getUpdateParameters() != null)
{
UpdateClause updateClause = typedParameter.getUpdateParameters().get(name);
updateClause.setValue(value);
}
else
{
logger.error("Error while setting parameter by clause:");
throw new QueryHandlerException("named parameter:" + name + " not found!");
}
}
}
else
{
throw new QueryHandlerException("No named parameter present for query");
}
}
/**
* Gets the entity class.
*
* @return the entityClass
*/
public final Class getEntityClass()
{
return entityClass;
}
public boolean isNative()
{
return isNativeQuery;
}
/**
* Gets the entity metadata.
*
* @return the entity metadata
*/
public final EntityMetadata getEntityMetadata()
{
EntityMetadata metadata = KunderaMetadataManager.getEntityMetadata(entityClass);
if (metadata == null)
{
throw new KunderaException("Unable to load entity metadata for :" + entityClass);
}
return metadata;
}
/**
* Gets the filter clause queue.
*
* @return the filters
*/
public final Queue getFilterClauseQueue()
{
return filtersQueue;
}
// class to keep hold of a where clause predicate
/**
* The Class FilterClause.
*/
public final class FilterClause
{
/** The property. */
private String property;
/** The condition. */
private String condition;
/** The value. */
Object value;
/**
* The Constructor.
*
* @param property
* the property
* @param condition
* the condition
* @param value
* the value
*/
public FilterClause(String property, String condition, Object value)
{
super();
this.property = property;
this.condition = condition.trim();
this.value = KunderaQuery.getValue(value);
}
/**
* Gets the property.
*
* @return the property
*/
public final String getProperty()
{
return property;
}
/**
* Gets the condition.
*
* @return the condition
*/
public final String getCondition()
{
return condition;
}
/**
* Gets the value.
*
* @return the value
*/
public final Object getValue()
{
return value;
}
/**
* Sets the value.
*
* @param value
* the value to set
*/
protected void setValue(Object value)
{
this.value = KunderaQuery.getValue(value);
}
/* @see java.lang.Object#toString() */
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("FilterClause [property=");
builder.append(property);
builder.append(", condition=");
builder.append(condition);
builder.append(", value=");
builder.append(value);
builder.append("]");
return builder.toString();
}
}
public final class UpdateClause
{
private String property;
private Object value;
public UpdateClause(final String property, final Object value)
{
this.property = property;
this.value = KunderaQuery.getValue(value);
}
/**
* @return the property
*/
public String getProperty()
{
return property;
}
/**
* @return the value
*/
public Object getValue()
{
return value;
}
/**
* @param value
* the value to set
*/
public void setValue(Object value)
{
this.value = KunderaQuery.getValue(value);
}
}
/* @see java.lang.Object#clone() */
/*
* (non-Javadoc)
*
* @see java.lang.Object#clone()
*/
@Override
public final Object clone() throws CloneNotSupportedException
{
return super.clone();
}
/* @see java.lang.Object#toString() */
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public final String toString()
{
StringBuilder builder = new StringBuilder();
builder.append("KunderaQuery [entityName=");
builder.append(entityName);
builder.append(", entityAlias=");
builder.append(entityAlias);
builder.append(", filtersQueue=");
builder.append(filtersQueue);
builder.append("]");
return builder.toString();
}
// helper method
/**
* Tokenize.
*
* @param where
* the where
* @param pattern
* the pattern
* @return the list
*/
private static List tokenize(String where, Pattern pattern)
{
List split = new ArrayList();
Matcher matcher = pattern.matcher(where);
int lastIndex = 0;
String s;
// int count = 0;
while (matcher.find())
{
s = where.substring(lastIndex, matcher.start()).trim();
split.add(s);
s = matcher.group();
split.add(s.toUpperCase());
lastIndex = matcher.end();
// count++;
}
s = where.substring(lastIndex).trim();
split.add(s);
return split;
}
/**
* Gets the metamodel.
*
* @return the metamodel
*/
private MetamodelImpl getMetamodel(String pu)
{
return KunderaMetadataManager.getMetamodel(pu);
}
/**
* Gets the persistence units.
*
* @return the persistenceUnits
*/
public String getPersistenceUnit()
{
return persistenceUnit;
}
/**
* Parses the ordering @See Order By Clause.
*
* @param ordering
* the ordering
*/
private void parseOrdering(String ordering)
{
final String comma = ",";
final String space = " ";
StringTokenizer tokenizer = new StringTokenizer(ordering, comma);
sortOrders = new ArrayList();
while (tokenizer.hasMoreTokens())
{
String order = (String) tokenizer.nextElement();
StringTokenizer token = new StringTokenizer(order, space);
SortOrder orderType = SortOrder.ASC;
String colName = (String) token.nextElement();
while (token.hasMoreElements())
{
String nextOrder = (String) token.nextElement();
// more spaces given.
if (StringUtils.isNotBlank(nextOrder))
{
try
{
orderType = SortOrder.valueOf(nextOrder);
}
catch (IllegalArgumentException e)
{
logger.error("Error while parsing order by clause:");
throw new JPQLParseException("Invalid sort order provided:" + nextOrder);
}
}
}
sortOrders.add(new SortOrdering(colName, orderType));
}
}
/**
* Containing SortOrder.
*/
public class SortOrdering
{
/** The column name. */
String columnName;
/** The order. */
SortOrder order;
/**
* Instantiates a new sort ordering.
*
* @param columnName
* the column name
* @param order
* the order
*/
public SortOrdering(String columnName, SortOrder order)
{
this.columnName = columnName;
this.order = order;
}
/**
* Gets the column name.
*
* @return the column name
*/
public String getColumnName()
{
return columnName;
}
/**
* Gets the order.
*
* @return the order
*/
public SortOrder getOrder()
{
return order;
}
}
/**
* The Enum SortOrder.
*/
public enum SortOrder
{
/** The ASC. */
ASC,
/** The DESC. */
DESC;
}
/**
* @return the updateClauseQueue
*/
public Queue getUpdateClauseQueue()
{
return updateClauseQueue;
}
public boolean isUpdateClause()
{
return !updateClauseQueue.isEmpty();
}
public void addUpdateClause(final String property, final String value)
{
UpdateClause updateClause = new UpdateClause(property.trim(), value.trim());
updateClauseQueue.add(updateClause);
addTypedParameter(value.trim().startsWith("?") ? Type.INDEXED : value.trim().startsWith(":") ? Type.NAMED
: null, property, updateClause);
}
/**
* @param b
*/
public void setIsDeleteUpdate(boolean b)
{
this.isDeleteUpdate = b;
}
public boolean isDeleteUpdate()
{
return isDeleteUpdate;
}
/**
* Return parsed token string.
*
* @param tokens
* inter claues token string.
* @param indexName
* table name
* @return tokens converted to "<=" and ">=" clause
*/
private List parseFilterForBetweenClause(List tokens)
{
// There should be whitespace on bothside of keyword between.
final String between = " BETWEEN ";
if (tokens.contains(between))
{
// change token set to parse and compile.
int idxOfBetween = tokens.indexOf(between);
String property = tokens.get(idxOfBetween - 1);
Matcher match = INTRA_CLAUSE_PATTERN.matcher(property);
// in case any intra clause given along with column name.
if (match.find())
{
logger.error("bad jpa query:");
throw new JPQLParseException("invalid column name" + property);
}
String minValue = tokens.get(idxOfBetween + 1);
String maxValue = tokens.get(idxOfBetween + 3);
tokens.set(idxOfBetween + 1, property + ">=" + minValue);
tokens.set(idxOfBetween + 3, property + "<=" + maxValue);
tokens.remove(idxOfBetween - 1);
tokens.remove(idxOfBetween - 1);
}
return tokens;
}
private class TypedParameter
{
private Type type;
private Set> jpaParameters = new HashSet>();
private Map parameters;
private Map updateParameters;
/**
*
*/
public TypedParameter(Type type)
{
this.type = type;
}
/**
* @return the type
*/
private Type getType()
{
return type;
}
/**
* @return the parameters
*/
Map getParameters()
{
return parameters;
}
/**
* @return the parameters
*/
Map getUpdateParameters()
{
return updateParameters;
}
void addParameters(String key, FilterClause clause)
{
if (parameters == null)
{
parameters = new HashMap();
}
parameters.put(key, clause);
}
void addParameters(String key, UpdateClause clause)
{
if (updateParameters == null)
{
updateParameters = new HashMap();
}
updateParameters.put(key, clause);
}
void addJPAParameter(Parameter param)
{
jpaParameters.add(param);
}
}
private enum Type
{
INDEXED, NAMED
}
/*
* JPA Parameter type
*/
private class JPAParameter implements Parameter
{
private String name;
private Integer position;
private Class type;
/**
*
*/
JPAParameter(String name, Integer position, Class type)
{
this.name = name;
this.position = position;
this.type = type;
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Parameter#getName()
*/
@Override
public String getName()
{
return name;
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Parameter#getPosition()
*/
@Override
public Integer getPosition()
{
return position;
}
/*
* (non-Javadoc)
*
* @see javax.persistence.Parameter#getParameterType()
*/
@Override
public Class getParameterType()
{
return type;
}
@Override
public int hashCode()
{
return HashCodeBuilder.reflectionHashCode(this);
}
@Override
public boolean equals(Object obj)
{
if (obj == null)
{
return false;
}
if (!obj.getClass().equals(this.getClass()))
{
return false;
}
Parameter> typed = (Parameter>) obj;
if (typed.getParameterType().equals(this.getParameterType()))
{
if (this.getName() == null && typed.getName() == null)
{
return this.getPosition() != null && this.getPosition().equals(typed.getPosition());
}
else
{
return this.getName() != null && this.getName().equals(typed.getName());
}
}
return false;
}
@Override
public String toString()
{
StringBuilder strBuilder = new StringBuilder();
strBuilder.append("[ name = " + this.getName() + "]");
strBuilder.append("[ position = " + this.getPosition() + "]");
strBuilder.append("[ type = " + this.getParameterType() + "]");
return strBuilder.toString();
}
}
/**
* Method to skip string literal as per JPA specification. if literal starts
* is enclose within "''" then skip "'" and include "'" in case of "''"
* replace it with "'".
*
* @param value
* value.
*
* @return replaced string in case of string, else will return original
* value.
*/
private static Object getValue(Object value)
{
if (value != null && value.getClass().isAssignableFrom(String.class))
{
return ((String) value).replaceAll("^'", "").replaceAll("'$", "").replaceAll("''", "'");
}
return value;
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy