diff --git a/AndroidAnnotations/androidannotations/src/main/java/com/sun/codemodel/JSuperWildcard.java b/AndroidAnnotations/androidannotations/src/main/java/com/sun/codemodel/JSuperWildcard.java
new file mode 100644
index 0000000000..e81ed86030
--- /dev/null
+++ b/AndroidAnnotations/androidannotations/src/main/java/com/sun/codemodel/JSuperWildcard.java
@@ -0,0 +1,76 @@
+package com.sun.codemodel;
+
+import java.util.Iterator;
+import java.util.List;
+
+// TODO : At his time (01/2013), it is not possible to handle the
+// super bound because code model does not offer a way to model
+// statement like " ? super X"
+// (see http://java.net/jira/browse/CODEMODEL-11)
+//
+// This class is a hack against it.
+// So, if it will be fixed in code model - just remove this
+public class JSuperWildcard extends JClass {
+
+ private final JClass bound;
+
+ public JSuperWildcard(JClass bound) {
+ super(bound.owner());
+ this.bound = bound;
+ }
+
+ public String name() {
+ return "? super "+ bound.name();
+ }
+
+ public String fullName() {
+ return "? super "+ bound.fullName();
+ }
+
+ public JPackage _package() {
+ return null;
+ }
+
+ /**
+ * Returns the class bound of this variable.
+ *
+ *
+ * If no bound is given, this method returns {@link Object}.
+ */
+ public JClass _extends() {
+ if(bound !=null)
+ return bound;
+ else
+ return owner().ref(Object.class);
+ }
+
+ /**
+ * Returns the interface bounds of this variable.
+ */
+ public Iterator _implements() {
+ return bound._implements();
+ }
+
+ public boolean isInterface() {
+ return false;
+ }
+
+ public boolean isAbstract() {
+ return false;
+ }
+
+ protected JClass substituteParams(JTypeVar[] variables, List bindings) {
+ JClass nb = bound.substituteParams(variables,bindings);
+ if(nb== bound)
+ return this;
+ else
+ return nb.wildcard();
+ }
+
+ public void generate(JFormatter f) {
+ if(bound._extends()==null)
+ f.p("?"); // instead of "? extends Object"
+ else
+ f.p("? super").g(bound);
+ }
+}
diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/BeanHandler.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/BeanHandler.java
index e41320009a..6cb75dccd3 100644
--- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/BeanHandler.java
+++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/BeanHandler.java
@@ -22,6 +22,7 @@
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.Element;
import javax.lang.model.type.TypeMirror;
+import javax.lang.model.util.Types;
import org.androidannotations.annotations.Bean;
import org.androidannotations.annotations.EBean;
@@ -60,6 +61,7 @@ public void process(Element element, EComponentHolder holder) throws Exception {
TypeMirror elementType = annotationHelper.extractAnnotationClassParameter(element);
if (elementType == null) {
elementType = element.asType();
+ elementType = holder.processingEnvironment().getTypeUtils().erasure(elementType);
}
String fieldName = element.getSimpleName().toString();
diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/APTCodeModelHelper.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/APTCodeModelHelper.java
index c99c7abc5f..a120b4f023 100644
--- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/APTCodeModelHelper.java
+++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/APTCodeModelHelper.java
@@ -18,7 +18,11 @@
import java.io.StringWriter;
import java.lang.reflect.Field;
import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
import java.util.List;
+import java.util.Map;
import javax.lang.model.element.Element;
import javax.lang.model.element.ExecutableElement;
@@ -31,6 +35,7 @@
import javax.lang.model.type.TypeMirror;
import javax.lang.model.type.WildcardType;
import javax.lang.model.util.ElementFilter;
+import javax.lang.model.util.Types;
import org.androidannotations.holder.EComponentHolder;
import org.androidannotations.holder.GeneratedClassHolder;
@@ -47,12 +52,17 @@
import com.sun.codemodel.JMethod;
import com.sun.codemodel.JMod;
import com.sun.codemodel.JStatement;
+import com.sun.codemodel.JSuperWildcard;
import com.sun.codemodel.JType;
import com.sun.codemodel.JVar;
public class APTCodeModelHelper {
public JClass typeMirrorToJClass(TypeMirror type, GeneratedClassHolder holder) {
+ return typeMirrorToJClass(type, holder, Collections.emptyMap());
+ }
+
+ private JClass typeMirrorToJClass(TypeMirror type, GeneratedClassHolder holder, Map substitute) {
if (type instanceof DeclaredType) {
DeclaredType declaredType = (DeclaredType) type;
@@ -65,7 +75,7 @@ public JClass typeMirrorToJClass(TypeMirror type, GeneratedClassHolder holder) {
List typeArgumentJClasses = new ArrayList();
for (TypeMirror typeArgument : typeArguments) {
- typeArgumentJClasses.add(typeMirrorToJClass(typeArgument, holder));
+ typeArgumentJClasses.add(typeMirrorToJClass(typeArgument, holder, substitute));
}
if (typeArgumentJClasses.size() > 0) {
declaredClass = declaredClass.narrow(typeArgumentJClasses);
@@ -73,30 +83,43 @@ public JClass typeMirrorToJClass(TypeMirror type, GeneratedClassHolder holder) {
return declaredClass;
} else if (type instanceof WildcardType) {
- // TODO : At his time (01/2013), it is not possible to handle the
- // super bound because code model does not offer a way to model
- // statement like " ? super X"
- // (see http://java.net/jira/browse/CODEMODEL-11)
WildcardType wildcardType = (WildcardType) type;
+ TypeMirror bound = wildcardType.getExtendsBound();
+ if (bound == null) {
+ bound = wildcardType.getSuperBound();
+ if (bound == null) {
+ return holder.classes().OBJECT.wildcard();
+ }
+ return superWildcard(typeMirrorToJClass(bound, holder, substitute));
+ }
+
TypeMirror extendsBound = wildcardType.getExtendsBound();
if (extendsBound == null) {
return holder.classes().OBJECT.wildcard();
} else {
- return typeMirrorToJClass(extendsBound, holder).wildcard();
+ return typeMirrorToJClass(extendsBound, holder, substitute).wildcard();
}
} else if (type instanceof ArrayType) {
ArrayType arrayType = (ArrayType) type;
- JClass refClass = typeMirrorToJClass(arrayType.getComponentType(), holder);
+ JClass refClass = typeMirrorToJClass(arrayType.getComponentType(), holder, substitute);
return refClass.array();
} else {
+ TypeMirror substituted = substitute.get(type.toString());
+ if (substituted != null && type != substituted) {
+ return typeMirrorToJClass(substituted, holder, substitute);
+ }
return holder.refClass(type.toString());
}
}
+ private JClass superWildcard(final JClass bound) {
+ return new JSuperWildcard(bound);
+ }
+
public static class Parameter {
public final String name;
public final JClass jClass;
@@ -107,15 +130,67 @@ public Parameter(String name, JClass jClass) {
}
}
+ private Map getActualTypes(Types typeUtils, DeclaredType baseClass, TypeMirror annotatedClass) {
+ List superTypes = new ArrayList();
+ superTypes.add(annotatedClass);
+ while(!superTypes.isEmpty()) {
+ TypeMirror x = superTypes.remove(0);
+ if (typeUtils.isSameType(typeUtils.erasure(x), typeUtils.erasure(baseClass))) {
+ DeclaredType type = (DeclaredType) x;
+ Map actualTypes = new HashMap();
+ for (int i = 0; i < type.getTypeArguments().size(); i++) {
+ TypeMirror actualArg = type.getTypeArguments().get(i);
+ TypeMirror formalArg = baseClass.getTypeArguments().get(i);
+ if (!typeUtils.isSameType(actualArg, formalArg)) {
+ actualTypes.put(formalArg.toString(), actualArg);
+ }
+ }
+ return actualTypes;
+ }
+ superTypes.addAll(typeUtils.directSupertypes(x));
+ }
+ return Collections.emptyMap();
+ }
+
+ public JClass typeBoundsToJClass(GeneratedClassHolder holder, List extends TypeMirror> bounds) {
+ return typeBoundsToJClass(holder, bounds, Collections.emptyMap());
+ }
+
+ private JClass typeBoundsToJClass(GeneratedClassHolder holder, List extends TypeMirror> bounds, Map actualTypes) {
+ if (bounds.isEmpty()) {
+ return holder.classes().OBJECT;
+ } else {
+ //TODO resolve bounds
+ return typeMirrorToJClass(bounds.get(0), holder, actualTypes);
+ }
+ }
+
public JMethod overrideAnnotatedMethod(ExecutableElement executableElement, GeneratedClassHolder holder) {
+ TypeMirror annotatedClass = holder.getAnnotatedElement().asType();
+ DeclaredType baseClass = (DeclaredType) executableElement.getEnclosingElement().asType();
+
+ Types typeUtils = holder.processingEnvironment().getTypeUtils();
+
+ Map actualTypes = getActualTypes(typeUtils, baseClass, annotatedClass);
+ Map methodTypes = new LinkedHashMap();
+
+ for (TypeParameterElement typeParameter : executableElement.getTypeParameters()) {
+ List extends TypeMirror> bounds = typeParameter.getBounds();
+ JClass jClassBounds = typeBoundsToJClass(holder, bounds, actualTypes);
+ methodTypes.put(typeParameter.toString(), jClassBounds);
+ }
+
+ actualTypes.keySet().removeAll(methodTypes.keySet());
String methodName = executableElement.getSimpleName().toString();
- JClass returnType = typeMirrorToJClass(executableElement.getReturnType(), holder);
+ JClass returnType = typeMirrorToJClass(executableElement.getReturnType(), holder, actualTypes);
List parameters = new ArrayList();
- for (VariableElement parameter : executableElement.getParameters()) {
- String parameterName = parameter.getSimpleName().toString();
- JClass parameterClass = typeMirrorToJClass(parameter.asType(), holder);
+ for (int i = 0; i < executableElement.getParameters().size(); i++) {
+ VariableElement parameter = executableElement.getParameters().get(i);
+
+ String parameterName = parameter.getSimpleName().toString();
+ JClass parameterClass = typeMirrorToJClass(parameter.asType(), holder, actualTypes);
parameters.add(new Parameter(parameterName, parameterClass));
}
@@ -128,32 +203,19 @@ public JMethod overrideAnnotatedMethod(ExecutableElement executableElement, Gene
JMethod method = holder.getGeneratedClass().method(JMod.PUBLIC, returnType, methodName);
method.annotate(Override.class);
- for (VariableElement parameter : executableElement.getParameters()) {
- String parameterName = parameter.getSimpleName().toString();
- JClass parameterClass = typeMirrorToJClass(parameter.asType(), holder);
- method.param(JMod.FINAL, parameterClass, parameterName);
- }
+ for (Map.Entry typeDeclaration : methodTypes.entrySet()) {
+ method.generify(typeDeclaration.getKey(), typeDeclaration.getValue());
+ }
+
+ for (Parameter parameter : parameters) {
+ method.param(JMod.FINAL, parameter.jClass, parameter.name);
+ }
for (TypeMirror superThrownType : executableElement.getThrownTypes()) {
- JClass thrownType = typeMirrorToJClass(superThrownType, holder);
+ JClass thrownType = typeMirrorToJClass(superThrownType, holder, actualTypes);
method._throws(thrownType);
}
- for (TypeParameterElement typeParameter : executableElement.getTypeParameters()) {
- List extends TypeMirror> bounds = typeParameter.getBounds();
-
- JClass jClassBounds;
- if (bounds.isEmpty()) {
- jClassBounds = holder.classes().OBJECT;
- } else {
- // Currently Codemodel can't generate generics with multiple
- // classes like this .
- // So we only take the first class
- jClassBounds = typeMirrorToJClass(bounds.get(0), holder);
- }
- method.generify(typeParameter.toString(), jClassBounds);
- }
-
callSuperMethod(method, holder, method.body());
return method;
diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/BaseGeneratedClassHolder.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/BaseGeneratedClassHolder.java
index 91880f0b29..af9fc6e21e 100644
--- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/BaseGeneratedClassHolder.java
+++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/BaseGeneratedClassHolder.java
@@ -20,8 +20,14 @@
import javax.annotation.processing.ProcessingEnvironment;
import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.TypeParameterElement;
+import javax.lang.model.util.Elements;
+import javax.lang.model.util.Types;
+import org.androidannotations.helper.APTCodeModelHelper;
import org.androidannotations.helper.ModelConstants;
+import org.androidannotations.logger.Logger;
+import org.androidannotations.logger.LoggerFactory;
import org.androidannotations.process.ProcessHolder;
import com.sun.codemodel.ClassType;
@@ -34,18 +40,25 @@ public abstract class BaseGeneratedClassHolder implements GeneratedClassHolder {
protected final ProcessHolder processHolder;
protected JDefinedClass generatedClass;
protected final TypeElement annotatedElement;
+ protected final APTCodeModelHelper codeModelHelper;
public BaseGeneratedClassHolder(ProcessHolder processHolder, TypeElement annotatedElement) throws Exception {
this.processHolder = processHolder;
this.annotatedElement = annotatedElement;
+ this.codeModelHelper = new APTCodeModelHelper();
setGeneratedClass();
}
protected void setGeneratedClass() throws Exception {
String annotatedComponentQualifiedName = annotatedElement.getQualifiedName().toString();
- String subComponentQualifiedName = annotatedComponentQualifiedName + ModelConstants.GENERATION_SUFFIX;
- JClass annotatedComponent = codeModel().directClass(annotatedComponentQualifiedName);
+ String subComponentQualifiedName = annotatedComponentQualifiedName + ModelConstants.GENERATION_SUFFIX;
+ JClass annotatedComponent = codeModel().directClass(annotatedElement.asType().toString());
+
generatedClass = codeModel()._class(PUBLIC | FINAL, subComponentQualifiedName, ClassType.CLASS);
+ for (TypeParameterElement typeParam : annotatedElement.getTypeParameters()) {
+ JClass bound = codeModelHelper.typeBoundsToJClass(this, typeParam.getBounds());
+ generatedClass.generify(typeParam.getSimpleName().toString(), bound);
+ }
generatedClass._extends(annotatedComponent);
}
diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/EComponentWithViewSupportHolder.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/EComponentWithViewSupportHolder.java
index 55b84f58d8..333d77af29 100644
--- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/EComponentWithViewSupportHolder.java
+++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/EComponentWithViewSupportHolder.java
@@ -32,7 +32,6 @@
import org.androidannotations.api.view.HasViews;
import org.androidannotations.api.view.OnViewChangedListener;
import org.androidannotations.api.view.OnViewChangedNotifier;
-import org.androidannotations.helper.APTCodeModelHelper;
import org.androidannotations.helper.ViewNotifierHelper;
import org.androidannotations.process.ProcessHolder;
@@ -47,7 +46,6 @@
public abstract class EComponentWithViewSupportHolder extends EComponentHolder {
- private APTCodeModelHelper codeModelHelper;
protected ViewNotifierHelper viewNotifierHelper;
private JBlock onViewChangedBody;
private JVar onViewChangedHasViewsParam;
@@ -60,7 +58,6 @@ public abstract class EComponentWithViewSupportHolder extends EComponentHolder {
public EComponentWithViewSupportHolder(ProcessHolder processHolder, TypeElement annotatedElement) throws Exception {
super(processHolder, annotatedElement);
- codeModelHelper = new APTCodeModelHelper();
viewNotifierHelper = new ViewNotifierHelper(this);
}
diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/EIntentServiceHolder.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/EIntentServiceHolder.java
index 488f291129..e0bd9970c2 100644
--- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/EIntentServiceHolder.java
+++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/EIntentServiceHolder.java
@@ -19,7 +19,6 @@
import javax.lang.model.element.TypeElement;
-import org.androidannotations.helper.APTCodeModelHelper;
import org.androidannotations.helper.AndroidManifest;
import org.androidannotations.process.ProcessHolder;
@@ -31,8 +30,6 @@
public class EIntentServiceHolder extends EServiceHolder {
- private APTCodeModelHelper codeModelHelper = new APTCodeModelHelper();
-
private JVar onHandleIntentIntent;
private JMethod onHandleIntentMethod;
private JBlock onHandleIntentBody;
diff --git a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/RestHolder.java b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/RestHolder.java
index e124153654..0d357eb880 100644
--- a/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/RestHolder.java
+++ b/AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/holder/RestHolder.java
@@ -29,7 +29,6 @@
import javax.lang.model.type.TypeKind;
import org.androidannotations.api.rest.RestErrorHandler;
-import org.androidannotations.helper.APTCodeModelHelper;
import org.androidannotations.helper.CanonicalNameConstants;
import org.androidannotations.helper.ModelConstants;
import org.androidannotations.process.ProcessHolder;
@@ -44,8 +43,6 @@
public class RestHolder extends BaseGeneratedClassHolder {
- private APTCodeModelHelper codeModelHelper;
-
private JMethod init;
private JFieldVar rootUrlField;
private JFieldVar restTemplateField;
@@ -56,7 +53,6 @@ public class RestHolder extends BaseGeneratedClassHolder {
public RestHolder(ProcessHolder processHolder, TypeElement annotatedElement) throws Exception {
super(processHolder, annotatedElement);
- codeModelHelper = new APTCodeModelHelper();
implementMethods();
}
diff --git a/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/ebean/EBeanTest.java b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/ebean/EBeanTest.java
index 3a95fcc88c..3a175116b1 100644
--- a/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/ebean/EBeanTest.java
+++ b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/ebean/EBeanTest.java
@@ -30,7 +30,11 @@ public void setup() {
@Test
public void activity_subclass_in_manifest_compiles() {
- assertCompilationSuccessful(compileFiles(SomeActivity.class, SomeImplementation.class));
- }
+ assertCompilationSuccessful(compileFiles(
+ SomeActivity.class,
+ SomeImplementation.class,
+ SomeGenericBean.class,
+ SomeGenericBeanExt.class));
+ }
}
diff --git a/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/ebean/SomeActivity.java b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/ebean/SomeActivity.java
index d00cf5ab3c..f0e8903e0c 100644
--- a/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/ebean/SomeActivity.java
+++ b/AndroidAnnotations/androidannotations/src/test/java/org/androidannotations/ebean/SomeActivity.java
@@ -28,4 +28,7 @@ public class SomeActivity extends Activity {
@Bean(SomeImplementation.class)
SomeInterface someInterface;
+ @Bean
+ SomeGenericBean