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

Commit 6a485f0

Browse files
committed
Implements @rootfragment annotation support.
1 parent deadb04 commit 6a485f0

8 files changed

Lines changed: 227 additions & 4 deletions

File tree

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
/**
2+
* Copyright (C) 2016-2019 the AndroidAnnotations project
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} annotated classes to inject
26+
* 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
31+
* activity.
32+
* </p>
33+
* <blockquote>
34+
*
35+
* Example :
36+
*
37+
* <pre>
38+
* &#064;EBean
39+
* public class MyClass {
40+
*
41+
* &#064;RootFragment
42+
* Fragment fragment;
43+
*
44+
* // Only injected if the root fragment implements a given interface
45+
* &#064;RootFragment
46+
* MyInterface fragment;
47+
* }
48+
* </pre>
49+
*
50+
* </blockquote>
51+
*/
52+
@Retention(RetentionPolicy.CLASS)
53+
@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
54+
public @interface RootFragment {
55+
}

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

Lines changed: 47 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/**
22
* Copyright (C) 2010-2016 eBusiness Information, Excilys Group
3+
* Copyright (C) 2016-2019 the AndroidAnnotations project
34
*
45
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
56
* use this file except in compliance with the License. You may obtain a copy of
@@ -40,15 +41,18 @@ public class EBeanHolder extends EComponentWithViewSupportHolder {
4041

4142
public static final String GET_INSTANCE_METHOD_NAME = "getInstance" + generationSuffix();
4243

44+
private JFieldVar rootFragmentField;
4345
private JFieldVar contextField;
46+
4447
private JMethod constructor;
48+
private JMethod overloadedConstructor;
4549

4650
public EBeanHolder(AndroidAnnotationsEnvironment environment, TypeElement annotatedElement) throws Exception {
4751
super(environment, annotatedElement);
48-
setConstructor();
52+
setConstructors();
4953
}
5054

51-
private void setConstructor() {
55+
private void setConstructors() {
5256
constructor = generatedClass.constructor(PRIVATE);
5357
JVar constructorContextParam = constructor.param(getClasses().CONTEXT, "context");
5458
JBlock constructorBody = constructor.body();
@@ -58,6 +62,16 @@ private void setConstructor() {
5862
constructorBody.invoke("super").arg(constructorContextParam);
5963
}
6064
constructorBody.assign(getContextField(), constructorContextParam);
65+
66+
overloadedConstructor = generatedClass.constructor(PRIVATE);
67+
JVar overloadedConstructorContextParam = overloadedConstructor.param(getClasses().CONTEXT, "context");
68+
JVar overloadedConstructorRootFragmentParam = overloadedConstructor.param(getClasses().OBJECT, "rootFragment");
69+
JBlock overloadedConstructorBody = overloadedConstructor.body();
70+
if (superConstructor.getParameters().size() == 1) {
71+
overloadedConstructorBody.invoke("super").arg(constructorContextParam);
72+
}
73+
overloadedConstructorBody.assign(getContextField(), overloadedConstructorContextParam);
74+
overloadedConstructorBody.assign(getRootFragmentField(), overloadedConstructorRootFragmentParam);
6175
}
6276

6377
public JFieldVar getContextField() {
@@ -67,19 +81,34 @@ public JFieldVar getContextField() {
6781
return contextField;
6882
}
6983

84+
public JFieldVar getRootFragmentField() {
85+
if (rootFragmentField == null) {
86+
rootFragmentField = generatedClass.field(PRIVATE, getClasses().OBJECT, "rootFragment" + generationSuffix());
87+
}
88+
return rootFragmentField;
89+
}
90+
7091
@Override
7192
protected void setContextRef() {
7293
contextRef = getContextField();
7394
}
7495

96+
@Override
97+
protected void setRootFragmentRef() {
98+
rootFragmentRef = getRootFragmentField();
99+
}
100+
75101
@Override
76102
protected void setInit() {
77103
init = generatedClass.method(PRIVATE, getCodeModel().VOID, "init" + generationSuffix());
78104
}
79105

80-
public void invokeInitInConstructor() {
106+
public void invokeInitInConstructors() {
81107
JBlock constructorBody = constructor.body();
82108
constructorBody.invoke(getInit());
109+
110+
JBlock overloadedConstructorBody = overloadedConstructor.body();
111+
overloadedConstructorBody.invoke(getInit());
83112
}
84113

85114
public void createFactoryMethod(boolean hasSingletonScope) {
@@ -112,9 +141,24 @@ public void createFactoryMethod(boolean hasSingletonScope) {
112141
factoryMethodBody._return(instanceField);
113142
} else {
114143
factoryMethodBody._return(_new(narrowedGeneratedClass).arg(factoryMethodContextParam));
144+
createOverloadedFactoryMethod();
115145
}
116146
}
117147

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

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

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
/**
22
* Copyright (C) 2010-2016 eBusiness Information, Excilys Group
3+
* Copyright (C) 2016-2019 the AndroidAnnotations project
34
*
45
* Licensed under the Apache License, Version 2.0 (the "License"); you may not
56
* use this file except in compliance with the License. You may obtain a copy of
@@ -15,6 +16,7 @@
1516
*/
1617
package org.androidannotations.holder;
1718

19+
import static com.helger.jcodemodel.JExpr._null;
1820
import static com.helger.jcodemodel.JExpr.cast;
1921
import static com.helger.jcodemodel.JMod.PRIVATE;
2022
import static org.androidannotations.helper.ModelConstants.generationSuffix;
@@ -33,6 +35,8 @@
3335
public abstract class EComponentHolder extends BaseGeneratedClassHolder {
3436

3537
protected IJExpression contextRef;
38+
protected IJExpression rootFragmentRef;
39+
3640
protected JMethod init;
3741
private JBlock initBodyBeforeInjectionBlock;
3842
private JBlock initBodyInjectionBlock;
@@ -53,6 +57,17 @@ public IJExpression getContextRef() {
5357

5458
protected abstract void setContextRef();
5559

60+
public IJExpression getRootFragmentRef() {
61+
if (rootFragmentRef == null) {
62+
setRootFragmentRef();
63+
}
64+
return rootFragmentRef;
65+
}
66+
67+
protected void setRootFragmentRef() {
68+
rootFragmentRef = _null();
69+
}
70+
5671
public JMethod getInit() {
5772
if (init == null) {
5873
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
@@ -20,6 +20,7 @@
2020

2121
import javax.lang.model.element.Element;
2222
import javax.lang.model.element.ElementKind;
23+
import javax.lang.model.element.TypeElement;
2324
import javax.lang.model.type.TypeMirror;
2425

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

86+
TypeElement declaredEBean = getProcessingEnvironment().getElementUtils().getTypeElement(typeQualifiedName);
87+
if (declaredEBean != null) {
88+
EBean annotation = declaredEBean.getAnnotation(EBean.class);
89+
if (annotation.scope() == EBean.Scope.Default) {
90+
beanInstance.arg(holder.getRootFragmentRef());
91+
}
92+
}
93+
8594
IJStatement assignment = fieldRef.assign(beanInstance);
8695
if (param.getKind() == ElementKind.FIELD) {
8796
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) 2016-2019 the AndroidAnnotations project
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 = targetBlock._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
84+
.arg(lit("Due to 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)