Package com.espertech.esper.epl.core

Source Code of com.espertech.esper.epl.core.OrderByProcessorImpl$OrderByElement

/**************************************************************************************
* Copyright (C) 2008 EsperTech, Inc. All rights reserved.                            *
* http://esper.codehaus.org                                                          *
* http://www.espertech.com                                                           *
* ---------------------------------------------------------------------------------- *
* The software in this package is published under the terms of the GPL license       *
* a copy of which has been included with this distribution in the license.txt file.  *
**************************************************************************************/
package com.espertech.esper.epl.core;

import com.espertech.esper.client.EventBean;
import com.espertech.esper.collection.MultiKeyUntyped;
import com.espertech.esper.epl.agg.AggregationService;
import com.espertech.esper.epl.expression.*;
import com.espertech.esper.epl.spec.OrderByItem;
import com.espertech.esper.util.MultiKeyCollatingComparator;
import com.espertech.esper.util.MultiKeyComparator;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import java.util.*;

/**
* An order-by processor that sorts events according to the expressions
* in the order_by clause.
*/
public class OrderByProcessorImpl implements OrderByProcessor {

  private static final Log log = LogFactory.getLog(OrderByProcessorImpl.class);

  private final OrderByElement[] orderBy;
  private final ExprEvaluator[] groupByNodes;
  private final boolean needsGroupByKeys;
  private final AggregationService aggregationService;

  private final Comparator<MultiKeyUntyped> comparator;

  /**
   * Ctor.
   *
   * @param orderByList -
   *            the nodes that generate the keys to sort events on
   * @param groupByNodes -
   *            generate the keys for determining aggregation groups
   * @param needsGroupByKeys -
   *            indicates whether this processor needs to have individual
   *            group by keys to evaluate the sort condition successfully
   * @param aggregationService -
   *            used to evaluate aggregate functions in the group-by and
   *            sort-by clauses
     * @param isSortUsingCollator for string value sorting using compare or Collator
     * @throws ExprValidationException when order-by items don't divulge a type
   */
  public OrderByProcessorImpl(final List<OrderByItem> orderByList,
                  List<ExprNode> groupByNodes,
                  boolean needsGroupByKeys,
                  AggregationService aggregationService,
                                  boolean isSortUsingCollator)
            throws ExprValidationException
    {
    this.orderBy = toElementArray(orderByList);
    this.groupByNodes = ExprNodeUtility.getEvaluators(groupByNodes);
    this.needsGroupByKeys = needsGroupByKeys;
    this.aggregationService = aggregationService;

        comparator = getComparator(orderBy, isSortUsingCollator);
    }

    public MultiKeyUntyped getSortKey(EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext)
    {
        Object[] values = new Object[orderBy.length];
        int count = 0;
        for (OrderByElement sortPair : orderBy)
        {
            values[count++] = sortPair.expr.evaluate(eventsPerStream, isNewData, exprEvaluatorContext);
        }

        return new MultiKeyUntyped(values);
    }

    public MultiKeyUntyped[] getSortKeyPerRow(EventBean[] generatingEvents, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext)
    {
        if (generatingEvents == null)
        {
            return null;
        }

        MultiKeyUntyped[] sortProperties = new MultiKeyUntyped[generatingEvents.length];

        int count = 0;
        EventBean[] evalEventsPerStream = new EventBean[1];
        for (EventBean event : generatingEvents)
        {
            Object[] values = new Object[orderBy.length];
            int countTwo = 0;
            evalEventsPerStream[0] = event;
            for (OrderByElement sortPair : orderBy)
            {
                values[countTwo++] = sortPair.expr.evaluate(evalEventsPerStream, isNewData, exprEvaluatorContext);
            }

            sortProperties[count] = new MultiKeyUntyped(values);
            count++;
        }

        return sortProperties;
    }

  public EventBean[] sort(EventBean[] outgoingEvents, EventBean[][] generatingEvents, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext)
  {
    if (outgoingEvents == null || outgoingEvents.length < 2)
    {
      return outgoingEvents;
    }

    // Get the group by keys if needed
    MultiKeyUntyped[] groupByKeys = null;
    if (needsGroupByKeys)
    {
      groupByKeys = generateGroupKeys(generatingEvents, isNewData, exprEvaluatorContext);
    }

    return sort(outgoingEvents, generatingEvents, groupByKeys, isNewData, exprEvaluatorContext);
  }

  public EventBean[] sort(EventBean[] outgoingEvents, EventBean[][] generatingEvents, MultiKeyUntyped[] groupByKeys, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext)
  {
        if (outgoingEvents == null || outgoingEvents.length < 2)
    {
      return outgoingEvents;
    }

    // Create the multikeys of sort values
    List<MultiKeyUntyped> sortValuesMultiKeys = createSortProperties(generatingEvents, groupByKeys, isNewData, exprEvaluatorContext);

    // Map the sort values to the corresponding outgoing events
    Map<MultiKeyUntyped, List<EventBean>> sortToOutgoing = new HashMap<MultiKeyUntyped, List<EventBean>>();
    int countOne = 0;
    for (MultiKeyUntyped sortValues : sortValuesMultiKeys)
    {
      List<EventBean> list = sortToOutgoing.get(sortValues);
      if (list == null)
      {
        list = new ArrayList<EventBean>();
      }
      list.add(outgoingEvents[countOne++]);
      sortToOutgoing.put(sortValues, list);
    }

    // Sort the sort values
    Collections.sort(sortValuesMultiKeys, comparator);

    // Sort the outgoing events in the same order
    Set<MultiKeyUntyped> sortSet = new LinkedHashSet<MultiKeyUntyped>(sortValuesMultiKeys);
    EventBean[] result = new EventBean[outgoingEvents.length];
    int countTwo = 0;
    for (MultiKeyUntyped sortValues : sortSet)
    {
      Collection<EventBean> output = sortToOutgoing.get(sortValues);
      for(EventBean event : output)
      {
        result[countTwo++] = event;
      }
    }

    return result;
  }

  private List<MultiKeyUntyped> createSortProperties(EventBean[][] generatingEvents, MultiKeyUntyped[] groupByKeys, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext)
  {
    MultiKeyUntyped[] sortProperties = new MultiKeyUntyped[generatingEvents.length];

    int count = 0;
    for (EventBean[] eventsPerStream : generatingEvents)
    {
      // Make a new multikey that contains the sort-by values.
      if (needsGroupByKeys)
      {
        aggregationService.setCurrentAccess(groupByKeys[count]);
      }

      Object[] values = new Object[orderBy.length];
      int countTwo = 0;
      for (OrderByElement sortPair : orderBy)
      {
        values[countTwo++] = sortPair.expr.evaluate(eventsPerStream, isNewData, exprEvaluatorContext);
      }

      sortProperties[count] = new MultiKeyUntyped(values);
      count++;
    }
    return Arrays.asList(sortProperties);
  }

  private MultiKeyUntyped generateGroupKey(EventBean[] eventsPerStream, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext)
  {
    Object[] keys = new Object[groupByNodes.length];

    int count = 0;
    for (ExprEvaluator exprNode : groupByNodes)
    {
      keys[count] = exprNode.evaluate(eventsPerStream, isNewData, exprEvaluatorContext);
      count++;
    }

    return new MultiKeyUntyped(keys);
  }

    public EventBean[] sort(EventBean[] outgoingEvents, MultiKeyUntyped[] orderKeys, ExprEvaluatorContext exprEvaluatorContext)
    {
        TreeMap<MultiKeyUntyped, Object> sort = new TreeMap<MultiKeyUntyped, Object>(comparator);

        if (outgoingEvents == null || outgoingEvents.length < 2)
        {
            return outgoingEvents;
        }

        for (int i = 0; i < outgoingEvents.length; i++)
        {
            Object entry = sort.get(orderKeys[i]);
            if (entry == null)
            {
                sort.put(orderKeys[i], outgoingEvents[i]);
            }
            else if (entry instanceof EventBean)
            {
                List<EventBean> list = new ArrayList<EventBean>();
                list.add((EventBean)entry);
                list.add(outgoingEvents[i]);
                sort.put(orderKeys[i], list);
            }
            else
            {
                List<EventBean> list = (List<EventBean>) entry;
                list.add(outgoingEvents[i]);
            }
        }

        EventBean[] result = new EventBean[outgoingEvents.length];
        int count = 0;
        for (Object entry : sort.values())
        {
            if (entry instanceof List)
            {
                List<EventBean> output = (List<EventBean>) entry;
                for(EventBean event : output)
                {
                    result[count++] = event;
                }
            }
            else
            {
                result[count++] = (EventBean) entry;
            }
        }
        return result;
    }

    private MultiKeyUntyped[] generateGroupKeys(EventBean[][] generatingEvents, boolean isNewData, ExprEvaluatorContext exprEvaluatorContext)
  {
    MultiKeyUntyped keys[] = new MultiKeyUntyped[generatingEvents.length];

    int count = 0;
    for (EventBean[] eventsPerStream : generatingEvents)
    {
      keys[count++] = generateGroupKey(eventsPerStream, isNewData, exprEvaluatorContext);
    }

    return keys;
  }

    /**
     * Returns a comparator for order items that may sort string values using Collator.
     * @param orderBy order-by items
     * @param isSortUsingCollator true for Collator string sorting
     * @return comparator
     * @throws ExprValidationException if the return type of order items cannot be determined
     */
    protected static Comparator<MultiKeyUntyped> getComparator(OrderByElement[] orderBy, boolean isSortUsingCollator) throws ExprValidationException
    {
        Comparator<MultiKeyUntyped> comparator;

        if (isSortUsingCollator)
        {
            // determine String types
            boolean hasStringTypes = false;
            boolean stringTypes[] = new boolean[orderBy.length];
            int count = 0;
            for (OrderByElement item : orderBy)
            {
                if (item.expr.getType() == String.class)
                {
                    hasStringTypes = true;
                    stringTypes[count] = true;
                }
                count++;
            }

            if (!hasStringTypes)
            {
                comparator = new MultiKeyComparator(getIsDescendingValues(orderBy));
            }
            else
            {
                comparator = new MultiKeyCollatingComparator(getIsDescendingValues(orderBy), stringTypes);
            }
        }
        else
        {
            comparator = new MultiKeyComparator(getIsDescendingValues(orderBy));
        }

        return comparator;
    }

  private static boolean[] getIsDescendingValues(OrderByElement[] orderBy)
  {
    boolean[] isDescendingValues  = new boolean[orderBy.length];
    int count = 0;
    for(OrderByElement pair : orderBy)
    {
      isDescendingValues[count++] = pair.isDescending;
    }
    return isDescendingValues;
  }

    private OrderByElement[] toElementArray(List<OrderByItem> orderByList) {
        OrderByElement[] elements = new OrderByElement[orderByList.size()];
        int count = 0;
        for (OrderByItem item : orderByList) {
            elements[count++] = new OrderByElement(item.getExprNode().getExprEvaluator(), item.isDescending());
        }
        return elements;
    }

    public static class OrderByElement
    {
        private ExprEvaluator expr;
        private boolean isDescending;

        public OrderByElement(ExprEvaluator expr, boolean descending) {
            this.expr = expr;
            isDescending = descending;
        }
    }
}
TOP

Related Classes of com.espertech.esper.epl.core.OrderByProcessorImpl$OrderByElement

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.