package org.radargun.service; import java.util.Collections; import java.util.List; import org.infinispan.query.dsl.FilterConditionContext; import org.infinispan.query.dsl.FilterConditionEndContext; import org.infinispan.query.dsl.QueryFactory; import org.radargun.traits.Query; import org.radargun.traits.Queryable; /** * Provides implementation of querying suited to Infinispan DSL Queries * * @author Radim Vansa <rvansa@redhat.com> */ public abstract class AbstractInfinispanQueryable implements Queryable { protected static class QueryBuilderImpl implements Query.Builder { protected final QueryFactory factory; protected final org.infinispan.query.dsl.QueryBuilder builder; protected FilterConditionContext context; public QueryBuilderImpl(QueryFactory factory, Class<?> clazz) { this.factory = factory; this.builder = factory.from(clazz); } protected QueryBuilderImpl(QueryFactory factory) { this.factory = factory; this.builder = null; } protected FilterConditionEndContext getEndContext(Query.SelectExpression selectExpression) { FilterConditionEndContext endContext; if (context != null) { endContext = context.and().having(selectExpression.attribute); } else if (builder != null) { endContext = builder.having(selectExpression.attribute); } else { endContext = factory.having(selectExpression.attribute); } return endContext; } @Override public Query.Builder subquery() { return new QueryBuilderImpl(factory); } @Override public Query.Builder eq(Query.SelectExpression selectExpression, Object value) { context = getEndContext(selectExpression).eq(value); return this; } @Override public Query.Builder lt(Query.SelectExpression selectExpression, Object value) { context = getEndContext(selectExpression).lt(value); return this; } @Override public Query.Builder le(Query.SelectExpression selectExpression, Object value) { context = getEndContext(selectExpression).lte(value); return this; } @Override public Query.Builder gt(Query.SelectExpression selectExpression, Object value) { context = getEndContext(selectExpression).gt(value); return this; } @Override public Query.Builder ge(Query.SelectExpression selectExpression, Object value) { context = getEndContext(selectExpression).gte(value); return this; } @Override public Query.Builder between(Query.SelectExpression selectExpression, Object lowerBound, boolean lowerInclusive, Object upperBound, boolean upperInclusive) { context = getEndContext(selectExpression).between(lowerBound, upperBound).includeLower(lowerInclusive).includeUpper(upperInclusive); return this; } @Override public Query.Builder isNull(Query.SelectExpression selectExpression) { context = getEndContext(selectExpression).isNull(); return this; } @Override public Query.Builder like(Query.SelectExpression selectExpression, String pattern) { context = getEndContext(selectExpression).like(pattern); return this; } @Override public Query.Builder contains(Query.SelectExpression selectExpression, Object value) { context = getEndContext(selectExpression).contains(value); return this; } @Override public Query.Builder not(Query.Builder subquery) { FilterConditionContext subqueryContext = ((QueryBuilderImpl) subquery).context; if (subqueryContext == null) { return this; } if (context != null) { context = context.and().not(subqueryContext); } else if (builder != null) { context = builder.not(subqueryContext); } else { context = factory.not(subqueryContext); } return this; } @Override public Query.Builder any(Query.Builder... subqueries) { if (subqueries.length == 0) { return this; } FilterConditionContext innerContext = null; for (Query.Builder subquery : subqueries) { if (innerContext == null) { innerContext = ((QueryBuilderImpl) subquery).context; } else { innerContext = innerContext.or(((QueryBuilderImpl) subquery).context); } } if (context != null) { context = context.and(innerContext); } else if (builder != null) { context = builder.not().not(innerContext); } else { context = factory.not().not(innerContext); } return this; } @Override public Query.Builder orderBy(Query.SelectExpression selectExpression) { if (builder == null) throw new IllegalArgumentException("You have to call orderBy() on root query builder!"); if (selectExpression.function != Query.AggregationFunction.NONE) throw new IllegalArgumentException("This version of infinispan doesn't support aggregations!"); builder.orderBy(selectExpression.attribute, selectExpression.asc ? org.infinispan.query.dsl.SortOrder.ASC : org.infinispan.query.dsl.SortOrder.DESC); return this; } @Override public Query.Builder projection(Query.SelectExpression... selectExpressions) { if (builder == null) throw new IllegalArgumentException("You have to call projection() on root query builder!"); String[] stringAttributes = new String[selectExpressions.length]; for (int i = 0; i < selectExpressions.length; i++) { if (selectExpressions[i].function != Query.AggregationFunction.NONE) { throw new IllegalArgumentException("This version of infinispan doesn't support aggregations!"); } stringAttributes[i] = selectExpressions[i].attribute; } builder.setProjection(stringAttributes); return this; } @Override public Query.Builder groupBy(String... attributes) { throw new RuntimeException("Grouping is not implemented in this version of infinispan."); } @Override public Query.Builder offset(long offset) { if (builder == null) throw new IllegalArgumentException("You have to call offset() on root query builder!"); builder.startOffset(offset); return this; } @Override public Query.Builder limit(long limit) { if (builder == null) throw new IllegalArgumentException("You have to call limit() on root query builder!"); builder.maxResults(limit > Integer.MAX_VALUE ? Integer.MAX_VALUE : (int) limit); return this; } @Override public Query build() { if (builder == null) throw new IllegalArgumentException("You have to call build() on root query builder!"); return new QueryImpl(builder.build()); } } protected static class QueryImpl implements Query { private final org.infinispan.query.dsl.Query query; public QueryImpl(org.infinispan.query.dsl.Query query) { this.query = query; } public org.infinispan.query.dsl.Query getDelegatingQuery() { return query; } @Override public Result execute(Context resource) { return new QueryResultImpl(query.list()); } } protected static class QueryResultImpl implements Query.Result { private final List<Object> list; public QueryResultImpl(List<Object> list) { this.list = list; } @Override public int size() { return list.size(); } @Override public List values() { return Collections.unmodifiableList(list); } } }