org.rythmengine.internal.AutoToStringCodeBuilder Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of rythm-engine Show documentation
Show all versions of rythm-engine Show documentation
A strong typed high performance Java Template engine with .Net Razor like syntax
/**
* Copyright (C) 2013-2016 The Rythm Engine project
* for LICENSE and other details see:
* https://github.com/rythmengine/rythmengine
*/
package org.rythmengine.internal;
import org.rythmengine.RythmEngine;
import org.rythmengine.internal.compiler.TemplateClass;
import org.rythmengine.internal.dialect.AutoToString;
import org.rythmengine.internal.parser.toString.AppendEndToken;
import org.rythmengine.internal.parser.toString.AppendFieldToken;
import org.rythmengine.internal.parser.toString.AppendStartToken;
import org.rythmengine.toString.ToStringOption;
import org.rythmengine.utils.S;
import org.rythmengine.utils.TextBuilder;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.*;
/**
* Created with IntelliJ IDEA.
* User: luog
* Date: 15/07/12
* Time: 8:21 AM
* To change this template use File | Settings | File Templates.
*/
public class AutoToStringCodeBuilder extends CodeBuilder {
public AutoToStringCodeBuilder(String template, String className, String tagName, TemplateClass templateClass, RythmEngine engine, IDialect dialect) {
super(template, className, tagName, templateClass, engine, dialect);
// skip annotations
skipAnnotations.addAll(Arrays.asList("org.codehaus.jackson.annotate.JsonIgnore org.rythmengine.toString.NoExpose ".split(" +")));
transientAnnotations.addAll(Arrays.asList("javax.persistence.Transient com.google.code.morphia.annotations.Transient".split(" +")));
if (dialect instanceof AutoToString) {
meta = ((AutoToString) dialect).meta;
} else {
throw new IllegalArgumentException("AutoToString expected, found: " + dialect.getClass());
}
}
@Override
protected String extended() {
return ToStringTemplateBase.class.getName();
}
@Override
protected void pSetup() {
ptn("protected void __setup() {");
if (logTime) {
p2tn("__logTime = true;");
}
p2t("__style = ").p(meta.style.toCode()).p(";").pn();
for (Map.Entry entry : renderArgs.entrySet()) {
RenderArgDeclaration arg = entry.getValue();
p2t("if (").p(entry.getKey()).p(" == null) {");
p(entry.getKey()).p("=(").p(arg.objectType()).p(")__get(\"").p(entry.getKey()).p("\");}\n");
}
ptn("}");
}
@Override
public TextBuilder build() {
parse();
pImports();
pClassOpen();
pRenderArgs();
pSetup();
pBuild();
pClassClose();
return this;
}
private AutoToString.AutoToStringData meta = null;
//
private Map expressions = new HashMap();
private Set transients = new HashSet();
private Set skips = new HashSet();
private Set skipAnnotations = new HashSet();
private Set transientAnnotations = new HashSet();
private boolean shouldSkip(Annotation[] aa) {
for (Annotation a : aa) {
String an = a.annotationType().getName();
if (skipAnnotations.contains(an)) return true;
if (transientAnnotations.contains(an) && !meta.option.appendTransient) return true;
}
return false;
}
private boolean shouldSkip(Field f) {
String fn = f.getName();
Annotation[] aa = f.getAnnotations();
if (shouldSkip(aa)) {
skips.add(fn);
return true;
}
int mod = f.getModifiers();
ToStringOption op = meta.option;
if (!op.appendTransient && Modifier.isTransient(mod) || !op.appendStatic && Modifier.isStatic(mod)) {
skips.add(fn);
return true;
}
return !Modifier.isPublic(mod);
}
private boolean shouldSkip(Method m, String fn) {
Annotation[] aa = m.getAnnotations();
if (shouldSkip(aa)) {
skips.add(fn);
return true;
}
int mod = m.getModifiers();
ToStringOption op = meta.option;
if (!op.appendTransient && Modifier.isTransient(mod) || !op.appendStatic && Modifier.isStatic(mod)) {
skips.add(fn);
return true;
}
if (!Modifier.isPublic(mod)) return true;
return false;
}
private List tokenList = new ArrayList();
private void appendFieldsIn(Class> c) {
Field[] fa = c.getDeclaredFields();
for (Field f : fa) {
String fn = f.getName();
if (!tokenList.contains(fn)) tokenList.add(fn);
if (shouldSkip(f)) {
continue;
}
expressions.put(fn, fn);
}
}
private void appendMethodsIn(Class> c) {
Method[] ma = c.getDeclaredMethods();
for (Method m : ma) {
String mn = m.getName();
if ("getClass".equals(mn)) continue;
String fn = null;
if (mn.startsWith("get")) {
fn = mn.replaceFirst("get", "");
} else if (mn.startsWith("is")) {
fn = mn.replaceFirst("is", "");
}
if (S.isEmpty(fn)) continue;
fn = S.lowerFirst(fn);
if (shouldSkip(m, fn)) {
continue;
}
mn = mn + "()";
if (!tokenList.contains(fn)) tokenList.add(fn);
expressions.put(fn, mn);
}
}
private void appendIn(Class> c) {
if (engine().conf().playFramework()) {
appendMethodsIn(c);
appendFieldsIn(c);
} else {
appendFieldsIn(c);
appendMethodsIn(c);
}
}
private void parse() {
Class> c = meta.clazz;
ToStringOption o = meta.option;
addBuilder(new AppendStartToken(this));
this.appendIn(c);
while (c.getSuperclass() != null && c != o.upToClass) {
c = c.getSuperclass();
this.appendIn(c);
}
for (String fn : skips) expressions.remove(fn);
for (String fn : tokenList) {
if (!expressions.containsKey(fn)) continue;
String exp = expressions.get(fn);
addBuilder(new AppendFieldToken(fn, exp, this));
}
addBuilder(new AppendEndToken(this));
this.addRenderArgs(-1, meta.clazz.getName().replace('$', '.'), "_");
}
}