org.arachna.netweaver.nwdi.documenter.report.DevelopmentConfigurationConfluenceWikiGenerator.java Source code

Java tutorial

Introduction

Here is the source code for org.arachna.netweaver.nwdi.documenter.report.DevelopmentConfigurationConfluenceWikiGenerator.java

Source

/**
 *
 */
package org.arachna.netweaver.nwdi.documenter.report;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintStream;
import java.io.Reader;
import java.io.StringWriter;
import java.util.HashMap;
import java.util.Map;

import javax.xml.transform.ErrorListener;
import javax.xml.transform.Templates;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerConfigurationException;
import javax.xml.transform.TransformerException;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;

import jenkins.plugins.confluence.soap.v1.RemotePageSummary;
import jenkins.plugins.confluence.soap.v2.RemotePage;
import jenkins.plugins.confluence.soap.v2.RemotePageUpdateOptions;

import org.apache.commons.io.IOUtils;
import org.arachna.netweaver.dc.types.Compartment;
import org.arachna.netweaver.dc.types.DevelopmentComponent;
import org.arachna.netweaver.dc.types.DevelopmentConfiguration;
import org.arachna.netweaver.dc.types.DevelopmentConfigurationVisitor;
import org.arachna.netweaver.nwdi.documenter.filter.VendorFilter;
import org.arachna.netweaver.nwdi.dot4j.DiagramDescriptor;
import org.arachna.netweaver.nwdi.dot4j.DiagramDescriptorContainer;

import com.myyearbook.hudson.plugins.confluence.ConfluenceSession;

/**
 * Generator for documentation of a development configuration in HTML.
 *
 * @author Dirk Weigenand
 */
public final class DevelopmentConfigurationConfluenceWikiGenerator implements DevelopmentConfigurationVisitor {
    /**
     * Confluence session used to publish to confluence site.
     */
    private final ConfluenceSession session;

    /**
     * filter development components by vendor.
     */
    private final VendorFilter vendorFilter;

    /**
     * base folder containing docbook sources for wiki pages.
     */
    private final File reportSourceFolder;

    /**
     * Log exceptional messages.
     */
    private final PrintStream logger;

    /**
     * keep track of track overview page (to append compartment pages as children).
     */
    private RemotePage trackOverviewPage;

    /**
     * keep track of the current compartment overview page (to add development component reports as child pages).
     */
    private RemotePage currentCompartmentOverviewPage;

    /**
     * container for descriptors of generated dependency diagrams.
     */
    private final DiagramDescriptorContainer dotFileDescriptorContainer;

    /**
     * additional context to supply to velocity.
     */
    private final Map<String, Object> additionalContext = new HashMap<String, Object>();

    /**
     * NWDI track name documentation is generated for.
     */
    private String trackName;

    /**
     * Template for transforming docbook to confluence wiki pages.
     */
    private final Templates template;

    /**
     * Create an instance of the confluence wiki content generator for development components.
     *
     * @param reportSourceFolder
     *            base folder containing docbook sources for wiki pages.
     * @param vendorFilter
     *            filter for development components by vendor.
     * @param session
     *            the confluence session
     * @param logger
     *            the logger to use
     * @param dotFileDescriptorContainer
     *            container for descriptors of generated dependency diagrams.
     * @param templates
     *            template for repeatedly transforming docbook sources using the same stylesheet.
     */
    public DevelopmentConfigurationConfluenceWikiGenerator(final File reportSourceFolder,
            final VendorFilter vendorFilter, final ConfluenceSession session, final PrintStream logger,
            final DiagramDescriptorContainer dotFileDescriptorContainer, final Templates templates) {
        this.vendorFilter = vendorFilter;
        this.session = session;
        this.logger = logger;
        this.dotFileDescriptorContainer = dotFileDescriptorContainer;
        this.reportSourceFolder = reportSourceFolder;
        template = templates;
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void visit(final DevelopmentConfiguration configuration) {
        try {
            trackName = configuration.getName();
            createOverviewPage(configuration);
            createGlobalLicenseOverviewPage(configuration);
        } catch (final IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Create an overview page of licenses for external libraries used in the given development configuration.
     *
     * @param configuration
     *            development configuration to create license overview for.
     */
    private void createGlobalLicenseOverviewPage(final DevelopmentConfiguration configuration) {
        createOrUpdatePage("LicenseOverviewExternalLibraries",
                transform(createDocBookTemplateReader("LicenseOverview.xml")), trackOverviewPage.getId());
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void visit(final Compartment compartment) {
        if (!vendorFilter.accept(compartment)) {
            currentCompartmentOverviewPage = createOrUpdatePage(compartment.getName(),
                    generateWikiPageContent(compartment), trackOverviewPage.getId());
        }
    }

    /**
     * Create wiki content for the given compartment.
     *
     * @param compartment
     *            compartment to generate wiki documentation from.
     * @return generated documentation
     */
    protected String generateWikiPageContent(final Compartment compartment) {
        final String docBook = String.format("%s/%s.xml", compartment.getName(), compartment.getName());
        return transform(createDocBookTemplateReader(docBook));
    }

    private Reader createDocBookTemplateReader(final String docBookTemplate) {
        try {
            return new FileReader(new File(reportSourceFolder, docBookTemplate));
        } catch (final FileNotFoundException e) {
            throw new IllegalStateException(e);
        }
    }

    /**
     * {@inheritDoc}
     */
    @Override
    public void visit(final DevelopmentComponent component) {
        if (!vendorFilter.accept(component) && component.isNeedsRebuild()) {
            final String pageName = component.getNormalizedName("_");
            final DiagramDescriptor descriptor = dotFileDescriptorContainer.getDescriptor(component);

            final String pageContent = generateWikiPageContent(component);
            final RemotePage page = createOrUpdatePage(pageName, pageContent,
                    currentCompartmentOverviewPage.getId());

            if (descriptor != null) {
                addDependencyDiagram(page.getId(), descriptor.getUsedDCsDiagram());
                addDependencyDiagram(page.getId(), descriptor.getUsingDCsDiagram());
            }
        }
    }

    /**
     * Add a dependency diagram to the given page.
     *
     * @param pageId
     *            id of page to attach diagram to.
     * @param dotFileName
     *            name of original diagram description (.dot).
     */
    private void addDependencyDiagram(final long pageId, final String dotFileName) {
        if (!dotFileName.isEmpty()) {
            final File attachment = new File(dotFileName.replaceFirst("\\.dot", "\\.svg"));

            try {
                logger.println(String.format("Uploading attachment: %s!", attachment.getAbsolutePath()));
                session.addAttachment(pageId, attachment, "image/svg+xml", "");
            } catch (final IOException e) {
                logger.println(String.format("Attachment not found: %s!", attachment.getAbsolutePath()));
            }
        }
    }

    /**
     * Create or update a wiki page with the given content. Associate it with the given parent page.
     *
     * @param pageName
     *            name of wiki page to create or update.
     * @param pageContent
     *            content of page
     * @param parent
     *            the parent to associate the page with.
     * @return the newly created or update page.
     */
    protected RemotePage createOrUpdatePage(final String pageName, final String pageContent, final Long parent) {
        final String realPageName = trackName.equals(pageName) ? pageName : trackName + '_' + pageName;

        try {
            RemotePage page = getRemotePage(realPageName, parent);

            if (!pageContent.equals(page.getContent())) {
                logger.println(Messages
                        .DevelopmentConfigurationConfluenceWikiGenerator_updating_development_component_page(
                                realPageName));

                page.setContent(pageContent);
                page = session.updatePageV2(page, new RemotePageUpdateOptions(true, ""));
            }

            return page;
        } catch (final java.rmi.RemoteException e) {
            throw new IllegalStateException(e);
        }
    }

    /**
     * Returns the remote page with the given name. If it does not exist yet a new page object will be created and associated with the given
     * parent page.
     *
     * @param pageName
     *            name of remote page to be retrieved.
     * @param parent
     *            parent page a newly created page should be associated with.
     * @return the remote page iff it exists or a newly created page object.
     * @throws java.rmi.RemoteException
     *             when the user associated with the current confluence session has no permission to access the page.
     */
    protected RemotePage getRemotePage(final String pageName, final Long parent) throws java.rmi.RemoteException {
        long pageId = -1;

        try {
            final RemotePageSummary pageSummary = session.getPageSummary(getSpaceKey(), pageName);
            pageId = pageSummary.getId();
        } catch (final Exception e) {
            logger.println(Messages.DevelopmentConfigurationConfluenceWikiGenerator_create_page(pageName));
            final jenkins.plugins.confluence.soap.v1.RemotePage p = new jenkins.plugins.confluence.soap.v1.RemotePage();
            p.setContent("");
            p.setTitle(pageName);
            p.setSpace(getSpaceKey());
            p.setParentId(parent);

            pageId = session.storePage(p).getId();
        }

        return session.getPageV2(pageId);
    }

    /**
     * Create wiki content for the given development component.
     *
     * @param component
     *            DC to generate wiki documentation from.
     * @return generated documentation
     */
    protected String generateWikiPageContent(final DevelopmentComponent component) {
        final String docBook = String.format("%s/%s.xml", component.getCompartment().getName(),
                component.getNormalizedName("_"));

        String result = null;

        try {
            result = transform(createDocBookTemplateReader(docBook));
        } catch (final IllegalStateException e) {
            final StringWriter output = new StringWriter();

            try {
                IOUtils.copy(createDocBookTemplateReader(docBook), output);
                logger.append(e.getLocalizedMessage()).append(output.toString());
            } catch (final IOException e1) {
                e1.printStackTrace(logger);
            }

            throw e;
        }

        return result;
    }

    /**
     * Create the overview page for a track/development configuration.
     *
     * @param configuration
     *            the development configuration.
     * @throws java.rmi.RemoteException
     *             when the home page could not be found.
     */
    protected void createOverviewPage(final DevelopmentConfiguration configuration)
            throws java.rmi.RemoteException {
        final Long homePageId = session.getSpace(getSpaceKey()).getHomePage();
        trackOverviewPage = createOrUpdatePage(configuration.getName(), generateWikiPageContent(configuration),
                homePageId);
    }

    /**
     * @param configuration
     * @return
     */
    private String generateWikiPageContent(final DevelopmentConfiguration configuration) {
        final String docBook = String.format("%s.xml", configuration.getName());
        return transform(createDocBookTemplateReader(docBook));
    }

    /**
     * Add a property to the global context.
     *
     * @param key
     * @param value
     */
    public void addToGlobalContext(final ContextPropertyName key, final String value) {
        additionalContext.put(key.getName(), value);
    }

    private String getSpaceKey() {
        return (String) additionalContext.get(ContextPropertyName.WikiSpace.getName());
    }

    private Transformer newTransformer() {
        Transformer transformer;

        try {
            transformer = template.newTransformer();
            transformer.setParameter("wikiSpace", getSpaceKey());
            transformer.setParameter("track", trackName);
            transformer.setErrorListener(new ErrorListener() {

                @Override
                public void warning(final TransformerException exception) throws TransformerException {
                    logger.append(exception.getMessageAndLocation());
                }

                @Override
                public void error(final TransformerException exception) throws TransformerException {
                    logger.append(exception.getMessageAndLocation());
                }

                @Override
                public void fatalError(final TransformerException exception) throws TransformerException {
                    logger.append(exception.getMessageAndLocation());
                }
            });
        } catch (final TransformerConfigurationException e) {
            throw new IllegalStateException(e);
        }

        return transformer;
    }

    private String transform(final Reader source) {
        final StringWriter result = new StringWriter();

        try {
            newTransformer().transform(new StreamSource(source), new StreamResult(result));
        } catch (final TransformerException e) {
            throw new IllegalStateException(e);
        }

        return result.toString();
    }
}