package com.sag.baf.tools;
import java.util.Collection;
import java.util.Stack;
/**
* This helper class is easy to override, and helps create a recursive function local to a method (nested functions don't exist in Java)
*
* @param <T> the type of object that we recurse on
*/
public abstract class RecursionHelper<T> {
private boolean depthFirst = false;
private Stack<T> currentRecursionStack;
private T startElement;
/**
* sets the recursionHelper to go down the depth of the tree first, before doing any action on the nodes
*
* @return
*/
public RecursionHelper<T> setDepthFirst() {
this.depthFirst = true;
return this;
}
/**
* gets the next level of recursion
*
* @param currentElement is never null
* @return the list of elements that are contained in currentElement
*/
public abstract Collection<T> getRecursedElements(T currentElement);
/**
* do the desired action on each recursed elements
*
* @param currentElement is never null
*/
public abstract void doActionOnElement(T currentElement);
public RecursionHelper(T startElement) {
this.startElement = startElement;
}
public int getCurrentRecursionLevel() {
if (currentRecursionStack == null)
return 0;
return currentRecursionStack.size();
}
public Stack<T> getCurrentRecursionStack() {
return currentRecursionStack;
}
public RecursionHelper<T> start() {
currentRecursionStack = new Stack<T>();
recurseOn(startElement);
return this;
}
void recurseOn(T currentElement) {
if (currentElement == null)
return;
if (currentRecursionStack.contains(currentElement))
throw new RuntimeException("Circular recursion !");
currentRecursionStack.push(currentElement);
if (!depthFirst)
doActionOnElement(currentElement);
Collection<T> nextLevelElements = getRecursedElements(currentElement);
if (nextLevelElements != null) {
for (T nextLevelElement : getRecursedElements(currentElement)) {
recurseOn(nextLevelElement);
}
}
if (depthFirst)
doActionOnElement(currentElement);
currentRecursionStack.pop();
}
}