Issue 36: changed to use classpath to load templates

git-svn-id: http://jclouds.googlecode.com/svn/trunk@870 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2009-05-29 10:10:17 +00:00
parent e102d1e64f
commit 60018ae8c8
1 changed files with 126 additions and 141 deletions

View File

@ -45,156 +45,141 @@ import freemarker.template.Template;
import freemarker.template.TemplateException;
/**
* Converts object models representing AWS API beans into Java
* classes.
* Converts object models representing AWS API beans into Java classes.
* <p>
* This implementation is designed to perform the following steps:
* <ul>
* <li>Parse the JSON object representation produced by the <tt>parse_ec2.pl</tt>
* perl script</li>
* <li>Parse the JSON object representation produced by the <tt>parse_ec2.pl</tt> perl script</li>
* <li>Convert the JSON into Java object models (@see org.jclouds.aws.codegen.models)</li>
* <li>Iterate through the Command objects generated above and with each one:
* <ul>
* <li>Load the <a href="http://freemarker.org/">FreeMarker</a>template file for the given
* object</li>
* <li>Create a package directory to receive the Java file, if necessary</li>
* <li>Process the object through the template, producing a Java implementation of the object</li>
* <ul>
* </li>
* <ul>
* <li>Load the <a href="http://freemarker.org/">FreeMarker</a>template file for the given object</li>
* <li>Create a package directory to receive the Java file, if necessary</li>
* <li>Process the object through the template, producing a Java implementation of the object</li>
* <ul></li>
*
* @author James Murty
*/
public class CodeGenerator {
public final static String COMMAND_TEMPLATE_FILENAME = "Command.ftl";
public final static String BEAN_TEMPLATE_FILENAME = "Bean.ftl";
private final File templateDirectory;
private final File targetDirectory;
private final String rootPackageName;
private final Configuration config;
public CodeGenerator(String rootPackageName, File templateDirectory, File targetDirectory)
throws IOException
{
this.rootPackageName = rootPackageName;
this.templateDirectory = templateDirectory;
this.targetDirectory = targetDirectory;
config = new Configuration();
config.setDirectoryForTemplateLoading(this.templateDirectory);
}
/**
* Parse a JSON object model file (as generated by
* <tt>aws/src/main/bin/parse_ec2.pl</tt>) and convert
* it into a Java object graph.
*
* @param objectModelFile
* @return
* @throws JsonParseException
* @throws FileNotFoundException
*/
public Model parseModelFromJSON(File objectModelFile)
throws JsonParseException, FileNotFoundException
{
Gson gson = new Gson();
return gson.fromJson(new FileReader(objectModelFile), Model.class);
}
/**
* Parse a JSON object model file and iterate over the resulting
* objects generating Java code files.
*
* @param objectModelFile
* @throws JsonParseException
* @throws IOException
* @throws TemplateException
*/
public void generateCode(File objectModelFile)
throws JsonParseException, IOException, TemplateException
{
Model model = parseModelFromJSON(objectModelFile);
for (Package pkg: model.getPackages()) {
for (Command command: pkg.getCommands()) {
generateClassFile(command, COMMAND_TEMPLATE_FILENAME);
if (command.getHandler() != null) {
generateClassFile(command.getHandler(), BEAN_TEMPLATE_FILENAME);
}
if (command.getOptions() != null) {
generateClassFile(command.getOptions(), BEAN_TEMPLATE_FILENAME);
}
if (command.getResponse() != null) {
generateClassFile(command.getResponse(), BEAN_TEMPLATE_FILENAME);
}
}
}
}
/**
* Generate a Java code file for the given object model bean, using the
* given template name as the basis for the Java class.
*
* @param bean
* @param templateFileName
* @throws IOException
* @throws TemplateException
*/
public void generateClassFile(BaseBean bean, String templateFileName)
throws IOException, TemplateException
{
String shortClassName = bean.getClassName().substring(
bean.getClassName().lastIndexOf('.') + 1);
Map<String, Object> objectMap = new HashMap<String, Object>();
objectMap.put("bean", bean);
objectMap.put("rootPackageName", this.rootPackageName);
objectMap.put("shortClassName", shortClassName);
public final static String COMMAND_TEMPLATE_FILENAME = "Command.ftl";
public final static String BEAN_TEMPLATE_FILENAME = "Bean.ftl";
File packageDir = new File(
this.targetDirectory, bean.getPackageName().replace('.', '/'));
if (packageDir.exists() || packageDir.mkdirs()) {
File javaFile = new File(packageDir, shortClassName + ".java");
FileWriter fw = new FileWriter(javaFile);
System.out.println("Generated " + javaFile);
applyTemplate(templateFileName, objectMap, fw);
} else {
throw new IllegalStateException(
"Unable to create target package directory: " + packageDir);
}
}
/**
* Apply the given template to the given object, and output the results into the given writer.
*
* @param templateFileName
* @param objectMap
* @param writer
* @throws IOException
* @throws TemplateException
*/
public void applyTemplate(String templateFileName, Map<String, Object> objectMap, Writer writer)
throws IOException, TemplateException
{
Template template = this.config.getTemplate(templateFileName, "UTF-8");
template.process(objectMap, writer);
}
private final File targetDirectory;
private final String rootPackageName;
private final Configuration config;
public CodeGenerator(String rootPackageName, File targetDirectory) throws IOException {
this.rootPackageName = rootPackageName;
this.targetDirectory = targetDirectory;
config = new Configuration();
config.setClassForTemplateLoading(this.getClass(), "/templates");
}
/**
* Parse a JSON object model file (as generated by <tt>aws/src/main/bin/parse_ec2.pl</tt>) and
* convert it into a Java object graph.
*
* @param objectModelFile
* @return
* @throws JsonParseException
* @throws FileNotFoundException
*/
public Model parseModelFromJSON(File objectModelFile) throws JsonParseException,
FileNotFoundException {
Gson gson = new Gson();
return gson.fromJson(new FileReader(objectModelFile), Model.class);
}
/**
* Parse a JSON object model file and iterate over the resulting objects generating Java code
* files.
*
* @param objectModelFile
* @throws JsonParseException
* @throws IOException
* @throws TemplateException
*/
public void generateCode(File objectModelFile) throws JsonParseException, IOException,
TemplateException {
Model model = parseModelFromJSON(objectModelFile);
for (Package pkg : model.getPackages()) {
for (Command command : pkg.getCommands()) {
generateClassFile(command, COMMAND_TEMPLATE_FILENAME);
if (command.getHandler() != null) {
generateClassFile(command.getHandler(), BEAN_TEMPLATE_FILENAME);
}
if (command.getOptions() != null) {
generateClassFile(command.getOptions(), BEAN_TEMPLATE_FILENAME);
}
if (command.getResponse() != null) {
generateClassFile(command.getResponse(), BEAN_TEMPLATE_FILENAME);
}
}
}
}
/**
* Generate a Java code file for the given object model bean, using the given template name as
* the basis for the Java class.
*
* @param bean
* @param templateFileName
* @throws IOException
* @throws TemplateException
*/
public void generateClassFile(BaseBean bean, String templateFileName) throws IOException,
TemplateException {
String shortClassName = bean.getClassName().substring(
bean.getClassName().lastIndexOf('.') + 1);
Map<String, Object> objectMap = new HashMap<String, Object>();
objectMap.put("bean", bean);
objectMap.put("rootPackageName", this.rootPackageName);
objectMap.put("shortClassName", shortClassName);
File packageDir = new File(this.targetDirectory, bean.getPackageName().replace('.', '/'));
if (packageDir.exists() || packageDir.mkdirs()) {
File javaFile = new File(packageDir, shortClassName + ".java");
FileWriter fw = new FileWriter(javaFile);
System.out.println("Generated " + javaFile);
applyTemplate(templateFileName, objectMap, fw);
} else {
throw new IllegalStateException("Unable to create target package directory: " + packageDir);
}
}
/**
* Apply the given template to the given object, and output the results into the given writer.
*
* @param templateFileName
* @param objectMap
* @param writer
* @throws IOException
* @throws TemplateException
*/
public void applyTemplate(String templateFileName, Map<String, Object> objectMap, Writer writer)
throws IOException, TemplateException {
Template template = this.config.getTemplate(templateFileName, "UTF-8");
template.process(objectMap, writer);
}
public static void main(String[] args) throws Exception {
if (args.length != 3) {
System.out.println("Usage: CodeGenerator objectModelFile rootPackage targetDir");
System.out.println(" E.g: CodeGenerator ec2.json org.jclouds.aws.ec2 aws/ec2/api/src");
System.exit(1);
}
File objectModelFile = new File(args[0]);
String rootPackage = args[1];
File targetDir = new File(args[2]);
new CodeGenerator(rootPackage, targetDir).generateCode(objectModelFile);
}
public static void main(String[] args) throws Exception {
if (args.length != 4) {
System.out.println(
"Usage: CodeGenerator objectModelFile rootPackage templatesDir targetDir");
System.out.println(
" E.g: CodeGenerator ec2.json org.jclouds.aws.ec2 aws/codegen/templates aws/ec2/api/src");
System.exit(1);
}
CodeGenerator codeGenerator = new CodeGenerator(
args[1], new File(args[2]), new File(args[3]));
codeGenerator.generateCode(new File(args[0]));
}
}