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

com.hazelcast.jet.aggregate.AllOfAggregationBuilder Maven / Gradle / Ivy

There is a newer version: 4.5.4
Show newest version
/*
 * Copyright (c) 2008-2018, Hazelcast, Inc. All Rights Reserved.
 *
 * 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.hazelcast.jet.aggregate;

import com.hazelcast.jet.datamodel.ItemsByTag;
import com.hazelcast.jet.datamodel.Tag;
import com.hazelcast.jet.function.DistributedFunction;

import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.List;

import static com.hazelcast.jet.datamodel.Tag.tag;
import static com.hazelcast.jet.function.DistributedFunction.identity;

/**
 * Offers a step-by-step fluent API to create a composite of multiple
 * aggregate operations. To obtain it, call {@link
 * AggregateOperations#allOfBuilder()}.
 *
 * @param  the type of the input items
 */
public final class AllOfAggregationBuilder {

    private List tags = new ArrayList<>();
    private List operations = new ArrayList<>();

    AllOfAggregationBuilder() { }

    /**
     * Adds the supplied aggregate operation to the composite. Use the returned
     * {@link Tag} as a key in the {@link ItemsByTag} you get in the result of
     * the composite aggregation.
     *
     * @param  the result type of this operation
     */
    @Nonnull
    public  Tag add(@Nonnull AggregateOperation1 operation) {
        operations.add(operation);
        Tag tag = tag(tags.size());
        tags.add(tag);
        return tag;
    }

    /**
     * Builds and returns the composite {@link AggregateOperation1}. Its result
     * type is {@link ItemsByTag} containing all the tags you got from the
     * {@link #add} method.
     */
    @Nonnull
    public AggregateOperation1 build() {
        return build(identity());
    }

    /**
     * Builds and returns the composite {@link AggregateOperation1}. It will
     * call the supplied {@code finishFn} to transform the {@link ItemsByTag}
     * it creates to the result type it emits as the actual result.
     *
     * @param finishFn function to convert {@link ItemsByTag} to the target result type
     */
    @Nonnull
    @SuppressWarnings({"unchecked", "ConstantConditions"})
    public  AggregateOperation1 build(@Nonnull DistributedFunction finishFn) {
        return (AggregateOperation1) AggregateOperation
                .withCreate(() -> {
                    Object[] acc = new Object[tags.size()];
                    for (int i = 0; i < acc.length; i++) {
                        acc[i] = operations.get(i).createFn().get();
                    }
                    return acc;
                })
                .andAccumulate((acc, item) -> {
                    for (int i = 0; i < acc.length; i++) {
                        operations.get(i).accumulateFn().accept(acc[i], item);
                    }
                })
                .andCombine(operations.stream().anyMatch(o -> o.combineFn() == null) ? null :
                        (acc1, acc2) -> {
                            for (int i = 0; i < acc1.length; i++) {
                                operations.get(i).combineFn().accept(acc1[i], acc2[i]);
                            }
                        }
                )
                .andDeduct(operations.stream().anyMatch(o -> o.deductFn() == null) ? null :
                        (acc1, acc2) -> {
                            for (int i = 0; i < acc1.length; i++) {
                                operations.get(i).deductFn().accept(acc1[i], acc2[i]);
                            }
                        }
                )
                .andFinish(acc -> {
                    ItemsByTag result = new ItemsByTag();
                    for (int i = 0; i < tags.size(); i++) {
                        Object finishedVal = operations.get(i).finishFn().apply(acc[i]);
                        result.put(tags.get(i), finishedVal);
                    }
                    return finishFn.apply(result);
                });
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy