Package org.jinq.jpa.transform

Source Code of org.jinq.jpa.transform.AggregateTransform

package org.jinq.jpa.transform;

import org.jinq.jpa.jpqlquery.AggregateFunctionExpression;
import org.jinq.jpa.jpqlquery.ColumnExpressions;
import org.jinq.jpa.jpqlquery.ConstantExpression;
import org.jinq.jpa.jpqlquery.Expression;
import org.jinq.jpa.jpqlquery.JPQLQuery;
import org.jinq.jpa.jpqlquery.SelectFromWhere;
import org.jinq.jpa.jpqlquery.SelectOnly;
import org.jinq.jpa.jpqlquery.SimpleRowReader;

import ch.epfl.labos.iu.orm.queryll2.symbolic.TypedValueVisitorException;

public class AggregateTransform extends JPQLOneLambdaQueryTransform
{
   public enum AggregateType
   {
      SUM, AVG, MAX, MIN,
      COUNT, // COUNT is only usable for multiaggregate and grouping subqueries
   }
  
   public AggregateTransform(JPQLQueryTransformConfiguration config, AggregateType type)
   {
      super(config);
      this.type = type;
   }
  
   private AggregateType type;
  
   @Override
   public <U, V> JPQLQuery<U> apply(JPQLQuery<V> query, LambdaAnalysis lambda, SymbExArgumentHandler parentArgumentScope) throws QueryTransformException
   {
      try  {
         if (query.isSelectFromWhere() || query instanceof SelectOnly)
         {
            SelectOnly<V> select = (SelectOnly<V>)query;
            Expression aggregatedExpr = null;
            SymbExArgumentHandler argumentHandler;
            if (type != AggregateType.COUNT)
            {
               if (select.isDistinct)
               {
                  // Can only perform an aggregation like SUM() or AVG() on distinct streams if we don't
                  // further modify those streams (i.e. we just pass the data through directly).
                  argumentHandler = SelectFromWhereLambdaArgumentHandler.forPassthroughTest(lambda, config.metamodel, parentArgumentScope, false);
                  SymbExToColumns translator = config.newSymbExToColumns(argumentHandler);
                  aggregatedExpr = makeSelectExpression(translator, lambda).getOnlyColumn();
                  if (aggregatedExpr != SelectFromWhereLambdaArgumentHandler.passthroughColsForTesting.getOnlyColumn())
                     throw new TypedValueVisitorException("Applying an aggregation to a distinct stream, but modifying the stream after the distinct but before the aggregation");
               }
               if (select.isSelectFromWhere())
               {
                  SelectFromWhere<V> sfw = (SelectFromWhere<V>)select;
                  argumentHandler = SelectFromWhereLambdaArgumentHandler.fromSelectFromWhere(sfw, lambda, config.metamodel, parentArgumentScope, false);
               }
               else // if (query instanceof SelectOnly)
               {
                  argumentHandler = SelectFromWhereLambdaArgumentHandler.fromSelectOnly(select, lambda, config.metamodel, parentArgumentScope, false);
               }
               SymbExToColumns translator = config.newSymbExToColumns(argumentHandler);
               aggregatedExpr = makeSelectExpression(translator, lambda).getOnlyColumn();
            }
            else
            {
               if (select.cols.isSingleColumn())
                  aggregatedExpr = select.cols.getOnlyColumn();
               else
                  aggregatedExpr = new ConstantExpression("1");
            }
            // Create the new query, merging in the analysis of the method
            SelectOnly<U> toReturn = (SelectOnly<U>)select.shallowCopy();
            toReturn.isAggregated = true;
            toReturn.cols = ColumnExpressions.singleColumn(
                  new SimpleRowReader<>(),
                  new AggregateFunctionExpression(aggregatedExpr, type.name(), select.isDistinct));
            return toReturn;
         }
         throw new QueryTransformException("Existing query cannot be transformed further");
      } catch (TypedValueVisitorException e)
      {
         throw new QueryTransformException(e);
      }
   }

   @Override
   public String getTransformationTypeCachingTag()
   {
      return AggregateTransform.class.getName() + ":" + type.name();
   }
}
TOP

Related Classes of org.jinq.jpa.transform.AggregateTransform

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.