maven report plugin to generate faqsuck
authorEric Barboni <skygo@netbeans.org>
Sat, 01 Mar 2014 20:06:26 +0100
changeset 1817557c4978c92ee
parent 18174 7af3bc4f762c
child 18176 bd79fb664e73
maven report plugin to generate faqsuck
also list external link in a report
it contains idea and code of Tim Boudreau from http://hg.netbeans.org/main/contrib/file/tip/other/faqsuck

mvn clean install site
other/wikitools/faqsuckplugin/pom.xml
other/wikitools/faqsuckplugin/src/main/java/org/netbeans/contrib/faqsuck/Category.java
other/wikitools/faqsuckplugin/src/main/java/org/netbeans/contrib/faqsuck/Entry.java
other/wikitools/faqsuckplugin/src/main/java/org/netbeans/contrib/faqsuck/FaqUtils.java
other/wikitools/faqsuckplugin/src/main/java/org/netbeans/contrib/faqsuck/FaqsuckMojo.java
other/wikitools/faqsuckplugin/src/main/java/org/netbeans/contrib/faqsuck/Reporter.java
other/wikitools/faqsuckplugin/src/main/java/org/netbeans/contrib/faqsuck/package-info.java
other/wikitools/faqsuckplugin/src/main/java/org/netbeans/contrib/wikitools/spi/WikiTasks.java
other/wikitools/faqsuckplugin/src/main/java/org/netbeans/contrib/wikitools/wikis/WikiTask1151.java
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/other/wikitools/faqsuckplugin/pom.xml	Sat Mar 01 20:06:26 2014 +0100
     1.3 @@ -0,0 +1,121 @@
     1.4 +<?xml version="1.0" encoding="UTF-8"?>
     1.5 +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
     1.6 +    <modelVersion>4.0.0</modelVersion>
     1.7 +    <groupId>org.netbeans.contrib</groupId>
     1.8 +    <artifactId>faqsuck</artifactId>
     1.9 +    <version>1.0-SNAPSHOT</version>
    1.10 +    <packaging>maven-plugin</packaging>
    1.11 +    <dependencies>
    1.12 +        <dependency>
    1.13 +            <groupId>org.jsoup</groupId>
    1.14 +            <artifactId>jsoup</artifactId>
    1.15 +            <version>1.7.3</version>
    1.16 +        </dependency>
    1.17 +        <dependency>
    1.18 +            <groupId>org.apache.maven</groupId>
    1.19 +            <artifactId>maven-plugin-api</artifactId>
    1.20 +            <version>3.0.5</version>
    1.21 +        </dependency>
    1.22 +        <dependency>
    1.23 +            <groupId>org.apache.maven.plugin-tools</groupId>
    1.24 +            <artifactId>maven-plugin-annotations</artifactId>
    1.25 +            <version>3.2</version>
    1.26 +        </dependency>
    1.27 +        <dependency>
    1.28 +            <artifactId>org-openide-util-lookup</artifactId>
    1.29 +            <groupId>org.netbeans.api</groupId>
    1.30 +            <type>jar</type>
    1.31 +            <version>RELEASE80-BETA</version>
    1.32 +        </dependency>
    1.33 +        <dependency>
    1.34 +            <groupId>org.apache.maven.reporting</groupId>
    1.35 +            <artifactId>maven-reporting-impl</artifactId>
    1.36 +            <version>2.2</version>
    1.37 +            <type>jar</type>
    1.38 +        </dependency>
    1.39 +    </dependencies>
    1.40 +    <properties>
    1.41 +        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    1.42 +        <maven.compiler.source>1.7</maven.compiler.source>
    1.43 +        <maven.compiler.target>1.7</maven.compiler.target>
    1.44 +    </properties>
    1.45 +    <build>
    1.46 +        <plugins>
    1.47 +            <plugin>
    1.48 +                <groupId>org.apache.maven.plugins</groupId>
    1.49 +                <artifactId>maven-plugin-plugin</artifactId>
    1.50 +                <version>3.2</version>
    1.51 +                <configuration>
    1.52 +                    <!-- see http://jira.codehaus.org/browse/MNG-5346 -->
    1.53 +                    <skipErrorNoDescriptorsFound>true</skipErrorNoDescriptorsFound>
    1.54 +                </configuration>
    1.55 +                <executions>
    1.56 +                    <execution>
    1.57 +                        <id>mojo-descriptor</id>
    1.58 +                        <goals>
    1.59 +                            <goal>descriptor</goal>
    1.60 +                        </goals>
    1.61 +                    </execution>
    1.62 +                    <!-- if you want to generate help goal -->
    1.63 +                    <execution>
    1.64 +                        <id>help-goal</id>
    1.65 +                        <goals>
    1.66 +                            <goal>helpmojo</goal>
    1.67 +                        </goals>
    1.68 +                    </execution>
    1.69 +                </executions>
    1.70 +            </plugin>
    1.71 +            
    1.72 +        </plugins>
    1.73 +    </build>
    1.74 +    <reporting>
    1.75 +        <plugins>
    1.76 +            <plugin>        
    1.77 +                <groupId>org.apache.maven.plugins</groupId>
    1.78 +                <artifactId>maven-project-info-reports-plugin</artifactId>
    1.79 +                <version>2.7</version>     
    1.80 +                <reportSets>
    1.81 +                    <reportSet>
    1.82 +                        <reports>
    1.83 +                            <report>index</report>   
    1.84 +                        </reports>   
    1.85 +                    </reportSet>
    1.86 +                </reportSets>  
    1.87 +            </plugin>
    1.88 +            <plugin>
    1.89 +                <groupId>${project.groupId}</groupId>
    1.90 +                <artifactId>${project.artifactId}</artifactId>
    1.91 +                <version>${project.version}</version>
    1.92 +                <configuration>
    1.93 +                    <mainURL>http://wiki.netbeans.org</mainURL>
    1.94 +                </configuration>
    1.95 +                <reportSets>
    1.96 +                    <reportSet>
    1.97 +                        <id>1</id>
    1.98 +                        <configuration>
    1.99 +                            <faqTOC>http://wiki.netbeans.org/NetBeansDeveloperFAQ</faqTOC>
   1.100 +                            <faqFile>${project.build.directory}/faqsuck/faq.html</faqFile>
   1.101 +                        </configuration>
   1.102 +                        
   1.103 +                        <reports>
   1.104 +                            <report>faqsuck</report>
   1.105 +                        </reports>
   1.106 +                       
   1.107 +                    </reportSet>
   1.108 +                </reportSets>
   1.109 +                <!--<execution>
   1.110 +                    <id>2</id>
   1.111 +                    <configuration>
   1.112 +                        <faqTOC>aadsda</faqTOC>
   1.113 +                    </configuration>
   1.114 +                    <phase>install</phase>
   1.115 +                    <goals>
   1.116 +                        <goal>faqsuck</goal>
   1.117 +                    </goals>
   1.118 +                </execution>-->
   1.119 +               
   1.120 +            </plugin>
   1.121 +        </plugins>
   1.122 +    </reporting>
   1.123 +    
   1.124 +</project>
   1.125 \ No newline at end of file
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/other/wikitools/faqsuckplugin/src/main/java/org/netbeans/contrib/faqsuck/Category.java	Sat Mar 01 20:06:26 2014 +0100
     2.3 @@ -0,0 +1,114 @@
     2.4 +/*
     2.5 + * To change this template, choose Tools | Templates
     2.6 + * and open the template in the editor.
     2.7 + */
     2.8 +package org.netbeans.contrib.faqsuck;
     2.9 +
    2.10 +import java.io.IOException;
    2.11 +import java.util.ArrayList;
    2.12 +import java.util.List;
    2.13 +import org.netbeans.contrib.wikitools.spi.WikiTasks;
    2.14 +
    2.15 +/**
    2.16 + *
    2.17 + * @author Tim Boudreau
    2.18 + * 
    2.19 + * 
    2.20 + */
    2.21 +public class Category {
    2.22 +
    2.23 +    public final String title;
    2.24 +    private final List<Entry> entries = new ArrayList<>();
    2.25 +    private final String id;
    2.26 +
    2.27 +    public Category(String title, String id) {
    2.28 +        this.title = title;
    2.29 +        this.id = id;
    2.30 +    }
    2.31 +
    2.32 +    public void addEntry(Entry entry) {
    2.33 +        entries.add(entry);
    2.34 +    }
    2.35 +
    2.36 +    public List<? extends Entry> entries() {
    2.37 +        return entries;
    2.38 +    }
    2.39 +
    2.40 +    @Override
    2.41 +    public boolean equals(Object obj) {
    2.42 +        if (obj == null) {
    2.43 +            return false;
    2.44 +        }
    2.45 +        if (getClass() != obj.getClass()) {
    2.46 +            return false;
    2.47 +        }
    2.48 +        final Category other = (Category) obj;
    2.49 +        return !((this.title == null) ? (other.title != null) : !this.title.equals(other.title));
    2.50 +    }
    2.51 +
    2.52 +    @Override
    2.53 +    public int hashCode() {
    2.54 +        int hash = 7;
    2.55 +        hash = 53 * hash + (this.title != null ? this.title.hashCode() : 0);
    2.56 +        return hash;
    2.57 +    }
    2.58 +
    2.59 +    @Override
    2.60 +    public String toString() {
    2.61 +        return title;
    2.62 +    }
    2.63 +
    2.64 +    public boolean allExternal() {
    2.65 +        boolean result = true;
    2.66 +        for (Entry entry : entries) {
    2.67 +            result &= entry.isExternal();
    2.68 +        }
    2.69 +        return result;
    2.70 +    }
    2.71 +
    2.72 +    public String toTocHtml() throws IOException {
    2.73 +        StringBuilder sb = new StringBuilder();
    2.74 +        sb.append("  <li class=\"tocCategory\"><a href=\"#").append(id).append("\"><b>");
    2.75 +        sb.append(title).append("</b></a>");
    2.76 +        sb.append('\n');
    2.77 +
    2.78 +        sb.append("    <ul>\n");
    2.79 +        int ix = 0;
    2.80 +        for (Entry entry : entries) {
    2.81 +            if (!entry.isExternal()) {
    2.82 +                sb.append("    <li>");
    2.83 +                sb.append(entry.getTocHtml());
    2.84 +                sb.append("</li>\n");
    2.85 +            }
    2.86 +            ix++;
    2.87 +            if (ix > FaqUtils.LIMIT) { //for debugging w/o reading all entries
    2.88 +                break;
    2.89 +            }
    2.90 +        }
    2.91 +        sb.append("</ul>\n");
    2.92 +        sb.append("  </li>\n");
    2.93 +
    2.94 +        return sb.toString();
    2.95 +    }
    2.96 +
    2.97 +    public String toBodyHtml(WikiTasks wt, FaqsuckMojo mojo) throws IOException {
    2.98 +        StringBuilder sb = new StringBuilder();
    2.99 +        sb.append("<h3 class=\"catTitle\" id=\"").append(id).append("\">");
   2.100 +        sb.append(title);
   2.101 +        sb.append("</h3>");
   2.102 +        int ix = 0;
   2.103 +        for (Entry entry : entries) {
   2.104 +            if (!entry.isExternal()) {
   2.105 +                sb.append(entry.toHtml(wt, mojo));
   2.106 +                sb.append('\n');
   2.107 +                sb.append('\n');
   2.108 +            }
   2.109 +            ix++;
   2.110 +            if (ix > FaqUtils.LIMIT) { //for debugging w/o reading all entries
   2.111 +                break;
   2.112 +            }
   2.113 +        }
   2.114 +        return sb.toString();
   2.115 +    }
   2.116 +
   2.117 +}
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/other/wikitools/faqsuckplugin/src/main/java/org/netbeans/contrib/faqsuck/Entry.java	Sat Mar 01 20:06:26 2014 +0100
     3.3 @@ -0,0 +1,85 @@
     3.4 +/*
     3.5 + * To change this template, choose Tools | Templates
     3.6 + * and open the template in the editor.
     3.7 + */
     3.8 +package org.netbeans.contrib.faqsuck;
     3.9 +
    3.10 +import java.io.IOException;
    3.11 +import java.net.URL;
    3.12 +import org.jsoup.Jsoup;
    3.13 +import org.jsoup.nodes.Document;
    3.14 +import org.netbeans.contrib.wikitools.spi.WikiTasks;
    3.15 +
    3.16 +/**
    3.17 + *
    3.18 + * @author Tim Boudreau
    3.19 + */
    3.20 +public class Entry {
    3.21 +
    3.22 +    public final String url;
    3.23 +    public final String title;
    3.24 +    public final String baseUrl;
    3.25 +
    3.26 +    public Entry(String url, String title, String baseUrl) {
    3.27 +        this.url = url;
    3.28 +        this.title = title;
    3.29 +        this.baseUrl = baseUrl;
    3.30 +    }
    3.31 +
    3.32 +    @Override
    3.33 +    public boolean equals(Object obj) {
    3.34 +        if (obj == null) {
    3.35 +            return false;
    3.36 +        }
    3.37 +        if (getClass() != obj.getClass()) {
    3.38 +            return false;
    3.39 +        }
    3.40 +        final Entry other = (Entry) obj;
    3.41 +        return !((this.url == null) ? (other.url != null) : !this.url.equals(other.url));
    3.42 +    }
    3.43 +
    3.44 +    @Override
    3.45 +    public int hashCode() {
    3.46 +        int hash = 5;
    3.47 +        hash = 73 * hash + (this.url != null ? this.url.hashCode() : 0);
    3.48 +        return hash;
    3.49 +    }
    3.50 +
    3.51 +    @Override
    3.52 +    public String toString() {
    3.53 +        return title + "(" + url + ")";
    3.54 +    }
    3.55 +
    3.56 +    public String getName() {
    3.57 +        int ix = url.lastIndexOf("/");
    3.58 +        return url.substring(ix + 1);
    3.59 +    }
    3.60 +
    3.61 +    public boolean isExternal() {
    3.62 +        return url.startsWith("http") || url.startsWith("file");
    3.63 +    }
    3.64 +
    3.65 +    public String getTocHtml() {
    3.66 +        return "<a href=\"#" + url.substring(1) + "\">" + title + "</a>";
    3.67 +    }
    3.68 +
    3.69 +    public String toHtml(WikiTasks wt, FaqsuckMojo mojo) throws IOException {
    3.70 +        StringBuilder sb = new StringBuilder("\n<h4 class=\"itemTitle\" id=\"" + getName() + "\">");
    3.71 +        sb.append(title);
    3.72 +        sb.append("<a href=\"#TOC\" style=\"font-size:small\">Back to top</a>" + "</h4>\n");
    3.73 +        Document document = Jsoup.connect(baseUrl + this.url).get();
    3.74 +        System.err.println("Read " + url);
    3.75 +        sb.append(wt.strip(document, mojo, this));
    3.76 +        return sb.toString();
    3.77 +
    3.78 +    }
    3.79 +
    3.80 +    public URL getWebUrl() throws IOException {
    3.81 +        if (isExternal()) {
    3.82 +            return new URL(url);
    3.83 +        } else {
    3.84 +            return new URL(baseUrl + url);
    3.85 +        }
    3.86 +    }
    3.87 +   
    3.88 +}
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/other/wikitools/faqsuckplugin/src/main/java/org/netbeans/contrib/faqsuck/FaqUtils.java	Sat Mar 01 20:06:26 2014 +0100
     4.3 @@ -0,0 +1,42 @@
     4.4 +/*
     4.5 + * To change this license header, choose License Headers in Project Properties.
     4.6 + * To change this template file, choose Tools | Templates
     4.7 + * and open the template in the editor.
     4.8 + */
     4.9 +package org.netbeans.contrib.faqsuck;
    4.10 +
    4.11 +import org.apache.maven.plugin.MojoExecutionException;
    4.12 +import org.jsoup.nodes.Document;
    4.13 +import org.jsoup.nodes.Element;
    4.14 +import org.jsoup.select.Elements;
    4.15 +import org.netbeans.contrib.wikitools.spi.WikiTasks;
    4.16 +import org.openide.util.Lookup;
    4.17 +
    4.18 +/**
    4.19 + *
    4.20 + * @author Eric
    4.21 + */
    4.22 +public class FaqUtils {
    4.23 +
    4.24 +    private FaqUtils() {
    4.25 +    }
    4.26 +    public static final int LIMIT = Integer.MAX_VALUE; //set to 3 during development
    4.27 +
    4.28 +    static WikiTasks getWikiTask(Document doc, FaqsuckMojo mojo) throws MojoExecutionException {
    4.29 +        Elements metaElements = doc.select("meta");
    4.30 +        String version = "no";
    4.31 +        for (Element e : metaElements) {
    4.32 +            if (e.attr("name").equals("generator")) {
    4.33 +                version = e.attr("content");
    4.34 +                for (WikiTasks wt : Lookup.getDefault().lookupAll(WikiTasks.class)) {
    4.35 +                    if (wt.getVersion().equals(version)) {
    4.36 +                        return wt;
    4.37 +                    }
    4.38 +                }
    4.39 +            }
    4.40 +        }
    4.41 +        throw new MojoExecutionException("No wiki task for wiki " + version);
    4.42 +    }
    4.43 +
    4.44 +    
    4.45 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/other/wikitools/faqsuckplugin/src/main/java/org/netbeans/contrib/faqsuck/FaqsuckMojo.java	Sat Mar 01 20:06:26 2014 +0100
     5.3 @@ -0,0 +1,229 @@
     5.4 +/*
     5.5 + * To change this license header, choose License Headers in Project Properties.
     5.6 + * To change this template file, choose Tools | Templates
     5.7 + * and open the template in the editor.
     5.8 + */
     5.9 +package org.netbeans.contrib.faqsuck;
    5.10 +
    5.11 +import java.io.BufferedOutputStream;
    5.12 +import java.io.File;
    5.13 +import java.io.FileOutputStream;
    5.14 +import java.io.IOException;
    5.15 +import java.io.PrintStream;
    5.16 +import java.net.URL;
    5.17 +import java.util.ArrayList;
    5.18 +import java.util.Date;
    5.19 +import java.util.List;
    5.20 +import java.util.Locale;
    5.21 +import org.apache.maven.doxia.sink.Sink;
    5.22 +import org.apache.maven.doxia.siterenderer.Renderer;
    5.23 +import org.apache.maven.plugin.MojoExecutionException;
    5.24 +import org.apache.maven.plugins.annotations.Component;
    5.25 +import org.apache.maven.plugins.annotations.Mojo;
    5.26 +import org.apache.maven.plugins.annotations.Parameter;
    5.27 +import org.apache.maven.project.MavenProject;
    5.28 +import org.apache.maven.reporting.AbstractMavenReport;
    5.29 +import org.apache.maven.reporting.MavenReportException;
    5.30 +import org.jsoup.Jsoup;
    5.31 +import org.jsoup.nodes.Document;
    5.32 +import org.netbeans.contrib.wikitools.spi.WikiTasks;
    5.33 +
    5.34 +/**
    5.35 + * main algorithm is inspired by previous work by Tim Boudreau
    5.36 + *
    5.37 + * @author Eric
    5.38 + */
    5.39 +@Mojo(name = "faqsuck", requiresProject = false)
    5.40 +public class FaqsuckMojo extends AbstractMavenReport {
    5.41 +
    5.42 +    /**
    5.43 +     * The greeting to display.
    5.44 +     */
    5.45 +    @Parameter(required = true)
    5.46 +    private URL mainURL;
    5.47 +
    5.48 +    /**
    5.49 +     * The greeting to display.
    5.50 +     */
    5.51 +    @Parameter(required = true)
    5.52 +    private URL faqTOC;
    5.53 +
    5.54 +    /**
    5.55 +     * The greeting to display.
    5.56 +     */
    5.57 +    @Parameter(required = true)
    5.58 +    private File faqFile;
    5.59 +
    5.60 +    @Component
    5.61 +    protected Renderer siteRenderer;
    5.62 +
    5.63 +    private Document tocDocument;
    5.64 +
    5.65 +    // List of url in the toc
    5.66 +    private List<String> knownurl;
    5.67 +    PrintStream outfaq;
    5.68 +    @Parameter(defaultValue = "${project.reporting.outputDirectory}", required = true)
    5.69 +    private File outputDirectory;
    5.70 +
    5.71 +    @Override
    5.72 +    public String getOutputName() {
    5.73 +        return "Netbeans Dev Report";
    5.74 +    }
    5.75 +
    5.76 +    @Override
    5.77 +    public void execute() throws MojoExecutionException {
    5.78 +        try {
    5.79 +            knownurl = new ArrayList<>();
    5.80 +            tocDocument = Jsoup.connect(faqTOC.toExternalForm()).get();
    5.81 +            faqFile.getParentFile().mkdirs();
    5.82 +            Sink sink = getSink();
    5.83 +            Reporter.setup(sink, mainURL.toExternalForm());
    5.84 +            outfaq = new PrintStream(new BufferedOutputStream(new FileOutputStream(faqFile)));
    5.85 +            readCategories(tocDocument);
    5.86 +
    5.87 +        } catch (IOException ex) {
    5.88 +            throw new MojoExecutionException("", ex);
    5.89 +        } finally {
    5.90 +            outfaq.close();
    5.91 +        }
    5.92 +        getLog().info("faqsuck file created in " + faqFile.toString());
    5.93 +    }
    5.94 +
    5.95 +    private void readCategories(Document tocDocument) throws MojoExecutionException, IOException {
    5.96 +
    5.97 +        List<Category> categories = new ArrayList<>();
    5.98 +        getLog().info("reading categories");
    5.99 +        readCategories(mainURL, tocDocument, categories);
   5.100 +        WikiTasks wikitask = FaqUtils.getWikiTask(tocDocument, this);
   5.101 +        wikitask.feedCategory(mainURL, tocDocument, categories, this);
   5.102 +        Reporter.printHead();
   5.103 +        outfaq.println(HEAD);
   5.104 +        outfaq.println("<span class=\"generated\"><i>Generated on " + new Date() + "</i>"
   5.105 +                + " from <a href=\"" + faqTOC.toExternalForm() + "\">" + faqTOC.toExternalForm() + "</a>"
   5.106 +                + "</span><p>&nbsp;</p>");
   5.107 +        outfaq.println("<ul id=\"TOC\">");
   5.108 +        Reporter.addHeader("Issues");
   5.109 +        int ix = 0;
   5.110 +        for (Category c : categories) {
   5.111 +            if (!c.allExternal()) {
   5.112 +                outfaq.println(c.toTocHtml());
   5.113 +            }
   5.114 +            ix++;
   5.115 +            if (ix > FaqUtils.LIMIT) { //for debugging w/o reading all entries
   5.116 +                break;
   5.117 +            }
   5.118 +        }
   5.119 +        outfaq.println("</ul>\n");
   5.120 +        outfaq.println("\n<hr/><p>&nbsp;</p>\n");
   5.121 +        ix = 0;
   5.122 +        for (Category c : categories) {
   5.123 +            if (!c.allExternal()) {
   5.124 +                outfaq.println(c.toBodyHtml(wikitask, this));
   5.125 +            }
   5.126 +            ix++;
   5.127 +            if (ix > FaqUtils.LIMIT) { //for debugging w/o reading all entries
   5.128 +                break;
   5.129 +            }
   5.130 +        }
   5.131 +
   5.132 +        List<Entry> list = new ArrayList<>();
   5.133 +        for (Category c : categories) {
   5.134 +            for (Entry e : c.entries()) {
   5.135 +                if (e.isExternal()) {
   5.136 +                    list.add(e);
   5.137 +                }
   5.138 +            }
   5.139 +        }
   5.140 +        if (!list.isEmpty()) {
   5.141 +            outfaq.println("<p>&nbsp;</p>");
   5.142 +            outfaq.println("<h1>External FAQ Entries</h1>");
   5.143 +            outfaq.println("The following FAQ entries are not hosted in the NetBeans wiki and could not be included:<ul>");
   5.144 +            Reporter.displayBadWiki(list);
   5.145 +            for (Entry e : list) {
   5.146 +                outfaq.println("<li><a target=\"extfaq\" href=\"" + e.url + "\">" + e.title + "</a></li>");
   5.147 +            }
   5.148 +
   5.149 +            outfaq.println("</ul>");
   5.150 +        }
   5.151 +
   5.152 +        Reporter.displayLinks();
   5.153 +
   5.154 +        outfaq.println(FOOT);
   5.155 +        Reporter.printFooter();
   5.156 +    }
   5.157 +
   5.158 +    private void readCategories(URL baseUrl, Document tocContent, List<Category> categories) throws MojoExecutionException, IOException {
   5.159 +
   5.160 +    }
   5.161 +
   5.162 +    private static final String HEAD = "<!DOCTYPE html>\n"
   5.163 +            + "<html>\n"
   5.164 +            + " <head>\n"
   5.165 +            + "  <title>NetBeans Developer FAQ</title>\n"
   5.166 +            + "  <style type=\"text/css\">\n"
   5.167 +            + "    body { margin-left: 1.25em;  margin-right: 1.25em;font-family:\"Verdana\",\"sans-serif\";}\n"
   5.168 +            + "    li {margin-top:0.45em;}\n"
   5.169 +            + "    .catTitle {background-color:#AA3322; color:#FFFFFF; border-color:#AA3322; border-style:solid; border-width:0.37em; margin-top:1em; font-size:1.7em;}\n"
   5.170 +            + "    .itemTitle {color:#AA3322; border-bottom-style:solid; border-bottom-width:2px; border-bottom-color:#DDAA88; margin-top:0.75em; font-size:1.45em;}\n"
   5.171 +            + "    .itemBody {margin-left:1.5em;  margin-right:1.5em;}\n"
   5.172 +            + "    .tocCategory {margin-top: 1.1em; margin-bottom:0.4em;}\n"
   5.173 +            + "    pre { background-color:#FFFFD9; overflow:auto; border: 1px solid #CCCCCC;}\n"
   5.174 +            + "    .generated { font-size:small}\n"
   5.175 +            + "    a.external:after {content:\"\\21D7\";color: #AA3322;font-size:x-small;}\n"
   5.176 +            + "    .trt{font-family: monospace;}\n"
   5.177 +            + "    a.wnetbeans:after{content:\"\\21D7 Netbeans Wiki\";}\n"
   5.178 +            + "    a.jdocnetbeans:after{content:\"\\21D7 APIdoc\";}\n"
   5.179 +            + "    a:link {text-decoration:none;}\n"
   5.180 +            + "    a:visited {text-decoration:none;}\n"
   5.181 +            + "  </style>\n"
   5.182 +            + " </head>\n"
   5.183 +            + "<body>\n"
   5.184 +            + " <h1>NetBeans Developer Faq</h1>";
   5.185 +    private static final String FOOT = "</body>\n"
   5.186 +            + "</html>";
   5.187 +
   5.188 +    public void addTOCURL(String attr) {
   5.189 +        knownurl.add(attr);
   5.190 +    }
   5.191 +
   5.192 +    public List<String> getKnownUrl() {
   5.193 +        return knownurl;
   5.194 +    }
   5.195 +
   5.196 +    @Override
   5.197 +    protected Renderer getSiteRenderer() {
   5.198 +        return siteRenderer;
   5.199 +    }
   5.200 +
   5.201 +    @Override
   5.202 +    protected String getOutputDirectory() {
   5.203 +        return outputDirectory.getAbsolutePath();
   5.204 +    }
   5.205 +
   5.206 +    @Override
   5.207 +    protected MavenProject getProject() {
   5.208 +        throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.
   5.209 +    }
   5.210 +
   5.211 +    @Override
   5.212 +    protected void executeReport(Locale locale) throws MavenReportException {
   5.213 +        if (!outputDirectory.exists()) {
   5.214 +            outputDirectory.mkdirs();
   5.215 +        }
   5.216 +        try {
   5.217 +            this.execute();
   5.218 +        } catch (MojoExecutionException ex) {
   5.219 +            throw new MavenReportException(ex.getMessage(), ex);
   5.220 +        }
   5.221 +    }
   5.222 +
   5.223 +    @Override
   5.224 +    public String getName(Locale locale) {
   5.225 +        return "faqsuck";
   5.226 +    }
   5.227 +
   5.228 +    @Override
   5.229 +    public String getDescription(Locale locale) {
   5.230 +        return "faq suck description";
   5.231 +    }
   5.232 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/other/wikitools/faqsuckplugin/src/main/java/org/netbeans/contrib/faqsuck/Reporter.java	Sat Mar 01 20:06:26 2014 +0100
     6.3 @@ -0,0 +1,150 @@
     6.4 +/*
     6.5 + * To change this license header, choose License Headers in Project Properties.
     6.6 + * To change this template file, choose Tools | Templates
     6.7 + * and open the template in the editor.
     6.8 + */
     6.9 +package org.netbeans.contrib.faqsuck;
    6.10 +
    6.11 +import java.util.ArrayList;
    6.12 +import java.util.List;
    6.13 +import java.util.Map;
    6.14 +import java.util.TreeMap;
    6.15 +import org.apache.maven.doxia.sink.Sink;
    6.16 +
    6.17 +/**
    6.18 + * Manage a web page to help seeking glitch in wiki
    6.19 + *
    6.20 + *
    6.21 + */
    6.22 +public class Reporter {
    6.23 +
    6.24 +    private static final Map<String, List<String>> allURL = new TreeMap<>();
    6.25 +    private static final Map<String, List<String>> apidoc = new TreeMap<>();
    6.26 +    private static final Map<String, List<String>> wikinb = new TreeMap<>();
    6.27 +    private static final Map<String, List<String>> mercurialnb = new TreeMap<>();
    6.28 +    private static final Map<String, List<String>> bugzillanb = new TreeMap<>();
    6.29 +
    6.30 +    private static Sink out1;
    6.31 +    private static String baseUrl;
    6.32 +
    6.33 +    static void printHead() {
    6.34 +        out1.head();
    6.35 +        out1.title();
    6.36 +        out1.text("NetBeans Developer FAQ Log");
    6.37 +        out1.title_();
    6.38 +        out1.head_();
    6.39 +        out1.body();
    6.40 +    }
    6.41 +
    6.42 +    static void setup(Sink printStream, String b) {
    6.43 +        out1 = printStream;
    6.44 +        baseUrl = b;
    6.45 +    }
    6.46 +
    6.47 +    static void addHeader(String sues) {
    6.48 +        out1.sectionTitle2();
    6.49 +        out1.text(sues);
    6.50 +        out1.sectionTitle2_();
    6.51 +    }
    6.52 +
    6.53 +    static void displayBadWiki(List<Entry> list) {
    6.54 +        out1.list();
    6.55 +        for (Entry e : list) {
    6.56 +            if (e.url.contains("wiki.netbeans.org")) {
    6.57 +                out1.listItem();
    6.58 +                out1.text("In page ");
    6.59 +                out1.link(e.url);
    6.60 +                out1.text(e.title);
    6.61 +                out1.link_();
    6.62 +                out1.text(e.url);
    6.63 +                out1.listItem_();
    6.64 +            }
    6.65 +        }
    6.66 +        out1.list_();
    6.67 +
    6.68 +    }
    6.69 +
    6.70 +    static void displayLinks() {
    6.71 +        displayLinks(allURL, "all links");
    6.72 +        displayLinks(apidoc, "api doc links");
    6.73 +        displayLinks(wikinb, "nb wiki links");
    6.74 +        displayLinks(mercurialnb, "mercurial nb links");
    6.75 +        displayLinks(bugzillanb, "bugzilla nb links");
    6.76 +    }
    6.77 +
    6.78 +    static void printFooter() {
    6.79 +        out1.body_();
    6.80 +    }
    6.81 +
    6.82 +    static void internaladdURL(String attr, String title, Map<String, List<String>> m) {
    6.83 +        if (!m.containsKey(attr)) {
    6.84 +            m.put(attr, new ArrayList());
    6.85 +        }
    6.86 +        if (!m.get(attr).contains(title)) {
    6.87 +            m.get(attr).add(title);
    6.88 +        }
    6.89 +    }
    6.90 +
    6.91 +    public static void wrongWikiLink(String url, String title, String text) {
    6.92 +        out1.paragraph();
    6.93 +        out1.text("In ");
    6.94 +        out1.link(baseUrl + url);
    6.95 +        out1.text(text);
    6.96 +        out1.link_();
    6.97 +        out1.text(" wiki link must be [[]] " + text);
    6.98 +        out1.paragraph_();
    6.99 +    }
   6.100 +
   6.101 +    public static void addURL(String attr, String title, String related) {
   6.102 +        if (attr.isEmpty()) {
   6.103 +            return;
   6.104 +        }
   6.105 +
   6.106 +        String second = title + " <a href=\"" + baseUrl + related + "\">" + related + "</a>";
   6.107 +        if (attr.startsWith("http://bits.netbeans.org/dev/javadoc")) {
   6.108 +            internaladdURL(attr, second, apidoc);
   6.109 +            return;
   6.110 +        }
   6.111 +        // wiki is http
   6.112 +        if (attr.startsWith("http://wiki.netbeans.org")) {
   6.113 +            internaladdURL(attr, second, wikinb);
   6.114 +            return;
   6.115 +        }
   6.116 +        // both https are valid
   6.117 +        if (attr.startsWith("http://hg.netbeans.org") || attr.startsWith("https://hg.netbeans.org")) {
   6.118 +            internaladdURL(attr, second, mercurialnb);
   6.119 +            return;
   6.120 +        }
   6.121 +        // https only
   6.122 +        if (attr.startsWith("https://netbeans.org/bugzilla")) {
   6.123 +            internaladdURL(attr, second, bugzillanb);
   6.124 +            return;
   6.125 +        }
   6.126 +        internaladdURL(attr, second, allURL);
   6.127 +
   6.128 +    }
   6.129 +
   6.130 +    /* static void println(String string) {
   6.131 +     out1.println(string);
   6.132 +     }*/
   6.133 +    private static void displayLinks(Map<String, List<String>> apidoc, String title) {
   6.134 +        Reporter.addHeader(title);
   6.135 +        out1.table();
   6.136 +        for (Map.Entry<String, List<String>> e : apidoc.entrySet()) {
   6.137 +            out1.tableRow();
   6.138 +            out1.tableCell();
   6.139 +            out1.text(e.getKey());
   6.140 +            out1.tableCell_();
   6.141 +            out1.tableCell();
   6.142 +            for (String s : e.getValue()) {
   6.143 +                out1.text(" " + s);
   6.144 +                out1.lineBreak();
   6.145 +            }
   6.146 +            out1.tableCell_();
   6.147 +            out1.tableRow_();
   6.148 +        }
   6.149 +        out1.table_();
   6.150 +
   6.151 +    }
   6.152 +
   6.153 +}
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/other/wikitools/faqsuckplugin/src/main/java/org/netbeans/contrib/faqsuck/package-info.java	Sat Mar 01 20:06:26 2014 +0100
     7.3 @@ -0,0 +1,10 @@
     7.4 +/*
     7.5 + * To change this license header, choose License Headers in Project Properties.
     7.6 + * To change this template file, choose Tools | Templates
     7.7 + * and open the template in the editor.
     7.8 + */
     7.9 +/**
    7.10 + * Faqsuck plugin
    7.11 + */
    7.12 +package org.netbeans.contrib.faqsuck;
    7.13 +
     8.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     8.2 +++ b/other/wikitools/faqsuckplugin/src/main/java/org/netbeans/contrib/wikitools/spi/WikiTasks.java	Sat Mar 01 20:06:26 2014 +0100
     8.3 @@ -0,0 +1,25 @@
     8.4 +/*
     8.5 + * To change this license header, choose License Headers in Project Properties.
     8.6 + * To change this template file, choose Tools | Templates
     8.7 + * and open the template in the editor.
     8.8 + */
     8.9 +package org.netbeans.contrib.wikitools.spi;
    8.10 +
    8.11 +import java.net.URL;
    8.12 +import java.util.List;
    8.13 +import org.jsoup.nodes.Document;
    8.14 +import org.netbeans.contrib.faqsuck.Category;
    8.15 +import org.netbeans.contrib.faqsuck.Entry;
    8.16 +import org.netbeans.contrib.faqsuck.FaqsuckMojo;
    8.17 +
    8.18 +/**
    8.19 + *
    8.20 + */
    8.21 +public interface WikiTasks {
    8.22 +
    8.23 +    String getVersion();
    8.24 +
    8.25 +    void feedCategory(URL baseUrl, Document tocContent, List<Category> categories, FaqsuckMojo mojo);
    8.26 +
    8.27 +    String strip(Document doc, FaqsuckMojo mojos, Entry ent);
    8.28 +}
     9.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     9.2 +++ b/other/wikitools/faqsuckplugin/src/main/java/org/netbeans/contrib/wikitools/wikis/WikiTask1151.java	Sat Mar 01 20:06:26 2014 +0100
     9.3 @@ -0,0 +1,205 @@
     9.4 +/*
     9.5 + * To change this license header, choose License Headers in Project Properties.
     9.6 + * To change this template file, choose Tools | Templates
     9.7 + * and open the template in the editor.
     9.8 + */
     9.9 +package org.netbeans.contrib.wikitools.wikis;
    9.10 +
    9.11 +import java.io.IOException;
    9.12 +import java.net.URL;
    9.13 +import java.util.ArrayList;
    9.14 +import java.util.Arrays;
    9.15 +import java.util.List;
    9.16 +import java.util.logging.Level;
    9.17 +import java.util.logging.Logger;
    9.18 +import org.jsoup.nodes.Comment;
    9.19 +import org.jsoup.nodes.Document;
    9.20 +import org.jsoup.nodes.Element;
    9.21 +import org.jsoup.nodes.Node;
    9.22 +import org.jsoup.parser.Tag;
    9.23 +import org.jsoup.select.Elements;
    9.24 +import org.netbeans.contrib.faqsuck.Category;
    9.25 +import org.netbeans.contrib.faqsuck.Entry;
    9.26 +import org.netbeans.contrib.faqsuck.FaqUtils;
    9.27 +import org.netbeans.contrib.faqsuck.FaqsuckMojo;
    9.28 +import org.netbeans.contrib.faqsuck.Reporter;
    9.29 +import org.netbeans.contrib.wikitools.spi.WikiTasks;
    9.30 +import org.openide.util.lookup.ServiceProvider;
    9.31 +
    9.32 +/**
    9.33 + *
    9.34 + * @author Eric
    9.35 + */
    9.36 +@ServiceProvider(service = WikiTasks.class)
    9.37 +public class WikiTask1151 implements WikiTasks {
    9.38 +
    9.39 +    @Override
    9.40 +    public String getVersion() {
    9.41 +        return "MediaWiki 1.15.1";
    9.42 +    }
    9.43 +
    9.44 +    @Override
    9.45 +    public void feedCategory(URL baseUrl, Document tocContent, List<Category> categories, FaqsuckMojo mojo) {
    9.46 +        Elements toc = tocContent.select("span.mw-headline");
    9.47 +        int ix = 0;
    9.48 +        for (Element e : toc) {
    9.49 +            Element aa = e.parent().previousElementSibling();
    9.50 +
    9.51 +            Category category = null;
    9.52 +            if (ix < FaqUtils.LIMIT) { //for debugging w/o reading all entries
    9.53 +                category = new Category(e.text(), aa.id());
    9.54 +                categories.add(category);
    9.55 +            }
    9.56 +            ix++;
    9.57 +            Element ul = e.parent().nextElementSibling();
    9.58 +            Elements items = ul.select("li");
    9.59 +            int ixx = 0;
    9.60 +            for (Element item : items) {
    9.61 +                Elements anchros = item.select("a");
    9.62 +                if (anchros.size() > 1) {
    9.63 +                    mojo.getLog().debug("<p>Category: <i>" + e.text() + "</i> contains more than one anchor for item: <b>" + item.text() + "</b></p>");
    9.64 +                }
    9.65 +                for (Element a : anchros) {
    9.66 +                    if (a.attr("href").startsWith("/")) {
    9.67 +                        mojo.getLog().debug("Main.knownurl.add(a.attr(\"href\"));" + a.attr("href"));
    9.68 +                        mojo.addTOCURL(a.attr("href"));
    9.69 +
    9.70 +                    }
    9.71 +
    9.72 +                    if (ixx < FaqUtils.LIMIT && category != null) { //for debugging w/o reading all entries
    9.73 +                        category.addEntry(new Entry(a.attr("href"), a.text(), baseUrl.toExternalForm()));
    9.74 +                        // break;
    9.75 +                    }
    9.76 +                    ixx++;
    9.77 +                }
    9.78 +
    9.79 +            }
    9.80 +
    9.81 +        }
    9.82 +    }
    9.83 +    private final List<String> selectorForRemoval = Arrays.asList(".printfooter", ".firstHeading", "#contentSub", "#toc", "hr");
    9.84 +    private final List<String> selectorForParentRemoval = Arrays.asList(".mw-headline");
    9.85 +
    9.86 +    private void removeElements(Element e) {
    9.87 +// candidate for deletion
    9.88 +        List<Node> nn = new ArrayList<>();
    9.89 +        Elements a = e.select("a");
    9.90 +        for (Element aa : a) {
    9.91 +            // remove anchor that have a name inside
    9.92 +            if ((aa.attr("name").equals(aa.attr("id")) && (!aa.attr("id").isEmpty()))) {
    9.93 +                nn.add(aa);
    9.94 +            }
    9.95 +        }
    9.96 +
    9.97 +        for (String selector : selectorForRemoval) {
    9.98 +            nn.addAll(e.select(selector));
    9.99 +        }
   9.100 +        for (String selector : selectorForParentRemoval) {
   9.101 +            for (Element printfoot : e.select(selector)) {
   9.102 +                nn.add(printfoot.parent());
   9.103 +
   9.104 +            }
   9.105 +        }
   9.106 +        for (Node n : e.childNodes()) {
   9.107 +            // remove comment block to save space
   9.108 +            if (n instanceof Comment) {
   9.109 +                nn.add(n);
   9.110 +            }
   9.111 +
   9.112 +        }
   9.113 +        for (Node n : nn) {
   9.114 +            n.remove();
   9.115 +        }
   9.116 +
   9.117 +    }
   9.118 +
   9.119 +    @Override
   9.120 +    public String strip(Document content, FaqsuckMojo mojos, Entry ent) {
   9.121 +        // Netbeans template #content
   9.122 +        Element e = content.select("#content").first();
   9.123 +        removeElements(e);
   9.124 +        // href managment
   9.125 +        Elements a = e.select("a");
   9.126 +        for (Element aa : a) {
   9.127 +
   9.128 +            //  considers all remainings link  (except image) as external and assure that they oppen new page or tab
   9.129 +            if (!aa.hasClass("image")) {
   9.130 +                aa.addClass("external");
   9.131 +            }
   9.132 +            aa.attr("target", "_blank");
   9.133 +
   9.134 +            // Not well formatted wiki must use [[]] instead  []
   9.135 +            if (aa.attr("href").contains("wiki.netbeans.org")) {
   9.136 +                Reporter.wrongWikiLink(ent.url, ent.title, aa.text());
   9.137 +            }
   9.138 +            // Start with / => local wiki link
   9.139 +            if (aa.attr("href").startsWith("/")) {
   9.140 +                if (mojos.getKnownUrl().contains(aa.attr("href"))) {
   9.141 +                    // its a know internal url replace to navigate in the same file
   9.142 +                    aa.attr("href", aa.attr("href").replaceFirst("/", "#"));
   9.143 +                    aa.removeClass("external");
   9.144 +                    aa.removeAttr("target");
   9.145 +                } else {
   9.146 +                    // wiki netbeans css class
   9.147 +                    aa.addClass("wnetbeans");
   9.148 +                    aa.attr("href", ent.baseUrl + aa.attr("href"));
   9.149 +
   9.150 +                }
   9.151 +            }
   9.152 +            // 
   9.153 +            if (aa.attr("href").startsWith("http://bits.netbeans.org/dev/javadoc")) {
   9.154 +                aa.addClass("jdocnetbeans");
   9.155 +            }
   9.156 +            if (!aa.attr("href").startsWith("#")) {
   9.157 +                Reporter.addURL(aa.attr("href"), aa.text(), ent.url);
   9.158 +
   9.159 +            }
   9.160 +        }
   9.161 +        // all headers => becomes h5 
   9.162 +        for (int i = 1; i < 7; i++) {
   9.163 +            Elements headers = e.select("h" + i);
   9.164 +            for (Element header : headers) {
   9.165 +                header.replaceWith(new Element(Tag.valueOf("h5"), "").html(header.html()));
   9.166 +            }
   9.167 +        }
   9.168 +        // all tt => becomes span with monospace font
   9.169 +        Elements truetype = e.select("tt");
   9.170 +        for (Element element : truetype) {
   9.171 +            element.replaceWith(new Element(Tag.valueOf("span"), "").addClass("trt").html(element.html()));
   9.172 +        }
   9.173 +        // img removal + link inclusion
   9.174 +        Elements images = e.select(".image");
   9.175 +        for (Element image : images) {
   9.176 +            try {
   9.177 +                image.replaceWith(new Element(Tag.valueOf("a"), "").attr("target", "_blank").attr("href", ent.getWebUrl().toString()).html("[image - see online version]"));
   9.178 +            } catch (IOException ex) {
   9.179 +                Logger.getLogger(WikiTask1151.class.getName()).log(Level.SEVERE, null, ex);
   9.180 +            }
   9.181 +        }
   9.182 +        e.removeAttr("id");
   9.183 +        return e.outerHtml();
   9.184 +        //Matcher m = CONTENT_PATTERN.matcher(content);*/
   9.185 +    /*     if (m.find()) {
   9.186 +         String result = m.group(1);
   9.187 +         result = result.replaceAll("<a href=\"/", "<a href=\"#");
   9.188 +         result = result.replaceAll("<img.*?>", "<a href=\"" + getWebUrl() + "\" target=\"ext\"><i>[image - see online version]</i></a>");
   9.189 +         result = result.replaceAll("</img>", "");
   9.190 +         result = result.replaceAll("<h[123456]>", "<h5>");
   9.191 +         result = result.replaceAll("</h[123456]>", "</h5>");
   9.192 +         result = result.replaceAll("<hr\\s*?/>", "");
   9.193 +
   9.194 +         int ix = result.indexOf("<p><b><span style=\"color:#ff6633;\">Attachments</span></b>");
   9.195 +         if (ix > 0) {
   9.196 +         System.err.println("F" + title + url);
   9.197 +         int newIx = result.lastIndexOf("<div", ix);
   9.198 +         ix = newIx < 0 ? ix : newIx;
   9.199 +         result = result.substring(0, ix);
   9.200 +         }
   9.201 +
   9.202 +         return "<div class=\"itemBody\">" + result + "\n</div>";
   9.203 +         } else {
   9.204 +         return "[no content found]";
   9.205 +         }*/
   9.206 +    }
   9.207 +
   9.208 +}