PropertyBags.java

/**
 * Copyright (c) 2017-2018, RTE (http://www.rte-france.com)
 * This Source Code Form is subject to the terms of the Mozilla Public
 * License, v. 2.0. If a copy of the MPL was not distributed with this
 * file, You can obtain one at http://mozilla.org/MPL/2.0/.
 * SPDX-License-Identifier: MPL-2.0
 */

package com.powsybl.triplestore.api;

import java.util.ArrayList;
import java.util.Collection;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.BiFunction;
import java.util.stream.Collectors;

/**
 * @author Luma Zamarre��o {@literal <zamarrenolm at aia.es>}
 */
public class PropertyBags extends ArrayList<PropertyBag> {

    public PropertyBags() {
        super();
    }

    public PropertyBags(Collection<PropertyBag> ps) {
        super(ps);
    }

    public List<String> pluck(String property) {
        return stream()
            .map(r -> r.get(property))
            .sorted(Comparator.nullsLast(String::compareTo))
            .collect(Collectors.toList());
    }

    public List<String> pluckLocals(String property) {
        return stream()
            .map(r -> r.getLocal(property))
            .sorted(Comparator.nullsLast(String::compareTo))
            .collect(Collectors.toList());
    }

    public List<String> pluckIdentifiers(String property) {
        return stream()
            .map(r -> r.getId(property))
            .sorted(Comparator.nullsLast(String::compareTo))
            .collect(Collectors.toList());
    }

    public List<String> pluckLocalsUnsorted(String property) {
        return stream()
                .map(r -> r.getLocal(property))
                .collect(Collectors.toList());
    }

    public PropertyBags pivot(
        String idProperty,
        String keyProperty,
        List<String> pivotPropertyNames,
        String valueProperty) {
        int estimatedNumObjects = size() / pivotPropertyNames.size();
        Map<String, PropertyBag> objects = new HashMap<>(estimatedNumObjects);
        List<String> propertyNames = new ArrayList<>(pivotPropertyNames.size() + 1);
        propertyNames.add(idProperty);
        propertyNames.addAll(pivotPropertyNames);
        forEach(b -> {
            String id = b.getId(idProperty);
            PropertyBag object = objects.computeIfAbsent(id, id1 -> {
                PropertyBag o1 = new PropertyBag(propertyNames, true, true);
                o1.put(idProperty, id1);
                return o1;
            });
            String property = b.get(keyProperty);
            String value = b.get(valueProperty);
            object.put(property, value);
        });
        return new PropertyBags(objects.values());
    }

    public PropertyBags pivotLocalNames(
        String idProperty,
        String keyProperty,
        List<String> pivotPropertyLocalNames,
        String valueProperty) {
        int estimatedNumObjects = size() / pivotPropertyLocalNames.size();
        Map<String, PropertyBag> objects = new HashMap<>(estimatedNumObjects);
        List<String> propertyNames = new ArrayList<>(pivotPropertyLocalNames.size() + 1);
        propertyNames.add(idProperty);
        propertyNames.addAll(pivotPropertyLocalNames);
        forEach(b -> {
            String id = b.getId(idProperty);
            PropertyBag object = objects.computeIfAbsent(id, id1 -> {
                PropertyBag o1 = new PropertyBag(propertyNames, true, true);
                o1.put(idProperty, id1);
                return o1;
            });
            String property = b.getLocal(keyProperty);
            String value = b.get(valueProperty);
            object.put(property, value);
        });
        return new PropertyBags(objects.values());
    }

    public String tabulateLocals() {
        return tabulate(PropertyBag::getLocal);
    }

    public String tabulate() {
        return tabulate(HashMap::get);
    }

    private String tabulate(BiFunction<PropertyBag, String, String> getValue) {
        if (size() == 0) {
            return "";
        }
        List<String> names = get(0).propertyNames();
        String columnSeparator = " \t ";
        String lineSeparator = System.lineSeparator();

        StringBuilder s = new StringBuilder(size() * 80);
        s.append(names.stream().collect(Collectors.joining(columnSeparator)));
        s.append(lineSeparator);
        s.append(stream().map(r -> names.stream()
            .map(n -> r.containsKey(n) ? getValue.apply(r, n) : "N/A")
            .collect(Collectors.joining(columnSeparator)))
            .collect(Collectors.joining(lineSeparator)));
        return s.toString();
    }
}