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.businessobject;
017    
018    import java.util.ArrayList;
019    import java.util.HashMap;
020    import java.util.LinkedHashMap;
021    import java.util.List;
022    import java.util.Map;
023    
024    import org.apache.commons.lang.StringUtils;
025    import org.kuali.kfs.coa.service.OrganizationReversionService;
026    import org.kuali.kfs.sys.KFSPropertyConstants;
027    import org.kuali.kfs.sys.businessobject.SystemOptions;
028    import org.kuali.kfs.sys.context.SpringContext;
029    import org.kuali.rice.kns.bo.GlobalBusinessObject;
030    import org.kuali.rice.kns.bo.GlobalBusinessObjectDetail;
031    import org.kuali.rice.kns.bo.PersistableBusinessObject;
032    import org.kuali.rice.kns.bo.PersistableBusinessObjectBase;
033    import org.kuali.rice.kns.service.BusinessObjectService;
034    import org.kuali.rice.kns.service.PersistenceStructureService;
035    import org.kuali.rice.kns.util.TypedArrayList;
036    
037    /**
038     * The representation of a Global Organization Reversion. A Global Organization Reversion is made up of three sections: 1. The
039     * University Fiscal Year and Chart of Accounts code for the Organizations going through reversion, with some account information.
040     * 2. A list of the appropriate Object Reversion Details 3. A list of Organizations to apply the Organization Reversion to
041     */
042    public class OrganizationReversionGlobal extends PersistableBusinessObjectBase implements GlobalBusinessObject {
043        protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(OrganizationReversionGlobal.class);
044        private String documentNumber;
045    
046        private Integer universityFiscalYear;
047        private String budgetReversionChartOfAccountsCode;
048        private String budgetReversionAccountNumber;
049        private Boolean carryForwardByObjectCodeIndicator;
050        private String cashReversionFinancialChartOfAccountsCode;
051        private String cashReversionAccountNumber;
052    
053        private Account cashReversionAccount;
054        private Account budgetReversionAccount;
055        private Chart budgetReversionChartOfAccounts;
056        private Chart cashReversionFinancialChartOfAccounts;
057        private SystemOptions universityFiscal;
058    
059        private List<OrganizationReversionGlobalDetail> organizationReversionGlobalDetails;
060        private List<OrganizationReversionGlobalOrganization> organizationReversionGlobalOrganizations;
061    
062        public OrganizationReversionGlobal() {
063            super();
064            organizationReversionGlobalDetails = new TypedArrayList(OrganizationReversionGlobalDetail.class);
065            organizationReversionGlobalOrganizations = new TypedArrayList(OrganizationReversionGlobalOrganization.class);
066        }
067    
068        /**
069         * @see org.kuali.rice.kns.bo.BusinessObjectBase#toStringMapper()
070         */
071        @Override
072        protected LinkedHashMap toStringMapper() {
073            LinkedHashMap stringMapper = new LinkedHashMap();
074            stringMapper.put(KFSPropertyConstants.DOCUMENT_NUMBER, this.documentNumber);
075            stringMapper.put(KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR, this.universityFiscalYear);
076            return stringMapper;
077        }
078    
079        /**
080         * Gets the budgetReversionAccount attribute.
081         * 
082         * @return Returns the budgetReversionAccount.
083         */
084        public Account getBudgetReversionAccount() {
085            return budgetReversionAccount;
086        }
087    
088        /**
089         * Gets the documentNumber attribute.
090         * 
091         * @return Returns the documentNumber.
092         */
093        public String getDocumentNumber() {
094            return documentNumber;
095        }
096    
097        /**
098         * Sets the documentNumber attribute value.
099         * 
100         * @param documentNumber The documentNumber to set.
101         */
102        public void setDocumentNumber(String documentNumber) {
103            this.documentNumber = documentNumber;
104        }
105    
106        /**
107         * Sets the budgetReversionAccount attribute value.
108         * 
109         * @param budgetReversionAccount The budgetReversionAccount to set.
110         * @deprecated
111         */
112        public void setBudgetReversionAccount(Account budgetReversionAccount) {
113            this.budgetReversionAccount = budgetReversionAccount;
114        }
115    
116        /**
117         * Gets the budgetReversionAccountNumber attribute.
118         * 
119         * @return Returns the budgetReversionAccountNumber.
120         */
121        public String getBudgetReversionAccountNumber() {
122            return budgetReversionAccountNumber;
123        }
124    
125        /**
126         * Sets the budgetReversionAccountNumber attribute value.
127         * 
128         * @param budgetReversionAccountNumber The budgetReversionAccountNumber to set.
129         */
130        public void setBudgetReversionAccountNumber(String budgetReversionAccountNumber) {
131            this.budgetReversionAccountNumber = budgetReversionAccountNumber;
132        }
133    
134        /**
135         * Gets the budgetReversionChartOfAccounts attribute.
136         * 
137         * @return Returns the budgetReversionChartOfAccounts.
138         */
139        public Chart getBudgetReversionChartOfAccounts() {
140            return budgetReversionChartOfAccounts;
141        }
142    
143        /**
144         * Sets the budgetReversionChartOfAccounts attribute value.
145         * 
146         * @param budgetReversionChartOfAccounts The budgetReversionChartOfAccounts to set.
147         * @deprecated
148         */
149        public void setBudgetReversionChartOfAccounts(Chart budgetReversionChartOfAccounts) {
150            this.budgetReversionChartOfAccounts = budgetReversionChartOfAccounts;
151        }
152    
153        /**
154         * Gets the budgetReversionChartOfAccountsCode attribute.
155         * 
156         * @return Returns the budgetReversionChartOfAccountsCode.
157         */
158        public String getBudgetReversionChartOfAccountsCode() {
159            return budgetReversionChartOfAccountsCode;
160        }
161    
162        /**
163         * Sets the budgetReversionChartOfAccountsCode attribute value.
164         * 
165         * @param budgetReversionChartOfAccountsCode The budgetReversionChartOfAccountsCode to set.
166         */
167        public void setBudgetReversionChartOfAccountsCode(String budgetReversionChartOfAccountsCode) {
168            this.budgetReversionChartOfAccountsCode = budgetReversionChartOfAccountsCode;
169        }
170    
171        /**
172         * Gets the carryForwardByObjectCodeIndicator attribute.
173         * 
174         * @return Returns the carryForwardByObjectCodeIndicator.
175         */
176        public Boolean isCarryForwardByObjectCodeIndicator() {
177            return carryForwardByObjectCodeIndicator;
178        }
179    
180        /**
181         * Gets the carryForwardByObjectCodeIndicator attribute: but for other methods that don't like to call "is" and would rather
182         * call "get"
183         * 
184         * @return Returns the carryForwardByObjectCodeIndicator.
185         */
186        public Boolean getCarryForwardByObjectCodeIndicator() {
187            return this.isCarryForwardByObjectCodeIndicator();
188        }
189    
190        /**
191         * Sets the carryForwardByObjectCodeIndicator attribute value.
192         * 
193         * @param carryForwardByObjectCodeIndicator The carryForwardByObjectCodeIndicator to set.
194         */
195        public void setCarryForwardByObjectCodeIndicator(Boolean carryForwardByObjectCodeIndicator) {
196            this.carryForwardByObjectCodeIndicator = carryForwardByObjectCodeIndicator;
197        }
198    
199        /**
200         * Gets the cashReversionAccount attribute.
201         * 
202         * @return Returns the cashReversionAccount.
203         */
204        public Account getCashReversionAccount() {
205            return cashReversionAccount;
206        }
207    
208        /**
209         * Sets the cashReversionAccount attribute value.
210         * 
211         * @param cashReversionAccount The cashReversionAccount to set.
212         * @deprecated
213         */
214        public void setCashReversionAccount(Account cashReversionAccount) {
215            this.cashReversionAccount = cashReversionAccount;
216        }
217    
218        /**
219         * Gets the cashReversionAccountNumber attribute.
220         * 
221         * @return Returns the cashReversionAccountNumber.
222         */
223        public String getCashReversionAccountNumber() {
224            return cashReversionAccountNumber;
225        }
226    
227        /**
228         * Sets the cashReversionAccountNumber attribute value.
229         * 
230         * @param cashReversionAccountNumber The cashReversionAccountNumber to set.
231         */
232        public void setCashReversionAccountNumber(String cashReversionAccountNumber) {
233            this.cashReversionAccountNumber = cashReversionAccountNumber;
234        }
235    
236        /**
237         * Gets the cashReversionFinancialChartOfAccounts attribute.
238         * 
239         * @return Returns the cashReversionFinancialChartOfAccounts.
240         */
241        public Chart getCashReversionFinancialChartOfAccounts() {
242            return cashReversionFinancialChartOfAccounts;
243        }
244    
245        /**
246         * Sets the cashReversionFinancialChartOfAccounts attribute value.
247         * 
248         * @param cashReversionFinancialChartOfAccounts The cashReversionFinancialChartOfAccounts to set.
249         * @deprecated
250         */
251        public void setCashReversionFinancialChartOfAccounts(Chart cashReversionFinancialChartOfAccounts) {
252            this.cashReversionFinancialChartOfAccounts = cashReversionFinancialChartOfAccounts;
253        }
254    
255        /**
256         * Gets the cashReversionFinancialChartOfAccountsCode attribute.
257         * 
258         * @return Returns the cashReversionFinancialChartOfAccountsCode.
259         */
260        public String getCashReversionFinancialChartOfAccountsCode() {
261            return cashReversionFinancialChartOfAccountsCode;
262        }
263    
264        /**
265         * Sets the cashReversionFinancialChartOfAccountsCode attribute value.
266         * 
267         * @param cashReversionFinancialChartOfAccountsCode The cashReversionFinancialChartOfAccountsCode to set.
268         */
269        public void setCashReversionFinancialChartOfAccountsCode(String cashReversionFinancialChartOfAccountsCode) {
270            this.cashReversionFinancialChartOfAccountsCode = cashReversionFinancialChartOfAccountsCode;
271        }
272    
273        /**
274         * Gets the organizationReversionGlobalOrganizations attribute.
275         * 
276         * @return Returns the organizationReversionGlobalOrganizations.
277         */
278        public List<OrganizationReversionGlobalOrganization> getOrganizationReversionGlobalOrganizations() {
279            return organizationReversionGlobalOrganizations;
280        }
281    
282        /**
283         * Sets the organizationReversionGlobalOrganizations attribute value.
284         * 
285         * @param organizationReversionGlobalOrganizations The organizationReversionGlobalOrganizations to set.
286         * @deprecated
287         */
288        public void setOrganizationReversionGlobalOrganizations(List<OrganizationReversionGlobalOrganization> organizationReversionGlobalOrganizations) {
289            this.organizationReversionGlobalOrganizations = organizationReversionGlobalOrganizations;
290        }
291    
292        /**
293         * Gets the organizationReversionGlobalDocumentDetails attribute.
294         * 
295         * @return Returns the organizationReversionGlobalDocumentDetails.
296         */
297        public List<OrganizationReversionGlobalDetail> getOrganizationReversionGlobalDetails() {
298            return organizationReversionGlobalDetails;
299        }
300    
301        /**
302         * Sets the organizationReversionGlobalDocumentDetails attribute value.
303         * 
304         * @param organizationReversionGlobalDocumentDetails The organizationReversionGlobalDocumentDetails to set.
305         */
306        public void setOrganizationReversionGlobalDetails(List<OrganizationReversionGlobalDetail> organizationReversionGlobalDetails) {
307            this.organizationReversionGlobalDetails = organizationReversionGlobalDetails;
308        }
309    
310        /**
311         * Gets the universityFiscalYear attribute.
312         * 
313         * @return Returns the universityFiscalYear.
314         */
315        public Integer getUniversityFiscalYear() {
316            return universityFiscalYear;
317        }
318    
319        /**
320         * Sets the universityFiscalYear attribute value.
321         * 
322         * @param universityFiscalYear The universityFiscalYear to set.
323         */
324        public void setUniversityFiscalYear(Integer universityFiscalYear) {
325            this.universityFiscalYear = universityFiscalYear;
326        }
327    
328        /**
329         * Gets the universityFiscal attribute.
330         * 
331         * @return Returns the universityFiscal.
332         */
333        public SystemOptions getUniversityFiscal() {
334            return universityFiscal;
335        }
336    
337        /**
338         * Sets the universityFiscal attribute value.
339         * 
340         * @param universityFiscal The universityFiscal to set.
341         */
342        public void setUniversityFiscal(SystemOptions universityFiscal) {
343            this.universityFiscal = universityFiscal;
344        }
345    
346        /**
347         * @see org.kuali.rice.kns.bo.GlobalBusinessObject#generateDeactivationsToPersist() As global organization reversions only update
348         *      existing records, deactivations will never be produced by creating one; thus, this method always returns an empty list.
349         */
350        public List<PersistableBusinessObject> generateDeactivationsToPersist() {
351            return null;
352        }
353    
354        /**
355         * @see org.kuali.rice.kns.bo.GlobalBusinessObject#generateGlobalChangesToPersist() This creates a list of changes to be made to the
356         *      existing Organization Reversion records impacted by this global reversion.
357         */
358        public List<PersistableBusinessObject> generateGlobalChangesToPersist() {
359            List<PersistableBusinessObject> persistingChanges = new ArrayList<PersistableBusinessObject>();
360    
361            BusinessObjectService boService = SpringContext.getBean(BusinessObjectService.class);
362            Map<String, OrganizationReversionGlobalDetail> detailsMap = this.rearrangeOrganizationReversionDetailsAsMap();
363    
364            for (OrganizationReversionGlobalOrganization orgRevOrg : this.getOrganizationReversionGlobalOrganizations()) {
365                // 1. find that organization reversion
366                OrganizationReversion currOrgRev = SpringContext.getBean(OrganizationReversionService.class).getByPrimaryId(this.getUniversityFiscalYear(), orgRevOrg.getChartOfAccountsCode(), orgRevOrg.getOrganizationCode());
367    
368                if (currOrgRev != null) { // only proceed if there's a pre-existing org reversion; we don't want to insert any new
369                                            // records
370                    if (!StringUtils.isBlank(this.getBudgetReversionChartOfAccountsCode())) {
371                        currOrgRev.setBudgetReversionChartOfAccountsCode(this.getBudgetReversionChartOfAccountsCode());
372                    }
373                    if (!StringUtils.isBlank(this.getBudgetReversionAccountNumber())) {
374                        currOrgRev.setBudgetReversionAccountNumber(this.getBudgetReversionAccountNumber());
375                    }
376                    if (!StringUtils.isBlank(this.getCashReversionFinancialChartOfAccountsCode())) {
377                        currOrgRev.setCashReversionFinancialChartOfAccountsCode(this.getCashReversionFinancialChartOfAccountsCode());
378                    }
379                    if (!StringUtils.isBlank(this.getCashReversionAccountNumber())) {
380                        currOrgRev.setCashReversionAccountNumber(this.getCashReversionAccountNumber());
381                    }
382    
383                    if (this.isCarryForwardByObjectCodeIndicator() != null) {
384                        currOrgRev.setCarryForwardByObjectCodeIndicator(this.isCarryForwardByObjectCodeIndicator().booleanValue());
385                    }
386    
387                    // 3. now, go through each org reversion detail and update each of those
388                    for (OrganizationReversionDetail orgRevDetail : currOrgRev.getOrganizationReversionDetail()) {
389                        OrganizationReversionGlobalDetail changeDetail = detailsMap.get(orgRevDetail.getOrganizationReversionCategoryCode());
390                        if (changeDetail != null) {
391                            if (!StringUtils.isBlank(changeDetail.getOrganizationReversionCode())) {
392                                orgRevDetail.setOrganizationReversionCode(changeDetail.getOrganizationReversionCode());
393                            }
394                            if (!StringUtils.isBlank(changeDetail.getOrganizationReversionObjectCode())) {
395                                orgRevDetail.setOrganizationReversionObjectCode(changeDetail.getOrganizationReversionObjectCode());
396                            }
397                        }
398                    }
399    
400                    currOrgRev.refreshNonUpdateableReferences();
401                    persistingChanges.add(currOrgRev);
402                }
403    
404            }
405            return persistingChanges;
406        }
407    
408        /**
409         * This sticks all of the Organization Reversion Change Details into a map, for quicker access in
410         * generateGlobalChangesToPersist.
411         * 
412         * @return a map of all organization reversion change details, keyed by OrganizationReversionCategory
413         */
414        private Map<String, OrganizationReversionGlobalDetail> rearrangeOrganizationReversionDetailsAsMap() {
415            Map<String, OrganizationReversionGlobalDetail> orgRevMap = new HashMap<String, OrganizationReversionGlobalDetail>();
416            for (OrganizationReversionGlobalDetail orgRevDetail : this.getOrganizationReversionGlobalDetails()) {
417                if (!StringUtils.isBlank(orgRevDetail.getOrganizationReversionObjectCode()) || !StringUtils.isBlank(orgRevDetail.getOrganizationReversionCode())) {
418                    orgRevMap.put(orgRevDetail.getOrganizationReversionCategoryCode(), orgRevDetail);
419                }
420            }
421            return orgRevMap;
422        }
423    
424        /**
425         * @see org.kuali.rice.kns.bo.GlobalBusinessObject#getAllDetailObjects() This returns a list of all the detail objects held within
426         *      this main global organization reversion container.
427         */
428        public List<? extends GlobalBusinessObjectDetail> getAllDetailObjects() {
429            List<GlobalBusinessObjectDetail> detailObjects = new ArrayList<GlobalBusinessObjectDetail>();
430            detailObjects.addAll(this.getOrganizationReversionGlobalDetails());
431            detailObjects.addAll(this.getOrganizationReversionGlobalOrganizations());
432            return detailObjects;
433        }
434    
435        /**
436         * @see org.kuali.rice.kns.bo.GlobalBusinessObject#isPersistable() returns whether this global object reversion can be stored in the
437         *      database, which is really a question of whether it and all of its details have all of their appropriate primary keys
438         *      set.
439         */
440        public boolean isPersistable() {
441            PersistenceStructureService persistenceStructureService = SpringContext.getBean(PersistenceStructureService.class);
442    
443            if (!persistenceStructureService.hasPrimaryKeyFieldValues(this)) {
444                return false;
445            }
446    
447            for (OrganizationReversionGlobalDetail orgRevDetail : this.getOrganizationReversionGlobalDetails()) {
448                if (!persistenceStructureService.hasPrimaryKeyFieldValues(orgRevDetail)) {
449                    return false;
450                }
451            }
452    
453            for (OrganizationReversionGlobalOrganization orgRevOrg : this.getOrganizationReversionGlobalOrganizations()) {
454                if (!persistenceStructureService.hasPrimaryKeyFieldValues(orgRevOrg)) {
455                    return false;
456                }
457            }
458    
459            // are we still here? really? Then, hey, let's persist!
460            return true;
461        }
462    
463        /**
464         * @see org.kuali.rice.kns.bo.PersistableBusinessObjectBase#buildListOfDeletionAwareLists()
465         */
466        @Override
467        public List buildListOfDeletionAwareLists() {
468            List<List> managedLists = super.buildListOfDeletionAwareLists();
469    
470            managedLists.add(getOrganizationReversionGlobalDetails());
471            managedLists.add(getOrganizationReversionGlobalOrganizations());
472    
473            return managedLists;
474        }
475    }