All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.querydsl.core.group.GroupByBuilder Maven / Gradle / Ivy

The newest version!
/*
 * 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 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;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Supplier;

/**
 * GroupByBuilder is a fluent builder for GroupBy transformer instances. This class is not to be
 * used directly, but via GroupBy.
 *
 * @author tiwe
 * @param 
 */
public class GroupByBuilder {

  protected final Expression key;

  /**
   * Create a new GroupByBuilder for the given key expression
   *
   * @param key key for aggregating
   */
  public GroupByBuilder(Expression key) {
    this.key = key;
  }

  /**
   * Get the results as a map
   *
   * @param expressions projection
   * @return new result transformer
   */
  public ResultTransformer> as(Expression... expressions) {
    return new GroupByMap<>(key, expressions);
  }

  /**
   * Get the results as a map
   *
   * @param mapFactory the map factory to use, i.e. {@code HashMap::new}.
   * @param expressions projection
   * @return new result transformer
   */
  public > ResultTransformer as(
      Supplier mapFactory, Expression... expressions) {
    return new GroupByGenericMap<>(mapFactory, key, expressions);
  }

  /**
   * Get the results as a closeable iterator
   *
   * @param expressions projection
   * @return new result transformer
   */
  public ResultTransformer> iterate(Expression... expressions) {
    return new GroupByIterate<>(key, expressions);
  }

  /**
   * Get the results as a list
   *
   * @param expressions projection
   * @return new result transformer
   */
  public ResultTransformer> list(Expression... expressions) {
    return new GroupByList<>(key, expressions);
  }

  /**
   * Get the results as a collection.
   *
   * @param resultFactory The collection factory to use, i.e. {@code HashSet::new}.
   * @param expressions projection
   * @return new result transformer
   */
  public > ResultTransformer collection(
      Supplier resultFactory, Expression... expressions) {
    return new GroupByGenericCollection<>(resultFactory, key, expressions);
  }

  /**
   * Get the results as a map
   *
   * @param expression projection
   * @return new result transformer
   */
  @SuppressWarnings("unchecked")
  public  ResultTransformer> as(Expression expression) {
    final Expression lookup = getLookup(expression);
    return new GroupByMap<>(key, expression) {
      @Override
      protected Map transform(Map groups) {
        Map results = new LinkedHashMap<>((int) Math.ceil(groups.size() / 0.75), 0.75f);
        for (Map.Entry entry : groups.entrySet()) {
          results.put(entry.getKey(), entry.getValue().getOne(lookup));
        }
        return results;
      }
    };
  }

  /**
   * Get the results as a map
   *
   * @param mapFactory The map factory to use, i.e. {@code HashMap::new}.
   * @param expression projection
   * @return new result transformer
   */
  public > ResultTransformer as(
      final Supplier mapFactory, Expression expression) {
    final Expression lookup = getLookup(expression);
    return new GroupByGenericMap<>(mapFactory, key, expression) {
      @Override
      protected RES transform(Map groups) {
        var results = mapFactory.get();
        for (Map.Entry 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  ResultTransformer> iterate(Expression expression) {
    final Expression lookup = getLookup(expression);
    return new GroupByIterate<>(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  ResultTransformer> list(Expression expression) {
    final Expression lookup = getLookup(expression);
    return new GroupByList<>(key, expression) {
      @Override
      protected V transform(Group group) {
        return group.getOne(lookup);
      }
    };
  }

  /**
   * Get the results as a set
   *
   * @param expression projection
   * @return new result transformer
   */
  public > ResultTransformer collection(
      Supplier resultFactory, Expression expression) {
    final Expression lookup = getLookup(expression);
    return new GroupByGenericCollection<>(resultFactory, key, expression) {
      @Override
      protected V transform(Group group) {
        return group.getOne(lookup);
      }
    };
  }

  protected  Expression getLookup(Expression expression) {
    if (expression instanceof GroupExpression) {
      @SuppressWarnings("unchecked") // This is the underlying type
      GroupExpression groupExpression = (GroupExpression) expression;
      return groupExpression.getExpression();
    } else {
      return expression;
    }
  }

  /**
   * Get the results as a map
   *
   * @param expression projection
   * @return new result transformer
   */
  public  ResultTransformer> as(FactoryExpression expression) {
    final FactoryExpression transformation = FactoryExpressionUtils.wrap(expression);
    var args = transformation.getArgs();
    return new GroupByMap(key, args.toArray(new Expression[0])) {

      @Override
      protected Map transform(Map groups) {
        Map results = new LinkedHashMap<>((int) Math.ceil(groups.size() / 0.75), 0.75f);
        for (Map.Entry 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 args = new ArrayList<>(groupExpressions.size() - 1);
        for (var 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  ResultTransformer> iterate(FactoryExpression expression) {
    final FactoryExpression transformation = FactoryExpressionUtils.wrap(expression);
    var args = transformation.getArgs();
    return new GroupByIterate<>(key, args.toArray(new Expression[0])) {
      @Override
      protected V transform(Group group) {
        // XXX Isn't group.toArray() suitable here?
        List args = new ArrayList<>(groupExpressions.size() - 1);
        for (var 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  ResultTransformer> list(FactoryExpression expression) {
    final FactoryExpression transformation = FactoryExpressionUtils.wrap(expression);
    var args = transformation.getArgs();
    return new GroupByList<>(key, args.toArray(new Expression[0])) {
      @Override
      protected V transform(Group group) {
        // XXX Isn't group.toArray() suitable here?
        List args = new ArrayList<>(groupExpressions.size() - 1);
        for (var 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 > ResultTransformer collection(
      Supplier resultFactory, FactoryExpression expression) {
    final FactoryExpression transformation = FactoryExpressionUtils.wrap(expression);
    var args = transformation.getArgs();
    return new GroupByGenericCollection<>(resultFactory, key, args.toArray(Expression[]::new)) {
      @Override
      protected V transform(Group group) {
        // XXX Isn't group.toArray() suitable here?
        List args = new ArrayList<>(groupExpressions.size() - 1);
        for (var i = 1; i < groupExpressions.size(); i++) {
          args.add(group.getGroup(groupExpressions.get(i)));
        }
        return transformation.newInstance(args.toArray());
      }
    };
  }
}