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.document; 017 018 import java.util.ArrayList; 019 import java.util.Collection; 020 import java.util.Collections; 021 import java.util.Comparator; 022 import java.util.List; 023 import java.util.Map; 024 025 import org.kuali.kfs.coa.businessobject.OrganizationReversion; 026 import org.kuali.kfs.coa.businessobject.OrganizationReversionCategory; 027 import org.kuali.kfs.coa.businessobject.OrganizationReversionDetail; 028 import org.kuali.kfs.coa.service.OrganizationReversionDetailTrickleDownInactivationService; 029 import org.kuali.kfs.coa.service.OrganizationReversionService; 030 import org.kuali.kfs.sys.context.SpringContext; 031 import org.kuali.kfs.sys.document.FinancialSystemMaintainable; 032 import org.kuali.rice.kns.bo.PersistableBusinessObject; 033 import org.kuali.rice.kns.document.MaintenanceDocument; 034 import org.kuali.rice.kns.maintenance.Maintainable; 035 import org.kuali.rice.kns.util.KNSConstants; 036 import org.kuali.rice.kns.util.ObjectUtils; 037 import org.kuali.rice.kns.util.TypedArrayList; 038 import org.kuali.rice.kns.web.ui.Field; 039 import org.kuali.rice.kns.web.ui.Row; 040 import org.kuali.rice.kns.web.ui.Section; 041 042 /** 043 * This class provides some specific functionality for the {@link OrganizationReversion} maintenance document inner class for doing 044 * comparisons on {@link OrganizationReversionCategory} populateBusinessObject setBusinessObject - pre-populate the static list of 045 * details with each category isRelationshipRefreshable - makes sure that {@code organizationReversionGlobalDetails} isn't wiped out 046 * accidentally 047 */ 048 public class OrganizationReversionMaintainableImpl extends FinancialSystemMaintainable { 049 private transient OrganizationReversionService organizationReversionService; 050 051 /** 052 * This comparator is used internally for sorting the list of categories 053 */ 054 private class categoryComparator implements Comparator<OrganizationReversionDetail> { 055 056 public int compare(OrganizationReversionDetail detail0, OrganizationReversionDetail detail1) { 057 058 OrganizationReversionCategory category0 = detail0.getOrganizationReversionCategory(); 059 OrganizationReversionCategory category1 = detail1.getOrganizationReversionCategory(); 060 061 String code0 = category0.getOrganizationReversionCategoryCode(); 062 String code1 = category1.getOrganizationReversionCategoryCode(); 063 064 return code0.compareTo(code1); 065 } 066 067 } 068 069 /** 070 * pre-populate the static list of details with each category 071 * 072 * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#setBusinessObject(org.kuali.rice.kns.bo.BusinessObject) 073 */ 074 public void setBusinessObject(PersistableBusinessObject businessObject) { 075 076 OrganizationReversionService organizationReversionService = SpringContext.getBean(OrganizationReversionService.class); 077 OrganizationReversion organizationReversion = (OrganizationReversion) businessObject; 078 List<OrganizationReversionDetail> details = organizationReversion.getOrganizationReversionDetail(); 079 080 if (details == null) { 081 details = new TypedArrayList(OrganizationReversionDetail.class); 082 organizationReversion.setOrganizationReversionDetail(details); 083 } 084 085 if (details.size() == 0) { 086 087 Collection<OrganizationReversionCategory> categories = organizationReversionService.getCategoryList(); 088 089 for (OrganizationReversionCategory category : categories) { 090 if (category.isActive()) { 091 OrganizationReversionDetail detail = new OrganizationReversionDetail(); 092 detail.setOrganizationReversionCategoryCode(category.getOrganizationReversionCategoryCode()); 093 detail.setOrganizationReversionCategory(category); 094 details.add(detail); 095 } 096 } 097 098 Collections.sort(details, new categoryComparator()); 099 100 } 101 102 super.setBusinessObject(businessObject); 103 } 104 105 /** 106 * A method that prevents lookups from refreshing the Organization Reversion Detail list (because, if it is refreshed before a 107 * save...it ends up destroying the list). 108 * 109 * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#isRelationshipRefreshable(java.lang.Class, java.lang.String) 110 */ 111 @Override 112 protected boolean isRelationshipRefreshable(Class boClass, String relationshipName) { 113 if (relationshipName.equals("organizationReversionDetail")) { 114 return false; 115 } 116 else { 117 return super.isRelationshipRefreshable(boClass, relationshipName); 118 } 119 } 120 121 /** 122 * Determines if this maint doc is inactivating an organization reversion 123 * @return true if the document is inactivating an active organization reversion, false otherwise 124 */ 125 protected boolean isInactivatingOrganizationReversion() { 126 // the account has to be closed on the new side when editing in order for it to be possible that we are closing the account 127 if (KNSConstants.MAINTENANCE_EDIT_ACTION.equals(getMaintenanceAction()) && !((OrganizationReversion) getBusinessObject()).isActive()) { 128 OrganizationReversion existingOrganizationReversionFromDB = retrieveExistingOrganizationReversion(); 129 if (ObjectUtils.isNotNull(existingOrganizationReversionFromDB)) { 130 // now see if the original account was not closed, in which case, we are closing the account 131 if (existingOrganizationReversionFromDB.isActive()) { 132 return true; 133 } 134 } 135 } 136 return false; 137 } 138 139 /** 140 * Determines if this maint doc is activating an organization reversion 141 * @return true if the document is activating an inactive organization reversion, false otherwise 142 */ 143 protected boolean isActivatingOrganizationReversion() { 144 // the account has to be closed on the new side when editing in order for it to be possible that we are closing the account 145 if (KNSConstants.MAINTENANCE_EDIT_ACTION.equals(getMaintenanceAction()) && ((OrganizationReversion) getBusinessObject()).isActive()) { 146 OrganizationReversion existingOrganizationReversionFromDB = retrieveExistingOrganizationReversion(); 147 if (ObjectUtils.isNotNull(existingOrganizationReversionFromDB)) { 148 // now see if the original account was not closed, in which case, we are closing the account 149 if (!existingOrganizationReversionFromDB.isActive()) { 150 return true; 151 } 152 } 153 } 154 return false; 155 } 156 157 /** 158 * Grabs the old version of this org reversion from the database 159 * @return the old version of this organization reversion 160 */ 161 protected OrganizationReversion retrieveExistingOrganizationReversion() { 162 final OrganizationReversion orgRev = (OrganizationReversion)getBusinessObject(); 163 final OrganizationReversion oldOrgRev = SpringContext.getBean(OrganizationReversionService.class).getByPrimaryId(orgRev.getUniversityFiscalYear(), orgRev.getChartOfAccountsCode(), orgRev.getOrganizationCode()); 164 return oldOrgRev; 165 } 166 167 /** 168 * Overridden to trickle down inactivation or activation to details 169 * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#saveBusinessObject() 170 */ 171 @Override 172 public void saveBusinessObject() { 173 final boolean isActivatingOrgReversion = isActivatingOrganizationReversion(); 174 final boolean isInactivatingOrgReversion = isInactivatingOrganizationReversion(); 175 176 super.saveBusinessObject(); 177 178 if (isActivatingOrgReversion) { 179 SpringContext.getBean(OrganizationReversionDetailTrickleDownInactivationService.class).trickleDownActiveOrganizationReversionDetails((OrganizationReversion)getBusinessObject(), documentNumber); 180 } else if (isInactivatingOrgReversion) { 181 SpringContext.getBean(OrganizationReversionDetailTrickleDownInactivationService.class).trickleDownInactiveOrganizationReversionDetails((OrganizationReversion)getBusinessObject(), documentNumber); 182 } 183 } 184 185 /** 186 * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#getSections(org.kuali.rice.kns.document.MaintenanceDocument, org.kuali.rice.kns.maintenance.Maintainable) 187 */ 188 @Override 189 public List getSections(MaintenanceDocument document, Maintainable oldMaintainable) { 190 List<Section> sections = super.getSections(document, oldMaintainable); 191 if (organizationReversionService == null) { 192 organizationReversionService = SpringContext.getBean(OrganizationReversionService.class); 193 } 194 for (Section section : sections) { 195 for (Row row : section.getRows()) { 196 List<Field> updatedFields = new ArrayList<Field>(); 197 for (Field field : row.getFields()) { 198 if (shouldIncludeField(field)) { 199 updatedFields.add(field); 200 } 201 } 202 row.setFields(updatedFields); 203 } 204 } 205 return sections; 206 } 207 208 /** 209 * Determines if the given field should be included in the updated row, once we take out inactive categories 210 * @param field the field to check 211 * @return true if the field should be included (ie, it doesn't describe an organization reversion with an inactive category); false otherwise 212 */ 213 protected boolean shouldIncludeField(Field field) { 214 boolean includeField = true; 215 if (field.getContainerRows() != null) { 216 for (Row containerRow : field.getContainerRows()) { 217 for (Field containedField : containerRow.getFields()) { 218 if (containedField.getPropertyName().matches("organizationReversionDetail\\[\\d+\\]\\.organizationReversionCategory\\.organizationReversionCategoryName")) { 219 final String categoryValue = containedField.getPropertyValue(); 220 includeField = organizationReversionService.isCategoryActiveByName(categoryValue); 221 } 222 } 223 } 224 } 225 return includeField; 226 } 227 228 }