package fitnesse.wiki.fs;
import java.io.File;
import java.util.*;
import fitnesse.util.StringUtils;
import fitnesse.wiki.*;
import fitnesse.wikitext.parser.VariableSource;
class FileSystemSubWikiPageFactory implements SubWikiPageFactory {
private final File rootPath;
private final FileSystem fileSystem;
private final VariableSource variableSource;
private final WikiPageFactory factory;
public FileSystemSubWikiPageFactory(File rootPath, FileSystem fileSystem, VariableSource variableSource,
WikiPageFactory factory) {
this.rootPath = rootPath;
this.fileSystem = fileSystem;
this.variableSource = variableSource;
this.factory = factory;
}
@Override
public List<WikiPage> getChildren(FileBasedWikiPage page) {
List<WikiPage> children = new ArrayList<>();
children.addAll(getNormalChildren(page));
children.addAll(getSymlinkChildren(page));
return children;
}
private Set<WikiPage> getNormalChildren(FileBasedWikiPage page) {
final File thisDir = page.getFileSystemPath();
final Set<WikiPage> children = new TreeSet<>();
if (fileSystem.exists(thisDir)) {
final String[] subFiles = fileSystem.list(thisDir);
for (String subFile : subFiles) {
WikiPage maybeChildPage = getChildPage(page, subFile);
if (maybeChildPage != null) {
children.add(maybeChildPage);
}
}
}
return children;
}
private List<WikiPage> getSymlinkChildren(WikiPage page) {
List<WikiPage> children = new LinkedList<>();
WikiPageProperty props = page.getData().getProperties();
WikiPageProperty symLinksProperty = props.getProperty(SymbolicPage.PROPERTY_NAME);
if (symLinksProperty != null) {
for (String linkName : symLinksProperty.keySet()) {
WikiPage linkedPage = createSymbolicPage(page, linkName);
if (linkedPage != null && !children.contains(linkedPage))
children.add(linkedPage);
}
}
return children;
}
@Override
public WikiPage getChildPage(FileBasedWikiPage page, String childName) {
File parent = page.getFileSystemPath();
WikiPage childPage = makeChildPage(new File(parent, childName), childName, page);
if (childPage == null) {
childPage = createSymbolicPage(page, childName);
}
return childPage;
}
private WikiPage makeChildPage(File path, String childName, FileBasedWikiPage parent) {
return factory.makePage(path, childName, parent, variableSource);
}
private WikiPage createSymbolicPage(WikiPage page, String linkName) {
WikiPageProperty symLinkProperty = page.getData().getProperties().getProperty(SymbolicPage.PROPERTY_NAME);
if (symLinkProperty == null)
return null;
String linkPath = symLinkProperty.get(linkName);
if (linkPath == null)
return null;
if (linkPath.startsWith("file:"))
return createExternalSymbolicLink(linkPath, linkName, page);
else
return createInternalSymbolicPage(linkPath, linkName, page);
}
private WikiPage createExternalSymbolicLink(String linkPath, String linkName, WikiPage parent) {
String fullPagePath = new VariableTool(variableSource).replace(linkPath);
File file = WikiPageUtil.resolveFileUri(fullPagePath, rootPath);
File parentDirectory = file.getParentFile();
if (fileSystem.exists(parentDirectory)) {
WikiPage externalRoot = makeChildPage(file, file.getName(), null);
if (externalRoot != null) {
return new SymbolicPage(linkName, externalRoot, parent);
}
}
return null;
}
protected WikiPage createInternalSymbolicPage(String linkPath, String linkName, WikiPage parent) {
WikiPagePath path = PathParser.parse(linkPath);
if (path == null) {
return null;
}
WikiPage start = (path.isRelativePath()) ? parent.getParent() : parent; //TODO -AcD- a better way?
WikiPage wikiPage = start.getPageCrawler().getPage(path);
if (wikiPage != null)
wikiPage = new SymbolicPage(linkName, wikiPage, parent);
return wikiPage;
}
}