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

com.espertech.esper.epl.join.assemble.CartesianUtil Maven / Gradle / Ivy

There is a newer version: 7.1.0
Show newest version
/*
 ***************************************************************************************
 *  Copyright (C) 2006 EsperTech, Inc. All rights reserved.                            *
 *  http://www.espertech.com/esper                                                     *
 *  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.join.assemble;

import com.espertech.esper.client.EventBean;

import java.util.Arrays;
import java.util.List;

/**
 * Helper class to compute the cartesian product of the events from two streams.
 */
public class CartesianUtil {
    /**
     * Form the 2-ary cartesian product between zero or more events from 2 streams.
     *
     * @param streamOne        is the events from stream one
     * @param subStreamNumsOne is the list of substream numbers to stream one to include in the product
     * @param streamTwo        is the events from stream two
     * @param subStreamNumsTwo is the list of substream numbers to stream two to include in the product
     * @param resultList       is where the result of the cartesian product is added to
     */

    protected static void computeCartesian(List streamOne, int[] subStreamNumsOne,
                                           List streamTwo, int[] subStreamNumsTwo,
                                           List resultList) {

        if ((streamTwo == null) || (streamTwo.isEmpty())) {
            if ((streamOne == null) || (streamOne.isEmpty())) {
                return;
            }
            resultList.addAll(streamOne);
            return;
        }

        if ((streamOne == null) || (streamOne.isEmpty())) {
            resultList.addAll(streamTwo);
            return;
        }

        int streamOneSize = streamOne.size();
        int streamTwoSize = streamTwo.size();

        if (streamOneSize == 1) {
            // Yes we are re-using the results of stream two, same row reference
            copyToEach(subStreamNumsOne, streamOne.get(0), streamTwo);
            resultList.addAll(streamTwo);
            return;
        }

        if (streamTwoSize == 1) {
            // Yes we are re-using the results of stream one, same row reference
            copyToEach(subStreamNumsTwo, streamTwo.get(0), streamOne);
            resultList.addAll(streamOne);
            return;
        }

        // we have more then 1 rows each child stream

        // Exchange streams if one is smaller then two
        // Since if one has 100 rows the other has 2 then we can re-use the 100 event rows.
        if (streamTwoSize > streamOneSize) {
            List holdRows = streamOne;
            int holdSize = streamOneSize;

            streamOne = streamTwo;
            streamOneSize = streamTwoSize;

            streamTwo = holdRows;
            streamTwoSize = holdSize;
            subStreamNumsTwo = subStreamNumsOne;
        }

        // allocate resultList of join
        int cartesianTotalRows = streamOneSize * streamTwoSize;
        int numColumns = streamOne.get(0).length;
        EventBean[][] results = new EventBean[cartesianTotalRows][];

        // Allocate and pre-populate copies of stream 1
        int streamOneCount = 0;
        for (EventBean[] row : streamOne) {
            // first use all events in stream 1
            results[streamOneCount] = row;

            // then allocate copies for each in stream 2
            for (int i = 1; i < streamTwoSize; i++) {
                EventBean[] dupRow = new EventBean[numColumns];
                System.arraycopy(row, 0, dupRow, 0, numColumns);

                int index = streamOneSize * i + streamOneCount;
                results[index] = dupRow;
            }

            streamOneCount++;
        }

        // Copy stream 2 rows into rows of stream 1
        int streamTwoCount = 0;
        for (EventBean[] row : streamTwo) {
            for (int i = 0; i < streamOneSize; i++) {
                int index = streamTwoCount * streamOneSize + i;
                copy(subStreamNumsTwo, row, results[index]);
            }
            streamTwoCount++;
        }

        // Add results
        resultList.addAll(Arrays.asList(results));
    }

    private static void copyToEach(int[] subStreamNums, EventBean[] sourceRow, List destRows) {
        for (EventBean[] destRow : destRows) {
            copy(subStreamNums, sourceRow, destRow);
        }
    }

    private static void copy(int[] subStreamsFrom, EventBean[] from, EventBean[] to) {
        for (int index : subStreamsFrom) {
            to[index] = from[index];
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy