001/**
002 * Copyright 2005-2016 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 */
016package org.kuali.rice.edl.impl.components;
017
018import javax.xml.xpath.XPath;
019import javax.xml.xpath.XPathConstants;
020import javax.xml.xpath.XPathExpressionException;
021
022import org.apache.commons.lang.StringUtils;
023import org.kuali.rice.edl.impl.EDLContext;
024import org.kuali.rice.edl.impl.EDLModelComponent;
025import org.kuali.rice.kew.rule.xmlrouting.XPathHelper;
026import org.w3c.dom.Document;
027import org.w3c.dom.Element;
028import org.w3c.dom.Node;
029import 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 */
042public 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}