package org.testng.internal; import org.testng.ITestNGMethod; import org.testng.collections.Lists; import org.testng.collections.Maps; import java.io.Serializable; import java.util.Collection; import java.util.List; import java.util.Map; /** * This class wraps access to beforeGroups and afterGroups methods, * since they are passed around the various invokers and potentially * modified in different threads. * * @author <a href="mailto:cedric@beust.com">Cedric Beust</a> * @author <a href='mailto:the_mindstorm@evolva.ro'>Alexandru Popescu</a> * @since 5.3 (Mar 2, 2006) */ public class ConfigurationGroupMethods implements Serializable { /** Use serialVersionUID for interoperability. */ private final static long serialVersionUID= 1660798519864898480L; /** The list of beforeGroups methods keyed by the name of the group */ private final Map<String, List<ITestNGMethod>> m_beforeGroupsMethods; /** The list of afterGroups methods keyed by the name of the group */ private final Map<String, List<ITestNGMethod>> m_afterGroupsMethods; /** The list of all test methods */ private final ITestNGMethod[] m_allMethods; /**A map that returns the last method belonging to the given group */ private Map<String, List<ITestNGMethod>> m_afterGroupsMap= null; public ConfigurationGroupMethods(ITestNGMethod[] allMethods, Map<String, List<ITestNGMethod>> beforeGroupsMethods, Map<String, List<ITestNGMethod>> afterGroupsMethods) { m_allMethods= allMethods; m_beforeGroupsMethods= beforeGroupsMethods; m_afterGroupsMethods= afterGroupsMethods; } public Map<String, List<ITestNGMethod>> getBeforeGroupsMethods() { return m_beforeGroupsMethods; } public Map<String, List<ITestNGMethod>> getAfterGroupsMethods() { return m_afterGroupsMethods; } /** * @return true if the passed method is the last to run for the group. * This method is used to figure out when is the right time to invoke * afterGroups methods. */ public synchronized boolean isLastMethodForGroup(String group, ITestNGMethod method) { // If we have more invocation to do, this is not the last one yet int invocationCount= method.getCurrentInvocationCount(); if(invocationCount < (method.getInvocationCount() * method.getParameterInvocationCount())) { return false; } // Lazy initialization since we might never be called if(m_afterGroupsMap == null) { m_afterGroupsMap= initializeAfterGroupsMap(); } List<ITestNGMethod> methodsInGroup= m_afterGroupsMap.get(group); if(null == methodsInGroup || methodsInGroup.isEmpty()) return false; methodsInGroup.remove(method); // Note: == is not good enough here as we may work with ITestNGMethod clones return methodsInGroup.isEmpty(); } private synchronized Map<String, List<ITestNGMethod>> initializeAfterGroupsMap() { Map<String, List<ITestNGMethod>> result= Maps.newHashMap(); for(ITestNGMethod m : m_allMethods) { String[] groups= m.getGroups(); for(String g : groups) { List<ITestNGMethod> methodsInGroup= result.get(g); if(null == methodsInGroup) { methodsInGroup= Lists.newArrayList(); result.put(g, methodsInGroup); } methodsInGroup.add(m); } } return result; } public synchronized void removeBeforeMethod(String group, ITestNGMethod method) { List<ITestNGMethod> methods= m_beforeGroupsMethods.get(group); if(methods != null) { Object success= methods.remove(method); if(success == null) { log("Couldn't remove beforeGroups method " + method + " for group " + group); } } else { log("Couldn't find any beforeGroups method for group " + group); } } private void log(String string) { Utils.log("ConfigurationGroupMethods", 2, string); } synchronized public Map<String, List<ITestNGMethod>> getBeforeGroupsMap() { return m_beforeGroupsMethods; } synchronized public Map<String, List<ITestNGMethod>> getAfterGroupsMap() { return m_afterGroupsMethods; } synchronized public void removeBeforeGroups(String[] groups) { for(String group : groups) { // log("Removing before group " + group); m_beforeGroupsMethods.remove(group); } } synchronized public void removeAfterGroups(Collection<String> groups) { for(String group : groups) { // log("Removing before group " + group); m_afterGroupsMethods.remove(group); } } }