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.rule; 017 018 import org.apache.commons.lang.StringUtils; 019 import org.kuali.rice.kew.api.KewApiConstants; 020 import org.kuali.rice.kew.api.WorkflowRuntimeException; 021 import org.kuali.rice.kew.api.extension.ExtensionDefinition; 022 import org.kuali.rice.kew.api.identity.Id; 023 import org.kuali.rice.kew.engine.RouteContext; 024 import org.kuali.rice.kew.routeheader.DocumentContent; 025 import org.kuali.rice.kew.rule.xmlrouting.GenericXMLRuleAttribute; 026 import org.kuali.rice.kew.rule.xmlrouting.XPathHelper; 027 import org.w3c.dom.Element; 028 import org.w3c.dom.NodeList; 029 import org.xml.sax.InputSource; 030 031 import javax.xml.xpath.XPath; 032 import javax.xml.xpath.XPathConstants; 033 import javax.xml.xpath.XPathExpressionException; 034 import java.io.StringReader; 035 import java.util.ArrayList; 036 import java.util.HashMap; 037 import java.util.List; 038 import java.util.Map; 039 040 /** 041 * A generic Role Attribute superclass that can be used to route to an ID. Can 042 * take as configuration the label to use for the element name in the XML. This 043 * allows for re-use of this component in different contexts. 044 * 045 * @author Kuali Rice Team (rice.collab@kuali.org) 046 */ 047 public abstract class AbstractIdRoleAttribute extends AbstractRoleAttribute 048 implements GenericXMLRuleAttribute { 049 050 private static final String XML_ELEMENT_LABEL = "xmlElementLabel"; 051 private static final String ROLE_NAME_LABEL = "roleNameLabel"; 052 053 private String idValue; 054 private Map paramMap = new HashMap(); 055 private ExtensionDefinition extensionDefinition; 056 057 protected abstract String getAttributeElementName(); 058 059 protected abstract Id resolveId(String id); 060 061 protected abstract String getIdName(); 062 063 /** 064 * Returns qualified role names based on IDs in the XML. Each returned 065 * qualified Role contains a single ID. 066 * 067 * @see org.kuali.rice.kew.rule.RoleAttribute#getQualifiedRoleNames(java.lang.String, 068 * org.kuali.rice.kew.routeheader.DocumentContent) 069 */ 070 public List<String> getQualifiedRoleNames(String roleName, 071 DocumentContent documentContent) { 072 try { 073 readConfiguration(); 074 String elementName = (String) getParamMap().get(XML_ELEMENT_LABEL); 075 List<String> qualifiedRoleNames = new ArrayList<String>(); 076 XPath xPath = XPathHelper.newXPath(); 077 NodeList idNodes = (NodeList) xPath.evaluate("//" 078 + getAttributeElementName() + "/" + elementName, 079 documentContent.getDocument(), XPathConstants.NODESET); 080 for (int index = 0; index < idNodes.getLength(); index++) { 081 Element idElement = (Element) idNodes.item(index); 082 String id = idElement.getTextContent(); 083 qualifiedRoleNames.add(id); 084 } 085 return qualifiedRoleNames; 086 } catch (XPathExpressionException e) { 087 throw new WorkflowRuntimeException( 088 "Failed to evaulate XPath expression to find ids.", e); 089 } 090 } 091 092 /** 093 * Takes the given qualified role which contains an ID and returns a 094 * resolved role for the entity with that id. 095 * 096 * @see org.kuali.rice.kew.rule.RoleAttribute#resolveQualifiedRole(org.kuali.rice.kew.engine.RouteContext, 097 * java.lang.String, java.lang.String) 098 */ 099 public ResolvedQualifiedRole resolveQualifiedRole( 100 RouteContext routeContext, String roleName, String qualifiedRole) { 101 String roleNameLabel = (String) getParamMap().get(ROLE_NAME_LABEL); 102 if (roleNameLabel == null) { 103 readConfiguration(); 104 roleNameLabel = (String) getParamMap().get(ROLE_NAME_LABEL); 105 } 106 ResolvedQualifiedRole resolvedRole = new ResolvedQualifiedRole(); 107 resolvedRole.setQualifiedRoleLabel(roleNameLabel); 108 resolvedRole.getRecipients().add(resolveId(qualifiedRole)); 109 return resolvedRole; 110 } 111 112 /** 113 * Generates XML containing the ID on this attribute. 114 * 115 * @see org.kuali.rice.kew.rule.AbstractWorkflowAttribute#getDocContent() 116 */ 117 @Override 118 public String getDocContent() { 119 readConfiguration(); 120 if (!StringUtils.isBlank(getIdValue())) { 121 String elementName = (String) getParamMap().get(XML_ELEMENT_LABEL); 122 return "<" + getAttributeElementName() + "><" + elementName + ">" 123 + getIdValue() + "</" + elementName + "></" 124 + getAttributeElementName() + ">"; 125 } 126 return ""; 127 } 128 129 /** 130 * Reads any configured values in the XML of the RuleAttribute and adds them 131 * to the paramMap. 132 * 133 */ 134 protected void readConfiguration() { 135 String idInMap = (String) getParamMap().get(getIdName()); 136 if (getIdValue() == null) { 137 setIdValue(idInMap); 138 } 139 if (getIdValue() != null) { 140 getParamMap().put(getIdName(), getIdValue()); 141 } 142 if (extensionDefinition != null) { 143 String xmlConfigData = extensionDefinition.getConfiguration().get(KewApiConstants.ATTRIBUTE_XML_CONFIG_DATA); 144 if (!StringUtils.isBlank(xmlConfigData)) { 145 XPath xPath = XPathHelper.newXPath(); 146 try { 147 String xmlElementLabel = xPath.evaluate("/configuration/" 148 + XML_ELEMENT_LABEL, new InputSource( 149 new StringReader(xmlConfigData))); 150 String roleNameLabel = xPath.evaluate("/configuration/" 151 + ROLE_NAME_LABEL, new InputSource( 152 new StringReader(xmlConfigData))); 153 if (!StringUtils.isBlank(xmlElementLabel)) { 154 getParamMap().put(XML_ELEMENT_LABEL, xmlElementLabel); 155 } 156 if (!StringUtils.isBlank(roleNameLabel)) { 157 getParamMap().put(ROLE_NAME_LABEL, roleNameLabel); 158 } 159 160 } catch (XPathExpressionException e) { 161 throw new WorkflowRuntimeException( 162 "Failed to locate Rule Attribute configuration."); 163 } 164 } 165 } 166 // setup default values if none were defined in XML 167 if (StringUtils.isBlank((String) getParamMap().get(XML_ELEMENT_LABEL))) { 168 getParamMap().put(XML_ELEMENT_LABEL, getIdName()); 169 } 170 if (getParamMap().get(ROLE_NAME_LABEL) == null) { 171 getParamMap().put(ROLE_NAME_LABEL, ""); 172 } 173 } 174 175 public String getIdValue() { 176 return this.idValue; 177 } 178 179 public void setIdValue(String idValue) { 180 this.idValue = idValue; 181 } 182 183 public Map getParamMap() { 184 return paramMap; 185 } 186 187 public void setParamMap(Map paramMap) { 188 this.paramMap = paramMap; 189 } 190 191 public void setExtensionDefinition(ExtensionDefinition extensionDefinition) { 192 this.extensionDefinition = extensionDefinition; 193 } 194 195 }