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.workflow.module.purap.attribute;
017:
018: import java.util.ArrayList;
019: import java.util.Collection;
020: import java.util.HashMap;
021: import java.util.HashSet;
022: import java.util.Iterator;
023: import java.util.List;
024: import java.util.Map;
025: import java.util.Set;
026:
027: import javax.xml.xpath.XPath;
028: import javax.xml.xpath.XPathConstants;
029: import javax.xml.xpath.XPathExpressionException;
030:
031: import org.apache.commons.lang.StringUtils;
032: import org.apache.log4j.Logger;
033: import org.kuali.core.lookup.LookupUtils;
034: import org.kuali.core.service.LookupService;
035: import org.kuali.core.util.ObjectUtils;
036: import org.kuali.kfs.KFSConstants;
037: import org.kuali.kfs.KFSPropertyConstants;
038: import org.kuali.kfs.bo.Options;
039: import org.kuali.kfs.context.SpringContext;
040: import org.kuali.kfs.service.ParameterEvaluator;
041: import org.kuali.kfs.service.ParameterService;
042: import org.kuali.module.chart.bo.Account;
043: import org.kuali.module.chart.bo.Chart;
044: import org.kuali.module.chart.bo.ObjectCode;
045: import org.kuali.module.chart.bo.SubFundGroup;
046: import org.kuali.module.chart.service.AccountService;
047: import org.kuali.module.chart.service.ObjectCodeService;
048: import org.kuali.module.purap.PurapParameterConstants;
049: import org.kuali.module.purap.document.PurchaseOrderDocument;
050: import org.kuali.workflow.KualiWorkflowUtils;
051: import org.w3c.dom.Node;
052: import org.w3c.dom.NodeList;
053:
054: import edu.iu.uis.eden.WorkflowServiceErrorImpl;
055: import edu.iu.uis.eden.lookupable.Row;
056: import edu.iu.uis.eden.plugin.attributes.WorkflowAttribute;
057: import edu.iu.uis.eden.routeheader.DocumentContent;
058: import edu.iu.uis.eden.routetemplate.RuleExtension;
059: import edu.iu.uis.eden.routetemplate.RuleExtensionValue;
060:
061: /**
062: * Attribute for Purchase Order document types to test whether the document should route to Contract and Grants Review Node<br>
063: * <br>
064: * <code>This attribute allows wildcard characters</code>
065: */
066: public class KualiPurchaseOrderContractAndGrantsAttribute implements
067: WorkflowAttribute {
068: private static Logger LOG = Logger
069: .getLogger(KualiPurchaseOrderContractAndGrantsAttribute.class);
070:
071: private static final String SUB_FUND_GROUP_CODE_KEY = "sub_fund_grp_cd";
072: private static final String UNIVERSITY_FISCAL_YEAR_KEY = "univ_fiscal_year";
073: private static final String CHART_CODE_KEY = "fin_coa_cd";
074: private static final String ACCOUNT_NUMBER_KEY = "account_number";
075: private static final String OBJECT_CODE_KEY = "object_code";
076:
077: private List ruleRows;
078: private List routingDataRows;
079: private boolean required = false;
080: private String fiscalYear;
081: private String chartCode;
082: private String accountNumber;
083: private String objectCode;
084: // following attribute only used for rule rows
085: private String subFundGroupCode;
086:
087: /**
088: * Constructs a KualiPurchaseOrderContractAndGrantsAttribute.java.
089: */
090: public KualiPurchaseOrderContractAndGrantsAttribute() {
091: ruleRows = new ArrayList<edu.iu.uis.eden.lookupable.Row>();
092: ruleRows.add(KualiWorkflowUtils.buildTextRowWithLookup(
093: SubFundGroup.class,
094: KFSPropertyConstants.SUB_FUND_GROUP_CODE,
095: SUB_FUND_GROUP_CODE_KEY));
096:
097: routingDataRows = new ArrayList<edu.iu.uis.eden.lookupable.Row>();
098: routingDataRows.add(KualiWorkflowUtils.buildTextRowWithLookup(
099: Options.class,
100: KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR,
101: UNIVERSITY_FISCAL_YEAR_KEY));
102: routingDataRows.add(KualiWorkflowUtils.buildTextRowWithLookup(
103: Chart.class,
104: KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE,
105: CHART_CODE_KEY));
106: Map fieldConversionMap = new HashMap();
107: fieldConversionMap.put(
108: KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE,
109: CHART_CODE_KEY);
110: routingDataRows.add(KualiWorkflowUtils.buildTextRowWithLookup(
111: Account.class, KFSPropertyConstants.ACCOUNT_NUMBER,
112: ACCOUNT_NUMBER_KEY, fieldConversionMap));
113: routingDataRows.add(KualiWorkflowUtils.buildTextRowWithLookup(
114: ObjectCode.class,
115: KFSPropertyConstants.FINANCIAL_OBJECT_CODE,
116: OBJECT_CODE_KEY, fieldConversionMap));
117: }
118:
119: /**
120: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#getDocContent()
121: */
122: public String getDocContent() {
123: if ((StringUtils.isBlank(getFiscalYear()))
124: && (StringUtils.isBlank(getChartCode()))
125: && (StringUtils.isBlank(getAccountNumber()))
126: && (StringUtils.isBlank(getObjectCode()))) {
127: return "";
128: } // attributeContent
129: StringBuffer returnValue = new StringBuffer(
130: KualiWorkflowUtils.XML_REPORT_DOC_CONTENT_PREFIX);
131: returnValue
132: .append(
133: "<"
134: + KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR
135: + ">")
136: .append(getFiscalYear())
137: .append(
138: "</"
139: + KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR
140: + ">");
141: returnValue
142: .append(
143: "<"
144: + KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE
145: + ">")
146: .append(getChartCode())
147: .append(
148: "</"
149: + KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE
150: + ">");
151: returnValue.append(
152: "<" + KFSPropertyConstants.ACCOUNT_NUMBER + ">")
153: .append(getAccountNumber()).append(
154: "</" + KFSPropertyConstants.ACCOUNT_NUMBER
155: + ">");
156: returnValue
157: .append(
158: "<"
159: + KFSPropertyConstants.FINANCIAL_OBJECT_CODE
160: + ">")
161: .append(getObjectCode())
162: .append(
163: "</"
164: + KFSPropertyConstants.FINANCIAL_OBJECT_CODE
165: + ">");
166: return returnValue.append(
167: KualiWorkflowUtils.XML_REPORT_DOC_CONTENT_SUFFIX)
168: .toString();
169: }
170:
171: /**
172: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#getRoutingDataRows()
173: */
174: public List<Row> getRoutingDataRows() {
175: return routingDataRows;
176: }
177:
178: /**
179: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#getRuleExtensionValues()
180: */
181: public List<RuleExtensionValue> getRuleExtensionValues() {
182: List extensions = new ArrayList();
183: if (StringUtils.isNotBlank(getSubFundGroupCode())) {
184: extensions.add(new RuleExtensionValue(
185: SUB_FUND_GROUP_CODE_KEY, getSubFundGroupCode()));
186: }
187: return extensions;
188: }
189:
190: /**
191: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#getRuleRows()
192: */
193: public List<Row> getRuleRows() {
194: return ruleRows;
195: }
196:
197: /**
198: * This method returns true if all the following conditions are met:
199: * <ol>
200: * <li>Account is marked as a 'Contract and Grants' account (see
201: * {@link org.kuali.module.chart.bo.Account#isForContractsAndGrants()})
202: * <li>Account has a Contract and Grants Restricted Object Code as defined in the system business rules
203: * <li>Account has Sub Fund Group Code matching rule value
204: * </ol>
205: *
206: * @param docContent
207: * @param ruleExtensions
208: * @return
209: */
210: public boolean isMatch(DocumentContent docContent,
211: List<RuleExtension> ruleExtensions) {
212: boolean alwaysMatches = false;
213: String ruleSubFundGroupCode = getRuleExtentionValue(
214: SUB_FUND_GROUP_CODE_KEY, ruleExtensions);
215: if ((StringUtils.isBlank(ruleSubFundGroupCode))
216: || (KFSConstants.WILDCARD_CHARACTER
217: .equalsIgnoreCase(ruleSubFundGroupCode))) {
218: // if rule extension is blank or the Wildcard character... always match this rule if criteria is true
219: alwaysMatches = true;
220: }
221: ruleSubFundGroupCode = LookupUtils.forceUppercase(
222: SubFundGroup.class,
223: KFSPropertyConstants.SUB_FUND_GROUP_CODE,
224: ruleSubFundGroupCode);
225: Set<AccountContainer> accountContainers = populateFromDocContent(docContent);
226:
227: for (AccountContainer accountContainer : accountContainers) {
228: // check to see if account is a C&G account
229: if (accountContainer.account.isForContractsAndGrants()) {
230: // check the restricted object code in rule table (object codes listed in the table should route via this attribute)
231: ParameterEvaluator parameterRulesByChart = SpringContext
232: .getBean(ParameterService.class)
233: .getParameterEvaluator(
234: PurchaseOrderDocument.class,
235: PurapParameterConstants.WorkflowParameters.PurchaseOrderDocument.CG_RESTRICTED_OBJECT_CODE_RULE_PARM_NM,
236: PurapParameterConstants.WorkflowParameters.PurchaseOrderDocument.NO_CG_RESTRICTED_OBJECT_CODE_RULE_PARM_NM,
237: accountContainer.account
238: .getChartOfAccountsCode(),
239: accountContainer.objectCode
240: .getFinancialObjectCode());
241: if (parameterRulesByChart.evaluationSucceeds()) {
242: if (StringUtils.isBlank(accountContainer.account
243: .getSubFundGroupCode())) {
244: // sub fund is blank
245: String errorMsg = "SubFund not found for account '"
246: + accountContainer.account
247: .getChartOfAccountsCode()
248: + "-"
249: + accountContainer.account
250: .getAccountNumber() + "'";
251: LOG.error(errorMsg);
252: throw new RuntimeException(errorMsg);
253: }
254: // if alwaysMatches is true then we return here
255: if (alwaysMatches) {
256: return true;
257: }
258: // rule fails (since rules are denoted as 'denied' this means the object code is in the rule parameter text)
259: int indexOfWildcard = ruleSubFundGroupCode
260: .indexOf(KFSConstants.WILDCARD_CHARACTER);
261: if (indexOfWildcard != -1) {
262: // found a wildcard character
263: String prefix = ruleSubFundGroupCode.substring(
264: 0, indexOfWildcard);
265: String suffix = ruleSubFundGroupCode
266: .substring(indexOfWildcard + 1);
267: if (((prefix.length() == 0) && (accountContainer.account
268: .getSubFundGroupCode().endsWith(suffix)))
269: || ((suffix.length() == 0) && (accountContainer.account
270: .getSubFundGroupCode()
271: .startsWith(prefix)))
272: || ((prefix.length() != 0)
273: && (suffix.length() != 0)
274: && (accountContainer.account
275: .getSubFundGroupCode()
276: .startsWith(prefix)) && (accountContainer.account
277: .getSubFundGroupCode()
278: .endsWith(suffix)))) {
279: return true;
280: }
281: } else {
282: // no valid wildcard character found
283: if (accountContainer.account
284: .getSubFundGroupCode().equals(
285: ruleSubFundGroupCode)) {
286: return true;
287: }
288: }
289: }
290: }
291: }
292: return false;
293: }
294:
295: private String getRuleExtentionValue(String key, List ruleExtensions) {
296: for (Iterator iter = ruleExtensions.iterator(); iter.hasNext();) {
297: RuleExtension extension = (RuleExtension) iter.next();
298: if (extension.getRuleTemplateAttribute().getRuleAttribute()
299: .getClassName().equals(this .getClass().getName())) {
300: for (Iterator iterator = extension.getExtensionValues()
301: .iterator(); iterator.hasNext();) {
302: RuleExtensionValue value = (RuleExtensionValue) iterator
303: .next();
304: if (value.getKey().equals(key)) {
305: return value.getValue();
306: }
307: }
308: }
309: }
310: return null;
311: }
312:
313: public Set<AccountContainer> populateFromDocContent(
314: DocumentContent docContent) {
315: Set accounts = new HashSet();
316: String currentXPath = null;
317: try {
318: XPath xpath = KualiWorkflowUtils.getXPath(docContent
319: .getDocument());
320: String finChart = null;
321: String finAccount = null;
322: String finObjectCode = null;
323: String finFiscalYear = null;
324: currentXPath = new StringBuffer(
325: KualiWorkflowUtils.XSTREAM_SAFE_PREFIX)
326: .append(
327: KualiWorkflowUtils.XSTREAM_MATCH_ANYWHERE_PREFIX)
328: .append(
329: KualiWorkflowUtils.XML_REPORT_DOC_CONTENT_XPATH_PREFIX)
330: .append(KualiWorkflowUtils.XSTREAM_SAFE_SUFFIX)
331: .toString();
332: boolean isReport = ((Boolean) xpath.evaluate(currentXPath,
333: docContent.getDocument(), XPathConstants.BOOLEAN))
334: .booleanValue();
335: if (isReport) {
336: currentXPath = new StringBuffer(
337: KualiWorkflowUtils.XSTREAM_SAFE_PREFIX)
338: .append(
339: KualiWorkflowUtils.XSTREAM_MATCH_ANYWHERE_PREFIX)
340: .append(
341: KualiWorkflowUtils.XML_REPORT_DOC_CONTENT_XPATH_PREFIX)
342: .append(
343: KualiWorkflowUtils.XPATH_ELEMENT_SEPARATOR)
344: .append(
345: KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE)
346: .append(KualiWorkflowUtils.XSTREAM_SAFE_SUFFIX)
347: .toString();
348: finChart = xpath.evaluate(currentXPath, docContent
349: .getDocument());
350: currentXPath = new StringBuffer(
351: KualiWorkflowUtils.XSTREAM_SAFE_PREFIX)
352: .append(
353: KualiWorkflowUtils.XSTREAM_MATCH_ANYWHERE_PREFIX)
354: .append(
355: KualiWorkflowUtils.XML_REPORT_DOC_CONTENT_XPATH_PREFIX)
356: .append(
357: KualiWorkflowUtils.XPATH_ELEMENT_SEPARATOR)
358: .append(KFSPropertyConstants.ACCOUNT_NUMBER)
359: .append(KualiWorkflowUtils.XSTREAM_SAFE_SUFFIX)
360: .toString();
361: finAccount = xpath.evaluate(currentXPath, docContent
362: .getDocument());
363: currentXPath = new StringBuffer(
364: KualiWorkflowUtils.XSTREAM_SAFE_PREFIX)
365: .append(
366: KualiWorkflowUtils.XSTREAM_MATCH_ANYWHERE_PREFIX)
367: .append(
368: KualiWorkflowUtils.XML_REPORT_DOC_CONTENT_XPATH_PREFIX)
369: .append(
370: KualiWorkflowUtils.XPATH_ELEMENT_SEPARATOR)
371: .append(
372: KFSPropertyConstants.FINANCIAL_OBJECT_CODE)
373: .append(KualiWorkflowUtils.XSTREAM_SAFE_SUFFIX)
374: .toString();
375: finObjectCode = xpath.evaluate(currentXPath, docContent
376: .getDocument());
377: currentXPath = new StringBuffer(
378: KualiWorkflowUtils.XSTREAM_SAFE_PREFIX)
379: .append(
380: KualiWorkflowUtils.XSTREAM_MATCH_ANYWHERE_PREFIX)
381: .append(
382: KualiWorkflowUtils.XML_REPORT_DOC_CONTENT_XPATH_PREFIX)
383: .append(
384: KualiWorkflowUtils.XPATH_ELEMENT_SEPARATOR)
385: .append(
386: KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR)
387: .append(KualiWorkflowUtils.XSTREAM_SAFE_SUFFIX)
388: .toString();
389: finFiscalYear = xpath.evaluate(currentXPath, docContent
390: .getDocument());
391: AccountContainer ac = getValidAccountContainer(
392: finFiscalYear, finChart, finAccount,
393: finObjectCode);
394: if (ObjectUtils.isNotNull(ac)) {
395: accounts.add(ac);
396: }
397: } else {
398: // now look at the global documents
399: String docTypeName = docContent.getRouteContext()
400: .getDocument().getDocumentType().getName();
401: if (!KualiWorkflowUtils.isTargetLineOnly(docTypeName)) {
402: currentXPath = KualiWorkflowUtils
403: .xstreamSafeXPath(KualiWorkflowUtils.XSTREAM_MATCH_ANYWHERE_PREFIX
404: + KualiWorkflowUtils
405: .getSourceAccountingLineClassName(docTypeName));
406: NodeList sourceLineNodes = (NodeList) xpath
407: .evaluate(currentXPath, docContent
408: .getDocument(),
409: XPathConstants.NODESET);
410: accounts.addAll(getAccountContainers(xpath,
411: sourceLineNodes));
412: }
413: if (!KualiWorkflowUtils.isSourceLineOnly(docTypeName)) {
414: currentXPath = KualiWorkflowUtils
415: .xstreamSafeXPath(KualiWorkflowUtils.XSTREAM_MATCH_ANYWHERE_PREFIX
416: + KualiWorkflowUtils
417: .getTargetAccountingLineClassName(docTypeName));
418: NodeList targetLineNodes = (NodeList) xpath
419: .evaluate(currentXPath, docContent
420: .getDocument(),
421: XPathConstants.NODESET);
422: accounts.addAll(getAccountContainers(xpath,
423: targetLineNodes));
424: }
425: }
426: return accounts;
427: } catch (XPathExpressionException e) {
428: throw new RuntimeException(
429: "XPath Exception caught executing expression: "
430: + currentXPath, e);
431: }
432: }
433:
434: private Set<AccountContainer> getAccountContainers(XPath xpath,
435: NodeList accountingLineNodes) {
436: String currentXPath = null;
437: try {
438: Set<AccountContainer> accountContainers = new HashSet();
439: for (int i = 0; i < accountingLineNodes.getLength(); i++) {
440: Node accountingLineNode = accountingLineNodes.item(i);
441: currentXPath = KualiWorkflowUtils.XSTREAM_MATCH_RELATIVE_PREFIX
442: + KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE;
443: String finChart = xpath.evaluate(currentXPath,
444: accountingLineNode);
445: currentXPath = KualiWorkflowUtils.XSTREAM_MATCH_RELATIVE_PREFIX
446: + KFSPropertyConstants.ACCOUNT_NUMBER;
447: String finAccount = xpath.evaluate(currentXPath,
448: accountingLineNode);
449: currentXPath = KualiWorkflowUtils.XSTREAM_MATCH_RELATIVE_PREFIX
450: + KFSPropertyConstants.FINANCIAL_OBJECT_CODE;
451: String finObjectCode = xpath.evaluate(currentXPath,
452: accountingLineNode);
453: currentXPath = KualiWorkflowUtils.XSTREAM_MATCH_RELATIVE_PREFIX
454: + KFSPropertyConstants.POSTING_YEAR;
455: String finFiscalYear = xpath.evaluate(currentXPath,
456: accountingLineNode);
457: AccountContainer ac = getValidAccountContainer(
458: finFiscalYear, finChart, finAccount,
459: finObjectCode);
460: if (ObjectUtils.isNotNull(ac)) {
461: accountContainers.add(ac);
462: }
463: }
464: return accountContainers;
465: } catch (XPathExpressionException e) {
466: throw new RuntimeException(
467: "XPath Exception caught executing expression: "
468: + currentXPath, e);
469: }
470: }
471:
472: private AccountContainer getValidAccountContainer(
473: String finFiscalYear, String finChart, String finAccount,
474: String finObjectCode) {
475: AccountContainer ac = getPotentialAccountContainer(
476: finFiscalYear, finChart, finAccount, finObjectCode);
477: if (ObjectUtils.isNotNull(ac)) {
478: String fiscalYearLabel = KualiWorkflowUtils
479: .getBusinessObjectAttributeLabel(Options.class,
480: KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR);
481: String chartCodeLabel = KualiWorkflowUtils
482: .getBusinessObjectAttributeLabel(Chart.class,
483: KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE);
484: String accountNumberLabel = KualiWorkflowUtils
485: .getBusinessObjectAttributeLabel(Account.class,
486: KFSPropertyConstants.ACCOUNT_NUMBER);
487: String objectCodeLabel = KualiWorkflowUtils
488: .getBusinessObjectAttributeLabel(ObjectCode.class,
489: KFSPropertyConstants.FINANCIAL_OBJECT_CODE);
490: if (ObjectUtils.isNull(ac.account)) {
491: String errorMsg = "Valid Account not found for values "
492: + chartCodeLabel + ": " + finChart + " and "
493: + accountNumberLabel + ":" + finAccount;
494: LOG.error(errorMsg);
495: throw new RuntimeException(errorMsg);
496: }
497: if (ObjectUtils.isNull(ac.objectCode)) {
498: String errorMsg = "Valid Object Code not found for values "
499: + fiscalYearLabel
500: + ": "
501: + finFiscalYear
502: + ", "
503: + chartCodeLabel
504: + ": "
505: + finChart
506: + ", and "
507: + objectCodeLabel + ": " + finObjectCode;
508: LOG.error(errorMsg);
509: throw new RuntimeException(errorMsg);
510: }
511: }
512: return ac;
513: }
514:
515: /**
516: * @param finFiscalYear - university fiscal year value
517: * @param finChart - chart code value
518: * @param finAccount - account number value
519: * @param finObjectCode - object code value
520: * @return null if one of the variables required is missing or the AccountContainer object holding the potentially valid Account
521: * object and the potentially valid Object Code object. One or both may or may not be null themselves.
522: */
523: private AccountContainer getPotentialAccountContainer(
524: String finFiscalYear, String finChart, String finAccount,
525: String finObjectCode) {
526: if (StringUtils.isNotEmpty(finChart)
527: && StringUtils.isNotEmpty(finAccount)
528: && StringUtils.isNotEmpty(finObjectCode)
529: && StringUtils.isNotEmpty(finFiscalYear)) {
530: Account testAccount = SpringContext.getBean(
531: AccountService.class).getByPrimaryIdWithCaching(
532: finChart, finAccount);
533: ObjectCode testObjectCode = SpringContext.getBean(
534: ObjectCodeService.class).getByPrimaryId(
535: Integer.valueOf(finFiscalYear), finChart,
536: finObjectCode);
537: return new AccountContainer(testAccount, testObjectCode);
538: }
539: return null;
540: }
541:
542: public List validateRoutingData(Map paramMap) {
543: List errors = new ArrayList();
544: String fiscalYearLabel = KualiWorkflowUtils
545: .getBusinessObjectAttributeLabel(Options.class,
546: KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR);
547: setFiscalYear(LookupUtils.forceUppercase(Options.class,
548: KFSPropertyConstants.UNIVERSITY_FISCAL_YEAR,
549: (String) paramMap.get(UNIVERSITY_FISCAL_YEAR_KEY)));
550: String chartCodeLabel = KualiWorkflowUtils
551: .getBusinessObjectAttributeLabel(Chart.class,
552: KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE);
553: setChartCode(LookupUtils.forceUppercase(Chart.class,
554: KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE,
555: (String) paramMap.get(CHART_CODE_KEY)));
556: String accountNumberLabel = KualiWorkflowUtils
557: .getBusinessObjectAttributeLabel(Account.class,
558: KFSPropertyConstants.ACCOUNT_NUMBER);
559: setAccountNumber(LookupUtils.forceUppercase(Account.class,
560: KFSPropertyConstants.ACCOUNT_NUMBER, (String) paramMap
561: .get(ACCOUNT_NUMBER_KEY)));
562: String objectCodeLabel = KualiWorkflowUtils
563: .getBusinessObjectAttributeLabel(ObjectCode.class,
564: KFSPropertyConstants.FINANCIAL_OBJECT_CODE);
565: setObjectCode(LookupUtils.forceUppercase(ObjectCode.class,
566: KFSPropertyConstants.FINANCIAL_OBJECT_CODE,
567: (String) paramMap.get(OBJECT_CODE_KEY)));
568: AccountContainer ac = getPotentialAccountContainer(
569: getFiscalYear(), getChartCode(), getAccountNumber(),
570: getObjectCode());
571: if (ObjectUtils.isNotNull(ac)) {
572: if (ObjectUtils.isNull(ac.account)) {
573: String errorMessage = "Valid Account not found for values "
574: + chartCodeLabel
575: + ": "
576: + getChartCode()
577: + " and "
578: + accountNumberLabel
579: + ":"
580: + getAccountNumber();
581: errors.add(new WorkflowServiceErrorImpl(errorMessage,
582: "routetemplate.xmlattribute.error",
583: errorMessage));
584: }
585: if (ObjectUtils.isNull(ac.objectCode)) {
586: String errorMessage = "Valid Object Code not found for values "
587: + fiscalYearLabel
588: + ": "
589: + getFiscalYear()
590: + ", "
591: + chartCodeLabel
592: + ": "
593: + getChartCode()
594: + ", and "
595: + objectCodeLabel
596: + ": "
597: + getObjectCode();
598: errors.add(new WorkflowServiceErrorImpl(errorMessage,
599: "routetemplate.xmlattribute.error",
600: errorMessage));
601: }
602: } else {
603: // if the account container is null then we are missing at least one value to use in the lookups
604: String errorMessage = "All values must be entered in order to continue";
605: errors.add(new WorkflowServiceErrorImpl(errorMessage,
606: "routetemplate.xmlattribute.error", errorMessage));
607: }
608: return errors;
609: }
610:
611: public List validateRuleData(Map paramMap) {
612: List errors = new ArrayList();
613: setSubFundGroupCode(LookupUtils.forceUppercase(
614: SubFundGroup.class,
615: KFSPropertyConstants.SUB_FUND_GROUP_CODE,
616: (String) paramMap.get(SUB_FUND_GROUP_CODE_KEY)));
617: if (isRequired() && StringUtils.isBlank(getSubFundGroupCode())) {
618: // value is required but is also blank
619: String errorMessage = KualiWorkflowUtils
620: .getBusinessObjectAttributeLabel(
621: SubFundGroup.class,
622: KFSPropertyConstants.SUB_FUND_GROUP_CODE)
623: + " is required";
624: errors.add(new WorkflowServiceErrorImpl(errorMessage,
625: "routetemplate.xmlattribute.error", errorMessage));
626: } else if (isRequired()
627: && StringUtils.isNotBlank(getSubFundGroupCode())
628: && KFSConstants.WILDCARD_CHARACTER
629: .equalsIgnoreCase(getSubFundGroupCode())) {
630: // value is required but entered value is the wildcard character
631: setSubFundGroupCode(null);
632: } else if (StringUtils.isNotBlank(getSubFundGroupCode())) {
633: // value is not blank so check value for validity of value
634: Map formProps = new HashMap();
635: formProps.put(KFSPropertyConstants.SUB_FUND_GROUP_CODE,
636: getSubFundGroupCode());
637: Collection subFundGroups = SpringContext.getBean(
638: LookupService.class)
639: .findCollectionBySearchUnbounded(
640: SubFundGroup.class, formProps);
641: if (subFundGroups.isEmpty()) {
642: String errorMessage = KualiWorkflowUtils
643: .getBusinessObjectAttributeLabel(
644: SubFundGroup.class,
645: KFSPropertyConstants.SUB_FUND_GROUP_CODE)
646: + " value does not correspond to any valid entries in the system";
647: errors.add(new WorkflowServiceErrorImpl(errorMessage,
648: "routetemplate.xmlattribute.error",
649: errorMessage));
650: }
651: }
652: return errors;
653: }
654:
655: /**
656: * Gets the accountNumber attribute.
657: *
658: * @return Returns the accountNumber.
659: */
660: public String getAccountNumber() {
661: return accountNumber;
662: }
663:
664: /**
665: * Sets the accountNumber attribute value.
666: *
667: * @param accountNumber The accountNumber to set.
668: */
669: public void setAccountNumber(String accountNumber) {
670: this .accountNumber = accountNumber;
671: }
672:
673: /**
674: * Gets the chartCode attribute.
675: *
676: * @return Returns the chartCode.
677: */
678: public String getChartCode() {
679: return chartCode;
680: }
681:
682: /**
683: * Sets the chartCode attribute value.
684: *
685: * @param chartCode The chartCode to set.
686: */
687: public void setChartCode(String chartCode) {
688: this .chartCode = chartCode;
689: }
690:
691: /**
692: * Gets the fiscalYear attribute.
693: *
694: * @return Returns the fiscalYear.
695: */
696: public String getFiscalYear() {
697: return fiscalYear;
698: }
699:
700: /**
701: * Sets the fiscalYear attribute value.
702: *
703: * @param fiscalYear The fiscalYear to set.
704: */
705: public void setFiscalYear(String fiscalYear) {
706: this .fiscalYear = fiscalYear;
707: }
708:
709: /**
710: * Gets the objectCode attribute.
711: *
712: * @return Returns the objectCode.
713: */
714: public String getObjectCode() {
715: return objectCode;
716: }
717:
718: /**
719: * Sets the objectCode attribute value.
720: *
721: * @param objectCode The objectCode to set.
722: */
723: public void setObjectCode(String objectCode) {
724: this .objectCode = objectCode;
725: }
726:
727: /**
728: * Gets the required attribute.
729: *
730: * @return Returns the required.
731: */
732: public boolean isRequired() {
733: return required;
734: }
735:
736: /**
737: * Sets the required attribute value.
738: *
739: * @param required The required to set.
740: */
741: public void setRequired(boolean required) {
742: this .required = required;
743: }
744:
745: /**
746: * Gets the subFundGroupCode attribute.
747: *
748: * @return Returns the subFundGroupCode.
749: */
750: public String getSubFundGroupCode() {
751: return subFundGroupCode;
752: }
753:
754: /**
755: * Sets the subFundGroupCode attribute value.
756: *
757: * @param subFundGroupCode The subFundGroupCode to set.
758: */
759: public void setSubFundGroupCode(String subFundGroupCode) {
760: this .subFundGroupCode = subFundGroupCode;
761: }
762:
763: private static class AccountContainer {
764: public Account account;
765: public ObjectCode objectCode;
766:
767: public AccountContainer(Account account, ObjectCode objectCode) {
768: super();
769: this.account = account;
770: this.objectCode = objectCode;
771: }
772: }
773: }
|