Skip to content

Commit d3b5451

Browse files
committed
Added keyRes parameter to @Defaultxxx annotations
1 parent df760b7 commit d3b5451

11 files changed

Lines changed: 183 additions & 64 deletions

File tree

‎AndroidAnnotations/androidannotations-api/src/main/java/org/androidannotations/annotations/sharedpreferences/DefaultBoolean.java‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,22 @@
2020
import java.lang.annotation.RetentionPolicy;
2121
import java.lang.annotation.Target;
2222

23+
import org.androidannotations.annotations.ResId;
24+
2325
/**
2426
* Use on methods in {@link SharedPref} annotated class to specified the default
2527
* value of this preference.
2628
* <p/>
2729
* The annotation value must be a <code>boolean</code>.
30+
* <p/>
31+
* The key of the preference will be the method name by default. This can be
32+
* overridden by specifying a string resource with the {@link #keyRes()}
33+
* parameter.
2834
*/
2935
@Retention(RetentionPolicy.CLASS)
3036
@Target(ElementType.METHOD)
3137
public @interface DefaultBoolean {
3238
boolean value();
39+
40+
int keyRes() default ResId.DEFAULT_VALUE;
3341
}

‎AndroidAnnotations/androidannotations-api/src/main/java/org/androidannotations/annotations/sharedpreferences/DefaultFloat.java‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,22 @@
2020
import java.lang.annotation.RetentionPolicy;
2121
import java.lang.annotation.Target;
2222

23+
import org.androidannotations.annotations.ResId;
24+
2325
/**
2426
* Use on methods in {@link SharedPref} annotated class to specified the default
2527
* value of this preference.
2628
* <p/>
2729
* The annotation value must be a <code>float</code>.
30+
* <p/>
31+
* The key of the preference will be the method name by default. This can be
32+
* overridden by specifying a string resource with the {@link #keyRes()}
33+
* parameter.
2834
*/
2935
@Retention(RetentionPolicy.CLASS)
3036
@Target(ElementType.METHOD)
3137
public @interface DefaultFloat {
3238
float value();
39+
40+
int keyRes() default ResId.DEFAULT_VALUE;
3341
}

‎AndroidAnnotations/androidannotations-api/src/main/java/org/androidannotations/annotations/sharedpreferences/DefaultInt.java‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,22 @@
2020
import java.lang.annotation.RetentionPolicy;
2121
import java.lang.annotation.Target;
2222

23+
import org.androidannotations.annotations.ResId;
24+
2325
/**
2426
* Use on methods in {@link SharedPref} annotated class to specified the default
2527
* value of this preference.
2628
* <p/>
2729
* The annotation value must be an <code>int</code>.
30+
* <p/>
31+
* The key of the preference will be the method name by default. This can be
32+
* overridden by specifying a string resource with the {@link #keyRes()}
33+
* parameter.
2834
*/
2935
@Retention(RetentionPolicy.CLASS)
3036
@Target(ElementType.METHOD)
3137
public @interface DefaultInt {
3238
int value();
39+
40+
int keyRes() default ResId.DEFAULT_VALUE;
3341
}

‎AndroidAnnotations/androidannotations-api/src/main/java/org/androidannotations/annotations/sharedpreferences/DefaultLong.java‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,22 @@
2020
import java.lang.annotation.RetentionPolicy;
2121
import java.lang.annotation.Target;
2222

23+
import org.androidannotations.annotations.ResId;
24+
2325
/**
2426
* Use on methods in {@link SharedPref} annotated class to specified the default
2527
* value of this preference.
2628
* <p/>
2729
* The annotation value must be a <code>long</code>.
30+
* <p/>
31+
* The key of the preference will be the method name by default. This can be
32+
* overridden by specifying a string resource with the {@link #keyRes()}
33+
* parameter.
2834
*/
2935
@Retention(RetentionPolicy.CLASS)
3036
@Target(ElementType.METHOD)
3137
public @interface DefaultLong {
3238
long value();
39+
40+
int keyRes() default ResId.DEFAULT_VALUE;
3341
}

‎AndroidAnnotations/androidannotations-api/src/main/java/org/androidannotations/annotations/sharedpreferences/DefaultRes.java‎

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,11 @@
2727
* value of this preference.
2828
* <p/>
2929
* The annotation value must be one of R.* fields. If the value is not set, the
30-
* field name will be used as the R.* field name.
30+
* method name will be used as the R.* field name.
31+
* <p/>
32+
* The key of the preference will be the method name by default. This can be
33+
* overridden by specifying a string resource with the {@link #keyRes()}
34+
* parameter.
3135
*/
3236
@Retention(RetentionPolicy.CLASS)
3337
@Target(ElementType.METHOD)
@@ -37,4 +41,5 @@
3741

3842
String resName() default "";
3943

44+
int keyRes() default ResId.DEFAULT_VALUE;
4045
}

‎AndroidAnnotations/androidannotations-api/src/main/java/org/androidannotations/annotations/sharedpreferences/DefaultString.java‎

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,14 +20,22 @@
2020
import java.lang.annotation.RetentionPolicy;
2121
import java.lang.annotation.Target;
2222

23+
import org.androidannotations.annotations.ResId;
24+
2325
/**
2426
* Use on methods in {@link SharedPref} annotated class to specified the default
2527
* value of this preference.
2628
* <p/>
2729
* The annotation value must be a {@link String}.
30+
* <p/>
31+
* The key of the preference will be the method name by default. This can be
32+
* overridden by specifying a string resource with the {@link #keyRes()}
33+
* parameter.
2834
*/
2935
@Retention(RetentionPolicy.CLASS)
3036
@Target(ElementType.METHOD)
3137
public @interface DefaultString {
3238
String value();
39+
40+
int keyRes() default ResId.DEFAULT_VALUE;
3341
}

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

Lines changed: 107 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -20,22 +20,27 @@
2020
import static com.sun.codemodel.JMod.PRIVATE;
2121
import static com.sun.codemodel.JMod.STATIC;
2222

23+
import java.lang.annotation.Annotation;
2324
import java.util.ArrayList;
25+
import java.util.HashMap;
2426
import java.util.List;
27+
import java.util.Map;
2528

2629
import javax.annotation.processing.ProcessingEnvironment;
2730
import javax.lang.model.element.Element;
2831
import javax.lang.model.element.ExecutableElement;
2932
import javax.lang.model.element.TypeElement;
3033
import javax.lang.model.util.ElementFilter;
3134

35+
import org.androidannotations.annotations.ResId;
3236
import org.androidannotations.annotations.sharedpreferences.DefaultBoolean;
3337
import org.androidannotations.annotations.sharedpreferences.DefaultFloat;
3438
import org.androidannotations.annotations.sharedpreferences.DefaultInt;
3539
import org.androidannotations.annotations.sharedpreferences.DefaultLong;
3640
import org.androidannotations.annotations.sharedpreferences.DefaultRes;
3741
import org.androidannotations.annotations.sharedpreferences.DefaultString;
3842
import org.androidannotations.annotations.sharedpreferences.SharedPref;
43+
import org.androidannotations.api.sharedpreferences.AbstractPrefField;
3944
import org.androidannotations.api.sharedpreferences.BooleanPrefField;
4045
import org.androidannotations.api.sharedpreferences.FloatPrefField;
4146
import org.androidannotations.api.sharedpreferences.IntPrefField;
@@ -44,16 +49,19 @@
4449
import org.androidannotations.helper.AndroidManifest;
4550
import org.androidannotations.helper.CanonicalNameConstants;
4651
import org.androidannotations.helper.IdAnnotationHelper;
52+
import org.androidannotations.helper.IdValidatorHelper;
53+
import org.androidannotations.helper.IdValidatorHelper.FallbackStrategy;
4754
import org.androidannotations.holder.SharedPrefHolder;
4855
import org.androidannotations.model.AndroidSystemServices;
4956
import org.androidannotations.model.AnnotationElements;
5057
import org.androidannotations.process.IsValid;
5158
import org.androidannotations.process.ProcessHolder;
5259
import org.androidannotations.rclass.IRClass;
60+
import org.androidannotations.rclass.IRClass.Res;
61+
import org.androidannotations.rclass.IRInnerClass;
5362

5463
import com.sun.codemodel.JBlock;
5564
import com.sun.codemodel.JClass;
56-
import com.sun.codemodel.JExpr;
5765
import com.sun.codemodel.JExpression;
5866
import com.sun.codemodel.JFieldRef;
5967
import com.sun.codemodel.JMethod;
@@ -63,6 +71,33 @@ public class SharedPrefHandler extends BaseAnnotationHandler<SharedPrefHolder> i
6371

6472
private IdAnnotationHelper annotationHelper;
6573

74+
private static final class DefaultPrefInfo<T> {
75+
final Class<? extends Annotation> annotationClass;
76+
final Class<? extends AbstractPrefField> prefFieldClass;
77+
final IRClass.Res resType;
78+
final T defaultValue;
79+
final String fieldHelperMethodName;
80+
81+
DefaultPrefInfo(Class<? extends Annotation> annotationClass, Class<? extends AbstractPrefField> prefFieldClass, Res resType, T defaultValue, String fieldHelperMethodName) {
82+
this.annotationClass = annotationClass;
83+
this.prefFieldClass = prefFieldClass;
84+
this.resType = resType;
85+
this.defaultValue = defaultValue;
86+
this.fieldHelperMethodName = fieldHelperMethodName;
87+
}
88+
}
89+
90+
private static final Map<String, DefaultPrefInfo<?>> DEFAULT_PREF_INFOS = new HashMap<String, SharedPrefHandler.DefaultPrefInfo<?>>() {
91+
private static final long serialVersionUID = 1L;
92+
{
93+
put("boolean", new DefaultPrefInfo<Boolean>(DefaultBoolean.class, BooleanPrefField.class, IRClass.Res.BOOL, false, "booleanField"));
94+
put("float", new DefaultPrefInfo<Float>(DefaultFloat.class, FloatPrefField.class, IRClass.Res.INTEGER, 0f, "floatField"));
95+
put("int", new DefaultPrefInfo<Integer>(DefaultInt.class, IntPrefField.class, IRClass.Res.INTEGER, 0, "intField"));
96+
put("long", new DefaultPrefInfo<Long>(DefaultLong.class, LongPrefField.class, IRClass.Res.INTEGER, 0l, "longField"));
97+
put(CanonicalNameConstants.STRING, new DefaultPrefInfo<String>(DefaultString.class, StringPrefField.class, IRClass.Res.STRING, "", "stringField"));
98+
}
99+
};
100+
66101
public SharedPrefHandler(ProcessingEnvironment processingEnvironment) {
67102
super(SharedPref.class, processingEnvironment);
68103
}
@@ -89,8 +124,24 @@ public void validate(Element element, AnnotationElements validatedElements, IsVa
89124
for (Element memberElement : inheritedMembers) {
90125
if (!memberElement.getEnclosingElement().asType().toString().equals("java.lang.Object")) {
91126
validatorHelper.isPrefMethod(memberElement, valid);
127+
128+
DefaultPrefInfo<?> info = null;
129+
IdValidatorHelper defaultAnnotationValidatorHelper = null;
130+
92131
if (valid.isValid()) {
132+
info = DEFAULT_PREF_INFOS.get(((ExecutableElement) memberElement).getReturnType().toString());
93133
validatorHelper.hasCorrectDefaultAnnotation((ExecutableElement) memberElement, valid);
134+
135+
if (valid.isValid() && memberElement.getAnnotation(DefaultRes.class) != null) {
136+
defaultAnnotationValidatorHelper = new IdValidatorHelper(new IdAnnotationHelper(processingEnv, DefaultRes.class.getName(), rClass));
137+
defaultAnnotationValidatorHelper.resIdsExist(memberElement, info.resType, FallbackStrategy.USE_ELEMENT_NAME, valid);
138+
} else if (valid.isValid() && memberElement.getAnnotation(info.annotationClass) != null) {
139+
defaultAnnotationValidatorHelper = new IdValidatorHelper(new IdAnnotationHelper(processingEnv, info.annotationClass.getName(), rClass));
140+
}
141+
142+
if (valid.isValid() && defaultAnnotationValidatorHelper != null) {
143+
defaultAnnotationValidatorHelper.annotationParameterIsOptionalValidResId(memberElement, IRClass.Res.STRING, "keyRes", valid);
144+
}
94145
}
95146
}
96147
}
@@ -117,23 +168,23 @@ private void generateConstructor(Element element, SharedPrefHolder holder) {
117168
constructorSuperBlock.invoke("super") //
118169
.arg(contextParam.invoke("getSharedPreferences") //
119170
.arg(invoke(getLocalClassName).arg(contextParam)) //
120-
.arg(JExpr.lit(mode)));
171+
.arg(lit(mode)));
121172
break;
122173
}
123174
case ACTIVITY: {
124175
JMethod getLocalClassName = getLocalClassName(holder);
125176
constructorSuperBlock.invoke("super") //
126177
.arg(contextParam.invoke("getSharedPreferences") //
127178
.arg(invoke(getLocalClassName).arg(contextParam) //
128-
.plus(JExpr.lit("_" + interfaceSimpleName))) //
129-
.arg(JExpr.lit(mode)));
179+
.plus(lit("_" + interfaceSimpleName))) //
180+
.arg(lit(mode)));
130181
break;
131182
}
132183
case UNIQUE: {
133184
constructorSuperBlock.invoke("super") //
134185
.arg(contextParam.invoke("getSharedPreferences") //
135-
.arg(JExpr.lit(interfaceSimpleName)) //
136-
.arg(JExpr.lit(mode)));
186+
.arg(lit(interfaceSimpleName)) //
187+
.arg(lit(mode)));
137188
break;
138189
}
139190
case APPLICATION_DEFAULT: {
@@ -175,8 +226,8 @@ private JMethod getLocalClassName(SharedPrefHolder holder) {
175226

176227
private void generateFieldMethodAndEditorFieldMethod(Element element, SharedPrefHolder sharedPrefHolder) {
177228
for (ExecutableElement method : getValidMethods(element)) {
178-
generateFieldMethod(sharedPrefHolder, method);
179-
sharedPrefHolder.createEditorFieldMethods(method);
229+
JExpression keyExpression = generateFieldMethod(sharedPrefHolder, method);
230+
sharedPrefHolder.createEditorFieldMethods(method, keyExpression);
180231
}
181232
}
182233

@@ -190,53 +241,44 @@ private List<ExecutableElement> getValidMethods(Element element) {
190241
return validMethods;
191242
}
192243

193-
private void generateFieldMethod(SharedPrefHolder holder, ExecutableElement method) {
194-
String returnType = method.getReturnType().toString();
195-
JExpression defaultValue = null;
196-
if ("boolean".equals(returnType)) {
197-
DefaultBoolean defaultAnnotation = method.getAnnotation(DefaultBoolean.class);
198-
if (defaultAnnotation != null) {
199-
defaultValue = JExpr.lit(defaultAnnotation.value());
200-
}
201-
createFieldMethod(holder, method, defaultValue, IRClass.Res.BOOL, JExpr.lit(false), BooleanPrefField.class, "booleanField");
202-
} else if ("float".equals(returnType)) {
203-
DefaultFloat defaultAnnotation = method.getAnnotation(DefaultFloat.class);
204-
if (defaultAnnotation != null) {
205-
defaultValue = JExpr.lit(defaultAnnotation.value());
206-
}
207-
createFieldMethod(holder, method, defaultValue, IRClass.Res.INTEGER, JExpr.lit(0f), FloatPrefField.class, "floatField");
208-
} else if ("int".equals(returnType)) {
209-
DefaultInt defaultAnnotation = method.getAnnotation(DefaultInt.class);
210-
if (defaultAnnotation != null) {
211-
defaultValue = JExpr.lit(defaultAnnotation.value());
212-
}
213-
createFieldMethod(holder, method, defaultValue, IRClass.Res.INTEGER, JExpr.lit(0), IntPrefField.class, "intField");
214-
} else if ("long".equals(returnType)) {
215-
DefaultLong defaultAnnotation = method.getAnnotation(DefaultLong.class);
216-
if (defaultAnnotation != null) {
217-
defaultValue = JExpr.lit(defaultAnnotation.value());
218-
}
219-
createFieldMethod(holder, method, defaultValue, IRClass.Res.INTEGER, JExpr.lit(0l), LongPrefField.class, "longField");
220-
} else if (CanonicalNameConstants.STRING.equals(returnType)) {
221-
DefaultString defaultAnnotation = method.getAnnotation(DefaultString.class);
222-
if (defaultAnnotation != null) {
223-
defaultValue = JExpr.lit(defaultAnnotation.value());
224-
}
225-
createFieldMethod(holder, method, defaultValue, IRClass.Res.STRING, JExpr.lit(""), StringPrefField.class, "stringField");
226-
}
244+
private JExpression generateFieldMethod(SharedPrefHolder holder, ExecutableElement method) {
245+
DefaultPrefInfo<?> info = DEFAULT_PREF_INFOS.get(method.getReturnType().toString());
246+
return createFieldMethod(holder, method, info.annotationClass, info.prefFieldClass, info.defaultValue, info.resType, info.fieldHelperMethodName);
227247
}
228248

229-
private void createFieldMethod(SharedPrefHolder holder, ExecutableElement method, JExpression defaultAnnotationValue, IRClass.Res res, JExpression defValue, Class<?> booleanPrefFieldClass, String fieldHelperMethodName) {
230-
JExpression defaultValue = defaultAnnotationValue;
231-
if (defaultAnnotationValue == null) {
232-
if (method.getAnnotation(DefaultRes.class) != null) {
233-
defaultValue = extractResValue(holder, method, res);
234-
} else {
235-
defaultValue = defValue;
236-
}
249+
private JExpression createFieldMethod(SharedPrefHolder holder, ExecutableElement method, Class<? extends Annotation> annotationClass, Class<? extends AbstractPrefField> prefFieldClass, Object defaultValue, Res resType, String fieldHelperMethodName) {
250+
Annotation annotation = method.getAnnotation(annotationClass);
251+
JExpression defaultValueExpr;
252+
253+
if (annotation != null) {
254+
defaultValueExpr = litObject(annotationHelper.extractAnnotationParameter(method, annotationClass.getName(), "value"));
255+
} else if (method.getAnnotation(DefaultRes.class) != null) {
256+
defaultValueExpr = extractResValue(holder, method, resType);
257+
annotationClass = DefaultRes.class;
258+
} else {
259+
defaultValueExpr = litObject(defaultValue);
260+
annotationClass = null;
237261
}
262+
263+
int keyResId = ResId.DEFAULT_VALUE;
264+
265+
if (annotationClass != null) {
266+
keyResId = annotationHelper.extractAnnotationParameter(method, annotationClass.getName(), "keyRes");
267+
}
268+
269+
JExpression keyExpression;
238270
String fieldName = method.getSimpleName().toString();
239-
holder.createFieldMethod(booleanPrefFieldClass, fieldName, fieldHelperMethodName, defaultValue);
271+
272+
if (keyResId == ResId.DEFAULT_VALUE) {
273+
keyExpression = lit(fieldName);
274+
} else {
275+
IRInnerClass idClass = rClass.get(IRClass.Res.STRING);
276+
JFieldRef idRef = idClass.getIdStaticRef(keyResId, processHolder);
277+
keyExpression = holder.getContextField().invoke("getString").arg(idRef);
278+
}
279+
280+
holder.createFieldMethod(prefFieldClass, keyExpression, fieldName, fieldHelperMethodName, defaultValueExpr);
281+
return keyExpression;
240282
}
241283

242284
private JExpression extractResValue(SharedPrefHolder holder, Element method, IRClass.Res res) {
@@ -258,4 +300,18 @@ private JExpression extractResValue(SharedPrefHolder holder, Element method, IRC
258300
}
259301
return holder.getContextField().invoke("getResources").invoke(resourceGetMethodName).arg(idRef);
260302
}
303+
304+
private static JExpression litObject(Object o) {
305+
if (o instanceof Integer) {
306+
return lit((Integer) o);
307+
} else if (o instanceof Float) {
308+
return lit((Float) o);
309+
} else if (o instanceof Long) {
310+
return lit((Long) o);
311+
} else if (o instanceof Boolean) {
312+
return lit((Boolean) o);
313+
} else {
314+
return lit((String) o);
315+
}
316+
}
261317
}

0 commit comments

Comments
 (0)