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    
024    import org.kuali.kfs.coa.businessobject.OrganizationReversion;
025    import org.kuali.kfs.coa.businessobject.OrganizationReversionCategory;
026    import org.kuali.kfs.coa.businessobject.OrganizationReversionGlobal;
027    import org.kuali.kfs.coa.businessobject.OrganizationReversionGlobalDetail;
028    import org.kuali.kfs.coa.businessobject.OrganizationReversionGlobalOrganization;
029    import org.kuali.kfs.coa.service.OrganizationReversionService;
030    import org.kuali.kfs.sys.KFSConstants;
031    import org.kuali.kfs.sys.context.SpringContext;
032    import org.kuali.kfs.sys.document.FinancialSystemGlobalMaintainable;
033    import org.kuali.rice.kns.bo.PersistableBusinessObject;
034    import org.kuali.rice.kns.document.MaintenanceLock;
035    import org.kuali.rice.kns.util.TypedArrayList;
036    
037    /**
038     * This class provides some specific functionality for the {@link OrganizationReversionGlobal} maintenance document inner class for
039     * doing comparisons on {@link OrganizationReversionCategory} generateMaintenanceLocks - generates the appropriate maintenance locks
040     * on {@link OrganizationReversion} setBusinessObject - populates the {@link OrganizationReversionGlobalDetail}s
041     * isRelationshipRefreshable - makes sure that {@code organizationReversionGlobalDetails} isn't wiped out accidentally
042     * processGlobalsAfterRetrieve - provides special handling for the details (which aren't a true collection)
043     */
044    public class OrganizationReversionGlobalMaintainableImpl extends FinancialSystemGlobalMaintainable {
045        protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(OrganizationReversionGlobalMaintainableImpl.class);
046    
047        /**
048         * This class is an inner class for comparing two {@link OrganizationReversionCategory}s
049         */
050        private class CategoryComparator implements Comparator<OrganizationReversionGlobalDetail> {
051            public int compare(OrganizationReversionGlobalDetail detailA, OrganizationReversionGlobalDetail detailB) {
052                OrganizationReversionCategory categoryA = detailA.getOrganizationReversionCategory();
053                OrganizationReversionCategory categoryB = detailB.getOrganizationReversionCategory();
054    
055                String code0 = categoryA.getOrganizationReversionCategoryCode();
056                String code1 = categoryB.getOrganizationReversionCategoryCode();
057    
058                return code0.compareTo(code1);
059            }
060        }
061    
062        /**
063         * This implementation locks all organization reversions that would be accessed by this global organization reversion. It does
064         * not lock any OrganizationReversionDetail objects, as we expect that those will be inaccessible
065         * 
066         * @see org.kuali.rice.kns.maintenance.KualiGlobalMaintainableImpl#generateMaintenaceLocks()
067         */
068        @Override
069        public List<MaintenanceLock> generateMaintenanceLocks() {
070            List<MaintenanceLock> locks = new ArrayList<MaintenanceLock>();
071            OrganizationReversionGlobal globalOrgRev = (OrganizationReversionGlobal) this.getBusinessObject();
072            if (globalOrgRev.getUniversityFiscalYear() != null && globalOrgRev.getOrganizationReversionGlobalOrganizations() != null && globalOrgRev.getOrganizationReversionGlobalOrganizations().size() > 0) { // only generate locks if we're going to have primary keys
073                for (OrganizationReversionGlobalOrganization orgRevOrg : globalOrgRev.getOrganizationReversionGlobalOrganizations()) {
074                    MaintenanceLock maintenanceLock = new MaintenanceLock();
075                    maintenanceLock.setDocumentNumber(globalOrgRev.getDocumentNumber());
076    
077                    StringBuffer lockRep = new StringBuffer();
078                    lockRep.append(OrganizationReversion.class.getName());
079                    lockRep.append(KFSConstants.Maintenance.AFTER_CLASS_DELIM);
080                    lockRep.append("chartOfAccountsCode");
081                    lockRep.append(KFSConstants.Maintenance.AFTER_FIELDNAME_DELIM);
082                    lockRep.append(orgRevOrg.getChartOfAccountsCode());
083                    lockRep.append(KFSConstants.Maintenance.AFTER_VALUE_DELIM);
084                    lockRep.append("universityFiscalYear");
085                    lockRep.append(KFSConstants.Maintenance.AFTER_FIELDNAME_DELIM);
086                    lockRep.append(globalOrgRev.getUniversityFiscalYear().toString());
087                    lockRep.append(KFSConstants.Maintenance.AFTER_VALUE_DELIM);
088                    lockRep.append("organizationCode");
089                    lockRep.append(KFSConstants.Maintenance.AFTER_FIELDNAME_DELIM);
090                    lockRep.append(orgRevOrg.getOrganizationCode());
091                    lockRep.append(KFSConstants.Maintenance.AFTER_VALUE_DELIM);
092    
093                    maintenanceLock.setLockingRepresentation(lockRep.toString());
094                    locks.add(maintenanceLock);
095                }
096            }
097    
098            return locks;
099        }
100    
101        /**
102         * Just like OrganizationReversionMaintainableImpl's setBusinessObject method populates the list of details so there is one
103         * detail per active Organization Reversion Category, this method populates a list of Organization Reversion Change details.
104         * 
105         * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#setBusinessObject(org.kuali.rice.kns.bo.PersistableBusinessObject)
106         */
107        @Override
108        public void setBusinessObject(PersistableBusinessObject businessObject) {
109            super.setBusinessObject(businessObject);
110            OrganizationReversionService organizationReversionService = SpringContext.getBean(OrganizationReversionService.class);
111            OrganizationReversionGlobal globalOrgRev = (OrganizationReversionGlobal) businessObject;
112            List<OrganizationReversionGlobalDetail> details = globalOrgRev.getOrganizationReversionGlobalDetails();
113            LOG.debug("Details size before adding categories = " + details.size());
114    
115            if (details == null) {
116                details = new TypedArrayList(OrganizationReversionGlobalDetail.class);
117                globalOrgRev.setOrganizationReversionGlobalDetails(details);
118            }
119    
120            if (details.size() == 0) {
121    
122                Collection<OrganizationReversionCategory> categories = organizationReversionService.getCategoryList();
123                for (OrganizationReversionCategory category : categories) {
124                    if (category.isActive()) {
125                        OrganizationReversionGlobalDetail detail = new OrganizationReversionGlobalDetail();
126                        detail.setOrganizationReversionCategoryCode(category.getOrganizationReversionCategoryCode());
127                        detail.setOrganizationReversionCategory(category);
128                        detail.setParentGlobalOrganizationReversion(globalOrgRev);
129                        details.add(detail);
130                    }
131                }
132                LOG.debug("Details size after adding categories = " + details.size());
133                Collections.sort(details, new CategoryComparator());
134            }
135            super.setBusinessObject(businessObject);
136        }
137    
138        /**
139         * Prevents Organization Reversion Change Details from being refreshed by a look up (because doing that refresh before a save
140         * would wipe out the list of organization reversion change details).
141         * 
142         * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#isRelationshipRefreshable(java.lang.Class, java.lang.String)
143         */
144        @Override
145        protected boolean isRelationshipRefreshable(Class boClass, String relationshipName) {
146            if (relationshipName.equals("organizationReversionGlobalDetails")) {
147                return false;
148            }
149            else {
150                return super.isRelationshipRefreshable(boClass, relationshipName);
151            }
152        }
153    
154        /**
155         * The org reversion detail collection does not behave like a true collection (no add lines). The records on the collection
156         * should not have the delete option.
157         * 
158         * @see org.kuali.rice.kns.maintenance.KualiGlobalMaintainableImpl#processGlobalsAfterRetrieve()
159         */
160        @Override
161        protected void processGlobalsAfterRetrieve() {
162            super.processGlobalsAfterRetrieve();
163            for (OrganizationReversionGlobalDetail changeDetail : ((OrganizationReversionGlobal) businessObject).getOrganizationReversionGlobalDetails()) {
164                changeDetail.setNewCollectionRecord(false);
165            }
166        }
167    
168        @Override
169        public Class<? extends PersistableBusinessObject> getPrimaryEditedBusinessObjectClass() {
170            return OrganizationReversion.class;
171        }
172    }