/**
*
*/
package org.springframework.data.aerospike.repository.query;
import java.lang.reflect.Constructor;
import org.springframework.beans.BeanUtils;
import org.springframework.data.aerospike.core.AerospikeOperations;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.Pageable;
import org.springframework.data.keyvalue.core.IterableConverter;
import org.springframework.data.repository.query.EvaluationContextProvider;
import org.springframework.data.repository.query.ParameterAccessor;
import org.springframework.data.repository.query.ParametersParameterAccessor;
import org.springframework.data.repository.query.QueryMethod;
import org.springframework.data.repository.query.RepositoryQuery;
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
import org.springframework.data.repository.query.parser.PartTree;
import org.springframework.expression.EvaluationContext;
import org.springframework.expression.spel.standard.SpelExpression;
import org.springframework.util.ClassUtils;
/**
*
*
* @author Peter Milne
* @author Jean Mercier
*
*/
public class AerospikePartTreeQuery implements RepositoryQuery {
private final EvaluationContextProvider evaluationContextProvider;
private final QueryMethod queryMethod;
private final AerospikeOperations aerospikeOperations;
private final Class<? extends AbstractQueryCreator<?, ?>> queryCreator;
private Query<?> query;
public AerospikePartTreeQuery(QueryMethod queryMethod, EvaluationContextProvider evalContextProvider,
AerospikeOperations aerospikeOperations, Class<? extends AbstractQueryCreator<?, ?>> queryCreator) {
this.queryMethod = queryMethod;
this.aerospikeOperations = aerospikeOperations;
this.evaluationContextProvider = evalContextProvider;
this.queryCreator = queryCreator;
}
/* (non-Javadoc)
* @see org.springframework.data.repository.query.RepositoryQuery#getQueryMethod()
*/
@Override
public QueryMethod getQueryMethod() {
return queryMethod;
}
/* (non-Javadoc)
* @see org.springframework.data.repository.query.RepositoryQuery#execute(java.lang.Object[])
*/
@SuppressWarnings({ "unchecked", "rawtypes" })
@Override
public Object execute(Object[] parameters) {
Query<?> query = prepareQuery(parameters);
if (queryMethod.isPageQuery() || queryMethod.isSliceQuery()) {
Pageable page = (Pageable) parameters[queryMethod.getParameters().getPageableIndex()];
query.setOffset(page.getOffset());
query.setRows(page.getPageSize());
Iterable<?> result = this.aerospikeOperations.find(query, queryMethod.getEntityInformation().getJavaType());
long count = queryMethod.isSliceQuery() ? 0 : aerospikeOperations.count(query, queryMethod.getEntityInformation()
.getJavaType());
return new PageImpl(IterableConverter.toList(result), page, count);
} else if (queryMethod.isCollectionQuery()) {
return this.aerospikeOperations.find(query, queryMethod.getEntityInformation().getJavaType());
} else if (queryMethod.isQueryForEntity()) {
Iterable<?> result = this.aerospikeOperations.find(query, queryMethod.getEntityInformation().getJavaType());
return result.iterator().hasNext() ? result.iterator().next() : null;
}
throw new UnsupportedOperationException("Query method not supported.");
}
/**
* @param parameters
* @return
*/
@SuppressWarnings("rawtypes")
private Query<?> prepareQuery(Object[] parameters) {
ParametersParameterAccessor accessor = new ParametersParameterAccessor(getQueryMethod().getParameters(), parameters);
this.query = createQuery(accessor);
Criteria criteria = (Criteria) query.getCritieria();
Query<?> q = new Query(criteria);
if (accessor.getPageable() != null) {
q.setOffset(accessor.getPageable().getOffset());
q.setRows(accessor.getPageable().getPageSize());
} else {
q.setOffset(-1);
q.setRows(-1);
}
if (accessor.getSort() != null) {
q.setSort(accessor.getSort());
} else {
q.setSort(this.query.getSort());
}
if (q.getCritieria() instanceof SpelExpression) {
EvaluationContext context = this.evaluationContextProvider.getEvaluationContext(getQueryMethod().getParameters(),
parameters);
((SpelExpression) q.getCritieria()).setEvaluationContext(context);
}
return q;
}
public Query<?> createQuery(ParametersParameterAccessor accessor) {
PartTree tree = new PartTree(getQueryMethod().getName(), getQueryMethod().getEntityInformation().getJavaType());
Constructor<? extends AbstractQueryCreator<?, ?>> constructor = (Constructor<? extends AbstractQueryCreator<?, ?>>) ClassUtils
.getConstructorIfAvailable(queryCreator, PartTree.class, ParameterAccessor.class);
return (Query<?>) BeanUtils.instantiateClass(constructor, tree, accessor).createQuery();
}
}