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