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 }