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