001/*
002 * Licensed to the Apache Software Foundation (ASF) under one or more
003 * contributor license agreements.  See the NOTICE file distributed with
004 * this work for additional information regarding copyright ownership.
005 * The ASF licenses this file to You under the Apache License, Version 2.0
006 * (the "License"); you may not use this file except in compliance with
007 * the License.  You may obtain a copy of the License at
008 *
009 *      https://www.apache.org/licenses/LICENSE-2.0
010 *
011 * Unless required by applicable law or agreed to in writing, software
012 * distributed under the License is distributed on an "AS IS" BASIS,
013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014 * See the License for the specific language governing permissions and
015 * limitations under the License.
016 */
017package org.apache.commons.release.plugin.velocity;
018
019import java.io.Writer;
020import java.util.regex.Pattern;
021
022import org.apache.commons.lang3.StringUtils;
023import org.apache.velocity.Template;
024import org.apache.velocity.VelocityContext;
025import org.apache.velocity.app.VelocityEngine;
026import org.apache.velocity.runtime.RuntimeConstants;
027import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
028
029/**
030 * Generates the <code>README.html</code> file that accompanies the release in the distribution area.
031 *
032 * @since 1.3
033 */
034public final class ReadmeHtmlVelocityDelegate {
035
036    /**
037     * A builder class for instantiation of the {@link ReadmeHtmlVelocityDelegate}.
038     */
039    public static final class ReadmeHtmlVelocityDelegateBuilder {
040
041        /** The Maven artifactId to use in the <code>README.vm</code> template. */
042        private String artifactId;
043
044        /** The Maven version to use in the <code>README.vm</code> template. */
045        private String version;
046
047        /** The site URL to use in the <code>README.vm</code> template. */
048        private String siteUrl;
049
050        /**
051         * Private constructor for using the builder through the {@link ReadmeHtmlVelocityDelegate#builder()}
052         * method.
053         */
054        private ReadmeHtmlVelocityDelegateBuilder() {
055        }
056
057        /**
058         * Builds up the {@link ReadmeHtmlVelocityDelegate} from the previously set parameters.
059         *
060         * @return A new {@link ReadmeHtmlVelocityDelegate}.
061         */
062        public ReadmeHtmlVelocityDelegate build() {
063            return new ReadmeHtmlVelocityDelegate(this.artifactId, this.version, this.siteUrl);
064        }
065
066        /**
067         * Sets the Maven artifact ID for the {@link ReadmeHtmlVelocityDelegate}.
068         *
069         * @param artifactId The {@link String} representing the Maven artifactId.
070         * @return The builder to continue building.
071         */
072        public ReadmeHtmlVelocityDelegateBuilder setArtifactId(final String artifactId) {
073            this.artifactId = artifactId;
074            return this;
075        }
076
077        /**
078         * Sets the site URL for the {@link ReadmeHtmlVelocityDelegate}.
079         *
080         * @param siteUrl The site URL to be used in the <code>README.html</code>
081         * @return The builder to continue building.
082         */
083        public ReadmeHtmlVelocityDelegateBuilder setSiteUrl(final String siteUrl) {
084            this.siteUrl = siteUrl;
085            return this;
086        }
087
088        /**
089         * Sets the version for the {@link ReadmeHtmlVelocityDelegate}.
090         *
091         * @param version The Maven version.
092         * @return The builder to continue building.
093         */
094        public ReadmeHtmlVelocityDelegateBuilder setVersion(final String version) {
095            this.version = version;
096            return this;
097        }
098    }
099
100    /**
101     * ".+\\d$" matches a non-empty string that terminates in a digit {0-9}.
102     */
103    private static final Pattern END_DIGIT = Pattern.compile(".+\\d$");
104
105    /** The location of the Velocity template for this class. */
106    private static final String TEMPLATE = "resources/org/apache/commons/release/plugin"
107                                         + "/velocity/README.vm";
108
109    /**
110     * Gets the {@link ReadmeHtmlVelocityDelegateBuilder} for constructing the {@link ReadmeHtmlVelocityDelegate}.
111     *
112     * @return The {@link ReadmeHtmlVelocityDelegateBuilder}.
113     */
114    public static ReadmeHtmlVelocityDelegateBuilder builder() {
115        return new ReadmeHtmlVelocityDelegateBuilder();
116    }
117
118    /** This is supposed to represent the Maven artifactId. */
119    private final String artifactId;
120
121    /** This is supposed to represent the Maven version of the release. */
122    private final String version;
123
124    /** The URL of the site that gets set into the <code>README.html</code>. */
125    private final String siteUrl;
126
127    /**
128     * The private constructor to be used by the {@link ReadmeHtmlVelocityDelegateBuilder}.
129     *
130     * @param artifactId sets the {@link ReadmeHtmlVelocityDelegate#artifactId}.
131     * @param version sets the {@link ReadmeHtmlVelocityDelegate#version}.
132     * @param siteUrl sets the {@link ReadmeHtmlVelocityDelegate#siteUrl}.
133     */
134    private ReadmeHtmlVelocityDelegate(final String artifactId, final String version, final String siteUrl) {
135        this.artifactId = artifactId;
136        this.version = version;
137        this.siteUrl = siteUrl;
138    }
139
140    /**
141     * Renders the <code>README.vm</code> Velocity template with the variables constructed with the
142     * {@link ReadmeHtmlVelocityDelegateBuilder}.
143     *
144     * @param writer is the {@link Writer} to which we wish to render the <code>README.vm</code> template.
145     * @return A reference to the {@link Writer} passed in.
146     */
147    public Writer render(final Writer writer) {
148        final VelocityEngine ve = new VelocityEngine();
149        ve.setProperty(RuntimeConstants.RESOURCE_LOADER, "classpath");
150        ve.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
151        ve.init();
152        final Template template = ve.getTemplate(TEMPLATE);
153        final String[] splitArtifactId = artifactId.split("-");
154        final String wordCommons = "commons";
155        String artifactShortName = "";
156        if (splitArtifactId.length > 1) {
157            artifactShortName = splitArtifactId[1];
158        } else if (splitArtifactId.length == 1) {
159            artifactShortName = splitArtifactId[0];
160        }
161        if (END_DIGIT.matcher(artifactShortName).matches()) {
162            artifactShortName = artifactShortName.substring(0, artifactShortName.length() - 1);
163        }
164        final String artifactIdWithFirstLetterscapitalized =
165                StringUtils.capitalize(wordCommons)
166                        + "-"
167                        + artifactShortName.toUpperCase();
168        final VelocityContext context = new VelocityContext();
169        context.internalPut("artifactIdWithFirstLetterscapitalized", artifactIdWithFirstLetterscapitalized);
170        context.internalPut("artifactShortName", artifactShortName.toUpperCase());
171        context.internalPut("artifactId", artifactId);
172        context.internalPut("version", version);
173        context.internalPut("siteUrl", siteUrl);
174        template.merge(context, writer);
175        return writer;
176    }
177}