package bk; import java.lang.reflect.InvocationTargetException; import javax.swing.JFrame; import javax.swing.JTree; import animation.AnimatedAlgorithm; import animation.AnimationController; import animation.PseudoCodeNode; import animation.PseudoCodeNode.CodeAction; import graph.LayeredGraphNode; /** * The main stage of the BK node placement algorithm. * @author kolja * */ public class BKNodePlacement extends AnimatedAlgorithm { /* * Private data structures to store the process of the algorithm */ public enum State { CONFLICTS, LAYOUT1, LAYOUT2, LAYOUT3, LAYOUT4, COMBINE } private ConflictDetection conftion; private State state; private ExtremalLayoutCalc layouts[]; private Combine combine; private PseudoCodeNode conflictsNode; private PseudoCodeNode layout1Node; private PseudoCodeNode layout2Node; private PseudoCodeNode layout3Node; private PseudoCodeNode layout4Node; private PseudoCodeNode combineNode; private boolean inside; public BKNodePlacement(AnimationController controller, LayeredGraphNode graph, JFrame view) { super(controller, graph, view); state = State.CONFLICTS; conftion = new ConflictDetection( graph ); layouts = new ExtremalLayoutCalc[ 4 ]; layouts[ 0 ] = new ExtremalLayoutCalc( ExtremalLayoutCalc.LayoutType.TOP_BOTTOM_LEFT, graph ); layouts[ 1 ] = new ExtremalLayoutCalc( ExtremalLayoutCalc.LayoutType.TOP_BOTTOM_RIGHT, graph ); layouts[ 2 ] = new ExtremalLayoutCalc( ExtremalLayoutCalc.LayoutType.BOTTOM_TOP_LEFT, graph ); layouts[ 3 ] = new ExtremalLayoutCalc( ExtremalLayoutCalc.LayoutType.BOTTOM_TOP_RIGHT, graph ); combine = new Combine( graph ); inside = false; } public State getAlgorithmState() { return state; } @Override public StageStatus forwardStep() { return forward( "forwardStep" ); } @Override public StageStatus backwardStep() { return backward( "backwardStep" ); } @Override public PseudoCodeNode createPseudocodeTree( JTree tree ) { PseudoCodeNode root = new PseudoCodeNode( "BK Node Placement Algorithm", tree ); root.setSelected( true ); conflictsNode = conftion.createPseudocodeTree( tree ); layout1Node = layouts[ 0 ].createPseudocodeTree( tree ); layout2Node = layouts[ 1 ].createPseudocodeTree( tree ); layout3Node = layouts[ 2 ].createPseudocodeTree( tree ); layout4Node = layouts[ 3 ].createPseudocodeTree( tree ); combineNode = combine.createPseudocodeTree( tree ); root.add( conflictsNode ); root.add( layout1Node ); root.add( layout2Node ); root.add( layout3Node ); root.add( layout4Node ); root.add( combineNode ); return root; } @Override public StageStatus forwardStepOver() { if( !inside ) { State oldState = state; StageStatus status = StageStatus.UNFINISHED; while( state == oldState && status == StageStatus.UNFINISHED ) status = forwardStep(); return status; } else return forward( "forwardStepOver" ); } @Override public StageStatus forwardStepOut() { if( !inside ) { StageStatus status = StageStatus.UNFINISHED; while( status == StageStatus.UNFINISHED ) status = forwardStep(); return status; } else return forward( "forwardStepOut" ); } @Override public StageStatus backwardStepOver() { if( !inside ) { State oldState = state; StageStatus status = StageStatus.UNFINISHED; while( state == oldState && status == StageStatus.UNFINISHED ) status = backwardStep(); return status; } else return backward( "backwardStepOver" ); } @Override public StageStatus backwardStepOut() { if( !inside ) { StageStatus status = StageStatus.UNFINISHED; while( status == StageStatus.UNFINISHED ) status = backwardStep(); return status; } else return backward( "backwardStepOut" ); } @Override public String getDebugString() { if( !inside ) return ""; switch( state ) { case CONFLICTS: return combine.getDebugString(); case LAYOUT1: return layouts[ 0 ].getDebugString(); case LAYOUT2: return layouts[ 1 ].getDebugString(); case LAYOUT3: return layouts[ 2 ].getDebugString(); case LAYOUT4: return layouts[ 3 ].getDebugString(); case COMBINE: return combine.getDebugString(); } return ""; } private StageStatus forward( String fName ) { boolean breakpoint = false; CodeAction action = null; try { switch( state ) { case CONFLICTS: action = conflictsNode.setSelected( true ); if( !conflictsNode.isSelected() ) breakpoint |= action == CodeAction.STOP; do { switch( (StageStatus)(ConflictDetection.class.getMethod( fName ).invoke( conftion ) ) ) { case FINISHED: inside = false; conflictsNode.setSelected( false ); CodeAction ca = layout1Node.setSelected( true ); breakpoint |= ca == CodeAction.STOP; state = State.LAYOUT1; if( ca == CodeAction.SKIP && !breakpoint ) return forward( fName ); break; case BREAKPOINT: inside = true; return StageStatus.BREAKPOINT; case UNFINISHED: inside = true; } } while( !breakpoint && action == CodeAction.SKIP ); break; case LAYOUT1: action = layout1Node.setSelected( true ); do { switch( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 0 ] ) ) ) { case FINISHED: inside = false; layout1Node.setSelected( false ); CodeAction ca = layout2Node.setSelected( true ); breakpoint |= ca == CodeAction.STOP; state = State.LAYOUT2; if( ca == CodeAction.SKIP && !breakpoint ) return forward( fName ); break; case BREAKPOINT: inside = true; return StageStatus.BREAKPOINT; case UNFINISHED: inside = true; } } while( !breakpoint && action == CodeAction.SKIP ); break; case LAYOUT2: action = layout2Node.setSelected( true ); do { switch( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 1 ] ) ) ) { case FINISHED: inside = false; layout2Node.setSelected( false ); CodeAction ca = layout3Node.setSelected( true ); breakpoint |= ca == CodeAction.STOP; state = State.LAYOUT3; if( ca == CodeAction.SKIP && !breakpoint ) return forward( fName ); break; case BREAKPOINT: inside = true; return StageStatus.BREAKPOINT; case UNFINISHED: inside = true; } } while( !breakpoint && action == CodeAction.SKIP ); break; case LAYOUT3: action = layout3Node.setSelected( true ); do { switch( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 2 ] ) ) ) { case FINISHED: inside = false; layout3Node.setSelected( false ); CodeAction ca = layout4Node.setSelected( true ); breakpoint |= ca == CodeAction.STOP; state = State.LAYOUT4; if( ca == CodeAction.SKIP && !breakpoint ) return forward( fName ); break; case BREAKPOINT: inside = true; return StageStatus.BREAKPOINT; case UNFINISHED: inside = true; } } while( !breakpoint && action == CodeAction.SKIP ); break; case LAYOUT4: action = layout4Node.setSelected( true ); do { switch( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 3 ] ) ) ) { case FINISHED: inside = false; layout4Node.setSelected( false ); CodeAction ca = combineNode.setSelected( true ); breakpoint |= ca == CodeAction.STOP; state = State.COMBINE; if( ca == CodeAction.SKIP && !breakpoint ) return forward( fName ); break; case BREAKPOINT: inside = true; return StageStatus.BREAKPOINT; case UNFINISHED: inside = true; } } while( !breakpoint && action == CodeAction.SKIP ); break; case COMBINE: action = combineNode.setSelected( true ); do { switch( (StageStatus)(Combine.class.getMethod( fName ).invoke( combine ) ) ) { case FINISHED: inside = false; return StageStatus.FINISHED; case BREAKPOINT: return StageStatus.BREAKPOINT; case UNFINISHED: inside = true; } } while( !breakpoint && action == CodeAction.SKIP ); } } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } if( breakpoint ) return StageStatus.BREAKPOINT; return StageStatus.UNFINISHED; } private StageStatus backward( String fName ) { boolean breakpoint = false; CodeAction action = null; try { switch( state ) { case CONFLICTS: action = conflictsNode.setSelected( true ); do { switch( (StageStatus)(ConflictDetection.class.getMethod( fName ).invoke( conftion ) ) ) { case FINISHED: inside = false; return StageStatus.FINISHED; case BREAKPOINT: inside = true; return StageStatus.BREAKPOINT; case UNFINISHED: inside = true; } } while( !breakpoint && action == CodeAction.SKIP ); case LAYOUT1: action = layout1Node.setSelected( true ); do { switch( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 0 ] ) ) ) { case FINISHED: inside = false; layout1Node.setSelected( false ); CodeAction ca = conflictsNode.setSelected( true ); breakpoint |= ca == CodeAction.STOP; state = State.CONFLICTS; if( ca == CodeAction.SKIP && !breakpoint ) return backward( fName ); break; case BREAKPOINT: inside = true; return StageStatus.BREAKPOINT; case UNFINISHED: inside = true; } } while( !breakpoint && action == CodeAction.SKIP ); break; case LAYOUT2: action = layout2Node.setSelected( true ); do { switch( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 1 ] ) ) ) { case FINISHED: inside = false; layout2Node.setSelected( false ); CodeAction ca = layout1Node.setSelected( true ); breakpoint |= ca == CodeAction.STOP; state = State.LAYOUT1; if( ca == CodeAction.SKIP && !breakpoint ) return backward( fName ); break; case BREAKPOINT: inside = true; return StageStatus.BREAKPOINT; case UNFINISHED: inside = true; } } while( !breakpoint && action == CodeAction.SKIP ); break; case LAYOUT3: action = layout3Node.setSelected( true ); do { switch( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 2 ] ) ) ) { case FINISHED: inside = false; layout3Node.setSelected( false ); CodeAction ca = layout2Node.setSelected( true ); breakpoint |= ca == CodeAction.STOP; state = State.LAYOUT2; if( ca == CodeAction.SKIP && !breakpoint ) return backward( fName ); break; case BREAKPOINT: inside = true; return StageStatus.BREAKPOINT; case UNFINISHED: inside = true; } } while( !breakpoint && action == CodeAction.SKIP ); break; case LAYOUT4: action = layout4Node.setSelected( true ); do { switch( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 3 ] ) ) ) { case FINISHED: inside = false; layout4Node.setSelected( false ); CodeAction ca = layout3Node.setSelected( true ); breakpoint |= ca == CodeAction.STOP; state = State.LAYOUT3; if( ca == CodeAction.SKIP && !breakpoint ) return backward( fName ); break; case BREAKPOINT: inside = true; return StageStatus.BREAKPOINT; case UNFINISHED: inside = true; } } while( !breakpoint && action == CodeAction.SKIP ); break; case COMBINE: action = combineNode.setSelected( true ); do { switch( (StageStatus)(Combine.class.getMethod( fName ).invoke( combine ) ) ) { case FINISHED: inside = false; combineNode.setSelected( false ); CodeAction ca = layout4Node.setSelected( true ); breakpoint |= ca == CodeAction.STOP; state = State.LAYOUT4; if( ca == CodeAction.SKIP && !breakpoint ) return backward( fName ); break; case BREAKPOINT: inside = true; return StageStatus.BREAKPOINT; case UNFINISHED: inside = true; } } while( !breakpoint && action == CodeAction.SKIP ); break; } } catch (IllegalAccessException e) { e.printStackTrace(); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (InvocationTargetException e) { e.printStackTrace(); } catch (NoSuchMethodException e) { e.printStackTrace(); } catch (SecurityException e) { e.printStackTrace(); } if( breakpoint ) return StageStatus.BREAKPOINT; return StageStatus.UNFINISHED; } }