// 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 java.util.Collection; import java.util.LinkedList; import java.util.List; import fitnesse.wikitext.parser.ParsingPage; import fitnesse.wikitext.parser.Symbol; public class SymbolicPage extends BaseWikitextPage { public static final String PROPERTY_NAME = "SymbolicLinks"; public static final String SHORT_CIRCUIT_BREAK_MESSAGE = "Short circuit! This page references %s, which is already one of the parent pages of this page."; private final WikiPage realPage; public SymbolicPage(String name, WikiPage realPage, WikiPage parent) { super(name, parent); this.realPage = realPage; } public WikiPage getRealPage() { return realPage; } private boolean containsWikitext() { return containsWikitext(realPage); } @Override public WikiPage addChildPage(String name) { return realPage.addChildPage(name); } @Override public boolean hasChildPage(String name) { return realPage.hasChildPage(name); } @Override public WikiPage getChildPage(String name) { WikiPage childPage = realPage.getChildPage(name); if (childPage != null) { childPage = createChildPage(childPage); } return childPage; } @Override public void removeChildPage(String name) { realPage.removeChildPage(name); } @Override public void remove() { realPage.remove(); } @Override public List<WikiPage> getChildren() { List<WikiPage> children = realPage.getChildren(); List<WikiPage> symChildren = new LinkedList<>(); for (WikiPage child : children) { symChildren.add(createChildPage(child)); } return symChildren; } private WikiPage createChildPage(WikiPage child) { WikiPage cyclicReference = findCyclicReference(child); if (cyclicReference != null) { return new WikiPageDummy(child.getName(), String.format(SHORT_CIRCUIT_BREAK_MESSAGE, cyclicReference.getPageCrawler().getFullPath().toString()), this); } else { return new SymbolicPage(child.getName(), child, this); } } private WikiPage findCyclicReference(WikiPage childPage) { for (WikiPage parentPage = getParent(); !parentPage.isRoot(); parentPage = parentPage.getParent()) { if (childPage.equals(parentPage)) { return parentPage; } } return null; } @Override public PageData getData() { return realPage.getData(); } @Override public Collection<VersionInfo> getVersions() { return realPage.getVersions(); } @Override public WikiPage getVersion(String versionName) { return new SymbolicPage(this.getName(), realPage.getVersion(versionName), this.getParent()); } @Override public VersionInfo commit(PageData data) { return realPage.commit(data); } @Override public String getVariable(String name) { if (containsWikitext()) { return super.getVariable(name); } String value = realPage.getVariable(name); return (value == null && !isRoot()) ? getParent().getVariable(name) : value; } @Override public String getHtml() { if (containsWikitext()) { return super.getHtml(); } return realPage.getHtml(); } @Override public ParsingPage getParsingPage() { if (containsWikitext()) { return super.getParsingPage(); } return null; } @Override public Symbol getSyntaxTree() { if (containsWikitext()) { return super.getSyntaxTree(); } return Symbol.emptySymbol; } @Override @SuppressWarnings("EqualsWhichDoesntCheckParameterClass") public boolean equals(Object other) { // Wrong! If Other is also a symbolicPage, the comparison is not valid return ((other instanceof SymbolicPage) && realPage.equals(((SymbolicPage) other).realPage)) || realPage.equals(other); } @Override public int hashCode() { return realPage.hashCode(); } public static boolean containsWikitext(WikiPage wikiPage) { if (wikiPage instanceof SymbolicPage) { return containsWikitext(((SymbolicPage) wikiPage).realPage); } else { return wikiPage instanceof WikitextPage; } } }