001    /*
002     * Copyright 2011 The Kuali Foundation.
003     * 
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     * 
008     * http://www.opensource.org/licenses/ecl2.php
009     * 
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.kfs.vnd.service.impl;
017    
018    import java.util.List;
019    
020    import org.kuali.kfs.sys.KFSKeyConstants;
021    import org.kuali.kfs.vnd.VendorConstants;
022    import org.kuali.kfs.vnd.VendorParameterConstants;
023    import org.kuali.kfs.vnd.businessobject.VendorDetail;
024    import org.kuali.kfs.vnd.service.TaxNumberService;
025    import org.kuali.rice.kns.service.ParameterService;
026    import org.kuali.rice.kns.util.ObjectUtils;
027    import org.kuali.rice.kns.web.format.FormatException;
028    
029    public class TaxNumberServiceImpl implements TaxNumberService {
030    
031        public ParameterService parameterService;
032    
033    
034        public void setParameterService(ParameterService parameterService) {
035            this.parameterService = parameterService;
036        }
037    
038    
039        public static List<String> taxNumberFormats;
040        public static List<String> feinNumberFormats;
041        public static List<String> notAllowedTaxNumbers;
042    
043    
044        public String formatToDefaultFormat(String taxNbr) throws FormatException {
045            String digits = taxNbr.replaceAll("\\D", "");
046    
047            Integer defaultTaxNumberDigits = new Integer(parameterService.getParameterValue(VendorDetail.class, VendorParameterConstants.DEFAULT_TAX_NUMBER_DIGITS));
048    
049            if (digits.length() < defaultTaxNumberDigits) {
050                throw new FormatException("Tax number has fewer than " + defaultTaxNumberDigits + " digits.", KFSKeyConstants.ERROR_CUSTOM, taxNbr);
051            }
052            else if (digits.length() > defaultTaxNumberDigits) {
053                throw new FormatException("Tax number has more than " + defaultTaxNumberDigits + " digits.", KFSKeyConstants.ERROR_CUSTOM, taxNbr);
054            }
055            else {
056                return digits;
057            }
058        }
059    
060        /**
061         * A predicate to determine if a String field is all numbers
062         * 
063         * @param field A String tax number
064         * @return True if String is numeric
065         */
066        public boolean isStringAllNumbers(String field) {
067            if (!isStringEmpty(field)) {
068                field = field.trim();
069                for (int x = 0; x < field.length(); x++) {
070                    char c = field.charAt(x);
071                    if (!Character.isDigit(c)) {
072                        return false;
073                    }
074                }
075                return true;
076            }
077            return false;
078        }
079    
080        /**
081         * A predicate to determine if a String field is null or empty
082         * 
083         * @param field A String tax number
084         * @return True if String is null or empty
085         */
086        public boolean isStringEmpty(String field) {
087            if (field == null || field.equals("")) {
088                return true;
089            }
090            else {
091                return false;
092            }
093        }
094    
095        /**
096         * A predicate to determine the validity of tax numbers We're using regular expressions stored in the business rules table to
097         * validate whether the tax number is in the correct format. The regular expressions are : (please update this javadoc comment
098         * when the regular expressions change) 1. For SSN : (?!000)(?!666)(\d{3})([ \-]?)(?!00)(\d{2})([\-]?)(?!0000)(\d{4}) 2. For
099         * FEIN : (?!00)(\d{3})([ \-]?)(\d{2})([\-]?)(?!0000)(\d{4})
100         * 
101         * @param taxNbr A tax number String (SSN or FEIN)
102         * @param taxType determines SSN or FEIN tax number type
103         * @return True if the tax number is known to be in a valid format
104         */
105        public boolean isValidTaxNumber(String taxNbr, String taxType) {
106            String[] ssnFormats = parseSSNFormats();
107            String[] feinFormats = parseFEINFormats();
108            Integer defaultTaxNumberDigits = new Integer(parameterService.getParameterValue(VendorDetail.class, "DEFAULT_TAX_NUMBER_DIGITS"));
109    
110            if (taxNbr.length() != defaultTaxNumberDigits || !isStringAllNumbers(taxNbr)) {
111                return false;
112            }
113    
114            if (taxType.equals(VendorConstants.TAX_TYPE_SSN)) {
115    
116                for (int i = 0; i < ssnFormats.length; i++) {
117                    if (taxNbr.matches(ssnFormats[i])) {
118                        return true;
119                    }
120                }
121                return false;
122            }
123            else if (taxType.equals(VendorConstants.TAX_TYPE_FEIN)) {
124                for (int i = 0; i < feinFormats.length; i++) {
125                    if (taxNbr.matches(feinFormats[i])) {
126                        return true;
127                    }
128                }
129                return false;
130            }
131    
132            return true;
133        }
134    
135    
136        /**
137         * Someday we'll have to use the rules table instead of using constants. This method will return true if the tax number is an
138         * allowed tax number and return false if it's not allowed.
139         * 
140         * @param taxNbr The tax number to be processed.
141         * @return boolean true if the tax number is allowed and false otherwise.
142         */
143        public boolean isAllowedTaxNumber(String taxNbr) {
144            String[] notAllowedTaxNumbers = parseNotAllowedTaxNumbers();
145            for (int i = 0; i < notAllowedTaxNumbers.length; i++) {
146                if (taxNbr.matches(notAllowedTaxNumbers[i])) {
147                    return false;
148                }
149            }
150            return true;
151        }
152    
153        /**
154         * Splits the set of tax number formats which are returned from the rule service as a semicolon-delimeted String into a String
155         * array.
156         * 
157         * @return A String array of the tax number format regular expressions.
158         */
159        public String[] parseSSNFormats() {
160            if (ObjectUtils.isNull(taxNumberFormats)) {
161                taxNumberFormats = parameterService.getParameterValues(VendorDetail.class, VendorParameterConstants.TAX_SSN_NUMBER_FORMATS);
162            }
163            return taxNumberFormats.toArray(new String[] {});
164        }
165    
166        /**
167         * Splits the set of tax fein number formats which are returned from the rule service as a semicolon-delimeted String into a
168         * String array.
169         * 
170         * @return A String array of the tax fein number format regular expressions.
171         */
172        public String[] parseFEINFormats() {
173            if (ObjectUtils.isNull(feinNumberFormats)) {
174                feinNumberFormats = parameterService.getParameterValues(VendorDetail.class, VendorParameterConstants.TAX_FEIN_NUMBER_FORMATS);
175            }
176            return feinNumberFormats.toArray(new String[] {});
177        }
178    
179        /**
180         * Splits the set of not allowed tax number formats which are returned from the rule service as a semicolon-delimeted String
181         * into a String array.
182         * 
183         * @return A String array of the not allowed tax number format regular expressions.
184         */
185        public String[] parseNotAllowedTaxNumbers() {
186            if (ObjectUtils.isNull(notAllowedTaxNumbers)) {
187                notAllowedTaxNumbers = parameterService.getParameterValues(VendorDetail.class, VendorParameterConstants.NOT_ALLOWED_TAX_NUMBERS);
188            }
189            return notAllowedTaxNumbers.toArray(new String[] {});
190        }
191    
192    }