001    /**
002     * Copyright 2004-2013 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.hr.time.clock.location.validation;
017    
018    import java.util.List;
019    
020    import org.apache.commons.lang.StringUtils;
021    import org.apache.log4j.Logger;
022    import org.kuali.hr.time.authorization.AuthorizationValidationUtils;
023    import org.kuali.hr.time.authorization.DepartmentalRule;
024    import org.kuali.hr.time.authorization.DepartmentalRuleAuthorizer;
025    import org.kuali.hr.time.clock.location.ClockLocationRule;
026    import org.kuali.hr.time.clock.location.ClockLocationRuleIpAddress;
027    import org.kuali.hr.time.service.base.TkServiceLocator;
028    import org.kuali.hr.time.util.TkConstants;
029    import org.kuali.hr.time.util.ValidationUtils;
030    import org.kuali.rice.kns.document.MaintenanceDocument;
031    import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase;
032    import org.kuali.rice.krad.bo.PersistableBusinessObject;
033    
034    public class ClockLocationRuleRule extends MaintenanceDocumentRuleBase {
035    
036            private static Logger LOG = Logger.getLogger(ClockLocationRuleRule.class);
037    
038            public static boolean validateIpAddress(String ip) {
039                    LOG.debug("Validating IP address: " + ip);
040                    if(ip == null) {
041                            return false;
042                    }
043                    if(ip.isEmpty() || ip.length() > 15 || ip.endsWith(TkConstants.IP_SEPERATOR) || ip.startsWith(TkConstants.IP_SEPERATOR)) {
044                            return false;
045                    }
046                    String[] lst =  StringUtils.split(ip, TkConstants.IP_SEPERATOR);
047                    if(lst.length > 4 || (lst.length <4 && ip.indexOf(TkConstants.WILDCARD_CHARACTER)< 0)) {
048                            return false;
049                    }
050                    for(String str : lst) {
051                            if(!str.matches(TkConstants.IP_WILDCARD_PATTERN)) {
052                                    return false;
053                            }
054                    }
055                    return true;
056            }
057            
058            boolean validateIpAddresses(List<ClockLocationRuleIpAddress> ipAddresses) {
059                    for(ClockLocationRuleIpAddress ip : ipAddresses) {
060                            if(!validateIpAddress(ip.getIpAddress())) {
061                                    return this.flagIPAddressError(ip.getIpAddress());
062                            }
063                    }
064                    return true;
065            }
066            
067            boolean flagIPAddressError(String ip) {
068                    this.putFieldError("ipAddresses", "ipaddress.invalid.format", ip);
069                    return false;
070            }
071    
072            boolean validateWorkArea(ClockLocationRule clr) {
073                    boolean valid = true;
074                    if (clr.getWorkArea() != null
075                                    && !ValidationUtils.validateWorkArea(clr.getWorkArea(), clr
076                                                    .getEffectiveDate())) {
077                            this.putFieldError("workArea", "error.existence", "workArea '"
078                                            + clr.getWorkArea() + "'");
079                            valid = false;
080                    } else if (clr.getWorkArea() != null
081                                    && !clr.getWorkArea().equals(TkConstants.WILDCARD_LONG)) {
082                            int count = TkServiceLocator.getWorkAreaService().getWorkAreaCount(clr.getDept(), clr.getWorkArea());
083                            valid = (count > 0);
084                            if (!valid) {
085                                    this.putFieldError("workArea", "dept.workarea.invalid.sync",
086                                                    clr.getWorkArea() + "");
087                            }
088                    }
089                    return valid;
090            }
091    
092            protected boolean validateDepartment(ClockLocationRule clr) {
093            boolean ret = false;
094    
095            if (!StringUtils.isEmpty(clr.getDept())) {
096                    if (!ValidationUtils.validateDepartment(clr.getDept(), clr.getEffectiveDate())) {
097                                this.putFieldError("dept", "error.existence", "department '" + clr.getDept() + "'");
098                } else if (!DepartmentalRuleAuthorizer.hasAccessToWrite(clr)) {
099                    this.putFieldError("dept", "error.department.permissions", clr.getDept());
100                } else {
101                    ret = true;
102                }
103            }
104    
105            return ret;
106            }
107    
108            protected boolean validateJobNumber(ClockLocationRule clr) {
109                    boolean valid = true;
110                    if (clr.getJobNumber() == null) {
111                            valid = false;
112                    } else if (!clr.getJobNumber().equals(TkConstants.WILDCARD_LONG)) {
113                            int count = TkServiceLocator.getJobService().getJobCount(clr.getPrincipalId(), clr.getJobNumber(),null);
114                            valid = (count > 0);
115                            if (!valid) {
116                                    this.putFieldError("jobNumber", "principalid.job.invalid.sync",
117                                                    clr.getJobNumber() + "");
118                            }
119                    }
120                    return valid;
121            }
122    
123            protected boolean validatePrincipalId(ClockLocationRule clr) {
124                    boolean valid = false;
125                    if (clr.getPrincipalId() == null) {
126                            valid = false;
127                    } else {
128                            valid = true;
129                    }
130                    return valid;
131            }
132    
133        /**
134         * This method will validate whether the wildcard combination and wild
135         * carded areas for this DepartmentalRule are valid or not. Errors are added
136         * to the field errors to report back to the user interface as well.
137         *
138         * @param clr The Departmental rule we are investigating.
139         *
140         * @return true if wild card setup is correct, false otherwise.
141         */
142        boolean validateWildcards(DepartmentalRule clr) {
143            boolean valid = true;
144    
145            if (!ValidationUtils.validateWorkAreaDeptWildcarding(clr)) {
146                // add error when work area defined, department is wild carded.
147                this.putFieldError("dept", "error.wc.wadef", "department '" + clr.getDept() + "'");
148                valid = false;
149            }
150    
151            if (StringUtils.equals(clr.getDept(), TkConstants.WILDCARD_CHARACTER) &&
152                    !AuthorizationValidationUtils.canWildcardDepartment(clr)) {
153                this.putFieldError("dept", "error.wc.dept.perm", "department '" + clr.getDept() + "'");
154                valid = false;
155            }
156    
157            if (clr!= null && clr.getWorkArea() != null && clr.getWorkArea().equals(TkConstants.WILDCARD_LONG) &&
158                    !AuthorizationValidationUtils.canWildcardWorkArea(clr)) {
159                this.putFieldError("dept", "error.wc.wa.perm", "department '" + clr.getDept() + "'");
160                valid = false;
161            }
162    
163            return valid;
164        }
165    
166    
167            /**
168             * It looks like the method that calls this class doesn't actually care
169             * about the return type.
170             */
171            @Override
172            protected boolean processCustomRouteDocumentBusinessRules(MaintenanceDocument document) {
173                    boolean valid = false;
174    
175                    PersistableBusinessObject pbo = (PersistableBusinessObject) this.getNewBo();
176                    if (pbo instanceof ClockLocationRule) {
177                            ClockLocationRule clr = (ClockLocationRule) pbo;
178                valid = this.validateDepartment(clr);
179                valid &= this.validateWorkArea(clr);
180                valid &= this.validateWildcards(clr);
181                valid &= this.validatePrincipalId(clr);
182                valid &= this.validateJobNumber(clr);
183                valid &= this.validateIpAddresses(clr.getIpAddresses());
184                    }
185    
186                    return valid;
187            }
188    }