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