// Copyright (C) 2003-2009 by Object Mentor, Inc. All rights reserved.
// Released under the terms of the CPL Common Public License version 1.0.
package fitnesse.testrunner;
import java.io.File;
import java.io.FilenameFilter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import fitnesse.components.TraversalListener;
import fitnesse.wiki.WikiPage;
import fitnesse.wiki.WikitextPage;
import fitnesse.wikitext.parser.HtmlTranslator;
import fitnesse.wikitext.parser.ParsingPage;
import fitnesse.wikitext.parser.Paths;
import fitnesse.wikitext.parser.Symbol;
import fitnesse.wikitext.parser.WikiSourcePage;
public class ClassPathBuilder {
public List<String> getClassPath(WikiPage page) {
List<String> paths = getInheritedPathElements(page);
return createClassPath(paths);
}
private List<String> getInheritedPathElements(WikiPage page) {
final List<String> items = new ArrayList<String>();
page.getPageCrawler().traversePageAndAncestors(new TraversalListener<WikiPage>() {
@Override
public void process(WikiPage p) {
items.addAll(getItemsFromPage(p));
}
});
return items;
}
public List<String> createClassPath(List<String> paths) {
paths = expandWildcards(paths);
Set<String> addedPaths = new HashSet<String>();
List<String> classPath = new ArrayList<String>();
for (String path : paths) {
if (!addedPaths.contains(path)) {
addedPaths.add(path);
classPath.add(path);
}
}
return classPath;
}
private List<String> expandWildcards(List<String> paths) {
List<String> allPaths = new ArrayList<String>();
for (String path : paths)
allPaths.addAll(expandWildcard(path));
return allPaths;
}
private List<String> expandWildcard(String path) {
List<String> allPaths = new ArrayList<String>();
File file = new File(path);
File dir = new File(file.getAbsolutePath()).getParentFile();
if (isExpandableDoubleWildcard(path, dir))
allPaths.addAll(recursivelyAddMatchingFiles(path, dir));
else if (isExpandableSingleWildcard(path, dir))
allPaths.addAll(getMatchingFiles(path, dir));
else
allPaths.add(path);
return allPaths;
}
private List<String> recursivelyAddMatchingFiles(String path, File dir) {
String singleWildcardPath = convertDoubleToSingleWildcard(path);
return getMatchingSubfiles(singleWildcardPath, dir);
}
private boolean isExpandableSingleWildcard(String path, File dir) {
return pathHasSingleWildcard(path) && dir.exists();
}
private boolean isExpandableDoubleWildcard(String path, File dir) {
return pathHasDoubleWildCard(path) && dir.exists();
}
private boolean pathHasSingleWildcard(String path) {
return path.indexOf('*') != -1;
}
private String convertDoubleToSingleWildcard(String path) {
path = path.replaceFirst("\\*\\*", "*");
return path;
}
private boolean pathHasDoubleWildCard(String path) {
return path.contains("**");
}
private List<String> getMatchingFiles(String path, File dir) {
String fileName = new File(path).getName();
File[] files = dir.listFiles(new Wildcard(fileName));
List<String> allPaths = new ArrayList<String>();
for (File file : files) {
allPaths.add(file.getPath());
}
return allPaths;
}
private List<String> getMatchingSubfiles(String path, File dir) {
List<String> allPaths = new ArrayList<String>();
allPaths.addAll(getMatchingFiles(path, dir));
for (File file : dir.listFiles()) {
if (file.isDirectory())
allPaths.addAll(getMatchingSubfiles(path, file));
}
return allPaths;
}
protected List<String> getItemsFromPage(WikiPage page) {
if (page instanceof WikitextPage) {
Symbol tree = ((WikitextPage) page).getSyntaxTree();
ParsingPage parsingPage = ((WikitextPage) page).getParsingPage();
return new Paths(new HtmlTranslator(new WikiSourcePage(page), parsingPage)).getPaths(tree);
}
return Collections.emptyList();
}
public static class Wildcard implements FilenameFilter {
private String pattern;
private String prefix;
private String suffix;
private int length;
public Wildcard(String pattern) {
int starIndex = pattern.indexOf("*");
if (starIndex > -1) {
prefix = pattern.substring(0, starIndex);
suffix = pattern.substring(starIndex + 1);
length = prefix.length() + suffix.length();
} else {
this.pattern = pattern;
}
}
public boolean accept(File dir, String name) {
if (pattern != null)
return pattern.equals(name);
boolean goodLength = name.length() >= length;
boolean goodPrefix = name.startsWith(prefix);
boolean goodSufix = name.endsWith(suffix);
return goodLength && goodPrefix && goodSufix;
}
}
}