View Javadoc
1   /*
2    * (c) Copyright 2006-2020 by rapiddweller GmbH & Volker Bergmann. All rights reserved.
3    *
4    * Redistribution and use in source and binary forms, with or without
5    * modification, is permitted under the terms of the
6    * GNU General Public License.
7    *
8    * For redistributing this software or a derivative work under a license other
9    * than the GPL-compatible Free Software License as defined by the Free
10   * Software Foundation or approved by OSI, you must first obtain a commercial
11   * license to this software product from rapiddweller GmbH & Volker Bergmann.
12   *
13   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
14   * WITHOUT A WARRANTY OF ANY KIND. ALL EXPRESS OR IMPLIED CONDITIONS,
15   * REPRESENTATIONS AND WARRANTIES, INCLUDING ANY IMPLIED WARRANTY OF
16   * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT, ARE
17   * HEREBY EXCLUDED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24   * POSSIBILITY OF SUCH DAMAGE.
25   */
26  
27  package com.rapiddweller.domain.br;
28  
29  import com.rapiddweller.common.MathUtil;
30  import com.rapiddweller.common.validator.bean.AbstractConstraintValidator;
31  
32  import javax.validation.ConstraintValidatorContext;
33  import java.util.regex.Pattern;
34  
35  /**
36   * Verifies Brazilian CPF numbers.
37   * CPF stands for 'Cadastro de Pessoa Fisica'
38   * and is a tax payer number assigned to an
39   * individual person (Pessoa Fisica).
40   * <br/><br/>
41   * Created: 17.10.2009 08:24:12
42   *
43   * @author Volker Bergmann
44   * @see "http://en.wikipedia.org/wiki/Cadastro_de_Pessoas_F%C3%ADsicas"
45   * @since 0.6.0
46   */
47  public class CPFValidator extends AbstractConstraintValidator<CPF, String> {
48  
49    private static final Pattern pattern =
50        Pattern.compile("\\d{3}\\.\\d{3}\\.\\d{3}-\\d{2}");
51  
52    private boolean acceptingFormattedNumbers = true;
53  
54    /**
55     * Instantiates a new Cpf validator.
56     */
57    public CPFValidator() {
58      this(false);
59    }
60  
61    /**
62     * Instantiates a new Cpf validator.
63     *
64     * @param acceptingFormattedNumbers the accepting formatted numbers
65     */
66    public CPFValidator(boolean acceptingFormattedNumbers) {
67      this.acceptingFormattedNumbers = acceptingFormattedNumbers;
68    }
69  
70    /**
71     * Is accepting formatted numbers boolean.
72     *
73     * @return the boolean
74     */
75    public boolean isAcceptingFormattedNumbers() {
76      return acceptingFormattedNumbers;
77    }
78  
79    /**
80     * Sets accepting formatted numbers.
81     *
82     * @param acceptingFormattedNumbers the accepting formatted numbers
83     */
84    public void setAcceptingFormattedNumbers(
85        boolean acceptingFormattedNumbers) {
86      this.acceptingFormattedNumbers = acceptingFormattedNumbers;
87    }
88  
89    @Override
90    public void initialize(CPF params) {
91      super.initialize(params);
92      acceptingFormattedNumbers = params.formatted();
93    }
94  
95    @Override
96    public boolean isValid(String number, ConstraintValidatorContext context) {
97      // do simple checks first
98      if (number == null) {
99        return false;
100     }
101 
102     if (number.length() == 14) {
103       if (acceptingFormattedNumbers &&
104           pattern.matcher(number).matches()) {
105         number = number.substring(0, 3) + number.substring(4, 7) +
106             number.substring(8, 11) + number.substring(12, 14);
107       } else {
108         return false;
109       }
110     }
111 
112     if (number.length() != 11) {
113       return false;
114     }
115 
116     // compute 1st verification digit
117     int v1 =
118         MathUtil.weightedSumOfDigits(number, 0, 10, 9, 8, 7, 6, 5, 4, 3,
119             2);
120     v1 = 11 - v1 % 11;
121     if (v1 >= 10) {
122       v1 = 0;
123     }
124 
125     // Check 1st verification digit
126     if (v1 != number.charAt(9) - '0') {
127       return false;
128     }
129 
130     // compute 2nd verification digit
131     int v2 = MathUtil.weightedSumOfDigits(number, 0, 11, 10, 9, 8, 7, 6, 5,
132         4, 3);
133     v2 += 2 * v1;
134     v2 = 11 - v2 % 11;
135     if (v2 >= 10) {
136       v2 = 0;
137     }
138 
139     // Check 2nd verification digit
140     return (v2 == number.charAt(10) - '0');
141   }
142 
143 }