1   
2   
3   
4   
5   
6   
7   
8   
9   
10  
11  
12  
13  
14  
15  
16  package org.kuali.rice.krms.impl.rule;
17  
18  import org.apache.commons.collections.CollectionUtils;
19  import org.apache.commons.lang.StringUtils;
20  import org.kuali.rice.core.api.resourceloader.GlobalResourceLoader;
21  import org.kuali.rice.core.api.uif.RemotableAttributeError;
22  import org.kuali.rice.core.api.util.RiceKeyConstants;
23  import org.kuali.rice.kns.maintenance.rules.MaintenanceDocumentRuleBase;
24  import org.kuali.rice.krad.bo.GlobalBusinessObject;
25  import org.kuali.rice.krad.bo.PersistableBusinessObject;
26  import org.kuali.rice.krad.maintenance.MaintenanceDocument;
27  import org.kuali.rice.krad.util.KRADConstants;
28  import org.kuali.rice.krms.api.KrmsConstants;
29  import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition;
30  import org.kuali.rice.krms.api.repository.rule.RuleDefinition;
31  import org.kuali.rice.krms.api.repository.type.KrmsTypeDefinition;
32  import org.kuali.rice.krms.api.repository.type.KrmsTypeRepositoryService;
33  import org.kuali.rice.krms.framework.type.ActionTypeService;
34  import org.kuali.rice.krms.framework.type.AgendaTypeService;
35  import org.kuali.rice.krms.impl.authorization.AgendaAuthorizationService;
36  import org.kuali.rice.krms.impl.repository.*;
37  import org.kuali.rice.krms.impl.ui.AgendaEditor;
38  import org.kuali.rice.krms.impl.util.KRMSPropertyConstants;
39  
40  import javax.xml.namespace.QName;
41  import java.util.List;
42  import java.util.Map;
43  
44  
45  
46  
47  public class AgendaEditorBusRule extends MaintenanceDocumentRuleBase {
48  
49  
50      protected boolean primaryKeyCheck(MaintenanceDocument document) {
51          
52          boolean success = true;
53          Class<?> dataObjectClass = document.getNewMaintainableObject().getDataObjectClass();
54  
55          
56          Object oldBo = ((AgendaEditor) document.getOldMaintainableObject().getDataObject()).getAgenda();
57          Object newDataObject = ((AgendaEditor) document.getNewMaintainableObject().getDataObject()).getAgenda();
58  
59          
60          
61          
62          
63          
64          if (newDataObject instanceof GlobalBusinessObject) {
65              return success;
66          }
67  
68          
69          
70          if (document.isEdit()) {
71              if (!getDataObjectMetaDataService().equalsByPrimaryKeys(oldBo, newDataObject)) {
72                  
73                  putDocumentError(KRADConstants.DOCUMENT_ERRORS,
74                          RiceKeyConstants.ERROR_DOCUMENT_MAINTENANCE_PRIMARY_KEYS_CHANGED_ON_EDIT,
75                          getHumanReadablePrimaryKeyFieldNames(dataObjectClass));
76                  success &= false;
77              }
78          }
79  
80          
81          
82          else if (document.isNew()) {
83  
84              
85              if (newDataObject instanceof PersistableBusinessObject) {
86  
87                  
88                  Map<String, ?> newPkFields = getDataObjectMetaDataService().getPrimaryKeyFieldValues(newDataObject);
89  
90                  
91                  
92                  
93                  
94  
95                  
96                  PersistableBusinessObject testBo = getBoService()
97                          .findByPrimaryKey(dataObjectClass.asSubclass(PersistableBusinessObject.class), newPkFields);
98  
99                  
100                 
101                 if (testBo != null) {
102                     putDocumentError(KRADConstants.DOCUMENT_ERRORS,
103                             RiceKeyConstants.ERROR_DOCUMENT_MAINTENANCE_KEYS_ALREADY_EXIST_ON_CREATE_NEW,
104                             getHumanReadablePrimaryKeyFieldNames(dataObjectClass));
105                     success &= false;
106                 }
107             }
108         }
109 
110         return success;
111     }
112 
113 
114 
115 
116     protected boolean processCustomSaveDocumentBusinessRules(MaintenanceDocument document) {
117         boolean isValid = true;
118 
119         AgendaEditor agendaEditor = (AgendaEditor) document.getNewMaintainableObject().getDataObject();
120         AgendaEditor oldAgendaEditor = (AgendaEditor) document.getOldMaintainableObject().getDataObject();
121         isValid &= validContext(agendaEditor);
122         isValid &= validAgendaName(agendaEditor);
123         isValid &= validContextAgendaNamespace(agendaEditor);
124         isValid &= validAgendaTypeAndAttributes(oldAgendaEditor, agendaEditor);
125 
126         return isValid;
127     }
128 
129     
130 
131 
132 
133 
134     public boolean validContext(AgendaEditor agendaEditor) {
135         boolean isValid = true;
136 
137         try {
138             if (getContextBoService().getContextByContextId(agendaEditor.getAgenda().getContextId()) == null) {
139                 this.putFieldError(KRMSPropertyConstants.Agenda.CONTEXT, "error.agenda.invalidContext");
140                 isValid = false;
141             } else {
142                 if (!getAgendaAuthorizationService().isAuthorized(KrmsConstants.MAINTAIN_KRMS_AGENDA,
143                         agendaEditor.getAgenda().getContextId())) {
144                     this.putFieldError(KRMSPropertyConstants.Agenda.CONTEXT, "error.agenda.unauthorizedContext");
145                     isValid = false;
146                 }
147             }
148         }
149         catch (IllegalArgumentException e) {
150             this.putFieldError(KRMSPropertyConstants.Agenda.CONTEXT, "error.agenda.invalidContext");
151             isValid = false;
152         }
153 
154         return isValid;
155     }
156 
157     
158 
159 
160 
161 
162     public boolean validContextAgendaNamespace(AgendaEditor agendaEditor) {
163         
164         if (StringUtils.isBlank(agendaEditor.getNamespace())) {
165             this.putFieldError(KRMSPropertyConstants.Context.NAMESPACE, "error.context.invalidNamespace");
166             return false;
167         }
168         return true;
169     }
170 
171     private boolean validAgendaTypeAndAttributes( AgendaEditor oldAgendaEditor, AgendaEditor newAgendaEditor) {
172         if (validAgendaType(newAgendaEditor.getAgenda().getTypeId(), newAgendaEditor.getAgenda().getContextId())) {
173             return validAgendaAttributes(oldAgendaEditor, newAgendaEditor);
174         } else {
175             return false;
176         }
177     }
178     private boolean validAgendaType(String typeId, String contextId) {
179         boolean isValid = true;
180 
181         if (!StringUtils.isBlank(typeId) && !StringUtils.isBlank(contextId)) {
182             if (getKrmsTypeRepositoryService().getAgendaTypeByAgendaTypeIdAndContextId(typeId, contextId) != null) {
183                 return true;
184             } else {
185                 this.putFieldError(KRMSPropertyConstants.Agenda.TYPE, "error.agenda.invalidType");
186                 return false;
187             }
188         }
189 
190         return isValid;
191     }
192 
193     private boolean validAgendaAttributes(AgendaEditor oldAgendaEditor, AgendaEditor newAgendaEditor) {
194         boolean isValid = true;
195 
196         String typeId = newAgendaEditor.getAgenda().getTypeId();
197 
198         if (!StringUtils.isEmpty(typeId)) {
199             KrmsTypeDefinition typeDefinition = getKrmsTypeRepositoryService().getTypeById(typeId);
200 
201             if (typeDefinition == null) {
202                 throw new IllegalStateException("agenda typeId must match the id of a valid krms type");
203             } else if (StringUtils.isBlank(typeDefinition.getServiceName())) {
204                 throw new IllegalStateException("agenda type definition must have a non-blank service name");
205             } else {
206                 AgendaTypeService agendaTypeService =
207                         (AgendaTypeService)KrmsRepositoryServiceLocator.getService(typeDefinition.getServiceName());
208 
209                 if (agendaTypeService == null) {
210                     throw new IllegalStateException("typeDefinition must have a valid serviceName");
211                 } else {
212 
213                     List<RemotableAttributeError> errors;
214                     if (oldAgendaEditor == null) {
215                         errors = agendaTypeService.validateAttributes(typeId, newAgendaEditor.getCustomAttributesMap());
216                     } else {
217                         errors = agendaTypeService.validateAttributesAgainstExisting(typeId, newAgendaEditor.getCustomAttributesMap(), oldAgendaEditor.getCustomAttributesMap());
218                     }
219 
220                     if (!CollectionUtils.isEmpty(errors)) {
221                         isValid = false;
222                         for (RemotableAttributeError error : errors) {
223                             for (String errorStr : error.getErrors()) {
224                                 this.putFieldError(
225                                         KRMSPropertyConstants.AgendaEditor.CUSTOM_ATTRIBUTES_MAP +
226                                                 "['" + error.getAttributeName() + "']",
227                                         errorStr
228                                 );
229                             }
230                         }
231                     }
232                 }
233             }
234         }
235         return isValid;
236     }
237 
238     
239 
240 
241 
242 
243     public boolean validAgendaName(AgendaEditor agendaEditor) {
244         try {
245             AgendaDefinition agendaFromDataBase = getAgendaBoService().getAgendaByNameAndContextId(
246                     agendaEditor.getAgenda().getName(), agendaEditor.getAgenda().getContextId());
247             if ((agendaFromDataBase != null) && !StringUtils.equals(agendaFromDataBase.getId(), agendaEditor.getAgenda().getId())) {
248                 this.putFieldError(KRMSPropertyConstants.Agenda.NAME, "error.agenda.duplicateName");
249                 return false;
250             }
251         }
252         catch (IllegalArgumentException e) {
253             this.putFieldError(KRMSPropertyConstants.Agenda.NAME, "error.agenda.invalidName");
254             return false;
255         }
256         return true;
257     }
258 
259     
260 
261 
262 
263 
264 
265     public boolean processAgendaItemBusinessRules(MaintenanceDocument document) {
266         boolean isValid = true;
267 
268         AgendaEditor newAgendaEditor = (AgendaEditor) document.getNewMaintainableObject().getDataObject();
269         AgendaEditor oldAgendaEditor = (AgendaEditor) document.getOldMaintainableObject().getDataObject();
270         RuleBo rule = newAgendaEditor.getAgendaItemLine().getRule();
271         isValid &= validateRuleName(rule, newAgendaEditor.getAgenda());
272         isValid &= validRuleType(rule.getTypeId(), newAgendaEditor.getAgenda().getContextId());
273         isValid &= validateRuleAction(oldAgendaEditor, newAgendaEditor);
274 
275         return isValid;
276     }
277 
278     
279 
280 
281 
282 
283 
284     private boolean validateRuleName(RuleBo rule, AgendaBo agenda) {
285         if (StringUtils.isBlank(rule.getName())) {
286             this.putFieldError(KRMSPropertyConstants.Rule.NAME, "error.rule.invalidName");
287             return false;
288         }
289         
290         for (AgendaItemBo agendaItem : agenda.getItems()) {
291             if (!StringUtils.equals(agendaItem.getRule().getId(), rule.getId()) && StringUtils.equals(agendaItem.getRule().getName(), rule.getName())
292                     && StringUtils.equals(agendaItem.getRule().getNamespace(), rule.getNamespace())) {
293                 this.putFieldError(KRMSPropertyConstants.Rule.NAME, "error.rule.duplicateName");
294                 return false;
295             }
296         }
297 
298         
299         if (StringUtils.isNotBlank(rule.getNamespace())) {
300             RuleDefinition ruleFromDatabase = getRuleBoService().getRuleByNameAndNamespace(rule.getName(), rule.getNamespace());
301             try {
302                 if ((ruleFromDatabase != null) && !StringUtils.equals(ruleFromDatabase.getId(), rule.getId())) {
303                     this.putFieldError(KRMSPropertyConstants.Rule.NAME, "error.rule.duplicateName");
304                     return false;
305                 }
306             }
307             catch (IllegalArgumentException e) {
308                 this.putFieldError(KRMSPropertyConstants.Rule.NAME, "error.rule.invalidName");
309                 return false;
310             }
311         }
312         return true;
313     }
314 
315     
316 
317 
318 
319 
320 
321     private boolean validRuleType(String ruleTypeId, String contextId) {
322         if (StringUtils.isBlank(ruleTypeId)) {
323             return true;
324         }
325 
326         if (getKrmsTypeRepositoryService().getRuleTypeByRuleTypeIdAndContextId(ruleTypeId, contextId) != null) {
327             return true;
328         } else {
329             this.putFieldError(KRMSPropertyConstants.Rule.TYPE, "error.rule.invalidType");
330             return false;
331         }
332     }
333 
334     private boolean validateRuleAction(AgendaEditor oldAgendaEditor, AgendaEditor newAgendaEditor) {
335         boolean isValid = true;
336         ActionBo newActionBo = newAgendaEditor.getAgendaItemLineRuleAction();
337 
338         isValid &= validRuleActionType(newActionBo.getTypeId(), newAgendaEditor.getAgenda().getContextId());
339         if (isValid && StringUtils.isNotBlank(newActionBo.getTypeId())) {
340             isValid &= validRuleActionName(newActionBo.getName());
341             isValid &= validRuleActionAttributes(oldAgendaEditor, newAgendaEditor);
342         }
343         return isValid;
344     }
345 
346     
347 
348 
349 
350 
351 
352     private boolean validRuleActionType(String typeId, String contextId) {
353         if (StringUtils.isBlank(typeId)) {
354             return true;
355         }
356 
357         if (getKrmsTypeRepositoryService().getActionTypeByActionTypeIdAndContextId(typeId, contextId) != null) {
358             return true;
359         } else {
360             this.putFieldError(KRMSPropertyConstants.Action.TYPE, "error.action.invalidType");
361             return false;
362         }
363     }
364 
365     
366 
367 
368     private boolean validRuleActionName(String name) {
369         if (StringUtils.isNotBlank(name)) {
370             return true;
371         } else {
372             this.putFieldError(KRMSPropertyConstants.Action.NAME, "error.action.missingName");
373             return false;
374         }
375     }
376 
377     private boolean validRuleActionAttributes(AgendaEditor oldAgendaEditor, AgendaEditor newAgendaEditor) {
378         boolean isValid = true;
379 
380         String typeId = newAgendaEditor.getAgendaItemLineRuleAction().getTypeId();
381 
382         if (!StringUtils.isBlank(typeId)) {
383             KrmsTypeDefinition typeDefinition = getKrmsTypeRepositoryService().getTypeById(typeId);
384 
385             if (typeDefinition == null) {
386                 throw new IllegalStateException("rule action typeId must match the id of a valid krms type");
387             } else if (StringUtils.isBlank(typeDefinition.getServiceName())) {
388                 throw new IllegalStateException("rule action type definition must have a non-blank service name");
389             } else {
390                 ActionTypeService actionTypeService = getActionTypeService(typeDefinition.getServiceName());
391 
392                 if (actionTypeService == null) {
393                     throw new IllegalStateException("typeDefinition must have a valid serviceName");
394                 } else {
395 
396                     List<RemotableAttributeError> errors;
397                     if (oldAgendaEditor == null) {
398                         errors = actionTypeService.validateAttributes(typeId,
399                                 newAgendaEditor.getCustomRuleActionAttributesMap());
400                     } else {
401                         errors = actionTypeService.validateAttributesAgainstExisting(typeId,
402                                 newAgendaEditor.getCustomRuleActionAttributesMap(), oldAgendaEditor.getCustomRuleActionAttributesMap());
403                     }
404 
405                     if (!CollectionUtils.isEmpty(errors)) {
406                         isValid = false;
407                         for (RemotableAttributeError error : errors) {
408                             for (String errorStr : error.getErrors()) {
409                                 this.putFieldError(
410                                         KRMSPropertyConstants.AgendaEditor.CUSTOM_RULE_ACTION_ATTRIBUTES_MAP +
411                                                 "['" + error.getAttributeName() + "']",
412                                         errorStr
413                                 );
414                             }
415                         }
416                     }
417                 }
418             }
419         }
420         return isValid;
421     }
422 
423     public ContextBoService getContextBoService() {
424         return KrmsRepositoryServiceLocator.getContextBoService();
425     }
426 
427     public AgendaBoService getAgendaBoService() {
428         return KrmsRepositoryServiceLocator.getAgendaBoService();
429     }
430 
431     public RuleBoService getRuleBoService() {
432         return KrmsRepositoryServiceLocator.getRuleBoService();
433     }
434 
435     public KrmsTypeRepositoryService getKrmsTypeRepositoryService() {
436         return KrmsRepositoryServiceLocator.getKrmsTypeRepositoryService();
437     }
438 
439     public ActionTypeService getActionTypeService(String serviceName) {
440         return (ActionTypeService)GlobalResourceLoader.getService(QName.valueOf(serviceName));
441     }
442     public AgendaAuthorizationService getAgendaAuthorizationService() {
443         return KrmsRepositoryServiceLocator.getAgendaAuthorizationService();
444     }
445 
446 }
447