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

jsonvalues.OpMapReduce Maven / Gradle / Ivy

package jsonvalues;

import java.util.Optional;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.Predicate;

import static jsonvalues.Trampoline.done;
import static jsonvalues.Trampoline.more;

final class OpMapReduce {
    private final BiFunction, Optional> accumulator;

    OpMapReduce(final Predicate predicate,
                final Function map,
                final BinaryOperator op
               ) {
        this.accumulator = (pair, acc) ->
        {
            if (!predicate.test(pair)) return acc;
            final T mapped = map.apply(pair);
            final Optional t = acc.map(it -> op.apply(it,
                                                         mapped
                                                        )
                                         );
            if (t.isPresent()) return t;
            return Optional.ofNullable(mapped);
        };
    }

    Optional reduceAll(JsObj obj) {
        return reduceObj(JsPath.empty(),
                         reduceHeadJsonAndObjTail_()
                        ).apply(obj,
                                Optional.empty()
                               )
                         .get();
    }

    Optional reduce(JsObj obj) {
        return reduceObj(JsPath.empty(),
                         reduceHeadJsonAndObjTail()
                        ).apply(obj,
                                Optional.empty()
                               )
                         .get();
    }

    Optional reduceAll(JsArray arr) {
        return reduceArr(JsPath.empty()
                               .index(-1),
                         reduceHeadJsonAndArrayTail_()
                        ).apply(arr,
                                Optional.empty()
                               )
                         .get();
    }

    Optional reduce(JsArray arr) {
        return reduceArr(JsPath.empty()
                               .index(-1),
                         reduceHeadJsonAndArrayTail()
                        ).apply(arr,
                                Optional.empty()
                               )
                         .get();
    }

    private BiFunction, BiFunction, Trampoline>>> reduceHeadJsonAndObjTail() {

        return (headPath, headJson) -> (tail, acc) -> Trampoline.more(() -> reduceObj(headPath.init(),
                                                                                      reduceHeadJsonAndObjTail()
                                                                                     ).apply(tail,
                                                                                             acc
                                                                                            )
                                                                     );
    }

    private BiFunction, BiFunction, Trampoline>>> reduceHeadJsonAndArrayTail() {

        return (headPath, headJson) -> (tail, acc) -> Trampoline.more(() -> reduceArr(headPath,
                                                                                      reduceHeadJsonAndArrayTail()
                                                                                     ).apply(tail,
                                                                                             acc
                                                                                            )
                                                                     );
    }

    private BiFunction, BiFunction, Trampoline>>> reduceHeadJsonAndObjTail_() {
        return (headPath, headJson) -> (tail, acc) -> more(() -> reduceJson(acc).apply(headPath,
                                                                                       headJson
                                                                                      )
                                                          ).flatMap(headAcc ->
                                                                            reduceObj(headPath.init(),
                                                                                      reduceHeadJsonAndObjTail_()
                                                                                     ).
                                                                                              apply(tail,
                                                                                                    headAcc
                                                                                                   ));
    }


    private BiFunction, BiFunction, Trampoline>>> reduceHeadJsonAndArrayTail_() {
        return (headPath, headJson) -> (tail, acc) -> more(() -> reduceJson(acc).apply(headPath,
                                                                                       headJson
                                                                                      )
                                                          ).flatMap(headAcc ->
                                                                            reduceArr(headPath,
                                                                                      reduceHeadJsonAndArrayTail_()
                                                                                     ).
                                                                                              apply(tail,
                                                                                                    headAcc
                                                                                                   ));
    }

    private BiFunction, Trampoline>> reduceJson(final Optional acc) {

        return (headPath, headJson) ->
        {
            if (headJson.isObj()) return reduceObj(headPath,
                                                   reduceHeadJsonAndObjTail_()
                                                  ).apply(headJson.toJsObj(),
                                                          acc
                                                         );
            return reduceArr(headPath.index(-1),
                             reduceHeadJsonAndArrayTail_()
                            ).apply(headJson.toJsArray(),
                                    acc
                                   );

        };
    }

    private BiFunction, Trampoline>> reduceObj(final JsPath startingPath,
                                                                              final BiFunction, BiFunction, Trampoline>>> reduceHeadJsonTail
                                                                             ) {

        return (obj, acc) ->
                obj.ifEmptyElse(done(acc),
                                (head, tail) ->
                                {
                                    final JsPath headPath = startingPath.key(head._1);
                                    return MatchExp.ifJsonElse(headJson ->
                                                                       reduceHeadJsonTail.apply(headPath,
                                                                                                headJson
                                                                                               )
                                                                                         .apply(tail,
                                                                                                acc
                                                                                               ),
                                                               headElem ->
                                                                       more(() -> reduceObj(startingPath,
                                                                                            reduceHeadJsonTail
                                                                                           ).apply(tail,
                                                                                                   accumulator.apply(JsPair.of(headPath,
                                                                                                                               headElem
                                                                                                                              ),
                                                                                                                     acc
                                                                                                                    )
                                                                                                  ))

                                                              )
                                                   .apply(head._2);

                                }
                               );


    }

    private BiFunction, Trampoline>> reduceArr(final JsPath startingPath,
                                                                                final BiFunction, BiFunction, Trampoline>>> reduceHeadJsonTail
                                                                               ) {

        return (arr, acc) -> arr.ifEmptyElse(done(acc),
                                             (head, tail) ->
                                             {
                                                 final JsPath headPath = startingPath.inc();

                                                 return MatchExp.ifJsonElse(json ->
                                                                                    reduceHeadJsonTail.apply(headPath,
                                                                                                             json
                                                                                                            )
                                                                                                      .apply(tail,
                                                                                                             acc
                                                                                                            ),
                                                                            elem ->
                                                                                    more(() -> reduceArr(headPath,
                                                                                                         reduceHeadJsonTail
                                                                                                        ).apply(tail,
                                                                                                                accumulator.apply(JsPair.of(headPath,
                                                                                                                                            elem
                                                                                                                                           ),
                                                                                                                                  acc
                                                                                                                                 )
                                                                                                               ))

                                                                           )
                                                                .apply(head);
                                             }
                                            );
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy