Skip to content

Instantly share code, notes, and snippets.

@UnquietCode
Created August 9, 2012 04:10
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save UnquietCode/3300868 to your computer and use it in GitHub Desktop.
Save UnquietCode/3300868 to your computer and use it in GitHub Desktop.
A simple traverser which handles recursive computations, specifically those where it is required to be aware of the previous, current, and next states.
/*******************************************************************************
Copyright 2012 Benjamin Fagin
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
******************************************************************************/
package unquietcode.tools.flapi.graph;
import java.util.Iterator;
/**
* A happy little class which manages the simple case of a traversal, where you would like
* to be aware of your current, previous, and next value. Some helper methods for determining
* the type and the nullity of a value are also provided.
*
* @param <_VisitorType> The type of visitor to be used.
* @param <_StateType> The base type of the state objects.
* @param <_ReturnValue> The value returned from the complete computation.
*/
public class StateTraverser<_VisitorType, _StateType extends StateTraverser.StateVisitorAware<_VisitorType>, _ReturnValue> {
protected _StateType previous, next;
private _StateType current;
private _ReturnValue initialValue;
private _ReturnValue returnValue;
private _VisitorType visitor;
private Iterator<_StateType> iterator;
public StateTraverser() {
// nothing
}
public StateTraverser(_VisitorType visitor) {
setVisitor(visitor);
}
public final _ReturnValue run(Iterator<_StateType> iterator) {
// setup
returnValue = initialValue;
this.iterator = iterator;
// compute
advance(); // we're technically 'before the start' when calling this
_ReturnValue retval = getReturnValue();
// cleanup
this.iterator = null;
previous = current = next = null;
returnValue = null;
return retval;
}
public final void setVisitor(_VisitorType visitor) {
this.visitor = visitor;
}
public final void setInitialValue(_ReturnValue initialValue) {
this.initialValue = initialValue;
}
private void advance() {
previous = current;
current = next;
if (iterator.hasNext()) {
next = iterator.next();
} else {
next = null;
}
}
protected final void setReturnValue(_ReturnValue value) {
returnValue = value;
}
protected final _ReturnValue getReturnValue() {
advance();
if (current != null) {
current.accept(visitor);
}
return returnValue;
}
// ---- - - - - - - - - ------------- - ---------- - - - -- - ----
@SuppressWarnings("unchecked")
protected static <T> T isType(Object object, Class<T> clazz) {
if (object == null) {
return null;
}
if (!clazz.isAssignableFrom(object.getClass())) {
throw new IllegalStateException(
"Object not of expected type. Was '"+object.getClass()+"' but expected '"+clazz+"'."
);
}
return (T) object;
}
protected static <T> T notNull(T object) {
if (object == null) {
throw new IllegalStateException("Object was expected to be non-null.");
}
return object;
}
protected static NullType isNull(Object object) {
if (object != null) {
throw new IllegalStateException(
"Object was expected to be null but was '"+object.getClass()+"' instead."
);
}
return NullType.getInstance();
}
// ---------------------------------------------------------------- //
public interface StateVisitorAware<_VisitorType> {
void accept(_VisitorType visitor);
}
protected static final class NullType {
private NullType() { }
public static final NullType INSTANCE = new NullType();
public static NullType getInstance() { return INSTANCE; }
}
}
/*******************************************************************************
Copyright 2012 Benjamin Fagin
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
******************************************************************************/
package unquietcode.tools.flapi.graph;
import java.util.ArrayList;
import java.util.List;
/**
* Simple test class for the {@link StateTraverser}.
*/
public class StateVisitorImpl extends StateTraverser<StateVisitorImpl, StateVisitorImpl.BaseType, String> {
public static void main(String[] args) {
List<BaseType> list = new ArrayList<BaseType>();
list.add(new TypeA());
list.add(new TypeA());
list.add(new TypeC());
StateVisitorImpl visitor = new StateVisitorImpl();
System.out.println("computed: " + visitor.run(list.iterator()));
}
public StateVisitorImpl() {
setVisitor(this);
setInitialValue("");
}
public void visit(TypeA type) {
visit(
previous,
type,
next
);
}
public void visit(TypeB type) {
visit(
isType(previous, TypeA.class),
type,
next
);
}
public void visit(TypeC type) {
visit(
isType(previous, TypeA.class),
type,
next
);
}
// --------- - - - ----- -- -- --------- -- - ----------- -
private void visit(BaseType previous, TypeA current, BaseType next) {
System.out.println("A type");
if (next == null) {
setReturnValue("A");
} else {
setReturnValue("A|" + getReturnValue());
}
}
private void visit(TypeA previous, TypeB current, BaseType next) {
System.out.println("B type");
if (next != null) {
throw new IllegalStateException("this should be the last state");
}
setReturnValue("B");
}
private void visit(TypeA previous, TypeC current, BaseType next) {
System.out.println("C type");
if (next != null) {
throw new IllegalStateException("this should be the last item");
}
setReturnValue("C");
}
// -------- - - - ---------- --- ----------- - - --------------
public abstract static class BaseType implements StateTraverser.StateVisitorAware<StateVisitorImpl> {
public abstract void accept(StateVisitorImpl visitor);
}
public static class TypeA extends BaseType {
public @Override void accept(StateVisitorImpl visitor) {
visitor.visit(this);
}
}
public static class TypeB extends BaseType {
public @Override void accept(StateVisitorImpl visitor) {
visitor.visit(this);
}
}
public static class TypeC extends BaseType {
public @Override void accept(StateVisitorImpl visitor) {
visitor.visit(this);
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment