package org.codehaus.xsite.io;

import java.util.List;
import java.util.Iterator;
import java.util.Collection;
import java.util.HashSet;

import org.codehaus.xsite.model.Page;
import org.codehaus.xsite.model.SiteMap;


/**
 * Verifies all the links in a SiteMap.
 *
 * @author Joe Walnes
 */
public class LinkChecker {

    private final Collection knownPageFileNames;
    private final SiteMap siteMap;
    private final Reporter reporter;

    /**
     * Callback for errors.
     */
    public static interface Reporter {
        void badLink(Page page, String link);
    }

    public LinkChecker(SiteMap siteMap, Reporter reporter) {
        this.siteMap = siteMap;
        this.reporter = reporter;
        knownPageFileNames = new HashSet();
        List allPages = siteMap.getAllPages();
        for (Iterator iterator = allPages.iterator(); iterator.hasNext();) {
            Page page = (Page) iterator.next();
            knownPageFileNames.add(page.getFilename());
        }
    }

    /**
     * Verifies all the links in the site. Returns true if all links are valid.
     * @return
     */
    public boolean verify() {
        boolean success = true;
        List allPages = siteMap.getAllPages();
        for (Iterator iterator = allPages.iterator(); iterator.hasNext();) {
            Page page = (Page) iterator.next();
            Collection links = page.getLinks();
            for (Iterator iterator1 = links.iterator(); iterator1.hasNext();) {
                String link = (String) iterator1.next();
                if (!verifyLink(link)) {
                    success = false;
                    reporter.badLink(page, link);
                }
            }
        }
        return success;
    }

    protected boolean verifyLink(String link) {
        if (link.startsWith("mailto:")) {
            // todo: valid email addresses should be cofigurable
            return true;
        } else if (link.startsWith("http://")) {
            // todo: HTTP get this address to check it's valid (cache result)
            return true;
        } else if (link.startsWith("javadoc/")) {
            // todo: Check the class is valid
            return true;
        } else if (knownPageFileNames.contains(link)) {
            return true;
        } else {
            return false;
        }
    }

}

@@ -1890,32 +1890,110 @@
    return true;%0A
+        %7D else if (link.startsWith(%22javascript:%22)) %7B%0A            return true;%0A
         %7D else i
@@ -2168,19 +2168,200 @@
 th(%22
-javadoc/
+nntp://%22)) %7B%0A            // todo: News get this address to check it's valid (cache result)%0A            return true;%0A        %7D else if (link.startsWith(siteMap.getProperty(%22javadoc-location
 %22))
+)
  %7B%0A 
@@ -2395,16 +2395,24 @@
 he class
+/package
  is vali
@@ -2449,24 +2449,330 @@
      %7D else 
+%7B%0A            int anchorIdx = link.lastIndexOf('#');%0A            if (anchorIdx %3E= 0) %7B%0A                // todo: Check anchors%0A                if (anchorIdx == 0) %7B%0A                    return true;%0A                %7D%0A                link = link.substring(0, link.lastIndexOf('#'));%0A            %7D%0A            
 if (knownPag
@@ -2804,32 +2804,36 @@
 ) %7B%0A            
+    
 return true;%0A   
@@ -2833,37 +2833,40 @@
 ue;%0A        
-%7D else %7B
+    %7D
 %0A    
+    %7D%0A
         retu
@@ -2875,26 +2875,16 @@
  false;%0A
-        %7D%0A
     %7D%0A%0A%7D

Support for Javascript links. Support for links to usenet. Support anchors in links. Support configurable javadoc links.