001 /* 002 * Copyright 2007 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 edu.sampleu.travel.workflow; 017 018 import java.util.ArrayList; 019 import java.util.Collections; 020 import java.util.HashMap; 021 import java.util.List; 022 import java.util.Map; 023 024 import org.apache.commons.lang.StringUtils; 025 import org.kuali.rice.core.util.KeyLabelPair; 026 import org.kuali.rice.kew.engine.RouteContext; 027 import org.kuali.rice.kew.exception.WorkflowRuntimeException; 028 import org.kuali.rice.kew.exception.WorkflowServiceErrorImpl; 029 import org.kuali.rice.kew.identity.Id; 030 import org.kuali.rice.kew.routeheader.DocumentContent; 031 import org.kuali.rice.kew.rule.GenericRoleAttribute; 032 import org.kuali.rice.kew.rule.QualifiedRoleName; 033 import org.kuali.rice.kew.rule.ResolvedQualifiedRole; 034 import org.kuali.rice.kew.rule.Role; 035 import org.kuali.rice.kew.user.AuthenticationUserId; 036 import org.kuali.rice.kew.user.UserId; 037 import org.kuali.rice.kew.user.WorkflowUserId; 038 import org.kuali.rice.kim.bo.entity.KimPrincipal; 039 import org.kuali.rice.kim.service.KIMServiceLocator; 040 import org.kuali.rice.kns.web.ui.Field; 041 import org.kuali.rice.kns.web.ui.Row; 042 043 044 /** 045 * An attribute implementation that can resolve organizational roles 046 */ 047 public class EmployeeAttribute extends GenericRoleAttribute { 048 private static final Role EMPLOYEE_ROLE = new Role(EmployeeAttribute.class, "employee", "Employee"); 049 private static final Role SUPERVISOR_ROLE = new Role(EmployeeAttribute.class, "supervisr", "Supervisor"); 050 private static final Role DIRECTOR_ROLE = new Role(EmployeeAttribute.class, "director", "Dean/Director"); 051 private static final List<Role> ROLES; 052 static { 053 List<Role> tmp = new ArrayList<Role>(1); 054 tmp.add(EMPLOYEE_ROLE); 055 tmp.add(SUPERVISOR_ROLE); 056 tmp.add(DIRECTOR_ROLE); 057 ROLES = Collections.unmodifiableList(tmp); 058 } 059 060 private static String USERID_FORM_FIELDNAME = "userid"; 061 062 /** 063 * Traveler to be set by client application so that doc content can be generated appropriately 064 */ 065 private String traveler; 066 067 //private AttributeParser _attributeParser = new AttributeParser(ATTRIBUTE_TAGNAME); 068 069 public EmployeeAttribute() { 070 super("employee"); 071 } 072 073 public EmployeeAttribute(String traveler) { 074 super("employee"); 075 this.traveler = traveler; 076 } 077 078 /** for edoclite?? */ 079 public void setTraveler(String traveler) { 080 this.traveler = traveler; 081 } 082 083 /* RoleAttribute methods */ 084 public List<Role> getRoleNames() { 085 return ROLES; 086 } 087 088 protected boolean isValidRole(String roleName) { 089 for (Role role: ROLES) { 090 if (role.getBaseName().equals(roleName)) { 091 return true; 092 } 093 } 094 return false; 095 } 096 097 098 @Override 099 protected List<String> getRoleNameQualifiers(String roleName, DocumentContent documentContent) { 100 if (!isValidRole(roleName)) { 101 throw new WorkflowRuntimeException("Invalid role: " + roleName); 102 } 103 104 List<String> qualifiers = new ArrayList<String>(); 105 qualifiers.add(roleName); 106 // find all traveller inputs in incoming doc 107 // List<Map<String, String>> attrs; 108 // try { 109 // attrs = content.parseContent(documentContent.getAttributeContent()); 110 // } catch (XPathExpressionException xpee) { 111 // throw new WorkflowRuntimeException("Error parsing attribute content: " + XmlHelper.jotNode(documentContent.getAttributeContent())); 112 // } 113 // for (Map<String, String> props: attrs) { 114 // String attrTraveler = props.get("traveler"); 115 // if (attrTraveler != null) { 116 // qualifiers.add(attrTraveler); 117 // } 118 // } 119 return qualifiers; 120 } 121 122 @Override 123 protected ResolvedQualifiedRole resolveQualifiedRole(RouteContext routeContext, QualifiedRoleName qualifiedRoleName) { 124 List<Id> recipients = resolveRecipients(routeContext, qualifiedRoleName); 125 ResolvedQualifiedRole rqr = new ResolvedQualifiedRole(getLabelForQualifiedRoleName(qualifiedRoleName), 126 recipients, 127 qualifiedRoleName.getBaseRoleName()); // default to no annotation... 128 return rqr; 129 } 130 131 @Override 132 protected List<Id> resolveRecipients(RouteContext routeContext, QualifiedRoleName qualifiedRoleName) { 133 List<Id> members = new ArrayList<Id>(); 134 UserId roleUserId = null; 135 String roleName = qualifiedRoleName.getBaseRoleName(); 136 String roleTraveler = qualifiedRoleName.getQualifier(); 137 138 /* EMPLOYEE role routes to traveler */ 139 if (StringUtils.equals(EMPLOYEE_ROLE.getBaseName(), roleName)) { 140 roleUserId = new WorkflowUserId(roleTraveler); 141 142 /* SUPERVISOR role routes to... supervisor */ 143 } else if (StringUtils.equals(SUPERVISOR_ROLE.getBaseName(), roleName)) { 144 // HACK: need to create an organizational-hierarchy service which 145 // has methods like 146 // getSupervisor( user ), getDirector( user ), getSupervised( user 147 // ), etc. 148 // using q.uhuuid() as input 149 roleUserId = new AuthenticationUserId("supervisr"); 150 151 /* SUPERVISOR role routes to... director */ 152 } else if (StringUtils.equals(DIRECTOR_ROLE.getBaseName(), roleName)) { 153 // HACK: need to create an organizational-hierarchy service which 154 // has methods like 155 // getSupervisor( user ), getDirector( user ), getSupervised( user 156 // ), etc. 157 // using q.uhuuid() as input 158 roleUserId = new AuthenticationUserId("director"); 159 } else { 160 // throw an exception if you get an unrecognized roleName 161 throw new WorkflowRuntimeException("unable to process unknown role '" + roleName + "'"); 162 } 163 members.add(roleUserId); 164 165 return members; 166 } 167 168 public Map<String, String> getProperties() { 169 Map<String, String> properties = new HashMap<String, String>(); 170 properties.put("traveler", traveler); 171 return properties; 172 } 173 174 /** 175 * Required to support flex routing report 176 * 177 * @see org.kuali.rice.kew.rule.WorkflowAttribute#getFieldConversions() 178 */ 179 public List getFieldConversions() { 180 List conversionFields = new ArrayList(); 181 conversionFields.add(new KeyLabelPair("userid", USERID_FORM_FIELDNAME)); 182 return conversionFields; 183 } 184 185 public List<Row> getRoutingDataRows() { 186 List<Row> rows = new ArrayList<Row>(); 187 188 List<Field> fields = new ArrayList<Field>(); 189 fields.add(new Field("Traveler username", "", Field.TEXT, false, USERID_FORM_FIELDNAME, "", false, false, null, null)); 190 rows.add(new Row(fields)); 191 192 return rows; 193 } 194 195 public List validateRoutingData(Map paramMap) { 196 List errors = new ArrayList(); 197 198 String userid = StringUtils.trim((String) paramMap.get(USERID_FORM_FIELDNAME)); 199 if (isRequired() && StringUtils.isBlank(userid)) { 200 errors.add(new WorkflowServiceErrorImpl("userid is required", "uh.accountattribute.userid.required")); 201 } 202 203 KimPrincipal principal = null; 204 if (!StringUtils.isBlank(userid)) { 205 principal = KIMServiceLocator.getIdentityManagementService().getPrincipalByPrincipalName(userid); 206 } 207 if (principal == null) { 208 errors.add(new WorkflowServiceErrorImpl("unable to retrieve user for userid '" + userid + "'", "uh.accountattribute.userid.invalid")); 209 } 210 211 if (errors.size() == 0) { 212 traveler = principal.getPrincipalId(); 213 } 214 215 return errors; 216 } 217 }