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.module.endow.document.service.impl;
017    
018    import java.sql.Date;
019    import java.util.Calendar;
020    
021    import org.kuali.kfs.module.endow.EndowConstants;
022    import org.kuali.kfs.module.endow.document.service.ValidateDateBasedOnFrequencyCodeService;
023    
024    /**
025     * This class...
026     */
027    public class ValidateDateBasedOnFrequencyCodeServiceImpl implements ValidateDateBasedOnFrequencyCodeService {
028    
029        /**
030         * @see org.kuali.kfs.module.endow.document.service.ValidateDateBasedOnFrequencyCodeService#validateDateBasedOnFrequencyCode(java.sql.Date,
031         *      java.lang.String)
032         */
033        public boolean validateDateBasedOnFrequencyCode(Date date, String frequencyCode) {
034            boolean isValid = true;
035            Calendar calendar = Calendar.getInstance();
036            calendar.setTime(date);
037    
038            String frequencyType = frequencyCode.substring(0, 1);
039    
040            if (frequencyType.equalsIgnoreCase(EndowConstants.FrequencyTypes.DAILY)) {
041                // any date is valid
042                return true;
043            }
044    
045            if (frequencyType.equalsIgnoreCase(EndowConstants.FrequencyTypes.WEEKLY)) {
046                String dayOfWeek = frequencyCode.substring(1, 4).toUpperCase();
047                int calendarDayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
048    
049                return validateWeekly(dayOfWeek, calendarDayOfWeek);
050    
051            }
052    
053            if (frequencyType.equalsIgnoreCase(EndowConstants.FrequencyTypes.SEMI_MONTHLY) || frequencyType.equalsIgnoreCase(EndowConstants.FrequencyTypes.MONTHLY)) {
054                String dayOfMonth = frequencyCode.substring(1, 3);
055                int calendarDayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
056                return validateDayOfMonth(dayOfMonth, calendarDayOfMonth);
057            }
058    
059            if (frequencyType.equalsIgnoreCase(EndowConstants.FrequencyTypes.QUARTERLY)) {
060                String month = frequencyCode.substring(1, 2);
061                int calendarMonth = calendar.get(Calendar.MONTH);
062                String dayOfMonth = frequencyCode.substring(2, 4);
063                int calendarDayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
064    
065                return validateQuarterly(month, calendarMonth, dayOfMonth, calendarDayOfMonth);
066            }
067    
068            if (frequencyType.equalsIgnoreCase(EndowConstants.FrequencyTypes.SEMI_ANNUALLY)) {
069    
070                String month = frequencyCode.substring(1, 2);
071                int calendarMonth = calendar.get(Calendar.MONTH);
072                String dayOfMonth = frequencyCode.substring(2, 4);
073                int calendarDayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
074    
075                return validateSemiAnnually(month, calendarMonth, dayOfMonth, calendarDayOfMonth);
076            }
077    
078            if (frequencyType.equalsIgnoreCase(EndowConstants.FrequencyTypes.ANNUALLY)) {
079                String month = frequencyCode.substring(1, 2);
080                int calendarMonth = calendar.get(Calendar.MONTH);
081                String dayOfMonth = frequencyCode.substring(2, 4);
082                int calendarDayOfMonth = calendar.get(Calendar.DAY_OF_MONTH);
083    
084                return validateDayAndMonth(month, calendarMonth, dayOfMonth, calendarDayOfMonth);
085    
086            }
087    
088            return isValid;
089        }
090    
091        /**
092         * Validates that the day of the given date corresponds to the day part of the weekly frequency code.
093         * 
094         * @param dayOfWeek
095         * @param calendarDayOfWeek
096         * @return true if valid, false otherwise
097         */
098        private boolean validateWeekly(String dayOfWeek, int calendarDayOfWeek) {
099            boolean isValid = true;
100    
101            if (EndowConstants.FrequencyWeekDays.MONDAY.equalsIgnoreCase(dayOfWeek)) {
102                if (calendarDayOfWeek != Calendar.MONDAY) {
103                    return false;
104                }
105            }
106            if (EndowConstants.FrequencyWeekDays.TUESDAY.equalsIgnoreCase(dayOfWeek)) {
107                if (calendarDayOfWeek != Calendar.TUESDAY) {
108                    return false;
109                }
110            }
111            if (EndowConstants.FrequencyWeekDays.WEDNESDAY.equalsIgnoreCase(dayOfWeek)) {
112                if (calendarDayOfWeek != Calendar.WEDNESDAY) {
113                    return false;
114                }
115            }
116            if (EndowConstants.FrequencyWeekDays.THURSDAY.equalsIgnoreCase(dayOfWeek)) {
117                if (calendarDayOfWeek != Calendar.THURSDAY) {
118                    return false;
119                }
120            }
121            if (EndowConstants.FrequencyWeekDays.FRIDAY.equalsIgnoreCase(dayOfWeek)) {
122                if (calendarDayOfWeek != Calendar.FRIDAY) {
123                    return false;
124                }
125            }
126    
127            return isValid;
128        }
129    
130        /**
131         * Validates the the day of the month part of the given date matches the day of the month part of the frequency code.
132         * 
133         * @param dayOfMonth
134         * @param calendarDayOfMonth
135         * @return true if valid, false otherwise
136         */
137        private boolean validateDayOfMonth(String dayOfMonth, int calendarDayOfMonth) {
138            boolean isValid = true;
139            int frequencyCodeDayOfMonth = Integer.parseInt(dayOfMonth);
140    
141            if (frequencyCodeDayOfMonth != calendarDayOfMonth) {
142                return false;
143            }
144            return isValid;
145        }
146    
147    
148        /**
149         * Validates that the day and month of the given date match the day and month of the frequency code.
150         * 
151         * @param month
152         * @param calendarMonth
153         * @param dayOfMonth
154         * @param calendarDayOfMonth
155         * @return true if valid, false otherwise
156         */
157        private boolean validateDayAndMonth(String month, int calendarMonth, String dayOfMonth, int calendarDayOfMonth) {
158            boolean isValid = true;
159    
160            if (EndowConstants.FrequencyMonthly.MONTH_END.equalsIgnoreCase(dayOfMonth)) {
161                dayOfMonth = String.valueOf(checkMaximumDaysInMonth(calendarMonth));
162            }
163    
164            if (!validateDayOfMonth(dayOfMonth, calendarDayOfMonth)) {
165                return false;
166            }
167            else {
168    
169                if (EndowConstants.FrequencyMonths.JANUARY.equalsIgnoreCase(month)) {
170                    if (calendarMonth != Calendar.JANUARY) {
171                        return false;
172                    }
173                }
174                if (EndowConstants.FrequencyMonths.FEBRUARY.equalsIgnoreCase(month)) {
175                    if (calendarMonth != Calendar.FEBRUARY) {
176                        return false;
177                    }
178                }
179                if (EndowConstants.FrequencyMonths.MARCH.equalsIgnoreCase(month)) {
180                    if (calendarMonth != Calendar.MARCH) {
181                        return false;
182                    }
183                }
184                if (EndowConstants.FrequencyMonths.APRIL.equalsIgnoreCase(month)) {
185                    if (calendarMonth != Calendar.APRIL) {
186                        return false;
187                    }
188                }
189                if (EndowConstants.FrequencyMonths.MAY.equalsIgnoreCase(month)) {
190                    if (calendarMonth != Calendar.MAY) {
191                        return false;
192                    }
193                }
194                if (EndowConstants.FrequencyMonths.JUNE.equalsIgnoreCase(month)) {
195                    if (calendarMonth != Calendar.JUNE) {
196                        return false;
197                    }
198                }
199                if (EndowConstants.FrequencyMonths.JULY.equalsIgnoreCase(month)) {
200                    if (calendarDayOfMonth != Calendar.JULY) {
201                        return false;
202                    }
203                }
204                if (EndowConstants.FrequencyMonths.AUGUST.equalsIgnoreCase(month)) {
205                    if (calendarMonth != Calendar.AUGUST) {
206                        return false;
207                    }
208                }
209                if (EndowConstants.FrequencyMonths.SEPTEMBER.equalsIgnoreCase(month)) {
210                    if (calendarMonth != Calendar.SEPTEMBER) {
211                        return false;
212                    }
213                }
214                if (EndowConstants.FrequencyMonths.OCTOBER.equalsIgnoreCase(month)) {
215                    if (calendarMonth != Calendar.OCTOBER) {
216                        return false;
217                    }
218                }
219                if (EndowConstants.FrequencyMonths.NOVEMBER.equalsIgnoreCase(month)) {
220                    if (calendarMonth != Calendar.NOVEMBER) {
221                        return false;
222                    }
223                }
224                if (EndowConstants.FrequencyMonths.DECEMBER.equalsIgnoreCase(month)) {
225                    if (calendarMonth != Calendar.DECEMBER) {
226                        return false;
227                    }
228                }
229            }
230            return isValid;
231        }
232    
233        /**
234         * Validates that the given date day and month coincide with valid values for the quarterly frequency code. For the Quarterly
235         * frequency code the month part can be J=January, F=February and M=March. Any of this months plus 3, 6, 9 months will be a
236         * valid value for the month.
237         * 
238         * @param month
239         * @param calendarMonth
240         * @param dayOfMonth
241         * @param calendarDayOfMonth
242         * @return true if valid, false otherwise
243         */
244        private boolean validateQuarterly(String month, int calendarMonth, String dayOfMonth, int calendarDayOfMonth) {
245            boolean isValid = true;
246    
247            if (EndowConstants.FrequencyMonthly.MONTH_END.equalsIgnoreCase(dayOfMonth)) {
248                dayOfMonth = String.valueOf(checkMaximumDaysInMonth(calendarMonth));
249            }
250    
251            if (!validateDayOfMonth(dayOfMonth, calendarDayOfMonth)) {
252                return false;
253            }
254    
255            if (EndowConstants.FrequencyMonths.JANUARY.equalsIgnoreCase(month)) {
256                if (!(calendarMonth == Calendar.JANUARY || calendarMonth == Calendar.APRIL || calendarMonth == Calendar.JULY || calendarMonth == Calendar.OCTOBER)) {
257                    return false;
258                }
259            }
260    
261            if (EndowConstants.FrequencyMonths.FEBRUARY.equalsIgnoreCase(month)) {
262                if (!(calendarMonth == Calendar.FEBRUARY || calendarMonth == Calendar.MAY || calendarMonth == Calendar.AUGUST || calendarMonth == Calendar.NOVEMBER)) {
263                    return false;
264                }
265            }
266    
267            if (EndowConstants.FrequencyMonths.MARCH.equalsIgnoreCase(month)) {
268                if (!(calendarMonth == Calendar.MARCH || calendarMonth == Calendar.JUNE || calendarMonth == Calendar.SEPTEMBER || calendarMonth == Calendar.DECEMBER)) {
269                    return false;
270                }
271            }
272    
273            return isValid;
274        }
275    
276        /**
277         * Validates the given date day and month coincide with a valid value for the semi-annually frequency code. The month part of
278         * the frequency code can be J=January, F=February, M=March, A=April, Y=May, U=June. Any of these month plus 6 months is a valid
279         * value.
280         * 
281         * @param month
282         * @param calendarMonth
283         * @param dayOfMonth
284         * @param calendarDayOfMonth
285         * @return true if valid, false otherwise
286         */
287        private boolean validateSemiAnnually(String month, int calendarMonth, String dayOfMonth, int calendarDayOfMonth) {
288            boolean isValid = true;
289    
290            if (EndowConstants.FrequencyMonthly.MONTH_END.equalsIgnoreCase(dayOfMonth)) {
291                dayOfMonth = String.valueOf(checkMaximumDaysInMonth(calendarMonth));
292            }
293    
294            if (!validateDayOfMonth(dayOfMonth, calendarDayOfMonth)) {
295                return false;
296            }
297    
298            if (EndowConstants.FrequencyMonths.JANUARY.equalsIgnoreCase(month)) {
299                if (!(calendarMonth == Calendar.JANUARY || calendarMonth == Calendar.JULY)) {
300                    return false;
301                }
302            }
303    
304            if (EndowConstants.FrequencyMonths.FEBRUARY.equalsIgnoreCase(month)) {
305                if (!(calendarMonth == Calendar.FEBRUARY || calendarMonth == Calendar.AUGUST)) {
306                    return false;
307                }
308            }
309    
310            if (EndowConstants.FrequencyMonths.MARCH.equalsIgnoreCase(month)) {
311                if (!(calendarMonth == Calendar.MARCH || calendarMonth == Calendar.SEPTEMBER)) {
312                    return false;
313                }
314            }
315    
316            if (EndowConstants.FrequencyMonths.APRIL.equalsIgnoreCase(month)) {
317                if (!(calendarMonth == Calendar.APRIL || calendarMonth == Calendar.OCTOBER)) {
318                    return false;
319                }
320            }
321    
322            if (EndowConstants.FrequencyMonths.MAY.equalsIgnoreCase(month)) {
323                if (!(calendarMonth == Calendar.MAY || calendarMonth == Calendar.NOVEMBER)) {
324                    return false;
325                }
326            }
327    
328            if (EndowConstants.FrequencyMonths.JUNE.equalsIgnoreCase(month)) {
329                if (!(calendarMonth == Calendar.JUNE || calendarMonth == Calendar.DECEMBER)) {
330                    return false;
331                }
332            }
333    
334            return isValid;
335        }
336    
337        /**
338         * This method will check and return maximum days in a month.
339         * 
340         * @param monthNumber The number of the month to test for maximum days..
341         * @return maxDays Maximum number of days in the month of February for calendar.
342         */
343        private int checkMaximumDaysInMonth(int monthNumber) {
344            int maxDays;
345    
346            Calendar calendar = Calendar.getInstance();
347            calendar.set(Calendar.MONTH, monthNumber);
348            maxDays = calendar.getActualMaximum(Calendar.DAY_OF_MONTH);
349    
350            return maxDays;
351        }
352    }