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