/*
* Demoiselle Framework
* Copyright (C) 2013 SERPRO
* ----------------------------------------------------------------------------
* This file is part of Demoiselle Framework.
*
* Demoiselle Framework is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public License version 3
* as published by the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License version 3
* along with this program; if not, see <http://www.gnu.org/licenses/>
* or write to the Free Software Foundation, Inc., 51 Franklin Street,
* Fifth Floor, Boston, MA 02110-1301, USA.
* ----------------------------------------------------------------------------
* Este arquivo é parte do Framework Demoiselle.
*
* O Framework Demoiselle é um software livre; você pode redistribuí-lo e/ou
* modificá-lo dentro dos termos da GNU LGPL versão 3 como publicada pela Fundação
* do Software Livre (FSF).
*
* Este programa é distribuído na esperança que possa ser útil, mas SEM NENHUMA
* GARANTIA; sem uma garantia implícita de ADEQUAÇÃO a qualquer MERCADO ou
* APLICAÇÃO EM PARTICULAR. Veja a Licença Pública Geral GNU/LGPL em português
* para maiores detalhes.
*
* Você deve ter recebido uma cópia da GNU LGPL versão 3, sob o título
* "LICENCA.txt", junto com esse programa. Se não, acesse <http://www.gnu.org/licenses/>
* ou escreva para a Fundação do Software Livre (FSF) Inc.,
* 51 Franklin St, Fifth Floor, Boston, MA 02111-1301, USA.
*/
package br.gov.frameworkdemoiselle.behave.controller;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
import org.apache.log4j.Logger;
import org.junit.Assert;
import br.gov.frameworkdemoiselle.behave.config.BehaveConfig;
import br.gov.frameworkdemoiselle.behave.exception.BehaveException;
import br.gov.frameworkdemoiselle.behave.internal.filter.StepsFilter;
import br.gov.frameworkdemoiselle.behave.internal.filter.StoryOrScenarioFilter;
import br.gov.frameworkdemoiselle.behave.internal.parser.StoryFileConverter;
import br.gov.frameworkdemoiselle.behave.internal.spi.InjectionManager;
import br.gov.frameworkdemoiselle.behave.message.BehaveMessage;
import br.gov.frameworkdemoiselle.behave.parser.Parser;
import br.gov.frameworkdemoiselle.behave.parser.Step;
/**
*
* @author SERPRO
*
*/
public class BehaveContext {
public static final BehaveContext instance = new BehaveContext();
private Parser parser;
private static Logger log = Logger.getLogger(BehaveContext.class);
private ArrayList<String> allOriginalStoriesPath = new ArrayList<String>();
private StoryOrScenarioFilter storyOrScenarioFilter = null;
private List<Step> steps = new ArrayList<Step>();
private List<String> storiesPath = new ArrayList<String>();
private List<String> storiesReusePath = new ArrayList<String>();
private List<Step> stepsGlobal = new ArrayList<Step>();
private List<String> storiesPathGlobal = new ArrayList<String>();
private List<String> storiesReusePathGlobal = new ArrayList<String>();
private List<Step> stepsClass = new ArrayList<Step>();
private List<String> storiesPathClass = new ArrayList<String>();
private List<String> storiesReusePathClass = new ArrayList<String>();
private List<Step> stepsMethod = new ArrayList<Step>();
private List<String> storiesPathMethod = new ArrayList<String>();
private List<String> storiesReusePathMethod = new ArrayList<String>();
private Throwable fail;
private String failStep;
private String currentScenario = "";
private BehaveMessage bm;
private BehaveContext() {
bm = new BehaveMessage(BehaveConfig.MESSAGEBUNDLE);
}
private void checkClassScopeManagerExtension(){
//String classname = sun.reflect.Reflection.getCallerClass(3).getSuperclass().getName();
//System.out.println(classname);
String str = Thread.currentThread().getStackTrace()[3].getClassName();
Class<?> myClass = null;
try {
myClass = Class.forName(str);
} catch (ClassNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
//System.out.println(str);
//Class myclass = sun.reflect.Reflection.getCallerClass(3).getSuperclass();
if (!ClassScopeManager.class.isAssignableFrom(myClass))
throw new BehaveException(bm.getString("exception-legacyRunner-classScopeManager-missing"));
}
public static BehaveContext getInstance() {
return instance;
}
public void addSteps(Step step) {
if (BehaveConfig.getRunner_LegacyRunner())
steps.add(step);
else
throw new BehaveException(bm.getString("exception-legacyRunner-true"));
}
public List<Step> getSteps() {
return steps;
}
public void addStepsGlobal(Step step) {
if (!BehaveConfig.getRunner_LegacyRunner())
stepsGlobal.add(step);
else
throw new BehaveException(bm.getString("exception-legacyRunner-false"));
}
public List<Step> getStepsGlobal() {
if (!BehaveConfig.getRunner_LegacyRunner())
return stepsGlobal;
else
throw new BehaveException(bm.getString("exception-legacyRunner-false"));
}
public void addStepsClass(Step step) {
if (!BehaveConfig.getRunner_LegacyRunner()){
checkClassScopeManagerExtension();
stepsClass.add(step);
}else
throw new BehaveException(bm.getString("exception-legacyRunner-false"));
}
public List<Step> getStepsClass() {
if (!BehaveConfig.getRunner_LegacyRunner())
return stepsClass;
else
throw new BehaveException(bm.getString("exception-legacyRunner-false"));
}
public void addStepsMethod(Step step) {
if (!BehaveConfig.getRunner_LegacyRunner())
stepsMethod.add(step);
else
throw new BehaveException(bm.getString("exception-legacyRunner-false"));
}
public List<Step> getStepsMethod() {
if (!BehaveConfig.getRunner_LegacyRunner())
return stepsGlobal;
else
throw new BehaveException(bm.getString("exception-legacyRunner-false"));
}
// Métodos para rodar o teste
public void run(List<String> storiesFiles) {
try {
log.info("--------------------------------");
log.info(bm.getString("message-behave-start"));
log.info("Demoiselle Behave " + BehaveConfig.getProperty("behave.version"));
log.info("--------------------------------");
BehaveConfig.logValueProperties();
// comportamento novo, suporte à escopos
if (!BehaveConfig.getRunner_LegacyRunner()){
steps.addAll(stepsGlobal);
steps.addAll(stepsClass);
steps.addAll(stepsMethod);
storiesFiles.addAll(storiesPathGlobal);
storiesFiles.addAll(storiesPathClass);
storiesFiles.addAll(storiesPathMethod);
storiesReusePath.addAll(storiesReusePathGlobal);
storiesReusePath.addAll(storiesReusePathClass);
storiesReusePath.addAll(storiesReusePathMethod);
}
if (storiesFiles == null || storiesFiles.isEmpty()) {
throw new BehaveException(bm.getString("exception-empty-story-list"));
}
// Correção de bug: Substitui as barras por File.separator para
// funcionar de acordo com o SO
ArrayList<String> listNewPaths = new ArrayList<String>();
for (String s : storiesFiles) {
listNewPaths.add(s.replace("\\", File.separator).replace("/", File.separator));
}
// Adiciono as novas histórias no array com TODAS, inclusive as da
// execução anterior
allOriginalStoriesPath.addAll(listNewPaths);
// Lista de historias só para reuso de cenários
ArrayList<String> listNewPathsReuse = new ArrayList<String>();
for (String s : storiesReusePath) {
listNewPathsReuse.add(s.replace("\\", File.separator).replace("/", File.separator));
}
// Adiciono as novas historias só para reuso de cenários
allOriginalStoriesPath.addAll(listNewPathsReuse);
// Faz a conversão
List<String> allStoriesConverted = StoryFileConverter.convertReusedScenarios(allOriginalStoriesPath, BehaveConfig.getParser_OriginalStoryFileExtension(), BehaveConfig.getParser_ConvertedStoryFileExtension(), true);
// Cria um novo array contendo somente as histórias atuais
// Correção de bug: Quando a história é explicitamente enviada novamente ao run ela tem que rodar
// Correção de bug: Quando existe reutilização de história ele alterava a ordem da execução atual de acordo com a reutilização
List<String> finalArray = new ArrayList<String>();
for (String storyFile : listNewPaths) {
for (String storyFileC : allStoriesConverted) {
if (storyFileC.contains(storyFile)) {
finalArray.add(storyFileC);
}
}
}
// Roda o runner com as histórias convertidas
parser = (Parser) InjectionManager.getInstance().getInstanceDependecy(Parser.class);
// parser.setSteps(steps); // Na versão 3.9 do JBehave foi alterada a ordem de carregamento dos steps
parser.setStoryPaths(finalArray);
parser.run();
if (fail != null) {
Assert.fail(bm.getString("exception-fail-step", failStep, fail.getMessage()));
}
} catch (BehaveException ex) {
log.error(bm.getString("exception-general"), ex);
throw ex;
} finally {
fail = null;
failStep = null;
storyOrScenarioFilter = null;
storiesPath.clear();
storiesReusePath.clear();
steps.clear();
// comportamento novo, suporte à escopos
if (!BehaveConfig.getRunner_LegacyRunner()){
allOriginalStoriesPath.clear();
stepsMethod.clear();
storiesPathMethod.clear();
storiesReusePathMethod.clear();
}
log.info("--------------------------------");
log.info(bm.getString("message-behave-end"));
log.info("--------------------------------");
}
}
public void run(String storiesPath) {
ArrayList<String> stories = new ArrayList<String>();
stories.add(storiesPath);
run(stories);
}
public void run() {
run(storiesPath);
}
public void run(String storiesPath, StoryOrScenarioFilter storyOrScenarioFilter) {
setStoryOrScenarioFilter(storyOrScenarioFilter);
run(storiesPath);
}
public void runWithScenarioFilter(String storiesPath, String scenarioFilter) {
run(storiesPath, StoryOrScenarioFilter.scenario(scenarioFilter));
}
public void runWithStoryFilter(String storiesPath, String storyFilter) {
run(storiesPath, StoryOrScenarioFilter.story(storyFilter));
}
public BehaveContext addStories(String storiesPath) {
if (BehaveConfig.getRunner_LegacyRunner()){
log.debug("addStories:" + storiesPath);
this.storiesPath.add(storiesPath);
return this;
}else
throw new BehaveException(bm.getString("exception-legacyRunner-true"));
}
public BehaveContext addStoriesGlobal(String storiesPath) {
if (!BehaveConfig.getRunner_LegacyRunner()){
log.debug("addStoriesGlobal:" + storiesPath);
this.storiesPathGlobal.add(storiesPath);
return this;
}else
throw new BehaveException(bm.getString("exception-legacyRunner-false"));
}
public BehaveContext addStoriesClass(String storiesPath) {
if (!BehaveConfig.getRunner_LegacyRunner()){
checkClassScopeManagerExtension();
log.debug("addStoriesClass:" + storiesPath);
this.storiesPathClass.add(storiesPath);
return this;
}else
throw new BehaveException(bm.getString("exception-legacyRunner-false"));
}
public List<String> getStoriesClass() {
if (!BehaveConfig.getRunner_LegacyRunner()){
return storiesPathClass;
}else
throw new BehaveException(bm.getString("exception-legacyRunner-false"));
}
public BehaveContext addStoriesMethod(String storiesPath) {
if (!BehaveConfig.getRunner_LegacyRunner()){
log.debug("addStoriesMethod:" + storiesPath);
this.storiesPathMethod.add(storiesPath);
return this;
}else
throw new BehaveException(bm.getString("exception-legacyRunner-false"));
}
public BehaveContext addStoriesReuse(String storiesPath) {
if (BehaveConfig.getRunner_LegacyRunner()){
log.debug("addStoriesReuse:" + storiesPath);
this.storiesReusePath.add(storiesPath);
return this;
}else
throw new BehaveException(bm.getString("exception-legacyRunner-true"));
}
public BehaveContext addStoriesReuseGlobal(String storiesPath) {
if (!BehaveConfig.getRunner_LegacyRunner()){
log.debug("addStoriesReuseGlobal:" + storiesPath);
this.storiesReusePathGlobal.add(storiesPath);
return this;
}else
throw new BehaveException(bm.getString("exception-legacyRunner-false"));
}
public BehaveContext addStoriesReuseClass(String storiesPath) {
if (!BehaveConfig.getRunner_LegacyRunner()){
checkClassScopeManagerExtension();
log.debug("addStoriesReuseClass:" + storiesPath);
this.storiesReusePathClass.add(storiesPath);
return this;
}else
throw new BehaveException(bm.getString("exception-legacyRunner-false"));
}
public List<String> getStoriesReuseClass() {
if (!BehaveConfig.getRunner_LegacyRunner()){
return storiesReusePathClass;
}else
throw new BehaveException(bm.getString("exception-legacyRunner-false"));
}
public BehaveContext addStoriesReuseMethod(String storiesPath) {
if (!BehaveConfig.getRunner_LegacyRunner()){
log.debug("addStoriesReuseMethod:" + storiesPath);
this.storiesReusePathMethod.add(storiesPath);
return this;
}else
throw new BehaveException(bm.getString("exception-legacyRunner-false"));
}
public String getCurrentScenario() {
return this.currentScenario;
}
public void setCurrentScenario(String scenario) {
this.currentScenario = scenario;
}
public void fail(String step, Throwable fail) {
this.failStep = step;
this.fail = fail;
}
public void clearAllOriginalStories() {
if (BehaveConfig.getRunner_LegacyRunner())
allOriginalStoriesPath.clear();
else
throw new BehaveException(bm.getString("exception-legacyRunner-true"));
}
// Seleciona o filtro para História OU Cenário
public void setStoryOrScenarioFilter(StoryOrScenarioFilter filter) {
this.storyOrScenarioFilter = filter;
}
public StoryOrScenarioFilter getStoryOrScenarioFilter() {
return this.storyOrScenarioFilter;
}
// Métodos para tratamento de filtro nos Steps
public void setStepsPackage(String name) {
steps.addAll(StepsFilter.scanPackage(name, new Class[] {}));
}
public void setStepsPackage(String name, String excludes) {
steps.addAll(StepsFilter.scanPackage(name, excludes));
}
@SuppressWarnings("rawtypes")
public void setStepsPackage(String name, Class... excludes) {
steps.addAll(StepsFilter.scanPackage(name, excludes));
}
}