All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.jrst.JrstSiteRenderer Maven / Gradle / Ivy

There is a newer version: 2.4
Show newest version
/*
 * #%L
 * JRst :: Site util
 * %%
 * Copyright (C) 2012 - 2016 CodeLutin
 * %%
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as 
 * published by the Free Software Foundation, either version 3 of the 
 * License, or (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Lesser Public License for more details.
 * 
 * You should have received a copy of the GNU General Lesser Public 
 * License along with this program.  If not, see
 * .
 * #L%
 */
package org.nuiton.jrst;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.StringWriter;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.lang.reflect.Field;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Locale;
import java.util.Map;

import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.maven.doxia.parser.Parser;
import org.apache.maven.doxia.site.decoration.Menu;
import org.apache.maven.doxia.site.decoration.MenuItem;
import org.apache.maven.doxia.siterenderer.DefaultSiteRenderer;
import org.apache.maven.doxia.siterenderer.DocumentRenderer;
import org.apache.maven.doxia.siterenderer.Renderer;
import org.apache.maven.doxia.siterenderer.RendererException;
import org.apache.maven.doxia.siterenderer.RenderingContext;
import org.apache.maven.doxia.siterenderer.SiteRenderingContext;
import org.apache.maven.project.MavenProject;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.codehaus.plexus.component.annotations.Component;
import org.codehaus.plexus.component.annotations.Requirement;
import org.codehaus.plexus.i18n.I18N;
import org.codehaus.plexus.velocity.VelocityComponent;
import org.dom4j.Document;

import com.google.common.collect.Maps;

/**
 * Override of the DefaultSiteRenderer to add pdf generation of the site.
 *
 * @author jpages
 * @author tchemit ([email protected])
 * @since 2.0
 */
@Component(role = Renderer.class, hint = "default")
public class JrstSiteRenderer extends DefaultSiteRenderer {

    public static final String DEFAULT_PDF_FILENAME = "site";

    /** All locales used to render sites. */
    protected List locales;

    /** Current locale used to render. */
    protected Locale locale;

    /** Current maven project to render. */
    protected MavenProject mavenProject;

    protected boolean pdfGenerationEnabled;

    protected boolean verbose;

    @Requirement(role = Parser.class, hint = "jrst", optional = true)
    protected AbstractJrstParser jrstParser;

    @Override
    public void render(Collection documents,
                       SiteRenderingContext siteRenderingContext,
                       File outputDirectory)
            throws RendererException, IOException {

        // prepare all common values for a given module

        locale = siteRenderingContext.getLocale();

        locales = Collections.unmodifiableList(siteRenderingContext.getSiteLocales());

        Map templateProperties = siteRenderingContext.getTemplateProperties();

        mavenProject = (MavenProject) templateProperties.get("project");

        verbose = getBooleanProperty("site.verbose") ||
                  getLogger().isDebugEnabled();

        pdfGenerationEnabled = getBooleanProperty("pdfGenerationEnabled");

        super.render(documents, siteRenderingContext, outputDirectory);

        if (pdfGenerationEnabled) {

            // Get relative paths of documents from menu definition (from site.xml model)
            List relativPathsFromMenu =
                    getDocumentRelativePathsFromMenu(siteRenderingContext);

            // Get relatifs map of all documents
            Map relatifPaths = buildDocMap(documents);

            // merge to have documents refs (to be used in pdf template)
            List documentRefs = getDocumentRefs(relatifPaths,
                                                        relativPathsFromMenu);

            if (CollectionUtils.isEmpty(documentRefs)) {
                // no docuemnts to render, skip pdf generation

                if (getLogger().isInfoEnabled()) {
                    getLogger().info("No document to put in pdf, skip pdf generation.");
                }
            } else {
                String pdfFilename = getPdfFileName();

                try {
                    Field i18nField = ReflectUtil.getField(DefaultSiteRenderer.class, "i18n");
                    I18N i18n = (I18N) i18nField.get(this);

                    renderPdf(i18n, documentRefs,
                              siteRenderingContext,
                              outputDirectory,
                              pdfFilename);
                } catch (Exception e) {
                    getLogger().error("Can't find rst resource to generate pdf documentation", e);
                }
            }

        }
    }

    @Override
    public void renderDocument(Writer writer,
                               RenderingContext renderingContext,
                               SiteRenderingContext context)
            throws RendererException, FileNotFoundException, UnsupportedEncodingException {

        if (AbstractJrstParser.JRST_PARSER_ID.equals(renderingContext.getParserId())) {

            // let's keep the current rendering context into the JrstParser
            // to be able to have the document name to parse
            jrstParser.setRenderingContext(renderingContext);
            jrstParser.setMavenProject(mavenProject);
            jrstParser.setVerbose(verbose);

        }
        super.renderDocument(writer, renderingContext, context);
    }

    protected String getPdfFileName() {
        // get pdfFilename
        String pdfFilename = getStringProperty("pdfFilename");
        if (StringUtils.isBlank(pdfFilename)) {
            pdfFilename = DEFAULT_PDF_FILENAME;
        }

        if (!locales.isEmpty() && !locale.equals(locales.get(0))) {
            // not default locale, prefix with locale country.
            pdfFilename += "_" + locale.getCountry();
        }
        pdfFilename += ".pdf";
        return pdfFilename;
    }

    protected void renderPdf(I18N i18n,
                             List documentRefs,
                             SiteRenderingContext siteRenderingContext,
                             File outputDirectory,
                             String pdfFilename)
            throws RendererException, FileNotFoundException, UnsupportedEncodingException {

        if (getLogger().isDebugEnabled()) {
            getLogger().debug("Generate Site Pdf: " + pdfFilename);
        }

        Context vc = preparePdfVelocityContext(i18n, documentRefs);

        // Define the output file
        File fileOut = new File(outputDirectory, pdfFilename);
        if (verbose) {
            getLogger().info("Will generate the site pdf: " + fileOut);
        }

        try {
            StringWriter sw = new StringWriter();
            Field velocityField =
                    ReflectUtil.getField(DefaultSiteRenderer.class, "velocity");

            VelocityComponent velocity = (VelocityComponent) velocityField.get(this);
            VelocityEngine engine = velocity.getEngine();

            String inputEncoding = siteRenderingContext.getInputEncoding();

            // Aggregate all rst file info one file
            //TODO tchemit-2012-06-29 : use a property
            engine.mergeTemplate("/META-INF/maven/RstAggregation.vm", inputEncoding, vc, sw);
            String fileContent = sw.toString();
            File pdfDoc = new File(outputDirectory, "pdfDoc.rst");
            FileUtils.writeStringToFile(pdfDoc, fileContent, inputEncoding);


            Document doc = jrstParser.getStrategy().generateRstToXml(
                    fileOut, inputEncoding);

            // Generate the pdf file
            JRST.generatePdf(pdfDoc, fileOut, JRST.Overwrite.ALLTIME, doc);

        } catch (Exception e) {
            getLogger().error("Can't generate pdf documentation of the project at " + fileOut, e);
        }
    }

    protected Context preparePdfVelocityContext(I18N i18n,
                                                List documentRefs) {

        Context vc = new VelocityContext();
        vc.put("locale", locale);
        vc.put("supportedLocales", locales);
        String tableOfContent = i18n.getString("jrst-site-renderer", locale, "content");
        String docName = mavenProject.getName();
        String titleDecoration = StringUtils.rightPad("", docName.length(), '=');
        vc.put("titleDecoration", titleDecoration);
        vc.put("docName", docName);
        vc.put("tableContentName", tableOfContent);

        // Build the map of html documents from .rst or .rst.vm files

        vc.put("basedir", mavenProject.getBasedir());
        vc.put("separator", File.separatorChar);
        vc.put("documentRefs", documentRefs);
        return vc;
    }

    protected List getDocumentRelativePathsFromMenu(SiteRenderingContext siteRenderingContext) {
        List paths = new LinkedList();
        for (Menu menu : siteRenderingContext.getDecoration().getMenus()) {
            for (MenuItem item : menu.getItems()) {
                buildListPathsFromMenuItem(item, paths);
            }
        }
        return paths;
    }

    protected List getDocumentRefs(Map relatifPaths,
                                           List relativPathsFromMenu) {

        // Merge the map and the list to obtain a list of rst files we can add in the pdf
        List documentRefs = new LinkedList();
        for (String path : relativPathsFromMenu) {
            // Seek in the hashmap if the rst file exists to add it in the doc list
            String rstFilename = relatifPaths.get(path);
            if (rstFilename != null) {
                if (verbose) {
                    getLogger().info("Add document to render in pdf: " +
                                     rstFilename);
                }
                documentRefs.add(rstFilename);
            }
        }
        return documentRefs;
    }

    protected Map buildDocMap(Collection documents) {

        Map map = Maps.newTreeMap();

        for (DocumentRenderer doc : documents) {
            RenderingContext renderingContext = doc.getRenderingContext();
            String inputName = renderingContext.getInputName();
//            String relativeDir = renderingContext.getRelativePath();
            if (inputName.endsWith("rst") || inputName.endsWith("rst.vm")) {
                // Change the extension to html
                String[] splitName = inputName.split("\\.");
                String htmlName = splitName[0] + "." + "html";
                String relativePath = "." + File.separator + htmlName;
                if (getLogger().isDebugEnabled()) {
                    getLogger().debug("relativePath: " + relativePath);
                }
                // Add in map
                map.put(relativePath, inputName);

                //TODO Why ?
//                if (relativeDir.equals(".") && inputName.startsWith("index")) {
//                    basedir = renderingContext.getBasedir();
//                }
            }
        }
        return map;
    }

    protected Collection buildListPathsFromMenuItem(MenuItem item,
                                                            Collection paths) {
        // add hrefs to paths if they don't start with "http" or ".."
        String href = item.getHref();
        if (!href.startsWith("http") && !href.startsWith("..")) {
            boolean addHref = true;
            for (Locale loc : locales) {
                if (href.startsWith(loc.toString())) {
                    addHref = false;
                }
            }
            if (addHref) {
                if (!href.startsWith("./")) {
                    href = "./" + href;
                }
                if (getLogger().isDebugEnabled()) {
                    getLogger().debug("document to render in pdf: " + href);
                }
                paths.add(href);
            }
        }
        // If the item has sub-items, we use recursion to add them to paths
        List subItems = item.getItems();
        if (!subItems.isEmpty()) {
            for (MenuItem subItem : subItems) {
                paths = buildListPathsFromMenuItem(subItem, paths);
            }
        }
        return paths;
    }

    protected String getStringProperty(String propertyName) {
        Object value = mavenProject.getProperties().get(propertyName);
        String result = value == null ? null : String.valueOf(value);
        return result;
    }

    protected boolean getBooleanProperty(String propertyName) {
        boolean result = "true".equals(getStringProperty(propertyName));
        return result;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy