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.document.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 agenda = (AgendaEditor) document.getNewMaintainableObject().getDataObject();
125 AgendaEditor oldAgenda = (AgendaEditor) document.getOldMaintainableObject().getDataObject();
126 isValid &= validContext(agenda);
127 isValid &= validAgendaName(agenda);
128 isValid &= validAgendaAttributes(oldAgenda, agenda);
129
130 return isValid;
131 }
132
133
134
135
136
137
138 private boolean validContext(AgendaEditor agenda) {
139 boolean isValid = true;
140
141 try {
142 if (getContextBoService().getContextByContextId(agenda.getAgenda().getContextId()) == null) {
143 this.putFieldError(KRMSPropertyConstants.Agenda.CONTEXT, "error.agenda.invalidContext");
144 isValid = false;
145 } else {
146 if (!getAgendaAuthorizationService().isAuthorized(KrmsConstants.MAINTAIN_KRMS_AGENDA,
147 agenda.getAgenda().getContextId())) {
148 this.putFieldError(KRMSPropertyConstants.Agenda.CONTEXT, "error.agenda.unauthorizedContext");
149 isValid = false;
150 }
151 }
152 }
153 catch (IllegalArgumentException e) {
154 this.putFieldError(KRMSPropertyConstants.Agenda.CONTEXT, "error.agenda.invalidContext");
155 isValid = false;
156 }
157
158 return isValid;
159 }
160
161 private boolean validAgendaAttributes(AgendaEditor oldAgenda, AgendaEditor newAgenda) {
162 boolean isValid = true;
163
164 String typeId = newAgenda.getAgenda().getTypeId();
165
166 if (!StringUtils.isEmpty(typeId)) {
167 KrmsTypeDefinition typeDefinition = getKrmsTypeRepositoryService().getTypeById(typeId);
168
169 if (typeDefinition == null) {
170 throw new IllegalStateException("agenda typeId must match the id of a valid krms type");
171 } else if (StringUtils.isBlank(typeDefinition.getServiceName())) {
172 throw new IllegalStateException("agenda type definition must have a non-blank service name");
173 } else {
174 AgendaTypeService agendaTypeService =
175 (AgendaTypeService)KrmsRepositoryServiceLocator.getService(typeDefinition.getServiceName());
176
177 if (agendaTypeService == null) {
178 throw new IllegalStateException("typeDefinition must have a valid serviceName");
179 } else {
180
181 List<RemotableAttributeError> errors;
182 if (oldAgenda == null) {
183 errors = agendaTypeService.validateAttributes(typeId, newAgenda.getCustomAttributesMap());
184 } else {
185 errors = agendaTypeService.validateAttributesAgainstExisting(typeId, newAgenda.getCustomAttributesMap(), oldAgenda.getCustomAttributesMap());
186 }
187
188 if (!CollectionUtils.isEmpty(errors)) {
189 isValid = false;
190 for (RemotableAttributeError error : errors) {
191 for (String errorStr : error.getErrors()) {
192 this.putFieldError(
193 KRMSPropertyConstants.AgendaEditor.CUSTOM_ATTRIBUTES_MAP +
194 "['" + error.getAttributeName() + "']",
195 errorStr
196 );
197 }
198 }
199 }
200 }
201 }
202 }
203 return isValid;
204 }
205
206
207
208
209
210
211 private boolean validAgendaName(AgendaEditor agenda) {
212 try {
213 AgendaDefinition agendaFromDataBase = getAgendaBoService().getAgendaByNameAndContextId(agenda.getAgenda().getName(),
214 agenda.getAgenda().getContextId());
215 if ((agendaFromDataBase != null) && !StringUtils.equals(agendaFromDataBase.getId(), agenda.getAgenda().getId())) {
216 this.putFieldError(KRMSPropertyConstants.Agenda.NAME, "error.agenda.duplicateName");
217 return false;
218 }
219 }
220 catch (IllegalArgumentException e) {
221 this.putFieldError(KRMSPropertyConstants.Agenda.NAME, "error.agenda.invalidName");
222 return false;
223 }
224 return true;
225 }
226
227 public boolean processAgendaItemBusinessRules(MaintenanceDocument document) {
228 boolean isValid = true;
229
230 AgendaEditor newAgendaEditor = (AgendaEditor) document.getNewMaintainableObject().getDataObject();
231 AgendaEditor oldAgendaEditor = (AgendaEditor) document.getOldMaintainableObject().getDataObject();
232 RuleBo rule = newAgendaEditor.getAgendaItemLine().getRule();
233 isValid &= validateRuleName(rule, newAgendaEditor.getAgenda());
234 isValid &= validRuleType(rule.getTypeId(), newAgendaEditor.getAgenda().getContextId());
235 isValid &= validateRuleAction(oldAgendaEditor, newAgendaEditor);
236
237 return isValid;
238 }
239
240
241
242
243
244
245
246 private boolean validateRuleName(RuleBo rule, AgendaBo agenda) {
247 if (StringUtils.isBlank(rule.getName())) {
248 this.putFieldError(KRMSPropertyConstants.Rule.NAME, "error.rule.invalidName");
249 return false;
250 }
251
252 for (AgendaItemBo agendaItem : agenda.getItems()) {
253 if (!StringUtils.equals(agendaItem.getRule().getId(), rule.getId()) && StringUtils.equals(agendaItem.getRule().getName(), rule.getName())
254 && StringUtils.equals(agendaItem.getRule().getNamespace(), rule.getNamespace())) {
255 this.putFieldError(KRMSPropertyConstants.Rule.NAME, "error.rule.duplicateName");
256 return false;
257 }
258 }
259
260
261 if (StringUtils.isNotBlank(rule.getNamespace())) {
262 RuleDefinition ruleFromDatabase = getRuleBoService().getRuleByNameAndNamespace(rule.getName(), rule.getNamespace());
263 try {
264 if ((ruleFromDatabase != null) && !StringUtils.equals(ruleFromDatabase.getId(), rule.getId())) {
265 this.putFieldError(KRMSPropertyConstants.Rule.NAME, "error.rule.duplicateName");
266 return false;
267 }
268 }
269 catch (IllegalArgumentException e) {
270 this.putFieldError(KRMSPropertyConstants.Rule.NAME, "error.rule.invalidName");
271 return false;
272 }
273 }
274 return true;
275 }
276
277
278
279
280
281
282
283 private boolean validRuleType(String ruleTypeId, String contextId) {
284 if (StringUtils.isBlank(ruleTypeId)) {
285 return true;
286 }
287
288 if (getKrmsTypeRepositoryService().getRuleTypeByRuleTypeIdAndContextId(ruleTypeId, contextId) != null) {
289 return true;
290 } else {
291 this.putFieldError(KRMSPropertyConstants.Rule.TYPE, "error.rule.invalidType");
292 return false;
293 }
294 }
295
296 private boolean validateRuleAction(AgendaEditor oldAgendaEditor, AgendaEditor newAgendaEditor) {
297 boolean isValid = true;
298 ActionBo newActionBo = newAgendaEditor.getAgendaItemLineRuleAction();
299
300 isValid &= validRuleActionType(newActionBo.getTypeId(), newAgendaEditor.getAgenda().getContextId());
301 if (isValid && StringUtils.isNotBlank(newActionBo.getTypeId())) {
302 isValid &= validRuleActionName(newActionBo.getName());
303 isValid &= validRuleActionAttributes(oldAgendaEditor, newAgendaEditor);
304 isValid &= validRuleActionDescription(newActionBo.getDescription());
305 }
306 return isValid;
307 }
308
309
310
311
312
313
314
315 private boolean validRuleActionType(String typeId, String contextId) {
316 if (StringUtils.isBlank(typeId)) {
317 return true;
318 }
319
320 if (getKrmsTypeRepositoryService().getActionTypeByActionTypeIdAndContextId(typeId, contextId) != null) {
321 return true;
322 } else {
323 this.putFieldError(KRMSPropertyConstants.Action.TYPE, "error.action.invalidType");
324 return false;
325 }
326 }
327
328
329
330
331 private boolean validRuleActionName(String name) {
332 if (StringUtils.isNotBlank(name)) {
333 return true;
334 } else {
335 this.putFieldError(KRMSPropertyConstants.Action.NAME, "error.action.missingName");
336 return false;
337 }
338 }
339
340 private boolean validRuleActionAttributes(AgendaEditor oldAgenda, AgendaEditor newAgenda) {
341 boolean isValid = true;
342
343 String typeId = newAgenda.getAgendaItemLineRuleAction().getTypeId();
344
345 if (!StringUtils.isBlank(typeId)) {
346 KrmsTypeDefinition typeDefinition = getKrmsTypeRepositoryService().getTypeById(typeId);
347
348 if (typeDefinition == null) {
349 throw new IllegalStateException("rule action typeId must match the id of a valid krms type");
350 } else if (StringUtils.isBlank(typeDefinition.getServiceName())) {
351 throw new IllegalStateException("rule action type definition must have a non-blank service name");
352 } else {
353 ActionTypeService actionTypeService = getActionTypeService(typeDefinition.getServiceName());
354
355 if (actionTypeService == null) {
356 throw new IllegalStateException("typeDefinition must have a valid serviceName");
357 } else {
358
359 List<RemotableAttributeError> errors;
360 if (oldAgenda == null) {
361 errors = actionTypeService.validateAttributes(typeId, newAgenda.getCustomRuleActionAttributesMap());
362 } else {
363 errors = actionTypeService.validateAttributesAgainstExisting(typeId, newAgenda.getCustomRuleActionAttributesMap(), oldAgenda.getCustomRuleActionAttributesMap());
364 }
365
366 if (!CollectionUtils.isEmpty(errors)) {
367 isValid = false;
368 for (RemotableAttributeError error : errors) {
369 for (String errorStr : error.getErrors()) {
370 this.putFieldError(
371 KRMSPropertyConstants.AgendaEditor.CUSTOM_RULE_ACTION_ATTRIBUTES_MAP +
372 "['" + error.getAttributeName() + "']",
373 errorStr
374 );
375 }
376 }
377 }
378 }
379 }
380 }
381 return isValid;
382 }
383
384
385
386
387 private boolean validRuleActionDescription(String description) {
388 if (StringUtils.isNotBlank(description)) {
389 return true;
390 } else {
391 this.putFieldError(KRMSPropertyConstants.Action.DESCRIPTION, "error.action.missingDescription");
392 return false;
393 }
394 }
395
396
397 public ContextBoService getContextBoService() {
398 return KrmsRepositoryServiceLocator.getContextBoService();
399 }
400
401 public AgendaBoService getAgendaBoService() {
402 return KrmsRepositoryServiceLocator.getAgendaBoService();
403 }
404
405 public RuleBoService getRuleBoService() {
406 return KrmsRepositoryServiceLocator.getRuleBoService();
407 }
408
409 public KrmsTypeRepositoryService getKrmsTypeRepositoryService() {
410 return KrmsRepositoryServiceLocator.getKrmsTypeRepositoryService();
411 }
412
413 public ActionTypeService getActionTypeService(String serviceName) {
414 return (ActionTypeService)KrmsRepositoryServiceLocator.getService(serviceName);
415 }
416 private AgendaAuthorizationService getAgendaAuthorizationService() {
417 return KrmsRepositoryServiceLocator.getAgendaAuthorizationService();
418 }
419
420 }
421