package fitnesse.wiki; import fitnesse.wikitext.parser.Symbol; import org.apache.commons.lang.StringUtils; import java.util.Arrays; import java.util.List; public class WikiWordReference { private WikiPage currentPage; private String wikiWord; public WikiWordReference(WikiPage currentPage, String wikiWord) { this.currentPage = currentPage; this.wikiWord = wikiWord; } public WikiPage getReferencedPage() { String theWord = expandPrefix(currentPage, wikiWord); WikiPage parentPage = currentPage.getParent(); return parentPage.getPageCrawler().getPage(PathParser.parse(theWord)); } public static String expandPrefix(WikiPage wikiPage, String theWord) { if (theWord.charAt(0) == '^' || theWord.charAt(0) == '>') { String prefix = wikiPage.getName(); return String.format("%s.%s", prefix, theWord.substring(1)); } else if (theWord.charAt(0) == '<') { String undecoratedPath = theWord.substring(1); String[] pathElements = undecoratedPath.split("\\."); String target = pathElements[0]; for (WikiPage current = wikiPage.getParent(); !current.isRoot(); current = current.getParent()) { if (current.getName().equals(target)) { pathElements[0] = PathParser.render(current.getPageCrawler().getFullPath()); return "." + StringUtils.join(Arrays.asList(pathElements), "."); } } return "." + undecoratedPath; } return theWord; } public void wikiWordRenameMovedPageIfReferenced(Symbol wikiWord, WikiPage pageToBeMoved, String newParentName) { WikiPagePath pathOfPageToBeMoved = pageToBeMoved.getPageCrawler().getFullPath(); pathOfPageToBeMoved.makeAbsolute(); String qualifiedNameOfPageToBeMoved = PathParser.render(pathOfPageToBeMoved); String reference = getQualifiedWikiWord(wikiWord.getContent()); if (refersTo(reference, qualifiedNameOfPageToBeMoved)) { String referenceTail = reference.substring(qualifiedNameOfPageToBeMoved.length()); String childPortionOfReference = pageToBeMoved.getName(); if (!referenceTail.isEmpty()) childPortionOfReference += referenceTail; String newQualifiedName; if ("".equals(newParentName)) newQualifiedName = "." + childPortionOfReference; else newQualifiedName = "." + newParentName + "." + childPortionOfReference; wikiWord.setContent(newQualifiedName); } } private String getQualifiedWikiWord(String wikiWordText) { String pathName = expandPrefix(currentPage, wikiWordText); WikiPagePath expandedPath = PathParser.parse(pathName); if (expandedPath == null) return wikiWordText; WikiPagePath fullPath = currentPage.getParent().getPageCrawler().getFullPathOfChild(expandedPath); return "." + PathParser.render(fullPath); //todo rcm 2/6/05 put that '.' into pathParser. Perhaps WikiPagePath.setAbsolute() } private boolean refersTo(String qualifiedReference, String qualifiedTarget) { return qualifiedReference.equals(qualifiedTarget) || qualifiedReference.startsWith(qualifiedTarget + "."); } public void wikiWordRenamePageIfReferenced(Symbol wikiWord, WikiPage pageToRename, String newName) { String fullPathToReferent = getQualifiedWikiWord(wikiWord.getContent()); WikiPagePath pathToPageBeingRenamed = pageToRename.getPageCrawler().getFullPath(); pathToPageBeingRenamed.makeAbsolute(); String absolutePathToPageBeingRenamed = PathParser.render(pathToPageBeingRenamed); if (refersTo(fullPathToReferent, absolutePathToPageBeingRenamed)) { int oldNameLength = absolutePathToPageBeingRenamed.length(); String renamedPath = "." + rename(absolutePathToPageBeingRenamed.substring(1), newName); String pathAfterRenamedPage = fullPathToReferent.substring(oldNameLength); String fullRenamedPathToReferent = renamedPath + pathAfterRenamedPage; String renamedReference = makeRenamedRelativeReference(wikiWord.getContent(), PathParser.parse(fullRenamedPathToReferent)); wikiWord.setContent(renamedReference); } } private String rename(String oldQualifiedName, String newPageName) { String newQualifiedName; int lastDotIndex = oldQualifiedName.lastIndexOf("."); if (lastDotIndex < 1) newQualifiedName = newPageName; else newQualifiedName = oldQualifiedName.substring(0, lastDotIndex + 1) + newPageName; return newQualifiedName; } private String makeRenamedRelativeReference(String wikiWordText, WikiPagePath renamedPathToReferent) { WikiPage parent = currentPage.getParent(); WikiPagePath parentPath = parent.getPageCrawler().getFullPath(); parentPath.makeAbsolute(); if (wikiWordText.startsWith(".")) return PathParser.render(renamedPathToReferent); else if (wikiWordText.startsWith("<")) { return buildBackwardSearchReference(parentPath, renamedPathToReferent); } else { boolean parentPathNotRenamed = renamedPathToReferent.startsWith(parentPath); if (parentPathNotRenamed) { WikiPagePath relativePath = renamedPathToReferent.subtractFromFront(parentPath); if (wikiWordText.startsWith("^") || wikiWordText.startsWith(">")) return ">" + PathParser.render(relativePath.getRest()); else return PathParser.render(relativePath); } } return wikiWordText; } private String buildBackwardSearchReference(WikiPagePath parentPath, WikiPagePath renamedPathToReferent) { int branchPoint = findBranchPoint(parentPath.getNames(), renamedPathToReferent.getNames()); List<String> referentPath = renamedPathToReferent.getNames(); List<String> referentPathAfterBranchPoint = referentPath.subList(branchPoint, referentPath.size()); return "<" + StringUtils.join(referentPathAfterBranchPoint, "."); } private int findBranchPoint(List<String> list1, List<String> list2) { int i; for (i = 0; i < list1.size(); i++) { if (!list1.get(i).equals(list2.get(i))) break; } return Math.max(0, i - 1); } }