View Javadoc
1   /**
2    * Copyright 2005-2016 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kew.rule;
17  
18  import org.joda.time.DateTime;
19  import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
20  import org.kuali.rice.kew.api.KewApiServiceLocator;
21  import org.kuali.rice.kew.api.WorkflowRuntimeException;
22  import org.kuali.rice.kew.api.extension.ExtensionDefinition;
23  import org.kuali.rice.kew.api.extension.ExtensionUtils;
24  import org.kuali.rice.kew.api.rule.RuleTemplate;
25  import org.kuali.rice.kew.api.rule.RuleTemplateAttribute;
26  import org.kuali.rice.kew.engine.RouteContext;
27  import org.kuali.rice.kew.engine.node.RouteNodeInstance;
28  import org.kuali.rice.kew.routeheader.DocumentContent;
29  import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
30  import org.kuali.rice.kew.rule.bo.RuleAttribute;
31  import org.kuali.rice.kew.util.PerformanceLogger;
32  
33  import java.sql.Timestamp;
34  import java.util.ArrayList;
35  import java.util.HashSet;
36  import java.util.List;
37  import java.util.Set;
38  
39  /**
40   * Rule selector that selects rules based on configured template name 
41   * @author Kuali Rice Team (rice.collab@kuali.org)
42   */
43  class TemplateRuleSelector implements RuleSelector {
44      /**
45       * Records the number of selected rules, prior to MassRuleAttribute filtering
46       */
47      private int numberOfSelectedRules;
48  
49      /**
50       * @return the number of selected rules, prior to MassRuleAttribute filtering
51       */
52      int getNumberOfSelectedRules() {
53  	return numberOfSelectedRules;
54      }
55  
56      public List<Rule> selectRules(RouteContext context, DocumentRouteHeaderValue routeHeader, RouteNodeInstance nodeInstance, String selectionCriterion, Timestamp effectiveDate) {
57          // for TemplateRuleSelector, the criterion is taken as a ruletemplate name
58          final String ruleTemplateName = selectionCriterion;
59  
60          Set<MassRuleAttribute> massRules = new HashSet<MassRuleAttribute>();
61          RuleTemplate template = KewApiServiceLocator.getRuleService().getRuleTemplateByName(ruleTemplateName);
62          if (template == null) {
63              throw new WorkflowRuntimeException("Could not locate the rule template with name " + ruleTemplateName + " on document " + routeHeader.getDocumentId());
64          }
65          for (RuleTemplateAttribute templateAttribute : template.getActiveRuleTemplateAttributes()) {
66              String ruleAttributeName = templateAttribute.getRuleAttribute().getName();
67              if (!RuleAttribute.isWorkflowAttribute(templateAttribute.getRuleAttribute().getType())) {
68                  continue;
69              }
70              ExtensionDefinition extensionDefinition = KewApiServiceLocator.getExtensionRepositoryService().getExtensionByName(ruleAttributeName);
71              Object attribute = ExtensionUtils.loadExtension(extensionDefinition);
72              if (attribute == null) {
73                  throw new RiceIllegalArgumentException("Failed to load WorkflowRuleAttribute for: " + extensionDefinition);
74              }
75              if (!WorkflowRuleAttribute.class.isAssignableFrom(attribute.getClass())) {
76                  throw new RiceIllegalArgumentException("Failed to locate a WorkflowRuleAttribute with the given name: " + ruleAttributeName);
77              }
78              if (attribute instanceof XmlConfiguredAttribute) {
79                  ((XmlConfiguredAttribute)attribute).setExtensionDefinition(extensionDefinition);
80              }
81  
82              WorkflowRuleAttribute ruleAttribute = (WorkflowRuleAttribute)attribute;
83              if (ruleAttribute instanceof MassRuleAttribute) {
84                  massRules.add((MassRuleAttribute) attribute);
85              }
86  
87          }
88  
89          List<org.kuali.rice.kew.api.rule.Rule> rules;
90          if (effectiveDate == null) {
91              rules = KewApiServiceLocator.getRuleService()
92                      .getRulesByTemplateNameAndDocumentTypeName(ruleTemplateName,
93                              routeHeader.getDocumentType().getName());
94          } else {
95              rules = KewApiServiceLocator.getRuleService()
96                      .getRulesByTemplateNameAndDocumentTypeNameAndEffectiveDate(ruleTemplateName,
97                              routeHeader.getDocumentType().getName(), new DateTime(effectiveDate.getTime()));
98          }
99          numberOfSelectedRules = rules.size();
100 
101         // TODO really the route context just needs to be able to support nested create and clears
102         // (i.e. a Stack model similar to transaction intercepting in Spring) and we wouldn't have to do this
103         if (context.getDocument() == null) {
104             context.setDocument(routeHeader);
105         }
106         if (context.getNodeInstance() == null) {
107             context.setNodeInstance(nodeInstance);
108         }
109         DocumentContent documentContent = context.getDocumentContent();
110         PerformanceLogger performanceLogger = new PerformanceLogger();
111         // have all mass rule attributes filter the list of non applicable rules
112         for (MassRuleAttribute massRuleAttribute : massRules) {
113             rules = massRuleAttribute.filterNonMatchingRules(context, rules);
114         }
115         performanceLogger.log("Time to filter massRules for template " + template.getName());
116 
117         List<Rule> ruleList = new ArrayList<Rule>(rules.size());
118         for (org.kuali.rice.kew.api.rule.Rule ruleDefinition: rules) {
119             ruleList.add(new RuleImpl(ruleDefinition));
120         }
121         return ruleList;
122     }
123 
124 }