View Javadoc

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