View Javadoc
1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kew.rule.xmlrouting;
17  
18  import org.junit.Test;
19  import org.kuali.rice.core.api.uif.RemotableAttributeError;
20  import org.kuali.rice.kew.api.WorkflowDocument;
21  import org.kuali.rice.kew.api.WorkflowDocumentFactory;
22  import org.kuali.rice.kew.api.document.attribute.WorkflowAttributeDefinition;
23  import org.kuali.rice.kew.api.rule.RuleExtension;
24  import org.kuali.rice.kew.docsearch.xml.StandardGenericXMLSearchableAttribute;
25  import org.kuali.rice.kew.api.exception.WorkflowException;
26  import org.kuali.rice.kew.engine.RouteContext;
27  import org.kuali.rice.kew.engine.node.RouteNode;
28  import org.kuali.rice.kew.engine.node.RouteNodeInstance;
29  import org.kuali.rice.kew.exception.WorkflowServiceError;
30  import org.kuali.rice.kew.routeheader.DocumentContent;
31  import org.kuali.rice.kew.routeheader.StandardDocumentContent;
32  import org.kuali.rice.kew.rule.RuleExtensionBo;
33  import org.kuali.rice.kew.rule.RuleExtensionValue;
34  import org.kuali.rice.kew.rule.bo.RuleAttribute;
35  import org.kuali.rice.kew.rule.bo.RuleTemplateAttributeBo;
36  import org.kuali.rice.kew.rule.bo.RuleTemplateBo;
37  import org.kuali.rice.kew.test.KEWTestCase;
38  import org.kuali.rice.kns.web.ui.Field;
39  import org.kuali.rice.kns.web.ui.Row;
40  import org.w3c.dom.Element;
41  import org.xml.sax.InputSource;
42  
43  import javax.xml.parsers.DocumentBuilderFactory;
44  import javax.xml.xpath.XPath;
45  import javax.xml.xpath.XPathConstants;
46  import javax.xml.xpath.XPathFactory;
47  import java.io.BufferedReader;
48  import java.io.StringReader;
49  import java.util.ArrayList;
50  import java.util.HashMap;
51  import java.util.Iterator;
52  import java.util.List;
53  import java.util.Map;
54  
55  import static org.junit.Assert.assertFalse;
56  import static org.junit.Assert.assertTrue;
57  
58  public class StandardGenericXMLRuleAttributeTest extends KEWTestCase {
59  
60  	private DocumentContent docContent;
61  	private StandardGenericXMLRuleAttribute attribute;
62  	private List<RuleExtension> extensions;
63  
64  	public void setUp() throws Exception {
65          super.setUp();
66  		attribute = new StandardGenericXMLRuleAttribute();
67  		String documentcontent =
68  			"<documentContent>" +
69  				"<attributeContent>"+
70  					"<xmlContent>"+
71  						"<fieldDef name=\"givenname\">"+
72  							"<value>Dave</value>"+
73  		                                "</fieldDef>"+
74  						"<fieldDef name=\"gender\">"+
75  							"<value>female</value>"+
76  						"</fieldDef>"+
77  						"<fieldDef name=\"color\">"+
78  							"<value>green</value>"+
79  						"</fieldDef>"+
80  						"<fieldDef name=\"totalDollar\">"+
81  							"<value>500</value>"+
82  						"</fieldDef>"+
83  					"</xmlContent>"+
84  					"<xmlContent>"+
85  						"<fieldDef name=\"givenname\">"+
86  							"<value>Jane</value>"+
87  		                                "</fieldDef>"+
88  						"<fieldDef name=\"gender\">"+
89  							"<value>female</value>"+
90  						"</fieldDef>"+
91  						"<fieldDef name=\"color\">"+
92  							"<value>blue</value>"+
93  						"</fieldDef>"+
94  						"<fieldDef name=\"totalDollar\">"+
95  							"<value>400</value>"+
96  						"</fieldDef>"+
97  					"</xmlContent>"+
98  				"</attributeContent>"+
99                              "</documentContent>";
100 
101 		String routingConfig =
102 			"<routingConfig>"+
103 				"<globalEvaluations>" +
104 					"<xpathexpression>//fieldDef/value != 'Nothing'</xpathexpression>" +
105 				"</globalEvaluations>"+
106 
107 				"<fieldDef name=\"givenname\" title=\"First name\" workflowType=\"ALL\">"+
108 					"<value>Joe</value>"+
109 					"<display>"+
110 						"<type>text</type>"+
111 						"<meta><name>size</name><value>20</value></meta>"+
112 					"</display>" +
113 					"<validation required=\"true\">"+
114 						"<regex>^[a-zA-Z ]+$</regex>"+
115 						"<message>Invalid first name</message>"+
116         			"</validation>"+
117 					"<fieldEvaluation><xpathexpression>//xmlContent/fieldDef[@name='givenname']/value = wf:ruledata('givenname')</xpathexpression></fieldEvaluation>"+
118 				"</fieldDef>"+
119 				"<fieldDef name=\"gender\" title=\"Gender\" workflowType=\"ALL\">"+
120 					"<value>male</value>"+
121 					"<display>"+
122 						"<type>radio</type>"+
123 						"<values title=\"Male\">male</values>"+
124 						"<values title=\"Female\">female</values>"+
125 					"</display>"+
126 			        "<validation required=\"true\">" +
127 		        		"<regex>(male|female)</regex>"+
128 		        		"<message>Invalid gender</message>"+
129 		        	"</validation>"+
130 					"<fieldEvaluation><xpathexpression>//xmlContent/fieldDef[@name='gender']/value = wf:ruledata('gender')</xpathexpression></fieldEvaluation>"+
131 				"</fieldDef>"+
132 				"<fieldDef name=\"color\" title=\"Color\" workflowType=\"ALL\">" +
133 					"<value>blue</value>" +
134 					"<display>" +
135 						"<type>select</type>" +
136 						"<values title=\"Red\">red</values>" +
137 						"<values title=\"Green\">green</values>" +
138 						"<values title=\"Blue\" selected=\"true\">blue</values>" +
139 					"</display>" +
140 					"<validation required=\"true\">"+
141 			        	"<regex>(red|green|blue|)</regex>"+
142 			        	"<message>Invalid color</message>"+
143 			        "</validation>"+
144 					"<fieldEvaluation><xpathexpression>//xmlContent/fieldDef[@name='color']/value = wf:ruledata('color')</xpathexpression></fieldEvaluation>"+
145 				"</fieldDef>"+
146 				"<fieldDef name=\"maxDollar\" title=\"Max dollar\" workflowType=\"RULE\">" +
147 					"<display>" +
148 						"<type>text</type>" +
149 					"</display>" +
150 					"<fieldEvaluation><xpathexpression>//xmlContent/fieldDef[@name='totalDollar']/value &lt;= wf:ruledata('maxDollar')</xpathexpression></fieldEvaluation>"+
151 				"</fieldDef>"+
152 				"<fieldDef name=\"minDollar\" title=\"Min dollar\" workflowType=\"RULE\">" +
153 					"<display>" +
154 						"<type>text</type>" +
155 					"</display>" +
156 					"<fieldEvaluation><xpathexpression>//xmlContent/fieldDef[@name='totalDollar']/value &gt;= wf:ruledata('minDollar')</xpathexpression></fieldEvaluation>"+
157 			    "</fieldDef>"+
158 				"<fieldDef name=\"totalDollar\" title=\"Total dollar\" workflowType=\"REPORT\">" +
159 					"<display>" +
160 						"<type>text</type>" +
161 					"</display>" +
162 		        "</fieldDef>" +
163             "</routingConfig>";
164 
165         // stub the RouteContext - it is needed for xpath caching optimization
166         RouteContext ctx = new RouteContext();
167 
168 		docContent = new StandardDocumentContent(documentcontent, ctx);
169 
170 		RuleAttribute ruleAttribute = new RuleAttribute();
171 		ruleAttribute.setXmlConfigData(routingConfig);
172 		ruleAttribute.setName("MyUniqueRuleAttribute1");
173         ruleAttribute.setType("SearchableXmlAttribute");
174         ruleAttribute.setResourceDescriptor(StandardGenericXMLSearchableAttribute.class.getName());
175 		attribute.setExtensionDefinition(RuleAttribute.to(ruleAttribute));
176 	}
177 
178 	@Test public void testValidateRoutingData(){
179         Map<String, String> paramMap = new HashMap<String, String>();
180 		paramMap.put("givenname", "Dave");
181 		paramMap.put("gender", "female");
182 		paramMap.put("color", "green");
183 		paramMap.put("totalDollar", "500");
184 
185 		assertTrue("Errors found", attribute.validateRoutingData(paramMap).isEmpty());
186 	}
187 
188 	@Test public void testValidateRuleData(){
189         Map<String, String> paramMap = new HashMap<String, String>();
190 		paramMap.put("givenname", "Dave");
191 		paramMap.put("gender", "female");
192 		paramMap.put("color", "green");
193 		paramMap.put("totalDollar", "500");
194 
195 		assertTrue("Errors found", attribute.validateRuleData(paramMap).isEmpty());
196 
197 		paramMap = new HashMap<String, String>();
198 		paramMap.put("givenname", "4444");
199 		paramMap.put("gender", "crap");
200 		paramMap.put("color", "green");
201 		paramMap.put("totalDollar", "500");
202 
203         assertFalse("Error list should contain at least one error.", attribute.validateRuleData(paramMap).isEmpty());
204 
205 		paramMap = new HashMap<String, String>();
206 		paramMap.put("givenname", "");
207 		paramMap.put("gender", "female");
208 		paramMap.put("color", "green");
209 		paramMap.put("totalDollar", "500");
210 
211 		assertFalse("givenname should be required.", attribute.validateRuleData(paramMap).isEmpty());
212 	}
213 
214     @Test public void testRuleDataAttributeErrorTypesAreConformant() {
215         Map<String, String> paramMap = new HashMap<String, String>();
216 		paramMap.put("givenname", "4444");
217 		paramMap.put("gender", "crap");
218 		paramMap.put("color", "green");
219 		paramMap.put("totalDollar", "500");
220 
221 		List<RemotableAttributeError> errors = attribute.validateRuleData(paramMap);
222         assertFalse("Error list should contain at least one error.", errors.isEmpty());
223         for (Object e: errors) {
224             assertTrue(RemotableAttributeError.class.isAssignableFrom(e.getClass()));
225         }
226     }
227 
228     @Test public void testRoutingDataAttributeErrorTypesAreConformant(){
229         Map<String, String> paramMap = new HashMap<String, String>();
230         paramMap.put("givenname", "4444");
231         paramMap.put("gender", "crap");
232         paramMap.put("color", "green");
233         paramMap.put("totalDollar", "500");
234 
235         List<RemotableAttributeError> errors = attribute.validateRoutingData(paramMap);
236         assertFalse("Error list should contain at least one error.", errors.isEmpty());
237         for (Object e: errors) {
238             assertTrue(RemotableAttributeError.class.isAssignableFrom(e.getClass()));
239         }
240     }
241 
242     /**
243      * Tests SGXA attribute matching behavior with extension value keys that do not necessarily match
244      * a field defined in the attribute
245      */
246     @Test public void testNonMatchingExtensionKey() throws WorkflowException {
247         loadXmlFile("TestExtensionValueMatching.xml");
248         WorkflowDocument doc = WorkflowDocumentFactory.createDocument(getPrincipalIdForName("arh14"), "TestDocument");
249 
250         WorkflowAttributeDefinition.Builder attr = WorkflowAttributeDefinition.Builder.create(StandardGenericXMLRuleAttribute.class.getName());
251         attr.setAttributeName("Attr1");
252         // expected to match RuleTemplate with extension value: value='1' with xpath expression /xmlRouting/field[@name=attr1] = wf:ruledata('value')
253         attr.addPropertyDefinition("attr1", "2");
254         doc.addAttributeDefinition(attr.build());
255 
256         doc.route("");
257 
258         String id = doc.getDocumentId();
259 
260         doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user1"), id);
261         assertTrue("Request should have been generated to user1", doc.isApprovalRequested());
262 
263         doc = WorkflowDocumentFactory.loadDocument(getPrincipalIdForName("user2"), id);
264         assertTrue("Expected approval request to user2", doc.isApprovalRequested());
265     }
266 
267 	/*
268 	 * Test method for 'org.kuali.rice.kew.rule.xmlrouting.StandardGenericXMLRuleAttribute.isMatch(DocumentContent, List)'
269 	 */
270 	@Test public void testIsMatch() {
271 		RuleExtensionBo extension = new RuleExtensionBo();
272 
273 		List<RuleExtensionValue> values = new ArrayList<RuleExtensionValue>();
274 		RuleExtensionValue value = new RuleExtensionValue();
275 		value.setKey("givenname");
276 		value.setValue("Dave");
277 		values.add(value);
278 
279 		RuleExtensionValue value2 = new RuleExtensionValue();
280 		value2.setKey("gender");
281 		value2.setValue("female");
282 		values.add(value2);
283 
284 		RuleExtensionValue value3 = new RuleExtensionValue();
285 		value3.setKey("color");
286 		value3.setValue("green");
287 		values.add(value3);
288 
289 		extension.setExtensionValues(values);
290 		RuleTemplateAttributeBo ruleTemplateAttribute = new RuleTemplateAttributeBo();
291 
292 		RuleAttribute ruleAttribute = new RuleAttribute();
293 		ruleAttribute.setName("MyUniqueRuleAttribute1");
294         ruleAttribute.setType("RuleAttribute");
295         ruleAttribute.setResourceDescriptor("noClass");
296 
297         RuleTemplateBo ruleTemplate = new RuleTemplateBo();
298         ruleTemplate.setId("ruleTemplateId1");
299 
300 		ruleTemplateAttribute.setRuleAttribute(ruleAttribute);
301         ruleTemplateAttribute.setRuleTemplate(ruleTemplate);
302         ruleTemplateAttribute.setDisplayOrder(new Integer(1));
303 		extension.setRuleTemplateAttribute(ruleTemplateAttribute);
304 		RuleExtensionBo extension2 = new RuleExtensionBo();
305 
306 		List values2 = new ArrayList();
307 		RuleExtensionValue valueNew = new RuleExtensionValue();
308 		valueNew.setKey("givenname");
309 		valueNew.setValue("Jack");
310 
311 		RuleExtensionValue minDollar = new RuleExtensionValue();
312 		minDollar.setKey("minDollar");
313 		minDollar.setValue("300");
314         RuleExtensionValue maxDollar = new RuleExtensionValue();
315         maxDollar.setKey("maxDollar");
316         maxDollar.setValue("600");
317 
318 
319 		values2.add(valueNew);
320 		values2.add(minDollar);
321 		values2.add(maxDollar);
322 		extension2.setExtensionValues(values2);
323 		RuleTemplateAttributeBo ruleTemplateAttribute2 = new RuleTemplateAttributeBo();
324 
325 		RuleAttribute ruleAttribute2 = new RuleAttribute();
326 		ruleAttribute2.setName("MyUniqueRuleAttribute2");
327         ruleAttribute2.setType("RuleAttribute");
328         ruleAttribute2.setResourceDescriptor("noClass");
329 
330         RuleTemplateBo ruleTemplate2 = new RuleTemplateBo();
331         ruleTemplate2.setId("ruleTemplateId2");
332 
333         ruleTemplateAttribute2.setRuleAttribute(ruleAttribute2);
334         ruleTemplateAttribute2.setRuleTemplate(ruleTemplate2);
335         ruleTemplateAttribute2.setDisplayOrder(new Integer(2));
336 		extension2.setRuleTemplateAttribute(ruleTemplateAttribute2);
337 
338 		extensions = new ArrayList();
339 		extensions.add(RuleExtensionBo.to(extension));
340 		extensions.add(RuleExtensionBo.to(extension2));
341 
342 		assertTrue("Givenname did not match Dave, gender did not match female, or color did not match green", attribute.isMatch(docContent, extensions));
343 
344 		extension = new RuleExtensionBo();
345 		values = new ArrayList();
346 		RuleExtensionValue value4 = new RuleExtensionValue();
347 		value4.setKey("givenname");
348 		value4.setValue("Dave");
349 		values.add(value4);
350 
351 		RuleExtensionValue value5 = new RuleExtensionValue();
352 		value5.setKey("gender");
353 		value5.setValue("male");
354 		values.add(value5);
355 
356 		RuleExtensionValue value6 = new RuleExtensionValue();
357 		value6.setKey("color");
358 		value6.setValue("green");
359 		values.add(value6);
360 
361 		extension.setExtensionValues(values);
362 		ruleTemplateAttribute = new RuleTemplateAttributeBo();
363 
364 		ruleAttribute = new RuleAttribute();
365 		ruleAttribute.setName("MyUniqueRuleAttribute1");
366         ruleAttribute.setType("RuleAttribute");
367         ruleAttribute.setResourceDescriptor("noClass");
368 
369         ruleTemplate = new RuleTemplateBo();
370         ruleTemplate.setId("ruleTemplateId");
371 
372         ruleTemplateAttribute.setRuleAttribute(ruleAttribute);
373         ruleTemplateAttribute.setRuleTemplate(ruleTemplate);
374         ruleTemplateAttribute.setDisplayOrder(new Integer(1));
375 		extension.setRuleTemplateAttribute(ruleTemplateAttribute);
376 
377 		values2 = new ArrayList();
378 		valueNew = new RuleExtensionValue();
379 		valueNew.setKey("givenname");
380 		valueNew.setValue("Jack");
381 
382 		values2.add(valueNew);
383 		extension2.setExtensionValues(values2);
384 		ruleTemplateAttribute2 = new RuleTemplateAttributeBo();
385 
386 		ruleAttribute2 = new RuleAttribute();
387 		ruleAttribute2.setName("MyUniqueRuleAttribute2");
388         ruleAttribute2.setType("RuleAttribute");
389         ruleAttribute2.setResourceDescriptor("noClass");
390 
391         ruleTemplate2 = new RuleTemplateBo();
392         ruleTemplate2.setId("ruleTemplateId2");
393 
394         ruleTemplateAttribute2.setRuleAttribute(ruleAttribute2);
395         ruleTemplateAttribute2.setRuleTemplate(ruleTemplate2);
396         ruleTemplateAttribute2.setDisplayOrder(new Integer(2));
397 		extension2.setRuleTemplateAttribute(ruleTemplateAttribute2);
398 
399 		extensions = new ArrayList();
400 		extensions.add(RuleExtensionBo.to(extension));
401 		extensions.add(RuleExtensionBo.to(extension2));
402 		assertFalse("Gender female != male.", attribute.isMatch(docContent, extensions));
403 
404 		///////
405 
406 		extension = new RuleExtensionBo();
407 		values = new ArrayList();
408 
409 		RuleExtensionValue value7 = new RuleExtensionValue();
410 		value7.setKey("maxDollar");
411 		value7.setValue("500");
412 
413 
414 		RuleExtensionValue value8 = new RuleExtensionValue();
415 		value8.setKey("minDollar");
416 		value8.setValue("100");
417 
418         values.add(value7);
419 		values.add(value8);
420 		extension.setExtensionValues(values);
421 
422         ruleTemplateAttribute = new RuleTemplateAttributeBo();
423 		ruleAttribute = new RuleAttribute();
424 		ruleAttribute.setName("MyUniqueRuleAttribute1");
425         ruleAttribute.setType("RuleAttribute");
426         ruleAttribute.setResourceDescriptor("noClass");
427 
428         ruleTemplate = new RuleTemplateBo();
429         ruleTemplate.setId("ruleTemplateId");
430 
431         ruleTemplateAttribute.setRuleAttribute(ruleAttribute);
432         ruleTemplateAttribute.setRuleTemplate(ruleTemplate);
433         ruleTemplateAttribute.setDisplayOrder(new Integer(1));
434 		extension.setRuleTemplateAttribute(ruleTemplateAttribute);
435 
436 		values2 = new ArrayList();
437 
438 		valueNew = new RuleExtensionValue();
439 		valueNew.setKey("givenname");
440 		valueNew.setValue("Jack");
441 		values2.add(valueNew);
442 
443 		extension2.setExtensionValues(values2);
444 		ruleTemplateAttribute2 = new RuleTemplateAttributeBo();
445 
446 		ruleAttribute2 = new RuleAttribute();
447 		ruleAttribute2.setName("MyUniqueRuleAttribute2");
448         ruleAttribute2.setType("RuleAttribute");
449         ruleAttribute2.setResourceDescriptor("noClass");
450 
451         ruleTemplate2 = new RuleTemplateBo();
452         ruleTemplate2.setId("ruleTemplateId2");
453 
454         ruleTemplateAttribute2.setRuleAttribute(ruleAttribute2);
455         ruleTemplateAttribute2.setRuleTemplate(ruleTemplate2);
456         ruleTemplateAttribute2.setDisplayOrder(new Integer(2));
457 		extension2.setRuleTemplateAttribute(ruleTemplateAttribute2);
458 
459 		extensions = new ArrayList();
460 		extensions.add(RuleExtensionBo.to(extension));
461 		extensions.add(RuleExtensionBo.to(extension2));
462 		assertTrue("Total dollar is greater than the max or less than the min.", attribute.isMatch(docContent, extensions));
463 	}
464 
465 	/*
466 	 * Test method for 'org.kuali.rice.kew.rule.xmlrouting.StandardGenericXMLRuleAttribute.getRuleRows()'
467 	 */
468 	@Test public void testGetRuleRows() {
469 		assertTrue("Invalid number of rule rows", attribute.getRuleRows().size() == 5);
470 
471 		String routingConfigWithQuickfinders =
472 			"<routingConfig>"+
473 				"<globalEvaluations>" +
474 					"<xpathexpression>//field/value != 'Nothing'</xpathexpression>" +
475 				"</globalEvaluations>"+
476 
477 				"<fieldDef name=\"chart\" title=\"Chart\" workflowType=\"ALL\">"+
478 					"<value>BL</value>"+
479 					"<display>"+
480 						"<type>text</type>"+
481 						"<meta><name>size</name><value>20</value></meta>"+
482 					"</display>" +
483 					"<fieldEvaluation><xpathexpression>//xmlContent/field[@name='chart']/value = wf:ruledata('chart')</xpathexpression></fieldEvaluation>"+
484 				"</fieldDef>"+
485 				"<fieldDef name=\"org\" title=\"Org\" workflowType=\"ALL\">"+
486 					"<display>"+
487 						"<type>text</type>"+
488 					"</display>" +
489 					"<lookup businessObjectClass=\"ChartOrgLookupableImplService\">" +
490 					    "<fieldConversions>" +
491 				          "<fieldConversion lookupFieldName=\"fin_coa_cd\" localFieldName=\"chart\"/>" +
492 					      "<fieldConversion lookupFieldName=\"org_cd\" localFieldName=\"org\"/>" +
493 					    "</fieldConversions>" +
494 					"</lookup>" +
495 					"<fieldEvaluation><xpathexpression>//xmlContent/field[@name='gender']/value = wf:ruledata('gender')</xpathexpression></fieldEvaluation>"+
496 				"</fieldDef>" +
497             "</routingConfig>";
498 
499 		RuleAttribute ruleAttribute = new RuleAttribute();
500 		ruleAttribute.setXmlConfigData(routingConfigWithQuickfinders);
501 		ruleAttribute.setName("MyUniqueRuleAttribute3");
502         ruleAttribute.setType("SearchableXmlAttribute");
503         ruleAttribute.setResourceDescriptor(StandardGenericXMLSearchableAttribute.class.getName());
504 		StandardGenericXMLRuleAttribute myAttribute = new StandardGenericXMLRuleAttribute();
505 		myAttribute.setExtensionDefinition(RuleAttribute.to(ruleAttribute));
506 
507 		for (Iterator iter = myAttribute.getRuleRows().iterator(); iter.hasNext();) {
508 			Row row = (Row) iter.next();
509 			for (Iterator iterator = row.getFields().iterator(); iterator.hasNext();) {
510 				Field field = (Field) iterator.next();
511 				if(field.getFieldType().equals(Field.QUICKFINDER)){
512 					assertTrue("Did not find quickfinder.", true);
513 				}
514 			}
515 		}
516 		assertTrue("Should have 2 rows and 3 fields: chart, org, and quickfinder.", myAttribute.getRuleRows().size() == 2);
517 	}
518 
519 	@Test public void testGetRoutingDataRows() {
520 		assertTrue("Invalid number of routing data rows",attribute.getRoutingDataRows().size() == 4);
521 	}
522 
523 	@Test public void testGetDocContent() {
524 		//test the standard doc content...
525         Map<String, String> paramMap = new HashMap<String, String>();
526 		paramMap.put("givenname", "Dave");
527 		paramMap.put("gender", "female");
528 		paramMap.put("color", "green");
529 		paramMap.put("totalDollar", "500");
530 
531 		attribute.setParamMap(paramMap);
532 		try{
533 			XPath xpath = XPathFactory.newInstance().newXPath();
534 			Element element = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new BufferedReader(new StringReader(attribute.getDocContent())))).getDocumentElement();
535 
536 			String findStuff = "//xmlRouting/field[@name='givenname']/value";
537 			assertTrue("Document content does not contain field givenname with value of Dave.", "Dave".equals(xpath.evaluate(findStuff, element, XPathConstants.STRING)));
538 
539 			findStuff = "//xmlRouting/field[@name='gender']/value";
540 			assertTrue("Document content does not contain field gender with value of female.", "female".equals(xpath.evaluate(findStuff, element, XPathConstants.STRING)));
541 
542 			findStuff = "//xmlRouting/field[@name='color']/value";
543 			assertTrue("Document content does not contain field color with value of green.", "green".equals(xpath.evaluate(findStuff, element, XPathConstants.STRING)));
544 
545 			findStuff = "//xmlRouting/field[@name='totalDollar']/value";
546 			assertTrue("Document content does not contain field totalDollar with value of 500.", "500".equals(xpath.evaluate(findStuff, element, XPathConstants.STRING)));
547 		} catch (Exception e){
548 			e.printStackTrace();
549 		}
550 
551 		// Now test the custom doc content...
552 		String routingConfig =
553 			"<routingConfig>" +
554 				"<fieldDef name=\"myname\" title=\"First name\" workflowType=\"ALL\">"+
555 					"<value>Joe</value>"+
556 					"<display>"+
557 						"<type>text</type>"+
558 						"<meta><name>size</name><value>20</value></meta>"+
559 					"</display>"+
560 					"<fieldEvaluation><xpathexpression>//putWhateverWordsIwantInsideThisTag/myname/value = wf:ruledata('myname')</xpathexpression></fieldEvaluation>"+
561 				"</fieldDef>"+
562 				"<fieldDef name=\"theGender\" title=\"Gender\" workflowType=\"ALL\">"+
563 					"<value>male</value>"+
564 					"<display>"+
565 						"<type>radio</type>"+
566 						"<values title=\"Male\">male</values>"+
567 						"<values title=\"Female\">female</values>"+
568 					"</display>"+
569 					"<fieldEvaluation><xpathexpression>//putWhateverWordsIwantInsideThisTag/theGender/value = wf:ruledata('theGender')</xpathexpression></fieldEvaluation>"+
570 				"</fieldDef>"+
571 				"<fieldDef name=\"myFavoriteColor\" title=\"Color\" workflowType=\"ALL\">" +
572 					"<value>blue</value>" +
573 					"<display>" +
574 						"<type>select</type>" +
575 						"<values title=\"Red\">red</values>" +
576 						"<values title=\"Green\">green</values>" +
577 						"<values title=\"Blue\" selected=\"true\">blue</values>" +
578 					"</display>" +
579 					"<fieldEvaluation><xpathexpression>//putWhateverWordsIwantInsideThisTag/myFavoriteColor/value = wf:ruledata('myFavoriteColor')</xpathexpression></fieldEvaluation>"+
580 				"</fieldDef>"+
581 				"<fieldDef name=\"maxDollar\" title=\"Max dollar\" workflowType=\"RULE\">" +
582 					"<display>" +
583 						"<type>text</type>" +
584 					"</display>" +
585 					"<fieldEvaluation><xpathexpression>//putWhateverWordsIwantInsideThisTag/myMoney/value &lt;= wf:ruledata('maxDollar')</xpathexpression></fieldEvaluation>"+
586 				"</fieldDef>"+
587 				"<fieldDef name=\"minDollar\" title=\"Min dollar\" workflowType=\"RULE\">" +
588 					"<display>" +
589 						"<type>text</type>" +
590 					"</display>" +
591 					"<fieldEvaluation><xpathexpression>//putWhateverWordsIwantInsideThisTag/myMoney/value &gt;= wf:ruledata('minDollar')</xpathexpression></fieldEvaluation>"+
592 			    "</fieldDef>"+
593 				"<fieldDef name=\"myMoney\" title=\"Total dollar\" workflowType=\"REPORT\">" +
594 					"<display>" +
595 						"<type>text</type>" +
596 					"</display>" +
597 		        "</fieldDef>"+
598 
599 		        "<xmlDocumentContent>"+
600 		        	"<putWhateverWordsIwantInsideThisTag>"+
601 		        		"<myname>"+
602 		        			"<value>%myname%</value>"+
603 	        		    "</myname>"+
604 	        		    "<theGender>"+
605 	        		    	"<value>%theGender%</value>"+
606 	    				"</theGender>"+
607 	    				"<myFavoriteColor>"+
608 	    					"<value>%myFavoriteColor%</value>"+
609 						"</myFavoriteColor>"+
610 		        		"<myMoney>"+
611 	        				"<value>%myMoney%</value>"+
612 	        			"</myMoney>"+
613 					"</putWhateverWordsIwantInsideThisTag>"+
614 		        "</xmlDocumentContent>"+
615             "</routingConfig>";
616 		try {
617 			paramMap = new HashMap<String, String>();
618 			paramMap.put("myname", "jack");
619 			paramMap.put("theGender", "male");
620 			paramMap.put("myFavoriteColor", "blue");
621 			paramMap.put("myMoney", "10");
622 
623 			attribute.setParamMap(paramMap);
624 
625 			RuleAttribute ruleAttribute = new RuleAttribute();
626 			ruleAttribute.setXmlConfigData(routingConfig);
627 			ruleAttribute.setName("MyUniqueRuleAttribute2");
628 			attribute.setExtensionDefinition(RuleAttribute.to(ruleAttribute));
629 
630 			String docContent = attribute.getDocContent();
631 			assertTrue("DocContent was not found.", docContent != null && docContent.length() > 0);
632 
633 
634 			XPath xpath = XPathFactory.newInstance().newXPath();
635 			Element foundDocContent = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(new BufferedReader(new StringReader(docContent)))).getDocumentElement();
636 
637 			String findStuff = "//putWhateverWordsIwantInsideThisTag/myMoney/value";
638 			assertTrue("Document content does not contain field myMoney with a value of 10.", "10".equals(xpath.evaluate(findStuff, foundDocContent, XPathConstants.STRING)));
639 
640 			findStuff = "//putWhateverWordsIwantInsideThisTag/myFavoriteColor/value";
641 			assertTrue("Document content does not contain field myFavoriteColor with value of blue.", "blue".equals(xpath.evaluate(findStuff, foundDocContent, XPathConstants.STRING)));
642 
643 			findStuff = "//putWhateverWordsIwantInsideThisTag/theGender/value";
644 			assertTrue("Document content does not contain field theGender with value of male.", "male".equals(xpath.evaluate(findStuff, foundDocContent, XPathConstants.STRING)));
645 
646 			findStuff = "//putWhateverWordsIwantInsideThisTag/myname/value";
647 			assertTrue("Document content does not contain field myname with value of jack.", "jack".equals(xpath.evaluate(findStuff, foundDocContent, XPathConstants.STRING)));
648 
649 		} catch(Exception e){
650 			e.printStackTrace();
651 		}
652 	}
653 }