com.legstar.codegen.CodeGenUtil Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of legstar-codegen Show documentation
Show all versions of legstar-codegen Show documentation
Common code generation classes for LegStar
The newest version!
/*******************************************************************************
* Copyright (c) 2015 LegSem.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Lesser Public License v2.1
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/old-licenses/gpl-2.0.html
*
* Contributors:
* LegSem - initial API and implementation
******************************************************************************/
package com.legstar.codegen;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStreamWriter;
import java.io.StringWriter;
import java.io.Writer;
import java.net.InetAddress;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.UnknownHostException;
import java.nio.charset.Charset;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Map;
import java.util.Random;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;
import org.apache.velocity.exception.MethodInvocationException;
import org.apache.velocity.exception.ParseErrorException;
import org.apache.velocity.exception.ResourceNotFoundException;
/**
* Various utility methods which are mostly useful for code generation using
* velocity templates.
*/
public final class CodeGenUtil {
/** Generated code has reference to generation date following this format. */
public static final String DATE_FORMAT_NOW = "yyyy-MM-dd HH:mm:ss";
/** Used to generate random serial version IDs. */
private static Random mRandom = new Random();
/** Suffix used for JAXB type variable names. */
public static final String JAXB_TYPE_SUFFIX = "Type";
/** Get the platform specific line separator. */
public static final String CRLF = System.getProperty("line.separator");
/** Logger. */
private static final Log LOG = LogFactory.getLog(CodeGenUtil.class);
/**
* Defeats instantiation. Utility class.
*/
private CodeGenUtil() {
}
/**
* Check that a directory is valid.
*
* @param dir the directory name to check
* @param create true if directory should be created when not found
* @param errorDirName name to refer to if an error occurs
*/
public static void checkDirectory(final String dir, final boolean create,
final String errorDirName) {
try {
checkDirectory(dir, create);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(errorDirName + ": "
+ e.getMessage());
}
}
/**
* Check that a directory is valid.
*
* @param fdir the directory name to check
* @param create true if directory should be created when not found
* @param errorDirName name to refer to if an error occurs
*/
public static void checkDirectory(final File fdir, final boolean create,
final String errorDirName) {
try {
checkDirectory(fdir, create);
} catch (IllegalArgumentException e) {
throw new IllegalArgumentException(errorDirName + ": "
+ e.getMessage());
}
}
/**
* Check that a directory is valid.
*
* @param dir the directory name to check
* @param create true if directory should be created when not found
*/
public static void checkDirectory(final String dir, final boolean create) {
if (dir == null || dir.length() == 0) {
throw (new IllegalArgumentException(
"No directory name was specified"));
}
checkDirectory(new File(dir), create);
}
/**
* Check that a directory is valid.
*
* @param fdir the directory to check
* @param create true if directory should be created when not found
*/
public static void checkDirectory(final File fdir, final boolean create) {
if (fdir == null) {
throw (new IllegalArgumentException(
"No directory name was specified"));
}
if (!fdir.exists()) {
if (!create) {
throw (new IllegalArgumentException(fdir.getName()
+ " does not exist"));
} else {
if (!fdir.mkdirs()) {
throw (new IllegalArgumentException(
"Could not create directory " + fdir.getName()));
} else {
return;
}
}
}
if (!fdir.isDirectory()) {
throw (new IllegalArgumentException(fdir.getName()
+ " is not a directory"));
}
if (!fdir.canWrite()) {
throw (new IllegalArgumentException("Directory " + fdir.getName()
+ " is not writable"));
}
}
/**
* Retrieve a file. Given a directory name and a filename, this creates a
* File according to the following rules:
*
* - If the filename is absolute, the directory name is ignored
* - If the directory is not null, it is assumed to exist
* - If the directory is not null and the filename is not absolute, then
* filename is appended to directory
*
*
* @param dir parent directory
* @param filename absolute or relative file name
* @return a File
*/
public static File getFile(final String dir, final String filename) {
File file = new File(filename);
if (file.isAbsolute()) {
return file;
}
if (dir == null || dir.length() == 0) {
return new File(filename);
}
return new File(dir, filename);
}
/**
* Retrieve a file. Given a directory and a filename, this creates a File
* according to the following rules:
*
* - If the filename is absolute, the directory name is ignored
* - Otherwise, filename is appended to directory
*
*
* @param fdir parent directory
* @param filename absolute or relative file name
* @return a File
*/
public static File getFile(final File fdir, final String filename) {
File file = new File(filename);
if (file.isAbsolute()) {
return file;
}
return new File(fdir, filename);
}
/**
* @deprecated use com.legstar.coxb.util.Utils#toClassName instead. Create a
* valid Java class name from a given noun.
*
* @param noun the characters to turn into a java class name
* @return the Java class name
*/
public static String classNormalize(final String noun) {
String className = null;
if (noun != null && noun.length() > 0) {
className = noun.substring(0, 1).toUpperCase();
if (noun.length() > 1) {
className += noun.substring(1, noun.length());
}
}
return className;
}
/**
* Given a package name, this method returns the relative path location of
* the java files. A package like seg1.seg2.seg3 becomes /seg1/seg2/seg3/
*
* @param packageName the package name
* @return the relative location of java files
*/
public static String relativeLocation(final String packageName) {
if (packageName == null || packageName.length() == 0) {
return "";
}
String loc = packageName.replace('.', '/');
if (loc.charAt(0) != '/') {
loc = '/' + loc;
}
if (loc.charAt(loc.length() - 1) != '/') {
loc += '/';
}
return loc;
}
/**
* Given a root directory name and a package name, returns the location for
* class files. Optionally the location can be physically created.
*
* @param rootDirName the root directory name.
* @param packageName the package name or null if none
* @param create true if directory should be created when not found
* @return an existing location to store class files
*/
public static String classFilesLocation(final String rootDirName,
final String packageName, final boolean create) {
if (rootDirName == null || rootDirName.length() == 0) {
throw (new IllegalArgumentException(
"No root directory name was specified"));
}
String dir;
if (packageName != null && packageName.length() > 0) {
dir = rootDirName + '/' + CodeGenUtil.relativeLocation(packageName);
} else {
dir = rootDirName;
}
if (create) {
CodeGenUtil.checkDirectory(dir, true);
}
return dir;
}
/**
* Concatenates the path derived from a package name to a root directory.
*
* @param rootDir the root directory. Optionally the location can be
* physically created.
* @param packageName the package name
* @param create true if directory should be created when not found
* @return the file derived from concatenating the root directory with the
* package path.
*/
public static File classFilesLocation(final File rootDir,
final String packageName, final boolean create) {
File dir = rootDir;
if (packageName != null && packageName.length() > 0) {
dir = new File(rootDir, CodeGenUtil.relativeLocation(packageName));
}
if (create) {
CodeGenUtil.checkDirectory(dir, true);
}
return dir;
}
/**
* Setup Velocity so that it searches for templates in the classpath.
*
* In order to work around issue 158 that arises when velocity dynamically
* loaded classes are already in the context classloader parent, we
* temporarily switch to a new context classloader that sees our plugin
* classes and dependencies only.
*
* @throws CodeGenVelocityException if setup fails
*/
public static void initVelocity() throws CodeGenVelocityException {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
try {
Velocity.addProperty("resource.loader", "classpath");
Velocity.addProperty("classpath.resource.loader.description",
"Velocity Classpath Resource Loader");
Velocity.addProperty("classpath.resource.loader.class",
"org.apache.velocity.runtime.resource.loader."
+ "ClasspathResourceLoader");
Velocity.addProperty("classpath.resource.loader.cache", true);
Thread.currentThread().setContextClassLoader(
Velocity.class.getClassLoader());
Velocity.init();
} catch (Exception e) {
throw new CodeGenVelocityException(e);
} finally {
Thread.currentThread().setContextClassLoader(loader);
}
}
/**
* A simple context to use by generation templates.
*
* @param generatorName generator name
* @return a velocity context
*/
public static VelocityContext getContext(final String generatorName) {
VelocityContext context = new VelocityContext();
context.put("formattedDate", now());
context.put("generatorName", generatorName);
return context;
}
/**
* Apply a velocity template taken from a code generation make xml.
*
* @param generatorName the generator name
* @param templateName the velocity template to apply
* @param modelName the model name
* @param model the model providing data for velocity templates
* @param parameters additional parameters to pass to template
* @param targetFile the file to generate using default charset
* @throws CodeGenMakeException if processing fails
*/
public static void processTemplate(final String generatorName,
final String templateName, final String modelName,
final Object model, final Map < String, Object > parameters,
final File targetFile) throws CodeGenMakeException {
processTemplate(generatorName, templateName, modelName, model,
parameters, targetFile, null);
}
/**
* Apply a velocity template taken from a code generation make xml.
*
* @param generatorName the generator name
* @param templateName the velocity template to apply
* @param modelName the model name
* @param model the model providing data for velocity templates
* @param parameters additional parameters to pass to template
* @param targetFile the file to generate
* @param targetCharsetName the target character set. null is interpreted as
* the default encoding
* @throws CodeGenMakeException if processing fails
*/
public static void processTemplate(final String generatorName,
final String templateName, final String modelName,
final Object model, final Map < String, Object > parameters,
final File targetFile, final String targetCharsetName)
throws CodeGenMakeException {
if (LOG.isDebugEnabled()) {
LOG.debug("Processing template");
LOG.debug("Template name = " + templateName);
LOG.debug("Target file = " + targetFile);
LOG.debug("Target charset name = " + targetCharsetName);
if (parameters != null) {
for (String key : parameters.keySet()) {
Object value = parameters.get(key);
LOG.debug("Parameter " + key + " = " + value);
}
}
}
VelocityContext context = CodeGenUtil.getContext(generatorName);
context.put(modelName, model);
context.put("serialVersionID", Long.toString(mRandom.nextLong()) + 'L');
if (parameters != null) {
for (String key : parameters.keySet()) {
context.put(key, parameters.get(key));
}
}
StringWriter w = new StringWriter();
try {
Velocity.mergeTemplate(templateName, "UTF-8", context, w);
Writer out = null;
try {
FileOutputStream fos = new FileOutputStream(targetFile);
OutputStreamWriter osw;
if (targetCharsetName == null) {
osw = new OutputStreamWriter(fos);
} else {
osw = new OutputStreamWriter(fos, targetCharsetName);
}
out = new BufferedWriter(osw);
out.write(w.toString());
} catch (IOException e) {
throw new CodeGenMakeException(e);
} finally {
if (out != null) {
out.close();
}
}
} catch (ResourceNotFoundException e) {
throw new CodeGenMakeException(e);
} catch (ParseErrorException e) {
throw new CodeGenMakeException(e);
} catch (MethodInvocationException e) {
throw new CodeGenMakeException(e);
} catch (Exception e) {
throw new CodeGenMakeException(e);
}
}
/**
* Formats todays date and time.
*
* @return a formatted date
*/
public static String now() {
Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat(DATE_FORMAT_NOW);
return sdf.format(cal.getTime());
}
/**
* Checks that a URI is valid and HTTP scheme.
*
* @param httpUri the URI to check
* @throws CodeGenMakeException if URI has wrong syntax
*/
public static void checkHttpURI(final String httpUri)
throws CodeGenMakeException {
try {
if (httpUri == null || httpUri.length() == 0) {
throw new CodeGenMakeException("You must specify a valid URI");
}
URI uri = new URI(httpUri);
if (uri.getScheme() == null
|| uri.getScheme().compareToIgnoreCase("http") != 0) {
throw new CodeGenMakeException("URI " + uri
+ " must have http scheme");
}
} catch (URISyntaxException e) {
throw new CodeGenMakeException(e);
}
}
/**
* Checks that a character set is valid.
*
* @param charset the character set
* @see java.nio.charset.Charset
* @throws CodeGenMakeException if character set not supported
*/
public static void checkCharset(final String charset)
throws CodeGenMakeException {
if (charset == null || charset.length() == 0) {
throw new CodeGenMakeException(
"You must specify a valid character set");
}
if (!Charset.isSupported(charset)) {
throw new CodeGenMakeException("Character set " + charset
+ " is not supported");
}
}
/**
* Field names are derived from property names by lower casing the first
* character.
*
* @param propertyName the property name
* @return a valid field name or null if property name is empty
*/
public static String fieldNameFromPropertyName(final String propertyName) {
String fieldName = null;
if (propertyName != null && propertyName.length() > 0) {
fieldName = propertyName.substring(0, 1).toLowerCase();
if (propertyName.length() > 1) {
fieldName += propertyName.substring(1, propertyName.length());
}
}
return fieldName;
}
/**
* Property names are derived from field names by upper casing the first
* character.
*
* @param fieldName the field name
* @return a valid property name or null if field name is empty
*/
public static String propertyNameFromFieldName(final String fieldName) {
String propertyName = null;
if (fieldName != null && fieldName.length() > 0) {
propertyName = fieldName.substring(0, 1).toUpperCase();
if (fieldName.length() > 1) {
propertyName += fieldName.substring(1, fieldName.length());
}
}
return propertyName;
}
/**
* Property names are derived from jaxb type names by stripping the type
* suffix (if any).
*
* @param jaxbType the jaxb type name
* @return a valid property name or null if jaxb type name is empty
*/
public static String propertyNameFromJaxbType(final String jaxbType) {
String propertyName = null;
if (jaxbType != null && jaxbType.length() > 0) {
propertyName = jaxbType;
if (propertyName.endsWith(JAXB_TYPE_SUFFIX)) {
propertyName = propertyName.substring(0, propertyName.length()
- JAXB_TYPE_SUFFIX.length());
}
}
return propertyName;
}
/**
* Retrieve the IP address of the generation machine .
*
* @return the local machine IP address
*/
public static String getLocalIPAddress() {
try {
InetAddress addr = InetAddress.getLocalHost();
byte[] ipAddr = addr.getAddress();
String ipAddrStr = "";
for (int i = 0; i < ipAddr.length; i++) {
if (i > 0) {
ipAddrStr += ".";
}
ipAddrStr += ipAddr[i] & 0xFF;
}
return ipAddrStr;
} catch (UnknownHostException e) {
return "";
}
}
}
© 2015 - 2024 Weber Informatics LLC | Privacy Policy