Skip to content

Instantly share code, notes, and snippets.

@juliomarcos
Created August 16, 2014 17:52
Show Gist options
  • Save juliomarcos/948344a2b3390a48e0d8 to your computer and use it in GitHub Desktop.
Save juliomarcos/948344a2b3390a48e0d8 to your computer and use it in GitHub Desktop.
Android form validator
package /* YOUR PACKAGE HERE */;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import android.app.Activity;
import android.app.AlertDialog;
import android.text.Html;
import android.text.TextUtils;
import android.view.View;
import android.widget.EditText;
import android.widget.Spinner;
public class FormValidator {
private class LabelFieldSimpleRuleTriplet {
public String fieldSimpleRule;
public String fieldLabel;
public View fieldView;
}
public interface OnLegalListener {
public void onLegal();
}
@SuppressWarnings("serial")
public class ListenerNotSetException extends RuntimeException {
public ListenerNotSetException(String message) {
super(message);
}
}
private static final String EQ = "equal";
private final static String NOT_EMPTY = "not_empty";
private static final String IGNORE_NOT_EMPTY_IF_ALL_EMPTY = "ignore_not_empty_if_all_empty";
private class RuleContainer {
public String rule;
public Integer msgResId;
public View[] views;
public RuleContainer(String rule, Integer msgResId, View[] views) {
this.rule = rule;
this.msgResId = msgResId;
this.views = views;
}
}
@SuppressWarnings("serial")
private class RuleContainers extends ArrayList<RuleContainer> {
public RuleContainer findRule(String rule) {
for (RuleContainer ruleContainer : this) {
if (ruleContainer.rule.equals(rule)) return ruleContainer;
}
return null;
}
public List<View> findViews(String rule) {
List<View> acc = new ArrayList<View>();
for (RuleContainer ruleContainer : this) {
if (ruleContainer.rule.equals(rule)) {
for (int i = 0; i < ruleContainer.views.length; i++) {
acc.add(ruleContainer.views[i]);
}
}
}
return acc;
}
}
private List<LabelFieldSimpleRuleTriplet> labelFieldSimpleRuleTripletList;
private List<String> criticas;
private RuleContainers ruleContainers;
private OnLegalListener onLegalListener;
public void setOnLegalListener(OnLegalListener onLegalListener) {
this.onLegalListener = onLegalListener;
}
public FormValidator(OnLegalListener onLegalListener) {
labelFieldSimpleRuleTripletList = new ArrayList<FormValidator.LabelFieldSimpleRuleTriplet>();
criticas = new ArrayList<String>();
ruleContainers = new RuleContainers();
criticasComRegras = new ArrayList<Integer>();
this.onLegalListener = onLegalListener;
}
public void notEmpty(final String label, final View field) {
labelFieldSimpleRuleTripletList.add(new LabelFieldSimpleRuleTriplet() {{
fieldSimpleRule = NOT_EMPTY;
fieldLabel = label;
fieldView = field;
}});
}
public void mirror(int msgResId, View... views) {
rule(EQ, msgResId, views);
}
public static class RandomDataOptions {
public final static int ALL_RANDOM = 0;
public final static int ALL_SAME = 1;
static String randomString(int length) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < length; i++) {
char randomCharacter = (char) (65 + Math.random() * 57);
sb.append(randomCharacter);
}
return sb.toString();
}
}
public void fillViewsWithRandomDataForTesting() {
fillViewsWithRandomDataForTesting(RandomDataOptions.ALL_RANDOM);
}
public void fillViewsWithRandomDataForTesting(int options) {
if (options == RandomDataOptions.ALL_RANDOM) {
for (LabelFieldSimpleRuleTriplet pair : labelFieldSimpleRuleTripletList) {
setViewValue(pair.fieldView, RandomDataOptions.randomString(7));
}
} else if (options == RandomDataOptions.ALL_SAME) {
String randomValue = RandomDataOptions.randomString(7);
for (LabelFieldSimpleRuleTriplet pair : labelFieldSimpleRuleTripletList) {
setViewValue(pair.fieldView, randomValue);
}
}
}
public void validate(Activity activity) {
if (onLegalListener == null) throw new ListenerNotSetException("validate() can't be called without setting an onLegalListener");
for (LabelFieldSimpleRuleTriplet labelFieldRuleTriplet : labelFieldSimpleRuleTripletList) {
String simpleRule = labelFieldRuleTriplet.fieldSimpleRule;
String label = labelFieldRuleTriplet.fieldLabel;
View view = labelFieldRuleTriplet.fieldView;
String viewValue = getViewValue(view);
mayAccumulateCritique(simpleRule, viewValue, label);
}
for (RuleContainer ruleContainer : ruleContainers) {
mayAccumulateRuledCritique(ruleContainer);
}
if (criticas.size() > 0 || criticasComRegras.size() > 0) {
buildErrorDialog(activity);
}
else {
onLegalListener.onLegal();
}
}
private void mayAccumulateCritique(String rule, String fieldValue, String fieldName) {
RuleContainer matchedRule = ruleContainers.findRule(IGNORE_NOT_EMPTY_IF_ALL_EMPTY);
if (rule.equals(NOT_EMPTY) && matchedRule != null) {
// do special comparison
// TODO: cada regra especial tinha que ter sua classe, e todas as
// regras deveriam ficar em uma RuleContainer. Ter dois tipos,
// simple rule e rule normal é muito ruim.
List<View> ruleViews = new ArrayList<View>(Arrays.asList(matchedRule.views));
List<View> matchedViews = findSimpleRuledViews(rule);
final List<String> viewValuesThatMatters = new ArrayList<String>();
for (View v : matchedViews) {
if (ruleViews.contains(v)) {
viewValuesThatMatters.add(getViewValue(v));
}
}
// Quero tanto java 8, esse tipo de loop...
boolean allEmpty = true;
for (String value : viewValuesThatMatters) {
if (!TextUtils.isEmpty(value)) {
allEmpty = false;
break;
}
}
if (!allEmpty) { // adicionar views das matched rules
if (rule.equals(NOT_EMPTY)){
if (TextUtils.isEmpty(fieldValue)) {
criticas.add(fieldName);
}
}
}
} else if (rule.equals(NOT_EMPTY)){
if (TextUtils.isEmpty(fieldValue)) {
criticas.add(fieldName);
}
}
}
private List<View> findSimpleRuledViews(String rule) {
List<View> acc = new ArrayList<View>();
for (LabelFieldSimpleRuleTriplet triplet : labelFieldSimpleRuleTripletList) {
if (triplet.fieldSimpleRule.equals(rule)) acc.add(triplet.fieldView);
}
return acc;
}
private String getViewValue(View view) {
if (view instanceof Spinner) {
Spinner spinner = (Spinner) view;
return spinner.getSelectedItem().toString();
} else if (view instanceof EditText) {
EditText editText = (EditText) view;
return editText.getText().toString();
}
// TODO: Talvez seja necessário tratar checkboxes
return null;
}
private void mayAccumulateRuledCritique(RuleContainer ruleContainer) {
String rule = ruleContainer.rule;
View[] views = ruleContainer.views;
Integer msgResId = ruleContainer.msgResId;
if (rule.equals(EQ)) {
String value = getViewValue(views[0]);
for (int i = 1; i < views.length; i++) {
String thatValue = getViewValue(views[i]);
if (!thatValue.equals(value)) {
criticasComRegras.add(msgResId);
return;
}
value = thatValue;
}
}
}
private void buildErrorDialog(Activity activity) {
StringBuilder sb = new StringBuilder();
if (criticas.size() > 0) {
sb.append(activity.getString(R.string.os_seguintes_campos_branco));
sb.append("<br/><br/>");
for (String critica : criticas) {
sb.append("&#8226;"); sb.append(critica); sb.append("<br/>");
}
}
if (criticasComRegras.size() > 0) {
if (criticas.size() > 0) sb.append("<br/>");
for (Integer msgResId : criticasComRegras) {
sb.append(activity.getString(msgResId));
}
}
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(activity);
alertDialogBuilder
.setIconAttribute(android.R.attr.alertDialogIcon)
.setTitle(R.string.campos_em_branco)
.setMessage(Html.fromHtml(sb.toString()))
.setNeutralButton("OK", null)
.create()
.show();
criticas.clear();
criticasComRegras.clear();
}
private List<Integer> criticasComRegras;
private void rule(String rule, int msgResId, View... views) {
ruleContainers.add(new RuleContainer(rule, msgResId, views));
}
private void setViewValue(View view, String value) {
if (view instanceof Spinner) {
Spinner spinner = (Spinner) view;
if (spinner.getCount() > 0) spinner.setSelection(1);
} else if (view instanceof EditText) {
EditText editText = (EditText) view;
editText.setText(value);
}
}
public void ignoreNotEmptyIfAllEmpty(View... views) {
ruleContainers.add(new RuleContainer(IGNORE_NOT_EMPTY_IF_ALL_EMPTY, null, views));
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment