/* * The Kuali Financial System, a comprehensive financial management system for higher education. * * Copyright 2005-2014 The Kuali Foundation * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ package org.kuali.kfs.module.cg.document; import java.util.Collection; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.kuali.kfs.module.cg.businessobject.Proposal; import org.kuali.kfs.module.cg.businessobject.ProposalProjectDirector; import org.kuali.kfs.module.cg.businessobject.ProposalResearchRisk; import org.kuali.kfs.module.cg.businessobject.ProposalSubcontractor; import org.kuali.kfs.module.cg.businessobject.ResearchRiskType; import org.kuali.kfs.module.cg.businessobject.defaultvalue.NextProposalNumberFinder; import org.kuali.kfs.module.cg.document.service.RoutingFormResearchRiskService; import org.kuali.kfs.sys.KFSConstants; import org.kuali.kfs.sys.KFSPropertyConstants; import org.kuali.kfs.sys.context.SpringContext; import org.kuali.kfs.sys.document.FinancialSystemMaintainable; import org.kuali.rice.kim.api.identity.principal.Principal; import org.kuali.rice.kim.api.services.KimApiServiceLocator; import org.kuali.rice.kns.document.MaintenanceDocument; import org.kuali.rice.krad.bo.PersistableBusinessObject; import org.kuali.rice.krad.util.ObjectUtils; /** * Methods for the Proposal maintenance document UI. */ public class ProposalMaintainableImpl extends FinancialSystemMaintainable { public ProposalMaintainableImpl() { super(); } /** * Constructs a new ProposalMaintainableImpl from an existing {@link Proposal}. * * @param proposal */ public ProposalMaintainableImpl(Proposal proposal) { super(proposal); this.setBoClass(proposal.getClass()); } /** * Use a new proposal number when creating a copy. */ @Override public void processAfterCopy(MaintenanceDocument document, Map<String, String[]> parameters) { getProposal().setProposalNumber(NextProposalNumberFinder.getLongValue()); getProposal().setProposalClosingDate(null); super.processAfterCopy(document, parameters); } /** * This method is called for refreshing the {@link Agency} before display to show the full name in case the agency number was * changed by hand before any submit that causes a redisplay. */ @Override public void processAfterRetrieve() { refreshProposal(false); super.processAfterRetrieve(); } /** * <p> * This method is called for refreshing the {@link Agency} before a save to display the full name in case the agency number was * changed by hand just before the save. Also, if there is only one {@link ProjectDirector}, then this method defaults it to be * primary. This method can change data, unlike the rules. It is run before the rules.<p/> This default primary is limited to * save actions (including route, etc) so that when the user adds multiple {@link ProjectDirectors} the first one added doesn't * default to primary (so the user must choose). */ @Override public void prepareForSave() { refreshProposal(false); List<ProposalProjectDirector> directors = getProposal().getProposalProjectDirectors(); if (directors.size() == 1) { directors.get(0).setProposalPrimaryProjectDirectorIndicator(true); } List<ProposalSubcontractor> proposalSubcontractors = getProposal().getProposalSubcontractors(); if (proposalSubcontractors != null && !proposalSubcontractors.isEmpty()) { int i = 0; for (ProposalSubcontractor proposalSubcontractor : proposalSubcontractors) { i++; if (StringUtils.isBlank(proposalSubcontractor.getProposalSubcontractorNumber())) { proposalSubcontractor.setProposalSubcontractorNumber("" + i); } } } super.prepareForSave(); } /** * This method is called for refreshing the {@link Agency} and other related BOs after a lookup, to display their full name & * etc without AJAX. * * @param refreshCaller * @param fieldValues * @param document */ @Override public void refresh(String refreshCaller, Map fieldValues, MaintenanceDocument document) { refreshProposal(KFSConstants.KUALI_LOOKUPABLE_IMPL.equals(fieldValues.get(KFSConstants.REFRESH_CALLER))); super.refresh(refreshCaller, fieldValues, document); } /** * This is a hook for initializing the BO from the maintenance framework. It initializes the {@link ResearchRiskType}s * collection. * * @param generateDefaultValues true for initialization */ @Override public void setGenerateDefaultValues(String docTypeName) { initResearchRiskTypes(); super.setGenerateDefaultValues(docTypeName); } /** * */ private void initResearchRiskTypes() { List<ProposalResearchRisk> risks = getProposal().getProposalResearchRisks(); // no requirement to exclude any risk types (except inactive ones, which the service excludes anyway) final String[] riskTypeCodesToExclude = new String[0]; List<ResearchRiskType> researchRiskTypes = SpringContext.getBean(RoutingFormResearchRiskService.class).getResearchRiskTypes(riskTypeCodesToExclude); for (ResearchRiskType type : researchRiskTypes) { ProposalResearchRisk ppr = new ProposalResearchRisk(); ppr.setResearchRiskTypeCode(type.getResearchRiskTypeCode()); ppr.setResearchRiskType(type); // one less refresh risks.add(ppr); } } /** * @param refreshFromLookup */ private void refreshProposal(boolean refreshFromLookup) { getProposal().refreshNonUpdateableReferences(); getNewCollectionLine(KFSPropertyConstants.PROPOSAL_SUBCONTRACTORS).refreshNonUpdateableReferences(); refreshNonUpdateableReferences(getProposal().getProposalOrganizations()); refreshNonUpdateableReferences(getProposal().getProposalSubcontractors()); refreshNonUpdateableReferences(getProposal().getProposalResearchRisks()); refreshProposalProjectDirectors(refreshFromLookup); } /** * Refreshes this maintainable's ProposalProjectDirectors. * * @param refreshFromLookup a lookup returns only the primary key, so ignore the secondary key when true */ private void refreshProposalProjectDirectors(boolean refreshFromLookup) { if (refreshFromLookup) { getNewCollectionLine(KFSPropertyConstants.PROPOSAL_PROJECT_DIRECTORS).refreshNonUpdateableReferences(); refreshNonUpdateableReferences(getProposal().getProposalProjectDirectors()); } else { refreshWithSecondaryKey((ProposalProjectDirector) getNewCollectionLine(KFSPropertyConstants.PROPOSAL_PROJECT_DIRECTORS)); for (ProposalProjectDirector ppd : getProposal().getProposalProjectDirectors()) { refreshWithSecondaryKey(ppd); } } } /** * @param collection */ private static void refreshNonUpdateableReferences(Collection<? extends PersistableBusinessObject> collection) { for (PersistableBusinessObject item : collection) { item.refreshNonUpdateableReferences(); } } /** * Refreshes the reference to ProjectDirector, giving priority to its secondary key. Any secondary key that it has may be user * input, so that overrides the primary key, setting the primary key. If its primary key is blank or nonexistent, then leave the * current reference as it is, because it may be a nonexistent instance which is holding the secondary key (the username, i.e., * principalName) so we can redisplay it to the user for correction. If it only has a primary key then use that, because it may * be coming from the database, without any user input. * * @param ppd the ProposalProjectDirector to refresh */ private static void refreshWithSecondaryKey(ProposalProjectDirector ppd) { String secondaryKey = null; if (ObjectUtils.isNotNull(ppd.getProjectDirector())) { secondaryKey = ppd.getProjectDirector().getPrincipalName(); } if (StringUtils.isNotBlank(secondaryKey)) { Principal dir = KimApiServiceLocator.getIdentityService().getPrincipalByPrincipalName(secondaryKey); ppd.setPrincipalId(dir == null ? null : dir.getPrincipalId()); } if (StringUtils.isNotBlank(ppd.getPrincipalId())) { Principal person = KimApiServiceLocator.getIdentityService().getPrincipal(ppd.getPrincipalId()); if (person != null) { ppd.refreshNonUpdateableReferences(); } } } /** * Gets the {@link Proposal} * * @return */ public Proposal getProposal() { return (Proposal) getBusinessObject(); } /** * called for refreshing the {@link Subcontractor} on {@link ProposalSubcontractor} before adding to the * {@link ProposalSubcontractor}s collection on the proposal. this is to ensure that the summary fields are shown correctly. * i.e. {@link Subcontractor} name * * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#addNewLineToCollection(java.lang.String) */ @Override public void addNewLineToCollection(String collectionName) { refreshProposal(false); super.addNewLineToCollection(collectionName); } }