Skip to content

Instantly share code, notes, and snippets.

@raymyers
Created January 7, 2020 23:37
Show Gist options
  • Save raymyers/6d5567b7e561d36d52ba601d5684db5b to your computer and use it in GitHub Desktop.
Save raymyers/6d5567b7e561d36d52ba601d5684db5b to your computer and use it in GitHub Desktop.
Abstract Tree Walker using Type-safe Heterogeneous Container pattern.
import com.google.common.collect.Multimap;
import com.google.common.collect.MultimapBuilder;
import java.util.Collection;
import java.util.function.Consumer;
public class AstWalker {
private final Multimap<Class<?>, Consumer<?>> enterNodeListeners = MultimapBuilder.linkedHashKeys().arrayListValues().build();
private final Multimap<Class<?>, Consumer<?>> exitNodeListeners = MultimapBuilder.linkedHashKeys().arrayListValues().build();
public <T extends BaseNode> void registerEnterNodeListener(Class<T> key, Consumer<T> value) {
enterNodeListeners.put( key, value );
}
public <T extends BaseNode> void registerExitNodeListener(Class<T> key, Consumer<T> value) {
exitNodeListeners.put( key, value );
}
public <T extends BaseNode> Collection<Consumer<BaseNode>> getEnterNodeListeners(Class<T> key ) {
return Collection.class.cast(enterNodeListeners.get( key ));
}
public <T extends BaseNode> Collection<Consumer<BaseNode>> getExitNodeListeners(Class<T> key ) {
return Collection.class.cast(exitNodeListeners.get( key ));
}
public void visitNode(BaseNode node) {
if (node == null) {
return;
}
for (Consumer<BaseNode> consumer : getEnterNodeListeners(node.getClass())) {
consumer.accept(node);
}
node.getChildren().forEach(child -> visitNode(child));
for (Consumer<BaseNode> consumer : getExitNodeListeners(node.getClass())) {
consumer.accept(node);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment