
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 super JsPair> predicate,
final Function super JsPair, T> 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