
org.nuiton.i18n.plugin.I18nMojoSupport Maven / Gradle / Ivy
/*
* #%L
* I18n :: Maven Plugin
* %%
* Copyright (C) 2007 - 2017 Code Lutin, Ultreia.io
* %%
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of the
* License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Lesser Public License for more details.
*
* You should have received a copy of the GNU General Lesser Public
* License along with this program. If not, see
* .
* #L%
*/
package org.nuiton.i18n.plugin;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.plugins.annotations.Parameter;
import org.apache.maven.project.MavenProject;
import org.nuiton.i18n.I18nUtil;
import org.nuiton.i18n.plugin.bundle.BundleValidation;
import org.nuiton.plugin.AbstractPlugin;
import org.nuiton.plugin.PluginHelper;
import org.nuiton.plugin.PluginWithEncoding;
import java.io.File;
import java.io.IOException;
import java.nio.charset.Charset;
import java.util.Locale;
import java.util.Map;
import java.util.Properties;
import java.util.SortedSet;
import java.util.TreeSet;
/**
* Lower level i18n mojo abstraction.
*
* We defines here all commons parameters and shared behaviour.
*
* @author Tony Chemit - [email protected]
* @author Julien Ruchaud - [email protected]
*/
public abstract class I18nMojoSupport extends AbstractPlugin implements PluginWithEncoding {
@Parameter(defaultValue = "${session}", readonly = true)
protected MavenSession mavenSession;
/**
* Dependance du projet.
*
* @since 1.0.2
*/
@Parameter(defaultValue = "${project}", readonly = true)
protected MavenProject project;
/**
* Locales to treat, separated by comma.
*
* Example :
*
fr_FR,en_GB
*/
@Parameter(property = "i18n.bundles", defaultValue = "fr_FR,en_GB", required = true)
protected String bundles;
/** Encoding used to load properties. */
@Parameter(property = "i18n.encoding", defaultValue = "${project.build.sourceEncoding}", required = true)
protected String encoding;
/**
* Name to use as prefix of generated files.
*
* Note : By default, use the artifact id.
*/
@Parameter(property = "i18n.artifactId", defaultValue = "${project.artifactId}", readonly = true)
protected String artifactId;
/** Directory where to find project i18n files. */
@Parameter(property = "i18n.sourceDirectory", defaultValue = "${basedir}/src/main/resources/i18n", required = true)
protected File sourceDirectory;
/** Build directory (used to know if files in sources are up-to-date). */
@Parameter(property = "i18n.buildOutputDirectory", defaultValue = "${project.build.outputDirectory}")
protected File buildOutputDirectory;
/** Directory where to generate getters files. */
@Parameter(property = "i18n.gettersDirectory", defaultValue = "${project.build.directory}/i18n/getters", required = true)
protected File gettersDirectory;
/**
* Verbose flag.
*
* Note : if not set, we used the {@code maven.verbose} property.
*/
@Parameter(property = "i18n.verbose", defaultValue = "${maven.verbose}")
protected boolean verbose;
/**
* Silent flag to see only errors in console.
*
* @since 1.0.0-rc-5
*/
@Parameter(property = "i18n.silent", defaultValue = "false")
protected boolean silent;
/** locales to process */
protected Locale[] locales;
protected Charset charset;
@Override
protected boolean checkPackaging() {
// nothing to do on a pom module
return !acceptPackaging(Packaging.pom);
}
@Override
public void init() throws Exception {
charset = Charset.forName(encoding);
if (verbose) {
// in verbose mode, no silent
silent = false;
getLog().info("config - verbose mode is on");
}
locales = I18nUtil.parseLocales(bundles);
if (locales.length == 0) {
throw new IllegalStateException(
"You need at least one locale, please fill the 'bundles' property.");
}
}
protected void checkBundle(Locale locale,
Properties propertiesOut,
boolean showEmpty,
BundleValidation bundleValidation) {
// on verifie qu'il n'y a pas de traduction vide
SortedSet emptyEntries = PluginHelper.getEmptyKeys(propertiesOut);
if (!emptyEntries.isEmpty()) {
if (bundleValidation != null) {
Map> unsafeHolder = bundleValidation.getKeysMissingValues();
// push empties i18n keys in the holder
SortedSet empties = unsafeHolder.computeIfAbsent(locale, k -> new TreeSet<>());
empties.addAll(emptyEntries);
}
StringBuilder buffer = new StringBuilder();
int size = emptyEntries.size();
buffer.append("bundle ");
buffer.append(locale);
buffer.append(" contains ");
buffer.append(size);
buffer.append("/");
buffer.append(propertiesOut.size());
buffer.append(" empty entries!");
if (showEmpty) {
int index = 0;
for (String key : emptyEntries) {
buffer.append("\n - ");
buffer.append(index++);
buffer.append("/");
buffer.append(size);
buffer.append(" : ");
buffer.append(key);
}
} else {
buffer.append(" (use -Di18n.showEmpty to see these entries)");
}
getLog().warn(buffer.toString());
} else {
if (!silent && verbose) {
getLog().info(String.format("bundle %s is valid (no empty entries).", locale));
}
}
}
@Override
public File getBackupFile(File file) {
return new File(file.getAbsolutePath() + "~");
}
@Override
protected void backupFile(File f) throws IOException {
File dst = getBackupFile(f);
copyFile(f, dst);
}
@Override
public MavenProject getProject() {
return project;
}
@Override
public void setProject(MavenProject project) {
this.project = project;
}
@Override
public boolean isVerbose() {
return verbose;
}
@Override
public void setVerbose(boolean verbose) {
this.verbose = verbose;
}
public boolean isSilent() {
return silent;
}
public String getEncoding() {
return encoding;
}
@Override
public void setEncoding(String encoding) {
this.encoding = encoding;
}
protected void failsIfAnyKeyMissingValue(boolean failsIfWarning, BundleValidation bundleValidation) throws MojoFailureException {
if (!failsIfWarning) {
// no check
return;
}
if (bundleValidation != null && bundleValidation.isAnyKeyMissingValue()) {
// there is at least one not complete bundle, fails the build
throw new MojoFailureException(
String.format("Bundles for locale(s) %s are not complete. Use the -Di18n.showEmpty to see missing translations.", bundleValidation.getKeysMissingValues().keySet()));
}
}
protected void failsIfAnyKeyMissingInBundle(boolean failsIfWarning, BundleValidation bundleValidation) throws MojoFailureException {
if (!failsIfWarning) {
// no check
return;
}
if (bundleValidation != null && bundleValidation.isAnyKeyMissingInBundle()) {
// there is at least one not complete bundle, fails the build
throw new MojoFailureException(
String.format("Bundles for locale(s) %s are not complete. Use the -Di18n.showEmpty to see missing keys.", bundleValidation.getMissingKeysPerLocale().keySet()));
}
}
/**
* @param root le repertoire ou sont stockes les fichiers i18n
* @param artifactId le nom de l'artifact
* @param locale le nom de la locale (peut-être nulle)
* @param create {@code true} pour creer le fichier si non present
* @return le fichier i18n
* @throws IOException si probleme lors de la creation du fichier
*/
protected File getI18nFile(File root, String artifactId, Locale locale, boolean create) throws IOException {
String path = root.getAbsolutePath() + File.separatorChar + artifactId;
if (locale != null) {
path += "_" + locale.toString();
}
path += ".properties";
File file = new File(path);
if (create && !file.exists()) {
PluginHelper.createNewFile(file);
}
return file;
}
protected String getProjectCacheKey() {
return getClass().getSimpleName() + ":" + getProject().getGroupId() + ":" + getProject().getArtifactId() + ":" + getProject().getArtifact().getClassifier() + ":" + getProject().getVersion();
}
}