package sk.stuba.fiit.perconik.core.java.dom;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import javax.annotation.Nullable;
import com.google.common.base.Function;
import com.google.common.base.Joiner;
import org.eclipse.jdt.core.dom.ASTNode;
import sk.stuba.fiit.perconik.eclipse.jdt.core.dom.NodeType;
import sk.stuba.fiit.perconik.utilities.MoreStrings;
import sk.stuba.fiit.perconik.utilities.function.ListCollector;
import static com.google.common.base.MoreObjects.firstNonNull;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Lists.newArrayList;
public final class NodeTokenizer<N extends ASTNode> implements ListCollector<N, String> {
private final Function<N, ? extends Iterable<ASTNode>> collector;
private final Function<ASTNode, String> transformer;
private final Tokenizer tokenizer;
NodeTokenizer(final Builder<N> builder) {
this.collector = firstNonNull(builder.collector, NodeCollectors.<N, ASTNode>ofType(NodeType.SIMPLE_NAME));
this.transformer = firstNonNull(builder.transformer, MoreStrings.<ASTNode>toStringFunction());
this.tokenizer = firstNonNull(builder.tokenizer, Tokenizers.shared);
}
public static <N extends ASTNode> NodeTokenizer<N> using(final Function<N, ? extends Iterable<ASTNode>> collector) {
return new Builder<N>().collector(collector).build();
}
public static final class Builder<N extends ASTNode> {
Function<N, ? extends Iterable<ASTNode>> collector;
Function<ASTNode, String> transformer;
Tokenizer tokenizer;
public Builder() {}
public Builder<N> collector(final Function<N, ? extends Iterable<ASTNode>> collector) {
checkState(this.collector == null);
this.collector = checkNotNull(collector);
return this;
}
public Builder<N> transformer(final Function<ASTNode, String> transformer) {
checkState(this.transformer == null);
this.transformer = checkNotNull(transformer);
return this;
}
public Builder<N> tokenizer(final Tokenizer tokenizer) {
checkState(this.tokenizer == null);
this.tokenizer = checkNotNull(tokenizer);
return this;
}
public NodeTokenizer<N> build() {
return new NodeTokenizer<>(this);
}
}
public static <N extends ASTNode> Builder<N> builder() {
return new Builder<>();
}
public List<String> apply(final N node) {
if (node == null) {
return Collections.emptyList();
}
Iterable<ASTNode> nodes = this.collector.apply(node);
List<String> tokens = newArrayList();
for (ASTNode other: nodes) {
String input = this.transformer.apply(other);
tokens.addAll(this.tokenizer.apply(input));
}
return tokens;
}
@Override
public boolean equals(@Nullable final Object o) {
if (this == o) {
return true;
}
if (!(o instanceof NodeTokenizer)) {
return false;
}
NodeTokenizer<?> other = (NodeTokenizer<?>) o;
return this.collector.equals(other.collector) && this.transformer.equals(other.transformer) && this.tokenizer.equals(other.tokenizer);
}
@Override
public int hashCode() {
return Objects.hash(this.collector, this.transformer, this.tokenizer);
}
@Override
public String toString() {
return "tokenizer(" + Joiner.on(",").join(this.collector, this.transformer, this.tokenizer) + ")";
}
public Function<N, ? extends Iterable<ASTNode>> getCollector() {
return this.collector;
}
public Function<ASTNode, String> getTransformer() {
return this.transformer;
}
public Tokenizer getTokenizer() {
return this.tokenizer;
}
}