Package br.com.caelum.stella.validation

Source Code of br.com.caelum.stella.validation.CPFValidator

package br.com.caelum.stella.validation;

import static br.com.caelum.stella.constraint.CPFConstraints.CPF_FORMATED;
import static br.com.caelum.stella.constraint.CPFConstraints.CPF_UNFORMATED;

import java.util.ArrayList;
import java.util.List;

import br.com.caelum.stella.MessageProducer;
import br.com.caelum.stella.SimpleMessageProducer;
import br.com.caelum.stella.format.CPFFormatter;
import br.com.caelum.stella.validation.error.CPFError;

/**
* Verifica se uma cadeia (String) é válida para o documento de CPF (Cadastro de
* Pessoa Física).
*
* @author Leonardo Bessa
*/
public class CPFValidator extends BaseValidator<String> {
    private static final int MOD = 11;

    private final boolean isFormatted;

    private final boolean isIgnoringRepeatedDigits;

    private static class RotinaPosProdutoInterno implements
            RotinaDeDigitoVerificador {
        public Integer transform(RotinaParameters parameter) {
            Integer mod = parameter.getDigitoVerificadorInfo().getMod();
            Integer result = parameter.getResult() % mod;
            if (result < 2) {
                result = 0;
            } else {
                result = 11 - result;
            }
            return result;
        }
    }

    private static final Integer DV1_POSITION = 10;

    private static final Integer[] DV1_MULTIPLIERS = { 10, 9, 8, 7, 6, 5, 4, 3,
            2 };

    private static final Integer DV2_POSITION = 11;

    private static final Integer[] DV2_MULTIPLIERS = { 11, 10, 9, 8, 7, 6, 5,
            4, 3, 2 };

    private static final DigitoVerificadorInfo DV1_INFO = new DigitoVerificadorInfo(
            0,
            new RotinaDeDigitoVerificador[] { new RotinaPosProdutoInterno() },
            MOD, DV1_MULTIPLIERS, DV1_POSITION);

    private static final DigitoVerificadorInfo DV2_INFO = new DigitoVerificadorInfo(
            0,
            new RotinaDeDigitoVerificador[] { new RotinaPosProdutoInterno() },
            MOD, DV2_MULTIPLIERS, DV2_POSITION);

    private static final ValidadorDeDV DV1_CHECKER = new ValidadorDeDV(DV1_INFO);

    private static final ValidadorDeDV DV2_CHECKER = new ValidadorDeDV(DV2_INFO);

    /**
     * Construtor padrão de validador de CPF. Este considera, por padrão, que as
     * cadeias estão formatadas e utiliza um {@linkplain SimpleMessageProducer}
     * para geração de mensagens.
     */
    public CPFValidator() {
        this(true);
    }

    /**
     * Construtor de validador de CPF. O validador utiliza um
     * {@linkplain SimpleMessageProducer} para geração de mensagens.
     */
    public CPFValidator(boolean isFormatted) {
        super();
        this.isFormatted = isFormatted;
        this.isIgnoringRepeatedDigits = true;
    }

    /**
     * <p>
     * Construtor do Validador de CPF.
     * </p>
     * <p>
     * Por padrão o validador criado aceita cadeias de CPF com todos os dígitos
     * repetidos, quando todas as outras condições de validação são aceitas.
     * Para considerar estes documentos inválidos use o construtor
     * {@link #CPFValidator(MessageProducer, boolean, boolean)} com a váriavel
     * {@linkplain #isIgnoringRepeatedDigits} em <code>false</code>.
     * </p>
     *
     * @param messageProducer
     *            produtor de mensagem de erro.
     * @param isFormatted
     *            considera cadeia no formato de CPF: "ddd.ddd.ddd-dd" onde "d"
     *            é um dígito decimal.
     */
    public CPFValidator(MessageProducer messageProducer, boolean isFormatted) {
        super(messageProducer);
        this.isFormatted = isFormatted;
        this.isIgnoringRepeatedDigits = true;
    }

    /**
     * @param messageProducer
     *            produtor de mensagem de erro.
     * @param isFormatted
     *            condição para considerar cadeia no formato de CPF:
     *            "ddd.ddd.ddd-dd" onde "d" é um dígito decimal.
     * @param isIgnoringRepeatedDigits
     *            condição para ignorar cadeias de CPF com todos os dígitos
     *            repetidos.
     */
    public CPFValidator(MessageProducer messageProducer, boolean isFormatted,
            boolean isIgnoringRepeatedDigits) {
        super(messageProducer);
        this.isFormatted = isFormatted;
        this.isIgnoringRepeatedDigits = isIgnoringRepeatedDigits;
    }

    /**
     * Valida se a cadeia está de acordo com as regras de um CPF.
     *
     * @see br.com.caelum.stella.validation.Validator#assertValid(java.lang.Object)
     * @return <code>true</code> se a cadeia é válida ou é nula;
     *         <code>false</code> caso contrario.
     */
    protected List<InvalidValue> getInvalidValues(String cpf) {
        List<InvalidValue> errors = new ArrayList<InvalidValue>();
        if (cpf != null) {
            String unformatedCPF = checkForCorrectFormat(cpf, errors);

            if (errors.isEmpty()) {
                if ((!isIgnoringRepeatedDigits)
                        && hasAllRepeatedDigits(unformatedCPF)) {
                    errors.add(CPFError.REPEATED_DIGITS);
                }
            }
            if (errors.isEmpty()) {
                if (!hasValidCheckDigits(unformatedCPF)) {
                    errors.add(CPFError.INVALID_CHECK_DIGITS);
                }
            }
        }
        return errors;
    }

    private String checkForCorrectFormat(String string,
            List<InvalidValue> errors) {
        String unformatedCPF = null;
        if (isFormatted) {
            if (!CPF_FORMATED.matcher(string).matches()) {
                errors.add(CPFError.INVALID_FORMAT);
            }
            unformatedCPF = (new CPFFormatter()).unformat(string);
        } else {
            if (!(CPF_UNFORMATED.matcher(string).matches())) {
                errors.add(CPFError.INVALID_DIGITS);
            }
            unformatedCPF = string;
        }
        return unformatedCPF;
    }

    private boolean hasValidCheckDigits(String value) {
        return (DV1_CHECKER.isDVValid(value)) && (DV2_CHECKER.isDVValid(value));
    }

    private boolean hasAllRepeatedDigits(String cpf) {
        for (int i = 1; i < cpf.length(); i++) {
            if (cpf.charAt(i) != cpf.charAt(0)) {
                return false;
            }
        }
        return true;
    }

    public boolean isEligible(String value) {
        boolean result;
        if (isFormatted) {
            result = CPF_FORMATED.matcher(value).matches();
        } else {
            result = CPF_FORMATED.matcher(value).matches();
        }
        return result;
    }

}
TOP

Related Classes of br.com.caelum.stella.validation.CPFValidator

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.