001: /*
002: * Copyright 2007 The Kuali Foundation.
003: *
004: * Licensed under the Educational Community License, Version 1.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/ecl1.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.module.cg.maintenance;
017:
018: import static org.kuali.kfs.KFSPropertyConstants.PROPOSAL_PROJECT_DIRECTORS;
019: import static org.kuali.kfs.KFSPropertyConstants.PROPOSAL_SUBCONTRACTORS;
020:
021: import java.util.ArrayList;
022: import java.util.Collection;
023: import java.util.List;
024: import java.util.Map;
025:
026: import org.apache.commons.lang.StringUtils;
027: import org.kuali.core.bo.PersistableBusinessObject;
028: import org.kuali.core.bo.user.UniversalUser;
029: import org.kuali.core.document.MaintenanceDocument;
030: import org.kuali.core.maintenance.KualiMaintainableImpl;
031: import org.kuali.core.maintenance.Maintainable;
032: import org.kuali.core.util.AssertionUtils;
033: import org.kuali.core.util.GlobalVariables;
034: import org.kuali.core.util.ObjectUtils;
035: import org.kuali.core.web.ui.Section;
036: import org.kuali.kfs.KFSConstants;
037: import org.kuali.kfs.context.SpringContext;
038: import org.kuali.kfs.service.ParameterService;
039: import org.kuali.kfs.service.impl.ParameterConstants;
040: import org.kuali.module.cg.CGConstants;
041: import org.kuali.module.cg.bo.ProjectDirector;
042: import org.kuali.module.cg.bo.Proposal;
043: import org.kuali.module.cg.bo.ProposalProjectDirector;
044: import org.kuali.module.cg.bo.ProposalResearchRisk;
045: import org.kuali.module.cg.lookup.valuefinder.NextProposalNumberFinder;
046: import org.kuali.module.cg.service.ProjectDirectorService;
047: import org.kuali.module.kra.routingform.bo.ResearchRiskType;
048: import org.kuali.module.kra.routingform.service.RoutingFormResearchRiskService;
049:
050: /**
051: * Methods for the Proposal maintenance document UI.
052: */
053: public class ProposalMaintainableImpl extends KualiMaintainableImpl {
054:
055: public ProposalMaintainableImpl() {
056: super ();
057: }
058:
059: /**
060: * Constructs a new ProposalMaintainableImpl from an existing {@link Proposal}.
061: *
062: * @param proposal
063: */
064: public ProposalMaintainableImpl(Proposal proposal) {
065: super (proposal);
066: this .setBoClass(proposal.getClass());
067: }
068:
069: /**
070: * Use a new proposal number when creating a copy.
071: */
072: @Override
073: public void processAfterCopy() {
074: getProposal().setProposalNumber(
075: NextProposalNumberFinder.getLongValue());
076: super .processAfterCopy();
077: }
078:
079: /**
080: * This method is called for refreshing the {@link Agency} before display to show the full name in case the agency number was
081: * changed by hand before any submit that causes a redisplay.
082: */
083: @Override
084: public void processAfterRetrieve() {
085: refreshProposal(false);
086: super .processAfterRetrieve();
087: }
088:
089: /**
090: * <p>
091: * This method is called for refreshing the {@link Agency} before a save to display the full name in case the agency number was
092: * changed by hand just before the save. Also, if there is only one {@link ProjectDirector}, then this method defaults it to be
093: * primary. This method can change data, unlike the rules. It is run before the rules.<p/> This default primary is limited to
094: * save actions (including route, etc) so that when the user adds multiple {@link ProjectDirectors} the first one added doesn't
095: * default to primary (so the user must choose).
096: */
097: @Override
098: public void prepareForSave() {
099: refreshProposal(false);
100: List<ProposalProjectDirector> directors = getProposal()
101: .getProposalProjectDirectors();
102: if (directors.size() == 1) {
103: directors.get(0)
104: .setProposalPrimaryProjectDirectorIndicator(true);
105: }
106: super .prepareForSave();
107: }
108:
109: /**
110: * This method is called for refreshing the {@link Agency} and other related BOs after a lookup, to display their full name &
111: * etc without AJAX.
112: *
113: * @param refreshCaller
114: * @param fieldValues
115: * @param document
116: */
117: @Override
118: public void refresh(String refreshCaller, Map fieldValues,
119: MaintenanceDocument document) {
120: refreshProposal(KFSConstants.KUALI_LOOKUPABLE_IMPL
121: .equals(fieldValues.get(KFSConstants.REFRESH_CALLER)));
122: super .refresh(refreshCaller, fieldValues, document);
123: }
124:
125: /**
126: * This is a hook for initializing the BO from the maintenance framework. It initializes the {@link ResearchRiskType}s
127: * collection.
128: *
129: * @param generateDefaultValues true for initialization
130: */
131: @Override
132: public void setGenerateDefaultValues(boolean generateDefaultValues) {
133: if (generateDefaultValues) {
134: initResearchRiskTypes();
135: }
136: super .setGenerateDefaultValues(generateDefaultValues);
137: }
138:
139: /**
140: *
141: */
142: private void initResearchRiskTypes() {
143: List<ProposalResearchRisk> risks = getProposal()
144: .getProposalResearchRisks();
145: AssertionUtils.assertThat(risks.isEmpty());
146: // no requirement to exclude any risk types (except inactive ones, which the service excludes anyway)
147: final String[] riskTypeCodesToExclude = new String[0];
148: List<ResearchRiskType> researchRiskTypes = SpringContext
149: .getBean(RoutingFormResearchRiskService.class)
150: .getResearchRiskTypes(riskTypeCodesToExclude);
151: for (ResearchRiskType type : researchRiskTypes) {
152: ProposalResearchRisk ppr = new ProposalResearchRisk();
153: ppr.setResearchRiskTypeCode(type.getResearchRiskTypeCode());
154: ppr.setResearchRiskType(type); // one less refresh
155: risks.add(ppr);
156: }
157: }
158:
159: /**
160: * @param refreshFromLookup
161: */
162: private void refreshProposal(boolean refreshFromLookup) {
163: getProposal().refreshNonUpdateableReferences();
164:
165: getNewCollectionLine(PROPOSAL_SUBCONTRACTORS)
166: .refreshNonUpdateableReferences();
167:
168: refreshNonUpdateableReferences(getProposal()
169: .getProposalOrganizations());
170: refreshNonUpdateableReferences(getProposal()
171: .getProposalSubcontractors());
172: refreshNonUpdateableReferences(getProposal()
173: .getProposalResearchRisks());
174:
175: refreshProposalProjectDirectors(refreshFromLookup);
176: }
177:
178: /**
179: * Refreshes this maintainable's ProposalProjectDirectors.
180: *
181: * @param refreshFromLookup a lookup returns only the primary key, so ignore the secondary key when true
182: */
183: private void refreshProposalProjectDirectors(
184: boolean refreshFromLookup) {
185: if (refreshFromLookup) {
186: getNewCollectionLine(PROPOSAL_PROJECT_DIRECTORS)
187: .refreshNonUpdateableReferences();
188: refreshNonUpdateableReferences(getProposal()
189: .getProposalProjectDirectors());
190: } else {
191: refreshWithSecondaryKey((ProposalProjectDirector) getNewCollectionLine(PROPOSAL_PROJECT_DIRECTORS));
192: for (ProposalProjectDirector ppd : getProposal()
193: .getProposalProjectDirectors()) {
194: refreshWithSecondaryKey(ppd);
195: }
196: }
197: }
198:
199: /**
200: * @param collection
201: */
202: private static void refreshNonUpdateableReferences(
203: Collection<? extends PersistableBusinessObject> collection) {
204: for (PersistableBusinessObject item : collection) {
205: item.refreshNonUpdateableReferences();
206: }
207: }
208:
209: /**
210: * Refreshes the reference to ProjectDirector, giving priority to its secondary key. Any secondary key that it has may be user
211: * input, so that overrides the primary key, setting the primary key. If its primary key is blank or nonexistent, then leave the
212: * current reference as it is, because it may be a nonexistent instance which is holding the secondary key (the username, i.e.,
213: * personUserIdentifier) so we can redisplay it to the user for correction. If it only has a primary key then use that, because
214: * it may be coming from the database, without any user input.
215: *
216: * @param ppd the ProposalProjectDirector to refresh
217: */
218: private static void refreshWithSecondaryKey(
219: ProposalProjectDirector ppd) {
220: String secondaryKey = null;
221: ppd.refreshReferenceObject("projectDirector");
222: if (ObjectUtils.isNotNull(ppd.getProjectDirector())) {
223: secondaryKey = ppd.getProjectDirector()
224: .getPersonUserIdentifier();
225: }
226: if (StringUtils.isNotBlank(secondaryKey)) {
227: ProjectDirector dir = SpringContext.getBean(
228: ProjectDirectorService.class)
229: .getByPersonUserIdentifier(secondaryKey);
230: ppd.setPersonUniversalIdentifier(dir == null ? null : dir
231: .getPersonUniversalIdentifier());
232: }
233: if (StringUtils.isNotBlank(ppd.getPersonUniversalIdentifier())
234: && SpringContext.getBean(ProjectDirectorService.class)
235: .primaryIdExists(
236: ppd.getPersonUniversalIdentifier())) {
237: ppd.refreshNonUpdateableReferences();
238: }
239: }
240:
241: /**
242: * Gets the {@link Proposal}
243: *
244: * @return
245: */
246: public Proposal getProposal() {
247: return (Proposal) getBusinessObject();
248: }
249:
250: /**
251: * called for refreshing the {@link Subcontractor} on {@link ProposalSubcontractor} before adding to the
252: * {@link ProposalSubcontractor}s collection on the proposal. this is to ensure that the summary fields are shown correctly.
253: * i.e. {@link Subcontractor} name
254: *
255: * @see org.kuali.core.maintenance.KualiMaintainableImpl#addNewLineToCollection(java.lang.String)
256: */
257: @Override
258: public void addNewLineToCollection(String collectionName) {
259: refreshProposal(false);
260: super .addNewLineToCollection(collectionName);
261: }
262:
263: /**
264: * Allows customizing the maintenance document interface to hide research risks to unprivileged users.
265: *
266: * @param oldMaintainable
267: * @return
268: */
269: @Override
270: public List getSections(Maintainable oldMaintainable) {
271: List<Section> sections = new ArrayList<Section>();
272:
273: List<Section> coreSections = getCoreSections(oldMaintainable);
274:
275: String preAwardWorkgroupName = SpringContext.getBean(
276: ParameterService.class).getParameterValue(
277: ParameterConstants.CONTRACTS_AND_GRANTS_DOCUMENT.class,
278: CGConstants.PRE_AWARD_GROUP);
279: String postAwardWorkgroupName = SpringContext.getBean(
280: ParameterService.class).getParameterValue(
281: ParameterConstants.CONTRACTS_AND_GRANTS_DOCUMENT.class,
282: CGConstants.POST_AWARD_GROUP);
283:
284: UniversalUser user = GlobalVariables.getUserSession()
285: .getUniversalUser();
286: if (!user.isMember(preAwardWorkgroupName)
287: && !user.isMember(postAwardWorkgroupName)) {
288: for (Section section : coreSections) {
289: if (!section.getSectionTitle().equalsIgnoreCase(
290: "Research Risks")) {
291: sections.add(section);
292: } else {
293: // Do nothing
294: }
295: }
296: } else {
297: sections.addAll(coreSections);
298: }
299: return sections;
300: }
301:
302: }
|