001: // Copyright (C) 2003,2004,2005 by Object Mentor, Inc. All rights reserved.
002: // Released under the terms of the GNU General Public License version 2 or later.
003: package fitnesse.wiki;
004:
005: import fitnesse.components.FitNesseTraversalListener;
006:
007: import java.util.*;
008:
009: public class PageCrawlerImpl implements PageCrawler {
010: private PageCrawlerDeadEndStrategy deadEndStrategy;
011:
012: protected PageCrawlerImpl() {
013: }
014:
015: public WikiPage getPage(WikiPage context, WikiPagePath path)
016: throws Exception {
017: if (path == null)
018: return null;
019:
020: if (isRoot(path))
021: return getRoot(context);
022:
023: if (path.isEmpty())
024: return context;
025:
026: if (path.isAbsolute()) {
027: WikiPagePath relativeToRoot = new WikiPagePath(path);
028: relativeToRoot.setPathMode(WikiPagePath.Mode.RELATIVE);
029: return getPage(getRoot(context), relativeToRoot);
030: }
031: String firstPathElement = path.getFirst();
032: WikiPagePath restOfPath = path.getRest();
033:
034: WikiPage childPage = context.getChildPage(firstPathElement);
035: if (childPage != null)
036: return getPage(childPage, restOfPath);
037: else
038: return getPageAfterDeadEnd(context, firstPathElement,
039: restOfPath);
040: }
041:
042: private boolean isRoot(WikiPagePath path) {
043: return path.isAbsolute() && path.isEmpty();
044: }
045:
046: protected WikiPage getPageAfterDeadEnd(WikiPage context,
047: String first, WikiPagePath rest) throws Exception {
048: rest.addNameToFront(first);
049: if (deadEndStrategy != null)
050: return deadEndStrategy.getPageAfterDeadEnd(context, rest,
051: this );
052: else
053: return null;
054: }
055:
056: public void setDeadEndStrategy(PageCrawlerDeadEndStrategy strategy) {
057: deadEndStrategy = strategy;
058: }
059:
060: public boolean pageExists(WikiPage context, WikiPagePath path)
061: throws Exception {
062: return getPage(context, path) != null;
063: }
064:
065: public WikiPagePath getFullPathOfChild(WikiPage parent,
066: WikiPagePath childPath) throws Exception {
067: WikiPagePath fullPathOfChild;
068: if (childPath.isAbsolute())
069: fullPathOfChild = childPath.relativePath();
070: else {
071: WikiPagePath absolutePathOfParent = new WikiPagePath(parent);
072: fullPathOfChild = absolutePathOfParent.append(childPath);
073: }
074: return fullPathOfChild;
075: }
076:
077: public WikiPagePath getFullPath(WikiPage page) throws Exception {
078: return new WikiPagePath(page);
079: }
080:
081: public WikiPage addPage(WikiPage context, WikiPagePath path,
082: String content) throws Exception {
083: WikiPage page = addPage(context, path);
084: if (page != null) {
085: PageData data = new PageData(page);
086: data.setContent(content);
087: page.commit(data);
088: }
089: return page;
090: }
091:
092: public WikiPage addPage(WikiPage context, WikiPagePath path)
093: throws Exception {
094: return getOrMakePage(context, path.getNames());
095: }
096:
097: private WikiPage getOrMakePage(WikiPage context, List namePieces)
098: throws Exception {
099: String first = (String) namePieces.get(0);
100: List rest = namePieces.subList(1, namePieces.size());
101: WikiPage current;
102: if (context.getChildPage(first) == null)
103: current = context.addChildPage(first);
104: else
105: current = context.getChildPage(first);
106: if (rest.size() == 0)
107: return current;
108: return getOrMakePage(current, rest);
109: }
110:
111: public String getRelativeName(WikiPage base, WikiPage page)
112: throws Exception {
113: StringBuffer qualName = new StringBuffer();
114: for (WikiPage p = page; !isRoot(p) && p != base; p = p
115: .getParent()) {
116: if (p != page)
117: qualName.insert(0, ".");
118: qualName.insert(0, p.getName());
119: }
120: return qualName.toString();
121: }
122:
123: //TODO this doesn't belong here
124: public static WikiPage getInheritedPage(String pageName,
125: WikiPage context) throws Exception {
126: List<WikiPage> ancestors = WikiPageUtil
127: .getAncestorsStartingWith(context);
128: for (WikiPage ancestor : ancestors) {
129: WikiPage namedPage = ancestor.getChildPage(pageName);
130: if (namedPage != null)
131: return namedPage;
132: }
133: return null;
134: }
135:
136: public boolean isRoot(WikiPage page) throws Exception {
137: WikiPage parent = page.getParent();
138: return parent == null || parent == page;
139: }
140:
141: public WikiPage getRoot(WikiPage page) throws Exception {
142: if (isRoot(page))
143: return page;
144: else
145: return getRoot(page.getParent());
146: }
147:
148: public void traverse(WikiPage context,
149: FitNesseTraversalListener listener) throws Exception {
150: if (context.getClass() == SymbolicPage.class)
151: return;
152: //TODO MdM Catch any exception thrown by the following and add the page name to the Exception message.
153: listener.processPage(context);
154: List children = context.getChildren();
155: for (Iterator iterator = children.iterator(); iterator
156: .hasNext();) {
157: WikiPage wikiPage = (WikiPage) iterator.next();
158: traverse(wikiPage, listener);
159: }
160: }
161:
162: /*
163: Todo: RcM. All calls to getPage should actually come here,
164: and be relative to the current page, not the parent page.
165: It was a gross error to have the whole wiki know that references
166: were relative to the parent instead of the page.
167: */
168: public WikiPage getSiblingPage(WikiPage page,
169: WikiPagePath pathRelativeToSibling) throws Exception {
170: PageCrawler crawler = page.getPageCrawler();
171: if (pathRelativeToSibling.isSubPagePath()) {
172: WikiPagePath relativePath = new WikiPagePath(
173: pathRelativeToSibling);
174: relativePath.setPathMode(WikiPagePath.Mode.RELATIVE);
175: return getPage(page, relativePath);
176: } else if (pathRelativeToSibling.isBackwardSearchPath()) {
177: String target = pathRelativeToSibling.getFirst();
178: for (WikiPage current = page.getParent(); !crawler
179: .isRoot(current); current = current.getParent()) {
180: if (current.getName().equals(target))
181: return getPage(current, pathRelativeToSibling
182: .getRest());
183: }
184: WikiPagePath absolutePath = new WikiPagePath(
185: pathRelativeToSibling);
186: absolutePath.makeAbsolute();
187: return getPage(crawler.getRoot(page), absolutePath);
188: } else {
189: WikiPage parent = page.getParent();
190: return getPage(parent, pathRelativeToSibling);
191: }
192: }
193: }
|