001package org.jsoup.select;
002
003import org.jsoup.nodes.Element;
004import org.jspecify.annotations.Nullable;
005
006import java.util.Optional;
007import java.util.stream.Collectors;
008
009/**
010 * Collects a list of elements that match the supplied criteria.
011 *
012 * @author Jonathan Hedley
013 */
014public class Collector {
015
016    private Collector() {}
017
018    /**
019     Build a list of elements, by visiting root and every descendant of root, and testing it against the evaluator.
020     @param eval Evaluator to test elements against
021     @param root root of tree to descend
022     @return list of matches; empty if none
023     */
024    public static Elements collect (Evaluator eval, Element root) {
025        eval.reset();
026
027        return root.stream()
028            .filter(eval.asPredicate(root))
029            .collect(Collectors.toCollection(Elements::new));
030    }
031
032    /**
033     Finds the first Element that matches the Evaluator that descends from the root, and stops the query once that first
034     match is found.
035     @param eval Evaluator to test elements against
036     @param root root of tree to descend
037     @return the first match; {@code null} if none
038     */
039    public static @Nullable Element findFirst(Evaluator eval, Element root) {
040        eval.reset();
041
042        Optional<Element> first = root.stream().filter(eval.asPredicate(root)).findFirst();
043        return first.orElse(null);
044    }
045}