package tc.oc.pgm.xml;
import java.util.Set;
import java.util.stream.Stream;
import javax.annotation.Nullable;
import org.jdom2.Element;
/**
* Builds a list of descendant {@link Element}s from a parent element,
* and inherits attributes down the tree.
*/
public class ElementFlattener {
public interface Filter {
boolean test(Element element, int depth);
}
private final Filter branchFilter;
private final Filter leafFilter;
public ElementFlattener(Filter branchFilter, Filter leafFilter) {
this.branchFilter = branchFilter;
this.leafFilter = leafFilter;
}
public ElementFlattener(Set<String> parentTagNames, @Nullable Set<String> childTagNames, int minChildDepth) {
this((el, depth) -> parentTagNames.contains(el.getName()),
(el, depth) -> depth >= minChildDepth && (childTagNames == null || childTagNames.contains(el.getName())));
}
public Stream<Element> flattenChildren(Element parent) {
return parent.getChildren()
.stream()
.flatMap(this::flatten);
}
public Stream<Element> flatten(Element element) {
return flatten(element, 0);
}
private Stream<Element> flatten(Element element, int depth) {
if(branchFilter.test(element, depth)) {
return wrap(element, depth).getChildren()
.stream()
.flatMap(child -> flatten(child, depth + 1));
} else if(leafFilter.test(element, depth)) {
return Stream.of(wrap(element, depth));
} else {
return Stream.empty();
}
}
private Element wrap(Element element, int depth) {
// Root node has nothing to inherit
return depth < 1 ? element : InheritingElement.of(element);
}
}