1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krms.impl.repository;
17
18 import java.util.ArrayList;
19 import java.util.Collection;
20 import java.util.Collections;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.List;
24 import java.util.Map;
25 import java.util.Map.Entry;
26 import java.util.Set;
27
28 import org.apache.commons.lang.StringUtils;
29 import org.kuali.rice.core.api.CoreApiServiceLocator;
30 import org.kuali.rice.core.api.criteria.CriteriaLookupService;
31 import org.kuali.rice.core.api.criteria.GenericQueryResults;
32 import org.kuali.rice.core.api.criteria.Predicate;
33 import org.kuali.rice.core.api.criteria.QueryByCriteria;
34 import org.kuali.rice.core.api.exception.RiceIllegalArgumentException;
35 import org.kuali.rice.core.api.exception.RiceIllegalStateException;
36 import org.kuali.rice.core.api.mo.ModelObjectUtils;
37 import org.kuali.rice.core.impl.services.CoreImplServiceLocator;
38 import org.kuali.rice.coreservice.api.CoreServiceApiServiceLocator;
39 import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator;
40 import org.kuali.rice.krad.service.BusinessObjectService;
41 import org.kuali.rice.krad.service.KRADServiceLocator;
42 import org.kuali.rice.krad.service.SequenceAccessorService;
43 import org.kuali.rice.krms.api.repository.agenda.AgendaDefinition;
44 import org.kuali.rice.krms.api.repository.agenda.AgendaItemDefinition;
45 import org.kuali.rice.krms.api.repository.type.KrmsAttributeDefinition;
46 import org.kuali.rice.krms.impl.util.KrmsImplConstants.PropertyNames;
47 import org.springframework.util.CollectionUtils;
48
49 import static org.kuali.rice.core.api.criteria.PredicateFactory.in;
50
51
52
53
54
55
56
57
58 public final class AgendaBoServiceImpl implements AgendaBoService {
59
60
61
62 private BusinessObjectService businessObjectService;
63 private CriteriaLookupService criteriaLookupService;
64 private KrmsAttributeDefinitionService attributeDefinitionService;
65 private SequenceAccessorService sequenceAccessorService;
66
67
68 private static final ModelObjectUtils.Transformer<AgendaItemBo, AgendaItemDefinition> toAgendaItemDefinition =
69 new ModelObjectUtils.Transformer<AgendaItemBo, AgendaItemDefinition>() {
70 public AgendaItemDefinition transform(AgendaItemBo input) {
71 return AgendaItemBo.to(input);
72 };
73 };
74
75
76 private static final ModelObjectUtils.Transformer<AgendaBo, AgendaDefinition> toAgendaDefinition =
77 new ModelObjectUtils.Transformer<AgendaBo, AgendaDefinition>() {
78 public AgendaDefinition transform(AgendaBo input) {
79 return AgendaBo.to(input);
80 };
81 };
82
83
84
85
86
87 @Override
88 public AgendaDefinition createAgenda(AgendaDefinition agenda) {
89 if (agenda == null){
90 throw new RiceIllegalArgumentException("agenda is null");
91 }
92 final String nameKey = agenda.getName();
93 final String contextId = agenda.getContextId();
94 final AgendaDefinition existing = getAgendaByNameAndContextId(nameKey, contextId);
95 if (existing != null){
96 throw new IllegalStateException("the agenda to create already exists: " + agenda);
97 }
98
99 AgendaBo agendaBo = from(agenda);
100 businessObjectService.save(agendaBo);
101 return to(agendaBo);
102 }
103
104
105
106
107 @Override
108 public void updateAgenda(AgendaDefinition agenda) {
109 if (agenda == null){
110 throw new RiceIllegalArgumentException("agenda is null");
111 }
112
113
114 final String agendaIdKey = agenda.getId();
115 final AgendaBo existing = businessObjectService.findBySinglePrimaryKey(AgendaBo.class, agendaIdKey);
116 if (existing == null) {
117 throw new IllegalStateException("the agenda does not exist: " + agenda);
118 }
119 final AgendaDefinition toUpdate;
120 if (existing.getId().equals(agenda.getId())) {
121 toUpdate = agenda;
122 } else {
123
124 final AgendaDefinition.Builder builder = AgendaDefinition.Builder.create(agenda);
125 builder.setId(existing.getId());
126 toUpdate = builder.build();
127 }
128
129
130 AgendaBo boToUpdate = from(toUpdate);
131
132
133 Map<String,String> fields = new HashMap<String,String>(1);
134 fields.put(PropertyNames.Agenda.AGENDA_ID, toUpdate.getId());
135 businessObjectService.deleteMatching(AgendaAttributeBo.class, fields);
136
137
138 businessObjectService.save(boToUpdate);
139 }
140
141 @Override
142 public void deleteAgenda(String agendaId) {
143 if (agendaId == null){ throw new RiceIllegalArgumentException("agendaId is null"); }
144 final AgendaBo bo = businessObjectService.findBySinglePrimaryKey(AgendaBo.class, agendaId);
145 if (bo == null){ throw new IllegalStateException("the Agenda to delete does not exists: " + agendaId);}
146
147 List<AgendaItemDefinition> agendaItems = this.getAgendaItemsByAgendaId(bo.getId());
148 for( AgendaItemDefinition agendaItem : agendaItems) {
149 businessObjectService.delete(AgendaItemBo.from(agendaItem));
150 }
151
152 businessObjectService.delete(bo);
153 }
154
155
156
157
158 @Override
159 public AgendaDefinition getAgendaByAgendaId(String agendaId) {
160 if (StringUtils.isBlank(agendaId)){
161 throw new RiceIllegalArgumentException("agenda id is null or blank");
162 }
163 AgendaBo bo = businessObjectService.findBySinglePrimaryKey(AgendaBo.class, agendaId);
164 return to(bo);
165 }
166
167
168
169
170 @Override
171 public AgendaDefinition getAgendaByNameAndContextId(String name, String contextId) {
172 if (StringUtils.isBlank(name)) {
173 throw new RiceIllegalArgumentException("name is blank");
174 }
175 if (StringUtils.isBlank(contextId)) {
176 throw new RiceIllegalArgumentException("contextId is blank");
177 }
178
179 final Map<String, Object> map = new HashMap<String, Object>();
180 map.put("name", name);
181 map.put("contextId", contextId);
182
183 AgendaBo myAgenda = businessObjectService.findByPrimaryKey(AgendaBo.class, Collections.unmodifiableMap(map));
184 return to(myAgenda);
185 }
186
187
188
189
190 @Override
191 public List<AgendaDefinition> getAgendasByContextId(String contextId) {
192 if (StringUtils.isBlank(contextId)){
193 throw new RiceIllegalArgumentException("context ID is null or blank");
194 }
195 final Map<String, Object> map = new HashMap<String, Object>();
196 map.put("contextId", contextId);
197 List<AgendaBo> bos = (List<AgendaBo>) businessObjectService.findMatching(AgendaBo.class, map);
198 return convertAgendaBosToImmutables(bos);
199 }
200
201
202
203
204 @Override
205 public AgendaItemDefinition createAgendaItem(AgendaItemDefinition agendaItem) {
206 if (agendaItem == null){
207 throw new RiceIllegalArgumentException("agendaItem is null");
208 }
209 if (agendaItem.getId() != null){
210 final AgendaDefinition existing = getAgendaByAgendaId(agendaItem.getId());
211 if (existing != null){
212 throw new IllegalStateException("the agendaItem to create already exists: " + agendaItem);
213 }
214 }
215
216 AgendaItemBo bo = AgendaItemBo.from(agendaItem);
217 businessObjectService.save(bo);
218 return AgendaItemBo.to(bo);
219 }
220
221
222
223
224 @Override
225 public void updateAgendaItem(AgendaItemDefinition agendaItem) {
226 if (agendaItem == null){
227 throw new RiceIllegalArgumentException("agendaItem is null");
228 }
229 final String agendaItemIdKey = agendaItem.getId();
230 final AgendaItemDefinition existing = getAgendaItemById(agendaItemIdKey);
231 if (existing == null) {
232 throw new IllegalStateException("the agenda item does not exist: " + agendaItem);
233 }
234 final AgendaItemDefinition toUpdate;
235 if (existing.getId().equals(agendaItem.getId())) {
236 toUpdate = agendaItem;
237 } else {
238 final AgendaItemDefinition.Builder builder = AgendaItemDefinition.Builder.create(agendaItem);
239 builder.setId(existing.getId());
240 toUpdate = builder.build();
241 }
242
243 AgendaItemBo aiBo = AgendaItemBo.from(toUpdate);
244 updateActionAttributes(aiBo);
245 businessObjectService.save(aiBo);
246 }
247
248 private void updateActionAttributes(AgendaItemBo aiBo) {
249 if(aiBo.getRule()!=null){
250 updateActionAttributes(aiBo.getRule().getActions());
251 }
252 if(aiBo.getWhenTrue()!=null){
253 updateActionAttributes(aiBo.getWhenTrue());
254 }
255 if(aiBo.getWhenFalse()!=null){
256 updateActionAttributes(aiBo.getWhenFalse());
257 }
258 if(aiBo.getAlways()!=null){
259 updateActionAttributes(aiBo.getAlways());
260 }
261 }
262
263 private void updateActionAttributes(List<ActionBo> actionBos) {
264 for (ActionBo action : actionBos) {
265 for (ActionAttributeBo aa : action.getAttributeBos()) {
266 Map<String, Object> map = new HashMap<String, Object>();
267 map.put("actionId", action.getId());
268 Collection<ActionAttributeBo> aaBos = businessObjectService.findMatching(ActionAttributeBo.class, map);
269
270 for (ActionAttributeBo aaBo : aaBos) {
271 if (aaBo.getAttributeDefinitionId().equals(aa.getAttributeDefinitionId())) {
272 aa.setId(aaBo.getId());
273 aa.setVersionNumber(aaBo.getVersionNumber());
274 }
275 }
276 }
277 }
278 }
279
280
281
282
283 @Override
284 public void addAgendaItem(AgendaItemDefinition agendaItem, String parentId, Boolean position) {
285 if (agendaItem == null){
286 throw new RiceIllegalArgumentException("agendaItem is null");
287 }
288 AgendaItemDefinition parent = null;
289 if (parentId != null){
290 parent = getAgendaItemById(parentId);
291 if (parent == null){
292 throw new IllegalStateException("parent agendaItem does not exist in repository. parentId = " + parentId);
293 }
294 }
295
296 final AgendaItemDefinition toCreate;
297 if (agendaItem.getId() == null) {
298 SequenceAccessorService sas = getSequenceAccessorService();
299 final AgendaItemDefinition.Builder builder = AgendaItemDefinition.Builder.create(agendaItem);
300 final String newId =sas.getNextAvailableSequenceNumber(
301 "KRMS_AGENDA_ITM_S", AgendaItemBo.class).toString();
302 builder.setId(newId);
303 toCreate = builder.build();
304 } else {
305 toCreate = agendaItem;
306 }
307 createAgendaItem(toCreate);
308
309
310 if (parentId != null) {
311 final AgendaItemDefinition.Builder builder = AgendaItemDefinition.Builder.create(parent);
312 if (position == null){
313 builder.setAlwaysId( toCreate.getId() );
314 } else if (position.booleanValue()){
315 builder.setWhenTrueId( toCreate.getId() );
316 } else if (!position.booleanValue()){
317 builder.setWhenFalseId( toCreate.getId() );
318 }
319 final AgendaItemDefinition parentToUpdate = builder.build();
320 updateAgendaItem( parentToUpdate );
321 }
322 }
323
324
325
326
327 @Override
328 public AgendaItemDefinition getAgendaItemById(String id) {
329 if (StringUtils.isBlank(id)){
330 throw new RiceIllegalArgumentException("agenda item id is null or blank");
331 }
332 AgendaItemBo bo = businessObjectService.findBySinglePrimaryKey(AgendaItemBo.class, id);
333 return AgendaItemBo.to(bo);
334 }
335
336 @Override
337 public List<AgendaItemDefinition> getAgendaItemsByAgendaId(String agendaId) {
338 if (StringUtils.isBlank(agendaId)){
339 throw new RiceIllegalArgumentException("agenda id is null or null");
340 }
341 List<AgendaItemDefinition> results = null;
342
343 Collection<AgendaItemBo> bos = businessObjectService.findMatching(AgendaItemBo.class, Collections.singletonMap("agendaId", agendaId));
344
345 if (CollectionUtils.isEmpty(bos)) {
346 results = Collections.emptyList();
347 } else {
348 results = Collections.unmodifiableList(ModelObjectUtils.transform(bos, toAgendaItemDefinition));
349 }
350
351 return results;
352 }
353
354 @Override
355 public List<AgendaDefinition> getAgendasByType(String typeId) throws RiceIllegalArgumentException {
356 if (StringUtils.isBlank(typeId)){
357 throw new RiceIllegalArgumentException("type ID is null or blank");
358 }
359 final Map<String, Object> map = new HashMap<String, Object>();
360 map.put("typeId", typeId);
361 List<AgendaBo> bos = (List<AgendaBo>) businessObjectService.findMatching(AgendaBo.class, map);
362 return convertAgendaBosToImmutables(bos);
363 }
364
365 @Override
366 public List<AgendaDefinition> getAgendasByTypeAndContext(String typeId,
367 String contextId) throws RiceIllegalArgumentException {
368 if (StringUtils.isBlank(typeId)){
369 throw new RiceIllegalArgumentException("type ID is null or blank");
370 }
371 if (StringUtils.isBlank(contextId)){
372 throw new RiceIllegalArgumentException("context ID is null or blank");
373 }
374 final Map<String, Object> map = new HashMap<String, Object>();
375 map.put("typeId", typeId);
376 map.put("contextId", contextId);
377 Collection<AgendaBo> bos = businessObjectService.findMatching(AgendaBo.class, map);
378 return convertAgendaBosToImmutables(bos);
379 }
380
381 @Override
382 public List<AgendaItemDefinition> getAgendaItemsByType(String typeId) throws RiceIllegalArgumentException {
383 return findAgendaItemsForAgendas(getAgendasByType(typeId));
384 }
385
386 @Override
387 public List<AgendaItemDefinition> getAgendaItemsByContext(String contextId) throws RiceIllegalArgumentException {
388 return findAgendaItemsForAgendas(getAgendasByContextId(contextId));
389 }
390
391 @Override
392 public List<AgendaItemDefinition> getAgendaItemsByTypeAndContext(String typeId,
393 String contextId) throws RiceIllegalArgumentException {
394 return findAgendaItemsForAgendas(getAgendasByTypeAndContext(typeId, contextId));
395 }
396
397 @Override
398 public void deleteAgendaItem(String agendaItemId) throws RiceIllegalArgumentException {
399 if (StringUtils.isBlank(agendaItemId)) {
400 throw new RiceIllegalArgumentException("agendaItemId must not be blank or null");
401 }
402
403 businessObjectService.deleteMatching(AgendaItemBo.class, Collections.singletonMap("id", agendaItemId));
404 }
405
406 private List<AgendaItemDefinition> findAgendaItemsForAgendas(List<AgendaDefinition> agendaDefinitions) {
407 List<AgendaItemDefinition> results = null;
408
409 if (!CollectionUtils.isEmpty(agendaDefinitions)) {
410 List<AgendaItemBo> boResults = new ArrayList<AgendaItemBo>(agendaDefinitions.size());
411
412 List<String> agendaIds = new ArrayList<String>(20);
413 for (AgendaDefinition agendaDefinition : agendaDefinitions) {
414 agendaIds.add(agendaDefinition.getId());
415
416 if (agendaIds.size() == 20) {
417
418
419 Predicate predicate = in("agendaId", agendaIds.toArray());
420 QueryByCriteria criteria = QueryByCriteria.Builder.fromPredicates(predicate);
421 GenericQueryResults<AgendaItemBo> batch = this.getCriteriaLookupService().lookup(AgendaItemBo.class, criteria);
422
423 boResults.addAll(batch.getResults());
424
425
426 agendaIds.clear();
427 }
428 }
429
430 if (agendaIds.size() > 0) {
431 Predicate predicate = in("agendaId", agendaIds.toArray());
432 QueryByCriteria criteria = QueryByCriteria.Builder.fromPredicates(predicate);
433 GenericQueryResults<AgendaItemBo> batch = this.getCriteriaLookupService().lookup(AgendaItemBo.class, criteria);
434
435 boResults.addAll(batch.getResults());
436 }
437
438 results = Collections.unmodifiableList(ModelObjectUtils.transform(boResults, toAgendaItemDefinition));
439 } else {
440 results = Collections.emptyList();
441 }
442
443 return results;
444 }
445
446 public CriteriaLookupService getCriteriaLookupService() {
447 if (criteriaLookupService == null) {
448 criteriaLookupService = KrmsRepositoryServiceLocator.getCriteriaLookupService();
449 }
450 return criteriaLookupService;
451 }
452
453 public void setCriteriaLookupService(CriteriaLookupService criteriaLookupService) {
454 this.criteriaLookupService = criteriaLookupService;
455 }
456
457
458
459
460
461
462 public void setBusinessObjectService(final BusinessObjectService businessObjectService) {
463 this.businessObjectService = businessObjectService;
464 }
465
466 protected BusinessObjectService getBusinessObjectService() {
467 if ( businessObjectService == null ) {
468 businessObjectService = KRADServiceLocator.getBusinessObjectService();
469 }
470 return businessObjectService;
471 }
472
473
474
475
476
477
478 public void setSequenceAccessorService(final SequenceAccessorService sequenceAccessorService) {
479 this.sequenceAccessorService = sequenceAccessorService;
480 }
481
482 protected SequenceAccessorService getSequenceAccessorService() {
483 if ( sequenceAccessorService == null ) {
484 sequenceAccessorService = KRADServiceLocator.getSequenceAccessorService();
485 }
486 return sequenceAccessorService;
487 }
488
489 protected KrmsAttributeDefinitionService getAttributeDefinitionService() {
490 if (attributeDefinitionService == null) {
491 attributeDefinitionService = KrmsRepositoryServiceLocator.getKrmsAttributeDefinitionService();
492 }
493 return attributeDefinitionService;
494 }
495
496 public void setAttributeDefinitionService(KrmsAttributeDefinitionService attributeDefinitionService) {
497 this.attributeDefinitionService = attributeDefinitionService;
498 }
499
500
501
502
503
504
505
506 public List<AgendaDefinition> convertAgendaBosToImmutables(final Collection<AgendaBo> agendaBos) {
507 if (CollectionUtils.isEmpty(agendaBos)) {
508 return Collections.emptyList();
509 }
510 return Collections.unmodifiableList(ModelObjectUtils.transform(agendaBos, toAgendaDefinition));
511 }
512
513
514
515
516
517
518 @Override
519 public AgendaDefinition to(AgendaBo bo) {
520 if (bo == null) { return null; }
521 return org.kuali.rice.krms.api.repository.agenda.AgendaDefinition.Builder.create(bo).build();
522 }
523
524
525
526
527
528
529
530 @Override
531 public AgendaBo from(AgendaDefinition im) {
532 if (im == null) { return null; }
533
534 AgendaBo bo = new AgendaBo();
535 bo.setId(im.getId());
536 bo.setName( im.getName() );
537 bo.setTypeId( im.getTypeId() );
538 bo.setContextId( im.getContextId() );
539 bo.setFirstItemId( im.getFirstItemId() );
540 bo.setVersionNumber( im.getVersionNumber() );
541 bo.setActive(im.isActive());
542 Set<AgendaAttributeBo> attributes = buildAgendaAttributeBo(im);
543
544 bo.setAttributeBos(attributes);
545
546 return bo;
547 }
548
549 private Set<AgendaAttributeBo> buildAgendaAttributeBo(AgendaDefinition im) {
550 Set<AgendaAttributeBo> attributes = new HashSet<AgendaAttributeBo>();
551
552
553 Map<String, KrmsAttributeDefinition> attributeDefinitionMap = new HashMap<String, KrmsAttributeDefinition>();
554
555 List<KrmsAttributeDefinition> attributeDefinitions =
556 getAttributeDefinitionService().findAttributeDefinitionsByType(im.getTypeId());
557
558 for (KrmsAttributeDefinition attributeDefinition : attributeDefinitions) {
559 attributeDefinitionMap.put(attributeDefinition.getName(), attributeDefinition);
560 }
561
562
563 for (Entry<String,String> entry : im.getAttributes().entrySet()){
564 KrmsAttributeDefinition attrDef = attributeDefinitionMap.get(entry.getKey());
565
566 if (attrDef != null) {
567 AgendaAttributeBo attributeBo = new AgendaAttributeBo();
568 attributeBo.setAgendaId( im.getId() );
569 attributeBo.setAttributeDefinitionId(attrDef.getId());
570 attributeBo.setValue(entry.getValue());
571 attributeBo.setAttributeDefinition(KrmsAttributeDefinitionBo.from(attrDef));
572 attributes.add( attributeBo );
573 } else {
574 throw new RiceIllegalStateException("there is no attribute definition with the name '" +
575 entry.getKey() + "' that is valid for the agenda type with id = '" + im.getTypeId() +"'");
576 }
577 }
578 return attributes;
579 }
580
581 }