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

net.pincette.mongo.streams.Redact Maven / Gradle / Ivy

The newest version!
package net.pincette.mongo.streams;

import static net.pincette.json.JsonUtil.createArrayBuilder;
import static net.pincette.json.JsonUtil.createObjectBuilder;
import static net.pincette.json.JsonUtil.createValue;
import static net.pincette.json.JsonUtil.isArray;
import static net.pincette.json.JsonUtil.isObject;
import static net.pincette.mongo.Expression.function;
import static net.pincette.rs.Box.box;
import static net.pincette.rs.Filter.filter;
import static net.pincette.rs.Mapper.map;
import static net.pincette.util.Collections.map;
import static net.pincette.util.Pair.pair;

import java.util.Map.Entry;
import java.util.Objects;
import java.util.Optional;
import java.util.concurrent.Flow.Processor;
import java.util.function.BiFunction;
import java.util.function.Function;
import javax.json.JsonArray;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import javax.json.JsonValue;
import net.pincette.rs.streams.Message;

/**
 * The $redact operator.
 *
 * @author Werner Donn\u00e9
 */
class Redact {
  private static final JsonValue DESCEND = createValue("DESCEND");
  private static final String DESCEND_VAR = "$$DESCEND";
  private static final JsonValue KEEP = createValue("KEEP");
  private static final String KEEP_VAR = "$$KEEP";
  private static final JsonValue PRUNE = createValue("PRUNE");
  private static final String PRUNE_VAR = "$$PRUNE";

  private Redact() {}

  static Processor, Message> stage(
      final JsonValue expression, final Context context) {
    final Function function =
        function(
            expression,
            map(pair(DESCEND_VAR, DESCEND), pair(KEEP_VAR, KEEP), pair(PRUNE_VAR, PRUNE)),
            context.features);

    return box(
        map(m -> m.withValue(transform(m.value, function).orElse(null))),
        filter(m -> m.value != null));
  }

  private static Optional transform(
      final JsonObject json, final Function function) {
    return Optional.of(function.apply(json))
        .filter(result -> DESCEND.equals(result) || KEEP.equals(result))
        .map(result -> KEEP.equals(result) ? json : transformEmbedded(json, function));
  }

  private static JsonValue transformArray(
      final JsonArray array, final Function function) {
    return array.stream()
        .map(v -> isObject(v) ? transform(v.asJsonObject(), function).orElse(null) : v)
        .filter(Objects::nonNull)
        .reduce(createArrayBuilder(), JsonArrayBuilder::add, (b1, b2) -> b1)
        .build();
  }

  private static JsonObject transformEmbedded(
      final JsonObject json, final Function function) {
    final BiFunction, JsonObjectBuilder> tryArray =
        (b, e) ->
            b.add(
                e.getKey(),
                isArray(e.getValue())
                    ? transformArray(e.getValue().asJsonArray(), function)
                    : e.getValue());

    return json.entrySet().stream()
        .reduce(
            createObjectBuilder(),
            (b, e) ->
                isObject(e.getValue())
                    ? transform(e.getValue().asJsonObject(), function)
                        .map(j -> b.add(e.getKey(), j))
                        .orElse(b)
                    : tryArray.apply(b, e),
            (b1, b2) -> b1)
        .build();
  }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy