/** * Copyright AdScale GmbH, Germany, 2009 */ package fitnesse.testrunner; import java.util.Arrays; import java.util.LinkedList; import java.util.List; import java.util.logging.Level; import java.util.logging.Logger; import fitnesse.wiki.PageCrawler; import fitnesse.wiki.PageData; import fitnesse.wiki.PageType; import fitnesse.wiki.WikiPage; import fitnesse.wiki.WikiPagePath; import org.apache.commons.lang.StringUtils; import static org.apache.commons.lang.StringUtils.equalsIgnoreCase; import static org.apache.commons.lang.StringUtils.trim; public class SuiteFilter { private static final Logger LOG = Logger.getLogger(SuiteFilter.class.getName()); private final SuiteTagMatcher notMatchTags; private final SuiteTagMatcher matchTags; private final String startWithTest; public static final SuiteFilter NO_MATCHING = new SuiteFilter(null, null, null, null) { @Override public boolean isMatchingTest(WikiPage testPage) { return false; } }; public static final SuiteFilter MATCH_ALL = new SuiteFilter(null, null, null, null); public SuiteFilter(String orTags, String mustNotMatchTags, String andTags, String startWithTest) { this.startWithTest = (!"".equals(startWithTest)) ? startWithTest : null; if(andTags != null) { matchTags = new SuiteTagMatcher(andTags, true, true); } else { matchTags = new SuiteTagMatcher(orTags, true, false); } notMatchTags = new SuiteTagMatcher(mustNotMatchTags, false, false); } public SuiteFilter(String suiteFilter, String excludeSuiteFilter) { matchTags = new SuiteTagMatcher(suiteFilter, true, false); notMatchTags = new SuiteTagMatcher(excludeSuiteFilter, false, false); startWithTest = null; } public boolean isMatchingTest(WikiPage testPage) { PageData data = testPage.getData(); boolean isTest = data.hasAttribute(PageType.TEST.toString()); return isTest && matchTags.matches(testPage) && !notMatchTags.matches(testPage) && afterStartingTest(testPage); } private boolean afterStartingTest(WikiPage testPage) { if (startWithTest == null) { return true; } PageCrawler crawler = testPage.getPageCrawler(); WikiPagePath pageName = crawler.getFullPath(); return (pageName.toString().compareTo(startWithTest) >= 0); } public boolean hasMatchingTests() { return (this != NO_MATCHING); } public SuiteFilter getFilterForTestsInSuite(WikiPage suitePage) { PageData pageData = suitePage.getData(); if (pageData.hasAttribute(PageType.SUITE.toString()) && matchTags.isFiltering() && matchTags.matches(suitePage)) { return new SuiteFilter(null, notMatchTags.tagString, null, startWithTest).getFilterForTestsInSuite(suitePage); } if (notMatchTags.matches(suitePage)) { return NO_MATCHING; } return this; } @Override public String toString() { List<String> criterias = new LinkedList<>(); if (matchTags.isFiltering()) { if(matchTags.andStrategy){ criterias.add("matches all of '" + matchTags.tagString + "'"); } else { criterias.add("matches '" + matchTags.tagString + "'"); } } if (notMatchTags.isFiltering()) { criterias.add("doesn't match '" + notMatchTags.tagString + "'"); } if (startWithTest != null) { criterias.add("starts with test '" + startWithTest + "'"); } return StringUtils.join(criterias, " & "); } private class SuiteTagMatcher { private static final String LIST_SEPARATOR = "\\s*,\\s*"; private final List<String> tags; final String tagString; private final boolean matchIfNoTags; private final boolean andStrategy; public SuiteTagMatcher(String suiteTags, boolean matchIfNoTags, boolean andStrategy) { tagString = suiteTags; if (StringUtils.isNotBlank(suiteTags)) { tags = Arrays.asList(suiteTags.split(LIST_SEPARATOR)); } else { tags = null; } this.matchIfNoTags = matchIfNoTags; this.andStrategy = andStrategy; } boolean isFiltering() { return (tags != null); } boolean matches(WikiPage wikiPage) { return (tags == null) ? matchIfNoTags : testMatchesQuery(wikiPage); } private boolean testMatchesQuery(WikiPage wikiPage) { String testTagString = getTestTags(wikiPage); return (testTagString != null && testTagsMatchQueryTags(testTagString)); } private String getTestTags(WikiPage context) { try { return context.getData().getAttribute(PageData.PropertySUITES); } catch (Exception e) { LOG.log(Level.WARNING, "Unable to retrieve tags for page " + context, e); return null; } } private boolean testTagsMatchQueryTags(String testTagString) { String[] testTags = testTagString.trim().split(LIST_SEPARATOR); if(andStrategy){ return checkIfAllQueryTagsExist(testTags); } else { return checkIfAnyTestTagMatchesAnyQueryTag(testTags); } } private boolean checkIfAllQueryTagsExist(String[] testTags) { for (String queryTag : tags) { if (!containsTag(testTags, queryTag)) { return false; } } return true; } private boolean checkIfAnyTestTagMatchesAnyQueryTag(String[] testTags) { for (String queryTag : tags) { if (containsTag(testTags, queryTag)) { return true; } } return false; } private boolean containsTag(String[] testTags, String queryTag) { for (String testTag: testTags) { if (tagsMatch(queryTag, testTag)) { return true; } } return false; } private boolean tagsMatch(String queryTag, String testTag) { return equalsIgnoreCase(trim(testTag), trim(queryTag)); } } }