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

Commit 11aa5ee

Browse files
committed
Implements @rootfragment annotation support.
1 parent 4056cff commit 11aa5ee

8 files changed

Lines changed: 224 additions & 4 deletions

File tree

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/**
2+
* Copyright (C) 2010-2016 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+
* Use it on Fragments fields in an {@link EBean}
26+
* annotated classes to inject the Fragment which injected the bean instance.
27+
* </p>
28+
* <p>
29+
* This field may not be injected at runtime if the fragment used to create the
30+
* bean is not of the appropriate type, or if the bean is injected in an activity.
31+
* </p>
32+
* <blockquote>
33+
*
34+
* Example :
35+
*
36+
* <pre>
37+
* &#064;EBean
38+
* public class MyClass {
39+
*
40+
* &#064;RootFragment
41+
* Fragment fragment;
42+
*
43+
* // Only injected if the root fragment implements a given interface
44+
* &#064;RootFragment
45+
* MyInterface fragment;
46+
* }
47+
* </pre>
48+
*
49+
* </blockquote>
50+
*/
51+
@Retention(RetentionPolicy.CLASS)
52+
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
53+
public @interface RootFragment {
54+
}

‎AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/holder/EBeanHolder.java‎

Lines changed: 46 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,15 +40,18 @@ public class EBeanHolder extends EComponentWithViewSupportHolder {
4040

4141
public static final String GET_INSTANCE_METHOD_NAME = "getInstance" + generationSuffix();
4242

43+
private JFieldVar rootFragmentField;
4344
private JFieldVar contextField;
45+
4446
private JMethod constructor;
47+
private JMethod overloadedConstructor;
4548

4649
public EBeanHolder(AndroidAnnotationsEnvironment environment, TypeElement annotatedElement) throws Exception {
4750
super(environment, annotatedElement);
48-
setConstructor();
51+
setConstructors();
4952
}
5053

51-
private void setConstructor() {
54+
private void setConstructors() {
5255
constructor = generatedClass.constructor(PRIVATE);
5356
JVar constructorContextParam = constructor.param(getClasses().CONTEXT, "context");
5457
JBlock constructorBody = constructor.body();
@@ -58,6 +61,16 @@ private void setConstructor() {
5861
constructorBody.invoke("super").arg(constructorContextParam);
5962
}
6063
constructorBody.assign(getContextField(), constructorContextParam);
64+
65+
overloadedConstructor = generatedClass.constructor(PRIVATE);
66+
JVar overloadedConstructorContextParam = overloadedConstructor.param(getClasses().CONTEXT, "context");
67+
JVar overloadedConstructorRootFragmentParam = overloadedConstructor.param(getClasses().OBJECT, "rootFragment");
68+
JBlock overloadedConstructorBody = overloadedConstructor.body();
69+
if (superConstructor.getParameters().size() == 1) {
70+
overloadedConstructorBody.invoke("super").arg(constructorContextParam);
71+
}
72+
overloadedConstructorBody.assign(getContextField(), overloadedConstructorContextParam);
73+
overloadedConstructorBody.assign(getRootFragmentField(), overloadedConstructorRootFragmentParam);
6174
}
6275

6376
public JFieldVar getContextField() {
@@ -67,19 +80,34 @@ public JFieldVar getContextField() {
6780
return contextField;
6881
}
6982

83+
public JFieldVar getRootFragmentField() {
84+
if (rootFragmentField == null) {
85+
rootFragmentField = generatedClass.field(PRIVATE, getClasses().OBJECT, "rootFragment" + generationSuffix());
86+
}
87+
return rootFragmentField;
88+
}
89+
7090
@Override
7191
protected void setContextRef() {
7292
contextRef = getContextField();
7393
}
7494

95+
@Override
96+
protected void setRootFragmentRef() {
97+
rootFragmentRef = getRootFragmentField();
98+
}
99+
75100
@Override
76101
protected void setInit() {
77102
init = generatedClass.method(PRIVATE, getCodeModel().VOID, "init" + generationSuffix());
78103
}
79104

80-
public void invokeInitInConstructor() {
105+
public void invokeInitInConstructors() {
81106
JBlock constructorBody = constructor.body();
82107
constructorBody.invoke(getInit());
108+
109+
JBlock overloadedConstructorBody = overloadedConstructor.body();
110+
overloadedConstructorBody.invoke(getInit());
83111
}
84112

85113
public void createFactoryMethod(boolean hasSingletonScope) {
@@ -112,9 +140,24 @@ public void createFactoryMethod(boolean hasSingletonScope) {
112140
factoryMethodBody._return(instanceField);
113141
} else {
114142
factoryMethodBody._return(_new(narrowedGeneratedClass).arg(factoryMethodContextParam));
143+
createOverloadedFactoryMethod();
115144
}
116145
}
117146

147+
private void createOverloadedFactoryMethod() {
148+
149+
AbstractJClass narrowedGeneratedClass = codeModelHelper.narrowGeneratedClass(generatedClass, annotatedElement.asType());
150+
JMethod factoryMethod = generatedClass.method(PUBLIC | STATIC, narrowedGeneratedClass, GET_INSTANCE_METHOD_NAME);
151+
codeModelHelper.generify(factoryMethod, annotatedElement);
152+
153+
JVar factoryMethodContextParam = factoryMethod.param(getClasses().CONTEXT, "context");
154+
JVar factoryMethodRootFragmentParam = factoryMethod.param(getClasses().OBJECT, "rootFragment");
155+
156+
JBlock factoryMethodBody = factoryMethod.body();
157+
factoryMethodBody._return(_new(narrowedGeneratedClass).arg(factoryMethodContextParam).arg(factoryMethodRootFragmentParam));
158+
159+
}
160+
118161
public void createRebindMethod() {
119162
JMethod rebindMethod = generatedClass.method(PUBLIC, getCodeModel().VOID, "rebind");
120163
JVar contextParam = rebindMethod.param(getClasses().CONTEXT, "context");

‎AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/holder/EComponentHolder.java‎

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

18+
import static com.helger.jcodemodel.JExpr._null;
1819
import static com.helger.jcodemodel.JExpr.cast;
1920
import static com.helger.jcodemodel.JMod.PRIVATE;
2021
import static org.androidannotations.helper.ModelConstants.generationSuffix;
@@ -33,6 +34,8 @@
3334
public abstract class EComponentHolder extends BaseGeneratedClassHolder {
3435

3536
protected IJExpression contextRef;
37+
protected IJExpression rootFragmentRef;
38+
3639
protected JMethod init;
3740
private JBlock initBodyBeforeInjectionBlock;
3841
private JBlock initBodyInjectionBlock;
@@ -53,6 +56,17 @@ public IJExpression getContextRef() {
5356

5457
protected abstract void setContextRef();
5558

59+
public IJExpression getRootFragmentRef() {
60+
if (rootFragmentRef == null) {
61+
setRootFragmentRef();
62+
}
63+
return rootFragmentRef;
64+
}
65+
66+
protected void setRootFragmentRef() {
67+
rootFragmentRef = _null();
68+
}
69+
5670
public JMethod getInit() {
5771
if (init == null) {
5872
setInit();

‎AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/holder/EFragmentHolder.java‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import static com.helger.jcodemodel.JExpr._new;
2222
import static com.helger.jcodemodel.JExpr._null;
2323
import static com.helger.jcodemodel.JExpr._super;
24+
import static com.helger.jcodemodel.JExpr._this;
2425
import static com.helger.jcodemodel.JExpr.cond;
2526
import static com.helger.jcodemodel.JExpr.invoke;
2627
import static com.helger.jcodemodel.JExpr.ref;
@@ -187,6 +188,11 @@ protected void setContextRef() {
187188
contextRef = JExpr.invoke("getActivity");
188189
}
189190

191+
@Override
192+
protected void setRootFragmentRef() {
193+
rootFragmentRef = _this();
194+
}
195+
190196
@Override
191197
protected void setInit() {
192198
init = generatedClass.method(PRIVATE, getCodeModel().VOID, "init" + generationSuffix());

‎AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/CorePlugin.java‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
import org.androidannotations.internal.core.handler.ReceiverActionHandler;
9292
import org.androidannotations.internal.core.handler.ReceiverHandler;
9393
import org.androidannotations.internal.core.handler.RootContextHandler;
94+
import org.androidannotations.internal.core.handler.RootFragmentHandler;
9495
import org.androidannotations.internal.core.handler.SeekBarProgressChangeHandler;
9596
import org.androidannotations.internal.core.handler.SeekBarTouchStartHandler;
9697
import org.androidannotations.internal.core.handler.SeekBarTouchStopHandler;
@@ -184,6 +185,7 @@ public List<AnnotationHandler<?>> getHandlers(AndroidAnnotationsEnvironment andr
184185
annotationHandlers.add(new CustomTitleHandler(androidAnnotationEnv));
185186
annotationHandlers.add(new FullscreenHandler(androidAnnotationEnv));
186187
annotationHandlers.add(new RootContextHandler(androidAnnotationEnv));
188+
annotationHandlers.add(new RootFragmentHandler(androidAnnotationEnv));
187189
annotationHandlers.add(new ExtraHandler(androidAnnotationEnv));
188190
annotationHandlers.add(new BindingObjectHandler(androidAnnotationEnv));
189191
annotationHandlers.add(new BeforeTextChangeHandler(androidAnnotationEnv));

‎AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/handler/BeanHandler.java‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
import javax.lang.model.element.Element;
2121
import javax.lang.model.element.ElementKind;
22+
import javax.lang.model.element.TypeElement;
2223
import javax.lang.model.type.TypeMirror;
2324

2425
import org.androidannotations.AndroidAnnotationsEnvironment;
@@ -81,6 +82,14 @@ public void assignValue(JBlock targetBlock, IJAssignmentTarget fieldRef, ECompon
8182
AbstractJClass injectedClass = getJClass(annotationHelper.generatedClassQualifiedNameFromQualifiedName(typeQualifiedName));
8283
JInvocation beanInstance = injectedClass.staticInvoke(EBeanHolder.GET_INSTANCE_METHOD_NAME).arg(holder.getContextRef());
8384

85+
TypeElement declaredEBean = getProcessingEnvironment().getElementUtils().getTypeElement(typeQualifiedName);
86+
if (declaredEBean != null) {
87+
EBean annotation = declaredEBean.getAnnotation(EBean.class);
88+
if (annotation.scope() == EBean.Scope.Default) {
89+
beanInstance.arg(holder.getRootFragmentRef());
90+
}
91+
}
92+
8493
IJStatement assignment = fieldRef.assign(beanInstance);
8594
if (param.getKind() == ElementKind.FIELD) {
8695
boolean hasNonConfigurationInstanceAnnotation = element.getAnnotation(NonConfigurationInstance.class) != null;

‎AndroidAnnotations/androidannotations-core/androidannotations/src/main/java/org/androidannotations/internal/core/handler/EBeanHandler.java‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ public void process(Element element, EBeanHolder holder) {
5555
holder.createFactoryMethod(hasSingletonScope);
5656

5757
if (!hasSingletonScope) {
58-
holder.invokeInitInConstructor();
58+
holder.invokeInitInConstructors();
5959
holder.createRebindMethod();
6060
}
6161
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
/**
2+
* Copyright (C) 2010-2016 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.internal.core.handler;
17+
18+
import static com.helger.jcodemodel.JExpr.cast;
19+
import static com.helger.jcodemodel.JExpr.lit;
20+
import static org.androidannotations.helper.LogHelper.logTagForClassHolder;
21+
22+
import javax.lang.model.element.Element;
23+
import javax.lang.model.type.TypeMirror;
24+
25+
import org.androidannotations.AndroidAnnotationsEnvironment;
26+
import org.androidannotations.ElementValidation;
27+
import org.androidannotations.annotations.RootFragment;
28+
import org.androidannotations.handler.BaseAnnotationHandler;
29+
import org.androidannotations.handler.MethodInjectionHandler;
30+
import org.androidannotations.helper.InjectHelper;
31+
import org.androidannotations.holder.EBeanHolder;
32+
33+
import com.helger.jcodemodel.AbstractJClass;
34+
import com.helger.jcodemodel.IJAssignmentTarget;
35+
import com.helger.jcodemodel.IJExpression;
36+
import com.helger.jcodemodel.JBlock;
37+
import com.helger.jcodemodel.JConditional;
38+
import com.helger.jcodemodel.JInvocation;
39+
40+
public class RootFragmentHandler extends BaseAnnotationHandler<EBeanHolder> implements MethodInjectionHandler<EBeanHolder> {
41+
42+
private final InjectHelper<EBeanHolder> injectHelper;
43+
44+
public RootFragmentHandler(AndroidAnnotationsEnvironment environment) {
45+
super(RootFragment.class, environment);
46+
injectHelper = new InjectHelper<>(validatorHelper, this);
47+
}
48+
49+
@Override
50+
public void validate(Element element, ElementValidation validation) {
51+
injectHelper.validate(RootFragment.class, element, validation);
52+
if (!validation.isValid()) {
53+
return;
54+
}
55+
56+
validatorHelper.isNotPrivate(element, validation);
57+
}
58+
59+
@Override
60+
public void process(Element element, EBeanHolder holder) {
61+
injectHelper.process(element, holder);
62+
}
63+
64+
@Override
65+
public JBlock getInvocationBlock(EBeanHolder holder) {
66+
return holder.getInitBodyInjectionBlock();
67+
}
68+
69+
@Override
70+
public void assignValue(JBlock targetBlock, IJAssignmentTarget fieldRef, EBeanHolder holder, Element element, Element param) {
71+
TypeMirror elementType = param.asType();
72+
String typeQualifiedName = elementType.toString();
73+
74+
IJExpression rootFragmentRef = holder.getRootFragmentRef();
75+
76+
AbstractJClass extendingContextClass = getEnvironment().getJClass(typeQualifiedName);
77+
78+
JConditional cond = getInvocationBlock(holder)._if(rootFragmentRef._instanceof(extendingContextClass));
79+
cond._then().add(fieldRef.assign(cast(extendingContextClass, rootFragmentRef)));
80+
81+
JInvocation warningInvoke = getClasses().LOG.staticInvoke("w");
82+
warningInvoke.arg(logTagForClassHolder(holder));
83+
warningInvoke.arg(
84+
lit("Due to Context class ").plus(rootFragmentRef.invoke("getClass").invoke("getSimpleName")).plus(lit(", the @RootFragment " + extendingContextClass.name() + " won't be populated")));
85+
cond._else().add(warningInvoke);
86+
}
87+
88+
@Override
89+
public void validateEnclosingElement(Element element, ElementValidation valid) {
90+
validatorHelper.enclosingElementHasEBeanAnnotation(element, valid);
91+
}
92+
}

0 commit comments

Comments
 (0)