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.rules;
017:
018: import java.sql.Date;
019: import java.util.Arrays;
020: import java.util.Collection;
021: import java.util.List;
022:
023: import org.apache.commons.lang.StringUtils;
024: import org.kuali.core.bo.BusinessObject;
025: import org.kuali.core.maintenance.rules.MaintenanceDocumentRuleBase;
026: import org.kuali.core.service.DataDictionaryService;
027: import org.kuali.core.util.ObjectUtils;
028: import org.kuali.kfs.KFSKeyConstants;
029: import org.kuali.kfs.KFSPropertyConstants;
030: import org.kuali.kfs.context.SpringContext;
031: import org.kuali.module.cg.bo.Agency;
032: import org.kuali.module.cg.bo.CGProjectDirector;
033: import org.kuali.module.cg.bo.Primaryable;
034: import org.kuali.module.cg.service.ProjectDirectorService;
035:
036: /**
037: * Rules for the Proposal/Award maintenance document.
038: */
039: public class CGMaintenanceDocumentRuleBase extends
040: MaintenanceDocumentRuleBase {
041:
042: private static final String PROJECT_DIRECTOR_DECEASED = "D";
043: private static final String[] PROJECT_DIRECTOR_INVALID_STATUSES = { PROJECT_DIRECTOR_DECEASED };
044:
045: private static final String AGENCY_TYPE_CODE_FEDERAL = "F";
046:
047: /**
048: * Checks to see if the end date is after the begin date
049: *
050: * @param begin
051: * @param end
052: * @param propertyName
053: * @return true if end is after begin, false otherwise
054: */
055: protected boolean checkEndAfterBegin(Date begin, Date end,
056: String propertyName) {
057: boolean success = true;
058: if (ObjectUtils.isNotNull(begin) && ObjectUtils.isNotNull(end)
059: && !end.after(begin)) {
060: putFieldError(propertyName,
061: KFSKeyConstants.ERROR_ENDING_DATE_NOT_AFTER_BEGIN);
062: success = false;
063: }
064: return success;
065: }
066:
067: /**
068: * @param <E>
069: * @param primaryables
070: * @param elementClass
071: * @param collectionName
072: * @param boClass
073: * @return
074: */
075: protected <E extends Primaryable> boolean checkPrimary(
076: Collection<E> primaryables, Class<E> elementClass,
077: String collectionName,
078: Class<? extends BusinessObject> boClass) {
079: boolean success = true;
080: int count = 0;
081: for (Primaryable p : primaryables) {
082: if (p.isPrimary()) {
083: count++;
084: }
085: }
086: if (count != 1) {
087: success = false;
088: String elementLabel = SpringContext.getBean(
089: DataDictionaryService.class)
090: .getCollectionElementLabel(boClass.getName(),
091: collectionName, elementClass);
092: switch (count) {
093: case 0:
094: putFieldError(collectionName,
095: KFSKeyConstants.ERROR_NO_PRIMARY, elementLabel);
096: break;
097: default:
098: putFieldError(collectionName,
099: KFSKeyConstants.ERROR_MULTIPLE_PRIMARY,
100: elementLabel);
101: }
102:
103: }
104: return success;
105: }
106:
107: /**
108: * @param <T>
109: * @param projectDirectors
110: * @param elementClass
111: * @param collectionName
112: * @return
113: */
114: protected <T extends CGProjectDirector> boolean checkProjectDirectorsExist(
115: List<T> projectDirectors, Class<T> elementClass,
116: String collectionName) {
117: boolean success = true;
118: final String personUserPropertyName = KFSPropertyConstants.PROJECT_DIRECTOR
119: + "." + KFSPropertyConstants.PERSON_USER_IDENTIFIER;
120: String label = SpringContext.getBean(
121: DataDictionaryService.class).getAttributeLabel(
122: elementClass, personUserPropertyName);
123: int i = 0;
124: for (T pd : projectDirectors) {
125: String propertyName = collectionName + "[" + (i++) + "]."
126: + personUserPropertyName;
127: String id = pd.getPersonUniversalIdentifier();
128: if (StringUtils.isBlank(id)
129: || !SpringContext.getBean(
130: ProjectDirectorService.class)
131: .primaryIdExists(id)) {
132: putFieldError(propertyName,
133: KFSKeyConstants.ERROR_EXISTENCE, label);
134: success = false;
135: }
136: }
137: return success;
138: }
139:
140: /**
141: * This method takes in a collection of {@link ProjectDirector}s and reviews them to see if any have invalid states for being
142: * added to a {@link Proposal}. An example would be a status code of "D" which means "Deceased". Project Directors with a
143: * status of "D" cannot be added to a {@link Proposal} or {@link Award}.
144: *
145: * @param projectDirectors Collection of project directors to be reviewed.
146: * @param elementClass Type of object that the collection belongs to.
147: * @param propertyName Name of field that error will be attached to.
148: * @return True if all the project directors have valid statuses, false otherwise.
149: */
150: protected <T extends CGProjectDirector> boolean checkProjectDirectorsStatuses(
151: List<T> projectDirectors, Class<T> elementClass,
152: String propertyName) {
153: boolean success = true;
154: final String personUserPropertyName = KFSPropertyConstants.PROJECT_DIRECTOR
155: + "." + KFSPropertyConstants.PERSON_USER_IDENTIFIER;
156: String label = SpringContext.getBean(
157: DataDictionaryService.class).getAttributeLabel(
158: elementClass, personUserPropertyName);
159: for (T pd : projectDirectors) {
160: String pdEmplStatusCode = pd.getProjectDirector()
161: .getUniversalUser().getEmployeeStatusCode();
162: String pdEmplStatusName = pd.getProjectDirector()
163: .getUniversalUser().getEmployeeStatus().getName();
164: if (StringUtils.isBlank(pdEmplStatusCode)
165: || Arrays.asList(PROJECT_DIRECTOR_INVALID_STATUSES)
166: .contains(pdEmplStatusCode)) {
167: String[] errors = {
168: pd.getProjectDirector().getPersonName(),
169: pdEmplStatusCode + " - " + pdEmplStatusName };
170: putFieldError(
171: propertyName,
172: KFSKeyConstants.ERROR_INVALID_PROJECT_DIRECTOR_STATUS,
173: errors);
174: success = false;
175: }
176: }
177: return success;
178: }
179:
180: /**
181: * This method checks to see if the two agency values passed in are the same {@link Agency}. The agency for a C&G document
182: * cannot be the same as the Federal Pass Through Agency for that same document.
183: *
184: * @param agency
185: * @param federalPassThroughAgency
186: * @param agencyPropertyName
187: * @return True if the agencies are not the same, false otherwise.
188: */
189: protected boolean checkAgencyNotEqualToFederalPassThroughAgency(
190: Agency agency, Agency federalPassThroughAgency,
191: String agencyPropertyName,
192: String fedPassThroughAgencyPropertyName) {
193: boolean success = true;
194: if (ObjectUtils.isNotNull(agency)
195: && ObjectUtils.isNotNull(federalPassThroughAgency)
196: && agency.equals(federalPassThroughAgency)) {
197: putFieldError(
198: agencyPropertyName,
199: KFSKeyConstants.ERROR_AGENCY_EQUALS_FEDERAL_PASS_THROUGH_AGENCY);
200: putFieldError(
201: fedPassThroughAgencyPropertyName,
202: KFSKeyConstants.ERROR_FEDERAL_PASS_THROUGH_AGENCY_EQUALS_AGENCY);
203: success = false;
204: }
205: return success;
206: }
207:
208: /**
209: * Checks if the required federal pass through fields are filled in if the federal pass through indicator is yes.
210: *
211: * @return True if all the necessary rules regarding the federal pass through agency input fields are met, false otherwise.
212: */
213: protected boolean checkFederalPassThrough(
214: boolean federalPassThroughIndicator, Agency primaryAgency,
215: String federalPassThroughAgencyNumber, Class propertyClass,
216: String federalPassThroughIndicatorFieldName) {
217: boolean success = true;
218:
219: // check if primary agency is federal
220: boolean primaryAgencyIsFederal = false;
221:
222: if (ObjectUtils.isNotNull(primaryAgency)) {
223: primaryAgencyIsFederal = AGENCY_TYPE_CODE_FEDERAL
224: .equalsIgnoreCase(primaryAgency.getAgencyTypeCode());
225: }
226:
227: String indicatorLabel = SpringContext.getBean(
228: DataDictionaryService.class).getAttributeErrorLabel(
229: propertyClass, federalPassThroughIndicatorFieldName);
230: String agencyLabel = SpringContext
231: .getBean(DataDictionaryService.class)
232: .getAttributeErrorLabel(
233: propertyClass,
234: KFSPropertyConstants.FEDERAL_PASS_THROUGH_AGENCY_NUMBER);
235:
236: if (primaryAgencyIsFederal) {
237: if (federalPassThroughIndicator) {
238: // fpt indicator should not be checked if primary agency is federal
239: putFieldError(
240: federalPassThroughIndicatorFieldName,
241: KFSKeyConstants.ERROR_PRIMARY_AGENCY_IS_FEDERAL_AND_FPT_INDICATOR_IS_CHECKED,
242: new String[] { primaryAgency.getAgencyNumber(),
243: AGENCY_TYPE_CODE_FEDERAL });
244: success = false;
245: }
246: if (!StringUtils.isBlank(federalPassThroughAgencyNumber)) {
247: // fpt agency number should be blank if primary agency is federal
248: putFieldError(
249: KFSPropertyConstants.FEDERAL_PASS_THROUGH_AGENCY_NUMBER,
250: KFSKeyConstants.ERROR_PRIMARY_AGENCY_IS_FEDERAL_AND_FPT_AGENCY_IS_NOT_BLANK,
251: new String[] { primaryAgency.getAgencyNumber(),
252: AGENCY_TYPE_CODE_FEDERAL });
253: success = false;
254: }
255: } else {
256: if (federalPassThroughIndicator
257: && StringUtils
258: .isBlank(federalPassThroughAgencyNumber)) {
259: // fpt agency number is required if fpt indicator is checked
260: putFieldError(
261: KFSPropertyConstants.FEDERAL_PASS_THROUGH_AGENCY_NUMBER,
262: KFSKeyConstants.ERROR_FPT_AGENCY_NUMBER_REQUIRED);
263: success = false;
264: } else if (!federalPassThroughIndicator
265: && !StringUtils
266: .isBlank(federalPassThroughAgencyNumber)) {
267: // fpt agency number should be blank if fpt indicator is not checked
268: putFieldError(
269: KFSPropertyConstants.FEDERAL_PASS_THROUGH_AGENCY_NUMBER,
270: KFSKeyConstants.ERROR_FPT_AGENCY_NUMBER_NOT_BLANK);
271: success = false;
272: }
273: }
274:
275: return success;
276: }
277:
278: }
|