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.uif.RemotableAttributeError;
21 import org.kuali.rice.core.api.util.RiceKeyConstants;
22 import org.kuali.rice.krad.bo.PersistableBusinessObject;
23 import org.kuali.rice.krad.maintenance.BulkUpdateMaintenanceDataObject;
24 import org.kuali.rice.krad.maintenance.MaintenanceDocument;
25 import org.kuali.rice.krad.rules.MaintenanceDocumentRuleBase;
26 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
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 static org.kuali.rice.krms.impl.repository.BusinessObjectServiceMigrationUtils.findSingleMatching;
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 BulkUpdateMaintenanceDataObject) {
73 return success;
74 }
75
76
77
78 if (document.isEdit()) {
79 if (!KRADServiceLocatorWeb.getLegacyDataAdapter().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 = KRADServiceLocatorWeb.getLegacyDataAdapter().getPrimaryKeyFieldValues(newDataObject);
97
98
99
100
101
102
103
104 PersistableBusinessObject testBo = findSingleMatching(getDataObjectService(),
105 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 if (StringUtils.isNotBlank(agendaEditor.getNamespace()) &&
172 getContextBoService().getContextByNameAndNamespace(agendaEditor.getContextName(), agendaEditor.getNamespace()) != null) {
173 return true;
174 } else {
175 this.putFieldError(KRMSPropertyConstants.Context.NAMESPACE, "error.context.invalidNamespace");
176 return false;
177 }
178 }
179
180 private boolean validAgendaTypeAndAttributes( AgendaEditor oldAgendaEditor, AgendaEditor newAgendaEditor) {
181 if (validAgendaType(newAgendaEditor.getAgenda().getTypeId(), newAgendaEditor.getAgenda().getContextId())) {
182 return validAgendaAttributes(oldAgendaEditor, newAgendaEditor);
183 } else {
184 return false;
185 }
186 }
187 private boolean validAgendaType(String typeId, String contextId) {
188 boolean isValid = true;
189
190 if (!StringUtils.isBlank(typeId) && !StringUtils.isBlank(contextId)) {
191 if (getKrmsTypeRepositoryService().getAgendaTypeByAgendaTypeIdAndContextId(typeId, contextId) != null) {
192 return true;
193 } else {
194 this.putFieldError(KRMSPropertyConstants.Agenda.TYPE, "error.agenda.invalidType");
195 return false;
196 }
197 }
198
199 return isValid;
200 }
201
202 private boolean validAgendaAttributes(AgendaEditor oldAgendaEditor, AgendaEditor newAgendaEditor) {
203 boolean isValid = true;
204
205 String typeId = newAgendaEditor.getAgenda().getTypeId();
206
207 if (!StringUtils.isEmpty(typeId)) {
208 KrmsTypeDefinition typeDefinition = getKrmsTypeRepositoryService().getTypeById(typeId);
209
210 if (typeDefinition == null) {
211 throw new IllegalStateException("agenda typeId must match the id of a valid krms type");
212 } else if (StringUtils.isBlank(typeDefinition.getServiceName())) {
213 throw new IllegalStateException("agenda type definition must have a non-blank service name");
214 } else {
215 AgendaTypeService agendaTypeService =
216 (AgendaTypeService)KrmsRepositoryServiceLocator.getService(typeDefinition.getServiceName());
217
218 if (agendaTypeService == null) {
219 throw new IllegalStateException("typeDefinition must have a valid serviceName");
220 } else {
221
222 List<RemotableAttributeError> errors;
223 if (oldAgendaEditor == null) {
224 errors = agendaTypeService.validateAttributes(typeId, newAgendaEditor.getCustomAttributesMap());
225 } else {
226 errors = agendaTypeService.validateAttributesAgainstExisting(typeId, newAgendaEditor.getCustomAttributesMap(), oldAgendaEditor.getCustomAttributesMap());
227 }
228
229 if (!CollectionUtils.isEmpty(errors)) {
230 isValid = false;
231 for (RemotableAttributeError error : errors) {
232 for (String errorStr : error.getErrors()) {
233 this.putFieldError(
234 KRMSPropertyConstants.AgendaEditor.CUSTOM_ATTRIBUTES_MAP +
235 "['" + error.getAttributeName() + "']",
236 errorStr
237 );
238 }
239 }
240 }
241 }
242 }
243 }
244 return isValid;
245 }
246
247
248
249
250
251
252 public boolean validAgendaName(AgendaEditor agendaEditor) {
253 try {
254 AgendaDefinition agendaFromDataBase = getAgendaBoService().getAgendaByNameAndContextId(
255 agendaEditor.getAgenda().getName(), agendaEditor.getAgenda().getContextId());
256 if ((agendaFromDataBase != null) && !StringUtils.equals(agendaFromDataBase.getId(), agendaEditor.getAgenda().getId())) {
257 this.putFieldError(KRMSPropertyConstants.Agenda.NAME, "error.agenda.duplicateName");
258 return false;
259 }
260 }
261 catch (IllegalArgumentException e) {
262 this.putFieldError(KRMSPropertyConstants.Agenda.NAME, "error.agenda.invalidName");
263 return false;
264 }
265 return true;
266 }
267
268
269
270
271
272
273
274 public boolean processAgendaItemBusinessRules(MaintenanceDocument document) {
275 boolean isValid = true;
276
277 AgendaEditor newAgendaEditor = (AgendaEditor) document.getNewMaintainableObject().getDataObject();
278 AgendaEditor oldAgendaEditor = (AgendaEditor) document.getOldMaintainableObject().getDataObject();
279 RuleBo rule = newAgendaEditor.getAgendaItemLine().getRule();
280 isValid &= validateRuleName(rule, newAgendaEditor.getAgenda());
281 isValid &= validRuleType(rule.getTypeId(), newAgendaEditor.getAgenda().getContextId());
282 isValid &= validateRuleAction(oldAgendaEditor, newAgendaEditor);
283
284 return isValid;
285 }
286
287
288
289
290
291
292
293 private boolean validateRuleName(RuleBo rule, AgendaBo agenda) {
294 if (StringUtils.isBlank(rule.getName())) {
295 this.putFieldError(KRMSPropertyConstants.Rule.NAME, "error.rule.invalidName");
296 return false;
297 }
298
299 for (AgendaItemBo agendaItem : agenda.getItems()) {
300 if (!StringUtils.equals(agendaItem.getRule().getId(), rule.getId()) && StringUtils.equals(agendaItem.getRule().getName(), rule.getName())
301 && StringUtils.equals(agendaItem.getRule().getNamespace(), rule.getNamespace())) {
302 this.putFieldError(KRMSPropertyConstants.Rule.NAME, "error.rule.duplicateName");
303 return false;
304 }
305 }
306
307
308 if (StringUtils.isNotBlank(rule.getNamespace())) {
309 RuleDefinition ruleFromDatabase = getRuleBoService().getRuleByNameAndNamespace(rule.getName(), rule.getNamespace());
310 try {
311 if ((ruleFromDatabase != null) && !StringUtils.equals(ruleFromDatabase.getId(), rule.getId())) {
312 this.putFieldError(KRMSPropertyConstants.Rule.NAME, "error.rule.duplicateName");
313 return false;
314 }
315 }
316 catch (IllegalArgumentException e) {
317 this.putFieldError(KRMSPropertyConstants.Rule.NAME, "error.rule.invalidName");
318 return false;
319 }
320 }
321 return true;
322 }
323
324
325
326
327
328
329
330 private boolean validRuleType(String ruleTypeId, String contextId) {
331 if (StringUtils.isBlank(ruleTypeId)) {
332 return true;
333 }
334
335 if (getKrmsTypeRepositoryService().getRuleTypeByRuleTypeIdAndContextId(ruleTypeId, contextId) != null) {
336 return true;
337 } else {
338 this.putFieldError(KRMSPropertyConstants.Rule.TYPE, "error.rule.invalidType");
339 return false;
340 }
341 }
342
343 private boolean validateRuleAction(AgendaEditor oldAgendaEditor, AgendaEditor newAgendaEditor) {
344 boolean isValid = true;
345 ActionBo newActionBo = newAgendaEditor.getAgendaItemLineRuleAction();
346
347 isValid &= validRuleActionType(newActionBo.getTypeId(), newAgendaEditor.getAgenda().getContextId());
348 if (isValid && StringUtils.isNotBlank(newActionBo.getTypeId())) {
349 isValid &= validRuleActionName(newActionBo.getName());
350 isValid &= validRuleActionAttributes(oldAgendaEditor, newAgendaEditor);
351 }
352 return isValid;
353 }
354
355
356
357
358
359
360
361 private boolean validRuleActionType(String typeId, String contextId) {
362 if (StringUtils.isBlank(typeId)) {
363 return true;
364 }
365
366 if (getKrmsTypeRepositoryService().getActionTypeByActionTypeIdAndContextId(typeId, contextId) != null) {
367 return true;
368 } else {
369 this.putFieldError(KRMSPropertyConstants.Action.TYPE, "error.action.invalidType");
370 return false;
371 }
372 }
373
374
375
376
377 private boolean validRuleActionName(String name) {
378 if (StringUtils.isNotBlank(name)) {
379 return true;
380 } else {
381 this.putFieldError(KRMSPropertyConstants.Action.NAME, "error.action.missingName");
382 return false;
383 }
384 }
385
386 private boolean validRuleActionAttributes(AgendaEditor oldAgendaEditor, AgendaEditor newAgendaEditor) {
387 boolean isValid = true;
388
389 String typeId = newAgendaEditor.getAgendaItemLineRuleAction().getTypeId();
390
391 if (!StringUtils.isBlank(typeId)) {
392 KrmsTypeDefinition typeDefinition = getKrmsTypeRepositoryService().getTypeById(typeId);
393
394 if (typeDefinition == null) {
395 throw new IllegalStateException("rule action typeId must match the id of a valid krms type");
396 } else if (StringUtils.isBlank(typeDefinition.getServiceName())) {
397 throw new IllegalStateException("rule action type definition must have a non-blank service name");
398 } else {
399 ActionTypeService actionTypeService = getActionTypeService(typeDefinition.getServiceName());
400
401 if (actionTypeService == null) {
402 throw new IllegalStateException("typeDefinition must have a valid serviceName");
403 } else {
404
405 List<RemotableAttributeError> errors;
406 if (oldAgendaEditor == null) {
407 errors = actionTypeService.validateAttributes(typeId,
408 newAgendaEditor.getCustomRuleActionAttributesMap());
409 } else {
410 errors = actionTypeService.validateAttributesAgainstExisting(typeId,
411 newAgendaEditor.getCustomRuleActionAttributesMap(), oldAgendaEditor.getCustomRuleActionAttributesMap());
412 }
413
414 if (!CollectionUtils.isEmpty(errors)) {
415 isValid = false;
416 for (RemotableAttributeError error : errors) {
417 for (String errorStr : error.getErrors()) {
418 this.putFieldError(
419 KRMSPropertyConstants.AgendaEditor.CUSTOM_RULE_ACTION_ATTRIBUTES_MAP +
420 "['" + error.getAttributeName() + "']",
421 errorStr
422 );
423 }
424 }
425 }
426 }
427 }
428 }
429 return isValid;
430 }
431
432 public ContextBoService getContextBoService() {
433 return KrmsRepositoryServiceLocator.getContextBoService();
434 }
435
436 public AgendaBoService getAgendaBoService() {
437 return KrmsRepositoryServiceLocator.getAgendaBoService();
438 }
439
440 public RuleBoService getRuleBoService() {
441 return KrmsRepositoryServiceLocator.getRuleBoService();
442 }
443
444 public KrmsTypeRepositoryService getKrmsTypeRepositoryService() {
445 return KrmsRepositoryServiceLocator.getKrmsTypeRepositoryService();
446 }
447
448 public ActionTypeService getActionTypeService(String serviceName) {
449 return (ActionTypeService)KrmsRepositoryServiceLocator.getService(serviceName);
450 }
451
452 public AgendaAuthorizationService getAgendaAuthorizationService() {
453 return KrmsRepositoryServiceLocator.getAgendaAuthorizationService();
454 }
455 }
456