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