Skip to content

Instantly share code, notes, and snippets.

@pfmiles
Last active August 29, 2015 13:59
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save pfmiles/10805682 to your computer and use it in GitHub Desktop.
Save pfmiles/10805682 to your computer and use it in GitHub Desktop.
用于代码生成的velocity封装
package xxx;
import xxx.RecParsing;
/**
* 实现一些业务方法,方便模板渲染时调用
*
* @author pf-miles 2014-4-15 下午2:42:49
*/
public class BizUtil {
/**
* 支持带调用栈(即每层递归调用的context彼此隔离)的parse, 当需要在递归parse过程中保持调用栈时可用于代替velocity中原本的#parse directive
*/
public static RecParsing recParsing(String tempPath) {
return new RecParsing(tempPath);
}
}
package xxx;
import java.util.Map;
import org.eclipse.jdt.core.JavaCore;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.formatter.CodeFormatter;
import org.eclipse.jdt.core.formatter.DefaultCodeFormatterConstants;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.text.edits.TextEdit;
import xxx.JavaSourceFile;
/**
* 调用eclipse jdt core对生成的java源码进行格式化
*
* @author pf-miles 2014-4-16 下午2:48:29
*/
public class JavaCodeFormattingUtil {
/**
* 尝试对传入的JavaSourceFile格式化,此操作若成功则将改变传入对象的内容
*/
@SuppressWarnings({ "rawtypes", "unchecked" })
public static void tryFormat(JavaSourceFile src) {
Map m = DefaultCodeFormatterConstants.getEclipseDefaultSettings();
m.put(JavaCore.COMPILER_COMPLIANCE, JavaCore.VERSION_1_6);
m.put(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, JavaCore.VERSION_1_6);
m.put(JavaCore.COMPILER_SOURCE, JavaCore.VERSION_1_6);
m.put(DefaultCodeFormatterConstants.FORMATTER_LINE_SPLIT, "160");
m.put(DefaultCodeFormatterConstants.FORMATTER_TAB_CHAR, JavaCore.SPACE);
String code = null;
IDocument doc = null;
try {
code = src.getCharContent(true).toString();
CodeFormatter codeFormatter = ToolFactory.createCodeFormatter(m);
TextEdit textEdit = codeFormatter.format(CodeFormatter.K_UNKNOWN, code, 0, code.length(), 0, null);
if (textEdit != null) {
doc = new Document(code);
textEdit.apply(doc);
src.setCode(doc.get());
}
} catch (Exception e) {
throw new RuntimeException("Error occured while formatting code: " + src.toUri(), e);
}
}
}
package xxx;
import java.util.HashMap;
import java.util.Map;
import xxx.TemplateRenderUtil;
/**
* 用于在velocity中执行带调用栈的递归渲染的辅助类,支持以“串接”形式添加参数
*
* @author pf-miles 2014-4-15 下午5:20:34
*/
public class RecParsing {
private Map<String, Object> ctx = new HashMap<String, Object>();
private String tempPath;
public RecParsing(String tempPath){
this.tempPath = tempPath;
}
public RecParsing addParam(String key, Object value) {
ctx.put(key, value);
return this;
}
public String toString() {
return TemplateRenderUtil.render(tempPath, ctx);
}
}
package xxx;
import java.beans.BeanInfo;
import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Properties;
import org.apache.commons.lang.ClassUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.VelocityEngine;
import org.apache.velocity.context.Context;
import org.apache.velocity.runtime.resource.loader.ClasspathResourceLoader;
import xxx.BizUtil;
/**
* 渲染模板util, 用于根据业务数据和模板文件,生成java源码
*
* @author pf-miles 2014-4-10 上午11:42:34
*/
public class TemplateRenderUtil {
private static final Properties props = new Properties();
private static final VelocityEngine tempEngine = new VelocityEngine();
static {
props.put(VelocityEngine.ENCODING_DEFAULT, "UTF-8");
props.put(VelocityEngine.INPUT_ENCODING, "UTF-8");
props.put(VelocityEngine.RESOURCE_LOADER, "classpath");
props.setProperty("classpath.resource.loader.class", ClasspathResourceLoader.class.getName());
props.put(VelocityEngine.SET_NULL_ALLOWED, "true");
try {
tempEngine.init(props);
} catch (Exception e) {
throw new RuntimeException(e);
}
}
/**
* 传入模板路径(classpath中的路径),以及任意pojo或map形式的context,返回merge好的String结果
*
* @param tempPath 模板路径, 以classpath根为起始
* @param ctxPojo 任意自定义pojo context,需提供符合javaBean规范的getter方法, 或map
* @return merge好的String结果
*/
public static <T> String render(String tempPath, T ctxPojo) {
Context ctx = new VelocityContext();
putAllPojoVals(ctxPojo, ctx);
StringWriter writer = new StringWriter();
try {
tempEngine.mergeTemplate(tempPath, "UTF-8", ctx, writer);
} catch (Exception e) {
throw new RuntimeException(e);
}
return writer.toString();
}
private static void putAllPojoVals(Object ctxPojo, Context ctx) {
ctx.put("StringUtils", StringUtils.class);
ctx.put("ClassUtils", ClassUtils.class);
ctx.put("BizUtil", BizUtil.class);
if (ctxPojo == null) return;
if (ctxPojo instanceof Map) {
for (Map.Entry<?, ?> e : ((Map<?, ?>) ctxPojo).entrySet()) {
ctx.put(e.getKey().toString(), e.getValue());
}
} else {
BeanInfo bi;
try {
bi = Introspector.getBeanInfo(ctxPojo.getClass());
for (PropertyDescriptor pd : bi.getPropertyDescriptors()) {
if ("class".equals(pd.getName())) continue;
Method rm = pd.getReadMethod();
if (rm != null) ctx.put(pd.getName(), rm.invoke(ctxPojo));
}
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}
}
@pfmiles
Copy link
Author

pfmiles commented Dec 25, 2014

“用于代码生成的模板引擎”已抽取为开源项目:min-velocity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment