/*
* Copyright (C) 2012 Mobs and Geeks
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the
* License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND,
* either express or implied. See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.pc.ioc.verification;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import android.content.Context;
import android.util.Log;
import android.view.View;
import android.widget.Checkable;
import android.widget.TextView;
import com.android.pc.ioc.verification.annotation.Checked;
import com.android.pc.ioc.verification.annotation.ConfirmPassword;
import com.android.pc.ioc.verification.annotation.Email;
import com.android.pc.ioc.verification.annotation.IpAddress;
import com.android.pc.ioc.verification.annotation.NumberRule;
import com.android.pc.ioc.verification.annotation.Password;
import com.android.pc.ioc.verification.annotation.Regex;
import com.android.pc.ioc.verification.annotation.Required;
import com.android.pc.ioc.verification.annotation.TextRule;
/**
* Class contains {@code static} methods that return appropriate {@link Rule}s for Saripaar annotations.
*
* @author Ragunath Jawahar <rj@mobsandgeeks.com>
*/
class AnnotationToRuleConverter {
// Debug
static final String TAG = AnnotationToRuleConverter.class.getSimpleName();
// Constants
static final String WARN_TEXT = "%s - @%s can only be applied to TextView and " + "its subclasses.";
static final String WARN_CHECKABLE = "%s - @%s can only be applied to Checkable, " + "its implementations and subclasses.";
public static Rule<?> getRule(Field field, View view, Annotation annotation) {
Class<?> annotationClass = annotation.getClass();
if (Required.class.isAssignableFrom(annotationClass)) {
return getRequiredRule(field, view, (Required) annotation);
} else if (Checked.class.isAssignableFrom(annotationClass)) {
return getCheckedRule(field, view, (Checked) annotation);
} else if (TextRule.class.isAssignableFrom(annotationClass)) {
return getTextRule(field, view, (TextRule) annotation);
} else if (Regex.class.isAssignableFrom(annotationClass)) {
return getRegexRule(field, view, (Regex) annotation);
} else if (NumberRule.class.isAssignableFrom(annotationClass)) {
return getNumberRule(field, view, (NumberRule) annotation);
} else if (Password.class.isAssignableFrom(annotationClass)) {
return getPasswordRule(field, view, (Password) annotation);
} else if (Email.class.isAssignableFrom(annotationClass)) {
return getEmailRule(field, view, (Email) annotation);
} else if (IpAddress.class.isAssignableFrom(annotationClass)) {
return getIpAddressRule(field, view, (IpAddress) annotation);
}
return null;
}
public static Rule<?> getRule(Field field, View view, Annotation annotation, Object... params) {
Class<?> annotationClass = annotation.getClass();
if (ConfirmPassword.class.isAssignableFrom(annotationClass)) {
TextView passwordTextView = (TextView) params[0];
return getConfirmPasswordRule(field, view, (ConfirmPassword) annotation, passwordTextView);
}
return (params == null || params.length == 0) ? getRule(field, view, annotation) : null;
}
private static Rule<TextView> getRequiredRule(Field field, View view, Required required) {
if (!TextView.class.isAssignableFrom(view.getClass())) {
Log.w(TAG, String.format(WARN_TEXT, field.getName(), Required.class.getSimpleName()));
return null;
}
int messageResId = required.messageResId();
String message = messageResId != 0 ? view.getContext().getString(messageResId) : required.message();
return Rules.required(message, required.trim());
}
private static Rule<View> getTextRule(Field field, View view, TextRule textRule) {
if (!TextView.class.isAssignableFrom(view.getClass())) {
Log.w(TAG, String.format(WARN_TEXT, field.getName(), TextRule.class.getSimpleName()));
return null;
}
List<Rule<?>> rules = new ArrayList<Rule<?>>();
int messageResId = textRule.messageResId();
String message = messageResId != 0 ? view.getContext().getString(messageResId) : textRule.message();
if (textRule.minLength() > 0) {
rules.add(Rules.minLength(null, textRule.minLength(), textRule.trim()));
}
if (textRule.maxLength() != Integer.MAX_VALUE) {
rules.add(Rules.maxLength(null, textRule.maxLength(), textRule.trim()));
}
Rule<?>[] ruleArray = new Rule<?>[rules.size()];
rules.toArray(ruleArray);
return Rules.and(message, ruleArray);
}
private static Rule<TextView> getRegexRule(Field field, View view, Regex regexRule) {
if (!TextView.class.isAssignableFrom(view.getClass())) {
Log.w(TAG, String.format(WARN_TEXT, field.getName(), Regex.class.getSimpleName()));
return null;
}
Context context = view.getContext();
int messageResId = regexRule.messageResId();
String message = messageResId != 0 ? context.getString(messageResId) : regexRule.message();
int patternResId = regexRule.patternResId();
String pattern = patternResId != 0 ? view.getContext().getString(patternResId) : regexRule.pattern();
return Rules.regex(message, pattern, regexRule.trim());
}
private static Rule<View> getNumberRule(Field field, View view, NumberRule numberRule) {
if (!TextView.class.isAssignableFrom(view.getClass())) {
Log.w(TAG, String.format(WARN_TEXT, field.getName(), NumberRule.class.getSimpleName()));
return null;
} else if (numberRule.type() == null) {
throw new IllegalArgumentException(String.format("@%s.type() cannot be null.", NumberRule.class.getSimpleName()));
}
List<Rule<?>> rules = new ArrayList<Rule<?>>();
int messageResId = numberRule.messageResId();
String message = messageResId != 0 ? view.getContext().getString(messageResId) : numberRule.message();
switch (numberRule.type()) {
case INTEGER:
case LONG:
Rules.regex(null, Rules.REGEX_INTEGER, true);
break;
case FLOAT:
case DOUBLE:
Rules.regex(null, Rules.REGEX_DECIMAL, true);
break;
}
if (numberRule.lt() != Double.MIN_VALUE) {
String ltNumber = String.valueOf(numberRule.lt());
double number = Double.parseDouble(ltNumber);
switch (numberRule.type()) {
case INTEGER:
rules.add(Rules.lt(null, ((int) number)));
break;
case LONG:
rules.add(Rules.lt(null, ((long) number)));
break;
case FLOAT:
rules.add(Rules.lt(null, Float.parseFloat(ltNumber)));
break;
case DOUBLE:
rules.add(Rules.lt(null, Double.parseDouble(ltNumber)));
break;
}
}
if (numberRule.gt() != Double.MAX_VALUE) {
String gtNumber = String.valueOf(numberRule.gt());
double number = Double.parseDouble(gtNumber);
switch (numberRule.type()) {
case INTEGER:
rules.add(Rules.gt(null, ((int) number)));
break;
case LONG:
rules.add(Rules.gt(null, ((long) number)));
break;
case FLOAT:
rules.add(Rules.gt(null, Float.parseFloat(gtNumber)));
break;
case DOUBLE:
rules.add(Rules.gt(null, Double.parseDouble(gtNumber)));
break;
}
}
if (numberRule.eq() != Double.MAX_VALUE) {
String eqNumber = String.valueOf(numberRule.eq());
double number = Double.parseDouble(eqNumber);
switch (numberRule.type()) {
case INTEGER:
rules.add(Rules.eq(null, ((int) number)));
break;
case LONG:
rules.add(Rules.eq(null, ((long) number)));
break;
case FLOAT:
rules.add(Rules.eq(null, Float.parseFloat(eqNumber)));
break;
case DOUBLE:
rules.add(Rules.eq(null, Double.parseDouble(eqNumber)));
break;
}
}
Rule<?>[] ruleArray = new Rule<?>[rules.size()];
rules.toArray(ruleArray);
return Rules.and(message, ruleArray);
}
private static Rule<View> getPasswordRule(Field field, View view, Password password) {
if (!TextView.class.isAssignableFrom(view.getClass())) {
Log.w(TAG, String.format(WARN_TEXT, field.getName(), Password.class.getSimpleName()));
return null;
}
int messageResId = password.messageResId();
String message = messageResId != 0 ? view.getContext().getString(messageResId) : password.message();
List<Rule<?>> rules = new ArrayList<Rule<?>>();
if (password.minLength() > 0) {
rules.add(Rules.minLength(null, password.minLength(), password.trim()));
}
if (password.maxLength() != Integer.MAX_VALUE) {
rules.add(Rules.maxLength(null, password.maxLength(), password.trim()));
}
Rule<?>[] ruleArray = new Rule<?>[rules.size()];
rules.toArray(ruleArray);
return Rules.and(message, ruleArray);
}
private static Rule<TextView> getConfirmPasswordRule(Field field, View view, ConfirmPassword confirmPassword, TextView passwordTextView) {
if (!TextView.class.isAssignableFrom(view.getClass())) {
Log.w(TAG, String.format(WARN_TEXT, field.getName(), ConfirmPassword.class.getSimpleName()));
return null;
}
int messageResId = confirmPassword.messageResId();
String message = messageResId != 0 ? view.getContext().getString(messageResId) : confirmPassword.message();
return Rules.eq(message, passwordTextView);
}
private static Rule<View> getEmailRule(Field field, View view, Email email) {
if (!TextView.class.isAssignableFrom(view.getClass())) {
Log.w(TAG, String.format(WARN_TEXT, field.getName(), Regex.class.getSimpleName()));
return null;
}
// int messageResId = email.messageResId();
// String message = messageResId != 0 ? view.getContext().getString(messageResId) : email.message();
// return Rules.or(message, Rules.eq(null, Rules.EMPTY_STRING), Rules.regex(message, Rules.REGEX_EMAIL, true));
int messageResId = email.messageResId();
String message = messageResId != 0 ? view.getContext().getString(messageResId) : email.message();
if (email.empty()) {
return Rules.or(message, Rules.eq(null, Rules.EMPTY_STRING), Rules.regex(message, Rules.REGEX_EMAIL, true));
}
List<Rule<?>> rules = new ArrayList<Rule<?>>();
rules.add(Rules.required(message, true));
rules.add(Rules.regex(message, Rules.REGEX_EMAIL, true));
Rule<?>[] ruleArray = new Rule<?>[rules.size()];
rules.toArray(ruleArray);
return Rules.and(message, ruleArray);
}
private static Rule<View> getIpAddressRule(Field field, View view, IpAddress ipAddress) {
if (!TextView.class.isAssignableFrom(view.getClass())) {
Log.w(TAG, String.format(WARN_TEXT, field.getName(), IpAddress.class.getSimpleName()));
return null;
}
int messageResId = ipAddress.messageResId();
String message = messageResId != 0 ? view.getContext().getString(messageResId) : ipAddress.message();
return Rules.or(message, Rules.eq(null, Rules.EMPTY_STRING), Rules.regex(message, Rules.REGEX_IP_ADDRESS, true));
}
private static Rule<Checkable> getCheckedRule(Field field, View view, Checked checked) {
if (!Checkable.class.isAssignableFrom(view.getClass())) {
Log.w(TAG, String.format(WARN_CHECKABLE, field.getName(), Checked.class.getSimpleName()));
return null;
}
int messageResId = checked.messageResId();
String message = messageResId != 0 ? view.getContext().getString(messageResId) : checked.message();
return Rules.checked(message, checked.checked());
}
}