org.nickelproject.nickel.dataflow.Collector.java Source code

Java tutorial

Introduction

Here is the source code for org.nickelproject.nickel.dataflow.Collector.java

Source

/*
 * Copyright (c) 2013, 2014 Nigel Duffy
 *
 * 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 org.nickelproject.nickel.dataflow;

import java.util.Map;

import org.nickelproject.util.functions.PairFunction;
import org.nickelproject.util.functions.ToPairFunction;
import org.nickelproject.util.tuple.Pair;

import com.google.common.base.Function;
import com.google.common.base.Functions;

/**
 * A wrapper to hide the irrelevant intermediate class in CollectorBase.
 *
 * @param <T>
 * @param <U>
 */
public final class Collector<T, U> implements CollectorInterface<T, U> {
    private static final long serialVersionUID = 1L;
    private final CollectorBase<T, ?, U> collectorBase;

    private Collector(final CollectorBase<T, ?, U> collectorBase) {
        this.collectorBase = collectorBase;
    }

    public static <S, T, V> Collector<S, V> create(final Function<S, T> preFunctor, final Reducer<T> reducer,
            final Function<T, V> postFunctor) {
        return new Collector<S, V>(new CollectorBase<S, T, V>(preFunctor, reducer, postFunctor));
    }

    public static <S, T> Collector<S, T> create(final Function<S, T> preFunction, final Reducer<T> reducer) {
        return create(preFunction, reducer, Functions.<T>identity());
    }

    public static <S, T, X, Y, V> Collector<S, V> create(final Function<S, T> preFunctor,
            final Collector<T, Y> collector, final Function<Y, V> postFunctor) {
        @SuppressWarnings("unchecked")
        final CollectorBase<T, X, Y> wrapped = (CollectorBase<T, X, Y>) collector.collectorBase;
        final Function<S, X> newPreFunction = Functions.compose(wrapped.preFunctor, preFunctor);
        final Function<X, V> newPostFunction = Functions.compose(postFunctor, wrapped.postFunctor);
        return new Collector<S, V>(new CollectorBase<S, X, V>(newPreFunction, wrapped.reducer, newPostFunction));
    }

    public static <S, T, V> Collector<S, V> create(final Function<S, T> preFunction,
            final Collector<T, V> collector) {
        return create(preFunction, collector, Functions.<V>identity());
    }

    public static <T, V, W> Collector<T, W> create(final Collector<T, V> collector,
            final Function<V, W> postFunction) {
        return create(Functions.<T>identity(), collector, postFunction);
    }

    public static <I, K, T, V> Collector<I, Source<Pair<K, V>>> groupBy(final Function<I, K> keyFunction,
            final Collector<I, V> aggregator) {
        final Reducer<Map<K, T>> mapReducer = MapMergingReducer
                .create((Reducer<T>) aggregator.collectorBase.reducer);
        final Function<I, Pair<I, I>> toPairFunction = new ToPairFunction<I>();
        final Function<Pair<I, I>, Pair<K, T>> pairFunction = PairFunction.of(keyFunction,
                (Function<I, T>) aggregator.collectorBase.preFunctor);
        final Function<Pair<K, T>, Map<K, T>> toMap = new ToMapFunction();
        return Collector.create(Functions.compose(toMap, Functions.compose(pairFunction, toPairFunction)),
                mapReducer,
                Functions.compose(
                        new TransformSourceFunction(PairFunction.of(Functions.<K>identity(),
                                (Function<T, V>) aggregator.collectorBase.postFunctor)),
                        new MapToPairSourceFunction<K, T>()));
    }

    @Override
    public Reductor<T, U> reductor() {
        return collectorBase.reductor();
    }

    private static final class CollectorBase<S, T, V> implements CollectorInterface<S, V> {
        private static final long serialVersionUID = 1L;
        private final Function<S, T> preFunctor;
        private final Reducer<T> reducer;
        private final Function<T, V> postFunctor;

        private CollectorBase(final Function<S, T> preFunctor, final Reducer<T> reducer,
                final Function<T, V> postFunctor) {
            this.preFunctor = preFunctor;
            this.reducer = reducer;
            this.postFunctor = postFunctor;
        }

        @Override
        public Reductor<S, V> reductor() {
            return new ComposingReductor<S, T, V>(preFunctor, reducer.reductor(), postFunctor);
        }

        private static final class ComposingReductor<S, T, V> implements Reductor<S, V> {
            private final Function<S, T> preFunction;
            private final Function<T, V> postFunction;
            private final Reductor<T, T> reductor;

            ComposingReductor(final Function<S, T> preFunction, final Reductor<T, T> reductor,
                    final Function<T, V> postFunction) {
                this.preFunction = preFunction;
                this.postFunction = postFunction;
                this.reductor = reductor;
            }

            @Override
            public void collect(final S pVal) {
                reductor.collect(preFunction.apply(pVal));
            }

            @Override
            public V reduce() {
                return postFunction.apply(reductor.reduce());
            }
        }
    }
}