001: /*
002: * Copyright 2005-2007 The Kuali Foundation.
003: *
004: *
005: * Licensed under the Educational Community License, Version 1.0 (the "License");
006: * you may not use this file except in compliance with the License.
007: * You may obtain a copy of the License at
008: *
009: * http://www.opensource.org/licenses/ecl1.php
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.kuali.workflow.role;
018:
019: import java.sql.Timestamp;
020: import java.util.ArrayList;
021: import java.util.HashSet;
022: import java.util.List;
023: import java.util.Set;
024:
025: import org.kuali.workflow.routemodule.BaseRouteModule;
026: import org.kuali.workflow.routemodule.RouteModuleException;
027:
028: import edu.iu.uis.eden.KEWServiceLocator;
029: import edu.iu.uis.eden.actionrequests.ActionRequestFactory;
030: import edu.iu.uis.eden.actionrequests.ActionRequestService;
031: import edu.iu.uis.eden.actionrequests.ActionRequestValue;
032: import edu.iu.uis.eden.engine.RouteContext;
033: import edu.iu.uis.eden.engine.node.RouteNode;
034: import edu.iu.uis.eden.routeheader.DocumentRouteHeaderValue;
035: import edu.iu.uis.eden.routetemplate.FlexRM;
036: import edu.iu.uis.eden.util.PerformanceLogger;
037:
038: /**
039: * The RouteModule which is responsible for generating Action Requests from Roles configured in the system.
040: *
041: * @author ewestfal
042: */
043: public class RoleRouteModule extends BaseRouteModule {
044:
045: private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger
046: .getLogger(FlexRM.class);
047:
048: public static String EFFECTIVE_DATE_PARAM = "RoleRouteModule.EffectiveDate";
049:
050: public List findActionRequests(RouteContext context)
051: throws Exception {
052: DocumentRouteHeaderValue document = context.getDocument();
053: Role role = getRole(context);
054: LOG.debug("Generating Action Requests for role '"
055: + role.getName() + "' on document "
056: + document.getRouteHeaderId());
057: List<QualifiedRole> roleEvaluationSet = loadRoleEvaluationSet(
058: context, role);
059: List<RoleResolver> roleResolvers = findRoleResolvers(role,
060: context);
061: if (roleResolvers == null || roleResolvers.isEmpty()) {
062: throw new RouteModuleException(
063: "Could not find a RoleResolver for this role '"
064: + role.getName() + "'");
065: }
066: List<QualifiedRole> matchingQualifiedRoles = applyRoleResolvers(
067: context, role, roleEvaluationSet, roleResolvers);
068: return generateActionRequests(context, matchingQualifiedRoles,
069: role);
070: }
071:
072: protected Role getRole(RouteContext context) {
073: String roleName = getRoleName(context);
074: Role role = KEWServiceLocator.getRoleService().findRoleByName(
075: roleName);
076: if (role == null) {
077: throw new RouteModuleException(
078: "Could not locate the role with the given name '"
079: + roleName + "'");
080: }
081: return role;
082: }
083:
084: protected List<QualifiedRole> loadRoleEvaluationSet(
085: RouteContext context, Role role) {
086: return getRoleService().findQualifiedRolesForRole(
087: role.getName(), getEffectiveDate(context));
088: }
089:
090: protected Timestamp getEffectiveDate(RouteContext context) {
091: return (Timestamp) context.getParameters().get(
092: EFFECTIVE_DATE_PARAM);
093: }
094:
095: protected List<QualifiedRole> applyRoleResolvers(
096: RouteContext context, Role role,
097: List<QualifiedRole> roleEvaluationSet,
098: List<RoleResolver> resolvers) {
099: List<List<QualifiedRole>> resolvedQualifiedRoles = new ArrayList<List<QualifiedRole>>();
100: for (RoleResolver resolver : resolvers) {
101: List<QualifiedRole> resolved = resolver.resolve(context,
102: role, roleEvaluationSet);
103: if (resolved != null && !resolved.isEmpty()) {
104: resolvedQualifiedRoles.add(resolved);
105: }
106: }
107: return mergeResolvedQualifiedRoles(context, role,
108: resolvedQualifiedRoles);
109: }
110:
111: protected List<QualifiedRole> mergeResolvedQualifiedRoles(
112: RouteContext context, Role role,
113: List<List<QualifiedRole>> resolvedQualifiedRoles) {
114: Set<Long> mergedIds = new HashSet<Long>();
115: List<QualifiedRole> qualifiedRoles = new ArrayList<QualifiedRole>();
116: for (List<QualifiedRole> qualifiedRoleSet : resolvedQualifiedRoles) {
117: for (QualifiedRole qualifiedRole : qualifiedRoleSet) {
118: Long qRoleId = qualifiedRole.getQualifiedRoleId();
119: if (!mergedIds.contains(qRoleId)) {
120: qualifiedRoles.add(qualifiedRole);
121: if (qRoleId != null) {
122: mergedIds.add(qRoleId);
123: }
124: }
125: }
126: }
127: return qualifiedRoles;
128: }
129:
130: protected String getRoleName(RouteContext context) {
131: RouteNode node = context.getNodeInstance().getRouteNode();
132: return node.getRouteMethodName();
133: }
134:
135: protected List<RoleResolver> findRoleResolvers(Role role,
136: RouteContext context) {
137: // TODO
138: return null;
139: }
140:
141: protected List<ActionRequestValue> generateActionRequests(
142: RouteContext context, List<QualifiedRole> qualifiedRoles,
143: Role role) {
144: PerformanceLogger performanceLogger = new PerformanceLogger();
145: ActionRequestFactory factory = new ActionRequestFactory(context
146: .getDocument(), context.getNodeInstance());
147: for (QualifiedRole qualifiedRole : qualifiedRoles) {
148: generateActionRequests(context, qualifiedRole, factory);
149: }
150: List<ActionRequestValue> actionRequests = factory
151: .getRequestGraphs();
152: performanceLogger.log("Time to make action requests for role '"
153: + role.getName() + "'");
154: return actionRequests;
155: }
156:
157: protected void generateActionRequests(RouteContext context,
158: QualifiedRole qualifiedRole, ActionRequestFactory factory) {
159: // TODO
160: }
161:
162: // public List getActionRequests(DocumentRouteHeaderValue routeHeader, RouteNodeInstance nodeInstance, String ruleTemplateName) throws EdenUserNotFoundException, WorkflowException {
163: // LOG.debug("Generating Action Requests for document " + routeHeader.getRouteHeaderId());
164: // RuleTemplate template = getRuleTemplateService().findByRuleTemplateName(ruleTemplateName);
165: // if (template == null) {
166: // throw new WorkflowRuntimeException("Could not locate the rule template with name " + ruleTemplateName + " on document " + routeHeader.getRouteHeaderId());
167: // }
168: // for (Iterator iter = template.getRuleTemplateAttributes().iterator(); iter.hasNext();) {
169: //
170: // RuleTemplateAttribute templateAttribute = (RuleTemplateAttribute) iter.next();
171: // if (!templateAttribute.isWorkflowAttribute()) {
172: // continue;
173: // }
174: // WorkflowAttribute attribute = templateAttribute.getWorkflowAttribute();
175: // if (attribute instanceof MassRuleAttribute) {
176: // massRules.add(attribute);
177: // }
178: //
179: // }
180: //
181: // List rules = null;
182: // if (getEffectiveDate() != null) {
183: // rules = getRuleService().fetchAllCurrentRulesForTemplateDocCombination(ruleTemplateName, routeHeader.getDocumentType().getName(), effectiveDate);
184: // } else {
185: // rules = getRuleService().fetchAllCurrentRulesForTemplateDocCombination(ruleTemplateName, routeHeader.getDocumentType().getName());
186: // }
187: // numberOfMatchingRules = rules.size();
188: //
189: // RouteContext context = RouteContext.getCurrentRouteContext();
190: // // TODO really the route context just needs to be able to support nested create and clears
191: // // (i.e. a Stack model similar to transaction intercepting in Spring) and we wouldn't have to do this
192: // if (context.getDocument() == null) {
193: // context.setDocument(routeHeader);
194: // }
195: // if (context.getNodeInstance() == null) {
196: // context.setNodeInstance(nodeInstance);
197: // }
198: // DocumentContent documentContent = context.getDocumentContent();
199: // PerformanceLogger performanceLogger = new PerformanceLogger();
200: // // have all mass rule attributes filter the list of non applicable rules
201: // for (Iterator iter = massRules.iterator(); iter.hasNext();) {
202: // MassRuleAttribute massRuleAttribute = (MassRuleAttribute) iter.next();
203: // rules = massRuleAttribute.filterNonMatchingRules(context, rules);
204: // }
205: // performanceLogger.log("Time to filter massRules for template " + template.getName());
206: //
207: // arFactory = new ActionRequestFactory(routeHeader, context.getNodeInstance());
208: // performanceLogger = new PerformanceLogger();
209: // List actionRequests = new ArrayList();
210: // for (Iterator iter = rules.iterator(); iter.hasNext();) {
211: // RuleBaseValues rule = (RuleBaseValues) iter.next();
212: // if (rule.isMatch(documentContent)) {
213: //// actionRequests.addAll(makeActionRequests(context, rule, routeHeader, null, null));
214: // makeActionRequests(context, rule, routeHeader, null, null);
215: // }
216: // }
217: // actionRequests = new ArrayList(arFactory.getRequestGraphs());
218: // performanceLogger.log("Time to make action request for template " + template.getName());
219: //
220: // return actionRequests;
221: // }
222:
223: // public ResponsibleParty resolveResponsibilityId(Long responsibilityId) {
224: // RuleResponsibility resp = getRuleService().findRuleResponsibility(responsibilityId);
225: // if (resp.isUsingRole()) {
226: // return new ResponsibleParty(resp.getResolvedRoleName());
227: // } else if (resp.isUsingWorkflowUser()) {
228: // return new ResponsibleParty(new WorkflowUserId(resp.getRuleResponsibilityName()));
229: // } else {
230: // return new ResponsibleParty(new WorkflowGroupId(new Long(resp.getRuleResponsibilityName())));
231: // }
232: // }
233:
234: // private void makeActionRequests(RouteContext context, RuleBaseValues rule, DocumentRouteHeaderValue routeHeader, ActionRequestValue parentRequest, RuleDelegation ruleDelegation)
235: // throws EdenUserNotFoundException, WorkflowException {
236: // List responsibilities = rule.getResponsibilities();
237: // for (Iterator iter = responsibilities.iterator(); iter.hasNext();) {
238: // RuleResponsibility resp = (RuleResponsibility) iter.next();
239: // if (resp.isUsingRole()) {
240: // makeRoleActionRequests(context, rule, resp, routeHeader, parentRequest, ruleDelegation);
241: // } else {
242: // makeActionRequest(context, rule, routeHeader, resp, parentRequest, ruleDelegation);
243: // }
244: // }
245: // }
246: //
247: // private void buildDelegationGraph(RouteContext context, RuleBaseValues delegationRule, DocumentRouteHeaderValue routeHeaderValue, ActionRequestValue parentRequest, RuleDelegation ruleDelegation)
248: // throws EdenUserNotFoundException, WorkflowException {
249: // context.setActionRequest(parentRequest);
250: // if (delegationRule.getActiveInd().booleanValue() && delegationRule.getToDate().after(new Date()) && delegationRule.getFromDate().before(new Date())) {
251: // for (Iterator iter = delegationRule.getResponsibilities().iterator(); iter.hasNext();) {
252: // RuleResponsibility delegationResp = (RuleResponsibility) iter.next();
253: // if (delegationResp.isUsingRole()) {
254: // makeRoleActionRequests(context, delegationRule, delegationResp, routeHeaderValue, parentRequest, ruleDelegation);
255: // } else if (delegationRule.isMatch(context.getDocumentContent())) {
256: // makeActionRequest(context, delegationRule, routeHeaderValue, delegationResp, parentRequest, ruleDelegation);
257: // }
258: // }
259: // }
260: // }
261: //
262: // private void makeRoleActionRequests(RouteContext context, RuleBaseValues rule, RuleResponsibility resp, DocumentRouteHeaderValue routeHeader, ActionRequestValue parentRequest,
263: // RuleDelegation ruleDelegation) throws EdenUserNotFoundException, WorkflowException {
264: //
265: // String roleName = resp.getResolvedRoleName();
266: // RoleAttribute roleAttribute = resp.resolveRoleAttribute();
267: // List<String> qualifiedRoleNames = new ArrayList<String>();
268: // if (parentRequest != null && parentRequest.getQualifiedRoleName() != null) {
269: // qualifiedRoleNames.add(parentRequest.getQualifiedRoleName());
270: // } else {
271: // qualifiedRoleNames.addAll(roleAttribute.getQualifiedRoleNames(roleName, context.getDocumentContent()));
272: // }
273: // for (Iterator iter = qualifiedRoleNames.iterator(); iter.hasNext();) {
274: // String qualifiedRoleName = (String) iter.next();
275: // if (parentRequest == null && isDuplicateActionRequestDetected(rule, routeHeader, context.getNodeInstance(), resp, qualifiedRoleName)) {
276: // continue;
277: // }
278: //
279: // ResolvedQualifiedRole resolvedRole = roleAttribute.resolveQualifiedRole(context, roleName, qualifiedRoleName);
280: // RoleRecipient recipient = new RoleRecipient(roleName, qualifiedRoleName, resolvedRole);
281: // if (parentRequest == null) {
282: // ActionRequestValue roleRequest = arFactory.addRoleRequest(recipient, resp.getActionRequestedCd(), resp.getApprovePolicy(), resp.getPriority(), resp.getResponsibilityId(), rule
283: // .getIgnorePrevious(), rule.getDescription(), rule.getRuleBaseValuesId());
284: // if (resp.isDelegating()) {
285: // // create delegations for all the children
286: // for (Iterator iterator = roleRequest.getChildrenRequests().iterator(); iterator.hasNext();) {
287: // ActionRequestValue request = (ActionRequestValue) iterator.next();
288: // for (Iterator ruleDelegationIterator = resp.getDelegationRules().iterator(); ruleDelegationIterator.hasNext();) {
289: // RuleDelegation childRuleDelegation = (RuleDelegation) ruleDelegationIterator.next();
290: // buildDelegationGraph(context, childRuleDelegation.getDelegationRuleBaseValues(), routeHeader, request, childRuleDelegation);
291: // }
292: // }
293: // }
294: // } else {
295: // arFactory.addDelegationRoleRequest(parentRequest, resp.getApprovePolicy(), recipient, resp.getResponsibilityId(), rule.getIgnorePrevious(), ruleDelegation.getDelegationType(), rule.getDescription(), rule.getRuleBaseValuesId());
296: // }
297: // }
298: // }
299: //
300: // private void makeActionRequest(RouteContext context, RuleBaseValues rule, DocumentRouteHeaderValue routeHeader, RuleResponsibility resp, ActionRequestValue parentRequest,
301: // RuleDelegation ruleDelegation) throws EdenUserNotFoundException, WorkflowException {
302: // if (parentRequest == null && isDuplicateActionRequestDetected(rule, routeHeader, context.getNodeInstance(), resp, null)) {
303: // return;
304: // }
305: // Recipient recipient;
306: // if (resp.isUsingWorkflowUser()) {
307: // recipient = KEWServiceLocator.getUserService().getWorkflowUser(new WorkflowUserId(resp.getRuleResponsibilityName()));
308: // } else {
309: // recipient = KEWServiceLocator.getWorkgroupService().getWorkgroup(new WorkflowGroupId(new Long(resp.getRuleResponsibilityName())));
310: // }
311: // ActionRequestValue actionRequest;
312: // if (parentRequest == null) {
313: // actionRequest = arFactory.addRootActionRequest(resp.getActionRequestedCd(), resp.getPriority(), recipient, rule.getDescription(), resp.getResponsibilityId(), rule.getIgnorePrevious(),
314: // resp.getApprovePolicy(), rule.getRuleBaseValuesId());
315: // if (resp.isDelegating()) {
316: // for (Iterator iterator = resp.getDelegationRules().iterator(); iterator.hasNext();) {
317: // RuleDelegation childRuleDelegation = (RuleDelegation) iterator.next();
318: // buildDelegationGraph(context, childRuleDelegation.getDelegationRuleBaseValues(), routeHeader, actionRequest, childRuleDelegation);
319: // }
320: // }
321: // } else {
322: // arFactory.addDelegationRequest(parentRequest, recipient, resp.getResponsibilityId(), rule.getIgnorePrevious(), ruleDelegation.getDelegationType(), rule.getDescription(), rule.getRuleBaseValuesId());
323: // }
324: // }
325: //
326: // private boolean isDuplicateActionRequestDetected(RuleBaseValues rule, DocumentRouteHeaderValue routeHeader, RouteNodeInstance nodeInstance, RuleResponsibility resp, String qualifiedRoleName) {
327: // List requests = getActionRequestService().findByStatusAndDocId(EdenConstants.ACTION_REQUEST_DONE_STATE, routeHeader.getRouteHeaderId());
328: // for (Iterator iterator = requests.iterator(); iterator.hasNext();) {
329: // ActionRequestValue request = (ActionRequestValue) iterator.next();
330: // if (((nodeInstance != null && request.getNodeInstance() != null && request.getNodeInstance().getRouteNodeInstanceId().equals(nodeInstance.getRouteNodeInstanceId())) || request
331: // .getRouteLevel().equals(routeHeader.getDocRouteLevel()))
332: // && request.getResponsibilityId().equals(resp.getResponsibilityId()) && ObjectUtils.equals(request.getQualifiedRoleName(), qualifiedRoleName)) {
333: // return true;
334: // }
335: // }
336: // return false;
337: // }
338:
339: private RoleService getRoleService() {
340: return KEWServiceLocator.getRoleService();
341: }
342:
343: private ActionRequestService getActionRequestService() {
344: return KEWServiceLocator.getActionRequestService();
345: }
346:
347: }
|