All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.nuiton.i18n.plugin.GenerateI18nEnumHelperMojo Maven / Gradle / Ivy

Go to download

Maven plugin to deal with i18n stuff in a project, mainly base on the nuiton-i18n api (but not only).

There is a newer version: 4.2
Show newest version
package org.nuiton.i18n.plugin;

/*
 * #%L
 * I18n :: Maven Plugin
 * %%
 * Copyright (C) 2007 - 2016 CodeLutin
 * %%
 * 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%
 */

import com.google.common.base.Charsets;
import com.google.common.io.Files;
import org.antlr.v4.runtime.ANTLRInputStream;
import org.antlr.v4.runtime.CommonTokenStream;
import org.antlr.v4.runtime.TokenStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.maven.plugins.annotations.LifecyclePhase;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.codehaus.plexus.util.StringUtils;
import org.nuiton.i18n.plugin.parser.java.Java8BaseVisitor;
import org.nuiton.i18n.plugin.parser.java.Java8Lexer;
import org.nuiton.i18n.plugin.parser.java.Java8Parser;
import org.nuiton.plugin.PluginHelper;

import java.io.BufferedWriter;
import java.io.File;
import java.io.IOException;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.TreeSet;

/**
 * Generate a i18n enum class helper.
 *
 * Created on 28/08/16.
 *
 * @author Tony Chemit - [email protected]
 * @since 3.6
 */
@Mojo(name = "generateI18nEnumHelper", defaultPhase = LifecyclePhase.GENERATE_SOURCES)
public class GenerateI18nEnumHelperMojo extends AbstractI18nMojo {

    /**
     * To set the package fully qualified name of the generated class.
     *
     * By default, will use groupId.artifactId (with {@code -} replaced by {@code .}).
     */
    @Parameter(property = "i18n.packageName")
    private String packageName;

    /**
     * Name of the generated class.
     */
    @Parameter(property = "i18n.className", defaultValue = "I18nEnumHelper", required = true)
    private String className;

    /**
     * The root directory where to generated.
     */
    @Parameter(property = "i18n.outputdirectory", defaultValue = "${basedir}/target/generated-sources/java", required = true)
    private File outputdirectory;

    /**
     * List of enumerations set to scan to generate i18n keys.
     *
     * 
     *     <enumerationSets>
     *       <enumerationSet>
     *         <name>label</name>
     *         <pattern>myPrefix.@CLASS_NAME@.@NAME@</pattern>
     *         <enums>
     *           <org.nuiton.Enum1>
     *           <org.nuiton.Enum2>
     *           <...>
     *         </enums>
     *       </enumerationSet>
     *     </enumerationSets>
     * 
* * Example with enum {@code enum org.nuiton.Enum1 { A,B }}, will generate i18n keys: *
    *
  • myPrefix.org.nuiton.Enum1.A
  • *
  • myPrefix.org.nuiton.Enum1.B
  • *
* * In pattern, you can use variable *
    * *
  • {@code @CLASS_NAME@} for enumeration class fully qualified name
  • *
  • {@code @CLASS_SIMPLE_NAME@} for enumeration class simple name
  • *
  • {@code @NAME@} for enumeration name
  • *
  • {@code @ORDINAL@} for enumeration ordinal
  • *
* * Moreover, two methods will be also generated according to specified name to translate those keys : *
     *     public static String getLabel(Enum)
     *     public static String getLabel(Locale, Enum)
     * 
*/ @Parameter(required = true) private List enumerationSets; @Override protected void doAction() throws Exception { if (packageName == null) { packageName = getProject().getGroupId() + "." + getProject().getArtifactId().replaceAll("-", "."); } File directory = PluginHelper.getFile(outputdirectory, packageName.trim().split("\\.")); File file = new File(directory, className + ".java"); Files.createParentDirs(file); getLog().info("Will generate to " + file); BufferedWriter writer = Files.newWriter(file, Charsets.UTF_8); try { writer.write("// Generated by " + getClass().getName() + " at " + new Date() + "\n"); writer.write("package " + packageName + ";\n"); writer.write("\n"); writer.write("import java.util.Locale;\n"); writer.write("\n"); writer.write("import static org.nuiton.i18n.I18n.l;\n"); writer.write("import static org.nuiton.i18n.I18n.n;\n"); writer.write("import static org.nuiton.i18n.I18n.t;\n"); writer.write("\n"); writer.write("\n"); writer.write("public class " + className + " {\n"); writer.write("\n"); Set names = new HashSet<>(); for (EnumerationSet enumerationSet : enumerationSets) { if (names.add(enumerationSet.getName())) { String methodName = "get" + StringUtils.capitalise(enumerationSet.getName()); writer.write(" public static > String " + methodName + "(E e) {\n"); writer.write(" return t(" + methodName + "Key(e));\n"); writer.write(" }\n"); writer.write("\n"); writer.write(" public static > String " + methodName + "(Locale locale, E e) {\n"); writer.write(" return l(locale, " + methodName + "Key(e));\n"); writer.write(" }\n"); writer.write("\n"); writer.write(" protected static > String " + methodName + "Key(E e) {\n"); writer.write(" return " + enumerationSet.transformToMessage() + ";\n"); writer.write(" }\n"); writer.write("\n"); } } writer.write(" static {\n\n"); for (EnumerationSet enumerationSet : enumerationSets) { for (String anEnumType : enumerationSet.getEnums()) { int ordinal = 0; String simpleName = anEnumType.substring(anEnumType.lastIndexOf('.') + 1); for (String name : getEnumConstants(anEnumType)) { writer.write(" n(\"" + enumerationSet.transformToKey(anEnumType, simpleName, name, (ordinal++) + "") + "\");\n"); } } } writer.write("\n }\n"); writer.write("\n protected static String removeAnonymousSuffix(String className) {\n"); writer.write(" return className.contains(\"$\") ? className.substring(0, className.indexOf(\"$\")) : className;"); writer.write("\n }\n"); writer.write("}\n"); writer.close(); } finally { IOUtils.closeQuietly(writer); } } private Set getEnumConstants(String anEnumType) throws ClassNotFoundException, IOException { getLog().info("Scan enum: " + anEnumType); Set result = new TreeSet<>(); try { Class aClass = Class.forName(anEnumType); if (!aClass.isEnum()) { throw new IllegalStateException("Type " + aClass.getName() + " is not an enum."); } for (Object o : aClass.getEnumConstants()) { result.add(((Enum) o).name()); } } catch (ClassNotFoundException e) { // try with antlr4 File basedir = new File(new File(new File(getProject().getBasedir(), "src"), "main"), "java"); File file = PluginHelper.getFile(basedir, anEnumType.trim().split("\\.")); File javaFile = new File(file.getParentFile(), file.getName() + ".java"); if (javaFile.exists()) { String content = FileUtils.readFileToString(javaFile, "UTF-8"); TokenStream tokenStream = new CommonTokenStream(new Java8Lexer(new ANTLRInputStream(content))); Java8Parser parser = new Java8Parser(tokenStream); // see http://stackoverflow.com/a/32918434/2038100 //parser.setErrorHandler(new BailErrorStrategy()); //parser.getInterpreter().setPredictionMode(PredictionMode.SLL); //parser.getInterpreter().tail_call_preserves_sll = false; parser.getInterpreter().enable_global_context_dfa = true; JavaParserVisitor visitor = new JavaParserVisitor(javaFile); parser.compilationUnit().accept(visitor); Set names = visitor.getNames(); result.addAll(names); } } return result; } protected class JavaParserVisitor extends Java8BaseVisitor { protected final Set names; protected final File file; private JavaParserVisitor(File file) { this.file = file; names = new LinkedHashSet<>(); } public Set getNames() { return names; } @Override public Void visitEnumConstant(Java8Parser.EnumConstantContext ctx) { String text = ctx.getChild(0).getText(); names.add(text); return super.visitEnumConstant(ctx); } } public static class EnumerationSet { private String name; private String pattern; private List enums; public String getName() { return name; } public void setName(String name) { this.name = name; } public String getPattern() { return pattern; } public void setPattern(String pattern) { this.pattern = pattern; } public List getEnums() { return enums; } public void setEnums(List enums) { this.enums = enums; } public String transformToKey(String className, String simpleName, String name, String ordinal) { String result = pattern; result = result.replace("@CLASS_NAME@", className); result = result.replace("@CLASS_SIMPLE_NAME@", simpleName); result = result.replace("@NAME@", name); result = result.replace("@ORDINAL@", ordinal); return result; } public String transformToMessage() { String result = ""; StringTokenizer stringTokenizer = new StringTokenizer(pattern, "@"); while (stringTokenizer.hasMoreTokens()) { if (!result.isEmpty()) { result += " + "; } String token = stringTokenizer.nextToken(); switch (token) { case "CLASS_SIMPLE_NAME": result += "e.getClass().getSimpleName()"; break; case "CLASS_NAME": result += "removeAnonymousSuffix(e.getClass().getName())"; break; case "NAME": result += "e.name()"; break; case "ORDINAL": result += "e.ordinal()"; break; default: result += "\"" + token + "\""; } } if (result.endsWith("+")) { result = result.substring(0, result.length() - 1); } return result; } } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy