001: /*
002: * Copyright 2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.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/ecl1.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.module.gl.service.impl;
017:
018: import java.util.Calendar;
019: import java.util.Date;
020: import java.util.StringTokenizer;
021:
022: import org.apache.commons.lang.StringUtils;
023: import org.kuali.kfs.service.ParameterService;
024: import org.kuali.module.gl.GLConstants;
025: import org.kuali.module.gl.batch.ScrubberStep;
026: import org.kuali.module.gl.service.RunDateService;
027:
028: /**
029: * The default implementation of RunDateService
030: */
031: public class RunDateServiceImpl implements RunDateService {
032: private static org.apache.log4j.Logger LOG = org.apache.log4j.Logger
033: .getLogger(RunDateServiceImpl.class);
034:
035: private ParameterService parameterService;
036:
037: /**
038: *
039: * @see org.kuali.module.gl.service.RunDateService#calculateRunDate(java.util.Date)
040: */
041: public Date calculateRunDate(Date executionDate) {
042: Calendar currentCal = Calendar.getInstance();
043: currentCal.setTime(executionDate);
044:
045: CutoffTime cutoffTime = parseCutoffTime(retrieveCutoffTimeValue());
046:
047: if (isCurrentDateBeforeCutoff(currentCal, cutoffTime)) {
048: // time to set the date to the previous day's last minute/second
049: currentCal.add(Calendar.DAY_OF_MONTH, -1);
050: // per old COBOL code (see KULRNE-70),
051: // the time is set to 23:59:59 (assuming 0 ms)
052: currentCal.set(Calendar.HOUR_OF_DAY, 23);
053: currentCal.set(Calendar.MINUTE, 59);
054: currentCal.set(Calendar.SECOND, 59);
055: currentCal.set(Calendar.MILLISECOND, 0);
056: return new Date(currentCal.getTimeInMillis());
057: }
058: return new Date(executionDate.getTime());
059: }
060:
061: /**
062: * Determines if the given calendar time is before the given cutoff time
063: *
064: * @param currentCal the current time
065: * @param cutoffTime the "start of the day" cut off time
066: * @return true if the current time is before the cutoff, false otherwise
067: */
068: protected boolean isCurrentDateBeforeCutoff(Calendar currentCal,
069: CutoffTime cutoffTime) {
070: if (cutoffTime != null) {
071: // if cutoff date is not properly defined
072: // 24 hour clock (i.e. hour is 0 - 23)
073:
074: // clone the calendar so we get the same month, day, year
075: // then change the hour, minute, second fields
076: // then see if the cutoff is before or after
077: Calendar cutoffCal = (Calendar) currentCal.clone();
078: cutoffCal.setLenient(false);
079: cutoffCal.set(Calendar.HOUR_OF_DAY, cutoffTime.hour);
080: cutoffCal.set(Calendar.MINUTE, cutoffTime.minute);
081: cutoffCal.set(Calendar.SECOND, cutoffTime.second);
082: cutoffCal.set(Calendar.MILLISECOND, 0);
083:
084: return currentCal.before(cutoffCal);
085: }
086: // if cutoff date is not properly defined, then it is considered to be after the cutoff
087: return false;
088: }
089:
090: /**
091: * Holds the hour, minute, and second of a given cut off time
092: */
093: protected class CutoffTime {
094: /**
095: * 24 hour time, from 0-23, inclusive
096: */
097: protected int hour;
098:
099: /**
100: * From 0-59, inclusive
101: */
102: protected int minute;
103:
104: /**
105: * From 0-59, inclusive
106: */
107: protected int second;
108:
109: /**
110: * Constructs a RunDateServiceImpl instance
111: * @param hour the cutoff hour
112: * @param minute the cutoff minute
113: * @param second the cutoff second
114: */
115: protected CutoffTime(int hour, int minute, int second) {
116: this .hour = hour;
117: this .minute = minute;
118: this .second = second;
119: }
120: }
121:
122: /**
123: * Parses a String representation of the cutoff time
124: *
125: * @param cutoffTime the cutoff time String to parse
126: * @return a record holding the cutoff time
127: */
128: protected CutoffTime parseCutoffTime(String cutoffTime) {
129: if (StringUtils.isBlank(cutoffTime)) {
130: return new CutoffTime(0, 0, 0);
131: } else {
132: cutoffTime = cutoffTime.trim();
133: LOG.debug("Cutoff time value found: " + cutoffTime);
134: StringTokenizer st = new StringTokenizer(cutoffTime, ":",
135: 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
147: || minuteInt > 59 || secondInt < 0
148: || secondInt > 59) {
149: throw new IllegalArgumentException(
150: "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");
151: }
152: return new CutoffTime(hourInt, minuteInt, secondInt);
153: } catch (Exception e) {
154: throw new IllegalArgumentException(
155: "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.");
156: }
157: }
158: }
159:
160: /**
161: * Retrieves the cutoff time from a repository.
162: *
163: * @return a time of day in the format "HH:mm:ss", where HH, mm, ss are defined in the java.text.SimpleDateFormat class. In
164: * particular, 0 <= hour <= 23, 0 <= minute <= 59, and 0 <= second <= 59
165: */
166: protected String retrieveCutoffTimeValue() {
167: String value = parameterService
168: .getParameterValue(
169: ScrubberStep.class,
170: GLConstants.GlScrubberGroupParameters.SCRUBBER_CUTOFF_TIME);
171: if (StringUtils.isBlank(value)) {
172: LOG
173: .error("Unable to retrieve parameter for GL process cutoff date. Defaulting to no cutoff time (i.e. midnight)");
174: value = null;
175: }
176: return value;
177: }
178:
179: public void setParameterService(ParameterService parameterService) {
180: this.parameterService = parameterService;
181: }
182:
183: }
|