View Javadoc
1   /*
2    * Copyright 2007 The Kuali Foundation
3    * 
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    * 
8    * http://www.opensource.org/licenses/ecl2.php
9    * 
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.ole.module.cg.document;
17  
18  import java.util.Collection;
19  import java.util.List;
20  import java.util.Map;
21  
22  import org.apache.commons.lang.StringUtils;
23  import org.kuali.ole.module.cg.businessobject.Proposal;
24  import org.kuali.ole.module.cg.businessobject.ProposalProjectDirector;
25  import org.kuali.ole.module.cg.businessobject.ProposalResearchRisk;
26  import org.kuali.ole.module.cg.businessobject.ProposalSubcontractor;
27  import org.kuali.ole.module.cg.businessobject.ResearchRiskType;
28  import org.kuali.ole.module.cg.businessobject.defaultvalue.NextProposalNumberFinder;
29  import org.kuali.ole.module.cg.document.service.RoutingFormResearchRiskService;
30  import org.kuali.ole.sys.OLEConstants;
31  import org.kuali.ole.sys.OLEPropertyConstants;
32  import org.kuali.ole.sys.context.SpringContext;
33  import org.kuali.ole.sys.document.FinancialSystemMaintainable;
34  import org.kuali.rice.kim.api.identity.Person;
35  import org.kuali.rice.kim.api.identity.PersonService;
36  import org.kuali.rice.kns.document.MaintenanceDocument;
37  import org.kuali.rice.krad.bo.PersistableBusinessObject;
38  import org.kuali.rice.krad.util.ObjectUtils;
39  
40  /**
41   * Methods for the Proposal maintenance document UI.
42   */
43  public class ProposalMaintainableImpl extends FinancialSystemMaintainable {
44      public ProposalMaintainableImpl() {
45          super();
46      }
47  
48      /**
49       * Constructs a new ProposalMaintainableImpl from an existing {@link Proposal}.
50       * 
51       * @param proposal
52       */
53      public ProposalMaintainableImpl(Proposal proposal) {
54          super(proposal);
55          this.setBoClass(proposal.getClass());
56      }
57  
58      /**
59       * Use a new proposal number when creating a copy.
60       */
61      @Override
62      public void processAfterCopy(MaintenanceDocument document, Map<String, String[]> parameters) {
63          getProposal().setProposalNumber(NextProposalNumberFinder.getLongValue());
64          getProposal().setProposalClosingDate(null);
65          super.processAfterCopy(document, parameters);
66      }
67  
68      /**
69       * This method is called for refreshing the {@link Agency} before display to show the full name in case the agency number was
70       * changed by hand before any submit that causes a redisplay.
71       */
72      @Override
73      public void processAfterRetrieve() {
74          refreshProposal(false);
75          super.processAfterRetrieve();
76      }
77  
78      /**
79       * <p>
80       * This method is called for refreshing the {@link Agency} before a save to display the full name in case the agency number was
81       * changed by hand just before the save. Also, if there is only one {@link ProjectDirector}, then this method defaults it to be
82       * primary. This method can change data, unlike the rules. It is run before the rules.<p/> This default primary is limited to
83       * save actions (including route, etc) so that when the user adds multiple {@link ProjectDirectors} the first one added doesn't
84       * default to primary (so the user must choose).
85       */
86      @Override
87      public void prepareForSave() {
88          refreshProposal(false);
89          List<ProposalProjectDirector> directors = getProposal().getProposalProjectDirectors();
90          if (directors.size() == 1) {
91              directors.get(0).setProposalPrimaryProjectDirectorIndicator(true);
92          }
93          List<ProposalSubcontractor> proposalSubcontractors = getProposal().getProposalSubcontractors();
94          if (proposalSubcontractors != null && !proposalSubcontractors.isEmpty()) {
95              int i = 0;
96              for (ProposalSubcontractor proposalSubcontractor : proposalSubcontractors) {
97                  i++;
98                  if (StringUtils.isBlank(proposalSubcontractor.getProposalSubcontractorNumber())) {
99                      proposalSubcontractor.setProposalSubcontractorNumber("" + i);
100                 }
101             }
102         }
103         super.prepareForSave();
104     }
105 
106     /**
107      * This method is called for refreshing the {@link Agency} and other related BOs after a lookup, to display their full name &
108      * etc without AJAX.
109      * 
110      * @param refreshCaller
111      * @param fieldValues
112      * @param document
113      */
114     @Override
115     public void refresh(String refreshCaller, Map fieldValues, MaintenanceDocument document) {
116         refreshProposal(OLEConstants.KUALI_LOOKUPABLE_IMPL.equals(fieldValues.get(OLEConstants.REFRESH_CALLER)));
117         super.refresh(refreshCaller, fieldValues, document);
118     }
119 
120     /**
121      * This is a hook for initializing the BO from the maintenance framework. It initializes the {@link ResearchRiskType}s
122      * collection.
123      * 
124      * @param generateDefaultValues true for initialization
125      */
126     @Override
127     public void setGenerateDefaultValues(String docTypeName) {
128         // if (generateDefaultValues) {
129         initResearchRiskTypes();
130         // }
131         super.setGenerateDefaultValues(docTypeName);
132     }
133 
134     /**
135      * 
136      */
137     private void initResearchRiskTypes() {
138         List<ProposalResearchRisk> risks = getProposal().getProposalResearchRisks();
139         // no requirement to exclude any risk types (except inactive ones, which the service excludes anyway)
140         final String[] riskTypeCodesToExclude = new String[0];
141         List<ResearchRiskType> researchRiskTypes = SpringContext.getBean(RoutingFormResearchRiskService.class).getResearchRiskTypes(riskTypeCodesToExclude);
142         for (ResearchRiskType type : researchRiskTypes) {
143             ProposalResearchRisk ppr = new ProposalResearchRisk();
144             ppr.setResearchRiskTypeCode(type.getResearchRiskTypeCode());
145             ppr.setResearchRiskType(type); // one less refresh
146             risks.add(ppr);
147         }
148     }
149 
150     /**
151      * @param refreshFromLookup
152      */
153     private void refreshProposal(boolean refreshFromLookup) {
154         getProposal().refreshNonUpdateableReferences();
155 
156         getNewCollectionLine(OLEPropertyConstants.PROPOSAL_SUBCONTRACTORS).refreshNonUpdateableReferences();
157 
158         refreshNonUpdateableReferences(getProposal().getProposalOrganizations());
159         refreshNonUpdateableReferences(getProposal().getProposalSubcontractors());
160         refreshNonUpdateableReferences(getProposal().getProposalResearchRisks());
161 
162         refreshProposalProjectDirectors(refreshFromLookup);
163     }
164 
165     /**
166      * Refreshes this maintainable's ProposalProjectDirectors.
167      * 
168      * @param refreshFromLookup a lookup returns only the primary key, so ignore the secondary key when true
169      */
170     private void refreshProposalProjectDirectors(boolean refreshFromLookup) {
171         if (refreshFromLookup) {
172             getNewCollectionLine(OLEPropertyConstants.PROPOSAL_PROJECT_DIRECTORS).refreshNonUpdateableReferences();
173             refreshNonUpdateableReferences(getProposal().getProposalProjectDirectors());
174         }
175         else {
176             refreshWithSecondaryKey((ProposalProjectDirector) getNewCollectionLine(OLEPropertyConstants.PROPOSAL_PROJECT_DIRECTORS));
177             for (ProposalProjectDirector ppd : getProposal().getProposalProjectDirectors()) {
178                 refreshWithSecondaryKey(ppd);
179             }
180         }
181     }
182 
183     /**
184      * @param collection
185      */
186     private static void refreshNonUpdateableReferences(Collection<? extends PersistableBusinessObject> collection) {
187         for (PersistableBusinessObject item : collection) {
188             item.refreshNonUpdateableReferences();
189         }
190     }
191 
192     /**
193      * Refreshes the reference to ProjectDirector, giving priority to its secondary key. Any secondary key that it has may be user
194      * input, so that overrides the primary key, setting the primary key. If its primary key is blank or nonexistent, then leave the
195      * current reference as it is, because it may be a nonexistent instance which is holding the secondary key (the username, i.e.,
196      * principalName) so we can redisplay it to the user for correction. If it only has a primary key then use that, because it may
197      * be coming from the database, without any user input.
198      * 
199      * @param ppd the ProposalProjectDirector to refresh
200      */
201     private static void refreshWithSecondaryKey(ProposalProjectDirector ppd) {
202         String secondaryKey = null;
203         if (ObjectUtils.isNotNull(ppd.getProjectDirector())) {
204             secondaryKey = ppd.getProjectDirector().getPrincipalName();
205         }
206         if (StringUtils.isNotBlank(secondaryKey)) {
207             Person dir = SpringContext.getBean(PersonService.class).getPersonByPrincipalName(secondaryKey);
208             ppd.setPrincipalId(dir == null ? null : dir.getPrincipalId());
209         }
210         if (StringUtils.isNotBlank(ppd.getPrincipalId())) {
211             Person person = SpringContext.getBean(PersonService.class).getPerson(ppd.getPrincipalId());
212             if (person != null) {
213                 ppd.refreshNonUpdateableReferences();
214             }
215         }
216     }
217 
218     /**
219      * Gets the {@link Proposal}
220      * 
221      * @return
222      */
223     public Proposal getProposal() {
224         return (Proposal) getBusinessObject();
225     }
226 
227     /**
228      * called for refreshing the {@link Subcontractor} on {@link ProposalSubcontractor} before adding to the
229      * {@link ProposalSubcontractor}s collection on the proposal. this is to ensure that the summary fields are shown correctly.
230      * i.e. {@link Subcontractor} name
231      * 
232      * @see org.kuali.rice.kns.maintenance.KualiMaintainableImpl#addNewLineToCollection(java.lang.String)
233      */
234     @Override
235     public void addNewLineToCollection(String collectionName) {
236         refreshProposal(false);
237         super.addNewLineToCollection(collectionName);
238     }
239 }