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  
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 }