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 }