Skip to content

Commit c42d4a0

Browse files
committed
Merge branch '210_fragment_arguments' into develop
Fixes androidannotations#210
2 parents 3aa4bf6 + dc0e1e3 commit c42d4a0

File tree

10 files changed

+575
-83
lines changed

10 files changed

+575
-83
lines changed

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

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
import com.googlecode.androidannotations.annotations.EView;
5151
import com.googlecode.androidannotations.annotations.EViewGroup;
5252
import com.googlecode.androidannotations.annotations.Extra;
53+
import com.googlecode.androidannotations.annotations.FragmentArg;
5354
import com.googlecode.androidannotations.annotations.FragmentById;
5455
import com.googlecode.androidannotations.annotations.FragmentByTag;
5556
import com.googlecode.androidannotations.annotations.FromHtml;
@@ -133,6 +134,7 @@
133134
import com.googlecode.androidannotations.processing.EViewGroupProcessor;
134135
import com.googlecode.androidannotations.processing.EViewProcessor;
135136
import com.googlecode.androidannotations.processing.ExtraProcessor;
137+
import com.googlecode.androidannotations.processing.FragmentArgProcessor;
136138
import com.googlecode.androidannotations.processing.FragmentByIdProcessor;
137139
import com.googlecode.androidannotations.processing.FragmentByTagProcessor;
138140
import com.googlecode.androidannotations.processing.FromHtmlProcessor;
@@ -196,6 +198,7 @@
196198
import com.googlecode.androidannotations.validation.EViewGroupValidator;
197199
import com.googlecode.androidannotations.validation.EViewValidator;
198200
import com.googlecode.androidannotations.validation.ExtraValidator;
201+
import com.googlecode.androidannotations.validation.FragmentArgValidator;
199202
import com.googlecode.androidannotations.validation.FragmentByIdValidator;
200203
import com.googlecode.androidannotations.validation.FragmentByTagValidator;
201204
import com.googlecode.androidannotations.validation.FromHtmlValidator;
@@ -311,6 +314,7 @@
311314
AfterTextChange.class, //
312315
OrmLiteDao.class, //
313316
HttpsClient.class, //
317+
FragmentArg.class, //
314318
OnActivityResult.class //
315319
})
316320
@SupportedSourceVersion(SourceVersion.RELEASE_6)
@@ -442,6 +446,7 @@ private ModelValidator buildModelValidator(IRClass rClass, AndroidSystemServices
442446
}
443447
modelValidator.register(new TransactionalValidator(processingEnv));
444448
modelValidator.register(new ExtraValidator(processingEnv));
449+
modelValidator.register(new FragmentArgValidator(processingEnv));
445450
modelValidator.register(new SystemServiceValidator(processingEnv, androidSystemServices));
446451
modelValidator.register(new SharedPrefValidator(processingEnv));
447452
modelValidator.register(new PrefValidator(processingEnv));
@@ -531,6 +536,7 @@ private ModelProcessor buildModelProcessor(IRClass rClass, AndroidSystemServices
531536
}
532537
modelProcessor.register(new TransactionalProcessor());
533538
modelProcessor.register(new ExtraProcessor(processingEnv));
539+
modelProcessor.register(new FragmentArgProcessor(processingEnv));
534540
modelProcessor.register(new SystemServiceProcessor(androidSystemServices));
535541
RestImplementationsHolder restImplementationHolder = new RestImplementationsHolder();
536542
modelProcessor.register(new RestProcessor(restImplementationHolder));
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
package com.googlecode.androidannotations.annotations;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
/**
9+
* Use on fields in fragments. This String value field corresponds to the
10+
* argument name.
11+
*
12+
* When {@link FragmentArg} is used on fields in a Fragment, the fragment
13+
* builder will hold dedicated methods for these arguments.
14+
*
15+
*/
16+
@Retention(RetentionPolicy.CLASS)
17+
@Target(ElementType.FIELD)
18+
public @interface FragmentArg {
19+
20+
String value() default "";
21+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
package com.googlecode.androidannotations.helper;
2+
3+
import static com.googlecode.androidannotations.helper.CanonicalNameConstants.BUNDLE;
4+
import static com.googlecode.androidannotations.helper.CanonicalNameConstants.CHAR_SEQUENCE;
5+
import static com.googlecode.androidannotations.helper.CanonicalNameConstants.STRING;
6+
7+
import java.util.HashMap;
8+
import java.util.Map;
9+
10+
import javax.lang.model.element.Element;
11+
import javax.lang.model.element.TypeElement;
12+
import javax.lang.model.type.ArrayType;
13+
import javax.lang.model.type.DeclaredType;
14+
import javax.lang.model.type.TypeKind;
15+
import javax.lang.model.type.TypeMirror;
16+
17+
public class BundleHelper {
18+
private static final Map<String, String> methodSuffixNameByTypeName = new HashMap<String, String>();
19+
20+
static {
21+
22+
methodSuffixNameByTypeName.put(BUNDLE, "Bundle");
23+
24+
methodSuffixNameByTypeName.put("boolean", "Boolean");
25+
methodSuffixNameByTypeName.put("boolean[]", "BooleanArray");
26+
27+
methodSuffixNameByTypeName.put("byte", "Byte");
28+
methodSuffixNameByTypeName.put("byte[]", "ByteArray");
29+
30+
methodSuffixNameByTypeName.put("char", "Char");
31+
methodSuffixNameByTypeName.put("char[]", "CharArray");
32+
33+
methodSuffixNameByTypeName.put(CHAR_SEQUENCE, "CharSequence");
34+
35+
methodSuffixNameByTypeName.put("double", "Double");
36+
methodSuffixNameByTypeName.put("double[]", "DoubleArray");
37+
38+
methodSuffixNameByTypeName.put("float", "Float");
39+
methodSuffixNameByTypeName.put("float[]", "FloatArray");
40+
41+
methodSuffixNameByTypeName.put("int", "Int");
42+
methodSuffixNameByTypeName.put("int[]", "IntArray");
43+
methodSuffixNameByTypeName.put("java.util.ArrayList<java.lang.Integer>", "IntegerArrayList");
44+
45+
methodSuffixNameByTypeName.put("long", "Long");
46+
methodSuffixNameByTypeName.put("long[]", "LongArray");
47+
48+
methodSuffixNameByTypeName.put("short", "Short");
49+
methodSuffixNameByTypeName.put("short[]", "ShortArray");
50+
51+
methodSuffixNameByTypeName.put(STRING, "String");
52+
methodSuffixNameByTypeName.put("java.lang.String[]", "StringArray");
53+
methodSuffixNameByTypeName.put("java.util.ArrayList<java.lang.String>", "StringArrayList");
54+
}
55+
56+
private AnnotationHelper annotationHelper;
57+
58+
private boolean restoreCallNeedCastStatement = false;
59+
private boolean restoreCallNeedsSuppressWarning = false;
60+
61+
private String methodNameToSave;
62+
private String methodNameToRestore;
63+
64+
public BundleHelper(AnnotationHelper helper, Element element) {
65+
annotationHelper = helper;
66+
67+
String typeString = element.asType().toString();
68+
TypeElement elementType = annotationHelper.typeElementFromQualifiedName(typeString);
69+
70+
if (methodSuffixNameByTypeName.containsKey(typeString)) {
71+
72+
methodNameToSave = "put" + methodSuffixNameByTypeName.get(typeString);
73+
methodNameToRestore = "get" + methodSuffixNameByTypeName.get(typeString);
74+
75+
} else if (element.asType().getKind() == TypeKind.ARRAY) {
76+
77+
ArrayType arrayType = (ArrayType) element.asType();
78+
79+
boolean hasTypeArguments = false;
80+
if (arrayType.getComponentType() instanceof DeclaredType) {
81+
DeclaredType declaredType = (DeclaredType) arrayType.getComponentType();
82+
typeString = declaredType.asElement().toString();
83+
hasTypeArguments = declaredType.getTypeArguments().size() > 0;
84+
} else {
85+
typeString = arrayType.getComponentType().toString();
86+
}
87+
88+
elementType = annotationHelper.typeElementFromQualifiedName(typeString);
89+
90+
if (isTypeParcelable(elementType)) {
91+
methodNameToSave = "put" + "ParcelableArray";
92+
methodNameToRestore = "get" + "ParcelableArray";
93+
restoreCallNeedCastStatement = true;
94+
95+
if (hasTypeArguments) {
96+
restoreCallNeedsSuppressWarning = true;
97+
}
98+
} else {
99+
methodNameToSave = "put" + "Serializable";
100+
methodNameToRestore = "get" + "Serializable";
101+
restoreCallNeedCastStatement = true;
102+
}
103+
} else {
104+
105+
TypeMirror elementAsType = element.asType();
106+
boolean hasTypeArguments = false;
107+
if (elementAsType instanceof DeclaredType) {
108+
DeclaredType declaredType = (DeclaredType) elementAsType;
109+
typeString = declaredType.asElement().toString();
110+
elementType = annotationHelper.typeElementFromQualifiedName(typeString);
111+
hasTypeArguments = declaredType.getTypeArguments().size() > 0;
112+
}
113+
114+
if (isTypeParcelable(elementType)) {
115+
methodNameToSave = "put" + "Parcelable";
116+
methodNameToRestore = "get" + "Parcelable";
117+
} else {
118+
methodNameToSave = "put" + "Serializable";
119+
methodNameToRestore = "get" + "Serializable";
120+
restoreCallNeedCastStatement = true;
121+
122+
if (hasTypeArguments) {
123+
restoreCallNeedsSuppressWarning = true;
124+
}
125+
}
126+
}
127+
}
128+
129+
public boolean restoreCallNeedCastStatement() {
130+
return restoreCallNeedCastStatement;
131+
}
132+
133+
public boolean restoreCallNeedsSuppressWarning() {
134+
return restoreCallNeedsSuppressWarning;
135+
}
136+
137+
public String getMethodNameToSave() {
138+
return methodNameToSave;
139+
}
140+
141+
public String getMethodNameToRestore() {
142+
return methodNameToRestore;
143+
}
144+
145+
private boolean isTypeParcelable(TypeElement elementType) {
146+
147+
TypeElement parcelableType = annotationHelper.typeElementFromQualifiedName("android.os.Parcelable");
148+
149+
return elementType != null && annotationHelper.isSubtype(elementType, parcelableType);
150+
}
151+
}

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -170,6 +170,11 @@ public void enclosingElementHasEActivityOrEFragment(Element element, AnnotationE
170170
hasOneOfClassAnnotations(element, enclosingElement, validatedElements, validAnnotations, valid);
171171
}
172172

173+
public void enclosingElementHasEFragment(Element element, AnnotationElements validatedElements, IsValid valid) {
174+
Element enclosingElement = element.getEnclosingElement();
175+
hasClassAnnotation(element, enclosingElement, validatedElements, EFragment.class, valid);
176+
}
177+
173178
public void hasEActivity(Element element, AnnotationElements validatedElements, IsValid valid) {
174179
hasClassAnnotation(element, element, validatedElements, EActivity.class, valid);
175180
}

AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/processing/EBeanHolder.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -96,6 +96,12 @@ public class EBeanHolder {
9696
*/
9797
public final HashMap<String, OnSeekBarChangeListenerHolder> onSeekBarChangeListeners = new HashMap<String, OnSeekBarChangeListenerHolder>();
9898

99+
public JVar fragmentArguments;
100+
public JFieldVar fragmentArgumentsBuilderField;
101+
public JMethod fragmentArgumentsInjectMethod;
102+
public JBlock fragmentArgumentsNotNullBlock;
103+
public JDefinedClass fragmentBuilderClass;
104+
99105
public JMethod findNativeFragmentById;
100106
public JMethod findSupportFragmentById;
101107
public JMethod findNativeFragmentByTag;

AndroidAnnotations/androidannotations/src/main/java/com/googlecode/androidannotations/processing/EFragmentProcessor.java

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,12 +17,14 @@
1717

1818
import static com.googlecode.androidannotations.helper.ModelConstants.GENERATION_SUFFIX;
1919
import static com.sun.codemodel.JExpr.FALSE;
20+
import static com.sun.codemodel.JExpr._new;
2021
import static com.sun.codemodel.JExpr._null;
2122
import static com.sun.codemodel.JExpr._super;
2223
import static com.sun.codemodel.JExpr.invoke;
2324
import static com.sun.codemodel.JMod.FINAL;
2425
import static com.sun.codemodel.JMod.PRIVATE;
2526
import static com.sun.codemodel.JMod.PUBLIC;
27+
import static com.sun.codemodel.JMod.STATIC;
2628

2729
import java.lang.annotation.Annotation;
2830

@@ -38,6 +40,7 @@
3840
import com.sun.codemodel.ClassType;
3941
import com.sun.codemodel.JBlock;
4042
import com.sun.codemodel.JClass;
43+
import com.sun.codemodel.JClassAlreadyExistsException;
4144
import com.sun.codemodel.JCodeModel;
4245
import com.sun.codemodel.JDefinedClass;
4346
import com.sun.codemodel.JFieldRef;
@@ -150,5 +153,38 @@ public void process(Element element, JCodeModel codeModel, EBeansHolder eBeansHo
150153
holder.initActivityRef = holder.contextRef;
151154
}
152155

156+
addFragmentBuilder(codeModel, holder, eBeanClass);
157+
}
158+
159+
private void addFragmentBuilder(JCodeModel codeModel, EBeanHolder holder, JClass eBeanClass) throws JClassAlreadyExistsException {
160+
JClass bundleClass = holder.classes().BUNDLE;
161+
162+
{
163+
holder.fragmentBuilderClass = holder.generatedClass._class(PUBLIC | STATIC, "FragmentBuilder_");
164+
holder.fragmentArgumentsBuilderField = holder.fragmentBuilderClass.field(PRIVATE, bundleClass, "args_");
165+
166+
{
167+
// Constructor
168+
JMethod constructor = holder.fragmentBuilderClass.constructor(PRIVATE);
169+
JBlock constructorBody = constructor.body();
170+
constructorBody.assign(holder.fragmentArgumentsBuilderField, _new(bundleClass));
171+
}
172+
173+
{
174+
// build()
175+
JMethod method = holder.fragmentBuilderClass.method(PUBLIC, eBeanClass, "build");
176+
JBlock body = method.body();
177+
178+
JVar fragment = body.decl(holder.generatedClass, "fragment_", _new(holder.generatedClass));
179+
body.invoke(fragment, "setArguments").arg(holder.fragmentArgumentsBuilderField);
180+
body._return(fragment);
181+
}
182+
183+
{
184+
// create()
185+
JMethod method = holder.generatedClass.method(STATIC | PUBLIC, holder.fragmentBuilderClass, "builder");
186+
method.body()._return(_new(holder.fragmentBuilderClass));
187+
}
188+
}
153189
}
154190
}

0 commit comments

Comments
 (0)