org.apache.maven.plugins.linkcheck.LinkcheckReportGenerator.java Source code

Java tutorial

Introduction

Here is the source code for org.apache.maven.plugins.linkcheck.LinkcheckReportGenerator.java

Source

/*
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 */

package org.apache.maven.plugins.linkcheck;

import java.util.List;
import java.util.Locale;

import org.apache.commons.io.FilenameUtils;

import org.apache.maven.doxia.linkcheck.model.LinkcheckFile;
import org.apache.maven.doxia.linkcheck.model.LinkcheckFileResult;
import org.apache.maven.doxia.linkcheck.model.LinkcheckModel;
import org.apache.maven.doxia.sink.Sink;

import org.codehaus.plexus.i18n.I18N;
import org.codehaus.plexus.util.StringUtils;

/**
 *
 * @author ltheussl
 * @since 1.1
 */
public class LinkcheckReportGenerator {
    private final I18N i18n;

    private String httpMethod;
    private boolean offline;
    private String[] excludedLinks;
    private Integer[] excludedHttpStatusErrors;
    private Integer[] excludedHttpStatusWarnings;
    private String[] excludedPages;
    private boolean httpFollowRedirect;

    /**
     *
     * @param i18n not null.
     */
    public LinkcheckReportGenerator(I18N i18n) {
        this.i18n = i18n;
    }

    /**
     *
     * @param excludedHttpStatusErrors may be null.
     */
    public void setExcludedHttpStatusErrors(Integer[] excludedHttpStatusErrors) {
        this.excludedHttpStatusErrors = excludedHttpStatusErrors;
    }

    /**
     *
     * @param excludedHttpStatusWarnings may be null.
     */
    public void setExcludedHttpStatusWarnings(Integer[] excludedHttpStatusWarnings) {
        this.excludedHttpStatusWarnings = excludedHttpStatusWarnings;
    }

    /**
     *
     * @param excludedLinks may be null.
     */
    public void setExcludedLinks(String[] excludedLinks) {
        this.excludedLinks = excludedLinks;
    }

    /**
     *
     * @param excludedPages may be null.
     */
    public void setExcludedPages(String[] excludedPages) {
        this.excludedPages = excludedPages;
    }

    /**
     *
     * @param httpFollowRedirect default is false.
     */
    public void setHttpFollowRedirect(boolean httpFollowRedirect) {
        this.httpFollowRedirect = httpFollowRedirect;
    }

    /**
     *
     * @param httpMethod may be null.
     */
    public void setHttpMethod(String httpMethod) {
        this.httpMethod = httpMethod;
    }

    /**
     *
     * @param offline default is false.
     */
    public void setOffline(boolean offline) {
        this.offline = offline;
    }

    /**
     * Genarate a report for the given LinkcheckModel and emit it into a Sink.
     * <strong>Note</strong> that the Sink is flushed and closed.
     *
     * @param locale not null.
     * @param linkcheckModel may be null.
     * @param sink not null.
     */
    public void generateReport(Locale locale, LinkcheckModel linkcheckModel, Sink sink) {
        String name = i18n.getString("linkcheck-report", locale, "report.linkcheck.name");

        sink.head();
        sink.title();
        sink.text(i18n.getString("linkcheck-report", locale, "report.linkcheck.title"));
        sink.title_();
        sink.head_();

        sink.body();

        if (linkcheckModel == null) {
            sink.section1();
            sink.sectionTitle1();
            sink.text(name);
            sink.sectionTitle1_();

            sink.paragraph();
            sink.rawText(i18n.getString("linkcheck-report", locale, "report.linkcheck.empty"));
            sink.paragraph_();

            sink.section1_();

            sink.body_();
            sink.flush();
            sink.close();

            return;
        }

        // Overview
        sink.section1();
        sink.sectionTitle1();
        sink.text(name);
        sink.sectionTitle1_();

        sink.paragraph();
        sink.rawText(i18n.getString("linkcheck-report", locale, "report.linkcheck.overview"));
        sink.paragraph_();

        sink.section1_();

        // Statistics
        generateSummarySection(locale, linkcheckModel, sink);

        if (linkcheckModel.getFiles().size() > 0) {
            // Details
            generateDetailsSection(locale, linkcheckModel, sink);
        }

        sink.body_();
        sink.flush();
        sink.close();
    }

    private void generateSummarySection(Locale locale, LinkcheckModel linkcheckModel, Sink sink) {
        // Calculus
        List linkcheckFiles = linkcheckModel.getFiles();

        int totalFiles = linkcheckFiles.size();

        int totalLinks = 0;
        int totalValidLinks = 0;
        int totalErrorLinks = 0;
        int totalWarningLinks = 0;
        for (Object linkcheckFile1 : linkcheckFiles) {
            LinkcheckFile linkcheckFile = (LinkcheckFile) linkcheckFile1;

            totalLinks += linkcheckFile.getNumberOfLinks();
            totalValidLinks += linkcheckFile.getNumberOfLinks(LinkcheckFileResult.VALID_LEVEL);
            totalErrorLinks += linkcheckFile.getNumberOfLinks(LinkcheckFileResult.ERROR_LEVEL);
            totalWarningLinks += linkcheckFile.getNumberOfLinks(LinkcheckFileResult.WARNING_LEVEL);
        }

        sink.section1();
        sink.sectionTitle1();
        sink.text(i18n.getString("linkcheck-report", locale, "report.linkcheck.summary"));
        sink.sectionTitle1_();

        // Summary of the analysis parameters
        sink.paragraph();
        sink.rawText(i18n.getString("linkcheck-report", locale, "report.linkcheck.summary.overview1"));
        sink.paragraph_();

        sink.table();

        sink.tableRow();
        sink.tableHeaderCell();
        sink.text(i18n.getString("linkcheck-report", locale, "report.linkcheck.summary.table.parameter"));
        sink.tableHeaderCell_();
        sink.tableHeaderCell();
        sink.text(i18n.getString("linkcheck-report", locale, "report.linkcheck.summary.table.value"));
        sink.tableHeaderCell_();
        sink.tableRow_();

        sink.tableRow();
        sink.tableCell();
        sink.rawText(
                i18n.getString("linkcheck-report", locale, "report.linkcheck.summary.table.httpFollowRedirect"));
        sink.tableCell_();
        sink.tableCell();
        sink.text(String.valueOf(httpFollowRedirect));
        sink.tableCell_();
        sink.tableRow_();

        sink.tableRow();
        sink.tableCell();
        sink.rawText(i18n.getString("linkcheck-report", locale, "report.linkcheck.summary.table.httpMethod"));
        sink.tableCell_();
        sink.tableCell();
        if (StringUtils.isEmpty(httpMethod)) {
            sink.text(i18n.getString("linkcheck-report", locale, "report.linkcheck.summary.table.none"));
        } else {
            sink.text(httpMethod);
        }
        sink.tableCell_();
        sink.tableRow_();

        sink.tableRow();
        sink.tableCell();
        sink.rawText(i18n.getString("linkcheck-report", locale, "report.linkcheck.summary.table.offline"));
        sink.tableCell_();
        sink.tableCell();
        sink.text(String.valueOf(offline));
        sink.tableCell_();
        sink.tableRow_();

        sink.tableRow();
        sink.tableCell();
        sink.rawText(i18n.getString("linkcheck-report", locale, "report.linkcheck.summary.table.excludedPages"));
        sink.tableCell_();
        sink.tableCell();
        if (excludedPages == null || excludedPages.length == 0) {
            sink.text(i18n.getString("linkcheck-report", locale, "report.linkcheck.summary.table.none"));
        } else {
            sink.text(StringUtils.join(excludedPages, ","));
        }
        sink.tableCell_();
        sink.tableRow_();

        sink.tableRow();
        sink.tableCell();
        sink.rawText(i18n.getString("linkcheck-report", locale, "report.linkcheck.summary.table.excludedLinks"));
        sink.tableCell_();
        sink.tableCell();
        if (excludedLinks == null || excludedLinks.length == 0) {
            sink.text(i18n.getString("linkcheck-report", locale, "report.linkcheck.summary.table.none"));
        } else {
            sink.text(StringUtils.join(excludedLinks, ","));
        }
        sink.tableCell_();
        sink.tableRow_();

        sink.tableRow();
        sink.tableCell();
        sink.rawText(i18n.getString("linkcheck-report", locale,
                "report.linkcheck.summary.table.excludedHttpStatusErrors"));
        sink.tableCell_();
        sink.tableCell();
        if (excludedHttpStatusErrors == null || excludedHttpStatusErrors.length == 0) {
            sink.text(i18n.getString("linkcheck-report", locale, "report.linkcheck.summary.table.none"));
        } else {
            sink.text(toString(excludedHttpStatusErrors));
        }
        sink.tableCell_();
        sink.tableRow_();

        sink.tableRow();
        sink.tableCell();
        sink.rawText(i18n.getString("linkcheck-report", locale,
                "report.linkcheck.summary.table.excludedHttpStatusWarnings"));
        sink.tableCell_();
        sink.tableCell();
        if (excludedHttpStatusWarnings == null || excludedHttpStatusWarnings.length == 0) {
            sink.text(i18n.getString("linkcheck-report", locale, "report.linkcheck.summary.table.none"));
        } else {
            sink.text(toString(excludedHttpStatusWarnings));
        }
        sink.tableCell_();
        sink.tableRow_();

        sink.table_();

        // Summary of the checked files
        sink.paragraph();
        sink.rawText(i18n.getString("linkcheck-report", locale, "report.linkcheck.summary.overview2"));
        sink.paragraph_();

        sink.table();

        // Header
        generateTableHeader(locale, false, sink);

        // Content
        sink.tableRow();

        sink.tableCell();
        sink.bold();
        sink.text(totalFiles + "");
        sink.bold_();
        sink.tableCell_();
        sink.tableCell();
        sink.bold();
        sink.text(totalLinks + "");
        sink.bold_();
        sink.tableCell_();
        sink.tableCell();
        sink.bold();
        sink.text(String.valueOf(totalValidLinks));
        sink.bold_();
        sink.tableCell_();
        sink.tableCell();
        sink.bold();
        sink.text(String.valueOf(totalWarningLinks));
        sink.bold_();
        sink.tableCell_();
        sink.tableCell();
        sink.bold();
        sink.text(String.valueOf(totalErrorLinks));
        sink.bold_();
        sink.tableCell_();

        sink.tableRow_();

        sink.table_();

        sink.section1_();
    }

    private void generateDetailsSection(Locale locale, LinkcheckModel linkcheckModel, Sink sink) {
        sink.section1();
        sink.sectionTitle1();
        sink.text(i18n.getString("linkcheck-report", locale, "report.linkcheck.detail"));
        sink.sectionTitle1_();

        sink.paragraph();
        sink.rawText(i18n.getString("linkcheck-report", locale, "report.linkcheck.detail.overview"));
        sink.paragraph_();

        sink.table();

        // Header
        generateTableHeader(locale, true, sink);

        // Content
        List linkcheckFiles = linkcheckModel.getFiles();
        for (Object linkcheckFile1 : linkcheckFiles) {
            LinkcheckFile linkcheckFile = (LinkcheckFile) linkcheckFile1;

            sink.tableRow();

            sink.tableCell();
            if (linkcheckFile.getUnsuccessful() == 0) {
                iconValid(locale, sink);
            } else {
                iconError(locale, sink);
            }
            sink.tableCell_();

            // tableCell( createLinkPatternedText( linkcheckFile.getRelativePath(), "./"
            // + linkcheckFile.getRelativePath() ) );
            sink.tableCell();
            sink.link(linkcheckFile.getRelativePath());
            sink.text(linkcheckFile.getRelativePath());
            sink.link_();
            sink.tableCell_();
            sink.tableCell();
            sink.text(String.valueOf(linkcheckFile.getNumberOfLinks()));
            sink.tableCell_();
            sink.tableCell();
            sink.text(String.valueOf(linkcheckFile.getNumberOfLinks(LinkcheckFileResult.VALID_LEVEL)));
            sink.tableCell_();
            sink.tableCell();
            sink.text(String.valueOf(linkcheckFile.getNumberOfLinks(LinkcheckFileResult.WARNING_LEVEL)));
            sink.tableCell_();
            sink.tableCell();
            sink.text(String.valueOf(linkcheckFile.getNumberOfLinks(LinkcheckFileResult.ERROR_LEVEL)));
            sink.tableCell_();

            sink.tableRow_();

            // Detail error
            if (linkcheckFile.getUnsuccessful() != 0) {
                sink.tableRow();

                sink.tableCell();
                sink.text("");
                sink.tableCell_();

                // TODO it is due to DOXIA-78
                sink.rawText("<td colspan=\"5\">");

                sink.table();

                for (Object o : linkcheckFile.getResults()) {
                    LinkcheckFileResult linkcheckFileResult = (LinkcheckFileResult) o;

                    if (linkcheckFileResult.getStatusLevel() == LinkcheckFileResult.VALID_LEVEL) {
                        continue;
                    }

                    sink.tableRow();

                    sink.tableCell();
                    if (linkcheckFileResult.getStatusLevel() == LinkcheckFileResult.WARNING_LEVEL) {
                        iconWarning(locale, sink);
                    } else if (linkcheckFileResult.getStatusLevel() == LinkcheckFileResult.ERROR_LEVEL) {
                        iconError(locale, sink);
                    }
                    sink.tableCell_();

                    sink.tableCell();
                    sink.italic();
                    if (linkcheckFileResult.getTarget().startsWith("#")) {
                        sink.link(linkcheckFile.getRelativePath() + linkcheckFileResult.getTarget());
                    } else if (linkcheckFileResult.getTarget().startsWith(".")) {
                        // We need to calculate a correct absolute path here, because target is a relative path
                        String absolutePath = FilenameUtils.getFullPath(linkcheckFile.getRelativePath())
                                + linkcheckFileResult.getTarget();
                        String normalizedPath = FilenameUtils.normalize(absolutePath);
                        if (normalizedPath == null) {
                            normalizedPath = absolutePath;
                        }
                        sink.link(normalizedPath);
                    } else {
                        sink.link(linkcheckFileResult.getTarget());
                    }
                    // Show the link as it was written to make it easy for
                    // the author to find it in the source document
                    sink.text(linkcheckFileResult.getTarget());
                    sink.link_();
                    sink.text(": ");
                    sink.text(linkcheckFileResult.getErrorMessage());
                    sink.italic_();
                    sink.tableCell_();

                    sink.tableRow_();
                }

                sink.table_();

                sink.tableCell_();

                sink.tableRow_();
            }
        }

        sink.table_();

        sink.section1_();
    }

    private void generateTableHeader(Locale locale, boolean detail, Sink sink) {
        sink.tableRow();
        if (detail) {
            sink.rawText("<th rowspan=\"2\">");
            sink.text("");
            sink.tableHeaderCell_();
        }
        sink.rawText("<th rowspan=\"2\">");
        sink.text(detail ? i18n.getString("linkcheck-report", locale, "report.linkcheck.detail.table.documents")
                : i18n.getString("linkcheck-report", locale, "report.linkcheck.summary.table.documents"));
        sink.tableHeaderCell_();
        // TODO it is due to DOXIA-78
        sink.rawText("<th colspan=\"4\" align=\"center\">");
        sink.text(i18n.getString("linkcheck-report", locale, "report.linkcheck.table.links"));
        sink.tableHeaderCell_();
        sink.tableRow_();

        sink.tableRow();
        sink.tableHeaderCell();
        sink.text(i18n.getString("linkcheck-report", locale, "report.linkcheck.table.totalLinks"));
        sink.tableHeaderCell_();
        sink.tableHeaderCell();
        iconValid(locale, sink);
        sink.tableHeaderCell_();
        sink.tableHeaderCell();
        iconWarning(locale, sink);
        sink.tableHeaderCell_();
        sink.tableHeaderCell();
        iconError(locale, sink);
        sink.tableHeaderCell_();
        sink.tableRow_();
    }

    private void iconError(Locale locale, Sink sink) {
        sink.figure();
        sink.figureCaption();
        sink.text(i18n.getString("linkcheck-report", locale, "report.linkcheck.icon.error"));
        sink.figureCaption_();
        sink.figureGraphics(LinkcheckReport.ICON_ERROR);
        sink.figure_();
    }

    private void iconValid(Locale locale, Sink sink) {
        sink.figure();
        sink.figureCaption();
        sink.text(i18n.getString("linkcheck-report", locale, "report.linkcheck.icon.valid"));
        sink.figureCaption_();
        sink.figureGraphics(LinkcheckReport.ICON_SUCCESS);
        sink.figure_();
    }

    private void iconWarning(Locale locale, Sink sink) {
        sink.figure();
        sink.figureCaption();
        sink.text(i18n.getString("linkcheck-report", locale, "report.linkcheck.icon.warning"));
        sink.figureCaption_();
        sink.figureGraphics(LinkcheckReport.ICON_WARNING);
        sink.figure_();
    }

    // ----------------------------------------------------------------------
    // static methods
    // ----------------------------------------------------------------------

    /**
     * Similar to {@link Arrays#toString(int[])} in 1.5.
     *
     * @param a not null
     * @return the array comma separated.
     */
    private static String toString(Object[] a) {
        if (a == null || a.length == 0) {
            return "";
        }

        StringBuilder buf = new StringBuilder();
        buf.append(a[0]);

        for (int i = 1; i < a.length; i++) {
            buf.append(", ");
            buf.append(a[i]);
        }

        return buf.toString();
    }
}