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.HashMap;
020    import java.util.HashSet;
021    import java.util.List;
022    import java.util.Map;
023    import java.util.Set;
024    
025    import org.apache.commons.lang.StringUtils;
026    import org.kuali.kfs.coa.businessobject.AccountDelegate;
027    import org.kuali.kfs.coa.businessobject.AccountDelegateGlobal;
028    import org.kuali.kfs.coa.businessobject.AccountDelegateGlobalDetail;
029    import org.kuali.kfs.coa.businessobject.AccountDelegateModel;
030    import org.kuali.kfs.coa.businessobject.AccountDelegateModelDetail;
031    import org.kuali.kfs.coa.businessobject.AccountGlobalDetail;
032    import org.kuali.kfs.coa.service.AccountDelegateService;
033    import org.kuali.kfs.sys.KFSConstants;
034    import org.kuali.kfs.sys.context.SpringContext;
035    import org.kuali.kfs.sys.document.FinancialSystemGlobalMaintainable;
036    import org.kuali.rice.kim.service.RoleManagementService;
037    import org.kuali.rice.kns.bo.DocumentHeader;
038    import org.kuali.rice.kns.bo.PersistableBusinessObject;
039    import org.kuali.rice.kns.document.MaintenanceDocument;
040    import org.kuali.rice.kns.document.MaintenanceLock;
041    import org.kuali.rice.kns.service.BusinessObjectService;
042    import org.kuali.rice.kns.util.ObjectUtils;
043    
044    /**
045     * This class overrides the base {@link FinancialSystemGlobalMaintainable} to generate the specific maintenance locks for Global delegates
046     * and to help with using delegate models
047     * 
048     * @see OrganizationRoutingModelName
049     */
050    public class AccountDelegateGlobalMaintainableImpl extends FinancialSystemGlobalMaintainable {
051        private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AccountDelegateGlobalMaintainableImpl.class);
052    
053        /**
054         * This method is used for the creation of a delegate from a {@link OrganizationRoutingModelName}
055         * 
056         * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#setupNewFromExisting()
057         */
058        @Override
059        public void setupNewFromExisting( MaintenanceDocument document, Map<String,String[]> parameters ) {
060            super.setupNewFromExisting( document, parameters );
061    
062            AccountDelegateGlobal globalDelegate = (AccountDelegateGlobal) this.getBusinessObject();
063            globalDelegate.setVersionNumber(1L);
064            this.setBusinessObject(globalDelegate);
065            // 1. if model name, chart of accounts, and org code are all present
066            // then let's see if we've actually got a model record
067            if (!StringUtils.isBlank(globalDelegate.getModelName()) && !StringUtils.isBlank(globalDelegate.getModelChartOfAccountsCode()) && !StringUtils.isBlank(globalDelegate.getModelOrganizationCode())) {
068                Map pkMap = new HashMap();
069                pkMap.put("accountDelegateModelName", globalDelegate.getModelName());
070                pkMap.put("chartOfAccountsCode", globalDelegate.getModelChartOfAccountsCode());
071                pkMap.put("organizationCode", globalDelegate.getModelOrganizationCode());
072    
073                AccountDelegateModel globalDelegateTemplate = (AccountDelegateModel) SpringContext.getBean(BusinessObjectService.class).findByPrimaryKey(AccountDelegateModel.class, pkMap);
074                if (globalDelegateTemplate != null) {
075                    // 2. if there is a model record, then let's populate the global delegate
076                    // based on that
077                    for (AccountDelegateModelDetail model : globalDelegateTemplate.getAccountDelegateModelDetails()) {
078                        if (model.isActive()) { // only populate with active models
079                            AccountDelegateGlobalDetail newDelegate = new AccountDelegateGlobalDetail(model);
080                            // allow deletion of the new delegate from the global delegate
081                            newDelegate.setNewCollectionRecord(true);
082                            globalDelegate.getDelegateGlobals().add(newDelegate);
083                        }
084                    }
085                }
086            }
087        }
088    
089        @Override
090        public String getLockingDocumentId() {
091           String lock = super.getLockingDocumentId();
092           if (StringUtils.isNotBlank(lock))
093               return lock;
094           else {
095               AccountDelegateService accountDelegateService = SpringContext.getBean(AccountDelegateService.class);
096               lock = accountDelegateService.getLockingDocumentId(this, this.documentNumber);
097               return lock;
098           }
099        }
100        
101        
102        /**
103         * This creates the particular locking representation for this global document.
104         * 
105         * @see org.kuali.rice.kns.maintenance.Maintainable#generateMaintenanceLocks()
106         */
107        @Override
108        public List<MaintenanceLock> generateMaintenanceLocks() {
109            // create locking rep for each combination of account and object code
110            List<MaintenanceLock> maintenanceLocks = new ArrayList();
111            AccountDelegateGlobal delegateGlobal = (AccountDelegateGlobal) getBusinessObject();
112    
113            // hold all the locking representations in a set to make sure we don't get any duplicates
114            Set<String> lockingRepresentations = new HashSet<String>();
115    
116            MaintenanceLock maintenanceLock;
117            if (ObjectUtils.isNotNull(delegateGlobal)) {
118                for (AccountGlobalDetail accountGlobalDetail : delegateGlobal.getAccountGlobalDetails()) {
119                    for (AccountDelegateGlobalDetail delegateGlobalDetail : delegateGlobal.getDelegateGlobals()) {
120                        StringBuilder lockRep = new StringBuilder();
121                        lockRep.append(AccountDelegate.class.getName());
122                        lockRep.append(KFSConstants.Maintenance.AFTER_CLASS_DELIM);
123                        lockRep.append("chartOfAccountsCode");
124                        lockRep.append(KFSConstants.Maintenance.AFTER_FIELDNAME_DELIM);
125                        lockRep.append(accountGlobalDetail.getChartOfAccountsCode());
126                        lockRep.append(KFSConstants.Maintenance.AFTER_VALUE_DELIM);
127                        lockRep.append("accountNumber");
128                        lockRep.append(KFSConstants.Maintenance.AFTER_FIELDNAME_DELIM);
129                        lockRep.append(accountGlobalDetail.getAccountNumber());
130                        lockRep.append(KFSConstants.Maintenance.AFTER_VALUE_DELIM);
131                        lockRep.append("financialDocumentTypeCode");
132                        lockRep.append(KFSConstants.Maintenance.AFTER_FIELDNAME_DELIM);
133                        lockRep.append(delegateGlobalDetail.getFinancialDocumentTypeCode());
134                        lockRep.append(KFSConstants.Maintenance.AFTER_VALUE_DELIM);
135                        lockRep.append("accountDelegateSystemId");
136                        lockRep.append(KFSConstants.Maintenance.AFTER_FIELDNAME_DELIM);
137                        lockRep.append(delegateGlobalDetail.getAccountDelegateUniversalId());
138                        // FIXME above is a bit dangerous b/c it hard codes the attribute names, which could change (particularly
139                        // accountDelegateSystemId) - guess they should either be constants or obtained by looping through Delegate keys;
140                        // however, I copied this from elsewhere which had them hard-coded, so I'm leaving it for now
141    
142                        if (!lockingRepresentations.contains(lockRep.toString())) {
143                            maintenanceLock = new MaintenanceLock();
144                            maintenanceLock.setDocumentNumber(delegateGlobal.getDocumentNumber());
145                            maintenanceLock.setLockingRepresentation(lockRep.toString());
146                            maintenanceLocks.add(maintenanceLock);
147                            lockingRepresentations.add(lockRep.toString());
148                        }
149    
150                        lockRep = new StringBuilder();
151                        lockRep.append(AccountDelegate.class.getName());
152                        lockRep.append(KFSConstants.Maintenance.AFTER_CLASS_DELIM);
153                        lockRep.append("chartOfAccountsCode");
154                        lockRep.append(KFSConstants.Maintenance.AFTER_FIELDNAME_DELIM);
155                        lockRep.append(accountGlobalDetail.getChartOfAccountsCode());
156                        lockRep.append(KFSConstants.Maintenance.AFTER_VALUE_DELIM);
157                        lockRep.append("accountNumber");
158                        lockRep.append(KFSConstants.Maintenance.AFTER_FIELDNAME_DELIM);
159                        lockRep.append(accountGlobalDetail.getAccountNumber());
160                        lockRep.append(KFSConstants.Maintenance.AFTER_VALUE_DELIM);
161                        lockRep.append("financialDocumentTypeCode");
162                        lockRep.append(KFSConstants.Maintenance.AFTER_FIELDNAME_DELIM);
163                        lockRep.append(delegateGlobalDetail.getFinancialDocumentTypeCode());
164                        lockRep.append(KFSConstants.Maintenance.AFTER_VALUE_DELIM);
165                        lockRep.append("accountsDelegatePrmrtIndicator");
166                        lockRep.append(KFSConstants.Maintenance.AFTER_FIELDNAME_DELIM);
167                        lockRep.append("true");
168    
169                        if (!lockingRepresentations.contains(lockRep.toString())) {
170                            maintenanceLock = new MaintenanceLock();
171                            maintenanceLock.setDocumentNumber(delegateGlobal.getDocumentNumber());
172                            maintenanceLock.setLockingRepresentation(lockRep.toString());
173                            maintenanceLocks.add(maintenanceLock);
174                            lockingRepresentations.add(lockRep.toString());
175                        }
176    
177                        lockRep = new StringBuilder();
178                        lockRep.append(AccountDelegateGlobal.class.getName());
179                        lockRep.append(KFSConstants.Maintenance.AFTER_CLASS_DELIM);
180                        lockRep.append("chartOfAccountsCode");
181                        lockRep.append(KFSConstants.Maintenance.AFTER_FIELDNAME_DELIM);
182                        lockRep.append(accountGlobalDetail.getChartOfAccountsCode());
183                        lockRep.append(KFSConstants.Maintenance.AFTER_VALUE_DELIM);
184                        lockRep.append("accountNumber");
185                        lockRep.append(KFSConstants.Maintenance.AFTER_FIELDNAME_DELIM);
186                        lockRep.append(accountGlobalDetail.getAccountNumber());
187    
188                        if (!lockingRepresentations.contains(lockRep.toString())) {
189                            maintenanceLock = new MaintenanceLock();
190                            maintenanceLock.setDocumentNumber(delegateGlobal.getDocumentNumber());
191                            maintenanceLock.setLockingRepresentation(lockRep.toString());
192                            maintenanceLocks.add(maintenanceLock);
193                            lockingRepresentations.add(lockRep.toString());
194                        }
195                    }
196                }
197            }
198            return maintenanceLocks;
199        }
200    
201        @Override
202        public Class<? extends PersistableBusinessObject> getPrimaryEditedBusinessObjectClass() {
203            return AccountDelegate.class;
204        }
205    
206        /**
207         * Overridden to update the delegations for currently routing documents; this also guarantees that the business
208         * objects to change will be saved in a separate transaction
209         * @see org.kuali.rice.kns.maintenance.KualiGlobalMaintainableImpl#saveBusinessObject()
210         */
211        @Override
212        public void saveBusinessObject() {
213            final AccountDelegateGlobal accountDelegateGlobal = (AccountDelegateGlobal)this.getBusinessObject();
214            final AccountDelegateService accountDelegateService = SpringContext.getBean(AccountDelegateService.class);
215            
216            accountDelegateService.saveInactivationsForGlobalMaintenanceDocument(accountDelegateGlobal.generateDeactivationsToPersist());
217            accountDelegateService.saveChangesForGlobalMaintenanceDocument(accountDelegateGlobal.generateGlobalChangesToPersist());
218            
219            accountDelegateService.updateDelegationRole();
220        }
221    }