View Javadoc
1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kns.workflow;
17  
18  import org.apache.commons.io.IOUtils;
19  import org.apache.commons.logging.Log;
20  import org.apache.commons.logging.LogFactory;
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.InputStream;
50  import java.io.StringReader;
51  import java.io.StringWriter;
52  import java.util.HashSet;
53  import java.util.Set;
54  
55  import org.junit.Assert;
56  
57  import static org.junit.Assert.assertNotNull;
58  
59  /**
60   * KualiXMLAttributeImplTest tests the {@link KualiXmlAttributeHelper} operations of getting data from the data dictionary for workflow
61   * attributes
62   * 
63   * @author Kuali Rice Team (rice.collab@kuali.org)
64   *
65   * @deprecated KNS test class, convert to KRAD equivalent if applicable.
66   */
67  @Deprecated
68  public class KualiXMLAttributeImplTest extends KRADTestCase {
69      private static Log LOG = LogFactory.getLog(KualiXMLAttributeImplTest.class);
70  
71      private static final String RULE_ATTRIBUTE_CONFIG_NODE_NAME = XmlConstants.ROUTING_CONFIG;
72      private static final String SEARCH_ATTRIBUTE_CONFIG_NODE_NAME = XmlConstants.SEARCHING_CONFIG;
73  
74      XPath myXPath = XPathHelper.newXPath();
75      String ruleAttributeXml = "";
76      String searchAttributeXml = "";
77  
78      @Override
79      public void setUp() throws Exception {
80          super.setUp();
81  
82          InputStream ruleInputStream = null;
83          InputStream searchInputStream = null;
84  
85          try {
86              ruleInputStream = getClass().getResourceAsStream("RuleAttributes.xml");
87              assertNotNull(ruleInputStream);
88              ruleAttributeXml = IOUtils.toString(ruleInputStream);
89  
90              searchInputStream = getClass().getResourceAsStream("SearchAttributes.xml");
91              assertNotNull(searchInputStream);
92              searchAttributeXml = IOUtils.toString(searchInputStream);
93          } finally {
94              if (ruleInputStream != null) {
95                  ruleInputStream.close();
96              }
97  
98              if (searchInputStream != null) {
99                  searchInputStream.close();
100             }
101         }
102     }
103 
104     /**
105      * goes through all of the ruleAttributes in the inputSource and tries to get a label out of the data dictionary
106      */
107     @Test public void testConfirmLabels() {
108         boolean failed = false;
109         // test rule xml attributes
110         failed |= confirmLabels(KualiXmlAttributeHelper.notFound, ruleAttributeXml, RULE_ATTRIBUTE_CONFIG_NODE_NAME);
111 
112         // test search xml attributes
113         failed |= confirmLabels(KualiXmlAttributeHelper.notFound, searchAttributeXml, SEARCH_ATTRIBUTE_CONFIG_NODE_NAME);
114         
115         Assert.assertFalse("At least one label was incorrect", failed);
116     }
117 
118     /**
119      * accepts a Node, and if all goes well, returns the exact same Node with expected changes
120      *
121      * <p>The node should have the name and title attributes added to
122      * the fieldDef element. This exercises the getConfigXML method on the class under test.</p>
123      * 
124      * @param xmlNode - an input node
125      * @return the input node with attributes added
126      * @throws TransformerException
127      */
128     private Node configureRuleAttribute(Node xmlNode, KualiXmlAttribute myAttribute) throws TransformerException {
129         ExtensionDefinition.Builder extensionDefinition = ExtensionDefinition.Builder.create("fakeName", "fakeType", "fakeResourceDescriptor");
130 
131         StringWriter xmlBuffer = new StringWriter();
132         Source source = new DOMSource(xmlNode);
133         Result result = new StreamResult(xmlBuffer);
134         TransformerFactory.newInstance().newTransformer().transform(source, result);
135 
136         extensionDefinition.getConfiguration().put(KewApiConstants.ATTRIBUTE_XML_CONFIG_DATA, new String(xmlBuffer.getBuffer()));
137 
138         if (LOG.isDebugEnabled()) {
139             LOG.debug("This is the XML that was added to the attribute");
140             LOG.debug(new String(xmlBuffer.getBuffer()));
141             StringWriter xmlBuffer2 = new StringWriter();
142             Source source2 = new DOMSource(xmlNode);
143             Result result2 = new StreamResult(xmlBuffer2);
144             TransformerFactory.newInstance().newTransformer().transform(source2, result2);
145             LOG.debug("This is the XML that was returned from the ruleAttribute");
146             LOG.debug(new String(xmlBuffer2.getBuffer()));
147         }
148         return myAttribute.getConfigXML(extensionDefinition.build());
149     }
150 
151     /**
152      * compares the label from the test to the expected, or not expected, value for all of the rule attributes in the file
153      *
154      * <p>The inputSource file should be as close to the production version as possible, as described by the class comments. It
155      * accepts the string to test against as a parameter.</p>
156      * 
157      * @param testString
158      * @param attributeXml
159      * @param configNodeName
160      */
161     private boolean confirmLabels(String testString, String attributeXml, String configNodeName) {
162         boolean testFailed = false;
163         String theTitle = "";
164         String theName = "";
165         String attributeName = "";
166         try {
167             NodeList tempList = (NodeList) myXPath.evaluate("//ruleAttribute", new InputSource(new StringReader(attributeXml)), XPathConstants.NODESET);
168             for (int i = 0; i < tempList.getLength(); i++) { // loop over ruleattributes
169                 Node originalNode = tempList.item(i);
170                 Set ruleAttributeFieldDefNames = new HashSet();
171                 Set ruleAttributeFieldDefTitles = new HashSet();
172                 attributeName = (String) myXPath.evaluate(WorkflowUtils.XSTREAM_MATCH_RELATIVE_PREFIX + "name", originalNode, XPathConstants.STRING);
173                 Node classNameNode = (Node) myXPath.evaluate(WorkflowUtils.XSTREAM_MATCH_RELATIVE_PREFIX + "className", originalNode, XPathConstants.NODE);
174                 if ((classNameNode != null) && (classNameNode.getFirstChild() != null)) {
175                     if (LOG.isInfoEnabled()) {
176                         LOG.info("Checking attribute with name '" + attributeName + "'");
177                     }
178                     KualiXmlAttribute myAttribute = (KualiXmlAttribute) GlobalResourceLoader.getObject(new ObjectDefinition(classNameNode.getFirstChild().getNodeValue()));
179                     Node xmlNode = configureRuleAttribute(originalNode, myAttribute);
180                     NamedNodeMap fieldDefAttributes = null;
181                     String potentialFailMessage = "";
182 
183                     try {
184                         NodeList xmlNodeList = (NodeList) myXPath.evaluate("//fieldDef", xmlNode, XPathConstants.NODESET);
185 
186                         for (int j = 0; j < xmlNodeList.getLength(); j++) {
187                             Node fieldDefXmlNode = xmlNodeList.item(j);
188                             fieldDefAttributes = fieldDefXmlNode.getAttributes();
189 
190                             theTitle = fieldDefAttributes.getNamedItem("title").getNodeValue();// Making sure they are clean
191                             theName = fieldDefAttributes.getNamedItem("name").getNodeValue();
192                             if (LOG.isDebugEnabled()) {
193                                 LOG.debug(attributeName);
194                                 LOG.debug("name=" + theName + "   title=" + theTitle);
195                             }
196                             if (ruleAttributeFieldDefNames.contains(theName)) {
197                                 // names of fieldDefs inside a single attribute must be unique
198                                 potentialFailMessage = "Each fieldDef name on a single attribute must be unique and the fieldDef name '" + theName + "' already exists on the attribute '" + attributeName + "'";
199                                 Assert.fail(potentialFailMessage);
200                             }
201                             else {
202                                 ruleAttributeFieldDefNames.add(theName);
203                             }
204                             if (testString.equals(KualiXmlAttributeHelper.notFound)) {
205                                 potentialFailMessage = "Each fieldDef title should be a valid value and currently the title for attribute '" + attributeName + "' is '" + theTitle + "'";
206                                 Assert.assertFalse(potentialFailMessage, theTitle.equals(testString));
207                                 if (ruleAttributeFieldDefTitles.contains(theTitle)) {
208                                     /*
209                                      * Titles of fieldDefs inside a single attribute should be unique in the normal case. Having two
210                                      * fields with the same label would certainly confuse the user. However, due to the way the
211                                      * confirmSource test works, all the titles/labels must be the same. So only run this check when
212                                      * not in the confirmSource test.
213                                      */
214                                     potentialFailMessage = "Each fieldDef title on a single attribute must be unique and the fieldDef title '" + theTitle + "' already exists on the attribute '" + attributeName + "'";
215                                     Assert.fail(potentialFailMessage);
216                                 }
217                                 else {
218                                     ruleAttributeFieldDefTitles.add(theTitle);
219                                 }
220                             }
221                             else {
222                                 potentialFailMessage = "For attribute '" + attributeName + "' the title should have been '" + testString + "' but was actually '" + theTitle + "'";
223                                 Assert.assertEquals(potentialFailMessage, testString, theTitle);
224                             }
225                         }
226                     }
227                     catch (AssertionError afe) {
228                         LOG.warn("Assertion Failed for attribute '" + attributeName + "' with error " + potentialFailMessage, afe);
229                         testFailed = true;
230                     }
231                     finally {
232                         attributeName = "";
233                     }
234                 }
235                 else {
236                     throw new RuntimeException("Could not find class for attribute named '" + attributeName + "'");
237                 }
238             }
239         }
240         catch (Exception e) {
241             LOG.error("General Exception thrown for attribute '" + attributeName + "'", e);
242             testFailed = true;
243         }
244         return testFailed;
245     }
246 
247     /**
248      * confirms that the labels are coming from the data dictionary
249      *
250      * <p>This is done by modifying all the dictionary values
251      * programatically to a nonsense value. It then rebuilds the Hash Table and runs confirmLabels() to make sure the labels have
252      * changed.</p>
253      */
254     @Test public void testLabelSource() {
255         DataDictionaryService myDDService = KRADServiceLocatorWeb.getDataDictionaryService();
256         String nonsenseString = "BananaRama";
257         for (Object tempEntity : myDDService.getDataDictionary().getBusinessObjectEntries().values()) {
258 
259             for ( AttributeDefinition attribute : ((BusinessObjectEntry) tempEntity).getAttributes() ) {
260                 attribute.setLabel(nonsenseString);
261                 attribute.setShortLabel(nonsenseString);
262             }
263 
264         }
265         for (Object tempEntity : myDDService.getDataDictionary().getDocumentEntries().values()) {
266 
267             for ( AttributeDefinition attribute : ((DocumentEntry) tempEntity).getAttributes() ) {
268                 attribute.setLabel(nonsenseString);
269                 attribute.setShortLabel(nonsenseString);
270             }
271 
272         }
273 
274         boolean failed = false;
275         Assert.assertFalse("At least one label was incorrect", failed);
276         // test rule xml attributes
277         failed |= confirmLabels(nonsenseString, ruleAttributeXml, RULE_ATTRIBUTE_CONFIG_NODE_NAME);
278 
279         // test search xml attributes
280         failed |= confirmLabels(nonsenseString, searchAttributeXml, SEARCH_ATTRIBUTE_CONFIG_NODE_NAME);
281 
282         Assert.assertFalse("At least one label was incorrect", failed);
283     }
284 
285 }