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