package sk.stuba.fiit.perconik.core.java.dom;
import java.util.LinkedList;
import javax.annotation.Nullable;
import com.google.common.base.Predicate;
import org.eclipse.jdt.core.dom.ASTNode;
import sk.stuba.fiit.perconik.eclipse.jdt.core.dom.NodeType;
import sk.stuba.fiit.perconik.utilities.function.ListCollector;
public final class NodeCollectors {
private NodeCollectors() {}
private enum ChildrenCollector implements ListCollector<ASTNode, ASTNode> {
INSTANCE;
public LinkedList<ASTNode> apply(@Nullable final ASTNode node) {
return Nodes.children(node);
}
@Override
public String toString() {
return "children";
}
}
private enum AncestorsCollector implements ListCollector<ASTNode, ASTNode> {
INSTANCE;
public LinkedList<ASTNode> apply(@Nullable final ASTNode node) {
return Nodes.ancestors(node);
}
@Override
public String toString() {
return "ancestors";
}
}
private enum DescendantsCollector implements ListCollector<ASTNode, ASTNode> {
INSTANCE;
public LinkedList<ASTNode> apply(@Nullable final ASTNode node) {
return Nodes.descendants(node);
}
@Override
public String toString() {
return "descendants";
}
}
private static <N extends ASTNode, R extends ASTNode> ListCollector<N, R> cast(final ListCollector<?, ?> collector) {
// only for stateless internal singletons shared across all types
@SuppressWarnings("unchecked")
ListCollector<N, R> result = (ListCollector<N, R>) collector;
return result;
}
public static <N extends ASTNode> ListCollector<N, ASTNode> children() {
return cast(ChildrenCollector.INSTANCE);
}
public static <N extends ASTNode> ListCollector<N, ASTNode> ancestors() {
return cast(AncestorsCollector.INSTANCE);
}
public static <N extends ASTNode> ListCollector<N, ASTNode> descendants() {
return cast(DescendantsCollector.INSTANCE);
}
public static <N extends R, R extends ASTNode> ListCollector<N, R> usingFilter(final Predicate<N> filter) {
return NodeFilteringCollector.using(filter);
}
public static <N extends ASTNode, R extends ASTNode> ListCollector<N, R> usingFilter(final NodeClassFilter<N, R> filter) {
return NodeFilteringCollector.using(filter);
}
@SafeVarargs
public static <N extends ASTNode, R extends ASTNode> ListCollector<N, R> ofClass(final Class<? extends R> implementation, final Class<? extends R> ... rest) {
return usingFilter(NodeClassFilter.<N, R>of(implementation, rest));
}
public static <N extends ASTNode, R extends ASTNode> ListCollector<N, R> ofClass(final Iterable<Class<? extends R>> implementations) {
return usingFilter(NodeClassFilter.<N, R>of(implementations));
}
public static <N extends R, R extends ASTNode> ListCollector<N, R> ofType(final NodeType type, final NodeType ... rest) {
return usingFilter(NodeFilters.<N>isMatching(type, rest));
}
public static <N extends R, R extends ASTNode> ListCollector<N, R> ofType(final Iterable<NodeType> types) {
return usingFilter(NodeFilters.<N>isMatching(types));
}
}