/**
* Copyright 2015 Santhosh Kumar Tekuri
*
* The JLibs authors license this file to you 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 jlibs.core.graph.walkers;
import jlibs.core.graph.*;
import jlibs.core.graph.sequences.AbstractSequence;
import jlibs.core.graph.sequences.DuplicateSequence;
import jlibs.core.graph.sequences.EmptySequence;
import jlibs.core.graph.sequences.EnumeratedSequence;
import javax.swing.*;
import javax.swing.tree.DefaultMutableTreeNode;
import java.util.Stack;
/**
* @author Santhosh Kumar T
*/
public class PreorderWalker<E> extends AbstractSequence<E> implements Walker<E>{
private Sequence<? extends E> seq;
private Navigator<E> navigator;
public PreorderWalker(Sequence<? extends E> seq, Navigator<E> navigator){
this.seq = seq;
this.navigator = navigator;
_reset();
}
public PreorderWalker(E elem, Navigator<E> navigator){
this(new DuplicateSequence<E>(elem), navigator);
}
/*-------------------------------------------------[ Reuse ]---------------------------------------------------*/
@Override
public void reset(){
super.reset();
_reset();
}
private void _reset(){
path = null;
stack.clear();
stack.push(new Children(seq.copy()));
}
@Override
public PreorderWalker<E> copy(){
return new PreorderWalker<E>(seq.copy(), navigator);
}
/*-------------------------------------------------[ Reuse ]---------------------------------------------------*/
private Stack<Children> stack = new Stack<Children>();
private Path path;
private class Children{
boolean breakpoint;
Sequence<? extends E> seq;
public Children(Sequence<? extends E> seq){
this.seq = seq;
}
}
@Override
protected E findNext(){
// pop empty sequences
while(!stack.isEmpty()){
Children elem = stack.peek();
if(elem.seq.next()==null){
if(elem.breakpoint)
return null;
else{
stack.pop();
if(path!=null)
path = path.getParentPath();
}
}else
break;
}
if(stack.isEmpty())
return null;
else{
Sequence<? extends E> peekSeq = stack.peek().seq;
E current = peekSeq.current();
path = path==null ? new Path(current) : path.append(current, peekSeq.index());
path.lastElem = !peekSeq.hasNext();
stack.push(new Children(navigator.children(current)));
return current;
}
}
/*-------------------------------------------------[ Walker ]---------------------------------------------------*/
public Path getCurrentPath(){
return path;
}
public void skip(){
if(stack.isEmpty())
throw new IllegalStateException("can't skip of descendants of null");
stack.peek().seq = EmptySequence.getInstance();
}
public void addBreakpoint(){
if(stack.isEmpty())
throw new IllegalStateException("can't add breakpoint on empty sequence");
stack.peek().breakpoint = true;
}
public boolean isPaused(){
return !stack.isEmpty() && stack.peek().breakpoint;
}
@SuppressWarnings("unchecked")
public void resume(){
if(isPaused()){
stack.peek().breakpoint = false;
current.set(current.index()-1, (E)path.getElement());
}
}
public static void main(String[] args){
Class<Number> c1 = Number.class;
Class<Integer> c2 = Integer.class;
System.out.println(c1.isAssignableFrom(c2));
System.out.println(c1.isAssignableFrom(c2));
JFrame frame = new JFrame();
JTree tree = new JTree();
frame.getContentPane().add(new JScrollPane(tree));
frame.pack();
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setVisible(true);
final PreorderWalker<DefaultMutableTreeNode> seq = new PreorderWalker<DefaultMutableTreeNode>((DefaultMutableTreeNode)tree.getModel().getRoot(), new Navigator<DefaultMutableTreeNode>(){
@Override
@SuppressWarnings({"unchecked"})
public Sequence<DefaultMutableTreeNode> children(DefaultMutableTreeNode elem){
return new EnumeratedSequence<DefaultMutableTreeNode>(elem.children());
}
});
WalkerUtil.print(seq, null);
}
}