Skip to content
This repository was archived by the owner on Feb 26, 2023. It is now read-only.

Commit 2773a13

Browse files
committed
Merge pull request #1092 from dodgex/ReceiverAction
Conflicts: AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/InstanceStateHandler.java
2 parents 825faa4 + b974019 commit 2773a13

11 files changed

Lines changed: 535 additions & 67 deletions

File tree

Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
/**
2+
* Copyright (C) 2010-2014 eBusiness Information, Excilys Group
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed To in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package org.androidannotations.annotations;
17+
18+
import java.lang.annotation.ElementType;
19+
import java.lang.annotation.Retention;
20+
import java.lang.annotation.RetentionPolicy;
21+
import java.lang.annotation.Target;
22+
23+
/**
24+
* <p>
25+
* Should be used on a method that must respond to a specific action in an
26+
* {@link EReceiver} annotated class. The method name will be used as action
27+
* name unless the {@link #value()} field is set.
28+
* </p>
29+
* <p>
30+
* The method could contain any type or parameters.
31+
* </p>
32+
* <p>
33+
* The class MAY contain several {@link ReceiverAction} annotated methods.
34+
* </p>
35+
* <p>
36+
* You MAY use the {@link ReceiverAction.Extra} annotation on parameters to
37+
* define a different extra name.
38+
* </p>
39+
* <p>
40+
* Parameters of type {@link android.content.Intent} or
41+
* {@link android.content.Context} will get the corresponding parameter of
42+
* {@code void onReceive(Context context, Intent intent)} assigned.
43+
* </p>
44+
* <blockquote>
45+
*
46+
* Example :
47+
*
48+
* <pre>
49+
* &#064;EReceiver
50+
* public class MyIntentService extends BroadcastReceiver {
51+
*
52+
* &#064;ReceiverAction
53+
* void mySimpleAction() {
54+
* // ...
55+
* }
56+
*
57+
* &#064;ReceiverAction
58+
* void myAction(String valueString, long valueLong) {
59+
* // ...
60+
* }
61+
*
62+
* &#064;ReceiverAction
63+
* void anotherAction(@ReceiverAction.Extra(&quot;specialExtraName&quot;) String valueString, long valueLong) {
64+
* // ...
65+
* }
66+
* }
67+
* </pre>
68+
*
69+
* </blockquote>
70+
*
71+
* @see EIntentService
72+
*/
73+
@Retention(RetentionPolicy.CLASS)
74+
@Target(ElementType.METHOD)
75+
public @interface ReceiverAction {
76+
77+
/**
78+
* Define the action's name. If this field isn't set the annotated method
79+
* name will be used.
80+
*
81+
* @return the action's name
82+
*/
83+
String value() default "";
84+
85+
@Retention(RetentionPolicy.CLASS)
86+
@Target(ElementType.PARAMETER)
87+
public @interface Extra {
88+
89+
/**
90+
* Define the extra's name. If this parameter isn't set the annotated
91+
* parameter name will be used.
92+
*
93+
* @return the extra's name
94+
*/
95+
String value() default "";
96+
}
97+
}

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/AnnotationHandlers.java‎

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,6 @@
1515
*/
1616
package org.androidannotations.handler;
1717

18-
import java.util.ArrayList;
19-
import java.util.Collections;
20-
import java.util.HashSet;
21-
import java.util.List;
22-
import java.util.Set;
23-
24-
import javax.annotation.processing.ProcessingEnvironment;
25-
2618
import org.androidannotations.handler.rest.DeleteHandler;
2719
import org.androidannotations.handler.rest.GetHandler;
2820
import org.androidannotations.handler.rest.HeadHandler;
@@ -40,6 +32,13 @@
4032
import org.androidannotations.process.ProcessHolder;
4133
import org.androidannotations.rclass.IRClass;
4234

35+
import javax.annotation.processing.ProcessingEnvironment;
36+
import java.util.ArrayList;
37+
import java.util.Collections;
38+
import java.util.HashSet;
39+
import java.util.List;
40+
import java.util.Set;
41+
4342
public class AnnotationHandlers {
4443

4544
private List<AnnotationHandler<? extends GeneratedClassHolder>> annotationHandlers = new ArrayList<AnnotationHandler<? extends GeneratedClassHolder>>();
@@ -119,6 +118,8 @@ public AnnotationHandlers(ProcessingEnvironment processingEnvironment) {
119118
add(new HierarchyViewerSupportHandler(processingEnvironment));
120119
add(new WindowFeatureHandler(processingEnvironment));
121120
add(new ReceiverHandler(processingEnvironment));
121+
add(new ReceiverActionHandler(processingEnvironment));
122+
add(new ReceiverActionExtraHandler(processingEnvironment));
122123

123124
add(new IgnoredWhenDetachedHandler(processingEnvironment));
124125
/* After injection methods must be after injections */

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/BaseAnnotationHandler.java‎

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,8 @@
1515
*/
1616
package org.androidannotations.handler;
1717

18-
import javax.annotation.processing.ProcessingEnvironment;
19-
import javax.lang.model.element.Element;
20-
18+
import com.sun.codemodel.JClass;
19+
import com.sun.codemodel.JCodeModel;
2120
import org.androidannotations.helper.AndroidManifest;
2221
import org.androidannotations.helper.IdAnnotationHelper;
2322
import org.androidannotations.helper.IdValidatorHelper;
@@ -28,8 +27,8 @@
2827
import org.androidannotations.process.ProcessHolder;
2928
import org.androidannotations.rclass.IRClass;
3029

31-
import com.sun.codemodel.JClass;
32-
import com.sun.codemodel.JCodeModel;
30+
import javax.annotation.processing.ProcessingEnvironment;
31+
import javax.lang.model.element.Element;
3332

3433
public abstract class BaseAnnotationHandler<T extends GeneratedClassHolder> implements AnnotationHandler<T> {
3534

@@ -43,7 +42,7 @@ public abstract class BaseAnnotationHandler<T extends GeneratedClassHolder> impl
4342
protected ProcessHolder processHolder;
4443

4544
public BaseAnnotationHandler(Class<?> targetClass, ProcessingEnvironment processingEnvironment) {
46-
this(targetClass.getName(), processingEnvironment);
45+
this(targetClass.getCanonicalName(), processingEnvironment);
4746
}
4847

4948
public BaseAnnotationHandler(String target, ProcessingEnvironment processingEnvironment) {

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/handler/InstanceStateHandler.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ public void validate(Element element, AnnotationElements validatedElements, IsVa
5050

5151
validatorHelper.isNotPrivate(element, valid);
5252

53-
validatorHelper.canBeSavedAsInstanceState(element, valid);
53+
validatorHelper.canBePutInABundle(element, valid);
5454
}
5555

5656
@Override
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
package org.androidannotations.handler;
2+
3+
import com.sun.codemodel.JBlock;
4+
import com.sun.codemodel.JClass;
5+
import com.sun.codemodel.JExpr;
6+
import com.sun.codemodel.JExpression;
7+
import com.sun.codemodel.JFieldVar;
8+
import com.sun.codemodel.JMethod;
9+
import com.sun.codemodel.JVar;
10+
import org.androidannotations.annotations.ReceiverAction;
11+
import org.androidannotations.helper.APTCodeModelHelper;
12+
import org.androidannotations.helper.AnnotationHelper;
13+
import org.androidannotations.helper.BundleHelper;
14+
import org.androidannotations.helper.CaseHelper;
15+
import org.androidannotations.holder.EReceiverHolder;
16+
import org.androidannotations.model.AnnotationElements;
17+
import org.androidannotations.process.IsValid;
18+
19+
import javax.annotation.processing.ProcessingEnvironment;
20+
import javax.lang.model.element.Element;
21+
import javax.lang.model.element.VariableElement;
22+
23+
import static com.sun.codemodel.JExpr.lit;
24+
import static com.sun.codemodel.JMod.FINAL;
25+
import static com.sun.codemodel.JMod.PUBLIC;
26+
import static com.sun.codemodel.JMod.STATIC;
27+
28+
public class ReceiverActionExtraHandler extends BaseAnnotationHandler<EReceiverHolder> {
29+
30+
public ReceiverActionExtraHandler(ProcessingEnvironment processingEnvironment) {
31+
super(ReceiverAction.Extra.class, processingEnvironment);
32+
}
33+
34+
@Override
35+
protected void validate(Element element, AnnotationElements validatedElements, IsValid valid) {
36+
validatorHelper.enclosingMethodHasAnnotation(ReceiverAction.class, element, validatedElements, valid);
37+
38+
validatorHelper.canBePutInABundle(element, valid);
39+
}
40+
41+
@Override
42+
public void process(Element element, EReceiverHolder holder) throws Exception {
43+
// We don't do anything here.
44+
}
45+
46+
public static JVar extractedFieldInExtra(VariableElement param, JVar extras, JBlock extrasNotNullBlock, EReceiverHolder holder, APTCodeModelHelper codeModelHelper, AnnotationHelper annotationHelper) {
47+
String paramName = param.getSimpleName().toString();
48+
JClass extraParamClass = codeModelHelper.typeMirrorToJClass(param.asType(), holder);
49+
50+
ReceiverAction.Extra annotation = param.getAnnotation(ReceiverAction.Extra.class);
51+
if (annotation != null && !annotation.value().isEmpty()) {
52+
paramName = annotation.value();
53+
}
54+
55+
String extraParamName = paramName.replaceAll("\\.", "_") + "_Extra";
56+
JFieldVar paramVar = getStaticExtraField(holder, paramName);
57+
BundleHelper bundleHelper = new BundleHelper(annotationHelper, param.asType());
58+
59+
JExpression getExtraExpression = JExpr.invoke(extras, bundleHelper.getMethodNameToRestore()).arg(paramVar);
60+
if (bundleHelper.restoreCallNeedCastStatement()) {
61+
getExtraExpression = JExpr.cast(extraParamClass, getExtraExpression);
62+
63+
if (bundleHelper.restoreCallNeedsSuppressWarning()) {
64+
JMethod onHandleIntentMethod = holder.getOnReceiveMethod();
65+
if (onHandleIntentMethod.annotations().size() == 0) {
66+
onHandleIntentMethod.annotate(SuppressWarnings.class).param("value", "unchecked");
67+
}
68+
}
69+
}
70+
return extrasNotNullBlock.decl(extraParamClass, extraParamName, getExtraExpression);
71+
}
72+
73+
private static JFieldVar getStaticExtraField(EReceiverHolder holder, String extraName) {
74+
String staticFieldName = CaseHelper.camelCaseToUpperSnakeCase(null, extraName, "Extra");
75+
JFieldVar staticExtraField = holder.getGeneratedClass().fields().get(staticFieldName);
76+
if (staticExtraField == null) {
77+
staticExtraField = holder.getGeneratedClass().field(PUBLIC | STATIC | FINAL, holder.classes().STRING, staticFieldName, lit(extraName));
78+
}
79+
return staticExtraField;
80+
}
81+
}
Lines changed: 115 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,115 @@
1+
/**
2+
* Copyright (C) 2010-2014 eBusiness Information, Excilys Group
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
5+
* use this file except in compliance with the License. You may obtain a copy of
6+
* the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed To in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12+
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13+
* License for the specific language governing permissions and limitations under
14+
* the License.
15+
*/
16+
package org.androidannotations.handler;
17+
18+
import com.sun.codemodel.JBlock;
19+
import com.sun.codemodel.JClass;
20+
import com.sun.codemodel.JExpr;
21+
import com.sun.codemodel.JFieldVar;
22+
import com.sun.codemodel.JInvocation;
23+
import com.sun.codemodel.JVar;
24+
import org.androidannotations.annotations.ReceiverAction;
25+
import org.androidannotations.helper.APTCodeModelHelper;
26+
import org.androidannotations.helper.AnnotationHelper;
27+
import org.androidannotations.helper.CaseHelper;
28+
import org.androidannotations.holder.EReceiverHolder;
29+
import org.androidannotations.model.AnnotationElements;
30+
import org.androidannotations.process.IsValid;
31+
32+
import javax.annotation.processing.ProcessingEnvironment;
33+
import javax.lang.model.element.Element;
34+
import javax.lang.model.element.ExecutableElement;
35+
import javax.lang.model.element.VariableElement;
36+
import java.util.List;
37+
38+
import static com.sun.codemodel.JExpr._null;
39+
import static com.sun.codemodel.JExpr.lit;
40+
import static com.sun.codemodel.JMod.FINAL;
41+
import static com.sun.codemodel.JMod.PUBLIC;
42+
import static com.sun.codemodel.JMod.STATIC;
43+
44+
public class ReceiverActionHandler extends BaseAnnotationHandler<EReceiverHolder> {
45+
46+
private final APTCodeModelHelper codeModelHelper = new APTCodeModelHelper();
47+
private AnnotationHelper annotationHelper;
48+
49+
public ReceiverActionHandler(ProcessingEnvironment processingEnvironment) {
50+
super(ReceiverAction.class, processingEnvironment);
51+
annotationHelper = new AnnotationHelper(processingEnvironment);
52+
}
53+
54+
@Override
55+
protected void validate(Element element, AnnotationElements validatedElements, IsValid valid) {
56+
57+
validatorHelper.enclosingElementHasEReceiver(element, validatedElements, valid);
58+
59+
validatorHelper.returnTypeIsVoid((ExecutableElement) element, valid);
60+
61+
validatorHelper.isNotPrivate(element, valid);
62+
63+
validatorHelper.param.hasNoOtherParameterThanContextOrIntentOrExtraAnnotated((ExecutableElement) element, valid);
64+
}
65+
66+
@Override
67+
public void process(Element element, EReceiverHolder holder) throws Exception {
68+
69+
ExecutableElement executableElement = (ExecutableElement) element;
70+
String methodName = element.getSimpleName().toString();
71+
72+
ReceiverAction annotation = element.getAnnotation(ReceiverAction.class);
73+
String extraKey = annotation.value();
74+
if (extraKey.isEmpty()) {
75+
extraKey = methodName;
76+
}
77+
78+
JFieldVar actionKeyField = createStaticActionField(holder, extraKey, methodName);
79+
addActionInOnReceive(holder, executableElement, methodName, actionKeyField);
80+
}
81+
82+
private JFieldVar createStaticActionField(EReceiverHolder holder, String extraKey, String methodName) {
83+
String staticFieldName = CaseHelper.camelCaseToUpperSnakeCase("action", methodName, null);
84+
return holder.getGeneratedClass().field(PUBLIC | STATIC | FINAL, classes().STRING, staticFieldName, lit(extraKey));
85+
}
86+
87+
private void addActionInOnReceive(EReceiverHolder holder, ExecutableElement executableElement, String methodName, JFieldVar actionKeyField) {
88+
// If action match, call the method
89+
JInvocation actionCondition = actionKeyField.invoke("equals").arg(holder.getOnReceiveIntentAction());
90+
JBlock callActionBlock = holder.getOnReceiveBody()._if(actionCondition)._then();
91+
JInvocation callActionInvocation = JExpr._super().invoke(methodName);
92+
93+
JVar extras = null;
94+
95+
List<? extends VariableElement> methodParameters = executableElement.getParameters();
96+
for (VariableElement param : methodParameters) {
97+
JClass extraParamClass = codeModelHelper.typeMirrorToJClass(param.asType(), holder);
98+
99+
if (extraParamClass.equals(classes().CONTEXT)) {
100+
callActionInvocation.arg(holder.getOnReceiveContext());
101+
} else if (extraParamClass.equals(classes().INTENT)) {
102+
callActionInvocation.arg(holder.getOnReceiveIntent());
103+
} else if (param.getAnnotation(ReceiverAction.Extra.class) != null) {
104+
if (extras == null){
105+
extras = callActionBlock.decl(classes().BUNDLE, "extras");
106+
extras.init(holder.getOnReceiveIntent().invoke("getExtras"));
107+
callActionBlock = callActionBlock._if(extras.ne(_null()))._then();
108+
}
109+
callActionInvocation.arg(ReceiverActionExtraHandler.extractedFieldInExtra(param, extras, callActionBlock, holder, codeModelHelper, annotationHelper));
110+
}
111+
}
112+
callActionBlock.add(callActionInvocation);
113+
callActionBlock._return();
114+
}
115+
}

0 commit comments

Comments
 (0)