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