/* * Copyright 2005-2010 Ignis Software Tools Ltd. All rights reserved. */ package jsystem.framework.scenario.flow_control; import java.util.ArrayList; import java.util.HashMap; import java.util.Properties; import java.util.logging.Level; import java.util.regex.Matcher; import jsystem.framework.common.CommonResources; import jsystem.framework.report.RunnerListenersManager; import jsystem.framework.scenario.JTest; import jsystem.framework.scenario.JTestContainer; import jsystem.framework.scenario.Parameter; import jsystem.framework.scenario.ParameterUtils; import jsystem.framework.scenario.ParametersManager; import jsystem.framework.scenario.RunnerFixture; import jsystem.framework.scenario.RunnerTest; import jsystem.framework.scenario.RunningProperties; import jsystem.framework.scenario.Scenario; import jsystem.framework.scenario.ScenarioHelpers; import jsystem.utils.FileUtils; import jsystem.utils.StringUtils; import jsystem.utils.XmlUtils; import junit.framework.TestResult; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * AntFlowControl is an abstract class for all of the Ant flow control classes, defining * the basic implementation. * * @author Shushu */ public abstract class AntFlowControl extends JTestContainer { /* * Flow control has its own parameters... */ protected HashMap<String, Parameter> parameters = new HashMap<String, Parameter>(); public AntFlowControl() { } public AntFlowControl (String name, JTestContainer parent, String id) { super(name, parent, id,getRandomUUID()); } /* (non-Javadoc) * @see jsystem.framework.scenario.JTest#load() * TODO: in global, this load() suppose to be similar to the Scenario's one, with some changes * It suppose to fill all of the allTests from the already defined content (XML ?) */ @Override public void load() throws Exception { // TODO Auto-generated method stub } /* (non-Javadoc) * @see jsystem.framework.scenario.JTest#setTestClassParameters() */ @Override public void setTestClassParameters() { // TODO Auto-generated method stub } /* (non-Javadoc) * @see jsystem.framework.scenario.JTest#setXmlFields(java.util.Properties) */ @Override public void setXmlFields(Properties fields) { // TODO: this feature seems to be relevant only for import mechanism, // which is not supported for flow control for now. throw new RuntimeException("setXmlFields method should not be called"); } /* (non-Javadoc) * @see junit.framework.Test#run(junit.framework.TestResult) */ @Override public void run(TestResult arg0) { // Flow control cannot be executed by itself (like Scenario can't) throw new RuntimeException("Flow control run should not be invoked"); } /* Gets a chunk of XML, and return a new AntFlowControl object * TODO: Maybe should be abstract and implemented separately */ public static AntFlowControl fromElement( Element parentScenarioCallingTarget, Element scenarioElementTarget, Object object, Scenario scenario) { // TODO Auto-generated method stub return null; } /** * get all tests parameters * * @param doFilter get only visible parameters * @return */ protected Parameter[] getParameters(boolean doFilter, boolean recursive) { ArrayList<Parameter> allParams = new ArrayList<Parameter>(); for (Parameter param : getFlowControlParams().values()) { allParams.add(param); } Parameter[] paramsArray = new Parameter[allParams.size()]; return (allParams.toArray(paramsArray)); } /** * Get all test parameters * * @param doFilter True will filter parameters that are not visible * @param recursive will go recursively into all sub-scenarios\containers * @return all Parameters array */ public Parameter[] getTestParameters(boolean doFilter,boolean recursive){ return getTestParameters(doFilter, recursive,false); } /** * Get all test parameters * * @param doFilter True will filter parameters that are not visible * @param recursive will go recursively into all sub-scenarios\containers * @param includingFlow if True then flow parameters will also be returned * @return all Parameters array */ public Parameter[] getTestParameters(boolean doFilter,boolean recursive, boolean includingFlow){ ArrayList<Parameter> allParams = new ArrayList<Parameter>(); if (includingFlow){ for (Parameter param : getFlowControlParams().values()) { allParams.add(param); } } // Get all of the parameters except to the control flow ones for (Parameter param : super.getParameters(doFilter,recursive)) { allParams.add(param); } return (allParams.toArray(new Parameter[0])); } private HashMap<String, Parameter> getFlowControlParams() { return parameters; } protected void setFlowControlParameters(Parameter[] params) { for (Parameter givenParameter : params) { if ((!givenParameter.isDirty()) || (givenParameter.getValue() == null)) { continue; } Parameter originalParameter = parameters.get(givenParameter.getName()); if (originalParameter == null){ continue; } Object value = givenParameter.getValue(); originalParameter.signalToSave(); originalParameter.setValue(value); } } /* * (non-Javadoc) * @see jsystem.framework.scenario.JTestContainer#setParameters(jsystem.framework.scenario.Parameter[]) * + first set the flow control parameters, and only then the other params */ public void setParameters(Parameter[] params, boolean recursively) { Parameter[] before = ParameterUtils.clone(getParameters()); Parameter[] after = ParameterUtils.clone(params); setFlowControlParameters(params); RunnerListenersManager.getInstance().testParametersChanged(getFlowFullUUID(), before,after); setTestComment(defaultComment()); } protected void addParameter(Parameter parameter) { this.parameters.put(parameter.getName(), parameter); } protected void updateScenarioPropertiesFile(){ Scenario r = (Scenario) getRoot(); ScenarioHelpers.updateTestProperties(getFlowFullUUID() + ".", getParameters(), r.getName(), true); } // TODO: maybe move to JTestContainer public void addTestsXmlToRoot(Document doc, Integer[] indexes) { updateScenarioPropertiesFile(); for (JTest jtest : rootTests) { String targetName = null; if (jtest instanceof RunnerFixture) { targetName = "f" + indexes[0] + "_" + ((RunnerFixture) jtest).getClassName(); indexes[0]++; jtest.setTestId(targetName); } else if ((jtest instanceof RunnerTest) || (jtest instanceof Scenario)) { targetName = "t" + indexes[1]; indexes[1]++; jtest.setTestId(targetName); } //appending test target to xml jtest.addTestsXmlToRoot(doc, indexes); } } public String getFullUUID() { return getParentFullUUID(); } /** * get the fullUuid (similar to RunnerTest\Scenario fullUuid) * * @return */ public String getFlowFullUUID(){ return super.getFullUUID(); } /** * Since Flow has no Unique ID in Ant context, * It should not have a unique ID in model too */ public String getUUIDUpTo(JTest toStopAt){ return getParent().getUUIDUpTo(toStopAt); } public String getFullTestId() { return getParent().getFullTestId(); } public abstract String defaultComment(); @Override public void addAntPropertiesToTarget(Element ant, Document doc) { for (Object testObject : rootTests) { JTest test = (JTest)testObject; test.addAntPropertiesToTarget(ant, doc); } } /** * Appends flow control entity additional properties * (for now it is only meaningful name) as an element comment. */ public void appendAdditionalData(Element element) { StringBuffer buffer = new StringBuffer(); buffer.append("#Jsystem#"); serializeMeaningfulName(buffer); XmlUtils.appendComment(element,buffer.toString()); } /** * Reads additional properties from element comment */ public static void deserializeAdditionalData(JTestContainer container,Element element) { String comment = XmlUtils.getComment(element, 0); if (comment == null){ return; } extractMeaningfulName(container, comment); } private void serializeMeaningfulName(StringBuffer buffer) { if (!StringUtils.isEmpty(getMeaningfulName())){ buffer.append(MEANINGFULNAME_FORMAT.format(new Object[]{getMeaningfulName()})); } } private static void extractMeaningfulName(JTestContainer container,String comment) { Matcher m = MEANINGFULNAME_PATTERN.matcher(comment); if (m.find()){ String meaningfulName = m.group(1); container.setMeaningfulName(meaningfulName, false); } } /** * Get name now checks whether there is a meaningful name, if so * it returns it, otherwise returns name and comment. * * Note that meaningful name supports embedding ant parameters * in the following format: ${param} * */ @Override public String getTestName() { if (!StringUtils.isEmpty(getMeaningfulName())){ return updateNameWithAntParameters(getMeaningfulName()); } return getName() + " - " + getComment(); } /** */ private String updateNameWithAntParameters(String name){ try { Matcher matcher = ParametersManager.PARAMETER_PATTERN.matcher(name); Properties props = FileUtils.loadPropertiesFromFile(CommonResources.ANT_INTERNAL_PROPERTIES_FILE); while (matcher.find()) { String param = matcher.group(1); String value = props.getProperty(param); String match = matcher.group(0); if (value != null){ name = StringUtils.replace(name, match,value); } } }catch (Exception e){ log.log(Level.FINE,"Failed loading ant properties file.",e); } return name; } /** * load the Unique test Id from the XML system property<br> * if no value is found, generate a new one otherwise * * @param target * the test target element * @return the unique id String */ public String loadUuid(Element target) { String uuid = target.getAttribute("fullUuid"); if (!StringUtils.isEmpty(uuid)){ String toReturn = uuid.substring(uuid.lastIndexOf(".") + 1); return toReturn; } log.fine("Flow element did not have a UUID, Generating a new one"); return getRandomUUID(); } /** * load the Unique test Id from the XML system property<br> * if no value is found, generate a new one otherwise * * @param target * the test target element * @return the unique id String */ public void loadUuidAndParameters(Element target) { setUUID(loadUuid(target)); loadParameters(); setTestComment(defaultComment()); } protected abstract void loadParameters(); /** * Add Unique ID and Scenario parent name values to Xml element * * @param element the element to add attributes to */ protected void addPropertiesToElement(Element element){ element.setAttribute("parentName", "${jsystem.parent.name}.${ant.project.name}"); element.setAttribute("fullUuid", "${jsystem.parent.uuid}.${jsystem.uuid}." + getUUID()); saveFlowDocumentation(); } /** * User documentation */ protected void loadAndSetUserDocumentation() { if (StringUtils.isEmpty(this.getFlowFullUUID())){ return; } String documentation = ScenarioHelpers.getTestProperty(this.getFlowFullUUID(), ScenarioHelpers.getRoot(this).getName(), RunningProperties.DOCUMENTATION_TAG); if (documentation != null) { setDocumentation(documentation); } } /** * */ private void saveFlowDocumentation() { Properties p = new Properties(); p.setProperty(RunningProperties.DOCUMENTATION_TAG,getDocumentation() == null? "" : getDocumentation()); ScenarioHelpers.setTestInnerProperty(getFlowFullUUID(), ScenarioHelpers.getRoot(this).getName(),p,true); } }