001 /** 002 * Copyright 2005-2012 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.kew.xml; 017 018 import org.apache.commons.lang.StringUtils; 019 import org.kuali.rice.core.api.impex.xml.XmlConstants; 020 import org.kuali.rice.core.api.util.xml.XmlException; 021 import org.kuali.rice.core.api.util.xml.XmlJotter; 022 import org.kuali.rice.kew.rule.bo.RuleAttribute; 023 import org.kuali.rice.kew.rule.xmlrouting.XPathHelper; 024 import org.kuali.rice.kew.service.KEWServiceLocator; 025 import org.kuali.rice.kew.api.KewApiConstants; 026 import org.w3c.dom.Element; 027 import org.w3c.dom.Node; 028 import org.w3c.dom.NodeList; 029 import org.xml.sax.InputSource; 030 031 import javax.xml.parsers.DocumentBuilderFactory; 032 import javax.xml.xpath.XPath; 033 import javax.xml.xpath.XPathConstants; 034 import javax.xml.xpath.XPathExpressionException; 035 import java.io.IOException; 036 import java.io.InputStream; 037 import java.util.ArrayList; 038 import java.util.Iterator; 039 import java.util.List; 040 041 import static org.kuali.rice.core.api.impex.xml.XmlConstants.APPLICATION_ID; 042 043 044 /** 045 * Parses {@link org.kuali.rice.kew.rule.bo.RuleAttribute}s from XML. 046 * 047 * @see org.kuali.rice.kew.rule.bo.RuleAttribute 048 * 049 * @author Kuali Rice Team (rice.collab@kuali.org) 050 */ 051 public class RuleAttributeXmlParser { 052 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(RuleAttributeXmlParser.class); 053 054 055 private static final String XPATH_RULE_ATTRIBUTES = "//" + XmlConstants.RULE_ATTRIBUTES + "/" + XmlConstants.RULE_ATTRIBUTE; 056 private static final String NAME = "name"; 057 private static final String CLASS_NAME = "className"; 058 private static final String LABEL = "label"; 059 private static final String DESCRIPTION = "description"; 060 private static final String TYPE = "type"; 061 private static final String CONFIG = "configuration"; 062 063 public List parseRuleAttributes(InputStream input) throws IOException, XmlException { 064 try { 065 Element root = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(input)).getDocumentElement(); 066 return parseRuleAttributes(root); 067 } catch (Exception e) { 068 throw new XmlException("error parsing xml data", e); 069 } 070 } 071 072 public List parseRuleAttributes(Element element) throws XmlException { 073 List ruleAttributes = new ArrayList(); 074 try { 075 XPath xpath = XPathHelper.newXPath(); 076 NodeList nodeList = (NodeList)xpath.evaluate(XPATH_RULE_ATTRIBUTES, element, XPathConstants.NODESET); 077 for (int i = 0; i < nodeList.getLength(); i++) { 078 Node ruleAttributeNode = nodeList.item(i); 079 ruleAttributes.add(parseRuleAttribute(ruleAttributeNode)); 080 } 081 082 for (Iterator iterator = ruleAttributes.iterator(); iterator.hasNext();) { 083 RuleAttribute ruleAttribute = (RuleAttribute) iterator.next(); 084 try { 085 RuleAttribute existingAttribute = KEWServiceLocator.getRuleAttributeService().findByName(ruleAttribute.getName()); 086 if (existingAttribute != null) { 087 ruleAttribute.setId(existingAttribute.getId()); 088 ruleAttribute.setVersionNumber(existingAttribute.getVersionNumber()); 089 } 090 KEWServiceLocator.getRuleAttributeService().save(ruleAttribute); 091 } catch (Exception e) { 092 LOG.error("Error saving rule attribute entered by XML", e); 093 } 094 } 095 } catch (XPathExpressionException e1) { 096 throw new XmlException("Could not find a rule attribute.", e1); 097 } 098 return ruleAttributes; 099 } 100 101 private RuleAttribute parseRuleAttribute(Node ruleAttributeNode) throws XmlException { 102 String name = ""; 103 String className = ""; 104 String label = ""; 105 String description = ""; 106 String type = ""; 107 String applicationId = null; 108 Node xmlConfig = null; 109 for (int i = 0; i < ruleAttributeNode.getChildNodes().getLength(); i++) { 110 Node childNode = ruleAttributeNode.getChildNodes().item(i); 111 if(NAME.equals(childNode.getNodeName())){ 112 name = childNode.getFirstChild().getNodeValue(); 113 } else if(CLASS_NAME.equals(childNode.getNodeName())){ 114 className = childNode.getFirstChild().getNodeValue(); 115 } else if(LABEL.equals(childNode.getNodeName())){ 116 label = childNode.getFirstChild().getNodeValue(); 117 } else if(DESCRIPTION.equals(childNode.getNodeName())){ 118 description = childNode.getFirstChild().getNodeValue(); 119 } else if(TYPE.equals(childNode.getNodeName())){ 120 type = childNode.getFirstChild().getNodeValue(); 121 } else if(XmlConstants.ROUTING_CONFIG.equals(childNode.getNodeName()) || XmlConstants.SEARCHING_CONFIG.equals(childNode.getNodeName()) || 122 XmlConstants.SEARCH_RESULT_CONFIG.equals(childNode.getNodeName()) || XmlConstants.RESOLVER_CONFIG.equals(childNode.getNodeName()) || 123 CONFIG.equals(childNode.getNodeName())){ 124 xmlConfig = childNode; 125 } else if (XmlConstants.SERVICE_NAMESPACE.equals(childNode.getNodeName())) { 126 applicationId = childNode.getFirstChild().getNodeValue(); 127 LOG.warn(XmlConstants.SERVICE_NAMESPACE + " element was set on rule attribute type XML but is deprecated and will be removed in a future version, please use " + APPLICATION_ID + " instead."); 128 } else if (XmlConstants.APPLICATION_ID.equals(childNode.getNodeName())) { 129 applicationId = childNode.getFirstChild().getNodeValue(); 130 } 131 } 132 if (org.apache.commons.lang.StringUtils.isEmpty(name)) { 133 throw new XmlException("RuleAttribute must have a name"); 134 } 135 if (org.apache.commons.lang.StringUtils.isEmpty(className)) { 136 throw new XmlException("RuleAttribute must have a className"); 137 } 138 if (org.apache.commons.lang.StringUtils.isEmpty(label)) { 139 LOG.warn("Label empty defaulting to name"); 140 label = name; 141 } 142 if (org.apache.commons.lang.StringUtils.isEmpty(type)) { 143 LOG.debug("No type specified, default to " + KewApiConstants.RULE_ATTRIBUTE_TYPE); 144 type = KewApiConstants.RULE_ATTRIBUTE_TYPE; 145 //throw new XmlException("RuleAttribute must have an attribute type"); 146 } 147 type = type.trim(); 148 validateRuleAttributeType(type); 149 150 RuleAttribute ruleAttribute = new RuleAttribute(); 151 ruleAttribute.setName(name.trim()); 152 ruleAttribute.setResourceDescriptor(className.trim()); 153 ruleAttribute.setType(type.trim()); 154 ruleAttribute.setLabel(label.trim()); 155 // default description to label 156 if (StringUtils.isEmpty(description)) { 157 description = label; 158 } 159 ruleAttribute.setDescription(description.trim()); 160 if (applicationId != null) 161 { 162 applicationId = applicationId.trim(); 163 } 164 ruleAttribute.setApplicationId(applicationId); 165 166 if(xmlConfig != null){ 167 ruleAttribute.setXmlConfigData(XmlJotter.jotNode(xmlConfig)); 168 } else { 169 if(KewApiConstants.RULE_XML_ATTRIBUTE_TYPE.equals(type)){ 170 throw new XmlException("A routing config must be present to be of type: "+type); 171 } else if(KewApiConstants.SEARCHABLE_XML_ATTRIBUTE_TYPE.equals(type)){ 172 throw new XmlException("A searching config must be present to be of type: "+type); 173 } 174 } 175 return ruleAttribute; 176 } 177 178 protected void validateRuleAttributeType(String type) { 179 180 } 181 }