ragunathjawahar / android-saripaar

UI form validation library for Android
Apache License 2.0
3.22k stars 460 forks source link

Custom rule for validate CPF #122

Closed LuizGadao closed 8 years ago

LuizGadao commented 9 years ago

How can I validate a field with this algorithm:

public static boolean validateCPF(String CPF) {
        if (CPF.equals("00000000000") || CPF.equals("11111111111") || CPF.equals("22222222222") || CPF.equals("33333333333") || CPF.equals("44444444444") || CPF.equals("55555555555") || CPF.equals("66666666666") || CPF.equals("77777777777") || CPF.equals("88888888888") || CPF.equals("99999999999") || (CPF.length() != 11))
            return (false);
        char dig10, dig11;
        int sm, i, r, num, peso;
        try {
            sm = 0;
            peso = 10;
            for (i = 0; i < 9; i++) {
                num = (int) (CPF.charAt(i) - 48);
                sm = sm + (num * peso);
                peso = peso - 1;
            }
            r = 11 - (sm % 11);
            if ((r == 10) || (r == 11)) dig10 = '0';
            else
                dig10 = (char) (r + 48);
            sm = 0;
            peso = 11;
            for (i = 0; i < 10; i++) {
                num = (int) (CPF.charAt(i) - 48);
                sm = sm + (num * peso);
                peso = peso - 1;
            }
            r = 11 - (sm % 11);
            if ((r == 10) || (r == 11)) dig11 = '0';
            else
                dig11 = (char) (r + 48);
            return (dig10 == CPF.charAt(9)) && (dig11 == CPF.charAt(10));
        } catch (InputMismatchException erro) {
            return (false);
        }
    }
AlbertoMonteiro commented 9 years ago

Assim:

package br.com.validation;

import com.mobsandgeeks.saripaar.annotation.ValidateUsing;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
 * Created by Alberto on 02/11/2015.
 */
@ValidateUsing(CpfCnpjRule.class)
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface CpfCnpj {
  boolean isRequired() default false;

  String emptyText() default "";

  int emptyTextResId() default -1;

  int sequence() default -1;

  int messageResId() default -1;

  String message() default "Cpf/Cnpj inválido";
}
package br.com.validation;

import android.view.View;

import com.google.common.base.Function;
import com.google.common.base.Joiner;
import com.google.common.collect.Iterators;
import com.google.common.collect.Lists;
import com.google.common.primitives.Chars;
import com.mobsandgeeks.saripaar.ContextualAnnotationRule;
import com.mobsandgeeks.saripaar.ValidationContext;
import com.mobsandgeeks.saripaar.annotation.NotEmpty;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * Created by Alberto on 02/11/2015.
 */
public class CpfCnpjRule extends ContextualAnnotationRule<CpfCnpj, String> {

  protected CpfCnpjRule(final ValidationContext validationContext, final CpfCnpj cpfCnpj) {
    super(validationContext, cpfCnpj);
  }

  @Override
  public boolean isValid(String data) {
    boolean stringIsEmpty = data == null || data.isEmpty();
    if (mRuleAnnotation.isRequired() && stringIsEmpty)
      return false;
    else if (!mRuleAnnotation.isRequired() && stringIsEmpty)
      return true;
    return IsValidCNPJ(data) || IsValidCPF(data);
  }

  private static boolean IsValidCNPJ(String cnpj) {
    return IsValid(cnpj, new Integer[]{6, 5, 4, 3, 2, 9, 8, 7, 6, 5, 4, 3, 2}, 14);
  }

  private static boolean IsValidCPF(String cpf) {
    return IsValid(cpf, new Integer[]{11, 10, 9, 8, 7, 6, 5, 4, 3, 2}, 11);
  }

  private static boolean IsValid(String cpfCnpj, Integer[] mult, int length) {
    if (cpfCnpj.length() != length)
      return false;

    String cpnjWithoutCheckDigit = cpfCnpj.substring(0, length - 2);
    List<Integer> ints = Arrays.asList(mult);
    int sum = Sum(cpnjWithoutCheckDigit, ints.subList(1, ints.size()));

    Integer rest = sum % 11;
    rest = rest < 2 ? 0 : 11 - rest;

    String digits = rest.toString();
    cpnjWithoutCheckDigit += digits;
    sum = Sum(cpnjWithoutCheckDigit, ints);

    rest = sum % 11;
    rest = rest < 2 ? 0 : 11 - rest;
    digits += rest.toString();
    return cpfCnpj.endsWith(digits);
  }

  private static int Sum(String cpnjWithoutCheckDigit, List<Integer> mult) {
    int sum = 0;
    List<Integer> ints = Lists.transform(Chars.asList(cpnjWithoutCheckDigit.toCharArray()), new Function<Character, Integer>() {
      @Override
      public Integer apply(Character input) {
        return Integer.parseInt(input.toString());
      }
    });
    for (int i = 0; i < ints.size(); i++) sum += ints.get(i) * mult.get(i);
    return sum;
  }

}

E ai você usa assim:

@CpfCnpj(messageResId = R.string.invalid_cpf_cnpj, isRequired = true)
@Bind(R.id.client_main_cpf_cnpj)
EditText mClientCpnjCpf;
LuizGadao commented 9 years ago

Eu tinha resolvido isso.

Mas, de qualquer forma muito obrigado.

ragunathjawahar commented 8 years ago

@AlbertoMonteiro Good job!

mcassiano commented 8 years ago

Tried doing this, but CpfCnpjRule is never getting called for EditTexts annotated with CpfCnpj. Did something change in Saripaar's API?

ragunathjawahar commented 8 years ago

Did you register CpfCnpjRule using validator.registerAnnotation(CpfCnpjRule.class)?

mcassiano commented 8 years ago

@ragunathjawahar Ha! That did it! But I had to do it a little differently:

Validator.registerAnnotation(CpfCnpj.class);

Thanks! 🎊

ragunathjawahar commented 8 years ago

@mcassiano You're right, that's a static method :)