AbstractParentMojo.java
package org.thewonderlemming.c4plantuml.mojo;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.function.Consumer;
import java.util.regex.Pattern;
import java.util.stream.Stream;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
/**
* A base implementation of a MOJO that handles shared parameters such as {@link Charset}, {@link MavenProject}, and so
* on.
*
* @author thewonderlemming
*
*/
public abstract class AbstractParentMojo extends AbstractMojo {
/**
* Default value for the C4 PlantUML files extension.
*/
public static final String DEFAULT_SOURCE_FILE_EXTENSION = ".puml";
private static final Pattern SOURCE_FILE_EXTENSION_PATTERN = Pattern.compile("^\\.[a-zA-Z0-9]+$");
private Charset currentCharset;
private String outputDirectory;
@Parameter(property = "project", defaultValue = "${project}", readonly = true, required = true)
private MavenProject project;
@Parameter(property = "sourceFileExtension", defaultValue = AbstractParentMojo.DEFAULT_SOURCE_FILE_EXTENSION,
alias = "sourceFileExtension")
private String sourceFileExtension;
private static boolean isFile(final Path path) {
return path.toFile().isFile();
}
/**
* The default implementation of {@link AbstractMojo#execute()}, that sets and validates shared parameters, then
* calls the abstract method {@link AbstractParentMojo#doExecute()}, that needs to be implemented by children
* classes.
* <p>
* {@inheritDoc}
*/
@Override
public final void execute() throws MojoExecutionException, MojoFailureException {
validateSourceFileExtension();
setCurrentCharset();
setOutputDirectory();
doExecute();
}
/**
* An abstract method to hold the children classes execution logic.
*
* @throws MojoExecutionException if there is an issue with the build that makes it impossible to continue.
* @throws MojoFailureException if there is any other kind of failures.
*/
protected abstract void doExecute() throws MojoExecutionException, MojoFailureException;
/**
* Returns the current {@link Charset} value.
*
* @return the current {@link Charset}.
*/
protected Charset getCurrentCharset() {
return currentCharset;
}
/**
* Returns the project output directory path.
*
* @return the project output directory.
*/
protected String getOutputDirectory() {
return this.outputDirectory;
}
/**
* Returns the current {@link MavenProject} instance.
*
* @return the {@link MavenProject} instance.
*/
protected MavenProject getProject() {
return this.project;
}
/**
* Returns the current sources filename extension.
* <p>
* This is how the plugin will determine which files it should process.
*
* @return the sources filename extension.
*/
protected String getSourceFileExtension() {
return this.sourceFileExtension;
}
/**
* An utility method that enables the processing of the C4 PlantUML sources in the output directory.
*
* @param pumlFileProcessor the source file consumer method.
* @throws IOException if any I/O error happens while accessing a source file.
*/
protected void processOutputDirectoryFiles(final Consumer<Path> pumlFileProcessor) throws IOException {
try (final Stream<Path> pathStream = Files.walk(Paths.get(getOutputDirectory()))) {
pathStream
.filter(AbstractParentMojo::isFile)
.filter(this::isPumlSource)
.forEach(pumlFileProcessor::accept);
}
}
/**
* Validates that the current {@code sourceFileExtension} property has a correct value, or sets it to the default
* value and displays an error message.
*/
protected void validateSourceFileExtension() {
assert (this.sourceFileExtension != null) : "Expecting sourceFileExtension to be set";
if (!SOURCE_FILE_EXTENSION_PATTERN.matcher(this.sourceFileExtension).matches()) {
final String errMsg = String
.format("Bad format for sourceFileExtension: %s. Reverting to default value instead: %s",
this.sourceFileExtension,
DEFAULT_SOURCE_FILE_EXTENSION);
getLog().warn(errMsg);
this.sourceFileExtension = DEFAULT_SOURCE_FILE_EXTENSION;
}
}
private boolean isPumlSource(final Path path) {
assert (this.sourceFileExtension != null) : "Expecting sourceFileExtension to be set";
return path.toString().toLowerCase().endsWith(this.sourceFileExtension);
}
private void setCurrentCharset() throws MojoExecutionException {
try {
final String sourceEncoding = this.project
.getProperties()
.getProperty("project.build.sourceEncoding", StandardCharsets.UTF_8.toString());
this.currentCharset = Charset.forName(sourceEncoding);
} catch (final IllegalArgumentException e) {
throw new MojoExecutionException("Cannot get character encoding for source files", e);
}
}
private void setOutputDirectory() throws MojoExecutionException {
this.outputDirectory = getProject().getBuild().getOutputDirectory();
if (!new File(this.outputDirectory).exists()) {
final String errMsg = "Cannot process source directory \"" + this.outputDirectory
+ "\" as it does not exist";
throw new MojoExecutionException(errMsg);
}
}
}