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 }