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.coa.batch.dataaccess.impl;
017
018 import java.sql.Date;
019 import java.util.Collection;
020 import java.util.GregorianCalendar;
021 import java.util.regex.Matcher;
022 import java.util.regex.Pattern;
023
024 import org.apache.commons.lang.StringUtils;
025 import org.apache.ojb.broker.query.Criteria;
026 import org.apache.ojb.broker.query.QueryByCriteria;
027 import org.kuali.kfs.coa.businessobject.AccountingPeriod;
028 import org.kuali.kfs.sys.KFSPropertyConstants;
029 import org.kuali.kfs.sys.batch.dataaccess.impl.FiscalYearMakerImpl;
030 import org.kuali.rice.kns.bo.PersistableBusinessObject;
031
032 /**
033 * Performs custom population of accounting periods records for a new year being created in the fiscal year maker process
034 */
035 public class AccountingPeriodFiscalYearMakerImpl extends FiscalYearMakerImpl {
036
037 public AccountingPeriodFiscalYearMakerImpl() {
038 super();
039
040 super.setAllowOverrideTargetYear(false);
041 }
042
043 /**
044 * Updates the year on the fiscal period name and sets status to open for next year records
045 *
046 * @see org.kuali.kfs.coa.batch.dataaccess.impl.FiscalYearMakerHelperImpl#changeForNewYear(java.lang.Integer,
047 * org.kuali.rice.kns.bo.PersistableBusinessObject)
048 */
049 @Override
050 public void changeForNewYear(Integer baseFiscalYear, PersistableBusinessObject currentRecord) {
051 super.changeForNewYear(baseFiscalYear, currentRecord);
052
053 AccountingPeriod accountingPeriod = (AccountingPeriod) currentRecord;
054
055 // update fiscal period name which contains the fiscal year
056 String fiscalPeriodName = accountingPeriod.getUniversityFiscalPeriodName();
057
058 String oldCalendarStartYear = new Integer(accountingPeriod.getUniversityFiscalYear() - 2).toString();
059 String oldCalendarEndYear = new Integer(accountingPeriod.getUniversityFiscalYear() - 1).toString();
060
061 String newCalendarStartYear = new Integer(accountingPeriod.getUniversityFiscalYear() - 1).toString();
062 String newCalendarEndYear = new Integer(accountingPeriod.getUniversityFiscalYear()).toString();
063
064 // replace 4 digit year in name if found, else replace 2 digit
065 if (StringUtils.contains(fiscalPeriodName, oldCalendarEndYear)) {
066 fiscalPeriodName = StringUtils.replace(fiscalPeriodName, oldCalendarEndYear, newCalendarEndYear);
067 }
068 else if (StringUtils.contains(fiscalPeriodName, oldCalendarStartYear)) {
069 fiscalPeriodName = StringUtils.replace(fiscalPeriodName, oldCalendarStartYear, newCalendarStartYear);
070 }
071 else {
072 fiscalPeriodName = updateTwoDigitYear(newCalendarEndYear.substring(2, 4), oldCalendarEndYear.substring(2, 4), fiscalPeriodName);
073 fiscalPeriodName = updateTwoDigitYear(newCalendarStartYear.substring(2, 4), oldCalendarStartYear.substring(2, 4), fiscalPeriodName);
074 }
075
076 accountingPeriod.setUniversityFiscalPeriodName(fiscalPeriodName);
077
078 // increment period end date by one year
079 accountingPeriod.setUniversityFiscalPeriodEndDate(addYearToDate(accountingPeriod.getUniversityFiscalPeriodEndDate()));
080
081 // set status to closed
082 accountingPeriod.setActive(false);
083 }
084
085 /**
086 * Retrieves all Accounting Period records for the first copied fiscal year and make active
087 *
088 * @see org.kuali.kfs.coa.batch.dataaccess.impl.FiscalYearMakerHelperImpl#performCustomProcessing(java.lang.Integer)
089 */
090 @Override
091 public void performCustomProcessing(Integer baseFiscalYear, boolean firstCopyYear) {
092 if (!firstCopyYear) {
093 return;
094 }
095
096 Criteria criteriaId = new Criteria();
097 criteriaId.addEqualTo(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, baseFiscalYear + 1);
098
099 QueryByCriteria queryId = new QueryByCriteria(AccountingPeriod.class, criteriaId);
100
101 Collection<AccountingPeriod> accountingPeriods = getPersistenceBrokerTemplate().getCollectionByQuery(queryId);
102 for (AccountingPeriod accountingPeriod : accountingPeriods) {
103 accountingPeriod.setActive(true);
104 getPersistenceBrokerTemplate().store(accountingPeriod);
105 }
106 }
107
108 /**
109 * Adds one year to the given date
110 *
111 * @param inDate date to increment
112 * @return Date incoming date plus one year
113 */
114 protected java.sql.Date addYearToDate(Date inDate) {
115 GregorianCalendar currentCalendarDate = new GregorianCalendar();
116 currentCalendarDate.clear();
117
118 currentCalendarDate.setTimeInMillis(inDate.getTime());
119 currentCalendarDate.add(GregorianCalendar.YEAR, 1);
120
121 return new Date(currentCalendarDate.getTimeInMillis());
122 }
123
124 /**
125 * this routine is provided to update string fields which contain two-digit years that need to be updated for display. it is
126 * very specific, but it's necessary. "two-digit year" means the two numeric characters preceded by a non-numeric character.
127 *
128 * @param newYear
129 * @param oldYear
130 * @param currentString
131 * @return the updated string for a two digit year
132 */
133 protected String updateTwoDigitYear(String newYear, String oldYear, String currentString) {
134 // group 1 is the bounded by the outermost set of parentheses
135 // group 2 is the first inner set
136 // group 3 is the second inner set--a two-digit year at the beginning of the line
137 String regExpString = "(([^0-9]{1}" + oldYear + ")|^(" + oldYear + "))";
138 Pattern pattern = Pattern.compile(regExpString);
139 Matcher matcher = pattern.matcher(currentString);
140
141 // start looking for a match
142 boolean matched = matcher.find();
143 if (!matched) {
144 // just return if nothing is found
145 return currentString;
146 }
147
148 // we found something
149 // we have to process it
150 String returnString = currentString;
151 StringBuffer outString = new StringBuffer();
152 // is there a match at the beginning of the line (a match with group 3)?
153 if (matcher.group(3) != null) {
154 // there is a two-digit-year string at the beginning of the line
155 // we want to replace it
156 matcher.appendReplacement(outString, newYear);
157 // find the next match if there is one
158 matched = matcher.find();
159 }
160
161 while (matched) {
162 // the new string will no longer match with group 3
163 // if there is still a match, it will be with group 2
164 // now we have to prefix the new year string with the same
165 // non-numeric character as the next match (hyphen, space, whatever)
166 String newYearString = matcher.group(2).substring(0, 1) + newYear;
167 matcher.appendReplacement(outString, newYearString);
168 matched = matcher.find();
169 }
170
171 // dump whatever detritus is left into the new string
172 matcher.appendTail(outString);
173
174 return outString.toString();
175 }
176
177 }