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