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 }