package fitnesse.responders.refactoring; import fitnesse.FitNesseContext; import fitnesse.Responder; import fitnesse.authentication.AlwaysSecureOperation; import fitnesse.authentication.SecureOperation; import fitnesse.authentication.SecureResponder; import fitnesse.wiki.refactoring.ReferenceRenamer; import fitnesse.html.HtmlUtil; import fitnesse.http.Request; import fitnesse.http.Response; import fitnesse.http.SimpleResponse; import fitnesse.responders.ErrorResponder; import fitnesse.responders.NotFoundResponder; import fitnesse.wiki.*; import java.util.List; public abstract class PageMovementResponder implements SecureResponder { protected String oldNameOfPageToBeMoved; protected WikiPage oldRefactoredPage; protected WikiPage newParentPage; protected WikiPagePath newParentPath; protected abstract boolean getAndValidateNewParentPage(FitNesseContext context, Request request); protected abstract boolean getAndValidateRefactoringParameters(Request request); protected abstract ReferenceRenamer getReferenceRenamer(FitNesseContext context); protected abstract String getNewPageName(); protected abstract String getErrorMessageHeader(); protected abstract void execute() throws RefactorException; @Override public Response makeResponse(FitNesseContext context, Request request) throws Exception { if (!getAndValidateRefactoredPage(context, request)) { return new NotFoundResponder().makeResponse(context, request); } if (!getAndValidateNewParentPage(context, request)) { return makeErrorMessageResponder(newParentPath == null ? "null" : newParentPath.toString() + " does not exist.").makeResponse(context, request); } if (!getAndValidateRefactoringParameters(request)) { return makeErrorMessageResponder("").makeResponse(context, request); } if (targetPageExists()) { return makeErrorMessageResponder(makeLink(getNewPageName()) + " already exists").makeResponse(context, request); } if (request.hasInput("refactorReferences")) { getReferenceRenamer(context).renameReferences(); } execute(); SimpleResponse response = new SimpleResponse(); response.redirect(context.contextRoot, createRedirectionUrl(newParentPage, getNewPageName())); return response; } protected boolean getAndValidateRefactoredPage(FitNesseContext context, Request request) { oldNameOfPageToBeMoved = request.getResource(); WikiPagePath path = PathParser.parse(oldNameOfPageToBeMoved); oldRefactoredPage = context.getRootPage().getPageCrawler().getPage(path); return (oldRefactoredPage != null); } private Responder makeErrorMessageResponder(String message) { return new ErrorResponder(getErrorMessageHeader() + " " + message); } private boolean targetPageExists() { return newParentPage.hasChildPage(getNewPageName()); } protected String makeLink(String page) { return HtmlUtil.makeLink(page, page).html(); } protected String createRedirectionUrl(WikiPage newParent, String newName) { if(newParent.isRoot()) { return newName; } PageCrawler crawler = newParent.getPageCrawler(); return PathParser.render(crawler.getFullPath().addNameToEnd(newName)); } protected void movePage(WikiPage movedPage, WikiPage newParentPage, String pageName) throws RefactorException { if (isSymlinkedPage(movedPage)) { if (isSymlinkedPage(movedPage.getParent())) { throw new RefactorException("Can not move symlink page when parent page is also a symlink"); } WikiPage referencedPage = ((SymbolicPage) movedPage).getRealPage(); removeSymlink(movedPage); createSymlink(referencedPage, newParentPage, pageName); } else { PageData pageData = movedPage.getData(); WikiPage targetPage = newParentPage.addChildPage(pageName); targetPage.commit(pageData); moveChildren(movedPage, targetPage); movedPage.remove(); } } protected void moveChildren(WikiPage movedPage, WikiPage newParentPage) throws RefactorException { List<WikiPage> children = movedPage.getChildren(); for (WikiPage page : children) { movePage(page, newParentPage, page.getName()); } } private boolean isSymlinkedPage(WikiPage page) { return page instanceof SymbolicPage; } private void removeSymlink(WikiPage movedPage) { WikiPage parent = movedPage.getParent(); PageData data = parent.getData(); WikiPageProperty symLinks = data.getProperties().getProperty(SymbolicPage.PROPERTY_NAME); symLinks.remove(movedPage.getName()); parent.commit(data); } private void createSymlink(WikiPage referencedPage, WikiPage newParentPage, String pageName) { PageData newParentData = newParentPage.getData(); WikiPageProperty symLinks = newParentData.getProperties().getProperty(SymbolicPage.PROPERTY_NAME); WikiPagePath fullPath; if (isChildOf(referencedPage, oldRefactoredPage)) { // Watch out: the referenced page will also be moved WikiPagePath relativePath = PathParser.parse(oldRefactoredPage.getParent().getPageCrawler().getRelativeName(referencedPage)); fullPath = this.newParentPage.getPageCrawler().getFullPathOfChild(relativePath); } else { fullPath = referencedPage.getPageCrawler().getFullPath(); } fullPath.makeAbsolute(); symLinks.set(pageName, PathParser.render(fullPath)); newParentPage.commit(newParentData); } private boolean isChildOf(WikiPage childPage, WikiPage parentPage) { String childPath = PathParser.render(childPage.getPageCrawler().getFullPath()); String parentPath = PathParser.render(parentPage.getPageCrawler().getFullPath()); return childPath.startsWith(parentPath); } @Override public SecureOperation getSecureOperation() { return new AlwaysSecureOperation(); } }