Completed basic templating implementation based on FreeMarker. The CodeGenerator now generates simple Java code files to represent the objects output by the parse_ec2.pl script.

git-svn-id: http://jclouds.googlecode.com/svn/trunk@861 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
jamurty 2009-05-27 05:11:34 +00:00
parent ac503f451e
commit b43e65dc5b
13 changed files with 649 additions and 24 deletions

View File

@ -0,0 +1,53 @@
[#ftl]
package ${bean.packageName};
[#if bean.packageName != rootPackageName]
import ${rootPackageName}.*;
[/#if]
/**
*
[#list bean.see as see]
[#if see?contains(".html")]
* @see <a href='${see}' />
[#else]
* @see ${see}
[/#if]
[/#list]
* @author Generated
*/
public class ${shortClassName} {
[#-- Print fields --]
[#list bean.parameters![] as field]
/**
*
* ${field.desc}
* /
private ${field.javaType} ${field.name?uncap_first};
[/#list]
[#-- Print get/set --]
[#list bean.parameters![] as field]
[#assign lowerName = field.name?uncap_first]
[#assign upperName = field.name?cap_first]
/**
*
* @return ${field.desc}
* /
public ${field.javaType} get${upperName}(){
return this.${lowerName};
}
/**
*
* @param ${lowerName}
* ${field.desc}
* /
public void set${upperName}(${field.javaType} ${lowerName}) {
this.${lowerName} = ${lowerName};
}
[/#list]
}

View File

@ -0,0 +1,50 @@
[#ftl]
package ${bean.packageName};
import ${rootPackageName}.domain.*;
import ${rootPackageName}.response.*;
[#if bean.options??]
import ${bean.options.packageName}.*;
[/#if]
import org.jclouds.http.commands.callables.xml.ParseSax;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
import org.jclouds.http.HttpFutureCommand;
/**
*
[#list bean.see as see]
[#if see?contains(".html")]
* @see <a href='${see}' />
[#else]
* @see ${see}
[/#if]
[/#list]
* @author Generated
*/
[#assign RT = bean.response.javaType]
public class ${shortClassName} extends HttpFutureCommand<${RT}> {
@Inject
public ${shortClassName}(@Named(AWSConstants.PROPERTY_AWS_ACCESSKEYID) String awsAccessKeyId,
@Named(AWSConstants.PROPERTY_AWS_SECRETACCESSKEY) String awsSecretAccessKey,
ParseSax<${RT}> callable,
[#if bean.options?? && bean.options.awsType??]
@Assisted ${bean.options.awsType} options,
[#else]
@Assisted BaseEC2RequestOptions<EC2RequestOptions> options,
[/#if]
[#list bean.parameters![] as param]
@Assisted ${param.javaType} ${param.name?uncap_first}[#rt]
[#if param_has_next],[#else])[/#if]
[/#list]
{
super("GET",
"/" + options.buildQueryString()
[#list bean.parameters![] as param]
.with${param.name?cap_first}(${param.name?uncap_first})
[/#list]
.signWith(awsAccessKeyId,awsSecretAccessKey),
callable);
}

View File

@ -82,6 +82,11 @@
<version>1.3</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.14</version>
</dependency>
</dependencies>
</project>

View File

@ -0,0 +1,47 @@
/**
*
* Copyright (C) 2009 James Murty <jamurty@gmail.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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,
* software distributed 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 and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.codegen.model;
/**
*
* @author James Murty
*/
public abstract class BaseBean {
private String className;
private String packageName;
private String awsType;
public String getClassName() {
return className;
}
public String getPackageName() {
return packageName;
}
public String getAwsType() {
return awsType;
}
}

View File

@ -1,13 +1,59 @@
/**
*
* Copyright (C) 2009 James Murty <jamurty@gmail.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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,
* software distributed 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 and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.codegen.model;
import java.util.List;
public class Command {
private String className;
private String packageName;
private String awsType;
/**
*
* @author James Murty
*/
public class Command extends BaseBean {
private List<Parameter> parameters;
private Options options;
private Handler handler;
private Response response;
private List<String> see;
public List<Parameter> getParameters() {
return parameters;
}
public Options getOptions() {
return options;
}
public Handler getHandler() {
return handler;
}
public Response getResponse() {
return response;
}
public List<String> getSee() {
return see;
}
}

View File

@ -1,11 +1,44 @@
/**
*
* Copyright (C) 2009 James Murty <jamurty@gmail.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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,
* software distributed 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 and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.codegen.model;
import java.util.List;
public class Handler {
private String className;
/**
*
* @author James Murty
*/
public class Handler extends BaseBean {
private String example;
private String awsType;
private String packageName;
private List<String> see;
public String getExample() {
return example;
}
public List<String> getSee() {
return see;
}
}

View File

@ -1,7 +1,34 @@
/**
*
* Copyright (C) 2009 James Murty <jamurty@gmail.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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,
* software distributed 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 and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.codegen.model;
import java.util.List;
/**
*
* @author James Murty
*/
public class Model {
private List<Package> packages;
@ -9,4 +36,8 @@ public class Model {
public String toString() {
return packages.toString();
}
public List<Package> getPackages() {
return packages;
}
}

View File

@ -0,0 +1,48 @@
/**
*
* Copyright (C) 2009 James Murty <jamurty@gmail.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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,
* software distributed 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 and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.codegen.model;
import java.util.List;
/**
*
* @author James Murty
*/
public class Options extends BaseBean {
private List<Parameter> parameters;
private String example;
private List<String> see;
public List<Parameter> getParameters() {
return parameters;
}
public String getExample() {
return example;
}
public List<String> getSee() {
return see;
}
}

View File

@ -1,7 +1,34 @@
/**
*
* Copyright (C) 2009 James Murty <jamurty@gmail.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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,
* software distributed 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 and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.codegen.model;
import java.util.List;
/**
*
* @author James Murty
*/
public class Package {
private String name;
private List<Command> commands;
@ -10,4 +37,13 @@ public class Package {
public String toString() {
return String.format("{'name':'%1$s', 'commands':%2$s", name, commands);
}
public String getName() {
return name;
}
public List<Command> getCommands() {
return commands;
}
}

View File

@ -1,9 +1,57 @@
/**
*
* Copyright (C) 2009 James Murty <jamurty@gmail.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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,
* software distributed 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 and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.codegen.model;
/**
*
* @author James Murty
*/
public class Parameter {
private String name;
private String type;
private String javaType;
private String param;
private String desc;
public String getName() {
return name;
}
public String getType() {
return type;
}
public String getJavaType() {
return javaType;
}
public String getParam() {
return param;
}
public String getDesc() {
return desc;
}
}

View File

@ -1,12 +1,49 @@
/**
*
* Copyright (C) 2009 James Murty <jamurty@gmail.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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,
* software distributed 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 and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.codegen.model;
import java.util.List;
public class Response {
private String className;
/**
*
* @author James Murty
*/
public class Response extends BaseBean {
private List<ResponseField> fields;
private String awsType;
private String javaType;
private String packageName;
private List<String> see;
private List<String> see;
public List<ResponseField> getFields() {
return fields;
}
public String getJavaType() {
return javaType;
}
public List<String> getSee() {
return see;
}
}

View File

@ -1,8 +1,52 @@
/**
*
* Copyright (C) 2009 James Murty <jamurty@gmail.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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,
* software distributed 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 and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.codegen.model;
/**
*
* @author James Murty
*/
public class ResponseField {
private String desc;
private String name;
private String type;
private String javaType;
public String getDesc() {
return desc;
}
public String getName() {
return name;
}
public String getType() {
return type;
}
public String getJavaType() {
return javaType;
}
}

View File

@ -1,25 +1,93 @@
/**
*
* Copyright (C) 2009 James Murty <jamurty@gmail.com>
*
* ====================================================================
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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,
* software distributed 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 and limitations
* under the License.
* ====================================================================
*/
package org.jclouds.aws.codegen.util;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Writer;
import java.util.HashMap;
import java.util.Map;
import org.jclouds.aws.codegen.model.BaseBean;
import org.jclouds.aws.codegen.model.Command;
import org.jclouds.aws.codegen.model.Model;
import org.jclouds.aws.codegen.model.Package;
import com.google.common.annotations.VisibleForTesting;
import com.google.gson.Gson;
import com.google.gson.JsonParseException;
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
/**
* TODO: Finish this class and document it.
*
* 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>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>
*
* @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);
}
/**
* Parses a JSON object model file (as generated by
* <tt>aws/src/main/bin/parse_ec2.pl</tt>) and converts
* 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
@ -34,22 +102,101 @@ public class CodeGenerator {
return gson.fromJson(new FileReader(objectModelFile), Model.class);
}
public void generateCode(File objectModelFile, String rootPackageName)
throws JsonParseException, FileNotFoundException
/**
* 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
*/
@VisibleForTesting
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 != 2) {
System.out.println("Usage: CodeGenerator objectModelFile rootPackage");
System.out.println(" E.g: CodeGenerator ec2.json org.jclouds.aws.ec2");
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();
codeGenerator.generateCode(new File(args[0]), args[1]);
CodeGenerator codeGenerator = new CodeGenerator(
args[1], new File(args[2]), new File(args[3]));
codeGenerator.generateCode(new File(args[0]));
}
}