View Javadoc

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