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
34 /**
35 * Validates Brazilian CNPJ numbers.
36 * CNPJ stands for <i>Cadastro Nacional da Pessoa JurÃdica</i>
37 * and is a tax payer number assigned to a
38 * legal person (Pessoa JurÃdica).
39 * Created: 17.10.2009 08:24:23
40 *
41 * @author Volker Bergmann
42 * @since 0.6.0
43 */
44 public class CNPJValidator
45 extends AbstractConstraintValidator<CNPJ, CharSequence> {
46
47 private boolean acceptingFormattedNumbers = true;
48
49 /**
50 * Instantiates a new Cnpj validator.
51 */
52 public CNPJValidator() {
53 this(false);
54 }
55
56 /**
57 * Instantiates a new Cnpj validator.
58 *
59 * @param acceptingFormattedNumbers the accepting formatted numbers
60 */
61 public CNPJValidator(boolean acceptingFormattedNumbers) {
62 this.acceptingFormattedNumbers = acceptingFormattedNumbers;
63 }
64
65 /**
66 * Is accepting formatted numbers boolean.
67 *
68 * @return the boolean
69 */
70 public boolean isAcceptingFormattedNumbers() {
71 return acceptingFormattedNumbers;
72 }
73
74 /**
75 * Sets accepting formatted numbers.
76 *
77 * @param acceptingFormattedNumbers the accepting formatted numbers
78 */
79 public void setAcceptingFormattedNumbers(
80 boolean acceptingFormattedNumbers) {
81 this.acceptingFormattedNumbers = acceptingFormattedNumbers;
82 }
83
84 @Override
85 public void initialize(CNPJ params) {
86 super.initialize(params);
87 acceptingFormattedNumbers = params.formatted();
88 }
89
90 @Override
91 public boolean isValid(CharSequence number,
92 ConstraintValidatorContext context) {
93 // do simple checks first
94 if (number == null) {
95 return false;
96 }
97 int length = number.length();
98 boolean formattedNumber = (acceptingFormattedNumbers && length == 18);
99 if (length != 14 && !formattedNumber) {
100 return false;
101 }
102 if (formattedNumber) {
103 // check grouping characters
104 if (number.charAt(2) != '.' || number.charAt(6) != '.' ||
105 number.charAt(10) != '/' || number.charAt(15) != '-') {
106 return false;
107 }
108 // remove grouping
109 number = "" + number.subSequence(0, 2) + number.subSequence(3, 6) +
110 number.subSequence(7, 10) +
111 number.subSequence(11, 15) + number.subSequence(16, 18);
112 }
113 // compute 1st verification digit
114 int v1 = MathUtil.weightedSumOfDigits(number, 0, 5, 4, 3, 2, 9, 8, 7, 6,
115 5, 4, 3, 2);
116 v1 = 11 - v1 % 11;
117 if (v1 >= 10) {
118 v1 = 0;
119 }
120
121 // Check 1st verification digit
122 if (v1 != number.charAt(12) - '0') {
123 return false;
124 }
125
126 // compute 2nd verification digit
127 int v2 = MathUtil.weightedSumOfDigits(number, 0, 6, 5, 4, 3, 2, 9, 8, 7,
128 6, 5, 4, 3);
129 v2 += 2 * v1;
130 v2 = 11 - v2 % 11;
131 if (v2 >= 10) {
132 v2 = 0;
133 }
134
135 // Check 2nd verification digit
136 return (v2 == number.charAt(13) - '0');
137 }
138
139 }