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

io.github.qudtlib.tools.contribute.support.tree.QuantityKindTree Maven / Gradle / Ivy

There is a newer version: 6.8.0
Show newest version
package io.github.qudtlib.tools.contribute.support.tree;

import static io.github.qudtlib.tools.contribute.support.tree.FormattingNodeVisitor.*;

import io.github.qudtlib.Qudt;
import io.github.qudtlib.model.QuantityKind;
import io.github.qudtlib.model.QudtNamespaces;
import io.github.qudtlib.model.Unit;
import java.util.*;
import java.util.stream.Collectors;

public class QuantityKindTree {
    public static String formatQuantityKindForest(Collection quantityKinds) {
        return formatSkosBroaderForest(makeSkosBroaderForest(quantityKinds));
    }

    public static String formatSkosBroaderForest(List> forest) {
        StringBuilder sb = new StringBuilder();
        NodeVisitor formattingVisitor =
                new FormattingNodeVisitor(sb)
                        .nodeFormatDefault(
                                node -> {
                                    StringBuilder ret = new StringBuilder();
                                    ret.append(getShortName(node.getData()));
                                    if (!node.getData().getExactMatches().isEmpty()) {
                                        ret.append(" - exact matches: ")
                                                .append(
                                                        node.getData().getExactMatches().stream()
                                                                .map(qk -> getShortName(qk))
                                                                .collect(Collectors.joining(",")));
                                    }
                                    return ret.toString();
                                });
        for (Node tree : forest) {
            TreeWalker.of(tree).walkDepthFirst(formattingVisitor);
        }
        return sb.toString();
    }

    public static List> makeSkosBroaderForest(
            Collection quantityKinds) {
        List> resultForest =
                Node.forestOf(
                        quantityKinds,
                        (parentCandidate, childCandidate) ->
                                childCandidate.getBroaderQuantityKinds().contains(parentCandidate));
        return resultForest;
    }

    public static List> makeCompleteSkosBroaderForestContaining(
            Collection quantityKinds) {
        Set transitiveHull = new HashSet<>(quantityKinds);
        int hullSize = -1;
        while (transitiveHull.size() > hullSize) {
            hullSize = transitiveHull.size();
            Set toAdd = new HashSet<>();
            for (QuantityKind qk : transitiveHull) {
                toAdd.addAll(qk.getBroaderQuantityKinds());
            }
            transitiveHull.addAll(toAdd);
        }
        Qudt.allQuantityKinds().stream()
                .filter(
                        qk ->
                                qk.getBroaderQuantityKinds().stream()
                                        .anyMatch(q -> transitiveHull.contains(q)))
                .forEach(transitiveHull::add);
        List> resultForest =
                Node.forestOf(
                        transitiveHull,
                        (parentCandidate, childCandidate) ->
                                childCandidate.getBroaderQuantityKinds().contains(parentCandidate));
        return resultForest;
    }

    public static List> addAssociatedUnitsToQuantityKindForest(
            List> forest) {
        List> qksWithUnits = new ArrayList<>();
        for (Node node : forest) {
            qksWithUnits.add(addUnits(node));
        }
        return qksWithUnits;
    }

    private static Node addUnits(Node node) {
        Node thisNode = new Node<>(node.getData());
        for (Node child : node.getChildren()) {
            thisNode.addChild(addUnits(child));
        }
        Qudt.allUnits().stream()
                .filter(u -> u.getQuantityKinds().contains(node.getData()))
                .forEach(
                        unit -> {
                            thisNode.addChild(new Node<>(unit));
                        });
        // node.getData().getApplicableUnits().forEach(u -> thisNode.addChild(u));
        return thisNode;
    }

    private static String getShortName(QuantityKind quantityKind) {
        return QudtNamespaces.quantityKind.abbreviate(quantityKind.getIri());
    }

    public static void formatQuantityKindTree(
            List> actualQuantityKindsWithUnits, StringBuilder stringBuilder) {
        formatQuantityKindTree(actualQuantityKindsWithUnits, null, stringBuilder);
    }

    public static void formatQuantityKindTree(
            List> actualQuantityKindsWithUnits,
            NodeToString nodeFormatter,
            StringBuilder stringBuilder) {
        if (nodeFormatter == null) {
            nodeFormatter = node -> getUnitOrQuantityKindIriAbbreviated(node);
        }
        for (Node root : actualQuantityKindsWithUnits) {
            FormattingNodeVisitor formatter =
                    new FormattingNodeVisitor(stringBuilder)
                            .nodeFormatDefault(nodeFormatter);
            formatter.treeDrawingConfig(
                    (config, node) -> {
                        if (node.getNode().getData() instanceof QuantityKind) {
                            config.branchStart(CHAR_SLIM_DOUBLE_RIGHT_T)
                                    .branchStartLast(CHAR_SLIM_DOUBLE_ANGLE)
                                    .branch(CHAR_DOUBLE_HORIZ)
                                    .branchEndLeaf(CHAR_DOUBLE_HORIZ)
                                    .branchEndInner(CHAR_DOUBLE_SLIM_T);
                        }
                    });
            TreeWalker.of(root)
                    .sorted(
                            Comparator.comparing(
                                            (Node node) ->
                                                    node.getData().getClass().getSimpleName())
                                    .thenComparing(
                                            QuantityKindTree::getUnitOrQuantityKindIriAbbreviated))
                    .walkDepthFirst(formatter);
        }
    }

    public static String getUnitOrQuantityKindIriAbbreviated(Node node) {
        return (node.getData() instanceof Unit)
                ? ((Unit) node.getData()).getIriAbbreviated()
                : QudtNamespaces.quantityKind.abbreviate(((QuantityKind) node.getData()).getIri());
    }

    public static void makeAndFormatQuantityKindAndUnitTree(
            Set quantityKindSet, StringBuilder stringBuilder) {
        makeAndFormatQuantityKindAndUnitTree(quantityKindSet, null, stringBuilder);
    }

    public static void makeAndFormatQuantityKindAndUnitTree(
            Set quantityKindSet,
            NodeToString nodeFormatter,
            StringBuilder stringBuilder) {
        List> actualQuantityKindForest =
                makeCompleteSkosBroaderForestContaining(quantityKindSet);
        List> actualQuantityKindsWithUnits =
                addAssociatedUnitsToQuantityKindForest(actualQuantityKindForest);
        formatQuantityKindTree(actualQuantityKindsWithUnits, nodeFormatter, stringBuilder);
    }
}