// 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.wiki;
import fitnesse.util.Clock;
import fitnesse.wiki.fs.WikiPageProperties;
import fitnesse.wikitext.parser.CompositeVariableSource;
import fitnesse.wikitext.parser.HtmlTranslator;
import fitnesse.wikitext.parser.Maybe;
import fitnesse.wikitext.parser.Parser;
import fitnesse.wikitext.parser.ParsingPage;
import fitnesse.wikitext.parser.Symbol;
import fitnesse.wikitext.parser.SymbolProvider;
import fitnesse.wikitext.parser.VariableSource;
import fitnesse.wikitext.parser.WikiSourcePage;
import static fitnesse.wiki.PageType.STATIC;
/**
* This class adds support for FitNesse wiki text ({@link fitnesse.wikitext.parser.Parser}).
*/
public abstract class BaseWikitextPage extends BaseWikiPage implements WikitextPage {
private final VariableSource variableSource;
private ParsingPage parsingPage;
private Symbol syntaxTree;
protected BaseWikitextPage(String name, VariableSource variableSource) {
this(name, null, variableSource);
}
protected BaseWikitextPage(String name, WikiPage parent) {
this(name, parent, parent instanceof BaseWikitextPage ? ((BaseWikitextPage) parent).variableSource : null);
}
protected BaseWikitextPage(String name, WikiPage parent, VariableSource variableSource) {
super(name, parent);
this.variableSource = variableSource;
}
protected VariableSource getVariableSource() {
return variableSource;
}
@Override
public String getVariable(String name) {
ParsingPage parsingPage = getParsingPage();
Maybe<String> variable = parsingPage.findVariable(name);
if (variable.isNothing()) return null;
Parser parser = Parser.make(parsingPage, "", SymbolProvider.variableDefinitionSymbolProvider);
return new HtmlTranslator(null, parsingPage).translate(parser.parseWithParent(variable.getValue(), null));
}
@Override
public String getHtml() {
return new HtmlTranslator(new WikiSourcePage(this), getParsingPage()).translateTree(getSyntaxTree());
}
@Override
public ParsingPage getParsingPage() {
parse();
return parsingPage;
}
@Override
public Symbol getSyntaxTree() {
parse();
return syntaxTree;
}
private void parse() {
if (syntaxTree == null) {
// This is the only page where we need a VariableSource
parsingPage = makeParsingPage(this);
syntaxTree = Parser.make(parsingPage, getData().getContent()).parse();
}
}
protected void resetCache() {
parsingPage = null;
syntaxTree = null;
}
public static ParsingPage makeParsingPage(BaseWikitextPage page) {
ParsingPage.Cache cache = new ParsingPage.Cache();
VariableSource compositeVariableSource = new CompositeVariableSource(
new ApplicationVariableSource(page.variableSource),
new PageVariableSource(page),
new UserVariableSource(page.variableSource),
cache,
new ParentPageVariableSource(page),
page.variableSource);
return new ParsingPage(new WikiSourcePage(page), compositeVariableSource, cache);
}
public WikiPageProperty defaultPageProperties() {
WikiPageProperties properties = new WikiPageProperties();
properties.set(WikiPageProperty.EDIT);
properties.set(WikiPageProperty.PROPERTIES);
properties.set(WikiPageProperty.REFACTOR);
properties.set(WikiPageProperty.WHERE_USED);
properties.set(WikiPageProperty.RECENT_CHANGES);
properties.set(WikiPageProperty.FILES);
properties.set(WikiPageProperty.VERSIONS);
properties.set(WikiPageProperty.SEARCH);
properties.setLastModificationTime(Clock.currentDate());
PageType pageType = PageType.getPageTypeForPageName(getName());
if (STATIC.equals(pageType))
return properties;
properties.set(pageType.toString());
return properties;
}
public static class UserVariableSource implements VariableSource {
private final VariableSource variableSource;
public UserVariableSource(VariableSource variableSource) {
this.variableSource = variableSource;
}
@Override
public Maybe<String> findVariable(String name) {
if(variableSource instanceof UrlPathVariableSource){
Maybe<String> result = ((UrlPathVariableSource) variableSource).findUrlVariable(name);
if (!result.isNothing()) return result;
}
return Maybe.noString;
}
}
public static class ParentPageVariableSource implements VariableSource {
private final WikiPage page;
public ParentPageVariableSource(WikiPage page) {
this.page = page;
}
@Override
public Maybe<String> findVariable(String name) {
if (page.isRoot()) {
// Get variable from
return Maybe.noString;
}
WikiPage parentPage = page.getParent();
if (parentPage instanceof WikitextPage) {
return ((WikitextPage) parentPage).getParsingPage().findVariable(name);
} else {
String value = parentPage.getVariable(name);
return value != null ? new Maybe<>(value) : Maybe.noString;
}
}
}
}