Skip to content

Commit aa6cf51

Browse files
committed
Change ValidatorParameterHelper to a fluent API
1 parent a4c647c commit aa6cf51

6 files changed

Lines changed: 284 additions & 3 deletions

File tree

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

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import javax.lang.model.element.VariableElement;
2424

2525
import org.androidannotations.helper.AndroidManifest;
26+
import org.androidannotations.helper.CanonicalNameConstants;
2627
import org.androidannotations.helper.IdAnnotationHelper;
2728
import org.androidannotations.helper.IdValidatorHelper;
2829
import org.androidannotations.holder.EComponentWithViewSupportHolder;
@@ -65,6 +66,8 @@ public void validate(Element element, AnnotationElements validatedElements, IsVa
6566
validatorHelper.returnTypeIsVoid((ExecutableElement) element, valid);
6667

6768
validatorHelper.hasSeekBarTouchTrackingMethodParameters((ExecutableElement) element, valid);
69+
70+
validatorHelper.param.oneparam().type(CanonicalNameConstants.SEEKBAR).optional().validate((ExecutableElement) element, valid);
6871
}
6972

7073
@Override

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

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,8 @@ public void validate(Element element, AnnotationElements validatedElements, IsVa
6868
validatorHelper.returnTypeIsVoid((ExecutableElement) element, valid);
6969

7070
validatorHelper.hasAfterTextChangedMethodParameters((ExecutableElement) element, valid);
71+
72+
validatorHelper.param.anyorder().type(CanonicalNameConstants.TEXT_VIEW).optional().type(CanonicalNameConstants.EDITABLE).optional().validate((ExecutableElement) element, valid);
7173
}
7274

7375
@Override

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import javax.lang.model.type.TypeMirror;
2525

2626
import org.androidannotations.annotations.Click;
27+
import org.androidannotations.helper.CanonicalNameConstants;
2728
import org.androidannotations.holder.EComponentWithViewSupportHolder;
2829
import org.androidannotations.model.AnnotationElements;
2930
import org.androidannotations.process.IsValid;
@@ -50,7 +51,7 @@ public void validate(Element element, AnnotationElements validatedElements, IsVa
5051

5152
validatorHelper.returnTypeIsVoid(executableElement, valid);
5253

53-
validatorHelper.param.zeroOrOneViewParameter(executableElement, valid);
54+
validatorHelper.param.oneparam().extendsType(CanonicalNameConstants.VIEW).optional().validate(executableElement, valid);
5455
}
5556

5657
@Override

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

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
import org.androidannotations.annotations.ItemClick;
3131
import org.androidannotations.helper.APTCodeModelHelper;
32+
import org.androidannotations.helper.CanonicalNameConstants;
3233
import org.androidannotations.holder.EComponentWithViewSupportHolder;
3334
import org.androidannotations.model.AnnotationElements;
3435
import org.androidannotations.process.IsValid;
@@ -57,7 +58,12 @@ public void validate(Element element, AnnotationElements validatedElements, IsVa
5758

5859
validatorHelper.returnTypeIsVoid(executableElement, valid);
5960

60-
validatorHelper.param.zeroOrOneParameter(executableElement, valid);
61+
validatorHelper.param.inorder().extendsType(CanonicalNameConstants.ADAPTER_VIEW).optional() //
62+
.anyType().optional() //
63+
.extendsType(CanonicalNameConstants.VIEW).optional() //
64+
.type(int.class.getName()).optional() //
65+
.type(long.class.getName()).optional() //
66+
.validate(executableElement, valid);
6167
}
6268

6369
@Override

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

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

5959
validatorHelper.isNotFinal(element, valid);
6060

61-
validatorHelper.param.zeroParameter(executableElement, valid);
61+
validatorHelper.param.noparam().validate(executableElement, valid);
6262
}
6363

6464
@Override

‎AndroidAnnotations/androidannotations/src/main/java/org/androidannotations/helper/ValidatorParameterHelper.java‎

Lines changed: 269 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,9 +20,12 @@
2020
import java.lang.annotation.Annotation;
2121
import java.util.Arrays;
2222
import java.util.Collection;
23+
import java.util.LinkedHashSet;
2324
import java.util.List;
25+
import java.util.Set;
2426

2527
import javax.lang.model.element.ExecutableElement;
28+
import javax.lang.model.element.TypeElement;
2629
import javax.lang.model.element.VariableElement;
2730
import javax.lang.model.type.TypeKind;
2831
import javax.lang.model.type.TypeMirror;
@@ -34,6 +37,272 @@
3437

3538
public class ValidatorParameterHelper {
3639

40+
public interface Validator {
41+
void validate(ExecutableElement executableElement, IsValid valid);
42+
}
43+
44+
public interface ParameterValidator<T> extends Validator {
45+
T extendsType(String fullyQualifiedName);
46+
47+
T type(String fullyQualifiedName);
48+
49+
T anyType();
50+
}
51+
52+
public static class ParameterRequirement<O extends Validator> implements Validator {
53+
54+
protected final ParameterValidator<?> validator;
55+
56+
protected final MethodParameter lastParameter;
57+
58+
public ParameterRequirement(ParameterValidator<?> anyOrderParameterValidator, MethodParameter lastParameter) {
59+
this.validator = anyOrderParameterValidator;
60+
this.lastParameter = lastParameter;
61+
}
62+
63+
@SuppressWarnings("unchecked")
64+
public final O optional() {
65+
lastParameter.required = false;
66+
return (O) validator;
67+
}
68+
69+
@SuppressWarnings("unchecked")
70+
public final O required() {
71+
return (O) validator;
72+
}
73+
74+
@Override
75+
public final void validate(ExecutableElement executableElement, IsValid valid) {
76+
validator.validate(executableElement, valid);
77+
}
78+
79+
}
80+
81+
public static class ChainableParameterRequirement<O extends Validator> extends ParameterRequirement<O> implements ParameterValidator<ParameterRequirement<O>> {
82+
public ChainableParameterRequirement(ParameterValidator<?> anyOrderParameterValidator, MethodParameter lastParameter) {
83+
super(anyOrderParameterValidator, lastParameter);
84+
}
85+
86+
@Override
87+
public final ParameterRequirement<O> extendsType(String fullyQualifiedName) {
88+
validator.extendsType(fullyQualifiedName);
89+
return this;
90+
}
91+
92+
@Override
93+
public final ParameterRequirement<O> type(String fullyQualifiedName) {
94+
validator.extendsType(fullyQualifiedName);
95+
return this;
96+
}
97+
98+
@Override
99+
public ParameterRequirement<O> anyType() {
100+
validator.anyType();
101+
return this;
102+
}
103+
}
104+
105+
abstract class ParameterValidatorBase<T> implements ParameterValidator<T> {
106+
protected Set<MethodParameter> expectedParameters = new LinkedHashSet<MethodParameter>();
107+
108+
protected MethodParameter addExpectedParameter(String fullyQualifiedName, boolean required, boolean extending) {
109+
MethodParameter param = new MethodParameter(fullyQualifiedName, required, extending);
110+
expectedParameters.add(param);
111+
return param;
112+
}
113+
114+
protected final boolean extendsType(VariableElement param, String fullyQualifiedName) {
115+
TypeMirror elementType = param.asType();
116+
117+
TypeElement typeElement = annotationHelper.typeElementFromQualifiedName(fullyQualifiedName);
118+
if (typeElement != null) {
119+
TypeMirror expectedType = typeElement.asType();
120+
return annotationHelper.isSubtype(elementType, expectedType);
121+
}
122+
return false;
123+
}
124+
125+
protected final boolean exactType(VariableElement param, String fullyQualifiedName) {
126+
return param.asType().toString().equals(fullyQualifiedName);
127+
}
128+
129+
protected void invalidate(ExecutableElement executableElement, IsValid valid) {
130+
printMessage(executableElement);
131+
valid.invalidate();
132+
}
133+
134+
protected final void printMessage(ExecutableElement element) {
135+
annotationHelper.printAnnotationError(element, "%s can only have the following parameters: " + createMessage(element));
136+
}
137+
138+
protected String createMessage(ExecutableElement element) {
139+
StringBuilder builder = new StringBuilder();
140+
builder.append("[ ");
141+
for (MethodParameter parameter : expectedParameters) {
142+
builder.append(parameter).append(",");
143+
}
144+
return builder.append(" ]").toString();
145+
}
146+
147+
@Override
148+
public void validate(ExecutableElement executableElement, IsValid valid) {
149+
List<? extends VariableElement> parameters = executableElement.getParameters();
150+
151+
if (parameters.size() > expectedParameters.size()) {
152+
invalidate(executableElement, valid);
153+
return;
154+
}
155+
156+
int index = 0;
157+
158+
for (MethodParameter expectedParameter : expectedParameters) {
159+
if (index < parameters.size()) {
160+
VariableElement parameter = parameters.get(index);
161+
162+
if (expectedParameter.extending && !extendsType(parameter, expectedParameter.typeName)) {
163+
invalidate(executableElement, valid);
164+
return;
165+
} else if (!expectedParameter.extending && !exactType(parameter, expectedParameter.typeName)) {
166+
invalidate(executableElement, valid);
167+
return;
168+
}
169+
} else if (expectedParameter.required) {
170+
invalidate(executableElement, valid);
171+
}
172+
173+
++index;
174+
}
175+
}
176+
177+
@Override
178+
public T anyType() {
179+
return extendsType(CanonicalNameConstants.OBJECT);
180+
}
181+
}
182+
183+
public class AnyOrderParameterValidator extends ParameterValidatorBase<ChainableParameterRequirement<AnyOrderParameterValidator>> {
184+
185+
@Override
186+
public void validate(ExecutableElement executableElement, IsValid valid) {
187+
for (VariableElement parameter : executableElement.getParameters()) {
188+
MethodParameter foundParameter = null;
189+
190+
for (MethodParameter expectedParameter : expectedParameters) {
191+
if (exactType(parameter, expectedParameter.typeName) || extendsType(parameter, expectedParameter.typeName)) {
192+
foundParameter = expectedParameter;
193+
break;
194+
}
195+
}
196+
197+
if (foundParameter != null) {
198+
expectedParameters.remove(foundParameter);
199+
} else {
200+
invalidate(executableElement, valid);
201+
return;
202+
}
203+
}
204+
205+
for (MethodParameter expectedParameter : expectedParameters) {
206+
if (expectedParameter.required) {
207+
invalidate(executableElement, valid);
208+
return;
209+
}
210+
}
211+
}
212+
213+
@Override
214+
public ChainableParameterRequirement<AnyOrderParameterValidator> extendsType(String fullyQualifiedName) {
215+
return new ChainableParameterRequirement<AnyOrderParameterValidator>(this, addExpectedParameter(fullyQualifiedName, true, true));
216+
}
217+
218+
@Override
219+
public ChainableParameterRequirement<AnyOrderParameterValidator> type(String fullyQualifiedName) {
220+
return new ChainableParameterRequirement<AnyOrderParameterValidator>(this, addExpectedParameter(fullyQualifiedName, true, false));
221+
}
222+
223+
@Override
224+
protected String createMessage(ExecutableElement element) {
225+
return super.createMessage(element) + " in any order";
226+
}
227+
}
228+
229+
public class InOrderParameterValidator extends ParameterValidatorBase<ChainableParameterRequirement<InOrderParameterValidator>> {
230+
231+
@Override
232+
public ChainableParameterRequirement<InOrderParameterValidator> extendsType(String fullyQualifiedName) {
233+
return new ChainableParameterRequirement<InOrderParameterValidator>(this, addExpectedParameter(fullyQualifiedName, true, true));
234+
}
235+
236+
@Override
237+
public ChainableParameterRequirement<InOrderParameterValidator> type(String fullyQualifiedName) {
238+
return new ChainableParameterRequirement<InOrderParameterValidator>(this, addExpectedParameter(fullyQualifiedName, true, false));
239+
}
240+
241+
@Override
242+
protected String createMessage(ExecutableElement element) {
243+
return super.createMessage(element) + " in the order above";
244+
}
245+
}
246+
247+
public class OneParamValidator extends ParameterValidatorBase<ParameterRequirement<Validator>> {
248+
249+
@Override
250+
public ParameterRequirement<Validator> extendsType(String fullyQualifiedName) {
251+
return new ParameterRequirement<Validator>(this, addExpectedParameter(fullyQualifiedName, true, true));
252+
}
253+
254+
@Override
255+
public ParameterRequirement<Validator> type(String fullyQualifiedName) {
256+
return new ParameterRequirement<Validator>(this, addExpectedParameter(fullyQualifiedName, true, false));
257+
}
258+
259+
}
260+
261+
public class NoParamValidator implements Validator {
262+
263+
@Override
264+
public void validate(ExecutableElement executableElement, IsValid valid) {
265+
if (!executableElement.getParameters().isEmpty()) {
266+
annotationHelper.printAnnotationError(executableElement, "%s cannot have any parameters");
267+
valid.invalidate();
268+
}
269+
}
270+
}
271+
272+
public class MethodParameter {
273+
274+
private String typeName;
275+
private boolean required;
276+
private boolean extending;
277+
278+
public MethodParameter(String typeName, boolean required, boolean extending) {
279+
this.typeName = typeName;
280+
this.required = required;
281+
this.extending = extending;
282+
}
283+
284+
@Override
285+
public String toString() {
286+
return "[ " + (extending ? " extending " : "") + typeName + (required ? " (required) " : " (optional) " + "]");
287+
}
288+
}
289+
290+
public Validator noparam() {
291+
return new NoParamValidator();
292+
}
293+
294+
public OneParamValidator oneparam() {
295+
return new OneParamValidator();
296+
}
297+
298+
public InOrderParameterValidator inorder() {
299+
return new InOrderParameterValidator();
300+
}
301+
302+
public AnyOrderParameterValidator anyorder() {
303+
return new AnyOrderParameterValidator();
304+
}
305+
37306
private static final List<String> ANDROID_SHERLOCK_MENU_ITEM_QUALIFIED_NAMES = asList(CanonicalNameConstants.MENU_ITEM, CanonicalNameConstants.SHERLOCK_MENU_ITEM);
38307
private static final List<String> EDITOR_ACTION_ALLOWED_PARAMETER_TYPES = asList(CanonicalNameConstants.TEXT_VIEW, CanonicalNameConstants.INTEGER, "int", CanonicalNameConstants.KEY_EVENT);
39308
private static final List<String> PREFERENCE_CHANGE_ALLOWED_NEWVALUE_PARAM = asList(CanonicalNameConstants.OBJECT, CanonicalNameConstants.SET, CanonicalNameConstants.STRING, CanonicalNameConstants.BOOLEAN);

0 commit comments

Comments
 (0)