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