View Javadoc
1   /*
2    * Copyright 2007 The Kuali Foundation
3    * 
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    * http://www.opensource.org/licenses/ecl2.php
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.gl.batch.service.impl;
17  
18  import java.util.Calendar;
19  import java.util.Date;
20  import java.util.StringTokenizer;
21  
22  import org.apache.commons.lang.StringUtils;
23  import org.kuali.ole.gl.GeneralLedgerConstants;
24  import org.kuali.ole.gl.batch.ScrubberStep;
25  import org.kuali.ole.gl.batch.service.RunDateService;
26  import org.kuali.rice.coreservice.framework.parameter.ParameterService;
27  
28  /**
29   * The default implementation of RunDateService
30   */
31  public class RunDateServiceImpl implements RunDateService {
32      private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(RunDateServiceImpl.class);
33  
34      private ParameterService parameterService;
35  
36      /**
37       * 
38       * @see org.kuali.ole.gl.batch.service.RunDateService#calculateRunDate(java.util.Date)
39       */
40      public Date calculateRunDate(Date executionDate) {
41          Calendar currentCal = Calendar.getInstance();
42          currentCal.setTime(executionDate);
43  
44          CutoffTime cutoffTime = parseCutoffTime(retrieveCutoffTimeValue());
45  
46          if (isCurrentDateBeforeCutoff(currentCal, cutoffTime)) {
47              // time to set the date to the previous day's last minute/second
48              currentCal.add(Calendar.DAY_OF_MONTH, -1);
49              // per old COBOL code (see KULRNE-70),
50              // the time is set to 23:59:59 (assuming 0 ms)
51              currentCal.set(Calendar.HOUR_OF_DAY, 23);
52              currentCal.set(Calendar.MINUTE, 59);
53              currentCal.set(Calendar.SECOND, 59);
54              currentCal.set(Calendar.MILLISECOND, 0);
55              return new Date(currentCal.getTimeInMillis());
56          }
57          return new Date(executionDate.getTime());
58      }
59  
60      /**
61       * Determines if the given calendar time is before the given cutoff time
62       * 
63       * @param currentCal the current time
64       * @param cutoffTime the "start of the day" cut off time
65       * @return true if the current time is before the cutoff, false otherwise
66       */
67      protected boolean isCurrentDateBeforeCutoff(Calendar currentCal, CutoffTime cutoffTime) {
68          if (cutoffTime != null) {
69              // if cutoff date is not properly defined
70              // 24 hour clock (i.e. hour is 0 - 23)
71  
72              // clone the calendar so we get the same month, day, year
73              // then change the hour, minute, second fields
74              // then see if the cutoff is before or after
75              Calendar cutoffCal = (Calendar) currentCal.clone();
76              cutoffCal.setLenient(false);
77              cutoffCal.set(Calendar.HOUR_OF_DAY, cutoffTime.hour);
78              cutoffCal.set(Calendar.MINUTE, cutoffTime.minute);
79              cutoffCal.set(Calendar.SECOND, cutoffTime.second);
80              cutoffCal.set(Calendar.MILLISECOND, 0);
81  
82              return currentCal.before(cutoffCal);
83          }
84          // if cutoff date is not properly defined, then it is considered to be after the cutoff
85          return false;
86      }
87  
88      /**
89       * Holds the hour, minute, and second of a given cut off time
90       */
91      protected class CutoffTime {
92          /**
93           * 24 hour time, from 0-23, inclusive
94           */
95          protected int hour;
96  
97          /**
98           * From 0-59, inclusive
99           */
100         protected int minute;
101 
102         /**
103          * From 0-59, inclusive
104          */
105         protected int second;
106 
107         /**
108          * Constructs a RunDateServiceImpl instance
109          * @param hour the cutoff hour
110          * @param minute the cutoff minute
111          * @param second the cutoff second
112          */
113         protected CutoffTime(int hour, int minute, int second) {
114             this.hour = hour;
115             this.minute = minute;
116             this.second = second;
117         }
118     }
119 
120     /**
121      * Parses a String representation of the cutoff time
122      * 
123      * @param cutoffTime the cutoff time String to parse
124      * @return a record holding the cutoff time
125      */
126     protected CutoffTime parseCutoffTime(String cutoffTime) {
127         if (StringUtils.isBlank(cutoffTime)) {
128             return new CutoffTime(0, 0, 0);
129         }
130         else {
131             cutoffTime = cutoffTime.trim();
132             if (LOG.isDebugEnabled()) {
133                 LOG.debug("Cutoff time value found: " + cutoffTime);
134             }
135             StringTokenizer st = new StringTokenizer(cutoffTime, ":", false);
136 
137             try {
138                 String hourStr = st.nextToken();
139                 String minuteStr = st.nextToken();
140                 String secondStr = st.nextToken();
141 
142                 int hourInt = Integer.parseInt(hourStr, 10);
143                 int minuteInt = Integer.parseInt(minuteStr, 10);
144                 int secondInt = Integer.parseInt(secondStr, 10);
145 
146                 if (hourInt < 0 || hourInt > 23 || minuteInt < 0 || minuteInt > 59 || secondInt < 0 || secondInt > 59) {
147                     throw new IllegalArgumentException("Cutoff time must be in the format \"HH:mm:ss\", where HH, mm, ss are defined in the java.text.SimpleDateFormat class.  In particular, 0 <= hour <= 23, 0 <= minute <= 59, and 0 <= second <= 59");
148                 }
149                 return new CutoffTime(hourInt, minuteInt, secondInt);
150             }
151             catch (Exception e) {
152                 throw new IllegalArgumentException("Cutoff time should either be null, or in the format \"HH:mm:ss\", where HH, mm, ss are defined in the java.text.SimpleDateFormat class.");
153             }
154         }
155     }
156 
157     /**
158      * Retrieves the cutoff time from a repository.
159      * 
160      * @return a time of day in the format "HH:mm:ss", where HH, mm, ss are defined in the java.text.SimpleDateFormat class. In
161      *         particular, 0 <= hour <= 23, 0 <= minute <= 59, and 0 <= second <= 59
162      */
163     protected String retrieveCutoffTimeValue() {
164         String value = parameterService.getParameterValueAsString(ScrubberStep.class, GeneralLedgerConstants.GlScrubberGroupParameters.SCRUBBER_CUTOFF_TIME);
165         if (StringUtils.isBlank(value)) {
166             LOG.error("Unable to retrieve parameter for GL process cutoff date.  Defaulting to no cutoff time (i.e. midnight)");
167             value = null;
168         }
169         return value;
170     }
171 
172     public void setParameterService(ParameterService parameterService) {
173         this.parameterService = parameterService;
174     }
175 
176 }