View Javadoc
1   /**
2    * Copyright 2005-2014 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kew.rule;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.kuali.rice.kew.api.KewApiConstants;
20  import org.kuali.rice.kew.api.WorkflowRuntimeException;
21  import org.kuali.rice.kew.api.extension.ExtensionDefinition;
22  import org.kuali.rice.kew.api.identity.Id;
23  import org.kuali.rice.kew.engine.RouteContext;
24  import org.kuali.rice.kew.routeheader.DocumentContent;
25  import org.kuali.rice.kew.rule.xmlrouting.GenericXMLRuleAttribute;
26  import org.kuali.rice.kew.rule.xmlrouting.XPathHelper;
27  import org.w3c.dom.Element;
28  import org.w3c.dom.NodeList;
29  import org.xml.sax.InputSource;
30  
31  import javax.xml.xpath.XPath;
32  import javax.xml.xpath.XPathConstants;
33  import javax.xml.xpath.XPathExpressionException;
34  import java.io.StringReader;
35  import java.util.ArrayList;
36  import java.util.HashMap;
37  import java.util.List;
38  import java.util.Map;
39  
40  /**
41   * A generic Role Attribute superclass that can be used to route to an ID. Can
42   * take as configuration the label to use for the element name in the XML. This
43   * allows for re-use of this component in different contexts.
44   * 
45   * @author Kuali Rice Team (rice.collab@kuali.org)
46   */
47  public abstract class AbstractIdRoleAttribute extends AbstractRoleAttribute
48  		implements GenericXMLRuleAttribute {
49  
50  	private static final String XML_ELEMENT_LABEL = "xmlElementLabel";
51  	private static final String ROLE_NAME_LABEL = "roleNameLabel";
52      private static final String GROUP_TOGETHER_LABEL = "groupTogether";
53      private static final String STRING_ID_SEPERATOR = ",";
54  
55  	private String idValue;
56  	private Map paramMap = new HashMap();
57  	private ExtensionDefinition extensionDefinition;
58  
59  	protected abstract String getAttributeElementName();
60  
61  	protected abstract Id resolveId(String id);
62  
63  	protected abstract String getIdName();
64  
65  	/**
66  	 * Returns qualified role names based on IDs in the XML. Each returned
67  	 * qualified Role contains a single ID.
68  	 * 
69  	 * @see org.kuali.rice.kew.rule.RoleAttribute#getQualifiedRoleNames(java.lang.String,
70  	 *      org.kuali.rice.kew.routeheader.DocumentContent)
71  	 */
72  	public List<String> getQualifiedRoleNames(String roleName,
73  			DocumentContent documentContent) {
74  		try {
75  			readConfiguration();
76  			String elementName = (String) getParamMap().get(XML_ELEMENT_LABEL);
77  			List<String> qualifiedRoleNames = new ArrayList<String>();
78  			XPath xPath = XPathHelper.newXPath();
79  			NodeList idNodes = (NodeList) xPath.evaluate("//"
80  					+ getAttributeElementName() + "/" + elementName,
81  					documentContent.getDocument(), XPathConstants.NODESET);
82              List<String> qualifiedRoleIds = new ArrayList<String>();  //used only for groupTogether parsing
83              for (int index = 0; index < idNodes.getLength(); index++) {
84  				Element idElement = (Element) idNodes.item(index);
85  				String id = idElement.getTextContent();
86                  if(isGroupTogetherRole()) {
87                      qualifiedRoleIds.add(id);
88                  } else {
89  			    	qualifiedRoleNames.add(id);
90  			    }
91              }
92              if(isGroupTogetherRole()){
93                  qualifiedRoleNames.add(StringUtils.join(qualifiedRoleIds, STRING_ID_SEPERATOR));
94              }
95  			return qualifiedRoleNames;
96  		} catch (XPathExpressionException e) {
97  			throw new WorkflowRuntimeException(
98  					"Failed to evaulate XPath expression to find ids.", e);
99  		}
100 	}
101 
102     private boolean isGroupTogetherRole(){
103         String value = (String) getParamMap().get(GROUP_TOGETHER_LABEL);
104         if(StringUtils.isNotBlank(value) && value.equalsIgnoreCase("true")){
105             return true;
106         }
107         return false;
108     }
109 
110 	/**
111 	 * Takes the given qualified role which contains an ID and returns a
112 	 * resolved role for the entity with that id.
113 	 * 
114 	 * @see org.kuali.rice.kew.rule.RoleAttribute#resolveQualifiedRole(org.kuali.rice.kew.engine.RouteContext,
115 	 *      java.lang.String, java.lang.String)
116 	 */
117 	public ResolvedQualifiedRole resolveQualifiedRole(
118 			RouteContext routeContext, String roleName, String qualifiedRole) {
119 		String roleNameLabel = (String) getParamMap().get(ROLE_NAME_LABEL);
120 		if (roleNameLabel == null) {
121 			readConfiguration();
122 			roleNameLabel = (String) getParamMap().get(ROLE_NAME_LABEL);
123 		}
124 
125         String groupTogetherLabel = (String) getParamMap().get(GROUP_TOGETHER_LABEL);
126         if (groupTogetherLabel == null) {
127             readConfiguration();
128             groupTogetherLabel = (String) getParamMap().get(GROUP_TOGETHER_LABEL);
129         }
130 
131         ResolvedQualifiedRole resolvedRole = new ResolvedQualifiedRole();
132 		resolvedRole.setQualifiedRoleLabel(roleNameLabel);
133 
134         if(isGroupTogetherRole()){
135             String[] qualifiedRoleIds = StringUtils.split(qualifiedRole, STRING_ID_SEPERATOR);
136             for (String qId : qualifiedRoleIds) {
137                 resolvedRole.getRecipients().add(resolveId(qId));
138             }
139         }else{
140     		resolvedRole.getRecipients().add(resolveId(qualifiedRole));
141         }
142         return resolvedRole;
143 	}
144 
145 	/**
146 	 * Generates XML containing the ID on this attribute.
147 	 * 
148 	 * @see org.kuali.rice.kew.rule.AbstractWorkflowAttribute#getDocContent()
149 	 */
150 	@Override
151 	public String getDocContent() {
152 		readConfiguration();
153 		if (!StringUtils.isBlank(getIdValue())) {
154 			String elementName = (String) getParamMap().get(XML_ELEMENT_LABEL);
155 			return "<" + getAttributeElementName() + "><" + elementName + ">"
156 					+ getIdValue() + "</" + elementName + "></"
157 					+ getAttributeElementName() + ">";
158 		}
159 		return "";
160 	}
161 
162 	/**
163 	 * Reads any configured values in the XML of the RuleAttribute and adds them
164 	 * to the paramMap.
165 	 * 
166 	 */
167 	protected void readConfiguration() {
168 		String idInMap = (String) getParamMap().get(getIdName());
169 		if (getIdValue() == null) {
170 			setIdValue(idInMap);
171 		}
172 		if (getIdValue() != null) {
173 			getParamMap().put(getIdName(), getIdValue());
174 		}
175 		if (extensionDefinition != null) {
176 			String xmlConfigData = extensionDefinition.getConfiguration().get(KewApiConstants.ATTRIBUTE_XML_CONFIG_DATA);
177 			if (!StringUtils.isBlank(xmlConfigData)) {
178 				XPath xPath = XPathHelper.newXPath();
179 				try {
180 					String xmlElementLabel = xPath.evaluate("/configuration/"
181 							+ XML_ELEMENT_LABEL, new InputSource(
182 							new StringReader(xmlConfigData)));
183 					String roleNameLabel = xPath.evaluate("/configuration/"
184 							+ ROLE_NAME_LABEL, new InputSource(
185 							new StringReader(xmlConfigData)));
186                     String groupTogetherLabel = xPath.evaluate("/configuration/"
187                             + GROUP_TOGETHER_LABEL, new InputSource(
188                             new StringReader(xmlConfigData)));
189 					if (!StringUtils.isBlank(xmlElementLabel)) {
190 						getParamMap().put(XML_ELEMENT_LABEL, xmlElementLabel);
191 					}
192 					if (!StringUtils.isBlank(roleNameLabel)) {
193 						getParamMap().put(ROLE_NAME_LABEL, roleNameLabel);
194 					}
195                     if (!StringUtils.isBlank(groupTogetherLabel)) {
196                         getParamMap().put(GROUP_TOGETHER_LABEL, groupTogetherLabel);
197                     }
198 
199 				} catch (XPathExpressionException e) {
200 					throw new WorkflowRuntimeException(
201 							"Failed to locate Rule Attribute configuration.");
202 				}
203 			}
204 		}
205 		// setup default values if none were defined in XML
206 		if (StringUtils.isBlank((String) getParamMap().get(XML_ELEMENT_LABEL))) {
207 			getParamMap().put(XML_ELEMENT_LABEL, getIdName());
208 		}
209 		if (getParamMap().get(ROLE_NAME_LABEL) == null) {
210 			getParamMap().put(ROLE_NAME_LABEL, "");
211 		}
212         if (StringUtils.isBlank((String) getParamMap().get(GROUP_TOGETHER_LABEL))) {
213             getParamMap().put(GROUP_TOGETHER_LABEL, "false");
214         }
215 	}
216 
217 	public String getIdValue() {
218 		return this.idValue;
219 	}
220 
221 	public void setIdValue(String idValue) {
222 		this.idValue = idValue;
223 	}
224 
225 	public Map getParamMap() {
226 		return paramMap;
227 	}
228 
229 	public void setParamMap(Map paramMap) {
230 		this.paramMap = paramMap;
231 	}
232 
233 	public void setExtensionDefinition(ExtensionDefinition extensionDefinition) {
234 		this.extensionDefinition = extensionDefinition;
235 	}
236 
237 }