Skip to content

Commit bfade7e

Browse files
committed
* Validates that ORMLite framework is in the classpath * Validation of ORMLite annotations is more robust (based on processor tools, not String parsing) * Generated code doesn't repeat the connectionSource injection block * Generated code looks better * No need to inject context, we already have this
1 parent e301bee commit bfade7e

6 files changed

Lines changed: 85 additions & 99 deletions

File tree

‎AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/AndroidAnnotationProcessor.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -522,7 +522,7 @@ private ModelProcessor buildModelProcessor(IRClass rClass, AndroidSystemServices
522522
modelProcessor.register(new NoTitleProcessor());
523523
modelProcessor.register(new FullscreenProcessor());
524524
modelProcessor.register(new RestServiceProcessor());
525-
modelProcessor.register(new OrmLiteDaoProcessor());
525+
modelProcessor.register(new OrmLiteDaoProcessor(processingEnv));
526526
modelProcessor.register(new RootContextProcessor());
527527
modelProcessor.register(new BeanProcessor(processingEnv));
528528
modelProcessor.register(new AfterViewsProcessor());

‎AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/helper/AnnotationHelper.java‎

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
package com.googlecode.androidannotations.helper;
1717

1818
import java.lang.annotation.Annotation;
19+
import java.lang.reflect.InvocationTargetException;
1920
import java.lang.reflect.Method;
2021
import java.util.ArrayList;
2122
import java.util.List;
@@ -26,6 +27,7 @@
2627
import javax.lang.model.element.Modifier;
2728
import javax.lang.model.element.NestingKind;
2829
import javax.lang.model.element.TypeElement;
30+
import javax.lang.model.type.MirroredTypeException;
2931
import javax.lang.model.type.TypeMirror;
3032
import javax.lang.model.util.Elements;
3133
import javax.lang.model.util.Types;
@@ -271,11 +273,17 @@ public int[] extractAnnotationResIdValueParameter(Element element, Class<? exten
271273
@SuppressWarnings("unchecked")
272274
public <T> T extractAnnotationParameter(Element element, Class<? extends Annotation> target, String methodName) {
273275
Annotation annotation = element.getAnnotation(target);
274-
275276
Method method;
276277
try {
277278
method = annotation.getClass().getMethod(methodName);
278279
return (T) method.invoke(annotation);
280+
} catch (InvocationTargetException e) {
281+
if (e.getCause() instanceof MirroredTypeException) {
282+
MirroredTypeException cause = (MirroredTypeException) e.getCause();
283+
return (T) cause.getTypeMirror();
284+
} else {
285+
throw new RuntimeException(e);
286+
}
279287
} catch (Exception e) {
280288
throw new RuntimeException(e);
281289
}

‎AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/helper/ValidatorHelper.java‎

Lines changed: 24 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
import javax.lang.model.type.ArrayType;
3636
import javax.lang.model.type.DeclaredType;
3737
import javax.lang.model.type.ErrorType;
38-
import javax.lang.model.type.MirroredTypeException;
3938
import javax.lang.model.type.TypeKind;
4039
import javax.lang.model.type.TypeMirror;
4140
import javax.lang.model.util.ElementFilter;
@@ -52,7 +51,6 @@
5251
import com.googlecode.androidannotations.annotations.EService;
5352
import com.googlecode.androidannotations.annotations.EView;
5453
import com.googlecode.androidannotations.annotations.EViewGroup;
55-
import com.googlecode.androidannotations.annotations.OrmLiteDao;
5654
import com.googlecode.androidannotations.annotations.Trace;
5755
import com.googlecode.androidannotations.annotations.ViewById;
5856
import com.googlecode.androidannotations.annotations.rest.Delete;
@@ -555,69 +553,32 @@ public void extendsContext(Element element, IsValid valid) {
555553
extendsType(element, CanonicalNameConstants.CONTEXT, valid);
556554
}
557555

558-
public void extendsOrmLiteDao(Element element, IsValid valid) {
559-
TypeMirror typeMirror = element.asType();
560-
String typeClass = typeMirror.toString().split("<")[0];
561-
boolean isValid = false;
556+
public void extendsOrmLiteDaoWithValidModelParameter(Element element, IsValid valid) {
557+
TypeMirror elementType = element.asType();
562558

563-
// get model annotation class value
564-
OrmLiteDao annotation = element.getAnnotation(OrmLiteDao.class);
565-
TypeMirror modelObjectTypeMirror = null;
566-
try {
567-
annotation.model();
568-
} catch (MirroredTypeException mte) {
569-
modelObjectTypeMirror = mte.getTypeMirror();
570-
}
559+
TypeMirror modelTypeMirror = annotationHelper.extractAnnotationParameter(element, "model");
571560

572-
// first case : element is a Dao
573-
TypeMirror daoTypeMirror = annotationHelper.typeElementFromQualifiedName(CanonicalNameConstants.DAO).asType();
574-
String daoTypeClass = daoTypeMirror.toString().split("<")[0];
561+
TypeElement daoTypeElement = annotationHelper.typeElementFromQualifiedName(CanonicalNameConstants.DAO);
562+
if (daoTypeElement != null) {
575563

576-
if (typeClass != null && typeClass.equalsIgnoreCase(daoTypeClass)) {
577-
isValid = hasDaoAnObjectModelParameterizedType(typeMirror, modelObjectTypeMirror);
578-
}
579-
// second case : element inherits from Dao
580-
else {
581-
List<? extends TypeMirror> supertypes = annotationHelper.getTypeUtils().directSupertypes(typeMirror);
582-
for (int i = supertypes.size(); i-- > 0;) {
583-
if (hasDaoAnObjectModelParameterizedType(supertypes.get(i), modelObjectTypeMirror)) {
584-
isValid = true;
585-
break;
586-
}
587-
}
588-
}
589-
590-
if (!isValid) {
591-
valid.invalidate();
592-
annotationHelper.printAnnotationError(element, "%s can only be used on an element that is a Dao or inherits from a Dao and has the parameterized type : " + modelObjectTypeMirror.toString());
593-
}
594-
}
564+
TypeMirror wildcardType = annotationHelper.getTypeUtils().getWildcardType(null, null);
565+
DeclaredType daoParameterizedType = annotationHelper.getTypeUtils().getDeclaredType(daoTypeElement, modelTypeMirror, wildcardType);
595566

596-
private boolean hasDaoAnObjectModelParameterizedType(TypeMirror daoType, TypeMirror objectModelType) {
597-
DeclaredType declaredType = (DeclaredType) daoType;
598-
List<? extends TypeMirror> argTypes = declaredType.getTypeArguments();
599-
if (argTypes.size() > 0) {
600-
if (argTypes.get(0).equals(objectModelType)) {
601-
return true;
567+
// Checks that elementType extends Dao<ModelType, ?>
568+
if (!annotationHelper.isSubtype(elementType, daoParameterizedType)) {
569+
valid.invalidate();
570+
annotationHelper.printAnnotationError(element, "%s can only be used on an element that extends " + daoParameterizedType.toString());
602571
}
603572
}
604-
return false;
605573
}
606574

607575
public void hasASqlLiteOpenHelperParameterizedType(Element element, IsValid valid) {
608-
// get helper annotation class value
609-
OrmLiteDao annotation = element.getAnnotation(OrmLiteDao.class);
610-
TypeMirror helperType = null;
611-
try {
612-
annotation.helper();
613-
} catch (MirroredTypeException mte) {
614-
helperType = mte.getTypeMirror();
615-
}
576+
TypeMirror helperType = annotationHelper.extractAnnotationParameter(element, "helper");
616577

617578
TypeMirror openHelperType = annotationHelper.typeElementFromQualifiedName(CanonicalNameConstants.SQLLITE_OPEN_HELPER).asType();
618-
if (!annotationHelper.getTypeUtils().isSubtype(helperType, openHelperType)) {
579+
if (!annotationHelper.isSubtype(helperType, openHelperType)) {
619580
valid.invalidate();
620-
annotationHelper.printAnnotationError(element, "helper value must inherits from : " + openHelperType.toString());
581+
annotationHelper.printAnnotationError(element, "%s helper() parameter must extend " + CanonicalNameConstants.SQLLITE_OPEN_HELPER);
621582
}
622583
}
623584

@@ -788,7 +749,16 @@ public void hasSpringAndroidJars(Element element, IsValid valid) {
788749

789750
if (elementUtils.getTypeElement(CanonicalNameConstants.REST_TEMPLATE) == null) {
790751
valid.invalidate();
791-
annotationHelper.printAnnotationError(element, "Could not find the SpringAndroid framework in the classpath, the following class is missing: org.springframework.web.client.RestTemplate");
752+
annotationHelper.printAnnotationError(element, "Could not find the SpringAndroid framework in the classpath, the following class is missing: " + CanonicalNameConstants.REST_TEMPLATE);
753+
}
754+
}
755+
756+
public void hasOrmLiteJars(Element element, IsValid valid) {
757+
Elements elementUtils = annotationHelper.getElementUtils();
758+
759+
if (elementUtils.getTypeElement(CanonicalNameConstants.DAO) == null) {
760+
valid.invalidate();
761+
annotationHelper.printAnnotationError(element, "Could not find the OrmLite framework in the classpath, the following class is missing: " + CanonicalNameConstants.DAO);
792762
}
793763
}
794764

‎AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/processing/OrmLiteDaoProcessor.java‎

Lines changed: 48 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,20 @@
2020

2121
import java.lang.annotation.Annotation;
2222

23+
import javax.annotation.processing.ProcessingEnvironment;
2324
import javax.lang.model.element.Element;
24-
import javax.lang.model.type.MirroredTypeException;
2525
import javax.lang.model.type.TypeMirror;
2626

2727
import com.googlecode.androidannotations.annotations.OrmLiteDao;
28-
import com.googlecode.androidannotations.helper.CanonicalNameConstants;
28+
import com.googlecode.androidannotations.helper.TargetAnnotationHelper;
2929
import com.googlecode.androidannotations.processing.EBeansHolder.Classes;
3030
import com.sun.codemodel.JBlock;
31+
import com.sun.codemodel.JCatchBlock;
3132
import com.sun.codemodel.JCodeModel;
32-
import com.sun.codemodel.JExpr;
3333
import com.sun.codemodel.JExpression;
3434
import com.sun.codemodel.JFieldVar;
3535
import com.sun.codemodel.JTryBlock;
36+
import com.sun.codemodel.JVar;
3637

3738
/**
3839
* This class generates the code that creates DAOs with ORMLite
@@ -41,6 +42,13 @@
4142
*/
4243
public class OrmLiteDaoProcessor implements DecoratingElementProcessor {
4344

45+
private static final String CONNECTION_SOURCE_FIELD_NAME = "connectionSource_";
46+
private TargetAnnotationHelper helper;
47+
48+
public OrmLiteDaoProcessor(ProcessingEnvironment processingEnv) {
49+
helper = new TargetAnnotationHelper(processingEnv, getTarget());
50+
}
51+
4452
@Override
4553
public Class<? extends Annotation> getTarget() {
4654
return OrmLiteDao.class;
@@ -51,51 +59,50 @@ public void process(Element element, JCodeModel codeModel, EBeanHolder holder) {
5159
Classes classes = holder.classes();
5260

5361
String fieldName = element.getSimpleName().toString();
54-
OrmLiteDao annotation = element.getAnnotation(OrmLiteDao.class);
55-
56-
// Get model object class
57-
TypeMirror modelObjectTypeMirror = null;
58-
try {
59-
annotation.model();
60-
} catch (MirroredTypeException mte) {
61-
modelObjectTypeMirror = mte.getTypeMirror();
62-
}
6362

64-
// Get database hleper class
65-
TypeMirror databaseHelperTypeMirror = null;
66-
try {
67-
annotation.helper();
68-
} catch (MirroredTypeException mte) {
69-
databaseHelperTypeMirror = mte.getTypeMirror();
70-
}
63+
TypeMirror modelObjectTypeMirror = helper.extractAnnotationParameter(element, "model");
7164

72-
JBlock methodBody = holder.init.body();
65+
TypeMirror databaseHelperTypeMirror = helper.extractAnnotationParameter(element, "helper");
7366

7467
// connection source field
75-
String connectionSourceRef = "connection_source_";
76-
try {
77-
holder.eBean.field(PRIVATE, classes.CONNECTION_SOURCE, connectionSourceRef);
78-
} catch (IllegalArgumentException e) {
79-
// connection_source_ already generated
80-
}
68+
boolean connectionSourceInjected = holder.eBean.fields().containsKey(CONNECTION_SOURCE_FIELD_NAME);
8169

82-
// context field
83-
String contextRef = "context_";
84-
JFieldVar contextField;
85-
try {
86-
contextField = holder.eBean.field(PRIVATE, classes.CONTEXT, contextRef);
87-
methodBody._if(JExpr._this()._instanceof(classes.CONTEXT))._then().assign(contextField, JExpr._this());
88-
} catch (IllegalArgumentException e) {
89-
// context_ already generated
90-
}
70+
JBlock initBody = holder.init.body();
9171

92-
// get connection source
93-
JExpression dbHelperExpr = holder.refClass(databaseHelperTypeMirror.toString()).dotclass();
94-
methodBody._if(JExpr.ref(connectionSourceRef).eq(JExpr._null()))._then().assign(ref(connectionSourceRef), holder.refClass(CanonicalNameConstants.OPEN_HELPER_MANAGER).staticInvoke("getHelper").arg(ref(contextRef)).arg(dbHelperExpr).invoke("getConnectionSource"));
72+
JFieldVar connectionSourceRef;
73+
if (connectionSourceInjected) {
74+
connectionSourceRef = holder.eBean.fields().get(CONNECTION_SOURCE_FIELD_NAME);
75+
} else {
76+
connectionSourceRef = holder.eBean.field(PRIVATE, classes.CONNECTION_SOURCE, CONNECTION_SOURCE_FIELD_NAME);
77+
78+
// get connection source
79+
JExpression dbHelperClass = holder.refClass(databaseHelperTypeMirror.toString()).dotclass();
80+
81+
initBody.assign(connectionSourceRef, //
82+
classes.OPEN_HELPER_MANAGER //
83+
.staticInvoke("getHelper") //
84+
.arg(holder.contextRef) //
85+
.arg(dbHelperClass) //
86+
.invoke("getConnectionSource"));
87+
}
9588

9689
// create dao from dao manager
97-
JTryBlock tryBlock = methodBody._try();
98-
tryBlock.body().assign(ref(fieldName), holder.refClass(CanonicalNameConstants.DAO_MANAGER).staticInvoke("createDao").arg(JExpr.ref(connectionSourceRef)).arg(holder.refClass(modelObjectTypeMirror.toString()).dotclass()));
99-
tryBlock._catch(classes.SQL_EXCEPTION).body().directStatement("android.util.Log.d(\"AndroidAnnotations\", _x.getMessage()); _x.printStackTrace();");
90+
JTryBlock tryBlock = initBody._try();
91+
92+
JExpression modelClass = holder.refClass(modelObjectTypeMirror.toString()).dotclass();
93+
tryBlock.body().assign(ref(fieldName), //
94+
classes.DAO_MANAGER //
95+
.staticInvoke("createDao") //
96+
.arg(connectionSourceRef) //
97+
.arg(modelClass));
98+
99+
JCatchBlock catchBlock = tryBlock._catch(classes.SQL_EXCEPTION);
100+
JVar exception = catchBlock.param("e");
101+
102+
catchBlock.body() //
103+
.staticInvoke(classes.LOG, "e") //
104+
.arg(holder.eBean.name()) //
105+
.arg("Could not create DAO") //
106+
.arg(exception);
100107
}
101108
}

‎AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/validation/OrmLiteDaoValidator.java‎

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,11 +46,13 @@ public boolean validate(Element element, AnnotationElements validatedElements) {
4646

4747
IsValid valid = new IsValid();
4848

49+
validatorHelper.hasOrmLiteJars(element, valid);
50+
4951
validatorHelper.enclosingElementHasEnhancedViewSupportAnnotation(element, validatedElements, valid);
5052

5153
validatorHelper.isNotPrivate(element, valid);
5254

53-
validatorHelper.extendsOrmLiteDao(element, valid);
55+
validatorHelper.extendsOrmLiteDaoWithValidModelParameter(element, valid);
5456

5557
validatorHelper.hasASqlLiteOpenHelperParameterizedType(element, valid);
5658

‎AndroidAnnotations/functional-test-1-5/src/main/java/com/googlecode/androidannotations/test15/ormlite/OrmLiteActivity.java‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,6 @@
2424

2525
@EActivity
2626
public class OrmLiteActivity extends Activity {
27-
2827
@OrmLiteDao(helper = DatabaseHelper.class, model = User.class)
2928
UserDao userDao;
3029

0 commit comments

Comments
 (0)