WatermarkingMojo.java

package org.thewonderlemming.c4plantuml.mojo;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;

/**
 * A MOJO that adds a watermark to the C4 PlantUML files that are contained in the output directory, allowing the
 * generated schemas to hold information on the generation date, the build version and so on.
 *
 * @author thewonderlemming
 *
 */
@Mojo(name = "watermark", defaultPhase = LifecyclePhase.PROCESS_CLASSES)
public class WatermarkingMojo extends AbstractParentMojo {

    /**
     * Default copyright name, if none is provided.
     * <p>
     * It is the default value for the {@code copyrightName} property.
     */
    public static final String DEFAULT_COPYRIGHT_NAME = "";

    /**
     * Default format for the date, if an invalid formatting pattern or no pattern is provided.
     * <p>
     * It defaults to {@code DateTimeFormatter.ISO_DATE}.
     */
    public static final DateTimeFormatter DEFAULT_DATE_FORMATTER = DateTimeFormatter.ISO_DATE;

    /**
     * Default diagram name, if none is provided.
     * <p>
     * It is the default value for the {@code watermarkName} property.
     */
    public static final String DEFAULT_WATERMARK_NAME = "changeMe";

    /**
     * Watermark string pattern.
     */
    public static final String WATERMARK_FORMAT_STRING = "FOOTER(\"Version %s - Generated on %s - \u00a9%d %s\", \"%s\")";

    private static final String END_UML_TAG = "@enduml";

    @Parameter(property = "copyrightName", defaultValue = DEFAULT_COPYRIGHT_NAME, alias = "copyrightName")
    private String copyrightName;

    @Parameter(property = "dateFormat", defaultValue = "", alias = "dateFormat")
    private String dateFormat;

    @Parameter(property = "watermarkName", defaultValue = DEFAULT_WATERMARK_NAME, alias = "watermarkName")
    private String watermarkName;


    /**
     * Adds watermark to the C4 PlantUML files contained in the output directory.
     * <p>
     * {@inheritDoc}
     */
    @Override
    protected void doExecute() throws MojoExecutionException, MojoFailureException {

        try {

            processOutputDirectory();

        } catch (final IOException e) {

            final String errMsg = "Cannot process output directory \"" + getOutputDirectory() + "\" for watermaking";
            throw new MojoFailureException(errMsg, e);
        }
    }

    private void addWatermarkToFile(final Path file) throws IOException {

        assert (getCurrentCharset() != null) : "Expected currentCharset to be set";
        assert (file != null && file.toFile().exists()) : "Expected given path to exist";
        assert (file.toFile().isFile()) : "Expected given path to be a file";

        final String content = new String(Files.readAllBytes(file), getCurrentCharset())
            .replace(END_UML_TAG, generateWatermarkString() + "\n" + END_UML_TAG);

        Files.write(file, content.getBytes(getCurrentCharset()));
    }

    private String generateWatermarkString() {

        final LocalDate currentDate = LocalDate.now();
        final String diagramVersion = getProject().getVersion();
        final String diagramName = this.watermarkName.isEmpty()
            ? getProject().getGroupId() + ":" + getProject().getArtifactId()
            : this.watermarkName;

        return String
            .format(WATERMARK_FORMAT_STRING,
                diagramVersion,
                currentDate.format(getDateTimeFormatter()),
                currentDate.getYear(),
                this.copyrightName != null ? this.copyrightName : "",
                diagramName);
    }

    private DateTimeFormatter getDateTimeFormatter() {

        try {

            return null != dateFormat
                ? DateTimeFormatter.ofPattern(this.dateFormat)
                : DEFAULT_DATE_FORMATTER;

        } catch (final IllegalArgumentException e) {
            return DEFAULT_DATE_FORMATTER;
        }
    }

    private void processOutputDirectory() throws IOException {

        assert (getOutputDirectory() != null) : "Expected outputDirectory to be set";

        processOutputDirectoryFiles(path -> {

            try {

                addWatermarkToFile(path);

            } catch (final IOException e) {
                getLog().error("Cannot add watermark to file: " + path, e);
            }
        });
    }
}