package org.mit.jstreamit;

/**
 * Visitor for StreamElements.
 * @author Jeffrey Bosboom <jeffreybosboom@gmail.com>
 * @since 11/22/2012
 */
public abstract class StreamVisitor {
	/**
	 * Visits a filter (stateless or stateful).
	 * @param filter a filter
	 */
	public abstract void visitFilter(Filter<?, ?> filter);

	/**
	 * Called when entering a pipeline. Implementations may return true to visit
	 * subelements of the pipeline or false to skip subelements. exitPipeline()
	 * will only be called if true is returned.
	 * @param pipeline a pipeline
	 * @return true to visit subelements, false to skip them
	 */
	public abstract boolean enterPipeline(Pipeline<?, ?> pipeline);

	/**
	 * Called when exiting a pipeline for which true was returned from the
	 * corresponding call to enterPipeline(). If false was returned, this method
	 * is not called.
	 * @param pipeline a pipeline
	 */
	public abstract void exitPipeline(Pipeline<?, ?> pipeline);

	/**
	 * Called when entering a splitjoin. Implementations may return true to
	 * visit subelements of the splitjoin or false to skip subelements.
	 * exitSplitjoin() will only be called if true is returned.
	 * @param splitjoin a splitjoin
	 * @return true to visit subelements, false to skip them
	 */
	public abstract boolean enterSplitjoin(Splitjoin<?, ?> splitjoin);

	/**
	 * Called when entering a splitjoin branch. Implementations may return true
	 * to visit the branch or false to skip it. exitSplitjoinBranch() will only
	 * be called if true is returned. Other branches of the splitjoin may be
	 * entered regardless of the return value.
	 * @param element a splitjoin branch
	 * @return true to visit the branch, false to skip it
	 */
	public abstract boolean enterSplitjoinBranch(OneToOneElement<?, ?> element);

	/**
	 * Called when exiting a splitjoin branch for which true was returned from
	 * the correspoding call to enterPipeline(). If false was returned, this
	 * method is not called.
	 * @param element a splitjoin branch
	 */
	public abstract void exitSplitjoinBranch(OneToOneElement<?, ?> element);

	/**
	 * Called when exiting a splitjoin for which true was returned from the
	 * corresponding call to enterSplitjoin(). If false was returned, this
	 * method is not called.
	 * @param splitjoin a splitjoin
	 */
	public abstract void exitSplitjoin(Splitjoin<?, ?> splitjoin);

	/**
	 * Visits a joiner.
	 * @param joiner a joiner
	 */
	public abstract void visitJoiner(Joiner<?, ?> joiner);

	/**
	 * Visits a splitter.
	 * @param splitter a splitter
	 */
	public abstract void visitSplitter(Splitter<?, ?> splitter);

	/**
	 * Called when visiting a stream element for which this visitor has not
	 * overridden the corresponding visit method. Implementations may return
	 * true if they wish to visit subelements of this element, false if they
	 * wish to skip this element and its subelements, or may throw an exception
	 * (the default).
	 * @param e the unknown element
	 * @return true to visit subelements, false to skip them
	 */
	public boolean visitUnknown(StreamElement<?, ?> e) {
		throw new UnsupportedOperationException(this.getClass().getSimpleName() + " visiting unknown element: " + e);
	}
}

@@ -1314,32 +1314,159 @@
 ?%3E splitjoin);%0A%0A
+%09/**%0A%09 * Visits a splitter.%0A%09 * @param splitter a splitter%0A%09 */%0A%09public abstract void visitSplitter(Splitter%3C?, ?%3E splitter);%0A%0A
 %09/**%0A%09 * Called 
@@ -2194,32 +2194,147 @@
 , ?%3E element);%0A%0A
+%09/**%0A%09 * Visits a joiner.%0A%09 * @param joiner a joiner%0A%09 */%0A%09public abstract void visitJoiner(Joiner%3C?, ?%3E joiner);%0A%0A
 %09/**%0A%09 * Called 
@@ -2600,250 +2600,8 @@
 );%0A%0A
-%09/**%0A%09 * Visits a joiner.%0A%09 * @param joiner a joiner%0A%09 */%0A%09public abstract void visitJoiner(Joiner%3C?, ?%3E joiner);%0A%0A%09/**%0A%09 * Visits a splitter.%0A%09 * @param splitter a splitter%0A%09 */%0A%09public abstract void visitSplitter(Splitter%3C?, ?%3E splitter);%0A%0A
 %09/**

Reorder StreamVisitor methods to better reflect visitation order