package fitnesse.wikitext.parser;
import fitnesse.html.HtmlTag;
import fitnesse.html.HtmlUtil;
import fitnesse.wiki.PageData;
import fitnesse.wiki.PageType;
import fitnesse.wiki.WikiImportProperty;
import util.GracefulNamer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
public class ContentsItemBuilder {
private Symbol contents;
private int level;
private SourcePage page;
public ContentsItemBuilder(Symbol contents, int level) {
this(contents, level, null);
}
public ContentsItemBuilder(Symbol contents, int level, SourcePage page) {
this.contents = contents;
this.level = level;
this.page = page;
}
public HtmlTag buildLevel(SourcePage page) {
HtmlTag list = new HtmlTag("ul");
list.addAttribute("class", "toc" + level);
for (SourcePage child: getSortedChildren(page)) {
list.add(buildListItem(child));
}
return list;
}
private HtmlTag buildListItem(SourcePage child) {
HtmlTag listItem = buildItem(child);
if (!child.getChildren().isEmpty()) {
if (level < getRecursionLimit()) {
listItem.add(new ContentsItemBuilder(contents, level + 1, child).buildLevel(child));
}
else if (getRecursionLimit() > 0){
listItem.add(contents.getVariable(Contents.MORE_SUFFIX_TOC, Contents.MORE_SUFFIX_DEFAULT));
}
}
return listItem;
}
private Collection<SourcePage> getSortedChildren(SourcePage parent) {
ArrayList<SourcePage> result = new ArrayList<>(parent.getChildren());
Collections.sort(result);
return result;
}
public HtmlTag buildItem(SourcePage page) {
HtmlTag listItem = new HtmlTag("li");
HtmlTag link = new HtmlTag("a", buildBody(page));
link.addAttribute("href", buildReference(page));
link.addAttribute("class", getBooleanPropertiesClasses(page));
listItem.add(link);
String help = page.getProperty(PageData.PropertyHELP);
if (!help.isEmpty()) {
if (hasOption("-h", Contents.HELP_TOC)) {
listItem.add(HtmlUtil.makeSpanTag("pageHelp", ": " + help));
}
else if (hasOption("-H", Contents.HELP_INSTEAD_OF_TITLE_TOC)) {
link.use(help);
}
else {
link.addAttribute("title", help);
}
}
return listItem;
}
private String buildBody(SourcePage page) {
String itemText = page.getName();
if (hasOption("-g", Contents.REGRACE_TOC)) {
//todo: DRY? see wikiwordbuilder
itemText = GracefulNamer.regrace(itemText);
}
if (hasOption("-p", Contents.PROPERTY_TOC)) {
String properties = getBooleanProperties(page);
if (!properties.isEmpty()) itemText += " " + properties;
}
if (hasOption("-f", Contents.FILTER_TOC)) {
String filters = page.getProperty(PageData.PropertySUITES);
if (!filters.isEmpty()) itemText += " (" + filters + ")";
}
return itemText;
}
private String buildReference(SourcePage sourcePage) {
return sourcePage.getFullName();
}
private int getRecursionLimit() {
for (Symbol child: contents.getChildren()) {
if (!child.getContent().startsWith("-R")) continue;
String level = child.getContent().substring(2);
if (level.isEmpty()) return Integer.MAX_VALUE;
try {
return Integer.parseInt(level);
}
catch (NumberFormatException e) {
return 0;
}
}
return 0;
}
private boolean hasOption(String option, String variableName) {
for (Symbol child: contents.getChildren()) {
if (child.getContent().equals(option)) return true;
}
return !variableName.isEmpty()
&& contents.getVariable(variableName, "").equals("true");
}
private String getBooleanProperties(SourcePage sourcePage) {
String propChars = contents.getVariable(Contents.PROPERTY_CHARACTERS,
Contents.PROPERTY_CHARACTERS_DEFAULT).trim();
if(propChars.length() != Contents.PROPERTY_CHARACTERS_DEFAULT.length() ){
propChars = Contents.PROPERTY_CHARACTERS_DEFAULT;
}
String result = "";
if (sourcePage.hasProperty(PageType.SUITE.toString())) result += propChars.charAt(0);
if (sourcePage.hasProperty(PageType.TEST.toString())) result += propChars.charAt(1);
if (sourcePage.hasProperty(WikiImportProperty.PROPERTY_NAME)) result += propChars.charAt(2);
if (page != null && page instanceof WikiSourcePage){
if (((WikiSourcePage)page).hasSymbolicLinkChild(sourcePage.getName())) result += propChars.charAt(3);
}
if (sourcePage.hasProperty(PageData.PropertyPRUNE)) result += propChars.charAt(4);
return result;
}
private String getBooleanPropertiesClasses(SourcePage sourcePage) {
String result = "";
if (sourcePage.hasProperty(PageType.SUITE.toString())) {
result += "suite";
}
else if (sourcePage.hasProperty(PageType.TEST.toString())) {
result += "test";
}
else {
result += "static";
}
if (sourcePage.hasProperty(WikiImportProperty.PROPERTY_NAME)) result += " linked";
if (sourcePage.hasProperty(PageData.PropertyPRUNE)) result += " pruned";
return result;
}
}