1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.service.impl;
17
18 import org.apache.commons.lang.StringUtils;
19 import org.apache.log4j.Logger;
20 import org.kuali.rice.core.api.exception.RiceRuntimeException;
21 import org.kuali.rice.krad.bo.AdHocRoutePerson;
22 import org.kuali.rice.krad.bo.AdHocRouteWorkgroup;
23 import org.kuali.rice.krad.document.Document;
24 import org.kuali.rice.krad.document.TransactionalDocument;
25 import org.kuali.rice.krad.maintenance.MaintenanceDocument;
26 import org.kuali.rice.krad.rules.MaintenanceDocumentRuleBase;
27 import org.kuali.rice.krad.rules.TransactionalDocumentRuleBase;
28 import org.kuali.rice.krad.rules.rule.BusinessRule;
29 import org.kuali.rice.krad.rules.rule.event.AddAdHocRoutePersonEvent;
30 import org.kuali.rice.krad.rules.rule.event.AddAdHocRouteWorkgroupEvent;
31 import org.kuali.rice.krad.rules.rule.event.DocumentEvent;
32 import org.kuali.rice.krad.rules.rule.event.RuleEvent;
33 import org.kuali.rice.krad.service.DataDictionaryService;
34 import org.kuali.rice.krad.service.DocumentDictionaryService;
35 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
36 import org.kuali.rice.krad.service.KualiRuleService;
37 import org.kuali.rice.krad.uif.component.MethodInvokerConfig;
38 import org.kuali.rice.krad.util.GlobalVariables;
39 import org.kuali.rice.krad.util.KRADConstants;
40 import org.kuali.rice.krad.util.MessageMap;
41
42 import java.util.ArrayList;
43 import java.util.List;
44
45
46
47
48
49
50
51
52 public class KualiRuleServiceImpl implements KualiRuleService {
53 private static final Logger LOG = Logger.getLogger(KualiRuleServiceImpl.class);
54
55 private DocumentDictionaryService documentDictionaryService;
56 private DataDictionaryService dataDictionaryService;
57
58
59
60
61 public boolean applyRules(DocumentEvent event) {
62 if (event == null) {
63 throw new IllegalArgumentException("invalid (null) event");
64 }
65
66 event.validate();
67 if (LOG.isDebugEnabled()) {
68 LOG.debug("calling applyRules for event " + event);
69 }
70
71 BusinessRule rule = getBusinessRulesInstance(event.getDocument(), event.getRuleInterfaceClass());
72
73 boolean success = true;
74 if (rule != null) {
75 if (LOG.isDebugEnabled()) {
76 LOG.debug("processing " + event.getName() + " with rule " + rule.getClass().getName());
77 }
78 increaseErrorPath(event.getErrorPathPrefix());
79
80
81 List<RuleEvent> events = event.generateEvents();
82 for (RuleEvent generatedEvent : events) {
83 success &= applyRules((DocumentEvent) generatedEvent);
84 }
85
86
87 if (StringUtils.isNotBlank(event.getRuleMethodName())) {
88 success &= invokeBusinessRuleMethod(rule, event);
89 } else {
90 success &= event.invokeRuleMethod(rule);
91 }
92
93 decreaseErrorPath(event.getErrorPathPrefix());
94
95
96 if (!success) {
97 if (LOG.isDebugEnabled()) {
98 LOG.debug(event.getName() + " businessRule " + rule.getClass().getName() + " failed");
99 }
100 } else {
101 if (LOG.isDebugEnabled()) {
102 LOG.debug("processed " + event.getName() + " for rule " + rule.getClass().getName());
103 }
104 }
105
106 }
107 return success;
108 }
109
110
111
112
113
114
115
116
117 public boolean invokeBusinessRuleMethod(BusinessRule rule, DocumentEvent event) {
118 boolean success = true;
119
120 String methodName = event.getRuleMethodName();
121 MethodInvokerConfig methodInvoker = new MethodInvokerConfig();
122 methodInvoker.setTargetClass(rule.getClass());
123 methodInvoker.setTargetMethod(methodName);
124
125 Object[] arguments = new Object[1];
126 arguments[0] = event;
127 methodInvoker.setArguments(arguments);
128
129
130 try {
131 LOG.debug("Invoking rule method: " + methodInvoker.getTargetMethod() + " for class: " + rule.getClass()
132 .getName());
133 methodInvoker.prepare();
134
135 Class<?> methodReturnType = methodInvoker.getPreparedMethod().getReturnType();
136 if (StringUtils.equals("void", methodReturnType.getName())) {
137 methodInvoker.invoke();
138 } else {
139 success &= (Boolean) methodInvoker.invoke();
140 }
141 } catch (Exception e) {
142 LOG.error("Error invoking rule method for class: " + rule.getClass().getName(), e);
143 throw new RuntimeException("Error invoking rule method for class: " + rule.getClass().getName(), e);
144 }
145
146 return success;
147 }
148
149
150
151
152
153
154
155 public List<AddAdHocRoutePersonEvent> generateAdHocRoutePersonEvents(Document document) {
156 List<AdHocRoutePerson> adHocRoutePersons = document.getAdHocRoutePersons();
157
158 List<AddAdHocRoutePersonEvent> events = new ArrayList<AddAdHocRoutePersonEvent>();
159
160 for (int i = 0; i < adHocRoutePersons.size(); i++) {
161 events.add(new AddAdHocRoutePersonEvent(
162 KRADConstants.EXISTING_AD_HOC_ROUTE_PERSON_PROPERTY_NAME + "[" + i + "]", document,
163 adHocRoutePersons.get(i)));
164 }
165
166 return events;
167 }
168
169
170
171
172
173
174
175 public List<AddAdHocRouteWorkgroupEvent> generateAdHocRouteWorkgroupEvents(Document document) {
176 List<AdHocRouteWorkgroup> adHocRouteWorkgroups = document.getAdHocRouteWorkgroups();
177
178 List<AddAdHocRouteWorkgroupEvent> events = new ArrayList<AddAdHocRouteWorkgroupEvent>();
179
180 for (int i = 0; i < adHocRouteWorkgroups.size(); i++) {
181 events.add(new AddAdHocRouteWorkgroupEvent(
182 KRADConstants.EXISTING_AD_HOC_ROUTE_WORKGROUP_PROPERTY_NAME + "[" + i + "]", document,
183 adHocRouteWorkgroups.get(i)));
184 }
185
186 return events;
187 }
188
189
190
191
192
193
194
195 public BusinessRule getBusinessRulesInstance(Document document, Class<? extends BusinessRule> ruleInterface) {
196
197 Class<? extends BusinessRule> businessRulesClass = null;
198 if (document instanceof TransactionalDocument) {
199 TransactionalDocument transactionalDocument = (TransactionalDocument) document;
200
201 businessRulesClass = getDocumentDictionaryService().getBusinessRulesClass(transactionalDocument);
202 if (businessRulesClass == null) {
203 return new TransactionalDocumentRuleBase();
204 }
205 } else if (document instanceof MaintenanceDocument) {
206 MaintenanceDocument maintenanceDocument = (MaintenanceDocument) document;
207
208 businessRulesClass = getDocumentDictionaryService().getBusinessRulesClass(maintenanceDocument);
209 if (businessRulesClass == null) {
210 return new MaintenanceDocumentRuleBase();
211 }
212 } else {
213 LOG.error("unable to get businessRulesClass for unknown document type '"
214 + document.getClass().getName()
215 + "'");
216 }
217
218
219 BusinessRule rule = null;
220 if (businessRulesClass != null) {
221 try {
222 if (ruleInterface.isAssignableFrom(businessRulesClass)) {
223 rule = businessRulesClass.newInstance();
224 }
225 } catch (IllegalAccessException e) {
226 throw new RiceRuntimeException("error processing business rules", e);
227 } catch (InstantiationException e) {
228 throw new RiceRuntimeException("error processing business rules", e);
229 }
230 }
231
232 return rule;
233 }
234
235
236
237
238
239
240
241 private void increaseErrorPath(String errorPathPrefix) {
242 MessageMap errorMap = GlobalVariables.getMessageMap();
243
244 if (!StringUtils.isBlank(errorPathPrefix)) {
245 errorMap.addToErrorPath(errorPathPrefix);
246 }
247 }
248
249
250
251
252
253
254
255 private void decreaseErrorPath(String errorPathPrefix) {
256 MessageMap errorMap = GlobalVariables.getMessageMap();
257
258 if (!StringUtils.isBlank(errorPathPrefix)) {
259 errorMap.removeFromErrorPath(errorPathPrefix);
260 }
261 }
262
263 public DocumentDictionaryService getDocumentDictionaryService() {
264 if (documentDictionaryService == null) {
265 this.documentDictionaryService = KRADServiceLocatorWeb.getDocumentDictionaryService();
266 }
267 return documentDictionaryService;
268 }
269
270 public void setDocumentDictionaryService(DocumentDictionaryService documentDictionaryService) {
271 this.documentDictionaryService = documentDictionaryService;
272 }
273
274 public DataDictionaryService getDataDictionaryService() {
275 return dataDictionaryService;
276 }
277
278 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
279 this.dataDictionaryService = dataDictionaryService;
280 }
281 }