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    }