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

io.fluxcapacitor.common.api.search.DocumentStats Maven / Gradle / Ivy

/*
 * Copyright (c) Flux Capacitor IP B.V. or its affiliates. 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 io.fluxcapacitor.common.api.search;

import io.fluxcapacitor.common.search.Document;
import lombok.AllArgsConstructor;
import lombok.Value;

import java.math.BigDecimal;
import java.math.MathContext;
import java.math.RoundingMode;
import java.util.Comparator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Stream;

import static io.fluxcapacitor.common.search.Document.EntryType.NUMERIC;
import static java.util.Comparator.comparing;
import static java.util.Comparator.naturalOrder;
import static java.util.function.Function.identity;
import static java.util.stream.Collectors.groupingBy;
import static java.util.stream.Collectors.toList;
import static java.util.stream.Collectors.toMap;

@Value
public class DocumentStats {

    public static List compute(Stream documents, List fields, List groupBy) {
        var finalFields = fields.isEmpty() ? List.of("") : fields;
        Map, List> groups = documents.collect(
                groupingBy(d -> groupBy.stream().map(
                        g -> d.getEntryAtPath(g).map(Document.Entry::getValue).orElse(null)).collect(toList())));
        Stream statsStream = groups.entrySet().stream().map(e -> new DocumentStats(
                finalFields.stream().collect(toMap(identity(), f -> new FieldStats(e.getValue(), f), (a, b) -> b)),
                asGroup(groupBy, e.getKey())));
        Comparator comparator = groupBy.stream().map(g -> Comparator.nullsLast(
                        comparing(d -> d.getGroup().get(g), Comparator.nullsLast(naturalOrder()))))
                .reduce(Comparator::thenComparing).orElse((a, b) -> 0);
        return statsStream.sorted(comparator).collect(toList());
    }

    private static Group asGroup(List groupBy, List values) {
        Map result = new LinkedHashMap<>();
        for (int i = 0; i < groupBy.size(); i++) {
            result.put(groupBy.get(i), values.get(i));
        }
        return new Group(result);
    }

    Map fieldStats;
    Group group;

    @Value
    @AllArgsConstructor
    public static class FieldStats {
        long count;
        BigDecimal min;
        BigDecimal max;
        BigDecimal sum;
        BigDecimal average;

        protected FieldStats(List documents, String path) {
            this.count = documents.size();
            List values = path.isBlank() ? List.of()
                    : documents.stream().flatMap(d -> d.getEntryAtPath(path).stream())
                    .filter(e -> e.getType() == NUMERIC).map(e -> new BigDecimal(e.getValue())).sorted()
                    .toList();
            if (values.isEmpty()) {
                min = max = sum = average = null;
            } else {
                min = values.get(0);
                max = values.get(values.size() - 1);
                sum = values.stream().reduce(BigDecimal.ZERO, BigDecimal::add);
                average = sum.divide(new BigDecimal(values.size()), new MathContext(10, RoundingMode.HALF_UP))
                        .stripTrailingZeros();
            }
        }
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy