diff --git a/pom.xml b/pom.xml new file mode 100644 index 000000000..47f2e10c3 --- /dev/null +++ b/pom.xml @@ -0,0 +1,51 @@ + + + + 4.0.0 + com.mysema.codegen + codegen + 0.1.0 + Codegen + Code generation and compilation for Java + + com.mysema.home + mysema-source + 0.2.0 + + jar + + 2010 + + + + net.sourceforge.collections + collections-generic + 4.01 + + + com.mysema.commons + mysema-commons-lang + 0.1.7 + + + commons-lang + commons-lang + 2.4 + + + + + junit + junit + 4.4 + test + + + javax.servlet + servlet-api + + + + + + diff --git a/src/main/java/com/mysema/codegen/CodeWriter.java b/src/main/java/com/mysema/codegen/CodeWriter.java new file mode 100644 index 000000000..2781f9aca --- /dev/null +++ b/src/main/java/com/mysema/codegen/CodeWriter.java @@ -0,0 +1,82 @@ +/* + * Copyright (c) 2010 Mysema Ltd. + * All rights reserved. + * + */ +package com.mysema.codegen; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.util.Collection; + +import org.apache.commons.collections15.Transformer; + +/** + * @author tiwe + * + */ +public interface CodeWriter extends Appendable{ + + CodeWriter annotation(Annotation annotation) throws IOException; + + CodeWriter annotation(Class annotation) throws IOException; + + CodeWriter beginClass(String simpleName) throws IOException; + + CodeWriter beginClass(String simpleName, String superClass, String... interfaces) throws IOException; + + CodeWriter beginConstructor(Collection params, Transformer transformer) throws IOException; + + CodeWriter beginConstructor(String... params) throws IOException; + + CodeWriter beginInterface(String simpleName, String... interfaces) throws IOException; + + CodeWriter beginLine(String... segments) throws IOException; + + CodeWriter beginPublicMethod(String returnType, String methodName, Collection parameters, Transformer transformer) throws IOException; + + CodeWriter beginPublicMethod(String returnType, String methodName, String... args) throws IOException; + + CodeWriter beginStaticMethod(String type, String name, Collection params, Transformer transformer) throws IOException; + + CodeWriter beginStaticMethod(String returnType, String methodName, String... args) throws IOException; + + CodeWriter end() throws IOException; + + CodeWriter field(String type, String name) throws IOException; + + CodeWriter imports(Class... imports) throws IOException; + + CodeWriter imports(Package... imports) throws IOException; + + CodeWriter javadoc(String... lines) throws IOException; + + String join(String prefix, String suffix, Iterable args); + + String join(String prefix, String suffix, String... args); + + CodeWriter line(String... segments) throws IOException; + + CodeWriter nl() throws IOException; + + CodeWriter packageDecl(String packageName) throws IOException; + + CodeWriter privateField(String type, String name) throws IOException; + + CodeWriter privateStaticFinal(String type, String name, String value) throws IOException; + + CodeWriter protectedField(String type, String name) throws IOException; + + CodeWriter publicField(String type, String name) throws IOException; + + CodeWriter publicFinal(String type, String name) throws IOException; + + CodeWriter publicFinal(String type, String name, String value) throws IOException; + + CodeWriter publicStaticFinal(String type, String name, String value) throws IOException; + + CodeWriter staticimports(Class... imports) throws IOException; + + CodeWriter suppressWarnings(String type) throws IOException; + +} \ No newline at end of file diff --git a/src/main/java/com/mysema/codegen/Evaluator.java b/src/main/java/com/mysema/codegen/Evaluator.java new file mode 100644 index 000000000..8c942e8d2 --- /dev/null +++ b/src/main/java/com/mysema/codegen/Evaluator.java @@ -0,0 +1,23 @@ +/* + * Copyright (c) 2010 Mysema Ltd. + * All rights reserved. + * + */ +package com.mysema.codegen; + +/** + * Evaluator defines an interface for returning a value as a result of + * evaluating an expression using the given argument array + * + * @author tiwe + * + */ +public interface Evaluator { + + /** + * @param args + * @return + */ + T evaluate(Object... args); + +} diff --git a/src/main/java/com/mysema/codegen/EvaluatorFactory.java b/src/main/java/com/mysema/codegen/EvaluatorFactory.java new file mode 100644 index 000000000..18bb65cc0 --- /dev/null +++ b/src/main/java/com/mysema/codegen/EvaluatorFactory.java @@ -0,0 +1,159 @@ +/* + * Copyright (c) 2010 Mysema Ltd. + * All rights reserved. + * + */ +package com.mysema.codegen; + +import java.io.File; +import java.io.IOException; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.io.Writer; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.net.MalformedURLException; +import java.net.URISyntaxException; +import java.net.URL; +import java.net.URLClassLoader; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import javax.tools.JavaCompiler; +import javax.tools.SimpleJavaFileObject; +import javax.tools.JavaCompiler.CompilationTask; + + +/** + * EvaluatorFactory is a factory implementation for creating Evaluator instances + * + * @author tiwe + * + */ +public class EvaluatorFactory { + + private final File classDir; + + private final ClassLoader loader; + + private final String classpath; + + private final JavaCompiler compiler; + + private final List compilationOptions; + + public EvaluatorFactory(JavaCompiler compiler, File classDir, + URLClassLoader parent) { + try { + this.compiler = compiler; + this.classDir = classDir; + if (!classDir.exists()){ + if (!classDir.mkdirs()){ + throw new IllegalArgumentException( + classDir.getAbsolutePath() + " could not be created"); + } + } + this.classpath = SimpleCompiler.getClassPath(parent); + this.loader = new URLClassLoader(new URL[] { classDir.toURI().toURL() }, parent); + this.compilationOptions = Arrays.asList( + "-classpath", classpath, + "-d", classDir.getAbsolutePath(), + "-g:none"); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + } + + private void compile(String source, Class projectionType, + String[] names, Class[] types, String id) throws IOException, + UnsupportedEncodingException { + // create source + StringWriter writer = new StringWriter(); + JavaWriter javaw = new JavaWriter(writer); + javaw.beginClass(id, null); + String[] params = new String[names.length]; + for (int i = 0; i < params.length; i++) { + params[i] = toName(types[i]) + " " + names[i]; + } + + javaw.beginStaticMethod(toName(projectionType), "eval", params); + javaw.line("return ", source, ";"); + javaw.end(); + javaw.end(); + + // compile + try { + SimpleJavaFileObject javaFileObject = new StringJavaFileObject(id, writer.toString()); + Writer out = new StringWriter(); + + CompilationTask task = compiler.getTask(out, null, null, + compilationOptions, null, Collections.singletonList(javaFileObject)); + if (!task.call().booleanValue()) { + throw new RuntimeException("Compilation of " + source + " failed.\n" + out.toString()); + } + } catch (URISyntaxException e) { + throw new IOException(e); + } + + } + + protected String toId(String source, Class returnType, Class... types) { + StringBuilder b = new StringBuilder("Q"); + b.append("_").append(source.hashCode()); + b.append("_").append(returnType.getName().hashCode()); + for (Class type : types) { + b.append("_").append(type.getName().hashCode()); + } + return b.toString().replace('-', '0'); + } + + protected String toName(Class cl) { + if (cl.isArray()) { + return toName(cl.getComponentType()) + "[]"; + } else if (cl.getPackage() == null || cl.getPackage().getName().equals("java.lang")) { + return cl.getSimpleName(); + } else { + return cl.getName().replace('$', '.'); + } + } + + public Evaluator createEvaluator(String source, + Class projectionType, String[] names, Class[] types) { + + try { + String id = toId(source, projectionType, types); + if (!new File(classDir, id + ".class").exists()) { + compile(source, projectionType, names, types, id); + } + + Class clazz = loader.loadClass(id); + final Method method = clazz.getMethod("eval", types); + return new Evaluator() { + @SuppressWarnings("unchecked") + @Override + public T evaluate(Object... args) { + try { + return (T) method.invoke(null, args); + } catch (IllegalAccessException e) { + throw new IllegalArgumentException(e); + } catch (InvocationTargetException e) { + throw new IllegalArgumentException(e); + } + } + }; + } catch (ClassNotFoundException e) { + throw new RuntimeException(e); + } catch (SecurityException e) { + throw new RuntimeException(e); + } catch (NoSuchMethodException e) { + throw new RuntimeException(e); + } catch (UnsupportedEncodingException e) { + throw new RuntimeException(e); + } catch (IOException e) { + throw new RuntimeException(e); + } + + } + +} diff --git a/src/main/java/com/mysema/codegen/JavaWriter.java b/src/main/java/com/mysema/codegen/JavaWriter.java new file mode 100644 index 000000000..c38516b8e --- /dev/null +++ b/src/main/java/com/mysema/codegen/JavaWriter.java @@ -0,0 +1,420 @@ +/* + * Copyright (c) 2010 Mysema Ltd. + * All rights reserved. + * + */ +package com.mysema.codegen; + +import static com.mysema.codegen.Symbols.ASSIGN; +import static com.mysema.codegen.Symbols.COMMA; +import static com.mysema.codegen.Symbols.DOT; +import static com.mysema.codegen.Symbols.NEWLINE; +import static com.mysema.codegen.Symbols.QUOTE; +import static com.mysema.codegen.Symbols.SEMICOLON; +import static com.mysema.codegen.Symbols.SPACE; + +import java.io.IOException; +import java.lang.annotation.Annotation; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import org.apache.commons.collections15.Transformer; +import org.apache.commons.lang.StringEscapeUtils; + +import com.mysema.commons.lang.Assert; + +/** + * @author tiwe + * + */ +public final class JavaWriter implements Appendable, CodeWriter{ + + private static final String EXTENDS = " extends "; + + private static final String IMPLEMENTS = " implements "; + + private static final String IMPORT = "import "; + + private static final String IMPORT_STATIC = "import static "; + + private static final String PACKAGE = "package "; + + private static final String PRIVATE = "private "; + + private static final String PRIVATE_STATIC_FINAL = "private static final "; + + private static final String PROTECTED = "protected "; + + private static final String PUBLIC = "public "; + + private static final String PUBLIC_CLASS = "public class "; + + private static final String PUBLIC_FINAL = "public final "; + + private static final String PUBLIC_INTERFACE = "public interface "; + + private static final String PUBLIC_STATIC = "public static "; + + private static final String PUBLIC_STATIC_FINAL = "public static final "; + + private final Appendable appendable; + + private final Set> importedClasses = new HashSet>(); + + private final Set importedPackages = new HashSet(); + + private String indent = ""; + + private String type; + + public JavaWriter(Appendable appendable){ + this.appendable = Assert.notNull(appendable,"appendable"); + importedPackages.add(Object.class.getPackage()); + } + + @Override + public JavaWriter annotation(Annotation annotation) throws IOException { + append(indent).append("@").appendType(annotation.annotationType()).append("("); + boolean first = true; + for (Method method : annotation.annotationType().getDeclaredMethods()){ + if (!first){ + append(COMMA); + } + append(method.getName()+"="); + try { + Object value = method.invoke(annotation); + annotationConstant(value); + } catch (IllegalArgumentException e) { + throw new RuntimeException(e); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } catch (InvocationTargetException e) { + throw new RuntimeException(e); + } + first = false; + } + return append(")").nl(); + } + + + @Override + public JavaWriter annotation(Class annotation) throws IOException{ + return append(indent).append("@").appendType(annotation).nl(); + } + + @SuppressWarnings("unchecked") + private void annotationConstant(Object value) throws IOException{ + if (value instanceof Class){ + appendType((Class)value).append(".class"); + }else if (value instanceof Number){ + append(value.toString()); + }else if (value instanceof Enum){ + Enum enumValue = (Enum)value; + append(enumValue.getDeclaringClass().getName()+DOT+enumValue.name()); + }else if (value instanceof String){ + append(QUOTE + StringEscapeUtils.escapeJava(value.toString()) + QUOTE); + }else{ + throw new IllegalArgumentException("Unsupported annotation value : " + value); + } + } + + + @Override + public JavaWriter append(char c) throws IOException { + appendable.append(c); + return this; + } + + @Override + public JavaWriter append(CharSequence csq) throws IOException { + appendable.append(csq); + return this; + } + + @Override + public JavaWriter append(CharSequence csq, int start, int end) throws IOException { + appendable.append(csq, start, end); + return this; + } + + private JavaWriter appendType(Class type) throws IOException{ + if (importedClasses.contains(type) || importedPackages.contains(type.getPackage())){ + append(type.getSimpleName()); + }else{ + append(type.getName()); + } + return this; + } + + public JavaWriter beginClass(String simpleName) throws IOException{ + return beginClass(simpleName, null); + } + + @Override + public JavaWriter beginClass(String simpleName, String superClass, String... interfaces) throws IOException{ + nl().append(indent + PUBLIC_CLASS + simpleName); + if (superClass != null){ + append(EXTENDS + superClass); + } + if (interfaces.length > 0){ + append(IMPLEMENTS).join(COMMA, interfaces); + } + append(" {").nl().nl(); + goIn(); + + type = simpleName; + if (type.contains("<")){ + type = type.substring(0, type.indexOf('<')); + } + return this; + } + + @Override + public JavaWriter beginConstructor(Collection parameters, Transformer transformer) throws IOException { + append(indent + PUBLIC + type).params(parameters, transformer).append(" {").nl(); + return goIn(); + } + + @Override + public JavaWriter beginConstructor(String... parameters) throws IOException{ + append(indent + PUBLIC + type).params(parameters).append(" {").nl(); + return goIn(); + } + + @Override + public JavaWriter beginInterface(String simpleName, String... interfaces) throws IOException { + nl().append(indent + PUBLIC_INTERFACE + simpleName); + if (interfaces.length > 0){ + append(EXTENDS).join(COMMA, interfaces); + } + append(" {").nl().nl(); + goIn(); + + type = simpleName; + if (type.contains("<")){ + type = type.substring(0, type.indexOf('<')); + } + return this; + + } + + @Override + public JavaWriter beginLine(String... segments) throws IOException { + append(indent); + for (String segment : segments){ + append(segment); + } + return this; + } + + private JavaWriter beginMethod(String returnType, String modifiers, String methodName, String... args) throws IOException{ + append(indent + modifiers + returnType + SPACE + methodName).params(args).append(" {").nl(); + return goIn(); + } + + @Override + public JavaWriter beginPublicMethod(String returnType, String methodName, Collection parameters, Transformer transformer) throws IOException { + return beginMethod(returnType, PUBLIC, methodName, transform(parameters, transformer)); + } + + @Override + public JavaWriter beginPublicMethod(String returnType, String methodName, String... args) throws IOException{ + return beginMethod(returnType, PUBLIC, methodName, args); + } + + @Override + public JavaWriter beginStaticMethod(String returnType, String methodName, Collection parameters, Transformer transformer) throws IOException { + return beginMethod(returnType, PUBLIC_STATIC, methodName, transform(parameters, transformer)); + } + + @Override + public JavaWriter beginStaticMethod(String returnType, String methodName, String... args) throws IOException{ + return beginMethod(returnType, PUBLIC_STATIC, methodName, args); + } + + @Override + public JavaWriter end() throws IOException{ + goOut(); + return line("}").nl(); + } + + @Override + public JavaWriter field(String type, String name) throws IOException { + return stmt(type + SPACE + name).nl(); + } + + private JavaWriter goIn(){ + indent += " "; + return this; + } + + private JavaWriter goOut(){ + if (indent.length() >= 4){ + indent = indent.substring(0, indent.length() - 4); + } + return this; + } + + @Override + public JavaWriter imports(Class... imports) throws IOException{ + for (Class cl : imports){ + importedClasses.add(cl); + line(IMPORT + cl.getName() + SEMICOLON); + } + return this; + } + + @Override + public JavaWriter imports(Package... imports) throws IOException { + for (Package p : imports){ + importedPackages.add(p); + line(IMPORT + p.getName() + ".*;"); + } + return this; + } + + @Override + public JavaWriter javadoc(String... lines) throws IOException { + line("/**"); + for (String line : lines){ + line(" * " + line); + } + return line(" */"); + } + + private JavaWriter join(String sep, String... args) throws IOException{ + for (int i = 0; i < args.length; i++){ + if (i > 0){ + append(sep); + } + append(args[i]); + } + return this; + } + + @Override + public String join(String prefix, String suffix, Iterable args) { + StringBuilder builder = new StringBuilder(); + boolean first = true; + for (String arg : args){ + if (!first){ + builder.append(COMMA); + } + builder.append(prefix).append(arg).append(suffix); + first = false; + } + return builder.toString(); + } + + + @Override + public String join(String prefix, String suffix, String... args) { + return join(prefix, suffix, Arrays.asList(args)); + } + + @Override + public JavaWriter line(String... segments) throws IOException{ + append(indent); + for (String segment : segments){ + append(segment); + } + return nl(); + } + + @Override + public JavaWriter nl() throws IOException { + return append(NEWLINE); + } + + @Override + public JavaWriter packageDecl(String packageName) throws IOException{ + return line(PACKAGE + packageName + SEMICOLON).nl(); + } + + private JavaWriter params(Collection parameters, Transformer transformer) throws IOException{ + append("("); + boolean first = true; + for (T param : parameters){ + if (!first){ + append(COMMA); + } + append(transformer.transform(param)); + first = false; + } + append(")"); + return this; + } + + private JavaWriter params(String... params) throws IOException{ + append("("); + join(COMMA, params); + append(")"); + return this; + } + + @Override + public JavaWriter privateField(String type, String name) throws IOException { + return stmt(PRIVATE + type + SPACE + name).nl(); + } + + @Override + public JavaWriter privateStaticFinal(String type, String name, String value) throws IOException { + return stmt(PRIVATE_STATIC_FINAL + type + SPACE + name + ASSIGN + value).nl(); + } + + @Override + public JavaWriter protectedField(String type, String name) throws IOException { + return stmt(PROTECTED + type + SPACE + name).nl(); + } + + @Override + public JavaWriter publicField(String type, String name) throws IOException { + return stmt(PUBLIC + type + SPACE + name).nl(); + } + + @Override + public JavaWriter publicFinal(String type, String name) throws IOException { + return stmt(PUBLIC_FINAL + type + SPACE + name).nl(); + } + + @Override + public JavaWriter publicFinal(String type, String name, String value) throws IOException { + return stmt(PUBLIC_FINAL + type + SPACE + name + ASSIGN + value).nl(); + } + + @Override + public JavaWriter publicStaticFinal(String type, String name, String value) throws IOException { + return stmt(PUBLIC_STATIC_FINAL + type + SPACE + name + ASSIGN + value).nl(); + } + + @Override + public JavaWriter staticimports(Class... imports) throws IOException{ + for (Class cl : imports){ + line(IMPORT_STATIC + cl.getName() + ".*;"); + } + return this; + } + + private JavaWriter stmt(String stmt) throws IOException{ + return line(stmt + SEMICOLON); + } + + @Override + public JavaWriter suppressWarnings(String type) throws IOException{ + return line("@SuppressWarnings(\"" + type +"\")"); + } + + private String[] transform(Collection parameters, Transformer transformer){ + String[] rv = new String[parameters.size()]; + int i = 0; + for (T value : parameters){ + rv[i++] = transformer.transform(value); + } + return rv; + } + +} diff --git a/src/main/java/com/mysema/codegen/SimpleCompiler.java b/src/main/java/com/mysema/codegen/SimpleCompiler.java new file mode 100644 index 000000000..01a9c7118 --- /dev/null +++ b/src/main/java/com/mysema/codegen/SimpleCompiler.java @@ -0,0 +1,121 @@ +/* + * Copyright (c) 2010 Mysema Ltd. + * All rights reserved. + * + */ +package com.mysema.codegen; + +import java.io.File; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.UnsupportedEncodingException; +import java.io.Writer; +import java.net.URL; +import java.net.URLClassLoader; +import java.net.URLDecoder; +import java.nio.charset.Charset; +import java.util.ArrayList; +import java.util.List; +import java.util.Locale; +import java.util.Set; + +import javax.lang.model.SourceVersion; +import javax.tools.DiagnosticListener; +import javax.tools.JavaCompiler; +import javax.tools.JavaFileManager; +import javax.tools.JavaFileObject; +import javax.tools.StandardJavaFileManager; +import javax.tools.ToolProvider; + +/** + * @author tiwe + * + */ +public class SimpleCompiler implements JavaCompiler{ + + private final ClassLoader classLoader; + + private String classPath; + + private final JavaCompiler compiler; + + public static String getClassPath(URLClassLoader classLoader) { + try{ + StringBuilder path = new StringBuilder(); + for (URL url : ((URLClassLoader)classLoader).getURLs()){ + if (path.length() > 0){ + path.append(File.pathSeparator); + } + String decodedPath = URLDecoder.decode(url.getPath(),"UTF-8"); + path.append(new File(decodedPath).getAbsolutePath()); + } + return path.toString(); + }catch(UnsupportedEncodingException e){ + throw new RuntimeException(e); + } + } + + public SimpleCompiler(){ + this(ToolProvider.getSystemJavaCompiler(), Thread.currentThread().getContextClassLoader()); + } + + public SimpleCompiler(JavaCompiler compiler, ClassLoader classLoader){ + this.compiler = compiler; + this.classLoader = classLoader; + } + + private String getClasspath(){ + if (classPath == null){ + if (classLoader instanceof URLClassLoader){ + classPath = getClassPath((URLClassLoader)classLoader); + }else{ + throw new IllegalArgumentException("Unsupported ClassLoader " + classLoader); + } + } + return classPath; + } + + @Override + public Set getSourceVersions() { + return compiler.getSourceVersions(); + } + + @Override + public StandardJavaFileManager getStandardFileManager( + DiagnosticListener diagnosticListener, + Locale locale, Charset charset) { + return compiler.getStandardFileManager(diagnosticListener, locale, charset); + } + + @Override + public CompilationTask getTask(Writer out, JavaFileManager fileManager, + DiagnosticListener diagnosticListener, + Iterable options, Iterable classes, + Iterable compilationUnits) { + return compiler.getTask(out, fileManager, diagnosticListener, options, classes, compilationUnits); + } + + @Override + public int isSupportedOption(String option) { + return compiler.isSupportedOption(option); + } + + @Override + public int run(InputStream in, OutputStream out, OutputStream err, String... arguments) { + for (String a : arguments){ + if (a.equals("-classpath")){ + return compiler.run(in, out, err, arguments); + } + } + + // no classpath given + List args = new ArrayList(arguments.length + 2); + args.add("-classpath"); + args.add(getClasspath()); + for (String arg : arguments){ + args.add(arg); + } + return compiler.run(in, out, err, args.toArray(new String[args.size()])); + } + +} diff --git a/src/main/java/com/mysema/codegen/StringJavaFileObject.java b/src/main/java/com/mysema/codegen/StringJavaFileObject.java new file mode 100644 index 000000000..d152bdba3 --- /dev/null +++ b/src/main/java/com/mysema/codegen/StringJavaFileObject.java @@ -0,0 +1,38 @@ +/* + * Copyright (c) 2010 Mysema Ltd. + * All rights reserved. + * + */ +package com.mysema.codegen; + +import java.io.IOException; +import java.net.URI; +import java.net.URISyntaxException; + +import javax.tools.SimpleJavaFileObject; + +/** + * @author tiwe + * + */ +public class StringJavaFileObject extends SimpleJavaFileObject { + + private final String contents; + + public StringJavaFileObject(String className, String contents) throws URISyntaxException{ + super(new URI(className), Kind.SOURCE); + this.contents = contents; + } + + @Override + public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException { + return contents; + } + + @Override + public boolean isNameCompatible(String simpleName, Kind kind) { + return kind.equals(getKind()) && + (simpleName.equals(toUri().getPath()) || toUri().getPath().endsWith("/" + simpleName)); + } + +} diff --git a/src/main/java/com/mysema/codegen/Symbols.java b/src/main/java/com/mysema/codegen/Symbols.java new file mode 100644 index 000000000..d297ae3c7 --- /dev/null +++ b/src/main/java/com/mysema/codegen/Symbols.java @@ -0,0 +1,47 @@ +/* + * Copyright (c) 2010 Mysema Ltd. + * All rights reserved. + * + */ +package com.mysema.codegen; + +/** + * @author tiwe + * + */ +public final class Symbols { + + public static final String ASSIGN = " = "; + + public static final String COMMA = ", "; + + public static final String DOT = "."; + + public static final String DOT_CLASS = ".class"; + + public static final String EMPTY = ""; + + public static final String NEW = "new "; + + public static final String NEWLINE = "\n"; + + public static final String QUOTE = "\""; + + public static final String RETURN = "return "; + + public static final String SEMICOLON = ";"; + + public static final String SERIAL = "serial"; + + public static final String SPACE = " "; + + public static final String STAR = "*"; + + public static final String SUPER = "super"; + + public static final String THIS = "this"; + + public static final String UNCHECKED = "unchecked"; + + private Symbols(){} +} diff --git a/src/test/java/com/mysema/codegen/JavaWriterTest.java b/src/test/java/com/mysema/codegen/JavaWriterTest.java new file mode 100644 index 000000000..a1b91ddd0 --- /dev/null +++ b/src/test/java/com/mysema/codegen/JavaWriterTest.java @@ -0,0 +1,61 @@ +package com.mysema.codegen; + +import java.io.IOException; +import java.io.StringWriter; + +import org.junit.Test; + +public class JavaWriterTest { + + @Test + public void testBasic() throws IOException { + StringWriter w = new StringWriter(); + CodeWriter writer = new JavaWriter(w); + writer.packageDecl("com.mysema.codegen"); + writer.imports(IOException.class, StringWriter.class, Test.class); + writer.beginClass("JavaWriterTest"); + writer.annotation(Test.class); + writer.beginPublicMethod("void", "test"); + writer.line("// TODO"); + writer.end(); + writer.end(); + System.out.println(w); + } + + @Test + public void testFields() throws IOException{ + StringWriter w = new StringWriter(); + CodeWriter writer = new JavaWriter(w); + writer.beginClass("FieldTests"); + // private + writer.privateField("String", "privateField"); + writer.privateStaticFinal("String", "privateStaticFinal", "\"val\""); + // protected + writer.protectedField("String","protectedField"); + // field + writer.field("String","field"); + // public + writer.publicField("String","publicField"); + writer.publicStaticFinal("String", "publicStaticFinal", "\"val\""); + writer.end(); + System.out.println(w); + } + + @Test + public void testMethods() throws IOException{ + StringWriter w = new StringWriter(); + CodeWriter writer = new JavaWriter(w); + writer.beginClass("MethodTests"); + // private + + // protected + + // method + + // public + + writer.end(); + System.out.println(w); + } + +}