moved codegen core model from querydsl-core to codegen

This commit is contained in:
Timo Westkämper 2010-08-03 15:29:47 +00:00
parent 7ada1f4bb0
commit b9749d0ced
31 changed files with 1324 additions and 217 deletions

11
pom.xml
View File

@ -28,6 +28,17 @@
<version>2.4</version>
</dependency>
<dependency>
<groupId>net.sourceforge.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>1.3.2</version>
</dependency>
<dependency>
<groupId>net.sourceforge.findbugs</groupId>
<artifactId>annotations</artifactId>
<version>1.3.2</version>
</dependency>
<!-- test -->
<dependency>
<groupId>junit</groupId>

View File

@ -0,0 +1,98 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen;
import static com.mysema.codegen.Symbols.NEWLINE;
import static com.mysema.codegen.Symbols.SEMICOLON;
import java.io.IOException;
/**
* @author tiwe
*
* @param <T>
*/
public abstract class AbstractCodeWriter<T extends AbstractCodeWriter<T>> implements Appendable, CodeWriter{
private static final int INDENT_SPACES = 4;
private final Appendable appendable;
private String indent = "";
@SuppressWarnings("unchecked")
private final T self = (T)this;
public AbstractCodeWriter(Appendable appendable){
if (appendable == null){
throw new IllegalArgumentException("appendable is null");
}
this.appendable = appendable;
}
@Override
public T append(char c) throws IOException {
appendable.append(c);
return self;
}
@Override
public T append(CharSequence csq) throws IOException {
appendable.append(csq);
return self;
}
@Override
public T append(CharSequence csq, int start, int end) throws IOException {
appendable.append(csq, start, end);
return self;
}
@Override
public T beginLine(String... segments) throws IOException {
append(indent);
for (String segment : segments){
append(segment);
}
return self;
}
protected T goIn(){
indent += " ";
return self;
}
protected T goOut(){
if (indent.length() >= INDENT_SPACES){
indent = indent.substring(0, indent.length() - INDENT_SPACES);
}
return self;
}
@Override
public T line(String... segments) throws IOException{
append(indent);
for (String segment : segments){
append(segment);
}
return nl();
}
@Override
public T nl() throws IOException {
return append(NEWLINE);
}
protected T stmt(String stmt) throws IOException{
return line(stmt + SEMICOLON);
}
}

View File

@ -1,93 +0,0 @@
package com.mysema.codegen;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* Type represents a generic type used in code generation
*
* @author tiwe
*
* @param <T>
*/
public class ClassType<T> implements Type<T> {
private final Class<T> javaClass;
private final List<Type<?>> parameters;
public ClassType(Class<T> javaClass, List<Type<?>> parameters) {
this.javaClass = javaClass;
this.parameters = parameters;
}
public ClassType(Class<T> clazz, Type<?>... parameters) {
this(clazz, Arrays.asList(parameters));
}
@Override
public boolean equals(Object o){
if (o == this){
return true;
}else if (o instanceof ClassType<?>){
ClassType<?> t = (ClassType<?>)o;
return t.javaClass.equals(javaClass) && t.parameters.equals(parameters);
}else{
return false;
}
}
@Override
public String getGenericName() {
return getGenericName(Collections.<String>emptySet(), Collections.<String>emptySet());
}
@Override
public String getGenericName(Set<String> packages, Set<String> classes) {
if (parameters.isEmpty()){
return ClassUtils.getName(javaClass, packages, classes);
}else{
StringBuilder builder = new StringBuilder();
builder.append(ClassUtils.getName(javaClass, packages, classes));
builder.append("<");
boolean first = true;
for (Type<?> parameter : parameters){
builder.append(parameter.getGenericName(packages, classes));
if (!first){
builder.append(",");
}
first = false;
}
builder.append(">");
return builder.toString();
}
}
@Override
public String getName() {
return javaClass.getName();
}
@Override
public String getPackageName() {
return javaClass.getPackage().getName();
}
@Override
public List<Type<?>> getParameters() {
return parameters;
}
@Override
public String getSimpleName() {
return javaClass.getSimpleName();
}
@Override
public int hashCode(){
return javaClass.hashCode();
}
}

View File

@ -33,7 +33,7 @@ public interface CodeWriter extends Appendable{
CodeWriter beginInterface(String simpleName, String... interfaces) throws IOException;
JavaWriter beginLine(String... segments) throws IOException;
CodeWriter beginLine(String... segments) throws IOException;
<T> CodeWriter beginPublicMethod(String returnType, String methodName, Collection<T> parameters, Transformer<T, String> transformer) throws IOException;

View File

@ -23,6 +23,12 @@ import javax.tools.StandardLocation;
import javax.tools.ToolProvider;
import javax.tools.JavaCompiler.CompilationTask;
import com.mysema.codegen.model.ClassType;
import com.mysema.codegen.model.Type;
import com.mysema.codegen.model.TypeCategory;
import com.mysema.codegen.support.ClassUtils;
/**
* EvaluatorFactory is a factory implementation for creating Evaluator instances
@ -54,15 +60,15 @@ public class EvaluatorFactory {
this.compilationOptions = Arrays.asList("-classpath", classpath, "-g:none");
}
private void compile(String source, Class<?> projectionType,
String[] names, Type<?>[] types, String id, Map<String,Object> constants) throws IOException {
private void compile(String source, Type projectionType,
String[] names, Type[] types, String id, Map<String,Object> constants) throws IOException {
// 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] = types[i].getGenericName() + " " + names[i];
params[i] = types[i].getGenericName(true) + " " + names[i];
}
for (Map.Entry<String,Object> entry : constants.entrySet()){
@ -71,9 +77,9 @@ public class EvaluatorFactory {
}
if (constants.isEmpty()){
javaw.beginStaticMethod(ClassUtils.getName(projectionType), "eval", params);
javaw.beginStaticMethod(projectionType.getGenericName(false), "eval", params);
}else{
javaw.beginPublicMethod(ClassUtils.getName(projectionType), "eval", params);
javaw.beginPublicMethod(projectionType.getGenericName(false), "eval", params);
}
javaw.append(source);
javaw.end();
@ -103,11 +109,11 @@ public class EvaluatorFactory {
String[] names,
Class<?>[] classes,
Map<String,Object> constants) {
Type<?>[] types = new Type[classes.length];
Type[] types = new Type[classes.length];
for (int i = 0; i < types.length; i++){
types[i] = new ClassType(classes[i]);
types[i] = new ClassType(TypeCategory.SIMPLE,classes[i]);
}
return createEvaluator(source, projectionType, names, types, classes, constants);
return createEvaluator(source, new ClassType(TypeCategory.SIMPLE,projectionType), names, types, classes, constants);
}
/**
@ -123,13 +129,13 @@ public class EvaluatorFactory {
*/
public <T> Evaluator<T> createEvaluator(
String source,
Class<? extends T> projection,
ClassType<? extends T> projection,
String[] names,
Type<?>[] types,
Type[] types,
Class<?>[] classes,
Map<String,Object> constants) {
try {
String id = toId(source, projection, types);
String id = toId(source, projection.getJavaClass(), types);
Class<?> clazz;
try{
clazz = loader.loadClass(id);
@ -147,7 +153,7 @@ public class EvaluatorFactory {
}
Method method = clazz.getMethod("eval", classes);
return new MethodEvaluator<T>(method, object, projection);
return new MethodEvaluator<T>(method, object, projection.getJavaClass());
} catch (ClassNotFoundException e) {
throw new CodegenException(e);
} catch (SecurityException e) {
@ -168,12 +174,12 @@ public class EvaluatorFactory {
}
protected String toId(String source, Class<?> returnType, Type<?>... types) {
protected String toId(String source, Class<?> returnType, Type... types) {
StringBuilder b = new StringBuilder("Q");
b.append("_").append(source.hashCode());
b.append("_").append(returnType.getName().hashCode());
for (Type<?> type : types) {
b.append("_").append(type.getName().hashCode());
for (Type type : types) {
b.append("_").append(type.getFullName().hashCode());
}
return b.toString().replace('-', '0');
}

View File

@ -8,7 +8,6 @@ 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;
@ -25,15 +24,14 @@ import org.apache.commons.collections15.Transformer;
import org.apache.commons.lang.StringEscapeUtils;
import org.apache.commons.lang.StringUtils;
/**
* JavaWriter is the default implementation of the CodeWriter interface
*
* @author tiwe
*
*/
public final class JavaWriter implements Appendable, CodeWriter{
private static final int INDENT_SPACES = 4;
public final class JavaWriter extends AbstractCodeWriter<JavaWriter>{
private static final String EXTENDS = " extends ";
@ -65,27 +63,20 @@ public final class JavaWriter implements Appendable, CodeWriter{
private static final String PUBLIC_STATIC_FINAL = "public static final ";
private final Appendable appendable;
private final Set<String> importedClasses = new HashSet<String>();
private final Set<String> importedPackages = new HashSet<String>();
private String indent = "";
private String type;
public JavaWriter(Appendable appendable){
if (appendable == null){
throw new IllegalArgumentException("appendable is null");
}
this.appendable = appendable;
super(appendable);
this.importedPackages.add("java.lang");
}
@Override
public JavaWriter annotation(Annotation annotation) throws IOException {
append(indent).append("@").appendType(annotation.annotationType());
beginLine().append("@").appendType(annotation.annotationType());
Method[] methods = annotation.annotationType().getDeclaredMethods();
if (methods.length == 1 && methods[0].getName().equals("value")){
try {
@ -133,7 +124,7 @@ public final class JavaWriter implements Appendable, CodeWriter{
@Override
public JavaWriter annotation(Class<? extends Annotation> annotation) throws IOException{
return append(indent).append("@").appendType(annotation).nl();
return beginLine().append("@").appendType(annotation).nl();
}
@SuppressWarnings("unchecked")
@ -152,25 +143,6 @@ public final class JavaWriter implements Appendable, CodeWriter{
}
}
@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.getName()) || importedPackages.contains(type.getPackage().getName())){
append(type.getSimpleName());
@ -186,7 +158,7 @@ public final class JavaWriter implements Appendable, CodeWriter{
@Override
public JavaWriter beginClass(String simpleName, String superClass, String... interfaces) throws IOException{
append(indent + PUBLIC_CLASS + simpleName);
beginLine(PUBLIC_CLASS + simpleName);
if (superClass != null){
append(EXTENDS + superClass);
}
@ -206,19 +178,19 @@ public final class JavaWriter implements Appendable, CodeWriter{
@Override
public <T> JavaWriter beginConstructor(Collection<T> parameters, Transformer<T,String> transformer) throws IOException {
append(indent + PUBLIC + type).params(parameters, transformer).append(" {").nl();
beginLine(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();
beginLine(PUBLIC + type).params(parameters).append(" {").nl();
return goIn();
}
@Override
public JavaWriter beginInterface(String simpleName, String... interfaces) throws IOException {
append(indent + PUBLIC_INTERFACE + simpleName);
beginLine(PUBLIC_INTERFACE + simpleName);
if (interfaces.length > 0){
append(EXTENDS);
append(StringUtils.join(interfaces, COMMA));
@ -234,17 +206,10 @@ public final class JavaWriter implements Appendable, CodeWriter{
}
@Override
public JavaWriter beginLine(String... segments) throws IOException {
append(indent);
for (String segment : segments){
append(segment);
}
return this;
}
private JavaWriter beginMethod(String modifiers, String returnType, String methodName, String... args) throws IOException{
append(indent + modifiers + returnType + SPACE + methodName).params(args).append(" {").nl();
beginLine(modifiers + returnType + SPACE + methodName).params(args).append(" {").nl();
return goIn();
}
@ -287,18 +252,6 @@ public final class JavaWriter implements Appendable, CodeWriter{
return stmt(modifier + type + SPACE + name + ASSIGN + value).nl();
}
private JavaWriter goIn(){
indent += " ";
return this;
}
private JavaWriter goOut(){
if (indent.length() >= INDENT_SPACES){
indent = indent.substring(0, indent.length() - INDENT_SPACES);
}
return this;
}
@Override
public JavaWriter imports(Class<?>... imports) throws IOException{
for (Class<?> cl : imports){
@ -347,20 +300,6 @@ public final class JavaWriter implements Appendable, CodeWriter{
}
return line(" */");
}
@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{
@ -451,10 +390,6 @@ public final class JavaWriter implements Appendable, CodeWriter{
}
return this;
}
private JavaWriter stmt(String stmt) throws IOException{
return line(stmt + SEMICOLON);
}
@Override
public JavaWriter suppressWarnings(String type) throws IOException{

View File

@ -1,25 +0,0 @@
package com.mysema.codegen;
import java.util.List;
import java.util.Set;
/**
* @author tiwe
*
* @param <T>
*/
public interface Type<T> {
String getGenericName();
String getGenericName(Set<String> packages, Set<String> classes);
String getName();
String getPackageName();
List<Type<?>> getParameters();
String getSimpleName();
}

View File

@ -0,0 +1,168 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen.model;
import java.lang.reflect.Modifier;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import com.mysema.codegen.support.ClassUtils;
/**
* @author tiwe
*
* @param <T>
*/
public class ClassType<T> implements Type {
private final TypeCategory category;
private final Class<T> javaClass;
private final List<Type> parameters;
private final Class<?> primitiveClass;
public ClassType(TypeCategory category, Class<T> javaClass, Class<?> primitiveClass) {
this(category, javaClass, primitiveClass, Collections.<Type>emptyList());
}
public ClassType(TypeCategory category, Class<T> javaClass, Class<?> primitiveClass, List<Type> parameters) {
this.category = category;
this.javaClass = javaClass;
this.primitiveClass = primitiveClass;
this.parameters = parameters;
}
public ClassType(TypeCategory category, Class<T> javaClass, List<Type> parameters) {
this(category, javaClass, null, parameters);
}
public ClassType(TypeCategory category, Class<T> clazz, Type... parameters) {
this(category, clazz, null, Arrays.asList(parameters));
}
@Override
public Type as(TypeCategory c) {
if (category == c){
return this;
}else{
return new ClassType<T>(c, javaClass);
}
}
@Override
public Type asArrayType() {
String fullName = javaClass.getName()+"[]";
String simpleName = javaClass.getSimpleName()+"[]";
return new SimpleType(TypeCategory.ARRAY, fullName, getPackageName(), simpleName, false, false);
}
@Override
public boolean equals(Object o){
if (o == this){
return true;
}else if (o instanceof Type){
Type t = (Type)o;
return t.getFullName().equals(javaClass.getName()) && t.getParameters().equals(parameters);
}else{
return false;
}
}
public TypeCategory getCategory() {
return category;
}
@Override
public String getFullName() {
return javaClass.getName();
}
@Override
public String getGenericName(boolean asArgType) {
return getGenericName(asArgType, Collections.<String>emptySet(), Collections.<String>emptySet());
}
@Override
public String getGenericName(boolean asArgType, Set<String> packages, Set<String> classes) {
if (parameters.isEmpty()){
return ClassUtils.getName(javaClass, packages, classes);
}else{
StringBuilder builder = new StringBuilder();
builder.append(ClassUtils.getName(javaClass, packages, classes));
builder.append("<");
boolean first = true;
for (Type parameter : parameters){
if (!first){
builder.append(",");
}
if (parameter == null || parameter.equals(this)){
builder.append("?");
}else{
builder.append(parameter.getGenericName(true, packages, classes));
}
first = false;
}
builder.append(">");
return builder.toString();
}
}
public Class<T> getJavaClass() {
return javaClass;
}
@Override
public String getPackageName() {
return javaClass.getPackage().getName();
}
@Override
public List<Type> getParameters() {
return parameters;
}
@Override
public String getPrimitiveName() {
return primitiveClass != null ? primitiveClass.getName() : null;
}
@Override
public String getRawName(Set<String> packages, Set<String> classes) {
return ClassUtils.getName(javaClass, packages, classes);
}
@Override
public String getSimpleName() {
return javaClass.getSimpleName();
}
@Override
public int hashCode(){
return javaClass.getName().hashCode();
}
@Override
public boolean isFinal() {
return Modifier.isFinal(javaClass.getModifiers());
}
@Override
public boolean isPrimitive() {
// return javaClass.isPrimitive();
return primitiveClass != null;
}
public String toString(){
return getGenericName(true);
}
}

View File

@ -0,0 +1,38 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen.model;
import java.util.Collection;
public final class Constructor {
private final Collection<Parameter> parameters;
public Constructor(Collection<Parameter> params) {
parameters = params;
}
@Override
public boolean equals(Object o){
if (o == this){
return true;
}else if (o instanceof Constructor){
return ((Constructor)o).parameters.equals(parameters);
}else{
return false;
}
}
public Collection<Parameter> getParameters() {
return parameters;
}
@Override
public int hashCode(){
return parameters.hashCode();
}
}

View File

@ -0,0 +1,49 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen.model;
/**
* Parameter represents a parameter in a Constructor
*
* @author tiwe
* @version $Id$
*/
public final class Parameter {
private final String name;
private final Type type;
public Parameter(String name, Type type) {
this.name = name;
this.type = type;
}
@Override
public boolean equals(Object o) {
if (o == this){
return true;
}else if (o instanceof Parameter){
return type.equals(((Parameter) o).type);
}else{
return false;
}
}
public String getName() {
return name;
}
public Type getType(){
return type;
}
@Override
public int hashCode() {
return type.hashCode();
}
}

View File

@ -0,0 +1,173 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen.model;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Set;
/**
* @author tiwe
*
* @param <T>
*/
public class SimpleType implements Type {
private final TypeCategory category;
private final String fullName, packageName, simpleName, localName;
private final List<Type> parameters;
private final boolean primitiveClass, finalClass;
public SimpleType(Type type, Type... parameters) {
this(type.getCategory(), type.getFullName(), type.getPackageName(), type.getSimpleName(),
type.isPrimitive(), type.isFinal(), Arrays.asList(parameters));
}
public SimpleType(TypeCategory category, String fullName, String packageName, String simpleName,
boolean primitiveClass, boolean finalClass,
List<Type> parameters) {
this.category = category;
this.fullName = fullName;
this.packageName = packageName;
this.simpleName = simpleName;
if (packageName.length() > 0){
this.localName = fullName.substring(packageName.length()+1);
}else{
this.localName = fullName;
}
this.primitiveClass = primitiveClass;
this.finalClass = finalClass;
this.parameters = parameters;
}
public SimpleType(TypeCategory typeCategory, String fullName, String packageName, String simpleName,
boolean p, boolean f, Type... parameters) {
this(typeCategory, fullName, packageName, simpleName, p, f, Arrays
.asList(parameters));
}
@Override
public Type as(TypeCategory c) {
if (category != c){
return new SimpleType(c, fullName, packageName, simpleName, primitiveClass, finalClass, parameters);
}else{
return this;
}
}
@Override
public Type asArrayType() {
String fullName = getFullName()+"[]";
String simpleName = getSimpleName()+"[]";
return new SimpleType(TypeCategory.ARRAY, fullName, getPackageName(), simpleName, false, false);
}
@Override
public boolean equals(Object o){
if (o == this){
return true;
}else if (o instanceof Type){
Type t = (Type)o;
return t.getFullName().equals(fullName) && t.getParameters().equals(parameters);
}else{
return false;
}
}
public TypeCategory getCategory() {
return category;
}
@Override
public String getFullName() {
return fullName;
}
@Override
public String getGenericName(boolean asArgType) {
return getGenericName(asArgType, Collections.<String>emptySet(), Collections.<String>emptySet());
}
@Override
public String getGenericName(boolean asArgType, Set<String> packages, Set<String> classes) {
if (parameters.isEmpty()){
return getRawName(packages, classes);
}else{
StringBuilder builder = new StringBuilder();
builder.append(getRawName(packages, classes));
builder.append("<");
boolean first = true;
for (Type parameter : parameters){
if (!first){
builder.append(",");
}
if (parameter == null || parameter.equals(this)){
builder.append("?");
}else{
builder.append(parameter.getGenericName(true, packages, classes));
}
first = false;
}
builder.append(">");
return builder.toString();
}
}
@Override
public String getPackageName() {
return packageName;
}
@Override
public List<Type> getParameters() {
return parameters;
}
@Override
public String getPrimitiveName() {
return null;
}
@Override
public String getRawName(Set<String> packages, Set<String> classes) {
if (packages.contains(packageName) || classes.contains(fullName)){
return localName;
}else{
return fullName;
}
}
@Override
public String getSimpleName() {
return simpleName;
}
@Override
public int hashCode(){
return fullName.hashCode();
}
@Override
public boolean isFinal() {
return finalClass;
}
@Override
public boolean isPrimitive() {
return primitiveClass;
}
public String toString(){
return getGenericName(true);
}
}

View File

@ -0,0 +1,44 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen.model;
import java.util.List;
import java.util.Set;
/**
* @author tiwe
*
* @param <T>
*/
public interface Type {
Type as(TypeCategory category);
Type asArrayType();
TypeCategory getCategory();
String getFullName();
String getGenericName(boolean asArgType);
String getGenericName(boolean asArgType, Set<String> packages, Set<String> classes);
String getPackageName();
List<Type> getParameters();
String getPrimitiveName();
String getRawName(Set<String> packages, Set<String> classes);
String getSimpleName();
boolean isFinal();
boolean isPrimitive();
}

View File

@ -0,0 +1,109 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen.model;
import java.util.List;
import java.util.Set;
/**
* TypeAdapter is a basic adapter implementation for the Type interface
*
* @author tiwe
*
*/
public class TypeAdapter implements Type{
private final Type type;
public TypeAdapter(Type type){
this.type = type;
}
@Override
public Type as(TypeCategory category) {
return type.as(category);
}
@Override
public Type asArrayType() {
return type.asArrayType();
}
@Override
public boolean equals(Object o){
return type.equals(o);
}
@Override
public TypeCategory getCategory() {
return type.getCategory();
}
@Override
public String getFullName() {
return type.getFullName();
}
@Override
public String getGenericName(boolean asArgType) {
return type.getGenericName(asArgType);
}
@Override
public String getGenericName(boolean asArgType, Set<String> packages, Set<String> classes) {
return type.getGenericName(asArgType, packages, classes);
}
@Override
public String getPackageName() {
return type.getPackageName();
}
@Override
public List<Type> getParameters() {
return type.getParameters();
}
@Override
public String getPrimitiveName() {
return type.getPrimitiveName();
}
@Override
public String getRawName(Set<String> packages, Set<String> classes) {
return type.getRawName(packages, classes);
}
@Override
public String getSimpleName() {
return type.getSimpleName();
}
protected Type getType(){
return type;
}
@Override
public int hashCode(){
return type.hashCode();
}
@Override
public boolean isFinal() {
return type.isFinal();
}
@Override
public boolean isPrimitive() {
return type.isPrimitive();
}
@Override
public String toString() {
return type.toString();
}
}

View File

@ -0,0 +1,137 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen.model;
import java.util.HashSet;
import java.util.Set;
/**
* TypeCategory defines the expression type used for a Field
*
* @author tiwe
*
*/
public enum TypeCategory {
/**
*
*/
SIMPLE(null),
/**
*
*/
MAP(null),
/**
*
*/
COLLECTION(null),
/**
*
*/
LIST(COLLECTION),
/**
*
*/
SET(COLLECTION),
/**
*
*/
ARRAY(null),
/**
*
*/
COMPARABLE(SIMPLE),
/**
*
*/
BOOLEAN(COMPARABLE, Boolean.class.getName()),
/**
*
*/
DATE(COMPARABLE, java.sql.Date.class.getName(), "org.joda.time.LocalDate"),
/**
*
*/
DATETIME(COMPARABLE,
java.util.Calendar.class.getName(),
java.util.Date.class.getName(),
java.sql.Timestamp.class.getName(),
"org.joda.time.LocalDateTime",
"org.joda.time.Instant",
"org.joda.time.DateTime",
"org.joda.time.DateMidnight"),
/**
*
*/
CUSTOM(null),
/**
*
*/
ENTITY(null),
/**
*
*/
NUMERIC(COMPARABLE),
/**
*
*/
STRING(COMPARABLE, String.class.getName()),
/**
*
*/
TIME(COMPARABLE, java.sql.Time.class.getName(), "org.joda.time.LocalTime");
private final TypeCategory superType;
private final Set<String> types;
TypeCategory(TypeCategory superType, String... types){
this.superType = superType;
this.types = new HashSet<String>(types.length);
for (String type : types){
this.types.add(type);
}
}
public TypeCategory getSuperType() {
return superType;
}
public boolean supports(Class<?> cl){
return supports(cl.getName());
}
public boolean supports(String className){
return types.contains(className);
}
/**
* transitive and reflexive subCategoryOf check
*
* @param ancestor
* @return
*/
public boolean isSubCategoryOf(TypeCategory ancestor){
if (this == ancestor){
return true;
}else if (superType == null){
return false;
}else{
return superType == ancestor || superType.isSubCategoryOf(ancestor);
}
}
public static TypeCategory get(String className){
for (TypeCategory category : values()){
if (category.supports(className)){
return category;
}
}
return SIMPLE;
}
}

View File

@ -0,0 +1,50 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen.model;
import java.util.Set;
/**
* @author tiwe
*
*/
public class TypeExtends extends TypeAdapter{
private final String varName;
public TypeExtends(String varName, Type type) {
super(type);
this.varName = varName;
}
public TypeExtends(Type type) {
super(type);
varName = null;
}
@Override
public String getGenericName(boolean asArgType){
if (!asArgType){
return "? extends " + super.getGenericName(true);
}else{
return super.getGenericName(asArgType);
}
}
@Override
public String getGenericName(boolean asArgType, Set<String> packages, Set<String> classes){
if (!asArgType){
return "? extends " + super.getGenericName(true, packages, classes);
}else{
return super.getGenericName(asArgType, packages, classes);
}
}
public String getVarName(){
return varName;
}
}

View File

@ -0,0 +1,56 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen.model;
import java.util.Set;
/**
* TypeSuper is a Type for type variables and wildcard types
*
* @author tiwe
*
*/
public class TypeSuper extends TypeAdapter{
private final Type superType;
private final String varName;
public TypeSuper(String varName, Type type) {
super(Types.OBJECT);
this.superType = type;
this.varName = varName;
}
public TypeSuper(Type type) {
super(Types.OBJECT);
this.superType = type;
this.varName = null;
}
@Override
public String getGenericName(boolean asArgType){
if (!asArgType){
return "? super " + superType.getGenericName(true);
}else{
return super.getGenericName(asArgType);
}
}
@Override
public String getGenericName(boolean asArgType, Set<String> packages, Set<String> classes){
if (!asArgType){
return "? super " + superType.getGenericName(true, packages, classes);
}else{
return super.getGenericName(asArgType, packages, classes);
}
}
public String getVarName(){
return varName;
}
}

View File

@ -0,0 +1,65 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen.model;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.net.URI;
import java.util.Collection;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
/**
* @author tiwe
*
*/
public final class Types {
public static final ClassType<Object> OBJECT = new ClassType<Object>(TypeCategory.SIMPLE,Object.class);
public static final ClassType<Object[]> OBJECTS = new ClassType<Object[]>(TypeCategory.ARRAY,Object[].class);
public static final ClassType<BigDecimal> BIG_DECIMAL = new ClassType<BigDecimal>(TypeCategory.NUMERIC,BigDecimal.class);
public static final ClassType<BigInteger> BIG_INTEGER = new ClassType<BigInteger>(TypeCategory.NUMERIC,BigInteger.class);
public static final ClassType<Boolean> BOOLEAN = new ClassType<Boolean>(TypeCategory.BOOLEAN,Boolean.class, boolean.class);
public static final ClassType<Byte> BYTE = new ClassType<Byte>(TypeCategory.NUMERIC,Byte.class, byte.class);
public static final ClassType<Character> CHAR = new ClassType<Character>(TypeCategory.COMPARABLE,Character.class, char.class);
public static final ClassType<Collection> COLLECTION = new ClassType<Collection>(TypeCategory.COLLECTION, Collection.class, OBJECT);
public static final ClassType<Double> DOUBLE = new ClassType<Double>(TypeCategory.NUMERIC,Double.class, double.class);
public static final ClassType<Float> FLOAT = new ClassType<Float>(TypeCategory.NUMERIC,Float.class, float.class);
public static final ClassType<Integer> INT = new ClassType<Integer>(TypeCategory.NUMERIC,Integer.class, int.class);
public static final ClassType<Iterable> ITERABLE = new ClassType<Iterable>(TypeCategory.SIMPLE, Iterable.class, OBJECT);
public static final ClassType<List> LIST = new ClassType<List>(TypeCategory.LIST, List.class, OBJECT);
public static final ClassType<Locale> LOCALE = new ClassType<Locale>(TypeCategory.SIMPLE, Locale.class);
public static final ClassType<Long> LONG = new ClassType<Long>(TypeCategory.NUMERIC,Long.class, long.class);
public static final ClassType<Map> MAP = new ClassType<Map>(TypeCategory.MAP, Map.class, OBJECT, OBJECT);
public static final ClassType<Set> SET = new ClassType<Set>(TypeCategory.SET, Set.class, OBJECT);
public static final ClassType<Short> SHORT = new ClassType<Short>(TypeCategory.NUMERIC,Short.class, short.class);
public static final ClassType<String> STRING = new ClassType<String>(TypeCategory.STRING,String.class);
public static final ClassType<URI> URI = new ClassType<URI>(TypeCategory.COMPARABLE,URI.class);
private Types(){}
}

View File

@ -0,0 +1,13 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
@DefaultAnnotation( { Nonnull.class })
package com.mysema.codegen.model;
import javax.annotation.Nonnull;
import edu.umd.cs.findbugs.annotations.DefaultAnnotation;

View File

@ -0,0 +1,16 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
/**
* Alias functionality
*/
@DefaultAnnotation( { Nonnull.class })
package com.mysema.codegen;
import javax.annotation.Nonnull;
import edu.umd.cs.findbugs.annotations.DefaultAnnotation;

View File

@ -3,7 +3,7 @@
* All rights reserved.
*
*/
package com.mysema.codegen;
package com.mysema.codegen.support;
import java.util.Collection;
import java.util.Collections;
@ -24,8 +24,16 @@ public final class ClassUtils {
public static String getName(Class<?> cl, Set<String> packages, Set<String> classes) {
if (cl.isArray()) {
return getName(cl.getComponentType(), packages, classes) + "[]";
} else if (cl.getPackage() == null || packages.contains(cl.getPackage().getName()) || classes.contains(cl.getName())) {
return cl.getSimpleName().replace('$', '.');
} else if (cl.getPackage() == null
|| cl.getPackage().getName().equals("java.lang")
|| packages.contains(cl.getPackage().getName())
|| classes.contains(cl.getName())) {
if (cl.getPackage() != null){
String localName = cl.getName().substring(cl.getPackage().getName().length()+1);
return localName.replace('$', '.');
}else{
return cl.getSimpleName().replace('$', '.');
}
} else {
return cl.getName().replace('$', '.');
}

View File

@ -0,0 +1,13 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
@DefaultAnnotation( { Nonnull.class })
package com.mysema.codegen.support;
import javax.annotation.Nonnull;
import edu.umd.cs.findbugs.annotations.DefaultAnnotation;

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen;
import static org.junit.Assert.assertEquals;

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen;
import static org.junit.Assert.*;
@ -9,14 +14,19 @@ import java.util.List;
import org.junit.Test;
import com.mysema.codegen.model.ClassType;
import com.mysema.codegen.model.Type;
import com.mysema.codegen.model.TypeCategory;
public class ComplexEvaluationTest {
private EvaluatorFactory factory = new EvaluatorFactory((URLClassLoader) getClass().getClassLoader());
@Test
@SuppressWarnings("unchecked")
public void testComplex(){ClassType<String> stringType = new ClassType<String>(String.class);
Type<List> resultType = new ClassType<List>(List.class, stringType);
public void testComplex(){ClassType<String> stringType = new ClassType<String>(TypeCategory.STRING,String.class);
ClassType<List> resultType = new ClassType<List>(TypeCategory.LIST,List.class, stringType);
StringBuilder source = new StringBuilder();
source.append("java.util.List<String> rv = new java.util.ArrayList<String>();\n");
source.append("for (String a : a_){\n");
@ -30,7 +40,7 @@ public class ComplexEvaluationTest {
Evaluator<List> evaluator = factory.createEvaluator(
source.toString(),
List.class,
resultType,
new String[]{"a_","b_"},
new Type[]{resultType, resultType},
new Class[]{List.class,List.class},

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen;
import static org.junit.Assert.assertEquals;

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen;
import static org.junit.Assert.*;

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen;
import java.io.File;

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen;
import static java.lang.annotation.ElementType.TYPE;

View File

@ -1,3 +1,8 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen;
import static java.lang.annotation.ElementType.TYPE;

View File

@ -0,0 +1,22 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen.model;
import static org.junit.Assert.*;
import org.junit.Test;
public class TypeCategoryTest {
@Test
public void testIsSubCategoryOf() {
assertTrue(TypeCategory.BOOLEAN.isSubCategoryOf(TypeCategory.COMPARABLE));
assertTrue(TypeCategory.STRING.isSubCategoryOf(TypeCategory.COMPARABLE));
assertTrue(TypeCategory.NUMERIC.isSubCategoryOf(TypeCategory.COMPARABLE));
assertTrue(TypeCategory.COMPARABLE.isSubCategoryOf(TypeCategory.SIMPLE));
}
}

View File

@ -0,0 +1,169 @@
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen.model;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.Collections;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import org.junit.Test;
public class TypeTest {
private Set<String> emptyStrings = Collections.<String>emptySet();
private ClassType<Locale> locale = new ClassType<Locale>(TypeCategory.SIMPLE,Locale.class);
private Type locale2 = new SimpleType(locale);
private Type stringList = new ClassType<List>(TypeCategory.LIST, List.class, Types.STRING);
private Type stringList2 = new SimpleType(Types.LIST, Types.STRING);
private Type stringMap = new ClassType<Map>(TypeCategory.MAP, Map.class, Types.STRING, Types.STRING);
private Type stringMap2 = new SimpleType(Types.MAP, Types.STRING, Types.STRING);
@Test
public void testEquals(){
assertEquals(locale, locale2);
assertEquals(locale2, locale);
assertEquals(stringList, stringList2);
assertEquals(stringList2, stringList);
}
@Test
public void testHashcode(){
assertEquals(locale.hashCode(), locale2.hashCode());
assertEquals(stringList.hashCode(), stringList2.hashCode());
}
@Test
public void testGetGenericNameBoolean() {
assertEquals("java.util.Locale",locale.getGenericName(true));
assertEquals("java.util.Locale",locale2.getGenericName(true));
assertEquals("java.util.List<String>",stringList.getGenericName(true));
assertEquals("java.util.List<String>",stringList2.getGenericName(true));
assertEquals("java.util.Map<String,String>", stringMap.getGenericName(true));
assertEquals("java.util.Map<String,String>", stringMap2.getGenericName(true));
}
@Test
public void testGetRawName() {
assertEquals("java.util.Locale",locale.getRawName(emptyStrings,emptyStrings));
assertEquals("java.util.Locale",locale2.getRawName(emptyStrings,emptyStrings));
assertEquals("java.util.List",stringList.getRawName(emptyStrings,emptyStrings));
assertEquals("java.util.List",stringList2.getRawName(emptyStrings,emptyStrings));
}
@Test
public void testGetGenericNameBooleanSetOfStringSetOfString() {
assertEquals("java.util.Locale",locale.getGenericName(true, emptyStrings, emptyStrings));
assertEquals("java.util.Locale",locale2.getGenericName(true, emptyStrings, emptyStrings));
assertEquals("java.util.List<String>",stringList.getGenericName(true,emptyStrings,emptyStrings));
assertEquals("java.util.List<String>",stringList2.getGenericName(true,emptyStrings,emptyStrings));
}
@Test
public void testGetFullName() {
assertEquals("java.util.Locale",locale.getFullName());
assertEquals("java.util.Locale",locale2.getFullName());
assertEquals("java.util.List",stringList.getFullName());
assertEquals("java.util.List",stringList2.getFullName());
}
@Test
public void testGetPackageName() {
assertEquals("java.util",locale.getPackageName());
assertEquals("java.util",locale2.getPackageName());
assertEquals("java.util",stringList.getPackageName());
assertEquals("java.util",stringList2.getPackageName());
}
@Test
public void testGetParameters() {
assertEquals(Collections.emptyList(), locale.getParameters());
assertEquals(Collections.emptyList(), locale2.getParameters());
assertEquals(Collections.singletonList(Types.STRING), stringList.getParameters());
assertEquals(Collections.singletonList(Types.STRING), stringList2.getParameters());
}
@Test
public void testGetSimpleName() {
assertEquals("Locale",locale.getSimpleName());
assertEquals("Locale",locale2.getSimpleName());
assertEquals("List",stringList.getSimpleName());
assertEquals("List",stringList2.getSimpleName());
}
@Test
public void testGetJavaClass() {
assertEquals(Locale.class,locale.getJavaClass());
}
@Test
public void testIsFinal() {
assertTrue(locale.isFinal());
assertTrue(locale2.isFinal());
assertFalse(stringList.isFinal());
}
@Test
public void testIsPrimitive() {
assertFalse(locale.isPrimitive());
assertFalse(locale2.isPrimitive());
assertFalse(stringList.isPrimitive());
assertFalse(stringList2.isPrimitive());
}
@Test
public void testGetCategory() {
assertEquals(TypeCategory.SIMPLE, locale.getCategory());
assertEquals(TypeCategory.SIMPLE, locale2.getCategory());
assertEquals(TypeCategory.LIST, stringList.getCategory());
assertEquals(TypeCategory.LIST, stringList2.getCategory());
}
@Test
public void testAs() {
assertEquals(TypeCategory.SIMPLE, stringList.as(TypeCategory.SIMPLE).getCategory());
assertEquals(TypeCategory.SIMPLE, stringList2.as(TypeCategory.SIMPLE).getCategory());
}
@Test
public void testGetPrimitiveName() {
assertNull(locale.getPrimitiveName());
assertNull(locale2.getPrimitiveName());
assertNull(stringList.getPrimitiveName());
assertNull(stringList2.getPrimitiveName());
}
@Test
public void testToString() {
assertEquals("java.util.Locale",locale.toString());
assertEquals("java.util.Locale",locale2.toString());
assertEquals("java.util.List<String>",stringList.toString());
assertEquals("java.util.List<String>",stringList2.toString());
}
@Test
public void testAsArrayType() {
assertEquals("java.util.Locale[]", locale.asArrayType().getFullName());
assertEquals(TypeCategory.ARRAY, locale.asArrayType().getCategory());
assertEquals("java.util.Locale[]", locale2.asArrayType().getFullName());
assertEquals(TypeCategory.ARRAY, locale2.asArrayType().getCategory());
assertEquals("java.util.List[]", stringList.asArrayType().getFullName());
assertEquals("java.util.List[]", stringList2.asArrayType().getFullName());
}
}

View File

@ -1,4 +1,9 @@
package com.mysema.codegen;
/*
* Copyright (c) 2010 Mysema Ltd.
* All rights reserved.
*
*/
package com.mysema.codegen.support;
import static org.junit.Assert.assertEquals;