package sk.stuba.fiit.perconik.core.java.dom; import java.util.Set; import javax.annotation.Nullable; import com.google.common.base.Joiner; import com.google.common.base.Predicate; import org.eclipse.jdt.core.dom.ASTNode; import sk.stuba.fiit.perconik.eclipse.jdt.core.dom.NodeType; import static com.google.common.collect.Sets.immutableEnumSet; public final class NodeFilters { private NodeFilters() {} private static abstract class AbstractNodeTypePredicate<N extends ASTNode> implements Predicate<N> { final Set<NodeType> types; AbstractNodeTypePredicate(final NodeType type, final NodeType ... rest) { this.types = immutableEnumSet(type, rest); } AbstractNodeTypePredicate(final Iterable<NodeType> types) { this.types = immutableEnumSet(types); } @Override public final int hashCode() { return this.getNodeTypes().hashCode(); } final Set<NodeType> getNodeTypes() { return this.types; } } private static final class IsInstancePredicate<N extends ASTNode> extends AbstractNodeTypePredicate<N> { IsInstancePredicate(final NodeType type, final NodeType ... rest) { super(type, rest); } IsInstancePredicate(final Iterable<NodeType> types) { super(types); } public boolean apply(final N node) { for (NodeType type: this.types) { if (type.isInstance(node)) { return true; } } return false; } @Override public boolean equals(@Nullable final Object o) { if (o instanceof IsInstancePredicate) { IsInstancePredicate<?> other = (IsInstancePredicate<?>) o; return this.getNodeTypes().equals(other.getNodeTypes()); } return false; } @Override public String toString() { return "isInstance(" + Joiner.on(',').join(this.getNodeTypes()) + ")"; } } private static final class IsMatchingPredicate<N extends ASTNode> extends AbstractNodeTypePredicate<N> { IsMatchingPredicate(final NodeType type, final NodeType ... rest) { super(type, rest); } IsMatchingPredicate(final Iterable<NodeType> types) { super(types); } public boolean apply(final N node) { for (NodeType type: this.types) { if (type.isMatching(node)) { return true; } } return false; } @Override public boolean equals(@Nullable final Object o) { if (o instanceof IsMatchingPredicate) { IsMatchingPredicate<?> other = (IsMatchingPredicate<?>) o; return this.getNodeTypes().equals(other.getNodeTypes()); } return false; } @Override public String toString() { return "isMatching(" + Joiner.on(',').join(this.getNodeTypes()) + ")"; } } public static <N extends ASTNode> Predicate<N> isInstance(final NodeType type, final NodeType ... rest) { return new IsInstancePredicate<>(type, rest); } public static <N extends ASTNode> Predicate<N> isInstance(final Iterable<NodeType> types) { return new IsInstancePredicate<>(types); } public static <N extends ASTNode> Predicate<N> isMatching(final NodeType type, final NodeType ... rest) { return new IsMatchingPredicate<>(type, rest); } public static <N extends ASTNode> Predicate<N> isMatching(final Iterable<NodeType> types) { return new IsMatchingPredicate<>(types); } }