/* * Copyright 2015, The Querydsl Team (http://www.querydsl.com/team) * * 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.querydsl.core.group; import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import com.mysema.commons.lang.CloseableIterator; import com.querydsl.core.ResultTransformer; import com.querydsl.core.types.Expression; import com.querydsl.core.types.FactoryExpression; import com.querydsl.core.types.FactoryExpressionUtils; /** * GroupByBuilder is a fluent builder for GroupBy transformer instances. This class is not to be used directly, * but via GroupBy. * * @author tiwe * * @param <K> */ public class GroupByBuilder<K> { private final Expression<K> key; /** * Create a new GroupByBuilder for the given key expression * * @param key key for aggregating */ public GroupByBuilder(Expression<K> key) { this.key = key; } /** * Get the results as a map * * @param expressions projection * @return new result transformer */ public ResultTransformer<Map<K, Group>> as(Expression<?>... expressions) { return new GroupByMap<K, Group>(key, expressions); } /** * Get the results as a closeable iterator * * @param expressions projection * @return new result transformer */ public ResultTransformer<CloseableIterator<Group>> iterate(Expression<?>... expressions) { return new GroupByIterate<K, Group>(key, expressions); } /** * Get the results as a list * * @param expressions projection * @return new result transformer */ public ResultTransformer<List<Group>> list(Expression<?>... expressions) { return new GroupByList<K, Group>(key, expressions); } /** * Get the results as a map * * @param expression projection * @return new result transformer */ @SuppressWarnings("unchecked") public <V> ResultTransformer<Map<K, V>> as(Expression<V> expression) { final Expression<V> lookup = getLookup(expression); return new GroupByMap<K, V>(key, expression) { @Override protected Map<K, V> transform(Map<K, Group> groups) { Map<K, V> results = new LinkedHashMap<K, V>((int) Math.ceil(groups.size() / 0.75), 0.75f); for (Map.Entry<K, Group> entry : groups.entrySet()) { results.put(entry.getKey(), entry.getValue().getOne(lookup)); } return results; } }; } /** * Get the results as a closeable iterator * * @param expression projection * @return new result transformer */ public <V> ResultTransformer<CloseableIterator<V>> iterate(Expression<V> expression) { final Expression<V> lookup = getLookup(expression); return new GroupByIterate<K, V>(key, expression) { @Override protected V transform(Group group) { return group.getOne(lookup); } }; } /** * Get the results as a list * * @param expression projection * @return new result transformer */ public <V> ResultTransformer<List<V>> list(Expression<V> expression) { final Expression<V> lookup = getLookup(expression); return new GroupByList<K, V>(key, expression) { @Override protected V transform(Group group) { return group.getOne(lookup); } }; } private <V> Expression<V> getLookup(Expression<V> expression) { if (expression instanceof GroupExpression) { @SuppressWarnings("unchecked") // This is the underlying type GroupExpression<V, ?> groupExpression = (GroupExpression<V, ?>) expression; return groupExpression.getExpression(); } else { return expression; } } /** * Get the results as a map * * @param expression projection * @return new result transformer */ public <V> ResultTransformer<Map<K, V>> as(FactoryExpression<V> expression) { final FactoryExpression<?> transformation = FactoryExpressionUtils.wrap(expression); List<Expression<?>> args = transformation.getArgs(); return new GroupByMap<K, V>(key, args.toArray(new Expression<?>[args.size()])) { @Override protected Map<K, V> transform(Map<K, Group> groups) { Map<K, V> results = new LinkedHashMap<K, V>((int) Math.ceil(groups.size() / 0.75), 0.75f); for (Map.Entry<K, Group> entry : groups.entrySet()) { results.put(entry.getKey(), transform(entry.getValue())); } return results; } @SuppressWarnings("unchecked") protected V transform(Group group) { // XXX Isn't group.toArray() suitable here? List<Object> args = new ArrayList<Object>(groupExpressions.size() - 1); for (int i = 1; i < groupExpressions.size(); i++) { args.add(group.getGroup(groupExpressions.get(i))); } return (V) transformation.newInstance(args.toArray()); } }; } /** * Get the results as a closeable iterator * * @param expression projection * @return new result transformer */ public <V> ResultTransformer<CloseableIterator<V>> iterate(FactoryExpression<V> expression) { final FactoryExpression<V> transformation = FactoryExpressionUtils.wrap(expression); List<Expression<?>> args = transformation.getArgs(); return new GroupByIterate<K, V>(key, args.toArray(new Expression<?>[args.size()])) { @Override protected V transform(Group group) { // XXX Isn't group.toArray() suitable here? List<Object> args = new ArrayList<Object>(groupExpressions.size() - 1); for (int i = 1; i < groupExpressions.size(); i++) { args.add(group.getGroup(groupExpressions.get(i))); } return transformation.newInstance(args.toArray()); } }; } /** * Get the results as a list * * @param expression projection * @return new result transformer */ public <V> ResultTransformer<List<V>> list(FactoryExpression<V> expression) { final FactoryExpression<V> transformation = FactoryExpressionUtils.wrap(expression); List<Expression<?>> args = transformation.getArgs(); return new GroupByList<K, V>(key, args.toArray(new Expression<?>[args.size()])) { @Override protected V transform(Group group) { // XXX Isn't group.toArray() suitable here? List<Object> args = new ArrayList<Object>(groupExpressions.size() - 1); for (int i = 1; i < groupExpressions.size(); i++) { args.add(group.getGroup(groupExpressions.get(i))); } return transformation.newInstance(args.toArray()); } }; } }