Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright 2010 Michel Jung
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License.You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, softwaredistributed under the License is distributed on an
* "AS IS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the License for the
* specific language governing permissions andlimitations under the License.
*/
package com.google.code.maven.propertiesenumplugin;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.io.Writer;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.plugin.MojoFailureException;
import org.apache.maven.project.MavenProject;
/**
* This Mojo generates a Java enum based on the keys of a properties file.
*
* @author Michel Jung
* @goal generate
* @phase generate-sources
*/
public class EnumGeneratorMojo extends AbstractMojo {
/**
* Code for the toString() method.
*/
private static final CharSequence TO_STRING_METHOD = " @Override\n public final String toString() {\n"
+ " return originalKey;\n }\n";
/**
* Code for getBaseName() method. Expects the base name as argument.
*/
private static final String GET_BASE_NAME_METHOD = " public final String getBaseName() {\n"
+ " return \"%s\";\n }\n\n";
/**
* Builds the base name for the given file.
*
* @param baseDir
* the base directory
* @param propertiesFile
* the properties file
* @return e.g. "com.example.Property" if baseDir is "src/main/resources" and propertiesFile
* is "src/main/resources/com/example/Property.properties"
*/
static String buildBaseName(final File baseDir, final File propertiesFile) {
String fileName = propertiesFile.getName();
String packageName = buildPackageName(propertiesFile, baseDir);
return packageName + "." + fileName.substring(0, fileName.indexOf('.'));
}
/**
* Builds the enum type name depending on the target file (e.g. "Enum.java" becomes "Enum").
*
* @param targetFile
* the enum target file
* @return the enum type name
*/
static String buildEnumTypeName(final File targetFile) {
String fileName = targetFile.getName();
return fileName.substring(0, fileName.lastIndexOf('.'));
}
/**
* Builds a javadoc with the given description and indentation.
*
* @param description
* the javadoc description
* @param indent
* a bunch of spaces, used to indent (e.g. two spaces " ");
* @param lineLength
* the maximum line length
* @return the builded javadoc string
*/
static String buildJavadoc(final String description, final String indent, final int lineLength) {
String javaDocPrefix = String.format("%s * ", indent);
StringBuilder builder = new StringBuilder();
builder.append(indent);
builder.append("/**");
for (String string : wordWrap(description, lineLength - javaDocPrefix.length())) {
builder.append('\n');
builder.append(javaDocPrefix);
builder.append(string);
}
builder.append('\n');
builder.append(indent);
builder.append(" */\n");
return builder.toString();
}
/**
* Builds the package name based on the properties file path, starting from {@link #baseDir}.
*
* @param propertiesFile
* the properties file
* @param baseDir
* the base directory path to cut off
* @return e.g. "com.example" if baseDir is "src/main/resources" and propertiesFile
* "src/main/resources/com/example/File.properties"
*/
static String buildPackageName(final File propertiesFile, final File baseDir) {
// substring(1) because there would be a leading dot
String parentDirPath = propertiesFile.getAbsoluteFile().getParent();
String relativePath = parentDirPath.replace(baseDir.getAbsolutePath(), "");
if (relativePath.length() > 1) {
return relativePath.replace(File.separatorChar, '.').substring(1);
}
return "";
}
/**
* Builds the target file using generateDirectory, packageName and the source properties file's name.
*
* @param propertiesFile
* the properties file name
* @param packageName
* the target file's package name
* @param targetDirectory
* the directory where the files will be generated in
* @return e.g. "target/generated-source/enum/com/example/Enum.java"
*/
static File buildTargetFile(final File propertiesFile, final String packageName, final String targetDirectory) {
String propertyFileName = propertiesFile.getName();
char[] charArray = propertyFileName.substring(0, propertyFileName.lastIndexOf('.')).toCharArray();
charArray[0] = Character.toUpperCase(charArray[0]);
String packageDirectory = packageName.replace('.', File.separatorChar);
return new File(targetDirectory + File.separator + packageDirectory + File.separator + new String(charArray)
+ ".java");
}
/**
* Create a directory and all its parent directories.
*
* @param directory
* the directory to create
* @throws IOException
* if a directory could not be created
*/
static void createDirectories(final File directory) throws IOException {
if (!directory.exists() && !directory.mkdirs()) {
throw new IOException("Could not create directory: " + directory.getAbsolutePath());
}
}
/**
* Word wrapping. Fails if a string is longer than length characters (I guess this string won't be
* returned then).
*
* @param string
* the string to wrap
* @param length
* the maximum line length
* @return wrapped lines
*/
static List wordWrap(final String string, final int length) {
Pattern pattern = Pattern.compile("(.{1," + length + "})(?:[\\s]|$)|([\\S]{" + length + ",})");
Matcher m = pattern.matcher(string);
List list = new LinkedList();
while (m.find()) {
String group1 = m.group(1);
String group2 = m.group(2);
if (group1 != null) {
list.add(group1);
} else {
list.add(group2);
}
}
return list;
}
/**
* The pattern a generated enum field name must match to be valid.
*
* @parameter default-value="^[A-Z][A-Z0-9]*[A-Z0-9_]*$"
*/
private String enumFieldPattern;
/**
* Fully qualified name of an interface to implement. This allows to make multiple generated enum types an
* implementation of the same interface.
*
* @parameter
*/
private String implement;
/**
* List of files to process. Relative to baseDir. The path will be used as package name, if
* packageName is not set.
*
* @parameter
*/
private List files;
/**
* Base directory for poperties files.
*
* @parameter default-value="${basedir}/src/main/resources"
*/
private String baseDir;
/**
* The directory to create the files in.
*
* @parameter default-value="${basedir}/target/generated-sources/enum"
*/
private String generateDirectory;
/**
* The maximum line length to use when creating the source file.
*
* @parameter default-value="80"
*/
private Integer lineLength;
/**
* Name of the target package. If not given, the package name will be same as the property's path, relative to
* baseDir.
*
* @parameter
*/
private String packageName;
/**
* String format for enum field's javadoc. Two strings are given: the first one is the property key, the second one
* the property value.
*
* @parameter default-value="Key "%1$s" for property with value "%2$s"."
*/
private String enumJavadoc;
/**
* Character encoding of the generated java file.
*
* @parameter default-value="UTF-8"
*/
private String targetEncoding;
/**
* Reference to the maven project.
*
* @parameter expression="${project}"
* @required
* @readonly
*/
private MavenProject project;
/**
* A map of enum field names that have already been declared. Key is the value the enum field name, value the property
* key.
*/
private final Map generatedEnumFieldNames;
/**
* The prefix of each key. This is the value that will be skipped when generating the enum field name.
*
* @parameter default-value=""
*/
private String prefix;
/**
* Constructs a new {@link EnumGeneratorMojo}.
*/
public EnumGeneratorMojo() {
generatedEnumFieldNames = new HashMap();
}
/**
* Builds an enumeration field's name, based on the property key. Converts camelCase to CAMEL_CASE and package.names
* to PACKAGE_NAMES. Note that if the key starts with {@link #prefix}, this prefix will be skipped when building the
* enum field name.
*
* @param propertyKey
* the property's key
* @return the enum field name
* @throws InvalidPropertyKeyException
* if the property key is invalid, so that the generated enum field name does not match the pattern
* {@link #enumFieldPattern}
*/
String buildEnumFieldName(final String propertyKey) throws InvalidPropertyKeyException {
String fieldName = propertyKey;
if (propertyKey.startsWith(prefix)) {
fieldName = propertyKey.substring(prefix.length());
}
fieldName = fieldName.replaceAll("([a-z])([A-Z])", "$1_$2").toUpperCase();
fieldName = fieldName.replaceAll("([A-Z])[\\.\\s-]([A-Z])", "$1_$2");
if (!fieldName.matches(enumFieldPattern)) {
throw new InvalidPropertyKeyException("The key \"" + propertyKey
+ "\" is invalid. The resulting enum must match the pattern " + enumFieldPattern);
}
return fieldName;
}
/**
* Generates an enum based on properties file.
*
* @throws MojoExecutionException
* if an exception occurred
* @throws MojoFailureException
* of the mojo failed
*/
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
prepare();
getLog().debug("baseDir: " + baseDir);
getLog().debug("generateDirectory: " + generateDirectory);
// Normalize directories
baseDir = new File(baseDir).getAbsolutePath();
generateDirectory = new File(generateDirectory).getAbsolutePath();
try {
for (String fileName : files) {
File sourceFile = new File(baseDir, fileName);
if (!sourceFile.exists()) {
throw new FileNotFoundException("The file " + sourceFile.getAbsolutePath() + " could not be found");
}
generateEnumFile(sourceFile);
}
} catch (IOException e) {
getLog().error(e);
throw new MojoExecutionException(e.getMessage(), e);
} catch (InvalidPropertyKeyException e) {
getLog().error(e);
throw new MojoFailureException(e.getMessage(), e);
}
project.addCompileSourceRoot(generateDirectory);
}
/**
* Generates an enum file based on a properties file.
*
* @param propertiesFile
* the properties file read
* @throws IOException
* if an I/O error occurred
* @throws InvalidPropertyKeyException
* if a property key is invalid, so that the generated enum field name does not match the pattern
* {@link #enumFieldPattern}
*/
void generateEnumFile(final File propertiesFile) throws IOException, InvalidPropertyKeyException {
if (packageName == null) {
packageName = buildPackageName(propertiesFile, new File(baseDir));
}
if (!Charset.isSupported(targetEncoding)) {
throw new UnsupportedEncodingException("The target charset " + targetEncoding + " is not supported");
}
File targetFile = buildTargetFile(propertiesFile, packageName, generateDirectory);
// Create package directory
createDirectories(targetFile.getParentFile());
/*
* I don't yet understand why targetEncoding is also needed for input stream (and not ISO-8859-1), but that was the
* only way that worked.
*/
Reader reader = new BufferedReader(new InputStreamReader(new FileInputStream(propertiesFile), targetEncoding));
Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(targetFile), targetEncoding));
try {
Properties properties = new Properties();
properties.load(reader);
writePackageDeclaration(writer, packageName);
writeEnumTypeJavadoc(writer, propertiesFile);
writeEnumTypeSignature(writer, buildEnumTypeName(targetFile));
Iterator> iterator = properties.entrySet().iterator();
while (iterator.hasNext()) {
Entry