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