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