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 }