package bk; import java.lang.reflect.InvocationTargetException; import javax.swing.JFrame; import javax.swing.JTree; import animation.AlgorithmStage; import animation.AnimatedAlgorithm; import animation.AnimationController; import animation.PseudoCodeNode; 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 */ private 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; } @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.FINISHED ) status = forwardStep(); return status; } else return forward( "forwardStepOver" ); } @Override public StageStatus forwardStepOut() { if( !inside ) { StageStatus status = StageStatus.UNFINISHED; while( status != StageStatus.FINISHED ) 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.FINISHED ) status = backwardStep(); return status; } else return backward( "backwardStepOver" ); } @Override public StageStatus backwardStepOut() { if( !inside ) { StageStatus status = StageStatus.UNFINISHED; while( status != StageStatus.FINISHED ) status = backwardStep(); return status; } else return backward( "backwardStepOut" ); } private StageStatus forward( String fName ) { try { switch( state ) { case CONFLICTS: conflictsNode.setSelected( true ); if( (StageStatus)(ConflictDetection.class.getMethod( fName ).invoke( conftion ) ) == StageStatus.FINISHED ) { inside = false; conflictsNode.setSelected( false ); layout1Node.setSelected( true ); state = State.LAYOUT1; } else inside = true; break; case LAYOUT1: if( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 0 ] ) ) == StageStatus.FINISHED ) { inside = false; layout1Node.setSelected( false ); layout2Node.setSelected( true ); state = State.LAYOUT2; } else inside = true; break; case LAYOUT2: if( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 1 ] ) ) == StageStatus.FINISHED ) { inside = false; layout2Node.setSelected( false ); layout3Node.setSelected( true ); state = State.LAYOUT3; } else inside = true; break; case LAYOUT3: if( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 2 ] ) ) == StageStatus.FINISHED ) { inside = false; layout3Node.setSelected( false ); layout4Node.setSelected( true ); state = State.LAYOUT4; } else inside = true; break; case LAYOUT4: if( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 3 ] ) ) == StageStatus.FINISHED ) { inside = false; layout4Node.setSelected( false ); combineNode.setSelected( true ); state = State.COMBINE; } else inside = true; break; case COMBINE: if( (StageStatus)(Combine.class.getMethod( fName ).invoke( combine ) ) == StageStatus.FINISHED ) { inside = false; return StageStatus.FINISHED; } else inside = true; } } 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(); } return StageStatus.UNFINISHED; } private StageStatus backward( String fName ) { try { switch( state ) { case CONFLICTS: if( (StageStatus)(ConflictDetection.class.getMethod( fName ).invoke( conftion ) ) == StageStatus.FINISHED ) { inside = false; return StageStatus.FINISHED; } else inside = true; case LAYOUT1: if( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 0 ] ) ) == StageStatus.FINISHED ) { inside = false; layout1Node.setSelected( false ); conflictsNode.setSelected( true ); state = State.CONFLICTS; } else inside = true; break; case LAYOUT2: if( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 1 ] ) ) == AlgorithmStage.StageStatus.FINISHED ) { inside = false; layout2Node.setSelected( false ); layout1Node.setSelected( true ); state = State.LAYOUT1; } else inside = true; break; case LAYOUT3: if( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 2 ] ) ) == AlgorithmStage.StageStatus.FINISHED ) { inside = false; layout3Node.setSelected( false ); layout2Node.setSelected( true ); state = State.LAYOUT2; } else inside = true; break; case LAYOUT4: if( (StageStatus)(ExtremalLayoutCalc.class.getMethod( fName ).invoke( layouts[ 3 ] ) ) == AlgorithmStage.StageStatus.FINISHED ) { inside = false; layout4Node.setSelected( false ); layout3Node.setSelected( true ); state = State.LAYOUT3; } else inside = true; break; case COMBINE: if( (StageStatus)(Combine.class.getMethod( fName ).invoke( combine ) ) == AlgorithmStage.StageStatus.FINISHED ) { inside = false; combineNode.setSelected( false ); layout4Node.setSelected( true ); state = State.LAYOUT4; } else inside = true; 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(); } return StageStatus.UNFINISHED; } }