001    /**
002     * Copyright 2005-2013 The Kuali Foundation
003     *
004     * Licensed under the Educational Community License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     * http://www.opensource.org/licenses/ecl2.php
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package org.kuali.rice.edl.impl.components;
017    
018    import javax.xml.xpath.XPath;
019    import javax.xml.xpath.XPathConstants;
020    import javax.xml.xpath.XPathExpressionException;
021    
022    import org.apache.commons.lang.StringUtils;
023    import org.kuali.rice.edl.impl.EDLContext;
024    import org.kuali.rice.edl.impl.EDLModelComponent;
025    import org.kuali.rice.kew.rule.xmlrouting.XPathHelper;
026    import org.w3c.dom.Document;
027    import org.w3c.dom.Element;
028    import org.w3c.dom.Node;
029    import org.w3c.dom.NodeList;
030    
031    
032    
033    /**
034     * Looks at a field definition for a select field and attempts to analyze and resolve any valuesGroups based on document data.
035     * 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
036     * <valuesGroup> element with a series of <values> elements that include the values contained with the values group.
037     * 
038     * <p>This allows for <select> fields to be dependent upon one another. 
039     * 
040     * @author Kuali Rice Team (rice.collab@kuali.org)
041     */
042    public class SelectControlEDLComponent implements EDLModelComponent {
043    
044            public void updateDOM(Document dom, Element currentDefinitionElement, EDLContext edlContext) {
045                Element currentVersion = VersioningPreprocessor.findCurrentVersion(dom);
046                XPath xPath = XPathHelper.newXPath(dom);
047                try {
048                    NodeList selectFieldDefs = (NodeList)xPath.evaluate("//fieldDef[display/type = 'select' and display/valuesGroup] | //fieldDef[display/type = 'select_refresh' and display/valuesGroup]", dom, XPathConstants.NODESET);
049                    for (int fIndex = 0; fIndex < selectFieldDefs.getLength(); fIndex++) {
050                        Element fieldDef = (Element)selectFieldDefs.item(fIndex);
051                    NodeList valuesGroups = (NodeList)xPath.evaluate("./display/valuesGroup", fieldDef, XPathConstants.NODESET);
052                    for (int index = 0; index < valuesGroups.getLength(); index++) {
053                        Element valuesGroupElem = (Element)valuesGroups.item(index);
054                        NodeList dependsOnFields = (NodeList)xPath.evaluate("./dependsOn/field", valuesGroupElem, XPathConstants.NODESET);
055                        String fieldEvalExpression = "";
056                        for (int dIndex = 0; dIndex < dependsOnFields.getLength(); dIndex++) {
057                            if (!StringUtils.isBlank(fieldEvalExpression)) {
058                                fieldEvalExpression += " and ";
059                            }
060                            Element fieldElem = (Element)dependsOnFields.item(dIndex);
061                            String name = fieldElem.getAttribute("name");
062                            String value = fieldElem.getTextContent();
063                            fieldEvalExpression += "./field[@name='" + name + "']/value = '" + value + "'";
064                        }
065                        if ((Boolean)xPath.evaluate(fieldEvalExpression, currentVersion, XPathConstants.BOOLEAN)) {
066                            includeValuesGroup(valuesGroupElem);
067                        } else {
068                            // remove the valuesGroup as it did not match
069                            valuesGroupElem.getParentNode().removeChild(valuesGroupElem);
070                        }
071                    }
072                    }
073                } catch (XPathExpressionException e) {
074                    throw new RuntimeException("Failed to evaluate xpath expression.", e);
075                }
076            }
077            
078            protected void includeValuesGroup(Element valuesGroupElem) {
079                Element valuesGroupParent = (Element)valuesGroupElem.getParentNode();
080                NodeList valuesGroupChildren = valuesGroupElem.getChildNodes();
081                
082                for (int index = 0; index < valuesGroupChildren.getLength(); index++) {
083                    Node item = valuesGroupChildren.item(index);
084                    if (Node.ELEMENT_NODE == item.getNodeType() && item.getNodeName().equals("values")) {
085                        valuesGroupParent.insertBefore(item, valuesGroupElem);
086                    }
087                }
088                valuesGroupParent.removeChild(valuesGroupElem);
089            }       
090            
091    }