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 }