org.sventon.util.HTMLCreator.java Source code

Java tutorial

Introduction

Here is the source code for org.sventon.util.HTMLCreator.java

Source

/*
 * ====================================================================
 * Copyright (c) 2005-2012 sventon project. All rights reserved.
 *
 * This software is licensed as described in the file LICENSE, which
 * you should have received as part of this distribution. The terms
 * are also available at http://www.sventon.org.
 * If newer versions of this license are posted there, you may use a
 * newer version instead, at your option.
 * ====================================================================
 */
package org.sventon.util;

import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.text.StrSubstitutor;
import org.sventon.model.ChangeType;
import org.sventon.model.ChangedPath;
import org.sventon.model.LogEntry;
import org.sventon.model.RepositoryName;

import javax.servlet.http.HttpServletResponse;
import java.text.DateFormat;
import java.util.HashMap;
import java.util.Map;
import java.util.SortedSet;
import java.util.regex.Matcher;

import static org.sventon.util.EncodingUtils.encodeUrl;

/**
 * Class responsible for creating HTML formatted content.
 *
 * @author jesper@sventon.org
 */
public final class HTMLCreator {

    public static final String LOG_MESSAGE_KEY = "logMessage";
    public static final String AUTHOR_KEY = "author";
    public static final String DATE_KEY = "date";
    public static final String ADDED_COUNT_KEY = "addedCount";
    public static final String MODIFIED_COUNT_KEY = "modifiedCount";
    public static final String REPLACED_COUNT_KEY = "replacedCount";
    public static final String DELETED_COUNT_KEY = "deletedCount";
    public static final String CHANGED_PATHS_KEY = "changedPaths";

    /**
     * Prevent instantiation.
     */
    private HTMLCreator() {
    }

    /**
     * Creates a string containing the details for a given revision.
     *
     * @param bodyTemplate   Body template string.
     * @param logEntry       log entry revision.
     * @param baseURL        Application base URL.
     * @param repositoryName Repository name.
     * @param response       Response, null if n/a.
     * @param dateFormat     Date formatter instance.
     * @return Result
     */
    public static String createRevisionDetailBody(final String bodyTemplate, final LogEntry logEntry,
            final String baseURL, final RepositoryName repositoryName, final DateFormat dateFormat,
            final HttpServletResponse response) {

        final Map<String, String> valueMap = new HashMap<String, String>();

        int added = 0;
        int modified = 0;
        int replaced = 0;
        int deleted = 0;

        //noinspection unchecked
        final SortedSet<ChangedPath> latestChangedPaths = logEntry.getChangedPaths();

        for (final ChangedPath entryPath : latestChangedPaths) {
            final ChangeType type = entryPath.getType();
            switch (type) {
            case ADDED:
                added++;
                break;
            case MODIFIED:
                modified++;
                break;
            case REPLACED:
                replaced++;
                break;
            case DELETED:
                deleted++;
                break;
            default:
                throw new IllegalArgumentException("Unsupported type: " + type);
            }
        }
        final String logMessage = WebUtils.nl2br(StringEscapeUtils.escapeHtml(logEntry.getMessage())); //TODO: Parse to apply Bugtraq link
        final String author = logEntry.getAuthor();

        valueMap.put(ADDED_COUNT_KEY, Matcher.quoteReplacement(String.valueOf(added)));
        valueMap.put(MODIFIED_COUNT_KEY, Matcher.quoteReplacement(String.valueOf(modified)));
        valueMap.put(REPLACED_COUNT_KEY, Matcher.quoteReplacement(String.valueOf(replaced)));
        valueMap.put(DELETED_COUNT_KEY, Matcher.quoteReplacement(String.valueOf(deleted)));
        valueMap.put(LOG_MESSAGE_KEY, Matcher.quoteReplacement(StringUtils.trimToEmpty(logMessage)));
        valueMap.put(AUTHOR_KEY, Matcher.quoteReplacement(StringUtils.trimToEmpty(author)));
        valueMap.put(DATE_KEY, dateFormat.format(logEntry.getDate()));
        valueMap.put(CHANGED_PATHS_KEY,
                Matcher.quoteReplacement(HTMLCreator.createChangedPathsTable(logEntry.getChangedPaths(),
                        logEntry.getRevision(), null, baseURL, repositoryName, false, false, response)));

        return new StrSubstitutor(valueMap).replace(bodyTemplate);
    }

    /**
     * Creates a HTML table containing the changed paths for given revision.
     *
     * @param changedPaths      Paths changed in this revision.
     * @param revision          Revision.
     * @param pathAtRevision    The target's path at current revision or <tt>null</tt> if unknown.
     * @param baseURL           Base application URL.
     * @param repositoryName    Repository name.
     * @param showLatestRevInfo If true, the latest revision details DIV will be displayed.
     * @param linkToHead        If true, navigation links will be pointing at HEAD if applicable.
     * @param response          The HTTP response, used to encode the session parameter to the generated URLs. Null if n/a.
     * @return The HTML table.
     */
    public static String createChangedPathsTable(final SortedSet<ChangedPath> changedPaths, final long revision,
            final String pathAtRevision, final String baseURL, final RepositoryName repositoryName,
            final boolean showLatestRevInfo, final boolean linkToHead, final HttpServletResponse response) {

        final StringBuilder sb = new StringBuilder("<table class=\"changedPathsTable\">\n");
        sb.append("  <tr>\n");
        sb.append("    <th align=\"left\">Action</th>\n");
        sb.append("    <th align=\"left\">Path</th>\n");
        sb.append("  </tr>\n");

        for (final ChangedPath path : changedPaths) {
            final ChangeType changeType = path.getType();

            sb.append("  <tr>\n");
            sb.append("    <td valign=\"top\"><i>").append(changeType).append("</i></td>\n");

            sb.append("    <td>");

            String goToUrl;
            switch (changeType) {
            case ADDED: // fall thru
            case REPLACED:
                // goToUrl
                goToUrl = createGoToUrl(baseURL, path.getPath(), revision, repositoryName, linkToHead);
                if (response != null) {
                    goToUrl = response.encodeURL(goToUrl);
                }
                sb.append("<a href=\"").append(goToUrl);
                if (showLatestRevInfo) {
                    sb.append("&showlatestrevinfo=true");
                }
                sb.append("\" title=\"Show\">");
                if (path.getPath().equals(pathAtRevision)) {
                    sb.append("<i>").append(path.getPath()).append("</i>").append("</a>");
                } else {
                    sb.append(path.getPath()).append("</a>");
                }
                break;
            case MODIFIED:
                // diffUrl
                String diffUrl = createDiffUrl(baseURL, path.getPath(), revision, repositoryName, linkToHead);
                if (response != null) {
                    diffUrl = response.encodeURL(diffUrl);
                }
                sb.append("<a href=\"").append(diffUrl);
                if (showLatestRevInfo) {
                    sb.append("&showlatestrevinfo=true");
                }
                sb.append("\" title=\"Diff with previous version\">");
                if (path.getPath().equals(pathAtRevision)) {
                    sb.append("<i>").append(path.getPath()).append("</i>").append("</a>");
                } else {
                    sb.append(path.getPath()).append("</a>");
                }
                break;
            case DELETED:
                // del
                goToUrl = createGoToUrl(baseURL, path.getPath(), revision - 1, repositoryName, false);
                if (response != null) {
                    goToUrl = response.encodeURL(goToUrl);
                }
                sb.append("<a href=\"").append(goToUrl);
                sb.append("\" title=\"Show previous revision\"><del>").append(path.getPath()).append("</del></a>");
                break;
            default:
                throw new IllegalArgumentException("Unsupported type: " + changeType);
            }

            if (path.getCopyPath() != null) {
                sb.append("<br>(<i>Copy from</i> ");
                goToUrl = createGoToUrl(baseURL, path.getCopyPath(), path.getCopyRevision(), repositoryName, false);
                if (response != null) {
                    goToUrl = response.encodeURL(goToUrl);
                }
                sb.append("<a href=\"").append(goToUrl);
                if (showLatestRevInfo) {
                    sb.append("&showlatestrevinfo=true");
                }
                sb.append("\" title=\"Show\">").append(path.getCopyPath()).append("</a>").append(" @ ");
                String revisionInfoUrl = createRevisionInfoUrl(baseURL, path.getCopyRevision(), repositoryName);
                if (response != null) {
                    revisionInfoUrl = response.encodeURL(revisionInfoUrl);
                }
                sb.append("<a href=\"").append(revisionInfoUrl);
                sb.append("\">");
                sb.append(path.getCopyRevision()).append("</a>)");
            }
            sb.append("</td>\n");
            sb.append("  </tr>\n");
        }
        sb.append("</table>");
        return sb.toString();
    }

    /**
     * Creates a <i>goto</i> URL based on given parameters.
     *
     * @param baseURL        Base application URL
     * @param path           Path
     * @param revision       Revision
     * @param repositoryName Repository name.
     * @param linkToHead     If true, the navigation link will point to head.
     * @return The URL
     */
    protected static String createGoToUrl(final String baseURL, final String path, final long revision,
            final RepositoryName repositoryName, final boolean linkToHead) {

        final StringBuilder sb = new StringBuilder(baseURL).append("repos/");
        sb.append(encodeUrl(repositoryName.toString() + "/goto" + path));
        sb.append("?revision=").append(linkToHead ? "HEAD" : revision);
        return sb.toString();
    }

    /**
     * Creates a <i>diff</i> URL based on given parameters.
     *
     * @param baseURL        Base application URL
     * @param path           Path
     * @param revision       Revision
     * @param repositoryName Repository name.
     * @param linkToHead     If true, the navigation link will point to head.
     * @return The URL
     */
    protected static String createDiffUrl(final String baseURL, final String path, final long revision,
            final RepositoryName repositoryName, final boolean linkToHead) {

        final String entry1 = path + "@" + revision;
        final String entry2 = path + "@" + (revision - 1);

        final StringBuilder sb = new StringBuilder(baseURL).append("repos/");
        sb.append(encodeUrl(repositoryName.toString() + "/diff" + path));
        sb.append("?revision=").append(linkToHead ? "HEAD" : revision);
        sb.append("&entries=").append(entry1);
        sb.append("&entries=").append(entry2);
        return sb.toString();
    }

    /**
     * Creates a <i>revision info</i> URL based on given parameters.
     *
     * @param baseURL        Base application URL
     * @param revision       Revision
     * @param repositoryName Repository name.
     * @return The URL
     */
    protected static String createRevisionInfoUrl(final String baseURL, final long revision,
            final RepositoryName repositoryName) {
        final StringBuilder sb = new StringBuilder(baseURL).append("repos/");
        sb.append(encodeUrl(repositoryName.toString() + "/info"));
        sb.append("?revision=").append(encodeUrl(String.valueOf(revision)));
        return sb.toString();
    }

}