/*
* Copyright 2005-2010 Ignis Software Tools Ltd. All rights reserved.
*/
package jsystem.framework.report;
import java.util.Stack;
import java.util.logging.Logger;
import jsystem.framework.scenario.JTest;
import jsystem.framework.scenario.JTestContainer;
import jsystem.framework.scenario.RunnerTest;
import jsystem.framework.scenario.flow_control.AntForLoop;
import jsystem.framework.scenario.flow_control.AntIfElse;
import jsystem.framework.scenario.flow_control.AntIfElseIf;
import jsystem.framework.scenario.flow_control.AntSwitchCase;
import jsystem.framework.scenario.flow_control.AntSwitchDefault;
/**
* used to analyze a test start and create events on containers starting and ending
*
* @author Nizan Freedman
*
*/
public class EventParser {
private Logger log = Logger.getLogger(EventParser.class.getName());
private Stack<LoopHandler> loopStack;
private Stack<JTestContainer> containersStack;
private boolean loopWasClosed;
RunnerListenersManager manager;
public EventParser(RunnerListenersManager manager){
this.manager = manager;
init();
}
public void init(){
loopStack = new Stack<LoopHandler>();
containersStack = new Stack<JTestContainer>();
}
/**
* notify EventParser on test start<br>
* the parser analyzes the containers start and end and sends the appropriate events back to RunnerListenersManager
*
* @param test the RunnerTest that started
*/
public void startTest(RunnerTest test){
JTestContainer container = test.getParent();
try{
notifyOnAllContainers(container,test,true);
}catch (Exception e) {
log.warning("Failed creating correct hierarchical reports");
}
}
/**
* create notify events on opening and closing of containers
*
* @param container
*/
private void notifyOnAllContainers(JTestContainer container, JTest test, boolean checkForLoopStart){
if (container == null){
return;
}
boolean checkParentForLoop = true;
/**
* if a new loop is starting, check if increase loop number.
* if loop counter is too big (loop number is greater then the loop values,
* signal closing of all container and start a new loop of parent loop.
* if the loop counter is OK, start a new loop.
*/
if (checkForLoopStart && checkIfLoopStart(test)){
checkParentForLoop = false;
LoopHandler handler = loopStack.peek();
AntForLoop loop = handler.getLoop();
int counter = handler.getCurrentLoopNumber();
int loopNum = loop.getNumOfLoops();
if (loopNum > -1 && loopNum <= counter){ // for finished
loopStack.pop();
loop = loopStack.peek().getLoop();
loopStack.push(handler);
notifyOnContainersClosing(loop);
notifyOnAllContainers(test.getParent(), test,true);
return;
}
handler.startNewLoop();
restartLoop(loop, counter);
}
/**
* close all finished containers
*/
if (containersStack.contains(container)){
notifyOnContainersClosing(container);
if (loopWasClosed){ // check if current loop starts a new loop
notifyOnAllContainers(container, test, true);
}
}
/**
* if container is new first add all new parents and then itself
*/
else {
notifyOnAllContainers(container.getParent(),container,checkParentForLoop);
startContainer(container);
if (container instanceof AntForLoop){
LoopHandler handler = new LoopHandler((AntForLoop)container,test);
loopStack.push(handler);
manager.startLoop((AntForLoop)container,1);
}
}
}
/**
* send notifications that a loop has restarted (ended and started again)<br>
* 1) send end loop number<br>
* 2) close all relevant containers<br>
* 3) send start loop number
*
* @param loop the AntForLoop object
* @param counter loop number
*/
private void restartLoop(AntForLoop loop, int counter){
manager.endLoop(loop,counter);
notifyOnContainersClosing(loop);
manager.startLoop(loop,counter+1);
}
/**
* check if the test is the first in a new loop
* @param test the test to check
* @return
*/
private boolean checkIfLoopStart(JTest test){
if (loopStack.size() == 0){
return false;
}
LoopHandler handler = loopStack.peek();
if (test instanceof AntSwitchCase || test instanceof AntSwitchDefault || test instanceof AntIfElse ||test instanceof AntIfElseIf){
return handler.isLoopStart(test.getParent());
}
return handler.isLoopStart(test);
}
private void startContainer(JTestContainer container){
manager.startContainer(container);
containersStack.push(container);
}
/**
* close ended containers
*
* @param container
*/
private void notifyOnContainersClosing(JTestContainer container){
loopWasClosed = false;
while (!containersStack.peek().equals(container)){
JTestContainer closedContainer = containersStack.pop();
if (closedContainer instanceof AntForLoop){
LoopHandler handler = loopStack.pop();
manager.endLoop((AntForLoop)closedContainer,handler.getCurrentLoopNumber());
loopWasClosed = true;
}
manager.endContainer(closedContainer);
}
}
/**
* close all open containers
*/
public void closeAllContainers(){
while (!containersStack.isEmpty()){
manager.endContainer(containersStack.pop());
}
init();
}
}
/**
* used for counting loop numbers
*
* @author Nizan Freedman
*
*/
class LoopHandler{
int counter = 1;
JTest firstLoopTest;
AntForLoop loop;
public LoopHandler(AntForLoop loop, JTest firstLoopTest){
this.loop = loop;
this.firstLoopTest = firstLoopTest;
}
public int startNewLoop(){
return ++counter;
}
public boolean isLoopStart(JTest test){
return firstLoopTest.equals(test);
}
public int getCurrentLoopNumber(){
return counter;
}
public AntForLoop getLoop() {
return loop;
}
}