001/**
002 * Copyright 2005-2015 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 */
016package edu.sampleu.travel.workflow;
017
018import org.apache.commons.lang.StringUtils;
019import org.kuali.rice.core.api.util.ConcreteKeyValue;
020import org.kuali.rice.kew.api.WorkflowRuntimeException;
021import org.kuali.rice.kew.api.identity.Id;
022import org.kuali.rice.kew.api.identity.PrincipalId;
023import org.kuali.rice.kew.api.identity.PrincipalName;
024import org.kuali.rice.kew.api.rule.RoleName;
025import org.kuali.rice.kew.api.user.UserId;
026import org.kuali.rice.kew.engine.RouteContext;
027import org.kuali.rice.kew.exception.WorkflowServiceErrorImpl;
028import org.kuali.rice.kew.routeheader.DocumentContent;
029import org.kuali.rice.kew.rule.GenericRoleAttribute;
030import org.kuali.rice.kew.rule.QualifiedRoleName;
031import org.kuali.rice.kew.rule.ResolvedQualifiedRole;
032import org.kuali.rice.kim.api.identity.principal.Principal;
033import org.kuali.rice.kim.api.services.KimApiServiceLocator;
034import org.kuali.rice.kns.web.ui.Field;
035import org.kuali.rice.kns.web.ui.Row;
036
037import java.util.ArrayList;
038import java.util.Collections;
039import java.util.HashMap;
040import java.util.List;
041import java.util.Map;
042
043/**
044 * An attribute implementation that can resolve organizational roles
045 */
046public 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}