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.krad.workflow;
17  
18  import org.apache.commons.logging.Log;
19  import org.apache.commons.logging.LogFactory;
20  import org.junit.Ignore;
21  import org.junit.Test;
22  import org.kuali.rice.core.api.impex.xml.XmlConstants;
23  import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
24  import org.kuali.rice.core.api.reflect.ObjectDefinition;
25  import org.kuali.rice.kew.api.KewApiConstants;
26  import org.kuali.rice.kew.api.extension.ExtensionDefinition;
27  import org.kuali.rice.kew.rule.bo.RuleAttribute;
28  import org.kuali.rice.kew.rule.xmlrouting.XPathHelper;
29  import org.kuali.rice.krad.datadictionary.AttributeDefinition;
30  import org.kuali.rice.krad.datadictionary.BusinessObjectEntry;
31  import org.kuali.rice.krad.datadictionary.DocumentEntry;
32  import org.kuali.rice.krad.service.DataDictionaryService;
33  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
34  import org.kuali.rice.krad.workflow.attribute.KualiXmlAttribute;
35  import org.kuali.rice.krad.workflow.attribute.KualiXmlAttributeHelper;
36  import org.kuali.rice.krad.workflow.attribute.KualiXmlRuleAttributeImpl;
37  import org.kuali.rice.krad.workflow.attribute.KualiXmlSearchableAttributeImpl;
38  import org.kuali.test.KRADTestCase;
39  import org.w3c.dom.NamedNodeMap;
40  import org.w3c.dom.Node;
41  import org.w3c.dom.NodeList;
42  import org.xml.sax.InputSource;
43  
44  import javax.xml.transform.Result;
45  import javax.xml.transform.Source;
46  import javax.xml.transform.TransformerException;
47  import javax.xml.transform.TransformerFactory;
48  import javax.xml.transform.dom.DOMSource;
49  import javax.xml.transform.stream.StreamResult;
50  import javax.xml.xpath.XPath;
51  import javax.xml.xpath.XPathConstants;
52  import java.io.StringReader;
53  import java.io.StringWriter;
54  import java.util.HashSet;
55  import java.util.Set;
56  
57  import static org.junit.Assert.*;
58  
59  
60  /**
61   * KualiXMLAttributeImplTest tests the {@link KualiXmlAttributeHelper} operations of getting data from the data dictionary for workflow
62   * attributes
63   * 
64   * @author Kuali Rice Team (rice.collab@kuali.org)
65   */
66  @Ignore
67  public class KualiXMLAttributeImplTest extends KRADTestCase {
68      private static Log LOG = LogFactory.getLog(KualiXMLAttributeImplTest.class);
69  
70      private static final String RULE_ATTRIBUTE_CONFIG_NODE_NAME = XmlConstants.ROUTING_CONFIG;
71      private static final String SEARCH_ATTRIBUTE_CONFIG_NODE_NAME = XmlConstants.SEARCHING_CONFIG;
72  
73      XPath myXPath = XPathHelper.newXPath();
74      String ruleAttributeXml = "";
75      String searchAttributeXml = "";
76  //    private boolean testFailed = false;
77  
78      @Override
79      public void setUp() throws Exception {
80          super.setUp();
81          // read in the file and make it a string
82  
83  //        InputStream is = new FileInputStream(getBaseDir() + "/src/test/resources/org/kuali/rice/kew/batch/data/RuleAttributeContent.xml");
84  //        is.
85  //        if ((StringUtils.isNotBlank(ruleAttributeXml)) && (StringUtils.isNotBlank(searchAttributeXml))) {
86  //            return;
87  //        }
88  //
89  //        DataSource mySource = KEWServiceLocator.getDataSource();
90  //        ruleAttributeXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<data >\n<ruleAttributes>\n";
91  //        searchAttributeXml = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<data >\n<ruleAttributes>\n";
92  //        Connection dbCon = null;
93  //        try {
94  //
95  //            dbCon = mySource.getConnection();
96  //            Statement dbAsk = dbCon.createStatement();
97  //            ResultSet dbAnswer = dbAsk.executeQuery("select * from EN_RULE_ATTRIB_T");
98  //            // ResultSet dbAnswer = dbAsk.executeQuery("select * from EN_RULE_ATTRIB_T where RULE_ATTRIB_NM =
99  //            // 'SystemParameterRoutingAttribute'");
100 //
101 //            while (dbAnswer.next()) {
102 //                String className = dbAnswer.getString("RULE_ATTRIB_CLS_NM");
103 //                if (StringUtils.isNotBlank(className)) {
104 //                    try {
105 //                        if (KualiXmlAttribute.class.isAssignableFrom(Class.forName(className))) {
106 //                            LOG.debug("Adding attribute to test with class name " + className);
107 //                            String attributeType = dbAnswer.getString("RULE_ATTRIB_TYP");
108 //                            if (KewApiConstants.RULE_XML_ATTRIBUTE_TYPE.equals(attributeType)) {
109 //                                ruleAttributeXml = ruleAttributeXml + "<ruleAttribute>\n\t<name>";
110 //                                ruleAttributeXml = ruleAttributeXml + dbAnswer.getString("RULE_ATTRIB_NM");
111 //                                ruleAttributeXml = ruleAttributeXml + "</name>\n\t<className>";
112 //                                ruleAttributeXml = ruleAttributeXml + className;
113 //                                ruleAttributeXml = ruleAttributeXml + "</className>\n\t<label>";
114 //                                ruleAttributeXml = ruleAttributeXml + dbAnswer.getString("RULE_ATTRIB_LBL_TXT");
115 //                                ruleAttributeXml = ruleAttributeXml + "</label>\n\t<description>";
116 //                                ruleAttributeXml = ruleAttributeXml + dbAnswer.getString("RULE_ATTRIB_DESC");
117 //                                ruleAttributeXml = ruleAttributeXml + "</description>\n\t<type>";
118 //                                ruleAttributeXml = ruleAttributeXml + attributeType;
119 //                                ruleAttributeXml = ruleAttributeXml + "</type>\n\t" + dbAnswer.getString("RULE_ATTRIB_XML_RTE_TXT") + "\n</ruleAttribute>\n";
120 //
121 //                            }
122 //                            else if (KewApiConstants.SEARCHABLE_XML_ATTRIBUTE_TYPE.equals(attributeType)) {
123 //                                searchAttributeXml = searchAttributeXml + "<ruleAttribute>\n\t<name>";
124 //                                searchAttributeXml = searchAttributeXml + dbAnswer.getString("RULE_ATTRIB_NM");
125 //                                searchAttributeXml = searchAttributeXml + "</name>\n\t<className>";
126 //                                searchAttributeXml = searchAttributeXml + className;
127 //                                searchAttributeXml = searchAttributeXml + "</className>\n\t<label>";
128 //                                searchAttributeXml = searchAttributeXml + dbAnswer.getString("RULE_ATTRIB_LBL_TXT");
129 //                                searchAttributeXml = searchAttributeXml + "</label>\n\t<description>";
130 //                                searchAttributeXml = searchAttributeXml + dbAnswer.getString("RULE_ATTRIB_DESC");
131 //                                searchAttributeXml = searchAttributeXml + "</description>\n\t<type>";
132 //                                searchAttributeXml = searchAttributeXml + attributeType;
133 //                                searchAttributeXml = searchAttributeXml + "</type>\n\t" + dbAnswer.getString("RULE_ATTRIB_XML_RTE_TXT") + "\n</ruleAttribute>\n";
134 //
135 //                            }
136 //                        }
137 //                        else {
138 //                            LOG.debug("Skipping attribute with class name " + className);
139 //                        }
140 //                    }
141 //                    catch (ClassNotFoundException cnfe) {
142 //                        LOG.debug("Could not find class for name '" + className + "'");
143 //                    }
144 //                }
145 //            }
146 //            ruleAttributeXml = ruleAttributeXml + "</ruleAttributes>\n</data>\n";
147 //            searchAttributeXml = searchAttributeXml + "</ruleAttributes>\n</data>\n";
148 //
149 //            ruleAttributeXml = ruleAttributeXml.replaceAll(" & ", " &amp; ");
150 //            searchAttributeXml = searchAttributeXml.replaceAll(" & ", " &amp; ");
151 //
152 //            loadDataDictionaryEntries();
153 //        }
154 //        catch (Exception e) {
155 //            e.printStackTrace();
156 //        }
157 //        finally {
158 //            try {
159 //                dbCon.close();
160 //            }
161 //            catch (SQLException sqle2) {
162 //                sqle2.printStackTrace();
163 //            }
164 //        }
165     }
166 
167     /**
168      * goes through all of the ruleAttributes in the inputSource and tries to get a label out of the data dictionary
169      */
170     @Test public void testConfirmLabels() {
171         boolean failed = false;
172         // test rule xml attributes
173         failed |= confirmLabels(KualiXmlAttributeHelper.notFound, ruleAttributeXml, RULE_ATTRIBUTE_CONFIG_NODE_NAME);
174 
175         // test search xml attributes
176         failed |= confirmLabels(KualiXmlAttributeHelper.notFound, searchAttributeXml, SEARCH_ATTRIBUTE_CONFIG_NODE_NAME);
177         
178         assertFalse("At least one label was incorrect", failed);
179     }
180 
181     /**
182      * accepts a Node, and if all goes well, returns the exact same Node with expected changes
183      *
184      * <p>The node should have the name and title attributes added to
185      * the fieldDef element. This exercises the getConfigXML method on the class under test.</p>
186      * 
187      * @param xmlNode - an input node
188      * @return the input node with attributes added
189      * @throws TransformerException
190      */
191     private Node configureRuleAttribute(Node xmlNode, KualiXmlAttribute myAttribute) throws TransformerException {
192         ExtensionDefinition.Builder extensionDefinition = ExtensionDefinition.Builder.create("fakeName", "fakeType", "fakeResourceDescriptor");
193 
194         StringWriter xmlBuffer = new StringWriter();
195         Source source = new DOMSource(xmlNode);
196         Result result = new StreamResult(xmlBuffer);
197         TransformerFactory.newInstance().newTransformer().transform(source, result);
198 
199         extensionDefinition.getConfiguration().put(KewApiConstants.ATTRIBUTE_XML_CONFIG_DATA, new String(xmlBuffer.getBuffer()));
200 
201         if (LOG.isDebugEnabled()) {
202             LOG.debug("This is the XML that was added to the attribute");
203             LOG.debug(new String(xmlBuffer.getBuffer()));
204             StringWriter xmlBuffer2 = new StringWriter();
205             Source source2 = new DOMSource(xmlNode);
206             Result result2 = new StreamResult(xmlBuffer2);
207             TransformerFactory.newInstance().newTransformer().transform(source2, result2);
208             LOG.debug("This is the XML that was returned from the ruleAttribute");
209             LOG.debug(new String(xmlBuffer2.getBuffer()));
210         }
211         return myAttribute.getConfigXML(extensionDefinition.build());
212     }
213 
214     /**
215      * compares the label from the test to the expected, or not expected, value for all of the rule attributes in the file
216      *
217      * <p>The inputSource file should be as close to the production version as possible, as described by the class comments. It
218      * accepts the string to test against as a parameter.</p>
219      * 
220      * @param testString
221      * @param attributeXml
222      * @param configNodeName
223      */
224     private boolean confirmLabels(String testString, String attributeXml, String configNodeName) {
225         boolean testFailed = false;
226         String theTitle = "";
227         String theName = "";
228         String attributeName = "";
229         try {
230             NodeList tempList = (NodeList) myXPath.evaluate("//ruleAttribute", new InputSource(new StringReader(attributeXml)), XPathConstants.NODESET);
231             for (int i = 0; i < tempList.getLength(); i++) { // loop over ruleattributes
232                 Node originalNode = tempList.item(i);
233                 Set ruleAttributeFieldDefNames = new HashSet();
234                 Set ruleAttributeFieldDefTitles = new HashSet();
235                 attributeName = (String) myXPath.evaluate(WorkflowUtils.XSTREAM_MATCH_RELATIVE_PREFIX + "name", originalNode, XPathConstants.STRING);
236                 Node classNameNode = (Node) myXPath.evaluate(WorkflowUtils.XSTREAM_MATCH_RELATIVE_PREFIX + "className", originalNode, XPathConstants.NODE);
237                 if ((classNameNode != null) && (classNameNode.getFirstChild() != null)) {
238                     if (LOG.isInfoEnabled()) {
239                         LOG.info("Checking attribute with name '" + attributeName + "'");
240                     }
241                     KualiXmlAttribute myAttribute = (KualiXmlAttribute) GlobalResourceLoader.getObject(new ObjectDefinition(classNameNode.getFirstChild().getNodeValue()));
242                     Node xmlNode = configureRuleAttribute(originalNode, myAttribute);
243                     NamedNodeMap fieldDefAttributes = null;
244                     String potentialFailMessage = "";
245 
246                     try {
247                         NodeList xmlNodeList = (NodeList) myXPath.evaluate("//fieldDef", xmlNode, XPathConstants.NODESET);
248 
249                         for (int j = 0; j < xmlNodeList.getLength(); j++) {
250                             Node fieldDefXmlNode = xmlNodeList.item(j);
251                             fieldDefAttributes = fieldDefXmlNode.getAttributes();
252 
253                             theTitle = fieldDefAttributes.getNamedItem("title").getNodeValue();// Making sure they are clean
254                             theName = fieldDefAttributes.getNamedItem("name").getNodeValue();
255                             if (LOG.isDebugEnabled()) {
256                                 LOG.debug(attributeName);
257                                 LOG.debug("name=" + theName + "   title=" + theTitle);
258                             }
259                             if (ruleAttributeFieldDefNames.contains(theName)) {
260                                 // names of fieldDefs inside a single attribute must be unique
261                                 potentialFailMessage = "Each fieldDef name on a single attribute must be unique and the fieldDef name '" + theName + "' already exists on the attribute '" + attributeName + "'";
262                                 fail(potentialFailMessage);
263                             }
264                             else {
265                                 ruleAttributeFieldDefNames.add(theName);
266                             }
267                             if (testString.equals(KualiXmlAttributeHelper.notFound)) {
268                                 potentialFailMessage = "Each fieldDef title should be a valid value and currently the title for attribute '" + attributeName + "' is '" + theTitle + "'";
269                                 assertFalse(potentialFailMessage, theTitle.equals(testString));
270                                 if (ruleAttributeFieldDefTitles.contains(theTitle)) {
271                                     /*
272                                      * Titles of fieldDefs inside a single attribute should be unique in the normal case. Having two
273                                      * fields with the same label would certainly confuse the user. However, due to the way the
274                                      * confirmSource test works, all the titles/labels must be the same. So only run this check when
275                                      * not in the confirmSource test.
276                                      */
277                                     potentialFailMessage = "Each fieldDef title on a single attribute must be unique and the fieldDef title '" + theTitle + "' already exists on the attribute '" + attributeName + "'";
278                                     fail(potentialFailMessage);
279                                 }
280                                 else {
281                                     ruleAttributeFieldDefTitles.add(theTitle);
282                                 }
283                             }
284                             else {
285                                 potentialFailMessage = "For attribute '" + attributeName + "' the title should have been '" + testString + "' but was actually '" + theTitle + "'";
286                                 assertEquals(potentialFailMessage, testString, theTitle);
287                             }
288                         }
289                     }
290                     catch (AssertionError afe) {
291                         LOG.warn("Assertion Failed for attribute '" + attributeName + "' with error " + potentialFailMessage, afe);
292                         testFailed = true;
293                     }
294                     finally {
295                         attributeName = "";
296                     }
297                 }
298                 else {
299                     throw new RuntimeException("Could not find class for attribute named '" + attributeName + "'");
300                 }
301             }
302         }
303         catch (Exception e) {
304             LOG.error("General Exception thrown for attribute '" + attributeName + "'", e);
305             testFailed = true;
306         }
307         return testFailed;
308     }
309 
310     /**
311      * confirms that the labels are coming from the data dictionary
312      *
313      * <p>This is done by modifying all the dictionary values
314      * programatically to a nonsense value. It then rebuilds the Hash Table and runs confirmLabels() to make sure the labels have
315      * changed.</p>
316      */
317     @Test public void testLabelSource() {
318         DataDictionaryService myDDService = KRADServiceLocatorWeb.getDataDictionaryService();
319         XPath xpath = XPathHelper.newXPath();
320         String nonsenseString = "BananaRama";
321         for (Object tempEntity : myDDService.getDataDictionary().getBusinessObjectEntries().values()) {
322 
323             for ( AttributeDefinition attribute : ((BusinessObjectEntry) tempEntity).getAttributes() ) {
324                 attribute.setLabel(nonsenseString);
325                 attribute.setShortLabel(nonsenseString);
326             }
327 
328         }
329         for (Object tempEntity : myDDService.getDataDictionary().getDocumentEntries().values()) {
330 
331             for ( AttributeDefinition attribute : ((DocumentEntry) tempEntity).getAttributes() ) {
332                 attribute.setLabel(nonsenseString);
333                 attribute.setShortLabel(nonsenseString);
334             }
335 
336         }
337         // KualiXmlAttributeHelper.buildDictionaryHash();
338 
339         boolean failed = false;
340         assertFalse("At least one label was incorrect", failed);
341         // test rule xml attributes
342         failed |= confirmLabels(nonsenseString, ruleAttributeXml, RULE_ATTRIBUTE_CONFIG_NODE_NAME);
343 
344         // test search xml attributes
345         failed |= confirmLabels(nonsenseString, searchAttributeXml, SEARCH_ATTRIBUTE_CONFIG_NODE_NAME);
346 
347         assertFalse("At least one label was incorrect", failed);
348     }
349 
350     /*
351     unused method
352 
353     private void loadDataDictionaryEntries() throws Exception {
354         KualiXmlRuleAttributeImpl myAttribute = new KualiXmlRuleAttributeImpl();
355         NamedNodeMap fieldDefAttributes = null;
356         NodeList tempList = (NodeList) myXPath.evaluate("//ruleAttribute", new InputSource(new StringReader(ruleAttributeXml)), XPathConstants.NODESET);
357         for (int i = 0; i < tempList.getLength(); i++) {
358             Node xmlNode = configureRuleAttribute(tempList.item(i), myAttribute);
359         }
360         KualiXmlSearchableAttributeImpl mySearchAttribute = new KualiXmlSearchableAttributeImpl();
361         fieldDefAttributes = null;
362         tempList = (NodeList) myXPath.evaluate("//ruleAttribute", new InputSource(new StringReader(searchAttributeXml)), XPathConstants.NODESET);
363         for (int i = 0; i < tempList.getLength(); i++) {
364             Node xmlNode = configureRuleAttribute(tempList.item(i), mySearchAttribute);
365         }
366     }*/
367 }