package org.testng.xml;

import org.testng.TestNG;
import org.testng.TestNGException;
import org.testng.collections.Lists;
import org.testng.collections.Maps;
import org.testng.reporters.XMLStringBuffer;
import org.testng.xml.dom.ParentSetter;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.UUID;

/**
 * This class describes the tag &lt;test&gt;  in testng.xml.
 *
 * @author <a href = "mailto:cedric&#64;beust.com">Cedric Beust</a>
 * @author <a href = 'mailto:the_mindstorm[at]evolva[dot]ro'>Alexandru Popescu</a>
 */
public class XmlTest implements Serializable, Cloneable {
  private static final long serialVersionUID = 6533504325942417606L;

  public static int DEFAULT_TIMEOUT_MS = Integer.MAX_VALUE;

  private XmlSuite m_suite;
  private String m_name;
  private Integer m_verbose = XmlSuite.DEFAULT_VERBOSE;
  private Boolean m_isJUnit = XmlSuite.DEFAULT_JUNIT;
  private int m_threadCount= -1;

  private List<XmlClass> m_xmlClasses = Lists.newArrayList();

  private List<String> m_includedGroups = Lists.newArrayList();
  private List<String> m_excludedGroups = Lists.newArrayList();

  private Map<String, List<String>> m_metaGroups = Maps.newHashMap();
  private Map<String, String> m_parameters = Maps.newHashMap();
  private String m_parallel;

  private List<XmlMethodSelector> m_methodSelectors = Lists.newArrayList();
  // test level packages
  private List<XmlPackage> m_xmlPackages = Lists.newArrayList();

  private String m_timeOut;
  private Boolean m_skipFailedInvocationCounts = XmlSuite.DEFAULT_SKIP_FAILED_INVOCATION_COUNTS;
  private Map<String, List<Integer>> m_failedInvocationNumbers = null; // lazily initialized

  private String m_preserveOrder = XmlSuite.DEFAULT_PRESERVE_ORDER;

  private int m_index;

  private Boolean m_groupByInstances;

  private Boolean m_allowReturnValues = null;

  private Map<String, String> m_xmlDependencyGroups = Maps.newHashMap();

  /**
   * Constructs a <code>XmlTest</code> and adds it to suite's list of tests.
   *
   * @param suite the parent suite.
   * @param index the index of this test tag in testng.xml
   */
  public XmlTest(XmlSuite suite, int index) {
    init(suite, index);
  }

  public XmlTest(XmlSuite suite) {
    init(suite, 0);
  }

  private void init(XmlSuite suite, int index) {
    m_suite = suite;
    m_suite.getTests().add(this);
    m_index = index;
    //no two tests in the same suite should have the same name.
    //so, make the default test name unique
    m_name = TestNG.DEFAULT_COMMAND_LINE_TEST_NAME
      + " " + UUID.randomUUID().toString();
  }

  // For YAML
  public XmlTest() {
  }

  public void setXmlPackages(List<XmlPackage> packages) {
    m_xmlPackages = Lists.newArrayList(packages);
  }

  public List<XmlPackage> getXmlPackages() {
    return m_xmlPackages;
  }

  // For YAML
  public List<XmlPackage> getPackages() {
    return getPackages();
  }

  // For YAML
  public void setPackages(List<XmlPackage> p) {
    setXmlPackages(p);
  }

  public List<XmlMethodSelector> getMethodSelectors() {
    return m_methodSelectors;
  }

  public void setMethodSelectors(List<XmlMethodSelector> methodSelectors) {
    m_methodSelectors = Lists.newArrayList(methodSelectors);
  }

  /**
   * Returns the suite this test is part of.
   * @return the suite this test is part of.
   */
  public XmlSuite getSuite() {
    return m_suite;
  }

  /**
   * @return the includedGroups.
   * Note: do not modify the returned value, use {@link #addIncludedGroup(String)}.
   */
  public List<String> getIncludedGroups() {
    List<String> result;
    if (m_xmlGroups != null) {
      result = m_xmlGroups.getRun().getIncludes();
      result.addAll(m_suite.getIncludedGroups());
    } else {
      // deprecated
      result = Lists.newArrayList(m_includedGroups);
      result.addAll(m_suite.getIncludedGroups());
    }
    return result;
  }

  /**
   * Sets the XML Classes.
   * @param classes The classes to set.
   * @deprecated use setXmlClasses
   */
  @Deprecated
  public void setClassNames(List<XmlClass> classes) {
    m_xmlClasses = classes;
  }

  /**
   * @return Returns the classes.
   */
  public List<XmlClass> getXmlClasses() {
    return m_xmlClasses;
  }

  // For YAML
  public List<XmlClass> getClasses() {
    return getXmlClasses();
  }

  // For YAML
  public void setClasses(List<XmlClass> c) {
    setXmlClasses(c);
  }

  /**
   * Sets the XML Classes.
   * @param classes The classes to set.
   */
  public void setXmlClasses(List<XmlClass> classes) {
    m_xmlClasses = classes;
  }

  /**
   * @return Returns the name.
   */
  public String getName() {
    return m_name;
  }

  /**
   * @param name The name to set.
   */
  public void setName(String name) {
    m_name = name;
  }

  /**
   * @param v
   */
  public void setVerbose(int v) {
    m_verbose = Integer.valueOf(v);
  }

  public int getThreadCount() {
    return m_threadCount > 0 ? m_threadCount : getSuite().getThreadCount();
  }

  public void setThreadCount(int threadCount) {
    m_threadCount = threadCount;
  }

  /**
   * @param g
   */
  public void setIncludedGroups(List<String> g) {
    m_includedGroups = g;
  }

  /**
   * @param g The excludedGrousps to set.
   */
  public void setExcludedGroups(List<String> g) {
    m_excludedGroups = g;
  }

  /**
   * @return Returns the excludedGroups.
   * Note: do not modify the returned value, use {@link #addExcludedGroup(String)}.
   */
  public List<String> getExcludedGroups() {
    List<String> result = new ArrayList(m_excludedGroups);
    result.addAll(m_suite.getExcludedGroups());
    return result;
  }

  public void addIncludedGroup(String g) {
    m_includedGroups.add(g);
  }

  public void addExcludedGroup(String g) {
    m_excludedGroups.add(g);
  }

  /**
   * @return Returns the verbose.
   */
  public int getVerbose() {
    Integer result = m_verbose;
    if (null == result || XmlSuite.DEFAULT_VERBOSE.equals(m_verbose)) {
      result = m_suite.getVerbose();
    }

    if (null != result) {
      return result.intValue();
    } else {
      return 1;
    }
  }

  public boolean getGroupByInstances() {
    Boolean result = m_groupByInstances;
    if (result == null || XmlSuite.DEFAULT_GROUP_BY_INSTANCES.equals(m_groupByInstances)) {
      result = m_suite.getGroupByInstances();
    }
    if (result != null) {
      return result.booleanValue();
    } else {
      return XmlSuite.DEFAULT_GROUP_BY_INSTANCES;
    }
  }

  public void setGroupByInstances(boolean f) {
    m_groupByInstances = f;
  }

  /**
   * @return Returns the isJUnit.
   */
  public boolean isJUnit() {
    Boolean result = m_isJUnit;
    if (null == result || XmlSuite.DEFAULT_JUNIT.equals(result)) {
      result = m_suite.isJUnit();
    }

    return result;
  }

  /**
   * @param isJUnit The isJUnit to set.
   */
  public void setJUnit(boolean isJUnit) {
    m_isJUnit = isJUnit;
  }

  // For YAML
  public void setJunit(boolean isJUnit) {
    setJUnit(isJUnit);
  }

  public void setSkipFailedInvocationCounts(boolean skip) {
    m_skipFailedInvocationCounts = skip;
  }

  /**
   * @return Returns the isJUnit.
   */
  public boolean skipFailedInvocationCounts() {
    Boolean result = m_skipFailedInvocationCounts;
    if (null == result) {
      result = m_suite.skipFailedInvocationCounts();
    }

    return result;
  }

  public void addMetaGroup(String name, List<String> metaGroup) {
    m_metaGroups.put(name, metaGroup);
  }

  // For YAML
  public void setMetaGroups(Map<String, List<String>> metaGroups) {
    m_metaGroups = metaGroups;
  }

  /**
   * @return Returns the metaGroups.
   */
  public Map<String, List<String>> getMetaGroups() {
    return m_metaGroups;
  }

  /**
   * @param parameters
   */
  public void setParameters(Map<String, String> parameters) {
    m_parameters = parameters;
  }

  public void addParameter(String key, String value) {
    m_parameters.put(key, value);
  }

  public String getParameter(String name) {
    String result = m_parameters.get(name);
    if (null == result) {
      result = m_suite.getParameter(name);
    }

    return result;
  }

  /**
   * Returns a merge of the the test parameters and its parent suite parameters. Test parameters
   * have precedence over suite parameters.
   *
   * @return a merge of the the test parameters and its parent suite parameters.
   */
  public Map<String, String> getParameters() {
    Map<String, String> result = Maps.newHashMap();
    Map<String, String> parameters = getSuite().getParameters();
    for (Map.Entry<String, String> parameter : parameters.entrySet()) {
      result.put(parameter.getKey(), parameter.getValue());
    }
    for (String key : m_parameters.keySet()) {
      result.put(key, m_parameters.get(key));
    }
    return result;
  }

  /**
   * @return the parameters defined on this <test> tag only
   */
  public Map<String, String> getTestParameters() {
    return m_parameters;
  }

  public void setParallel(String parallel) {
    m_parallel = parallel;
  }

  public String getParallel() {
    String result = null;
    if (null != m_parallel || XmlSuite.DEFAULT_PARALLEL.equals(m_parallel)) {
      result = m_parallel;
    }
    else {
      result = m_suite.getParallel();
    }

    return result;
  }

  public String getTimeOut() {
    String result = null;
    if (null != m_timeOut) {
      result = m_timeOut;
    }
    else {
      result = m_suite.getTimeOut();
    }

    return result;
  }

  public long getTimeOut(long def) {
    long result = def;
    if (getTimeOut() != null) {
        result = new Long(getTimeOut()).longValue();
    }

    return result;
  }

  public void setTimeOut(long timeOut) {
      m_timeOut = Long.toString(timeOut);
  }

  public void setExpression(String expression) {
    setBeanShellExpression(expression);
  }

  public void setBeanShellExpression(String expression) {
    List<XmlMethodSelector> selectors = getMethodSelectors();
    if (selectors.size() > 0) {
      selectors.get(0).setExpression(expression);
    } else if (expression != null) {
      XmlMethodSelector xms = new XmlMethodSelector();
      xms.setExpression(expression);
      xms.setLanguage("BeanShell");
      getMethodSelectors().add(xms);
    }
  }

  public String getExpression() {
    List<XmlMethodSelector> selectors = getMethodSelectors();
    if (selectors.size() > 0) {
      return selectors.get(0).getExpression();
    } else {
      return null;
    }
  }

  public String toXml(String indent) {
    XMLStringBuffer xsb = new XMLStringBuffer(indent);
    Properties p = new Properties();
    p.setProperty("name", getName());
    if (m_isJUnit != null) {
      XmlUtils.setProperty(p, "junit", m_isJUnit.toString(), XmlSuite.DEFAULT_JUNIT.toString());
    }
    if (m_parallel != null) {
      XmlUtils.setProperty(p, "parallel", m_parallel, XmlSuite.DEFAULT_PARALLEL);
    }
    if (m_verbose != null) {
      XmlUtils.setProperty(p, "verbose", m_verbose.toString(), XmlSuite.DEFAULT_VERBOSE.toString());
    }
    if (null != m_timeOut) {
      p.setProperty("time-out", m_timeOut.toString());
    }
    if (m_preserveOrder != null) {
      p.setProperty("preserve-order", m_preserveOrder.toString());
    }
    if (m_threadCount != -1) {
      p.setProperty("thread-count", Integer.toString(m_threadCount));
    }

    xsb.push("test", p);


    if (null != getMethodSelectors() && !getMethodSelectors().isEmpty()) {
      xsb.push("method-selectors");
      for (XmlMethodSelector selector: getMethodSelectors()) {
        xsb.getStringBuffer().append(selector.toXml(indent + "    "));
      }

      xsb.pop("method-selectors");
    }

    // parameters
    if (!m_parameters.isEmpty()) {
      for(Map.Entry<String, String> para: m_parameters.entrySet()) {
        Properties paramProps= new Properties();
        paramProps.setProperty("name", para.getKey());
        paramProps.setProperty("value", para.getValue());
        xsb.addEmptyElement("parameter", paramProps); // BUGFIX: TESTNG-27
      }
    }

    // groups
    if (!m_metaGroups.isEmpty() || !m_includedGroups.isEmpty() || !m_excludedGroups.isEmpty()
        || !m_xmlDependencyGroups.isEmpty()) {
      xsb.push("groups");

      // define
      for (String metaGroupName: m_metaGroups.keySet()) {
        Properties metaGroupProp= new Properties();
        metaGroupProp.setProperty("name",  metaGroupName);

        xsb.push("define", metaGroupProp);

        for (String groupName: m_metaGroups.get(metaGroupName)) {
          Properties includeProps = new Properties();
          includeProps.setProperty("name", groupName);

          xsb.addEmptyElement("include", includeProps);
        }

        xsb.pop("define");
      }

      // run
      if (!m_includedGroups.isEmpty() || !m_excludedGroups.isEmpty()) {
        xsb.push("run");

        for (String includeGroupName: m_includedGroups) {
          Properties includeProps = new Properties();
          includeProps.setProperty("name", includeGroupName);

          xsb.addEmptyElement("include", includeProps);
        }

        for (String excludeGroupName: m_excludedGroups) {
          Properties excludeProps = new Properties();
          excludeProps.setProperty("name", excludeGroupName);

          xsb.addEmptyElement("exclude", excludeProps);
        }

        xsb.pop("run");
      }

      // group dependencies
      if (m_xmlDependencyGroups != null && ! m_xmlDependencyGroups.isEmpty()) {
        xsb.push("dependencies");
        for (Map.Entry<String, String> entry : m_xmlDependencyGroups.entrySet()) {
          xsb.addEmptyElement("group", "name", entry.getKey(), "depends-on", entry.getValue());
        }
        xsb.pop("dependencies");
      }

      xsb.pop("groups");
    }

    if (null != m_xmlPackages && !m_xmlPackages.isEmpty()) {
      xsb.push("packages");

      for (XmlPackage pack: m_xmlPackages) {
        xsb.getStringBuffer().append(pack.toXml("      "));
      }

      xsb.pop("packages");
    }

    // classes
    if (null != getXmlClasses() && !getXmlClasses().isEmpty()) {
      xsb.push("classes");
      for (XmlClass cls : getXmlClasses()) {
        xsb.getStringBuffer().append(cls.toXml(indent + "    "));
      }
      xsb.pop("classes");
    }

    xsb.pop("test");

    return xsb.toXML();
  }

  @Override
  public String toString() {
//    return toXml("");
    StringBuffer result = new StringBuffer("[Test: \"" + m_name + "\"")
      .append(" verbose:" + m_verbose);

    result.append("[parameters:");
    for (String k : m_parameters.keySet()) {
      String v = m_parameters.get(k);
      result.append(k + "=>" + v);
    }

    result.append("]");
    result.append("[metagroups:");
    for (String g : m_metaGroups.keySet()) {
      List<String> mg = m_metaGroups.get(g);
      result.append(g).append("=");
      for (String n : mg) {
        result.append(n).append(",");
      }
    }
    result.append("] ");

    result.append("[included: ");
    for (String g : m_includedGroups) {
      result.append(g).append(" ");
    }
    result.append("]");

    result.append("[excluded: ");
    for (String g : m_excludedGroups) {
      result.append(g).append("");
    }
    result.append("] ");

    result.append(" classes:");
    for (XmlClass cl : m_xmlClasses) {
      result.append(cl).append(" ");
    }

    result.append(" packages:");
    for (XmlPackage p : m_xmlPackages) {
      result.append(p).append(" ");
    }

    result.append("] ");

    return result.toString();
  }

  static void ppp(String s) {
    System.out.println("[XmlTest] " + s);
  }

  /**
   * Clone the <TT>source</TT> <CODE>XmlTest</CODE> by including:
   * - test attributes
   * - groups definitions
   * - parameters
   *
   * The &lt;classes&gt; sub element is ignored for the moment.
   *
   * @return a clone of the current XmlTest
   */
  @Override
  public Object clone() {
    XmlTest result = new XmlTest(getSuite());

    result.setName(getName());
    result.setIncludedGroups(getIncludedGroups());
    result.setExcludedGroups(getExcludedGroups());
    result.setJUnit(isJUnit());
    result.setParallel(getParallel());
    result.setVerbose(getVerbose());
    result.setParameters(getParameters());
    result.setXmlPackages(getXmlPackages());

    Map<String, List<String>> metagroups = getMetaGroups();
    for (Map.Entry<String, List<String>> group: metagroups.entrySet()) {
      result.addMetaGroup(group.getKey(), group.getValue());
    }

    return result;
  }

  /**
   * Convenience method to cache the ordering numbers for methods.
   */
  public List<Integer> getInvocationNumbers(String method) {
    if (m_failedInvocationNumbers == null) {
      m_failedInvocationNumbers = Maps.newHashMap();
      for (XmlClass c : getXmlClasses()) {
        for (XmlInclude xi : c.getIncludedMethods()) {
          List<Integer> invocationNumbers = xi.getInvocationNumbers();
          if (invocationNumbers.size() > 0) {
            String methodName = c.getName() + "." + xi.getName();
            m_failedInvocationNumbers.put(methodName, invocationNumbers);
          }
        }
      }
    }

    List<Integer> result = m_failedInvocationNumbers.get(method);
    if (result == null) {
      // Don't use emptyList here since this list might end up receiving values if
      // the test run fails.
      return Lists.newArrayList();
    } else {
      return result;
    }
  }

  public void setPreserveOrder(String preserveOrder) {
    m_preserveOrder = preserveOrder;
  }

  public String getPreserveOrder() {
    String result = m_preserveOrder;
    if (result == null || XmlSuite.DEFAULT_PRESERVE_ORDER.equals(m_verbose)) {
      result = m_suite.getPreserveOrder();
    }

    return result;
  }

  public void setSuite(XmlSuite result) {
    m_suite = result;
  }

  public Boolean getAllowReturnValues() {
    if (m_allowReturnValues != null) return m_allowReturnValues;
    else return getSuite().getAllowReturnValues();
  }

  public void setAllowReturnValues(Boolean allowReturnValues) {
    m_allowReturnValues = allowReturnValues;
  }

  /**
   * Note that this attribute does not come from the XML file, it's calculated
   * internally and represents the order in which this test tag was found in its
   * &lt;suite&gt; tag.  It's used to calculate the ordering of the tests
   * when preserve-test-order is true.
   */
  public int getIndex() {
    return m_index;
  }

  @Override
  public int hashCode() {
    final int prime = 31;
    int result = 1;
    result = prime * result
        + ((m_excludedGroups == null) ? 0 : m_excludedGroups.hashCode());
    result = prime
        * result
        + ((m_failedInvocationNumbers == null) ? 0 : m_failedInvocationNumbers
            .hashCode());
    result = prime * result
        + ((m_includedGroups == null) ? 0 : m_includedGroups.hashCode());
    result = prime * result + ((m_isJUnit == null) ? 0 : m_isJUnit.hashCode());
    result = prime * result
        + ((m_metaGroups == null) ? 0 : m_metaGroups.hashCode());
    result = prime * result
        + ((m_methodSelectors == null) ? 0 : m_methodSelectors.hashCode());
    result = prime * result + ((m_name == null) ? 0 : m_name.hashCode());
    result = prime * result
        + ((m_parallel == null) ? 0 : m_parallel.hashCode());
    result = prime * result
        + ((m_parameters == null) ? 0 : m_parameters.hashCode());
    result = prime * result
        + ((m_preserveOrder == null) ? 0 : m_preserveOrder.hashCode());
    result = prime
        * result
        + ((m_skipFailedInvocationCounts == null) ? 0
            : m_skipFailedInvocationCounts.hashCode());
    result = prime * result + m_threadCount;
    result = prime * result + ((m_timeOut == null) ? 0 : m_timeOut.hashCode());
    result = prime * result + ((m_verbose == null) ? 0 : m_verbose.hashCode());
    result = prime * result
        + ((m_xmlClasses == null) ? 0 : m_xmlClasses.hashCode());
    result = prime * result
        + ((m_xmlPackages == null) ? 0 : m_xmlPackages.hashCode());
    return result;
  }

  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null)
      return XmlSuite.f();
    if (getClass() != obj.getClass())
      return XmlSuite.f();
    XmlTest other = (XmlTest) obj;
    if (m_excludedGroups == null) {
      if (other.m_excludedGroups != null)
        return XmlSuite.f();
    } else if (!m_excludedGroups.equals(other.m_excludedGroups))
      return XmlSuite.f();
//    if (m_expression == null) {
//      if (other.m_expression != null)
//        return XmlSuite.f();
//    } else if (!m_expression.equals(other.m_expression))
//      return XmlSuite.f();
    if (m_failedInvocationNumbers == null) {
      if (other.m_failedInvocationNumbers != null)
        return XmlSuite.f();
    } else if (!m_failedInvocationNumbers
        .equals(other.m_failedInvocationNumbers))
      return XmlSuite.f();
    if (m_includedGroups == null) {
      if (other.m_includedGroups != null)
        return XmlSuite.f();
    } else if (!m_includedGroups.equals(other.m_includedGroups))
      return XmlSuite.f();
    if (m_isJUnit == null) {
      if (other.m_isJUnit != null && ! other.m_isJUnit.equals(XmlSuite.DEFAULT_JUNIT))
        return XmlSuite.f();
    } else if (!m_isJUnit.equals(other.m_isJUnit))
      return XmlSuite.f();
    if (m_metaGroups == null) {
      if (other.m_metaGroups != null)
        return XmlSuite.f();
    } else if (!m_metaGroups.equals(other.m_metaGroups))
      return XmlSuite.f();
    if (m_methodSelectors == null) {
      if (other.m_methodSelectors != null)
        return XmlSuite.f();
    } else if (!m_methodSelectors.equals(other.m_methodSelectors))
      return XmlSuite.f();
    if (m_name == null) {
      if (other.m_name != null)
        return XmlSuite.f();
    } else if (!m_name.equals(other.m_name))
      return XmlSuite.f();
    if (m_parallel == null) {
      if (other.m_parallel != null)
        return XmlSuite.f();
    } else if (!m_parallel.equals(other.m_parallel))
      return XmlSuite.f();
    if (m_parameters == null) {
      if (other.m_parameters != null)
        return XmlSuite.f();
    } else if (!m_parameters.equals(other.m_parameters))
      return XmlSuite.f();
    if (m_preserveOrder == null) {
      if (other.m_preserveOrder != null)
        return XmlSuite.f();
    } else if (!m_preserveOrder.equals(other.m_preserveOrder))
      return XmlSuite.f();
    if (m_skipFailedInvocationCounts == null) {
      if (other.m_skipFailedInvocationCounts != null)
        return XmlSuite.f();
    } else if (!m_skipFailedInvocationCounts
        .equals(other.m_skipFailedInvocationCounts))
      return XmlSuite.f();
    if (m_threadCount != other.m_threadCount)
      return XmlSuite.f();
    if (m_timeOut == null) {
      if (other.m_timeOut != null)
        return XmlSuite.f();
    } else if (!m_timeOut.equals(other.m_timeOut))
      return XmlSuite.f();
    if (m_verbose == null) {
      if (other.m_verbose != null)
        return XmlSuite.f();
    } else if (!m_verbose.equals(other.m_verbose))
      return XmlSuite.f();
    if (m_xmlClasses == null) {
      if (other.m_xmlClasses != null)
        return XmlSuite.f();
    } else if (!m_xmlClasses.equals(other.m_xmlClasses))
      return XmlSuite.f();
    if (m_xmlPackages == null) {
      if (other.m_xmlPackages != null)
        return XmlSuite.f();
    } else if (!m_xmlPackages.equals(other.m_xmlPackages))
      return XmlSuite.f();

    return true;
  }

  public void addXmlDependencyGroup(String group, String dependsOn) {
    if (! m_xmlDependencyGroups.containsKey(group)) {
      m_xmlDependencyGroups.put(group, dependsOn);
    } else {
      throw new TestNGException("Duplicate group dependency found for group \"" + group + "\""
          + ", use a space-separated list of groups in the \"depends-on\" attribute");
    }
  }

  public Map<String, String> getXmlDependencyGroups() {
    return m_xmlDependencyGroups;
  }

  @ParentSetter
  public void setXmlSuite(XmlSuite suite) {
	  m_suite = suite;
  }

  private XmlGroups m_xmlGroups;

  public void setGroups(XmlGroups xmlGroups) {
    m_xmlGroups = xmlGroups;
  }
}
