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