Java tutorial
/* * Copyright 2005-2010 The Kuali Foundation * * Licensed under the Educational Community License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.osedu.org/licenses/ECL-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.kuali.kra.budget.rates; import java.sql.Date; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; import org.apache.commons.collections.CollectionUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.kuali.kra.bo.AbstractInstituteRate; import org.kuali.kra.bo.InstituteLaRate; import org.kuali.kra.bo.InstituteRate; import org.kuali.kra.bo.Unit; import org.kuali.kra.budget.core.Budget; import org.kuali.kra.budget.core.BudgetParent; import org.kuali.kra.budget.core.BudgetService; import org.kuali.kra.budget.document.BudgetDocument; import org.kuali.kra.budget.document.BudgetParentDocument; import org.kuali.kra.budget.parameters.BudgetPeriod; import org.kuali.kra.budget.personnel.BudgetPerson; import org.kuali.kra.budget.web.struts.form.BudgetForm; import org.kuali.kra.infrastructure.Constants; import org.kuali.kra.infrastructure.KeyConstants; import org.kuali.kra.infrastructure.KraServiceLocator; import org.kuali.kra.proposaldevelopment.bo.ActivityType; import org.kuali.rice.kns.bo.BusinessObject; import org.kuali.rice.kns.service.BusinessObjectService; import org.kuali.rice.kns.util.AuditCluster; import org.kuali.rice.kns.util.AuditError; import org.kuali.rice.kns.util.GlobalVariables; public class BudgetRatesServiceImpl<T extends BudgetParent> implements BudgetRatesService<T> { private static final String SPACE = " "; public static final String UNIT_NUMBER_KEY = "unitNumber"; public static final String ACTIVITY_TYPE_CODE_KEY = "activityTypeCode"; public static final String BUDGET_ID_KEY = "budgetId"; private BusinessObjectService _businessObjectService; private static final String PERIOD_SEARCH_SEPARATOR = "|"; private static final String PERIOD_DISPLAY_SEPARATOR = ","; private static final Log LOG = LogFactory.getLog(BudgetRatesServiceImpl.class); private static final String BUDGET_RATE_AUDIT_WARNING_KEY = "budgetRateAuditWarnings"; /** * @see org.kuali.kra.budget.rates.BudgetRatesService#resetAllBudgetRates(org.kuali.kra.budget.core.Budget) */ public void resetAllBudgetRates(Budget budget) { resetAbstractBudgetApplicableRatesToInstituteRates(budget.getBudgetRates()); resetAbstractBudgetApplicableRatesToInstituteRates(budget.getBudgetLaRates()); } /** * reset budget rates for a panel * each panel is based on rate class type * * @see org.kuali.kra.budget.rates.BudgetRatesService#resetBudgetRatesForRateClassType(java.lang.String, org.kuali.kra.budget.core.Budget) */ public void resetBudgetRatesForRateClassType(String rateClassType, Budget budget) { List<RateClass> rateClasses = budget.getRateClasses(); resetBudgetRatesForRateClassType(rateClasses, rateClassType, budget.getBudgetRates()); resetBudgetRatesForRateClassType(rateClasses, rateClassType, budget.getBudgetLaRates()); } /** * @see org.kuali.kra.budget.rates.BudgetRatesService#syncAllBudgetRates(org.kuali.kra.budget.core.Budget) */ public void syncAllBudgetRates(BudgetDocument<T> budgetDocument) { Budget budget = budgetDocument.getBudget(); List<InstituteRate> allInstituteRates = new ArrayList<InstituteRate>(getInstituteRates(budgetDocument)); List<InstituteLaRate> allInstituteLaRates = new ArrayList<InstituteLaRate>( getInstituteLaRates(budgetDocument)); if (isOutOfSync(budget)) { Map<String, AbstractInstituteRate> mapOfExistingBudgetProposalRates = mapRatesToKeys( budget.getBudgetRates()); Map<String, AbstractInstituteRate> mapOfExistingBudgetProposalLaRates = mapRatesToKeys( budget.getBudgetLaRates()); budget.getBudgetRates().clear(); budget.getBudgetLaRates().clear(); budget.getRateClasses().clear(); // since different rate schedules can change UnrecoveredFandA, clear here budget.getBudgetUnrecoveredFandAs().clear(); getBudgetRates(budgetDocument, allInstituteRates); getBudgetLaRates(budgetDocument, allInstituteLaRates); syncVersionNumber(mapOfExistingBudgetProposalRates, budget.getBudgetRates()); syncVersionNumber(mapOfExistingBudgetProposalLaRates, budget.getBudgetLaRates()); } else { syncBudgetRates(budget.getBudgetRates(), allInstituteRates); syncBudgetRates(budget.getBudgetLaRates(), allInstituteLaRates); } } @SuppressWarnings("unchecked") protected void syncVersionNumber(Map<String, AbstractInstituteRate> oldRateMap, List rates) { List<AbstractBudgetRate> abstractBudgetRates = (List<AbstractBudgetRate>) rates; for (AbstractBudgetRate budgetRate : abstractBudgetRates) { AbstractInstituteRate oldRate = oldRateMap.get(budgetRate.getRateKeyAsString()); if (oldRate != null) { budgetRate.setVersionNumber(oldRate.getVersionNumber()); } } } /* update view - location * * */ public void viewLocation(String viewLocation, Integer budgetPeriod, Budget budget) { viewLocation(viewLocation, budgetPeriod, budget.getBudgetRates()); viewLocation(viewLocation, budgetPeriod, budget.getBudgetLaRates()); } /** * * Does nothing. Placeholder for Award Budget * @param budgetDocument */ public void syncParentDocumentRates(BudgetDocument<T> budgetDocument) { } /* sync budget rates for a panel * each panel is based on rate class type * */ public void syncBudgetRatesForRateClassType(String rateClassType, BudgetDocument<T> budgetDocument) { Budget budget = budgetDocument.getBudget(); populateInstituteRates(budgetDocument); Map<String, AbstractInstituteRate> mapOfExistingBudgetProposalRates = mapRatesToKeys( budget.getBudgetRates()); Map<String, AbstractInstituteRate> mapOfExistingBudgetProposalLaRates = mapRatesToKeys( budget.getBudgetLaRates()); replaceRateClassesForRateClassType(rateClassType, budget, budget.getInstituteRates()); replaceRateClassesForRateClassType(rateClassType, budget, budget.getInstituteLaRates()); replaceBudgetRatesForRateClassType(rateClassType, budgetDocument, budget.getBudgetRates(), budget.getInstituteRates()); replaceBudgetRatesForRateClassType(rateClassType, budgetDocument, budget.getBudgetLaRates(), budget.getInstituteLaRates()); syncVersionNumber(mapOfExistingBudgetProposalRates, budget.getBudgetRates()); syncVersionNumber(mapOfExistingBudgetProposalLaRates, budget.getBudgetLaRates()); } /** * * @see org.kuali.kra.budget.rates.BudgetRatesService#getBudgetRates(java.util.List, org.kuali.kra.budget.core.Budget) */ public void getBudgetRates(List<RateClassType> rateClassTypes, BudgetDocument<T> budgetDocument) { getBudgetRates(rateClassTypes, budgetDocument, getInstituteRates(budgetDocument)); } /* verify and add activity type prefix if required for rate class type description * * */ protected void checkActivityPrefixForRateClassTypes(List<RateClassType> rateClassTypes, BudgetDocument<T> budgetDocument) { //String activityTypeDescription = budget.getProposal().getActivityType().getDescription().concat(SPACE); Budget budget = budgetDocument.getBudget(); String activityTypeDescription = getActivityTypeDescription(budgetDocument); List<BudgetRate> budgetRates = budget.getBudgetRates(); List<BudgetLaRate> budgetLaRates = budget.getBudgetLaRates(); for (RateClassType rateClassType : rateClassTypes) { if (rateClassType.getPrefixActivityType()) { String newRateClassTypeDescription = activityTypeDescription.concat(rateClassType.getDescription()); rateClassType.setDescription(newRateClassTypeDescription); rateClassType.setPrefixActivityType(false); /* set in proposal rates reference */ for (BudgetRate budgetRate : budgetRates) { RateClassType BPRateClassType = budgetRate.getRateClass().getRateClassTypeT(); if (rateClassType.getRateClassType().equalsIgnoreCase(BPRateClassType.getRateClassType())) { BPRateClassType.setDescription(newRateClassTypeDescription); } } /* set in proposal LA rates reference */ for (BudgetLaRate budgetLaRate : budgetLaRates) { RateClassType BPLRateClassType = budgetLaRate.getRateClass().getRateClassTypeT(); if (rateClassType.getRateClassType().equalsIgnoreCase(BPLRateClassType.getRateClassType())) { BPLRateClassType.setDescription(newRateClassTypeDescription); } } } } } @SuppressWarnings("unchecked") protected String getActivityTypeDescription(BudgetDocument<T> budgetDocument) { Budget budget = budgetDocument.getBudget(); BudgetParent budgetParent = budgetDocument.getParentDocument().getBudgetParent(); if (budget.isRateSynced() || !KraServiceLocator.getService(BudgetService.class) .checkActivityTypeChange(getBudgetParentDocument(budget), budget)) { if (budgetParent.getActivityType() != null) { return budgetParent.getActivityType().getDescription().concat(SPACE); } else { return ""; } } else { String activityTypeCode = null; if (CollectionUtils.isNotEmpty(budget.getBudgetRates())) { activityTypeCode = ((BudgetRate) budget.getBudgetRates().get(0)).getActivityTypeCode(); } if (activityTypeCode != null) { Map pkMap = new HashMap(); pkMap.put("activityTypeCode", activityTypeCode); ActivityType activityType = (ActivityType) KraServiceLocator.getService(BusinessObjectService.class) .findByPrimaryKey(ActivityType.class, pkMap); if (activityType == null) { return ""; } else { return activityType.getDescription().concat(SPACE); } } else { return ""; } } } /** * @see org.kuali.kra.budget.rates.BudgetRatesService#getBudgetPeriods() */ @SuppressWarnings("unchecked") public List<BudgetPeriod> getBudgetPeriods() { BudgetForm budgetForm = (BudgetForm) GlobalVariables.getKualiForm(); BudgetDocument<T> budgetDocument = budgetForm.getBudgetDocument(); List<BudgetPeriod> budgetPeriods = budgetDocument.getBudget().getBudgetPeriods(); return budgetPeriods; } /** * Sets the businessObjectService attribute value. * @param businessObjectService The businessObjectService to set. */ public void setBusinessObjectService(BusinessObjectService businessObjectService) { this._businessObjectService = businessObjectService; } /** * Build rates for each period. * @return . */ protected void updateRatesForEachPeriod(Budget budget) { List<BudgetRate> budgetRates = budget.getBudgetRates(); List<BudgetLaRate> budgetLaRates = budget.getBudgetLaRates(); List<BudgetPeriod> budgetPeriods = budget.getBudgetPeriods(); for (BudgetPeriod budgetPeriod : budgetPeriods) { for (BudgetRate budgetRate : budgetRates) { if (budgetRate.getStartDate().compareTo(budgetPeriod.getEndDate()) <= 0) { String dispBudgetPeriod = budgetPeriod.getBudgetPeriod().toString(); String formattedPeriod = dispBudgetPeriod.concat(PERIOD_SEARCH_SEPARATOR); String currBudgetPeriod = budgetRate.getTrackAffectedPeriod(); //(String)ratesForEachPeriod.get(budgetPeriod.getBudgetPeriod()); if (currBudgetPeriod == null) { currBudgetPeriod = PERIOD_SEARCH_SEPARATOR.concat(formattedPeriod); budgetRate.setTrackAffectedPeriod(currBudgetPeriod); } else { if (currBudgetPeriod.indexOf(formattedPeriod) < 0) { currBudgetPeriod = currBudgetPeriod.concat(formattedPeriod); budgetRate.setTrackAffectedPeriod(currBudgetPeriod); } } budgetRate.setAffectedBudgetPeriod(getFormattedAffectedBudgetPeriod(currBudgetPeriod)); } } for (BudgetLaRate budgetLaRate : budgetLaRates) { if (budgetLaRate.getStartDate().compareTo(budgetPeriod.getEndDate()) <= 0) { String dispBudgetPeriod = budgetPeriod.getBudgetPeriod().toString(); String formattedPeriod = dispBudgetPeriod.concat(PERIOD_SEARCH_SEPARATOR); String currBudgetPeriod = budgetLaRate.getTrackAffectedPeriod(); //(String)ratesForEachPeriod.get(budgetPeriod.getBudgetPeriod()); if (currBudgetPeriod == null) { currBudgetPeriod = PERIOD_SEARCH_SEPARATOR.concat(formattedPeriod); budgetLaRate.setTrackAffectedPeriod(currBudgetPeriod); } else { if (currBudgetPeriod.indexOf(formattedPeriod) < 0) { currBudgetPeriod = currBudgetPeriod.concat(formattedPeriod); budgetLaRate.setTrackAffectedPeriod(currBudgetPeriod); } } budgetLaRate.setAffectedBudgetPeriod(getFormattedAffectedBudgetPeriod(currBudgetPeriod)); } } } } /** * This method load institute rates to hashmap * @param rates * @return */ @SuppressWarnings("unchecked") protected Map<String, AbstractInstituteRate> mapRatesToKeys(Collection rates) { Collection<AbstractInstituteRate> abstractInstituteRates = (Collection<AbstractInstituteRate>) rates; Map<String, AbstractInstituteRate> rateMap = new HashMap<String, AbstractInstituteRate>(); for (AbstractInstituteRate abstractInstituteRate : abstractInstituteRates) { rateMap.put(abstractInstituteRate.getRateKeyAsString(), abstractInstituteRate); } return rateMap; } /* get all institute rates - based on activity type * and unit number * */ @SuppressWarnings("unchecked") protected Collection<InstituteRate> getInstituteRates(BudgetDocument<T> budgetDocument) { //get first unit number in hierarchy with rates then select appropriate rates Unit firstUnit = findFirstUnitWithRates(budgetDocument.getParentDocument().getBudgetParent().getUnit(), InstituteRate.class); if (firstUnit == null) { return new ArrayList(); } Collection abstractRates = getActiveInstituteRates(InstituteRate.class, firstUnit, budgetDocument.getParentDocument().getBudgetParent().getActivityTypeCode()); return (Collection<InstituteRate>) abstractRates; } @SuppressWarnings("unchecked") protected Unit findFirstUnitWithRates(Unit leadUnit, Class rateType) { Unit currentUnit = leadUnit; Map<String, String> currentSearchMap = new HashMap<String, String>(); Collection currentRates = null; while (currentUnit != null) { currentSearchMap.put(UNIT_NUMBER_KEY, currentUnit.getUnitNumber()); currentRates = filterForActiveRatesOnly( getBusinessObjectService().findMatching(rateType, currentSearchMap)); if (currentRates != null && !currentRates.isEmpty()) { break; } currentUnit = currentUnit.getParentUnit(); } return currentUnit; } @SuppressWarnings("unchecked") protected Collection<AbstractInstituteRate> getActiveInstituteRates(Class rateType, Unit unit, String activityTypeCode) { Map<String, String> searchMap = new HashMap<String, String>(); searchMap.put(UNIT_NUMBER_KEY, unit.getUnitNumber()); searchMap.put(ACTIVITY_TYPE_CODE_KEY, activityTypeCode); return filterForActiveRatesOnly(getBusinessObjectService().findMatching(rateType, searchMap)); } /* get all institute rates - based on * and unit number * */ @SuppressWarnings("unchecked") protected Collection<InstituteLaRate> getInstituteLaRates(BudgetDocument<T> budgetDocument) { // Budget budget = budgetDocument.getBudget(); BudgetParent budgetParent = budgetDocument.getParentDocument().getBudgetParent(); String unitNumber = budgetParent.getUnitNumber(); Collection abstractInstituteRates = getFilteredInstituteLaRates(InstituteLaRate.class, unitNumber, budgetParent.getUnit(), getRateFilterMap(budgetDocument)); abstractInstituteRates = abstractInstituteRates.size() > 0 ? abstractInstituteRates : new ArrayList(); return (Collection<InstituteLaRate>) abstractInstituteRates; } /** * This method... * @param budget * @return */ @SuppressWarnings("unchecked") protected BudgetParentDocument<T> getBudgetParentDocument(Budget budget) { BudgetDocument<T> budgetDocument = budget.getBudgetDocument(); if (budgetDocument == null) { budget.refreshReferenceObject("budgetDocument"); budgetDocument = budget.getBudgetDocument(); } // ProposalDevelopmentDocument proposal = (ProposalDevelopmentDocument)budgetDocument.getParentDocument(); return budgetDocument.getParentDocument(); } protected Map<String, String> getRateFilterMap(BudgetDocument<T> budgetDocument) { BudgetParent budgetParent = budgetDocument.getParentDocument().getBudgetParent(); Map<String, String> rateFilterMap = new HashMap<String, String>(); rateFilterMap.put(UNIT_NUMBER_KEY, budgetParent.getUnitNumber()); return rateFilterMap; } @SuppressWarnings("unchecked") protected Collection getFilteredInstituteLaRates(Class rateType, String unitNumber, Unit currentUnit, Map<String, String> rateFilterMap) { Collection abstractInstituteRates; abstractInstituteRates = filterForActiveRatesOnly( getBusinessObjectService().findMatching(rateType, rateFilterMap)); return abstractInstituteRates; } @SuppressWarnings("unchecked") protected Collection getFilteredInstituteRates(Class rateType, String unitNumber, Unit currentUnit, Map<String, String> rateFilterMap) { Collection abstractInstituteRates; do { abstractInstituteRates = filterForActiveRatesOnly( getBusinessObjectService().findMatching(rateType, rateFilterMap)); currentUnit = makeParentUnitAsCurrentUnit(currentUnit, rateFilterMap); } while (abstractInstituteRates.size() == 0 && currentUnit != null); return abstractInstituteRates; } @SuppressWarnings("unchecked") protected Collection filterForActiveRatesOnly(Collection abstractInstituteRates) { List filteredList = new ArrayList(); for (AbstractInstituteRate rate : (Collection<AbstractInstituteRate>) abstractInstituteRates) { if (rate.getActive()) { filteredList.add(rate); } else { if (LOG.isDebugEnabled()) { LOG.debug("Filtering inactive rate: " + rate.getObjectId()); } } } return filteredList; } protected Unit makeParentUnitAsCurrentUnit(Unit currentUnit, Map<String, String> rateFilterMap) { Unit parentUnit = currentUnit == null ? null : currentUnit.getParentUnit(); if (parentUnit != null) { rateFilterMap.put(UNIT_NUMBER_KEY, parentUnit.getUnitNumber()); } return parentUnit; } /* Rate effective date is between project start and end dates. * But if budget persons are defined and the earliest salary effective * date is prior to project start date, Inflation rates are retrieved from * that date on (salary effective date). * This date is used to fetch inflation rates * * */ protected Date getRateEffectiveStartDate(Budget budget, AbstractInstituteRate rate, Date personEffectiveDate) { Date effectiveDate = budget.getStartDate(); if (rate.getRateClass().getRateClassType().equalsIgnoreCase(Constants.RATE_CLASS_TYPE_FOR_INFLATION) && personEffectiveDate != null && personEffectiveDate.compareTo(effectiveDate) < 0) { effectiveDate = personEffectiveDate; } return effectiveDate; } /* Look for budget persons salary effective date and return the * earliest effective date * This date is used to fetch/calculate inflation rates * * */ @SuppressWarnings("unchecked") protected Date getBudgetPersonSalaryEffectiveDate(Budget budget) { Map queryMap = new HashMap(); queryMap.put("budgetId", budget.getBudgetId()); Collection<BudgetPerson> budgetPersons = getBusinessObjectService().findMatching(BudgetPerson.class, queryMap); Date effectiveDate = null; for (BudgetPerson budgetPerson : budgetPersons) { if (effectiveDate == null || budgetPerson.getEffectiveDate().compareTo(effectiveDate) < 0) { effectiveDate = budgetPerson.getEffectiveDate(); } } return effectiveDate; } /* get all rates within project start and end date range * * */ @SuppressWarnings("unchecked") protected void getRatesForProjectDates(Budget budget, Collection allRates, Collection filteredRates, Date personSalaryEffectiveDate) { List<AbstractInstituteRate> dateFilteredRates = (List<AbstractInstituteRate>) filteredRates; List<AbstractInstituteRate> allAbstractInstituteRates = (List<AbstractInstituteRate>) allRates; for (AbstractInstituteRate rate : allAbstractInstituteRates) { Date rateStartDate = rate.getStartDate(); Date rateEffectiveDate = getRateEffectiveStartDate(budget, rate, personSalaryEffectiveDate); if (rateStartDate.compareTo(rateEffectiveDate) >= 0 && rateStartDate.compareTo(budget.getEndDate()) <= 0) { dateFilteredRates.add(rate); } } } /* get applicable rates before project start date * get the latest * */ @SuppressWarnings("unchecked") protected void getApplicableRates(Budget budget, Collection allRates, Collection filteredRates, Date personSalaryEffectiveDate) { List<AbstractInstituteRate> allAbstractInstituteRates = (List<AbstractInstituteRate>) allRates; Map<String, AbstractInstituteRate> instRates = new HashMap<String, AbstractInstituteRate>(); for (AbstractInstituteRate instituteRate : allAbstractInstituteRates) { Date rateStartDate = instituteRate.getStartDate(); Date rateEffectiveDate = getRateEffectiveStartDate(budget, instituteRate, personSalaryEffectiveDate); if (rateStartDate.before(rateEffectiveDate)) { String hKey = generateThreePartKey(instituteRate); AbstractInstituteRate instRate = instRates.get(hKey); if ((instRate != null) && (instRate.getStartDate().compareTo(rateStartDate) <= 0)) { Date currentStartDate = instRate.getStartDate(); if (currentStartDate.compareTo(rateStartDate) <= 0) { instRates.remove(hKey); } } if (!instRates.keySet().contains(hKey)) { instRates.put(hKey, instituteRate); } } } filteredRates.addAll(instRates.values()); } protected String generateThreePartKey(AbstractInstituteRate instituteRate) { return new StringBuilder(instituteRate.getRateClassCode()).append(instituteRate.getRateTypeCode()) .append(getLocationFlagAsString(instituteRate.getOnOffCampusFlag())).toString(); } /* filter institute rates - get rates applicable for * the project * */ @SuppressWarnings("unchecked") protected void filterRates(Budget budget, Collection allAbstractInstituteRates, Collection filteredAbstractInstituteRates) { filteredAbstractInstituteRates.clear(); Date personSalaryEffectiveDate = getBudgetPersonSalaryEffectiveDate(budget); getRatesForProjectDates(budget, allAbstractInstituteRates, filteredAbstractInstituteRates, personSalaryEffectiveDate); getApplicableRates(budget, allAbstractInstituteRates, filteredAbstractInstituteRates, personSalaryEffectiveDate); } protected boolean isOutOfSync(Budget budget) { return isOutOfSync(budget.getInstituteRates(), budget.getBudgetRates()) || isOutOfSync(budget.getInstituteLaRates(), budget.getBudgetLaRates()); } @SuppressWarnings("unchecked") protected boolean isOutOfSync(List instituteRates, List budgetRates) { boolean outOfSync = areNumbersOfBudgetRatesOutOfSyncWithInstituteRates(instituteRates, budgetRates); if (!outOfSync) { outOfSync = areBudgetRatesOutOfSyncWithInsttituteRates(instituteRates, budgetRates); } return outOfSync; } @SuppressWarnings("unchecked") protected boolean areNumbersOfBudgetRatesOutOfSyncWithInstituteRates(List instituteRates, List budgetRates) { return instituteRates.size() != budgetRates.size(); } @SuppressWarnings("unchecked") protected boolean areBudgetRatesOutOfSyncWithInsttituteRates(List instituteRates, List budgetRates) { Set<String> instituteRateKeys = storeAllKeys((List<AbstractInstituteRate>) instituteRates); Set<String> budgetRateKeys = storeAllKeys((List<AbstractInstituteRate>) budgetRates); return !instituteRateKeys.containsAll(budgetRateKeys); } protected Set<String> storeAllKeys(List<AbstractInstituteRate> rates) { Set<String> keys = new HashSet<String>(rates.size(), 1.0f); for (AbstractInstituteRate rate : rates) { keys.add(rate.getRateKeyAsString()); } return keys; } @SuppressWarnings("unchecked") protected void resetAbstractBudgetApplicableRatesToInstituteRates(List budgetRates) { List<AbstractBudgetRate> abstractBudgetRates = (List<AbstractBudgetRate>) budgetRates; for (AbstractBudgetRate abstractBudgetRate : abstractBudgetRates) { abstractBudgetRate.setApplicableRate(abstractBudgetRate.getInstituteRate()); } } @SuppressWarnings("unchecked") protected void resetBudgetRatesForRateClassType(List<RateClass> rateClasses, String rateClassType, List budgetRates) { List<AbstractBudgetRate> abstractBudgetRates = (List<AbstractBudgetRate>) budgetRates; for (RateClass rateClass : rateClasses) { if (rateClass.getRateClassType().equalsIgnoreCase(rateClassType)) { for (AbstractBudgetRate abstractBudgetRate : abstractBudgetRates) { if (abstractBudgetRate.getRateClassCode().equalsIgnoreCase(rateClass.getRateClassCode())) { abstractBudgetRate.setApplicableRate(abstractBudgetRate.getInstituteRate()); } } } } } @SuppressWarnings("unchecked") protected void syncBudgetRates(List budgetRates, Collection abstractIntituteRates) { List<AbstractBudgetRate> abstractBudgetRates = (List<AbstractBudgetRate>) budgetRates; Map<String, AbstractInstituteRate> instRateMap = mapRatesToKeys(abstractIntituteRates); for (AbstractBudgetRate abstractBudgetRate : abstractBudgetRates) { String hKey = abstractBudgetRate.getRateKeyAsString(); AbstractInstituteRate abstractInstituteRate = instRateMap.get(hKey); abstractBudgetRate.setInstituteRate(abstractInstituteRate.getInstituteRate()); abstractBudgetRate.setApplicableRate(abstractInstituteRate.getInstituteRate()); } } protected String getFormattedAffectedBudgetPeriod(String periodAffected) { String budgetPeriodAffected = periodAffected; if (budgetPeriodAffected != null) { budgetPeriodAffected = budgetPeriodAffected.trim(); budgetPeriodAffected = budgetPeriodAffected.replace(PERIOD_SEARCH_SEPARATOR, PERIOD_DISPLAY_SEPARATOR); budgetPeriodAffected = budgetPeriodAffected.substring(1, budgetPeriodAffected.length() - 1); } return budgetPeriodAffected; } @SuppressWarnings("unchecked") protected void viewLocation(String viewLocation, Integer budgetPeriod, List rates) { List<AbstractBudgetRate> budgetRates = (List<AbstractBudgetRate>) rates; for (AbstractBudgetRate budgetRate : budgetRates) { String onOffCampusFlag = getLocationFlagAsString(budgetRate.getOnOffCampusFlag()); boolean displayRate = (viewLocation == null || (viewLocation.equalsIgnoreCase(onOffCampusFlag))); /* check budget Period */ if (displayRate && budgetPeriod != null) { String trackAffectedPeriod = budgetRate.getTrackAffectedPeriod(); String formattedBudgetPeriod = getSeparatedBudgetPeriod(budgetPeriod); if (trackAffectedPeriod == null || (trackAffectedPeriod.indexOf(formattedBudgetPeriod) < 0)) { displayRate = false; } } budgetRate.setDisplayLocation(displayRate); } } protected String getLocationFlagAsString(boolean onOffCampusFlag) { return onOffCampusFlag ? Constants.ON_CAMUS_FLAG : Constants.OFF_CAMUS_FLAG; } protected String getSeparatedBudgetPeriod(Integer budgetPeriod) { return new StringBuilder(PERIOD_SEARCH_SEPARATOR).append(budgetPeriod).append(PERIOD_SEARCH_SEPARATOR) .toString(); } @SuppressWarnings("unchecked") protected void syncBudgetRatesForRateClassType(List<RateClass> rateClasses, String rateClassType, Collection abstractInstituteRates, List budgetRates) { List<AbstractBudgetRate> abstractBudgetRates = (List<AbstractBudgetRate>) budgetRates; Map<String, AbstractInstituteRate> instRateMap = mapRatesToKeys(abstractInstituteRates); for (RateClass rateClass : rateClasses) { if (rateClass.getRateClassType().equalsIgnoreCase(rateClassType)) { for (AbstractBudgetRate budgetRate : abstractBudgetRates) { if (budgetRate.getRateClassCode().equalsIgnoreCase(rateClass.getRateClassCode())) { String hKey = budgetRate.getRateKeyAsString(); InstituteRate instituteRate = (InstituteRate) instRateMap.get(hKey); budgetRate.setInstituteRate(instituteRate.getInstituteRate()); budgetRate.setApplicableRate(instituteRate.getInstituteRate()); } } } } } protected Map<String, RateClassType> populateExistingRateClassTypeMap(List<RateClassType> rateClassTypes) { Map<String, RateClassType> existingRateClassTypeMap = new HashMap<String, RateClassType>(); for (RateClassType rateClassType : rateClassTypes) { existingRateClassTypeMap.put(rateClassType.getRateClassType(), rateClassType); } return existingRateClassTypeMap; } protected void getBudgetRates(BudgetDocument<T> budgetDocument, Collection<InstituteRate> allInstituteRates) { Budget budget = budgetDocument.getBudget(); getBudgetRates(budget.getRateClassTypes(), budgetDocument, allInstituteRates); } /* get budget rates applicable for the proposal - based on activity type * and unit number * */ protected void getBudgetRates(List<RateClassType> rateClassTypes, BudgetDocument<T> budgetDocument, Collection<InstituteRate> allInstituteRates) { Budget budget = budgetDocument.getBudget(); List<InstituteRate> instituteRates = budget.getInstituteRates(); filterRates(budget, allInstituteRates, instituteRates); List<BudgetRate> budgetRates = budget.getBudgetRates(); syncBudgetRateCollections(rateClassTypes, budgetDocument, instituteRates, budgetRates); getBudgetLaRates(rateClassTypes, budgetDocument); checkActivityPrefixForRateClassTypes(rateClassTypes, budgetDocument); } protected void getBudgetLaRates(BudgetDocument<T> budgetDocument, List<InstituteLaRate> allInstituteLaRates) { Budget budget = budgetDocument.getBudget(); getBudgetLaRates(budget.getRateClassTypes(), budgetDocument, allInstituteLaRates); } protected void getBudgetLaRates(List<RateClassType> rateClassTypes, BudgetDocument<T> budgetDocument) { getBudgetLaRates(rateClassTypes, budgetDocument, new ArrayList<InstituteLaRate>(getInstituteLaRates(budgetDocument))); } /** * Get budget LA rates applicable for the proposal - based on unit number * @param rateClassTypes * @param budget * @param allInstituteLaRates */ protected void getBudgetLaRates(List<RateClassType> rateClassTypes, BudgetDocument<T> budgetDocument, List<InstituteLaRate> allInstituteLaRates) { Budget budget = budgetDocument.getBudget(); List<InstituteLaRate> instituteLaRates = budget.getInstituteLaRates(); filterRates(budget, allInstituteLaRates, instituteLaRates); List<BudgetLaRate> budgetRates = budget.getBudgetLaRates(); syncBudgetRateCollections(rateClassTypes, budgetDocument, instituteLaRates, budgetRates); } public BusinessObjectService getBusinessObjectService() { return _businessObjectService; } @SuppressWarnings("unchecked") protected void syncBudgetRateCollections(List<RateClassType> rateClassTypes, BudgetDocument<T> budgetDocument, List abstractInstituteRates, List budgetRates) { Budget budget = budgetDocument.getBudget(); List<AbstractBudgetRate> abstractBudgetRates = (List<AbstractBudgetRate>) budgetRates; List<AbstractInstituteRate> instituteRates = (List<AbstractInstituteRate>) abstractInstituteRates; syncAllRateClasses(budget, instituteRates); syncAllRateClassTypes(budget, rateClassTypes, instituteRates); if (budgetRates.size() == 0) { syncAllBudgetRatesForInstituteRateType(budgetDocument, abstractBudgetRates, instituteRates); } } @SuppressWarnings("unchecked") public void syncBudgetRateCollectionsToExistingRates(List<RateClassType> rateClassTypes, BudgetDocument<T> budgetDocument) { Budget budget = budgetDocument.getBudget(); syncAllRateClasses(budget, (List) budget.getBudgetRates()); syncAllRateClassTypes(budget, rateClassTypes, (List) budget.getBudgetRates()); syncAllRateClasses(budget, (List) budget.getBudgetLaRates()); syncAllRateClassTypes(budget, rateClassTypes, (List) budget.getBudgetLaRates()); checkActivityPrefixForRateClassTypes(rateClassTypes, budgetDocument); } protected void syncAllBudgetRatesForInstituteRateType(BudgetDocument<T> budgetDocument, List<AbstractBudgetRate> budgetRates, List<AbstractInstituteRate> instituteRates) { for (AbstractInstituteRate abstractInstituteRate : instituteRates) { if (abstractInstituteRate.getRateClass() != null) { budgetRates.add(generateBudgetRate(budgetDocument, abstractInstituteRate)); } } updateRatesForEachPeriod(budgetDocument.getBudget()); Collections.sort(budgetRates); } @SuppressWarnings("unchecked") protected void replaceRateClassesForRateClassType(String rateClassType, Budget budget, List rates) { List<AbstractInstituteRate> instituteRates = (List<AbstractInstituteRate>) rates; List<RateClass> budgetRateClasses = budget.getRateClasses(); removeAllPreviouslyRegisteredRateClassesForRateClassType(rateClassType, budgetRateClasses); addRateClassesForRateClassType(rateClassType, instituteRates); } protected void removeAllPreviouslyRegisteredRateClassesForRateClassType(String rateClassType, List<RateClass> budgetRateClasses) { Iterator<RateClass> iter = budgetRateClasses.iterator(); while (iter.hasNext()) { RateClass rateClass = iter.next(); if (rateClassType.equals(rateClass.getRateClassType())) { iter.remove(); } } } protected void addRateClassesForRateClassType(String rateClassType, List<AbstractInstituteRate> instituteRates) { Map<String, RateClass> mapOfMatchingRateClasses = new HashMap<String, RateClass>(); for (AbstractInstituteRate abstractInstituteRate : instituteRates) { if (abstractInstituteRate.getRateType() != null) { RateClass rateClass = abstractInstituteRate.getRateType().getRateClass(); if (rateClass == null) abstractInstituteRate.getRateType().refreshNonUpdateableReferences(); rateClass = abstractInstituteRate.getRateType().getRateClass(); if (rateClass.getRateClassType().equals(rateClassType) && mapOfMatchingRateClasses.get(rateClass.getRateClassCode()) == null) { mapOfMatchingRateClasses.put(rateClass.getRateClassCode(), rateClass); } } } } @SuppressWarnings("unchecked") protected void replaceBudgetRatesForRateClassType(String rateClassType, BudgetDocument<T> budgetDocument, List existingBudgetRates, List rates) { List<AbstractInstituteRate> instituteRates = (List<AbstractInstituteRate>) rates; List<AbstractBudgetRate> abstractBudgetRates = (List<AbstractBudgetRate>) existingBudgetRates; Map<String, AbstractBudgetRate> existingBudgetRateMap = preservePersistedBudgetRatesForRateClassType( rateClassType, abstractBudgetRates); removeRegisteredBudgetRatesForRateClassType(rateClassType, abstractBudgetRates); Map<String, AbstractBudgetRate> newBudgetRateMap = generateNewAndUpdatedBudgetRates(rateClassType, budgetDocument, instituteRates, existingBudgetRateMap); registerNewAndUpdatedBudgetRates(abstractBudgetRates, newBudgetRateMap); updateRatesForEachPeriod(budgetDocument.getBudget()); Collections.sort(abstractBudgetRates); } protected void registerNewAndUpdatedBudgetRates(List<AbstractBudgetRate> abstractBudgetRates, Map<String, AbstractBudgetRate> newBudgetRateMap) { abstractBudgetRates.addAll(newBudgetRateMap.values()); } protected Map<String, AbstractBudgetRate> generateNewAndUpdatedBudgetRates(String rateClassType, BudgetDocument<T> budgetDocument, List<AbstractInstituteRate> instituteRates, Map<String, AbstractBudgetRate> existingBudgetRateMap) { Map<String, AbstractBudgetRate> newBudgetRateMap = new HashMap<String, AbstractBudgetRate>(); for (AbstractInstituteRate abstractInstituteRate : instituteRates) { if (abstractInstituteRate.getRateType() != null) { RateClass rateClass = abstractInstituteRate.getRateType().getRateClass(); if (rateClassType.equals(rateClass.getRateClassType())) { AbstractBudgetRate newBudgetRate = generateBudgetRate(budgetDocument, abstractInstituteRate); String hKey = abstractInstituteRate.getRateKeyAsString(); AbstractBudgetRate existingBudgetRate = existingBudgetRateMap.get(hKey); if (existingBudgetRate != null) { newBudgetRate.setVersionNumber(existingBudgetRate.getVersionNumber()); } newBudgetRateMap.put(hKey, newBudgetRate); } } } return newBudgetRateMap; } protected void removeRegisteredBudgetRatesForRateClassType(String rateClassType, List<AbstractBudgetRate> abstractBudgetRates) { Iterator<AbstractBudgetRate> iter = abstractBudgetRates.iterator(); while (iter.hasNext()) { AbstractBudgetRate budgetRate = iter.next(); if (rateClassType.equals(budgetRate.getRateClass().getRateClassType())) { iter.remove(); } } } protected Map<String, AbstractBudgetRate> preservePersistedBudgetRatesForRateClassType(String rateClassType, List<AbstractBudgetRate> abstractBudgetRates) { Map<String, AbstractBudgetRate> existingBudgetRateMap = new HashMap<String, AbstractBudgetRate>(); for (AbstractBudgetRate abstractBudgetRate : abstractBudgetRates) { if (rateClassType.equals(abstractBudgetRate.getRateClass().getRateClassType())) { existingBudgetRateMap.put(abstractBudgetRate.getRateKeyAsString(), abstractBudgetRate); } } return existingBudgetRateMap; } protected void syncAllRateClasses(Budget budget, List<AbstractInstituteRate> instituteRates) { Map<String, RateClass> rateClassMap = new HashMap<String, RateClass>(); for (AbstractInstituteRate abstractInstituteRate : instituteRates) { if (abstractInstituteRate.getRateClass() != null) { String rateClassCode = abstractInstituteRate.getRateClassCode(); if (rateClassMap.get(rateClassCode) == null) { rateClassMap.put(rateClassCode, abstractInstituteRate.getRateClass()); } } } budget.getRateClasses().addAll(rateClassMap.values()); } protected void syncAllRateClassTypes(Budget budget, List<RateClassType> rateClassTypes, List<AbstractInstituteRate> instituteRates) { Map<String, RateClassType> existingRateClassTypeMap = populateExistingRateClassTypeMap(rateClassTypes); Map<String, RateClassType> rateClassTypeMap = new HashMap<String, RateClassType>(); for (AbstractInstituteRate abstractInstituteRate : instituteRates) { if (abstractInstituteRate.getRateClass() != null) { String rateClassType = abstractInstituteRate.getRateClass().getRateClassType(); if (existingRateClassTypeMap.get(rateClassType) == null) { rateClassTypeMap.put(rateClassType, abstractInstituteRate.getRateClass().getRateClassTypeT()); } } } rateClassTypes.addAll(rateClassTypeMap.values()); } protected AbstractBudgetRate generateBudgetProposalRate(BudgetDocument<T> budgetDocument, InstituteRate instituteRate) { BudgetParent budgetParent = budgetDocument.getParentDocument().getBudgetParent(); return new BudgetRate(budgetParent.getUnitNumber(), instituteRate); } protected AbstractBudgetRate generateBudgetProposalLaRate(BudgetDocument<T> budgetDocument, InstituteLaRate instituteLaRate) { BudgetParent budgetParent = budgetDocument.getParentDocument().getBudgetParent(); return new BudgetLaRate(budgetParent.getUnitNumber(), instituteLaRate); } protected AbstractBudgetRate generateBudgetRate(BudgetDocument<T> budgetDocument, AbstractInstituteRate abstractInstituteRate) { Budget budget = budgetDocument.getBudget(); AbstractBudgetRate abstractBudgetRate = (abstractInstituteRate instanceof InstituteRate) ? generateBudgetProposalRate(budgetDocument, (InstituteRate) abstractInstituteRate) : generateBudgetProposalLaRate(budgetDocument, (InstituteLaRate) abstractInstituteRate); abstractBudgetRate.setBudgetId(budget.getBudgetId()); abstractBudgetRate.setBudget(budget); return abstractBudgetRate; } /** * Searches for persisted {@link RateClass} instances based on the given <code>rateClassType</code>. Uses the {@link BusinessObjectService} * to grab appropriate {@link RateClass} instances since {@link RateClass} is a {@link BusinessObject} * * @param rateClassType to use for retrieving {@link RateClass} instances * @returns a List of {@link RateClass} instances */ @SuppressWarnings("unchecked") public Collection<RateClass> getBudgetRateClasses(String rateClassType) { Map<String, String> queryMap = new HashMap<String, String>(); queryMap.put("rateClassType", rateClassType); return getBusinessObjectService().findMatching(RateClass.class, queryMap); } /** * Retrieves {@link RateClass} instances as a {@link Map} keyed from the <code>rateTypeCode</code>. This makes it easy for * classes (particularly in the UI) to grab {@link RateClass} information via rateTypeCode * * @param rateClassType to use for {@link RateClass} instances to be retrieved * @return a {@link Map} keyed on rateTypeCode containing {@link RateClass} instances */ public Map<String, RateClass> getBudgetRateClassMap(String rateClassType) { Map<String, RateClass> retval = new HashMap<String, RateClass>(); for (RateClass rateClass : getBudgetRateClasses(rateClassType)) { retval.put(rateClass.getRateClassCode(), rateClass); } return retval; } @SuppressWarnings("unchecked") protected void populateInstituteRates(BudgetDocument<T> budgetDocument) { Budget budget = budgetDocument.getBudget(); List instituteRates = (List) getInstituteRates(budgetDocument); filterRates(budget, instituteRates, budget.getInstituteRates()); List instituteLaRates = (List) getInstituteLaRates(budgetDocument); filterRates(budget, instituteLaRates, budget.getInstituteLaRates()); } public boolean isOutOfSyncForRateAudit(BudgetDocument<T> budgetDocument) { populateInstituteRates(budgetDocument); Budget budget = budgetDocument.getBudget(); return isOutOfSyncForRateAudit(budget.getInstituteRates(), budget.getBudgetRates()) || isOutOfSyncForRateAudit(budget.getInstituteLaRates(), budget.getBudgetLaRates()); } /** * * This method is to check to the class type level * @param instituteRates * @param budgetRates * @return */ @SuppressWarnings("unchecked") protected boolean isOutOfSyncForRateAudit(List instituteRates, List budgetRates) { boolean outOfSync = false; outOfSync = !isRatesMatched(instituteRates, budgetRates) || outOfSync; outOfSync = !isRatesMatched(budgetRates, instituteRates) || outOfSync; return outOfSync; } protected boolean isRatesMatched(List<AbstractInstituteRate> fromRates, List<AbstractInstituteRate> toRates) { boolean matched = true; for (Object rate : fromRates) { AbstractInstituteRate budgetRate = (AbstractInstituteRate) rate; boolean isRateMatched = false; for (Object rate1 : toRates) { AbstractInstituteRate instituteRate = (AbstractInstituteRate) rate1; if ((instituteRate.getRateKeyAsString() + instituteRate.getInstituteRate()) .equals(budgetRate.getRateKeyAsString() + budgetRate.getInstituteRate())) { if (instituteRate instanceof InstituteRate) { if (((InstituteRate) instituteRate).getActivityTypeCode() .equals(((BudgetRate) budgetRate).getActivityTypeCode())) { isRateMatched = true; break; } } else { isRateMatched = true; break; } } } if (!isRateMatched) { matched = false; String rateClassType = budgetRate.getRateClass().getRateClassTypeT().getDescription(); String errorPath = "document.budgetProposalRate[" + rateClassType + "]"; boolean isNewError = true; for (AuditError auditError : getAuditErrors()) { if (auditError.getErrorKey().equals(errorPath) && auditError.getMessageKey().equals(KeyConstants.AUDIT_WARNING_RATE_OUT_OF_SYNC) && auditError.getLink().equals(Constants.BUDGET_RATE_PAGE + "." + rateClassType)) { isNewError = false; break; } } if (isNewError) { getAuditErrors().add(new AuditError(errorPath, KeyConstants.AUDIT_WARNING_RATE_OUT_OF_SYNC, Constants.BUDGET_RATE_PAGE + "." + rateClassType)); } } } return matched; } @SuppressWarnings("unchecked") protected List<AuditError> getAuditErrors() { List<AuditError> auditErrors = new ArrayList<AuditError>(); if (!GlobalVariables.getAuditErrorMap().containsKey(BUDGET_RATE_AUDIT_WARNING_KEY)) { GlobalVariables.getAuditErrorMap().put(BUDGET_RATE_AUDIT_WARNING_KEY, new AuditCluster(Constants.BUDGET_RATE_PANEL_NAME, auditErrors, Constants.AUDIT_WARNINGS)); } else { auditErrors = ((AuditCluster) GlobalVariables.getAuditErrorMap().get(BUDGET_RATE_AUDIT_WARNING_KEY)) .getAuditErrorList(); } return auditErrors; } @SuppressWarnings("unchecked") protected boolean isOutOfSyncForRateAudit_org(List instituteRates, List budgetRates) { boolean outOfSync = areNumbersOfBudgetRatesOutOfSyncWithInstituteRates(instituteRates, budgetRates); if (!outOfSync) { outOfSync = areBudgetRatesOutOfSyncWithInsttituteRatesForRateAudit(instituteRates, budgetRates); } return outOfSync; } @SuppressWarnings("unchecked") protected boolean areBudgetRatesOutOfSyncWithInsttituteRatesForRateAudit(List instituteRates, List budgetRates) { Set<String> instituteRateKeys = storeAllKeysWithRate((List<AbstractInstituteRate>) instituteRates); Set<String> budgetRateKeys = storeAllKeysWithRate((List<AbstractInstituteRate>) budgetRates); return !instituteRateKeys.containsAll(budgetRateKeys); } protected Set<String> storeAllKeysWithRate(List<AbstractInstituteRate> rates) { Set<String> keys = new HashSet<String>(rates.size(), 1.0f); for (AbstractInstituteRate rate : rates) { keys.add(rate.getRateKeyAsString() + rate.getInstituteRate()); } return keys; } public void populateBudgetRatesForNewVersion(BudgetDocument<T> budgetDocument) { getBudgetRates(new ArrayList<RateClassType>(), budgetDocument); } /** * By default it does not have to perform sync * @see org.kuali.kra.budget.rates.BudgetRatesService#performSyncFlag() */ public boolean performSyncFlag(BudgetDocument<T> budgetDocument) { return false; } }