View Javadoc
1   /**
2    * Copyright 2005-2015 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.edl.impl.components;
17  
18  import javax.xml.xpath.XPath;
19  import javax.xml.xpath.XPathConstants;
20  import javax.xml.xpath.XPathExpressionException;
21  
22  import org.apache.commons.lang.StringUtils;
23  import org.kuali.rice.edl.impl.EDLContext;
24  import org.kuali.rice.edl.impl.EDLModelComponent;
25  import org.kuali.rice.kew.rule.xmlrouting.XPathHelper;
26  import org.w3c.dom.Document;
27  import org.w3c.dom.Element;
28  import org.w3c.dom.Node;
29  import org.w3c.dom.NodeList;
30  
31  
32  
33  /**
34   * Looks at a field definition for a select field and attempts to analyze and resolve any valuesGroups based on document data.
35   * The result of this is to take a fieldDef that has a valuesGroup and either remove it if it does not match or replace the
36   * <valuesGroup> element with a series of <values> elements that include the values contained with the values group.
37   * 
38   * <p>This allows for <select> fields to be dependent upon one another. 
39   * 
40   * @author Kuali Rice Team (rice.collab@kuali.org)
41   */
42  public class SelectControlEDLComponent implements EDLModelComponent {
43  
44  	public void updateDOM(Document dom, Element currentDefinitionElement, EDLContext edlContext) {
45  	    Element currentVersion = VersioningPreprocessor.findCurrentVersion(dom);
46  	    XPath xPath = XPathHelper.newXPath(dom);
47  	    try {
48  		NodeList selectFieldDefs = (NodeList)xPath.evaluate("//fieldDef[display/type = 'select' and display/valuesGroup] | //fieldDef[display/type = 'select_refresh' and display/valuesGroup]", dom, XPathConstants.NODESET);
49  		for (int fIndex = 0; fIndex < selectFieldDefs.getLength(); fIndex++) {
50  		    Element fieldDef = (Element)selectFieldDefs.item(fIndex);
51  		NodeList valuesGroups = (NodeList)xPath.evaluate("./display/valuesGroup", fieldDef, XPathConstants.NODESET);
52  		for (int index = 0; index < valuesGroups.getLength(); index++) {
53  		    Element valuesGroupElem = (Element)valuesGroups.item(index);
54  		    NodeList dependsOnFields = (NodeList)xPath.evaluate("./dependsOn/field", valuesGroupElem, XPathConstants.NODESET);
55  		    String fieldEvalExpression = "";
56  		    for (int dIndex = 0; dIndex < dependsOnFields.getLength(); dIndex++) {
57  			if (!StringUtils.isBlank(fieldEvalExpression)) {
58  			    fieldEvalExpression += " and ";
59  			}
60  			Element fieldElem = (Element)dependsOnFields.item(dIndex);
61  			String name = fieldElem.getAttribute("name");
62  			String value = fieldElem.getTextContent();
63  			fieldEvalExpression += "./field[@name='" + name + "']/value = '" + value + "'";
64  		    }
65  		    if ((Boolean)xPath.evaluate(fieldEvalExpression, currentVersion, XPathConstants.BOOLEAN)) {
66  			includeValuesGroup(valuesGroupElem);
67  		    } else {
68  			// remove the valuesGroup as it did not match
69  			valuesGroupElem.getParentNode().removeChild(valuesGroupElem);
70  		    }
71  		}
72  		}
73  	    } catch (XPathExpressionException e) {
74  		throw new RuntimeException("Failed to evaluate xpath expression.", e);
75  	    }
76  	}
77  	
78  	protected void includeValuesGroup(Element valuesGroupElem) {
79  	    Element valuesGroupParent = (Element)valuesGroupElem.getParentNode();
80  	    NodeList valuesGroupChildren = valuesGroupElem.getChildNodes();
81  	    
82  	    for (int index = 0; index < valuesGroupChildren.getLength(); index++) {
83  		Node item = valuesGroupChildren.item(index);
84  		if (Node.ELEMENT_NODE == item.getNodeType() && item.getNodeName().equals("values")) {
85  		    valuesGroupParent.insertBefore(item, valuesGroupElem);
86  		}
87  	    }
88  	    valuesGroupParent.removeChild(valuesGroupElem);
89  	}	
90  	
91  }