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.HashSet;
020: import java.util.Iterator;
021: import java.util.List;
022: import java.util.Map;
023: import java.util.Set;
024:
025: import javax.xml.xpath.XPath;
026: import javax.xml.xpath.XPathConstants;
027: import javax.xml.xpath.XPathExpressionException;
028:
029: import org.apache.commons.lang.StringUtils;
030: import org.kuali.core.util.ObjectUtils;
031: import org.kuali.kfs.KFSPropertyConstants;
032: import org.kuali.kfs.context.SpringContext;
033: import org.kuali.module.purap.PurapPropertyConstants;
034: import org.kuali.module.vendor.VendorPropertyConstants;
035: import org.kuali.module.vendor.bo.VendorDetail;
036: import org.kuali.module.vendor.service.VendorService;
037: import org.kuali.workflow.KualiWorkflowUtils;
038:
039: import edu.iu.uis.eden.WorkflowServiceErrorImpl;
040: import edu.iu.uis.eden.lookupable.Field;
041: import edu.iu.uis.eden.lookupable.Row;
042: import edu.iu.uis.eden.routeheader.DocumentContent;
043: import edu.iu.uis.eden.routetemplate.AbstractWorkflowAttribute;
044: import edu.iu.uis.eden.routetemplate.RuleExtension;
045: import edu.iu.uis.eden.routetemplate.RuleExtensionValue;
046: import edu.iu.uis.eden.util.KeyLabelPair;
047:
048: public class KualiPurApDocumentTaxReviewAttribute extends
049: AbstractWorkflowAttribute {
050: private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger
051: .getLogger(KualiPurApDocumentTaxReviewAttribute.class);
052:
053: private static final String VENDOR_ROUTE_AS_ATTRIBUTE_KEY = "vendor_route_attribute";
054: private static final String VENDOR_HEADER_GENERATED_ID_KEY = "vendorHeaderGeneratedIdentifier";
055: private static final String ROUTE_AS_TYPE_FIELD_LABEL = "Vendor Tax Attribute";
056:
057: private static final String VENDOR_IS_EMPLOYEE = "Employee Vendor";
058: private static final String VENDOR_IS_FOREIGN = "Foreign Vendor";
059: private static final String VENDOR_IS_FOREIGN_EMPLOYEE = "Foreign and Employee Vendor";
060:
061: private static Set<String> validValues = new HashSet<String>();
062: static {
063: validValues.add(VENDOR_IS_FOREIGN_EMPLOYEE);
064: validValues.add(VENDOR_IS_EMPLOYEE);
065: validValues.add(VENDOR_IS_FOREIGN);
066: }
067:
068: private String vendorRouteAsTypeKey;
069: private String vendorHeaderGeneratedId;
070: private List<Row> ruleRows;
071: private List<Row> routingDataRows;
072:
073: /**
074: * No arg constructor
075: */
076: public KualiPurApDocumentTaxReviewAttribute() {
077: ruleRows = new ArrayList<edu.iu.uis.eden.lookupable.Row>();
078: ruleRows.add(constructDropdown());
079:
080: routingDataRows = new ArrayList<edu.iu.uis.eden.lookupable.Row>();
081: routingDataRows.add(KualiWorkflowUtils.buildTextRowWithLookup(
082: VendorDetail.class,
083: VendorPropertyConstants.VENDOR_HEADER_GENERATED_ID,
084: VENDOR_HEADER_GENERATED_ID_KEY));
085: routingDataRows.add(constructDropdown());
086: }
087:
088: private edu.iu.uis.eden.lookupable.Row constructDropdown() {
089: List validValuesTemp = new ArrayList();
090: for (String validValue : validValues) {
091: validValuesTemp
092: .add(new KeyLabelPair(validValue, validValue));
093: }
094: List chartFields = new ArrayList();
095: chartFields.add(new Field(ROUTE_AS_TYPE_FIELD_LABEL, "",
096: Field.DROPDOWN, false, VENDOR_ROUTE_AS_ATTRIBUTE_KEY,
097: "", validValuesTemp, null,
098: VENDOR_ROUTE_AS_ATTRIBUTE_KEY));
099: return new Row(chartFields);
100: }
101:
102: /**
103: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#getDocContent()
104: */
105: public String getDocContent() {
106: if ((StringUtils.isNotBlank(getVendorRouteAsTypeKey()))
107: || (StringUtils
108: .isNotBlank(getVendorHeaderGeneratedId()))) {
109: StringBuffer returnValue = new StringBuffer(
110: KualiWorkflowUtils.XML_REPORT_DOC_CONTENT_PREFIX);
111: String xmlKey = "vendorRouteTypeCode";
112: returnValue.append(
113: "<" + VENDOR_ROUTE_AS_ATTRIBUTE_KEY + ">").append(
114: getVendorRouteAsTypeKey()).append(
115: "</" + VENDOR_ROUTE_AS_ATTRIBUTE_KEY + ">");
116: returnValue.append(
117: "<" + VENDOR_HEADER_GENERATED_ID_KEY + ">").append(
118: getVendorHeaderGeneratedId()).append(
119: "</" + VENDOR_HEADER_GENERATED_ID_KEY + ">");
120: return returnValue.append(
121: KualiWorkflowUtils.XML_REPORT_DOC_CONTENT_SUFFIX)
122: .toString();
123: }
124: return "";
125: }
126:
127: /**
128: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#getRoutingDataRows()
129: */
130: public List<Row> getRoutingDataRows() {
131: return routingDataRows;
132: }
133:
134: /**
135: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#getRuleExtensionValues()
136: */
137: public List<RuleExtensionValue> getRuleExtensionValues() {
138: List extensions = new ArrayList();
139: extensions.add(new RuleExtensionValue(
140: VENDOR_ROUTE_AS_ATTRIBUTE_KEY,
141: getVendorRouteAsTypeKey()));
142: return extensions;
143: }
144:
145: /**
146: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#getRuleRows()
147: */
148: public List<Row> getRuleRows() {
149: return ruleRows;
150: }
151:
152: /**
153: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#isMatch(edu.iu.uis.eden.routeheader.DocumentContent, java.util.List)
154: */
155: public boolean isMatch(DocumentContent documentContent,
156: List<RuleExtension> ruleExtensions) {
157: // Document doc = documentContent.getDocument();
158: String currentXpathExpression = null;
159: String vendorHeaderGeneratedId = null;
160: try {
161: XPath xPath = KualiWorkflowUtils.getXPath(documentContent
162: .getDocument());
163: currentXpathExpression = KualiWorkflowUtils
164: .xstreamSafeXPath(KualiWorkflowUtils.XSTREAM_MATCH_ANYWHERE_PREFIX
165: + KualiWorkflowUtils.XML_REPORT_DOC_CONTENT_XPATH_PREFIX);
166: boolean isReport = ((Boolean) xPath.evaluate(
167: currentXpathExpression, documentContent
168: .getDocument(), XPathConstants.BOOLEAN))
169: .booleanValue();
170: if (isReport) {
171: currentXpathExpression = KualiWorkflowUtils.XSTREAM_MATCH_ANYWHERE_PREFIX
172: + KualiWorkflowUtils.XML_REPORT_DOC_CONTENT_XPATH_PREFIX
173: + "/" + VENDOR_HEADER_GENERATED_ID_KEY;
174: } else {
175: currentXpathExpression = KualiWorkflowUtils.XSTREAM_MATCH_ANYWHERE_PREFIX
176: + KFSPropertyConstants.DOCUMENT
177: + "/"
178: + PurapPropertyConstants.VENDOR_HEADER_GENERATED_ID;
179: }
180: vendorHeaderGeneratedId = KualiWorkflowUtils
181: .xstreamSafeEval(xPath, currentXpathExpression,
182: documentContent.getDocument());
183: if (StringUtils.isBlank(vendorHeaderGeneratedId)) {
184: // no vendor header id so can't check for proper tax routing
185: return false;
186: }
187: VendorService vendorService = SpringContext
188: .getBean(VendorService.class);
189: boolean routeDocumentAsEmployeeVendor = vendorService
190: .isVendorInstitutionEmployee(Integer
191: .valueOf(vendorHeaderGeneratedId));
192: boolean routeDocumentAsForeignVendor = vendorService
193: .isVendorForeign(Integer
194: .valueOf(vendorHeaderGeneratedId));
195: if ((!routeDocumentAsEmployeeVendor)
196: && (!routeDocumentAsForeignVendor)) {
197: // no need to route
198: return false;
199: }
200:
201: String value = getRuleExtentionValue(
202: VENDOR_ROUTE_AS_ATTRIBUTE_KEY, ruleExtensions);
203: if (StringUtils.equals(VENDOR_IS_EMPLOYEE, value)) {
204: return routeDocumentAsEmployeeVendor;
205: } else if (StringUtils.equals(VENDOR_IS_FOREIGN, value)) {
206: return routeDocumentAsForeignVendor;
207: } else if (StringUtils.equals(VENDOR_IS_FOREIGN_EMPLOYEE,
208: value)) {
209: return routeDocumentAsEmployeeVendor
210: && routeDocumentAsForeignVendor;
211: }
212: return false;
213: } catch (NumberFormatException nfe) {
214: String errorMsg = "Number format exception for invalid vendor header id of "
215: + vendorHeaderGeneratedId;
216: LOG.error(errorMsg, nfe);
217: throw new RuntimeException(errorMsg, nfe);
218: } catch (XPathExpressionException xe) {
219: String errorMsg = "Xpath error occurred while using xpath expression "
220: + currentXpathExpression;
221: LOG.error(errorMsg, xe);
222: throw new RuntimeException(errorMsg, xe);
223: }
224: }
225:
226: private String getRuleExtentionValue(String key,
227: List<RuleExtension> ruleExtensions) {
228: for (RuleExtension extension : ruleExtensions) {
229: if (extension.getRuleTemplateAttribute().getRuleAttribute()
230: .getClassName().equals(this .getClass().getName())) {
231: for (Iterator iterator = extension.getExtensionValues()
232: .iterator(); iterator.hasNext();) {
233: RuleExtensionValue value = (RuleExtensionValue) iterator
234: .next();
235: if (value.getKey().equals(key)) {
236: return value.getValue();
237: }
238: }
239: }
240: }
241: return null;
242: }
243:
244: /**
245: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#validateRoutingData(java.util.Map)
246: */
247: public List validateRoutingData(Map paramMap) {
248: List errors = new ArrayList();
249: setVendorHeaderGeneratedId((String) paramMap
250: .get(VENDOR_HEADER_GENERATED_ID_KEY));
251: errors.addAll(validateRuleData(paramMap));
252: String label = KualiWorkflowUtils
253: .getBusinessObjectAttributeLabel(
254: VendorDetail.class,
255: VendorPropertyConstants.VENDOR_HEADER_GENERATED_ID);
256: if (isRequired()
257: && StringUtils.isBlank(getVendorHeaderGeneratedId())) {
258: // required but blank
259: String errorMessage = label + " is required";
260: errors.add(new WorkflowServiceErrorImpl(errorMessage,
261: "routetemplate.xmlattribute.error", errorMessage));
262: } else if (StringUtils.isNotBlank(getVendorHeaderGeneratedId())) {
263: try {
264: // check valid values?
265: VendorDetail vendor = SpringContext.getBean(
266: VendorService.class).getParentVendor(
267: Integer.valueOf(getVendorHeaderGeneratedId()));
268: if (ObjectUtils.isNull(vendor)) {
269: String errorMessage = "No valid vendor found for given value of "
270: + label;
271: errors.add(new WorkflowServiceErrorImpl(
272: errorMessage,
273: "routetemplate.xmlattribute.error",
274: errorMessage));
275: }
276: } catch (NumberFormatException e) {
277: String errorMessage = "The value of " + label
278: + " must be a valid number";
279: LOG.info(errorMessage, e);
280: errors.add(new WorkflowServiceErrorImpl(errorMessage,
281: "routetemplate.xmlattribute.error",
282: errorMessage));
283: }
284: }
285: return errors;
286:
287: }
288:
289: /**
290: * @see edu.iu.uis.eden.plugin.attributes.WorkflowAttribute#validateRuleData(java.util.Map)
291: */
292: public List validateRuleData(Map paramMap) {
293: List errors = new ArrayList();
294: setVendorRouteAsTypeKey((String) paramMap
295: .get(VENDOR_ROUTE_AS_ATTRIBUTE_KEY));
296: if (isRequired()
297: && StringUtils.isBlank(getVendorRouteAsTypeKey())) {
298: // required but blank
299: String errorMessage = ROUTE_AS_TYPE_FIELD_LABEL
300: + " is required";
301: errors.add(new WorkflowServiceErrorImpl(errorMessage,
302: "routetemplate.xmlattribute.error", errorMessage));
303: } else if (StringUtils.isNotBlank(getVendorRouteAsTypeKey())) {
304: // check valid values?
305: if (!validValues.contains(getVendorRouteAsTypeKey())) {
306: String errorMessage = ROUTE_AS_TYPE_FIELD_LABEL
307: + " is not a valid value for the field";
308: errors.add(new WorkflowServiceErrorImpl(errorMessage,
309: "routetemplate.xmlattribute.error",
310: errorMessage));
311: }
312: }
313: return errors;
314: }
315:
316: /**
317: * Gets the vendorHeaderGeneratedId attribute.
318: *
319: * @return Returns the vendorHeaderGeneratedId.
320: */
321: public String getVendorHeaderGeneratedId() {
322: return vendorHeaderGeneratedId;
323: }
324:
325: /**
326: * Sets the vendorHeaderGeneratedId attribute value.
327: *
328: * @param vendorHeaderGeneratedId The vendorHeaderGeneratedId to set.
329: */
330: public void setVendorHeaderGeneratedId(
331: String vendorHeaderGeneratedId) {
332: this .vendorHeaderGeneratedId = vendorHeaderGeneratedId;
333: }
334:
335: /**
336: * Gets the vendorRouteAsTypeKey attribute.
337: *
338: * @return Returns the vendorRouteAsTypeKey.
339: */
340: public String getVendorRouteAsTypeKey() {
341: return vendorRouteAsTypeKey;
342: }
343:
344: /**
345: * Sets the vendorRouteAsTypeKey attribute value.
346: *
347: * @param vendorRouteAsTypeKey The vendorRouteAsTypeKey to set.
348: */
349: public void setVendorRouteAsTypeKey(String vendorRouteAsTypeKey) {
350: this.vendorRouteAsTypeKey = vendorRouteAsTypeKey;
351: }
352:
353: }
|