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.attribute;
017:
018: import java.util.ArrayList;
019: import java.util.HashMap;
020: import java.util.HashSet;
021: import java.util.Iterator;
022: import java.util.List;
023: import java.util.Map;
024: import java.util.Set;
025:
026: import javax.xml.xpath.XPath;
027: import javax.xml.xpath.XPathConstants;
028:
029: import org.apache.commons.lang.StringUtils;
030: import org.apache.log4j.Logger;
031: import org.kuali.core.lookup.LookupUtils;
032: import org.kuali.kfs.KFSPropertyConstants;
033: import org.kuali.kfs.context.SpringContext;
034: import org.kuali.module.chart.bo.SubAccount;
035: import org.kuali.module.chart.service.SubAccountService;
036: import org.kuali.workflow.KualiWorkflowUtils;
037: import org.w3c.dom.Node;
038: import org.w3c.dom.NodeList;
039:
040: import edu.iu.uis.eden.WorkflowServiceErrorImpl;
041: import edu.iu.uis.eden.doctype.DocumentType;
042: import edu.iu.uis.eden.engine.RouteContext;
043: import edu.iu.uis.eden.lookupable.Row;
044: import edu.iu.uis.eden.plugin.attributes.MassRuleAttribute;
045: import edu.iu.uis.eden.plugin.attributes.WorkflowAttribute;
046: import edu.iu.uis.eden.routeheader.DocumentContent;
047: import edu.iu.uis.eden.routetemplate.RuleBaseValues;
048: import edu.iu.uis.eden.routetemplate.RuleExtension;
049: import edu.iu.uis.eden.routetemplate.RuleExtensionValue;
050: import edu.iu.uis.eden.util.Utilities;
051:
052: /**
053: * This class...
054: */
055: public class KualiSubAccountAttribute implements WorkflowAttribute,
056: MassRuleAttribute {
057:
058: static final long serialVersionUID = 1000;
059:
060: private static Logger LOG = Logger
061: .getLogger(KualiAccountAttribute.class);
062:
063: public static final String FIN_COA_CD_KEY = "fin_coa_cd";
064:
065: public static final String ACCOUNT_NBR_KEY = "account_nbr";
066:
067: public static final String ORG_CD_KEY = "org_cd";
068:
069: public static final String SUB_ACCOUNT_NBR_KEY = "sub_acct_nbr";
070:
071: private static final String SUB_ACCOUNT_ATTRIBUTE = "KUALI_SUB_ACCOUNT_ATTRIBUTE";
072:
073: private static final String DOCUMENT_SUB_ACCOUNT_VALUES_KEY = "subAccounts";
074:
075: // defined here so field creation matches rule errors
076: private static final Class SUB_ACCOUNT_NUMBER_FIELD_CLASS = SubAccount.class;
077: private static final String SUB_ACCOUNT_NUMBER_FIELD_PROPERTY = KFSPropertyConstants.SUB_ACCOUNT_NUMBER;
078: private static final Class ACCOUNT_NUMBER_FIELD_CLASS = SUB_ACCOUNT_NUMBER_FIELD_CLASS;
079: private static final String ACCOUNT_NUMBER_FIELD_PROPERTY = KFSPropertyConstants.ACCOUNT_NUMBER;
080: private static final Class ORG_CODE_FIELD_CLASS = SUB_ACCOUNT_NUMBER_FIELD_CLASS;
081: private static final String ORG_CODE_FIELD_PROPERTY = KFSPropertyConstants.FIN_REPORT_ORGANIZATION_CODE;
082: private static final Class CHART_CODE_FIELD_CLASS = SUB_ACCOUNT_NUMBER_FIELD_CLASS;
083: private static final String CHART_CODE_FIELD_PROPERTY = KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE;
084:
085: private String finCoaCd;
086: private String accountNbr;
087: private String subAccountNbr;
088: private String orgCd;
089:
090: private boolean required;
091:
092: private List ruleRows;
093:
094: private List routingDataRows;
095:
096: /**
097: * No arg constructor
098: */
099: public KualiSubAccountAttribute() {
100: ruleRows = new ArrayList();
101: ruleRows.add(KualiWorkflowUtils.buildTextRowWithLookup(
102: CHART_CODE_FIELD_CLASS, CHART_CODE_FIELD_PROPERTY,
103: FIN_COA_CD_KEY));
104: Map fieldConversionMap = new HashMap();
105: fieldConversionMap.put(CHART_CODE_FIELD_PROPERTY,
106: FIN_COA_CD_KEY);
107: ruleRows.add(KualiWorkflowUtils.buildTextRowWithLookup(
108: ACCOUNT_NUMBER_FIELD_CLASS,
109: ACCOUNT_NUMBER_FIELD_PROPERTY, ACCOUNT_NBR_KEY,
110: fieldConversionMap));
111: ruleRows.add(KualiWorkflowUtils.buildTextRowWithLookup(
112: ORG_CODE_FIELD_CLASS, ORG_CODE_FIELD_PROPERTY,
113: ORG_CD_KEY, fieldConversionMap));
114: fieldConversionMap.put(ACCOUNT_NUMBER_FIELD_PROPERTY,
115: ACCOUNT_NBR_KEY);
116: ruleRows.add(KualiWorkflowUtils.buildTextRowWithLookup(
117: SUB_ACCOUNT_NUMBER_FIELD_CLASS,
118: SUB_ACCOUNT_NUMBER_FIELD_PROPERTY, SUB_ACCOUNT_NBR_KEY,
119: fieldConversionMap));
120:
121: routingDataRows = new ArrayList();
122: routingDataRows.add(KualiWorkflowUtils.buildTextRowWithLookup(
123: CHART_CODE_FIELD_CLASS, CHART_CODE_FIELD_PROPERTY,
124: FIN_COA_CD_KEY));
125: fieldConversionMap = new HashMap();
126: fieldConversionMap.put(CHART_CODE_FIELD_PROPERTY,
127: FIN_COA_CD_KEY);
128: routingDataRows.add(KualiWorkflowUtils.buildTextRowWithLookup(
129: ACCOUNT_NUMBER_FIELD_CLASS,
130: ACCOUNT_NUMBER_FIELD_PROPERTY, ACCOUNT_NBR_KEY));
131: routingDataRows
132: .add(KualiWorkflowUtils.buildTextRowWithLookup(
133: SUB_ACCOUNT_NUMBER_FIELD_CLASS,
134: SUB_ACCOUNT_NUMBER_FIELD_PROPERTY,
135: SUB_ACCOUNT_NBR_KEY));
136: }
137:
138: /**
139: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#getDocContent()
140: */
141: public String getDocContent() {
142: if (Utilities.isEmpty(getFinCoaCd())
143: || Utilities.isEmpty(getAccountNbr())
144: || Utilities.isEmpty(getSubAccountNbr())) {
145: return "";
146: }
147: StringBuffer chartCode = new StringBuffer()
148: .append(
149: "<"
150: + KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE
151: + ">")
152: .append(getFinCoaCd())
153: .append(
154: "</"
155: + KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE
156: + ">");
157: StringBuffer accountNumber = new StringBuffer().append(
158: "<" + KFSPropertyConstants.ACCOUNT_NUMBER + ">")
159: .append(getAccountNbr()).append(
160: "</" + KFSPropertyConstants.ACCOUNT_NUMBER
161: + ">");
162: StringBuffer subAccountNumber = new StringBuffer().append(
163: "<" + KFSPropertyConstants.SUB_ACCOUNT_NUMBER + ">")
164: .append(getSubAccountNbr()).append(
165: "</" + KFSPropertyConstants.SUB_ACCOUNT_NUMBER
166: + ">");
167: return new StringBuffer(
168: KualiWorkflowUtils.XML_REPORT_DOC_CONTENT_PREFIX)
169: .append(chartCode)
170: .append(accountNumber)
171: .append(subAccountNumber)
172: .append(
173: KualiWorkflowUtils.XML_REPORT_DOC_CONTENT_SUFFIX)
174: .toString();
175: }
176:
177: /**
178: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#getRoutingDataRows()
179: */
180: public List<Row> getRoutingDataRows() {
181: return routingDataRows;
182: }
183:
184: /**
185: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#getRuleExtensionValues()
186: */
187: public List<RuleExtensionValue> getRuleExtensionValues() {
188: List extensions = new ArrayList();
189: extensions.add(new RuleExtensionValue(FIN_COA_CD_KEY,
190: getFinCoaCd()));
191: if (!StringUtils.isBlank(getAccountNbr())) {
192: extensions.add(new RuleExtensionValue(ACCOUNT_NBR_KEY,
193: getAccountNbr()));
194: }
195: if (!StringUtils.isBlank(getOrgCd())) {
196: extensions.add(new RuleExtensionValue(ORG_CD_KEY,
197: getOrgCd()));
198: }
199: extensions.add(new RuleExtensionValue(SUB_ACCOUNT_NBR_KEY,
200: getSubAccountNbr()));
201: return extensions;
202: }
203:
204: /**
205: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#getRuleRows()
206: */
207: public List<Row> getRuleRows() {
208: return ruleRows;
209: }
210:
211: /**
212: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#isRequired()
213: */
214: public boolean isRequired() {
215: return required;
216: }
217:
218: /**
219: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#setRequired(boolean)
220: */
221: public void setRequired(boolean required) {
222: this .required = required;
223: }
224:
225: /**
226: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#validateRoutingData(java.util.Map)
227: */
228: public List validateRoutingData(Map paramMap) {
229: return validateSubAccountValues(paramMap);
230: }
231:
232: /**
233: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#validateRuleData(java.util.Map)
234: */
235: public List validateRuleData(Map paramMap) {
236: return validateSubAccountValues(paramMap);
237: }
238:
239: private List validateSubAccountValues(Map paramMap) {
240: setAccountNbr(LookupUtils.forceUppercase(SubAccount.class,
241: KFSPropertyConstants.ACCOUNT_NUMBER, (String) paramMap
242: .get(ACCOUNT_NBR_KEY)));
243: setOrgCd(LookupUtils.forceUppercase(SubAccount.class,
244: KFSPropertyConstants.FIN_REPORT_ORGANIZATION_CODE,
245: (String) paramMap.get(ORG_CD_KEY)));
246: String chartFieldName = KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE;
247: if (StringUtils.isBlank(getAccountNbr())) {
248: chartFieldName = KFSPropertyConstants.FINANCIAL_REPORT_CHART_CODE;
249: }
250: setFinCoaCd(LookupUtils.forceUppercase(SubAccount.class,
251: chartFieldName, (String) paramMap.get(FIN_COA_CD_KEY)));
252: setSubAccountNbr(LookupUtils.forceUppercase(SubAccount.class,
253: KFSPropertyConstants.SUB_ACCOUNT_NUMBER,
254: (String) paramMap.get(SUB_ACCOUNT_NBR_KEY)));
255: List errors = new ArrayList();
256: if ((!isRequired())
257: && (StringUtils.isBlank(getFinCoaCd())
258: && StringUtils.isBlank(getSubAccountNbr()) && (StringUtils
259: .isBlank(getAccountNbr()) && StringUtils
260: .isBlank(getOrgCd())))) {
261: // attribute is not required and no fields are filled in
262: return new ArrayList();
263: } else if ((isRequired())
264: && (StringUtils.isBlank(getFinCoaCd())
265: || StringUtils.isBlank(getSubAccountNbr()) || ((StringUtils
266: .isBlank(getAccountNbr())) && (StringUtils
267: .isBlank(getOrgCd()))))) {
268: // attribute is required and at least one needed field is blank
269: String error = KualiWorkflowUtils
270: .getBusinessObjectAttributeLabel(
271: CHART_CODE_FIELD_CLASS,
272: CHART_CODE_FIELD_PROPERTY)
273: + ", "
274: + KualiWorkflowUtils
275: .getBusinessObjectAttributeLabel(
276: SUB_ACCOUNT_NUMBER_FIELD_CLASS,
277: SUB_ACCOUNT_NUMBER_FIELD_PROPERTY)
278: + ", and one of "
279: + KualiWorkflowUtils
280: .getBusinessObjectAttributeLabel(
281: ACCOUNT_NUMBER_FIELD_CLASS,
282: ACCOUNT_NUMBER_FIELD_PROPERTY)
283: + " or "
284: + KualiWorkflowUtils
285: .getBusinessObjectAttributeLabel(
286: ORG_CODE_FIELD_CLASS,
287: ORG_CODE_FIELD_PROPERTY)
288: + " is required";
289: errors.add(new WorkflowServiceErrorImpl(error,
290: "routetemplate.xmlattribute.error", error));
291: } else if (StringUtils.isNotBlank(getAccountNbr())
292: && StringUtils.isNotBlank(getOrgCd())) {
293: // you cannot have both fields filled in
294: String error = KualiWorkflowUtils
295: .getBusinessObjectAttributeLabel(
296: ACCOUNT_NUMBER_FIELD_CLASS,
297: ACCOUNT_NUMBER_FIELD_PROPERTY)
298: + " and "
299: + KualiWorkflowUtils
300: .getBusinessObjectAttributeLabel(
301: ORG_CODE_FIELD_CLASS,
302: ORG_CODE_FIELD_PROPERTY)
303: + " cannot be entered together. You must enter a value for "
304: + KualiWorkflowUtils
305: .getBusinessObjectAttributeLabel(
306: ACCOUNT_NUMBER_FIELD_CLASS,
307: ACCOUNT_NUMBER_FIELD_PROPERTY)
308: + " or "
309: + KualiWorkflowUtils
310: .getBusinessObjectAttributeLabel(
311: ORG_CODE_FIELD_CLASS,
312: ORG_CODE_FIELD_PROPERTY)
313: + " but not both";
314: errors.add(new WorkflowServiceErrorImpl(error,
315: "routetemplate.xmlattribute.error", error));
316: } else {
317: // may or may not be required but we have values to check
318: List subAccounts = getSubAccounts(getFinCoaCd(),
319: getAccountNbr(), getOrgCd(), getSubAccountNbr());
320: if ((subAccounts == null) || (subAccounts.isEmpty())) {
321: if (StringUtils.isNotBlank(getAccountNbr())) {
322: String error = KualiWorkflowUtils
323: .getBusinessObjectAttributeLabel(
324: CHART_CODE_FIELD_CLASS,
325: CHART_CODE_FIELD_PROPERTY)
326: + ", "
327: + KualiWorkflowUtils
328: .getBusinessObjectAttributeLabel(
329: ACCOUNT_NUMBER_FIELD_CLASS,
330: ACCOUNT_NUMBER_FIELD_PROPERTY)
331: + ", and "
332: + KualiWorkflowUtils
333: .getBusinessObjectAttributeLabel(
334: SUB_ACCOUNT_NUMBER_FIELD_CLASS,
335: SUB_ACCOUNT_NUMBER_FIELD_PROPERTY)
336: + " combination is invalid";
337: errors.add(new WorkflowServiceErrorImpl(error,
338: "routetemplate.xmlattribute.error", error));
339: } else {
340: String error = KualiWorkflowUtils
341: .getBusinessObjectAttributeLabel(
342: CHART_CODE_FIELD_CLASS,
343: CHART_CODE_FIELD_PROPERTY)
344: + ", "
345: + KualiWorkflowUtils
346: .getBusinessObjectAttributeLabel(
347: ORG_CODE_FIELD_CLASS,
348: ORG_CODE_FIELD_PROPERTY)
349: + ", and "
350: + KualiWorkflowUtils
351: .getBusinessObjectAttributeLabel(
352: SUB_ACCOUNT_NUMBER_FIELD_CLASS,
353: SUB_ACCOUNT_NUMBER_FIELD_PROPERTY)
354: + " combination is invalid";
355: errors.add(new WorkflowServiceErrorImpl(error,
356: "routetemplate.xmlattribute.error", error));
357: }
358: }
359: }
360: return errors;
361: }
362:
363: private List getSubAccounts(String chartCode, String accountNumber,
364: String orgCode, String subAccountNumer) {
365: List subAccounts = new ArrayList();
366: SubAccountService subAccountService = SpringContext
367: .getBean(SubAccountService.class);
368: if (StringUtils.isNotBlank(accountNumber)) {
369: SubAccount subAccount = subAccountService
370: .getByPrimaryIdWithCaching(chartCode,
371: accountNumber, subAccountNumer);
372: if (subAccount != null) {
373: subAccounts.add(subAccount);
374: }
375: } else if (StringUtils.isNotBlank(orgCode)) {
376: List testSubAccounts = subAccountService
377: .getSubAccountsByReportsToOrganization(chartCode,
378: orgCode, subAccountNumer);
379: if ((testSubAccounts != null)
380: && (!(testSubAccounts.isEmpty()))) {
381: subAccounts.addAll(testSubAccounts);
382: }
383: }
384: return subAccounts;
385: }
386:
387: /**
388: * Actual matching logic is handled in filterNonMatchingRules where the List of rules is narrowed down to those that should
389: * fire.
390: *
391: * @see #filterNonMatchingRules(RouteContext, List)
392: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#isMatch(java.lang.String, java.util.List)
393: */
394: public boolean isMatch(DocumentContent docContent,
395: List ruleExtensions) {
396: return true;
397: }
398:
399: /**
400: * Filters the List of Rules by those that will match.
401: */
402: public List filterNonMatchingRules(RouteContext routeContext,
403: List rules) {
404: List filteredRules = new ArrayList();
405: DocumentType documentType = routeContext.getDocument()
406: .getDocumentType();
407: Set subAccountValues = populateFromDocContent(documentType
408: .getName(), routeContext.getDocumentContent(),
409: routeContext);
410: for (Iterator iterator = rules.iterator(); iterator.hasNext();) {
411: RuleBaseValues rule = (RuleBaseValues) iterator.next();
412: List ruleExtensions = rule.getRuleExtensions();
413: setAccountNbr(LookupUtils.forceUppercase(SubAccount.class,
414: KFSPropertyConstants.ACCOUNT_NUMBER,
415: getRuleExtentionValue(ACCOUNT_NBR_KEY,
416: ruleExtensions)));
417: setOrgCd(LookupUtils.forceUppercase(SubAccount.class,
418: KFSPropertyConstants.FIN_REPORT_ORGANIZATION_CODE,
419: getRuleExtentionValue(ORG_CD_KEY, ruleExtensions)));
420: String chartFieldName = KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE;
421: if (StringUtils.isBlank(getAccountNbr())) {
422: chartFieldName = KFSPropertyConstants.FINANCIAL_REPORT_CHART_CODE;
423: }
424: setFinCoaCd(LookupUtils.forceUppercase(SubAccount.class,
425: chartFieldName, getRuleExtentionValue(
426: FIN_COA_CD_KEY, ruleExtensions)));
427: setSubAccountNbr(LookupUtils.forceUppercase(
428: SubAccount.class,
429: KFSPropertyConstants.SUB_ACCOUNT_NUMBER,
430: getRuleExtentionValue(SUB_ACCOUNT_NBR_KEY,
431: ruleExtensions)));
432: if (ruleMatches(subAccountValues)) {
433: filteredRules.add(rule);
434: }
435: }
436: return filteredRules;
437: }
438:
439: /**
440: * Determines if the given Rule matches the document data by comparing the values.
441: */
442: protected boolean ruleMatches(Set subAccountValues) {
443: for (Iterator iter = subAccountValues.iterator(); iter
444: .hasNext();) {
445: SubAccount subAccount = (SubAccount) iter.next();
446: if (StringUtils.isNotBlank(getOrgCd())) {
447: // check based on org
448: if ((StringUtils.equals(subAccount
449: .getFinancialReportChartCode(), getFinCoaCd()))
450: && (StringUtils.equals(subAccount
451: .getFinReportOrganizationCode(),
452: getOrgCd()))
453: && (StringUtils.equals(subAccount
454: .getSubAccountNumber(),
455: getSubAccountNbr()))) {
456: return true;
457: }
458: } else {
459: // check based on account
460: if ((StringUtils.equals(subAccount
461: .getChartOfAccountsCode(), getFinCoaCd()))
462: && (StringUtils.equals(subAccount
463: .getAccountNumber(), getAccountNbr()))
464: && (StringUtils.equals(subAccount
465: .getSubAccountNumber(),
466: getSubAccountNbr()))) {
467: return true;
468: }
469: }
470: }
471: return false;
472: }
473:
474: private String getRuleExtentionValue(String key, List ruleExtensions) {
475: for (Iterator iter = ruleExtensions.iterator(); iter.hasNext();) {
476: RuleExtension extension = (RuleExtension) iter.next();
477: if (extension.getRuleTemplateAttribute().getRuleAttribute()
478: .getClassName().equals(this .getClass().getName())) {
479: for (Iterator iterator = extension.getExtensionValues()
480: .iterator(); iterator.hasNext();) {
481: RuleExtensionValue value = (RuleExtensionValue) iterator
482: .next();
483: if (value.getKey().equals(key)) {
484: return value.getValue();
485: }
486: }
487: }
488: }
489: return null;
490: }
491:
492: /**
493: * this method will take the document content, and populate a list of SubAccount objects from the document values
494: *
495: * @param docContent
496: * @return a list of SubAccount objects that are contained in the doc
497: */
498: protected Set populateFromDocContent(String docTypeName,
499: DocumentContent docContent, RouteContext routeContext) {
500: Set subAccountValues = null;
501: if (routeContext.getParameters().containsKey(
502: DOCUMENT_SUB_ACCOUNT_VALUES_KEY)) {
503: subAccountValues = (Set) routeContext.getParameters().get(
504: DOCUMENT_SUB_ACCOUNT_VALUES_KEY);
505: } else {
506: subAccountValues = new HashSet();
507: XPath xpath = KualiWorkflowUtils.getXPath(docContent
508: .getDocument());
509: try {
510: String chart = null;
511: String account = null;
512: String org = null;
513: String subAccount = null;
514: String reportMatchAnywhereExpressionPrefix = new StringBuffer(
515: KualiWorkflowUtils.XSTREAM_MATCH_ANYWHERE_PREFIX)
516: .append(
517: KualiWorkflowUtils.XML_REPORT_DOC_CONTENT_XPATH_PREFIX)
518: .toString();
519: boolean isReport = ((Boolean) xpath
520: .evaluate(
521: new StringBuffer(
522: KualiWorkflowUtils.XSTREAM_SAFE_PREFIX)
523: .append(
524: KualiWorkflowUtils.XSTREAM_MATCH_ANYWHERE_PREFIX)
525: .append(
526: KualiWorkflowUtils.XML_REPORT_DOC_CONTENT_XPATH_PREFIX)
527: .append(
528: KualiWorkflowUtils.XSTREAM_SAFE_SUFFIX)
529: .toString(), docContent
530: .getDocument(),
531: XPathConstants.BOOLEAN)).booleanValue();
532: if (isReport) {
533: account = xpath
534: .evaluate(
535: new StringBuffer(
536: KualiWorkflowUtils.XSTREAM_SAFE_PREFIX)
537: .append(
538: reportMatchAnywhereExpressionPrefix)
539: .append(
540: KualiWorkflowUtils.XPATH_ELEMENT_SEPARATOR)
541: .append(
542: KFSPropertyConstants.ACCOUNT_NUMBER)
543: .append(
544: KualiWorkflowUtils.XSTREAM_SAFE_SUFFIX)
545: .toString(), docContent
546: .getDocument());
547: org = xpath
548: .evaluate(
549: new StringBuffer(
550: KualiWorkflowUtils.XSTREAM_SAFE_PREFIX)
551: .append(
552: reportMatchAnywhereExpressionPrefix)
553: .append(
554: KualiWorkflowUtils.XPATH_ELEMENT_SEPARATOR)
555: .append(
556: KFSPropertyConstants.ORGANIZATION_CODE)
557: .append(
558: KualiWorkflowUtils.XSTREAM_SAFE_SUFFIX)
559: .toString(), docContent
560: .getDocument());
561: subAccount = xpath
562: .evaluate(
563: new StringBuffer(
564: KualiWorkflowUtils.XSTREAM_SAFE_PREFIX)
565: .append(
566: reportMatchAnywhereExpressionPrefix)
567: .append(
568: KualiWorkflowUtils.XPATH_ELEMENT_SEPARATOR)
569: .append(
570: KFSPropertyConstants.SUB_ACCOUNT_NUMBER)
571: .append(
572: KualiWorkflowUtils.XSTREAM_SAFE_SUFFIX)
573: .toString(), docContent
574: .getDocument());
575: String chartFieldName = KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE;
576: if (StringUtils.isBlank(account)) {
577: chartFieldName = KFSPropertyConstants.FINANCIAL_REPORT_CHART_CODE;
578: }
579: chart = xpath
580: .evaluate(
581: new StringBuffer(
582: KualiWorkflowUtils.XSTREAM_SAFE_PREFIX)
583: .append(
584: reportMatchAnywhereExpressionPrefix)
585: .append(
586: KualiWorkflowUtils.XPATH_ELEMENT_SEPARATOR)
587: .append(chartFieldName)
588: .append(
589: KualiWorkflowUtils.XSTREAM_SAFE_SUFFIX)
590: .toString(), docContent
591: .getDocument());
592: subAccountValues.addAll(attemptSubAccountRetrieval(
593: chart, account, org, subAccount));
594: } else {
595: String xpathExp = null;
596: if (KualiWorkflowUtils
597: .isSourceLineOnly(docTypeName)) {
598: xpathExp = new StringBuffer(
599: KualiWorkflowUtils.XSTREAM_SAFE_PREFIX)
600: .append(
601: KualiWorkflowUtils.XSTREAM_MATCH_ANYWHERE_PREFIX)
602: .append(
603: KualiWorkflowUtils
604: .getSourceAccountingLineClassName(docTypeName))
605: .append(
606: "/"
607: + KFSPropertyConstants.SUB_ACCOUNT)
608: .append(
609: KualiWorkflowUtils.XSTREAM_SAFE_SUFFIX)
610: .toString();
611: } else if (KualiWorkflowUtils
612: .isTargetLineOnly(docTypeName)) {
613: xpathExp = new StringBuffer(
614: KualiWorkflowUtils.XSTREAM_SAFE_PREFIX)
615: .append(
616: KualiWorkflowUtils.XSTREAM_MATCH_ANYWHERE_PREFIX)
617: .append(
618: KualiWorkflowUtils
619: .getTargetAccountingLineClassName(docTypeName))
620: .append(
621: "/"
622: + KFSPropertyConstants.SUB_ACCOUNT)
623: .append(
624: KualiWorkflowUtils.XSTREAM_SAFE_SUFFIX)
625: .toString();
626: } else {
627: xpathExp = new StringBuffer(
628: KualiWorkflowUtils.XSTREAM_SAFE_PREFIX)
629: .append(
630: KualiWorkflowUtils.XSTREAM_MATCH_ANYWHERE_PREFIX)
631: .append(
632: KualiWorkflowUtils
633: .getSourceAccountingLineClassName(docTypeName))
634: .append(
635: "/"
636: + KFSPropertyConstants.SUB_ACCOUNT)
637: .append(
638: KualiWorkflowUtils.XSTREAM_SAFE_SUFFIX)
639: .append(" | ")
640: .append(
641: KualiWorkflowUtils.XSTREAM_SAFE_PREFIX)
642: .append(
643: KualiWorkflowUtils.XSTREAM_MATCH_ANYWHERE_PREFIX)
644: .append(
645: KualiWorkflowUtils
646: .getTargetAccountingLineClassName(docTypeName))
647: .append(
648: "/"
649: + KFSPropertyConstants.SUB_ACCOUNT)
650: .append(
651: KualiWorkflowUtils.XSTREAM_SAFE_SUFFIX)
652: .toString();
653: }
654: NodeList nodes = (NodeList) xpath.evaluate(
655: xpathExp, docContent.getDocument(),
656: XPathConstants.NODESET);
657: for (int i = 0; i < nodes.getLength(); i++) {
658: Node subAccountNode = nodes.item(i);
659: account = xpath
660: .evaluate(
661: KualiWorkflowUtils.XSTREAM_MATCH_RELATIVE_PREFIX
662: + KFSPropertyConstants.ACCOUNT_NUMBER,
663: subAccountNode);
664: org = xpath
665: .evaluate(
666: KualiWorkflowUtils.XSTREAM_MATCH_RELATIVE_PREFIX
667: + KFSPropertyConstants.FIN_REPORT_ORGANIZATION_CODE,
668: subAccountNode);
669: String chartFieldName = KFSPropertyConstants.CHART_OF_ACCOUNTS_CODE;
670: if (StringUtils.isBlank(account)) {
671: chartFieldName = KFSPropertyConstants.FINANCIAL_REPORT_CHART_CODE;
672: }
673: chart = xpath
674: .evaluate(
675: KualiWorkflowUtils.XSTREAM_MATCH_RELATIVE_PREFIX
676: + chartFieldName,
677: subAccountNode);
678: subAccount = xpath
679: .evaluate(
680: KualiWorkflowUtils.XSTREAM_MATCH_RELATIVE_PREFIX
681: + KFSPropertyConstants.SUB_ACCOUNT_NUMBER,
682: subAccountNode);
683: subAccountValues
684: .addAll(attemptSubAccountRetrieval(
685: chart, account, org, subAccount));
686: }
687: }
688: } catch (Exception e) {
689: throw new RuntimeException(e);
690: }
691: routeContext.getParameters().put(
692: DOCUMENT_SUB_ACCOUNT_VALUES_KEY, subAccountValues);
693: }
694: return subAccountValues;
695: }
696:
697: private List<SubAccount> attemptSubAccountRetrieval(String chart,
698: String account, String org, String subAccount) {
699: List<SubAccount> subAccountValues = new ArrayList();
700: if (StringUtils.isNotBlank(chart)
701: && StringUtils.isNotBlank(subAccount)
702: && (StringUtils.isNotBlank(account) || StringUtils
703: .isNotBlank(org))) {
704: List subAccounts = getSubAccounts(chart, account, org,
705: subAccount);
706: if ((subAccounts == null) || (subAccounts.isEmpty())) {
707: throw new RuntimeException(
708: "Sub Account declared on the document cannot be found in the system, routing cannot continue.");
709: }
710: // possibly duplicate add, but this is safe in a HashSet
711: for (Iterator iter = subAccounts.iterator(); iter.hasNext();) {
712: SubAccount subAccountToAdd = (SubAccount) iter.next();
713: subAccountValues.add(subAccountToAdd);
714: }
715: }
716: return subAccountValues;
717: }
718:
719: /**
720: * Gets the accountNbr attribute.
721: *
722: * @return Returns the accountNbr.
723: */
724: public String getAccountNbr() {
725: return accountNbr;
726: }
727:
728: /**
729: * Sets the accountNbr attribute value.
730: *
731: * @param accountNbr The accountNbr to set.
732: */
733: public void setAccountNbr(String accountNbr) {
734: this .accountNbr = accountNbr;
735: }
736:
737: /**
738: * Gets the finCoaCd attribute.
739: *
740: * @return Returns the finCoaCd.
741: */
742: public String getFinCoaCd() {
743: return finCoaCd;
744: }
745:
746: /**
747: * Sets the finCoaCd attribute value.
748: *
749: * @param finCoaCd The finCoaCd to set.
750: */
751: public void setFinCoaCd(String finCoaCd) {
752: this .finCoaCd = finCoaCd;
753: }
754:
755: /**
756: * Gets the orgCd attribute.
757: *
758: * @return Returns the orgCd.
759: */
760: public String getOrgCd() {
761: return orgCd;
762: }
763:
764: /**
765: * Sets the orgCd attribute value.
766: *
767: * @param orgCd The orgCd to set.
768: */
769: public void setOrgCd(String orgCd) {
770: this .orgCd = orgCd;
771: }
772:
773: /**
774: * Gets the subAccountNbr attribute.
775: *
776: * @return Returns the subAccountNbr.
777: */
778: public String getSubAccountNbr() {
779: return subAccountNbr;
780: }
781:
782: /**
783: * Sets the subAccountNbr attribute value.
784: *
785: * @param subAccountNbr The subAccountNbr to set.
786: */
787: public void setSubAccountNbr(String subAccountNbr) {
788: this .subAccountNbr = subAccountNbr;
789: }
790:
791: /**
792: * Sets the routingDataRows attribute value.
793: *
794: * @param routingDataRows The routingDataRows to set.
795: */
796: public void setRoutingDataRows(List routingDataRows) {
797: this .routingDataRows = routingDataRows;
798: }
799:
800: /**
801: * Sets the ruleRows attribute value.
802: *
803: * @param ruleRows The ruleRows to set.
804: */
805: public void setRuleRows(List ruleRows) {
806: this.ruleRows = ruleRows;
807: }
808:
809: }
|