1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.actionlist.service.impl;
17
18 import org.apache.commons.collections.CollectionUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.kuali.rice.core.api.config.property.ConfigContext;
21 import org.kuali.rice.core.api.criteria.Predicate;
22 import org.kuali.rice.core.api.criteria.QueryByCriteria;
23 import org.kuali.rice.core.api.criteria.QueryResults;
24 import org.kuali.rice.core.api.datetime.DateTimeService;
25 import org.kuali.rice.core.api.delegation.DelegationType;
26 import org.kuali.rice.coreservice.framework.CoreFrameworkServiceLocator;
27 import org.kuali.rice.kew.actionitem.ActionItem;
28 import org.kuali.rice.kew.actionitem.ActionItemBase;
29 import org.kuali.rice.kew.actionitem.OutboxItem;
30 import org.kuali.rice.kew.actionlist.ActionListFilter;
31 import org.kuali.rice.kew.actionlist.dao.ActionListDAO;
32 import org.kuali.rice.kew.actionlist.dao.impl.ActionListPriorityComparator;
33 import org.kuali.rice.kew.actionlist.service.ActionListService;
34 import org.kuali.rice.kew.actionrequest.ActionRequestValue;
35 import org.kuali.rice.kew.actionrequest.KimGroupRecipient;
36 import org.kuali.rice.kew.actionrequest.Recipient;
37 import org.kuali.rice.kew.actionrequest.service.ActionRequestService;
38 import org.kuali.rice.kew.actiontaken.ActionTakenValue;
39 import org.kuali.rice.kew.api.KewApiConstants;
40 import org.kuali.rice.kew.doctype.bo.DocumentType;
41 import org.kuali.rice.kew.doctype.service.DocumentTypeService;
42 import org.kuali.rice.kew.notification.service.NotificationService;
43 import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
44 import org.kuali.rice.kew.routeheader.service.RouteHeaderService;
45 import org.kuali.rice.kew.useroptions.UserOptions;
46 import org.kuali.rice.kew.useroptions.UserOptionsService;
47 import org.kuali.rice.kew.util.WebFriendlyRecipient;
48 import org.kuali.rice.kim.api.group.GroupService;
49 import org.kuali.rice.kim.api.services.KimApiServiceLocator;
50 import org.kuali.rice.krad.data.DataObjectService;
51 import org.kuali.rice.krad.util.KRADConstants;
52
53 import java.sql.Timestamp;
54 import java.util.ArrayList;
55 import java.util.Calendar;
56 import java.util.Collection;
57 import java.util.Collections;
58 import java.util.Date;
59 import java.util.HashMap;
60 import java.util.List;
61 import java.util.Map;
62
63 import static org.kuali.rice.core.api.criteria.PredicateFactory.*;
64
65
66
67
68
69
70 public class ActionListServiceImpl implements ActionListService {
71
72 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(ActionListServiceImpl.class);
73 private static final Integer DEFAULT_OUTBOX_ITEM_LIMIT = Integer.valueOf(10000);
74
75 protected DataObjectService dataObjectService;
76 protected NotificationService notificationService;
77 protected DateTimeService dateTimeService;
78 protected ActionRequestService actionRequestService;
79 protected DocumentTypeService documentTypeService;
80 protected UserOptionsService userOptionsService;
81 protected RouteHeaderService routeHeaderService;
82
83 protected ActionListDAO actionListDAO;
84
85 @Override
86 public Collection<Recipient> findUserSecondaryDelegators(String principalId) {
87
88 QueryByCriteria query = QueryByCriteria.Builder.fromPredicates(
89 equal("principalId", principalId),
90 equal("delegationType", DelegationType.SECONDARY.getCode()),
91 or(isNotNull("delegatorPrincipalId"), isNotNull("delegatorGroupId")));
92
93 QueryResults<ActionItem> results = dataObjectService.findMatching(ActionItem.class, query);
94
95 Map<Object, Recipient> delegators = new HashMap<Object, Recipient>(results.getResults().size());
96
97 for ( ActionItem actionItem : results.getResults() ) {
98 String delegatorPrincipalId = actionItem.getDelegatorPrincipalId();
99 String delegatorGroupId = actionItem.getDelegatorGroupId();
100
101 if (delegatorPrincipalId != null && !delegators.containsKey(delegatorPrincipalId)) {
102 delegators.put(delegatorPrincipalId,new WebFriendlyRecipient(KimApiServiceLocator.getPersonService().getPerson(delegatorPrincipalId)));
103 } else if (delegatorGroupId != null && !delegators.containsKey(delegatorGroupId)) {
104 delegators.put(delegatorGroupId, new KimGroupRecipient(KimApiServiceLocator.getGroupService().getGroup(delegatorGroupId)));
105 }
106 }
107
108 return delegators.values();
109 }
110
111 @Override
112 public Collection<Recipient> findUserPrimaryDelegations(String principalId) {
113 List<String> workgroupIds = KimApiServiceLocator.getGroupService().getGroupIdsByPrincipalId(principalId);
114
115 Predicate whoPredicate = null;
116 if (CollectionUtils.isNotEmpty(workgroupIds)) {
117 whoPredicate = or( equal("delegatorPrincipalId", principalId), in("delegatorGroupId", workgroupIds ) );
118 } else {
119 whoPredicate = equal("delegatorPrincipalId", principalId);
120 }
121 QueryByCriteria query = QueryByCriteria.Builder.fromPredicates(whoPredicate, equal("delegationType", DelegationType.PRIMARY.getCode() ) );
122
123 QueryResults<ActionItem> results = dataObjectService.findMatching(ActionItem.class, query);
124
125 Map<String, Recipient> delegators = new HashMap<String, Recipient>(results.getResults().size());
126
127 for ( ActionItem actionItem : results.getResults() ) {
128 String recipientPrincipalId = actionItem.getPrincipalId();
129 if (recipientPrincipalId != null && !delegators.containsKey(recipientPrincipalId)) {
130 delegators.put(recipientPrincipalId, new WebFriendlyRecipient(
131 KimApiServiceLocator.getPersonService().getPerson(recipientPrincipalId)));
132 }
133 }
134
135 return delegators.values();
136 }
137
138 @Override
139 public Collection<ActionItem> getActionList(String principalId, ActionListFilter filter) {
140 List<String> filteredByItems = new ArrayList<String>();
141
142 List<Predicate> crit = handleActionItemCriteria(principalId, filter, filteredByItems);
143
144 if ( LOG.isDebugEnabled() ) {
145 LOG.debug("running query to get action list for criteria " + crit);
146 }
147 QueryByCriteria query = QueryByCriteria.Builder.fromPredicates(crit);
148 QueryResults<ActionItem> results = dataObjectService.findMatching(ActionItem.class, query);
149 if ( LOG.isDebugEnabled() ) {
150 LOG.debug("found " + results.getResults().size() + " action items for user " + principalId);
151 }
152
153 if (filter != null) {
154 boolean filterOn = !filteredByItems.isEmpty();
155 filter.setFilterOn(filterOn);
156 filter.setFilterLegend(StringUtils.join(filteredByItems, ", "));
157 }
158
159 return createActionListForUser(results.getResults());
160 }
161
162 protected List<Predicate> handleActionItemCriteria( String principalId, ActionListFilter filter, List<String> filteredByItems ) {
163 LOG.debug("setting up Action List criteria");
164 ArrayList<Predicate> crit = new ArrayList<Predicate>();
165
166 if ( filter != null ) {
167 handleActionRequestedCriteria(filter, crit, filteredByItems);
168 handleDocumentCreateDateCriteria(filter, crit, filteredByItems);
169 handleAssignedDateCriteria(filter, crit, filteredByItems);
170 handleRouteStatusCriteria(filter, crit, filteredByItems);
171 handleDocumentTitleCriteria(filter, crit, filteredByItems);
172 handleDocumentTypeCriteria(filter, crit, filteredByItems);
173 handleWorkgroupCriteria(filter, crit, filteredByItems);
174 handleRecipientCriteria(principalId, filter, crit, filteredByItems);
175 } else {
176 crit.add( equal("principalId", principalId) );
177 }
178 LOG.debug( "Completed setting up Action List criteria");
179 return crit;
180 }
181
182 protected void handleActionRequestedCriteria( ActionListFilter filter, Collection<Predicate> crit, List<String> filteredByItems ) {
183 if ( StringUtils.isNotBlank(filter.getActionRequestCd())
184 && !filter.getActionRequestCd().equals(KewApiConstants.ALL_CODE)) {
185 if (filter.isExcludeActionRequestCd()) {
186 crit.add( notEqual("actionRequestCd", filter.getActionRequestCd()));
187 } else {
188 crit.add( equal("actionRequestCd", filter.getActionRequestCd()));
189 }
190 filteredByItems.add( "Action Requested" );
191 }
192 }
193
194 protected void handleDateCriteria( String propertyPath, String filterLabel, Date fromDate, Date toDate, boolean excludeDates, Collection<Predicate> crit, List<String> filteredByItems ) {
195 if (fromDate != null || toDate != null) {
196 Timestamp fromDateTimestamp = beginningOfDay(fromDate);
197 Timestamp toDateTimestamp = endOfDay(toDate);
198 if (excludeDates) {
199 if (fromDate != null && toDate != null) {
200 crit.add( notBetween(propertyPath, fromDateTimestamp, toDateTimestamp ) );
201 } else if (fromDate != null && toDate == null) {
202 crit.add( lessThanOrEqual(propertyPath, fromDateTimestamp ) );
203 } else if (fromDate == null && toDate != null) {
204 crit.add( greaterThanOrEqual(propertyPath, toDateTimestamp ) );
205 }
206 } else {
207 if (fromDate != null && toDate != null) {
208 crit.add( between(propertyPath, fromDateTimestamp, toDateTimestamp ) );
209 } else if (fromDate != null && toDate == null) {
210 crit.add( greaterThanOrEqual(propertyPath, fromDateTimestamp ) );
211 } else if (fromDate == null && toDate != null) {
212 crit.add( lessThanOrEqual(propertyPath, toDateTimestamp ) );
213 }
214 }
215 filteredByItems.add("Date Created");
216 }
217 }
218
219 protected void handleDocumentCreateDateCriteria( ActionListFilter filter, Collection<Predicate> crit, List<String> filteredByItems ) {
220 handleDateCriteria("routeHeader.createDate", "Date Created", filter.getCreateDateFrom(), filter.getCreateDateTo(), filter.isExcludeCreateDate(), crit, filteredByItems);
221 }
222
223 protected void handleAssignedDateCriteria( ActionListFilter filter, Collection<Predicate> crit, List<String> filteredByItems ) {
224 handleDateCriteria("dateAssigned", "Date Last Assigned", filter.getLastAssignedDateFrom(), filter.getLastAssignedDateTo(), filter.isExcludeLastAssignedDate(), crit, filteredByItems);
225 }
226
227 protected void handleRouteStatusCriteria( ActionListFilter filter, Collection<Predicate> crit, List<String> filteredByItems ) {
228 if ( StringUtils.isNotBlank(filter.getDocRouteStatus())
229 && !filter.getDocRouteStatus().equals(KewApiConstants.ALL_CODE)) {
230 if (filter.isExcludeRouteStatus()) {
231 crit.add( notEqual("routeHeader.docRouteStatus", filter.getDocRouteStatus() ) );
232 } else {
233 crit.add( equal("routeHeader.docRouteStatus", filter.getDocRouteStatus() ) );
234 }
235 filteredByItems.add( "Document Route Status" );
236 }
237 }
238
239 protected void handleDocumentTitleCriteria( ActionListFilter filter, Collection<Predicate> crit, List<String> filteredByItems ) {
240 if ( StringUtils.isNotBlank(filter.getDocumentTitle()) ) {
241 String docTitle = filter.getDocumentTitle().trim();
242 if (docTitle.endsWith("*")) {
243 docTitle = docTitle.substring(0, docTitle.length() - 1);
244 }
245 if (filter.isExcludeDocumentTitle()) {
246 crit.add( notLike("docTitle", "%" + docTitle + "%" ) );
247 } else {
248 crit.add( like("docTitle", "%" + docTitle + "%" ) );
249 }
250 filteredByItems.add( "Document Title" );
251 }
252 }
253
254 protected void handleDocumentTypeCriteria( ActionListFilter filter, Collection<Predicate> crit, List<String> filteredByItems ) {
255 if ( StringUtils.isNotBlank(filter.getDocumentType()) ) {
256 String documentTypeName = filter.getDocumentType();
257 if (filter.isExcludeDocumentType()) {
258 crit.add( notLike( "docName", "%" + documentTypeName + "%" ) );
259 } else {
260 DocumentType documentType = documentTypeService.findByName(documentTypeName);
261
262 if (documentType == null) {
263 crit.add( like( "docName", "%" + documentTypeName + "%" ) );
264 } else {
265
266 Collection<DocumentType> docs = getAllChildDocumentTypes(documentType);
267 Collection<String> docNames = new ArrayList<String>(docs.size()+1);
268 docNames.add(documentType.getName());
269 for ( DocumentType doc : docs ) {
270 docNames.add(doc.getName());
271 }
272 crit.add( in("docName", docNames) );
273 }
274 }
275 filteredByItems.add( "Document Type" );
276 }
277 }
278
279 protected Collection<DocumentType> getAllChildDocumentTypes( DocumentType docType ) {
280 Collection<DocumentType> allChildren = new ArrayList<DocumentType>();
281
282 List<DocumentType> immediateChildren = documentTypeService.getChildDocumentTypes(docType.getId());
283 if ( immediateChildren != null ) {
284 allChildren.addAll(immediateChildren);
285
286 for ( DocumentType childDoc : immediateChildren ) {
287 allChildren.addAll( getAllChildDocumentTypes(childDoc));
288 }
289 }
290
291 return allChildren;
292 }
293
294 protected void handleWorkgroupCriteria( ActionListFilter filter, Collection<Predicate> crit, List<String> filteredByItems ) {
295 filter.setGroupId(null);
296 if ( StringUtils.isNotBlank(filter.getGroupIdString())
297 && !filter.getGroupIdString().trim().equals(KewApiConstants.NO_FILTERING)) {
298
299 filter.setGroupId(filter.getGroupIdString().trim());
300
301 if (filter.isExcludeGroupId()) {
302 crit.add( or(
303 notEqual("groupId", filter.getGroupId()),
304 isNull("groupId") ) );
305 } else {
306 crit.add( equal("groupId", filter.getGroupId()) );
307 }
308 filteredByItems.add( "Action Request Workgroup" );
309 }
310 }
311
312 protected void applyPrimaryDelegationCriteria( String actionListUserPrincipalId, ActionListFilter filter, Collection<Predicate> crit, List<String> filteredByItems ) {
313
314 List<String> delegatorGroupIds = KimApiServiceLocator.getGroupService().getGroupIdsByPrincipalId(actionListUserPrincipalId);
315
316 if (delegatorGroupIds != null && !delegatorGroupIds.isEmpty()) {
317 crit.add( or( equal("delegatorPrincipalId", actionListUserPrincipalId), in("delegatorGroupId", delegatorGroupIds) ) );
318 } else {
319 crit.add( equal("delegatorPrincipalId", actionListUserPrincipalId) );
320 }
321 crit.add( equal("delegationType", DelegationType.PRIMARY.getCode() ) );
322 filter.setDelegationType(DelegationType.PRIMARY.getCode());
323 filter.setExcludeDelegationType(false);
324 filteredByItems.add("Primary Delegator Id");
325 }
326
327
328
329
330
331
332
333
334 protected boolean handlePrimaryDelegation( String actionListUserPrincipalId, ActionListFilter filter, Collection<Predicate> crit, List<String> filteredByItems ) {
335 if ( StringUtils.isBlank(filter.getPrimaryDelegateId())
336 || filter.getPrimaryDelegateId().trim().equals(KewApiConstants.ALL_CODE) ) {
337
338 applyPrimaryDelegationCriteria(actionListUserPrincipalId, filter, crit, filteredByItems);
339
340 return true;
341 } else if (!filter.getPrimaryDelegateId().trim().equals(KewApiConstants.PRIMARY_DELEGATION_DEFAULT)) {
342
343 crit.add( equal("principalId", filter.getPrimaryDelegateId() ) );
344 applyPrimaryDelegationCriteria(actionListUserPrincipalId, filter, crit, filteredByItems);
345
346 return true;
347 }
348
349 return false;
350 }
351
352
353
354
355
356
357
358
359 protected boolean handleSecondaryDelegation( String actionListUserPrincipalId, ActionListFilter filter, Collection<Predicate> crit, List<String> filteredByItems ) {
360 crit.add( equal("principalId", actionListUserPrincipalId) );
361 if (StringUtils.isBlank(filter.getDelegatorId())) {
362 filter.setDelegationType(DelegationType.SECONDARY.getCode());
363
364
365 if (!filter.isExcludeDelegationType()) {
366 crit.add( equal("delegationType", DelegationType.SECONDARY.getCode() ) );
367 filteredByItems.add("Secondary Delegator Id");
368
369 return true;
370 }
371 } else if (filter.getDelegatorId().trim().equals(KewApiConstants.ALL_CODE)) {
372
373 crit.add( equal("delegationType", DelegationType.SECONDARY.getCode() ) );
374 filter.setDelegationType(DelegationType.SECONDARY.getCode());
375 filter.setExcludeDelegationType(false);
376 filteredByItems.add("Secondary Delegator Id");
377
378 return true;
379 } else if (!filter.getDelegatorId().trim().equals(KewApiConstants.DELEGATION_DEFAULT)) {
380
381 filter.setDelegationType(DelegationType.SECONDARY.getCode());
382 filter.setExcludeDelegationType(false);
383
384 if (filter.isExcludeDelegatorId()) {
385 crit.add( or( notEqual("delegatorPrincipalId", filter.getDelegatorId()), isNull("delegatorPrincipalId") ) );
386 crit.add( or( notEqual("delegatorGroupId", filter.getDelegatorId()), isNull("delegatorGroupId") ) );
387 } else {
388 crit.add( or( equal("delegatorPrincipalId", filter.getDelegatorId()), equal("delegatorGroupId", filter.getDelegatorId()) ) );
389 }
390 filteredByItems.add("Secondary Delegator Id");
391
392 return true;
393 }
394
395 return false;
396 }
397
398
399
400
401
402
403
404
405
406 protected void handleRecipientCriteria( String actionListUserPrincipalId, ActionListFilter filter, Collection<Predicate> crit, List<String> filteredByItems ) {
407 if (StringUtils.isBlank(filter.getDelegationType())
408 && StringUtils.isBlank(filter.getPrimaryDelegateId())
409 && StringUtils.isBlank(filter.getDelegatorId())) {
410 crit.add( equal("principalId", actionListUserPrincipalId) );
411 return;
412 }
413 if ( StringUtils.equals(filter.getDelegationType(), DelegationType.PRIMARY.getCode() )
414 || StringUtils.isNotBlank(filter.getPrimaryDelegateId())) {
415
416 if ( handlePrimaryDelegation(actionListUserPrincipalId, filter, crit, filteredByItems)) {
417 return;
418 }
419 }
420
421 if (StringUtils.equals(filter.getDelegationType(), DelegationType.SECONDARY.getCode())
422 || StringUtils.isNotBlank(filter.getDelegatorId()) ) {
423
424 if ( handleSecondaryDelegation(actionListUserPrincipalId, filter, crit, filteredByItems) ) {
425 return;
426 }
427 }
428
429
430 filter.setDelegationType(DelegationType.SECONDARY.getCode());
431 filter.setExcludeDelegationType(true);
432 crit.add( equal("principalId", actionListUserPrincipalId) );
433 crit.add( or( notEqual("delegationType", DelegationType.SECONDARY.getCode()), isNull("delegationType") ) );
434 }
435
436
437
438
439
440
441
442
443 private Collection<ActionItem> createActionListForUser(Collection<ActionItem> actionItems) {
444 Map<String, ActionItem> actionItemMap = new HashMap<String, ActionItem>();
445 ActionListPriorityComparator comparator = new ActionListPriorityComparator();
446 for (ActionItem potentialActionItem: actionItems) {
447 ActionItem existingActionItem = actionItemMap.get(potentialActionItem.getDocumentId());
448 if (existingActionItem == null || comparator.compare(potentialActionItem, existingActionItem) > 0) {
449 actionItemMap.put(potentialActionItem.getDocumentId(), potentialActionItem);
450 }
451 }
452 return actionItemMap.values();
453 }
454
455
456
457
458
459 @Override
460 public Collection<ActionItem> getActionListForSingleDocument(String documentId) {
461 if ( LOG.isDebugEnabled() ) {
462 LOG.debug("getting action list for document id " + documentId);
463 }
464 Collection<ActionItem> collection = findByDocumentId(documentId);
465 if ( LOG.isDebugEnabled() ) {
466 LOG.debug("found " + collection.size() + " action items for document id " + documentId);
467 }
468 return createActionListForRouteHeader(collection);
469 }
470
471
472
473
474
475
476
477
478 protected Collection<ActionItem> createActionListForRouteHeader(Collection<ActionItem> actionItems) {
479 Map<String, ActionItem> actionItemMap = new HashMap<String, ActionItem>();
480 ActionListPriorityComparator comparator = new ActionListPriorityComparator();
481 for (ActionItem potentialActionItem: actionItems) {
482 ActionItem existingActionItem = actionItemMap.get(potentialActionItem.getPrincipalId());
483 if (existingActionItem == null || comparator.compare(potentialActionItem, existingActionItem) > 0) {
484 actionItemMap.put(potentialActionItem.getPrincipalId(), potentialActionItem);
485 }
486 }
487 return actionItemMap.values();
488 }
489
490 public void setActionListDAO(ActionListDAO actionListDAO) {
491 this.actionListDAO = actionListDAO;
492 }
493
494 public ActionListDAO getActionListDAO() {
495 return actionListDAO;
496 }
497
498 @Override
499 public void deleteActionItemNoOutbox(ActionItem actionItem) {
500 deleteActionItem(actionItem, false, false);
501 }
502
503 @Override
504 public void deleteActionItem(ActionItem actionItem) {
505 deleteActionItem(actionItem, false);
506 }
507
508 @Override
509 public void deleteActionItem(ActionItem actionItem, boolean forceIntoOutbox) {
510 deleteActionItem(actionItem, forceIntoOutbox, true);
511 }
512
513 protected void deleteActionItem(ActionItem actionItem, boolean forceIntoOutbox, boolean putInOutbox) {
514 dataObjectService.delete(actionItem);
515
516 notificationService.removeNotification(Collections.singletonList(ActionItem.to(actionItem)));
517 if (putInOutbox) {
518 saveOutboxItem(actionItem, forceIntoOutbox);
519 }
520 }
521
522 @Override
523 public void deleteByDocumentId(String documentId) {
524 dataObjectService.deleteMatching(ActionItem.class, QueryByCriteria.Builder.forAttribute("documentId", documentId).build());
525 }
526
527 @Override
528 public Collection<ActionItem> findByDocumentId(String documentId) {
529 QueryResults<ActionItem> results = dataObjectService.findMatching(ActionItem.class,
530 QueryByCriteria.Builder.forAttribute("documentId", documentId).build());
531
532 return results.getResults();
533 }
534
535 @Override
536 public Collection<ActionItem> findByActionRequestId(String actionRequestId) {
537 QueryResults<ActionItem> results = dataObjectService.findMatching(ActionItem.class,
538 QueryByCriteria.Builder.forAttribute("actionRequestId", actionRequestId).build());
539
540 return results.getResults();
541 }
542
543 @Override
544 public Collection<ActionItem> findByWorkflowUserDocumentId(String workflowUserId, String documentId) {
545 Map<String,String> criteria = new HashMap<String, String>(2);
546 criteria.put( "principalId", workflowUserId );
547 criteria.put( "documentId", documentId );
548 QueryResults<ActionItem> results = dataObjectService.findMatching(ActionItem.class,
549 QueryByCriteria.Builder.andAttributes(criteria).build());
550
551 return results.getResults();
552 }
553
554 @Override
555 public Collection<ActionItem> findByDocumentTypeName(String documentTypeName) {
556 QueryResults<ActionItem> results = dataObjectService.findMatching(ActionItem.class,
557 QueryByCriteria.Builder.forAttribute("docName", documentTypeName).build());
558
559 return results.getResults();
560 }
561
562 @Override
563 public ActionItem createActionItemForActionRequest(ActionRequestValue actionRequest) {
564 ActionItem actionItem = new ActionItem();
565
566 DocumentRouteHeaderValue routeHeader = actionRequest.getRouteHeader();
567 DocumentType docType = routeHeader.getDocumentType();
568
569 actionItem.setActionRequestCd(actionRequest.getActionRequested());
570 actionItem.setActionRequestId(actionRequest.getActionRequestId());
571 actionItem.setDocName(docType.getName());
572 actionItem.setRoleName(actionRequest.getQualifiedRoleName());
573 actionItem.setPrincipalId(actionRequest.getPrincipalId());
574 actionItem.setDocumentId(actionRequest.getDocumentId());
575 actionItem.setDateAssigned(new Timestamp(new Date().getTime()));
576 actionItem.setDocHandlerURL(docType.getResolvedDocumentHandlerUrl());
577 actionItem.setDocLabel(docType.getLabel());
578 actionItem.setDocTitle(routeHeader.getDocTitle());
579 actionItem.setGroupId(actionRequest.getGroupId());
580 actionItem.setResponsibilityId(actionRequest.getResponsibilityId());
581 actionItem.setDelegationType(actionRequest.getDelegationType());
582 actionItem.setRequestLabel(actionRequest.getRequestLabel());
583
584 ActionRequestValue delegatorActionRequest = actionRequestService.findDelegatorRequest(actionRequest);
585 if (delegatorActionRequest != null) {
586 actionItem.setDelegatorPrincipalId(delegatorActionRequest.getPrincipalId());
587 actionItem.setDelegatorGroupId(delegatorActionRequest.getGroupId());
588 }
589
590 return actionItem;
591 }
592
593
594 @Override
595 public void updateActionItemsForTitleChange(String documentId, String newTitle) {
596 Collection<ActionItem> items = findByDocumentId(documentId);
597 for ( ActionItem item : items ) {
598 item.setDocTitle(newTitle);
599 saveActionItem(item);
600 }
601 }
602
603 @Override
604 public ActionItem saveActionItem(ActionItem actionItem) {
605 return saveActionItemBase(actionItem);
606 }
607
608 @Override
609 public OutboxItem saveOutboxItem(OutboxItem outboxItem) {
610 return saveActionItemBase(outboxItem);
611 }
612
613 protected <T extends ActionItemBase> T saveActionItemBase(T actionItemBase) {
614 if (actionItemBase.getDateAssigned() == null) {
615 actionItemBase.setDateAssigned(dateTimeService.getCurrentTimestamp());
616 }
617 return dataObjectService.save(actionItemBase);
618 }
619
620 public GroupService getGroupService(){
621 return KimApiServiceLocator.getGroupService();
622 }
623
624 @Override
625 public ActionItem findByActionItemId(String actionItemId) {
626 return dataObjectService.find(ActionItem.class, actionItemId);
627 }
628
629 @Override
630 public int getCount(String principalId) {
631 return actionListDAO.getCount(principalId);
632 }
633
634
635
636
637 @Override
638 public List<Object> getMaxActionItemDateAssignedAndCountForUser(String principalId) {
639
640
641 List<Object> verifiedList = new ArrayList<Object>();
642 List<Object> maxDateAndUserCount = getActionListDAO().getMaxActionItemDateAssignedAndCountForUser(principalId);
643
644 verifiedList.add(0, verifyMaxActionItemDateAssigned(maxDateAndUserCount));
645 verifiedList.add(1, verifyCountForUser(maxDateAndUserCount));
646
647 return verifiedList;
648 }
649
650
651
652
653
654
655
656 private Object verifyMaxActionItemDateAssigned(List<Object> maxDateAndUserCount) {
657 if (maxDateAndUserCount != null && maxDateAndUserCount.size() > 0 &&
658 maxDateAndUserCount.get(0) != null && (maxDateAndUserCount.get(0) instanceof Timestamp)) {
659
660 return maxDateAndUserCount.get(0);
661 } else {
662 return new Timestamp(new Date().getTime());
663 }
664 }
665
666
667
668
669
670
671 private Object verifyCountForUser(List<Object> maxDateAndUserCount) {
672 if (maxDateAndUserCount != null && maxDateAndUserCount.size() > 1 && maxDateAndUserCount.get(1) != null) {
673 return maxDateAndUserCount.get(1);
674 } else {
675 return Long.valueOf(0);
676 }
677 }
678
679
680
681
682 @Override
683 public Collection<OutboxItem> getOutbox(String principalId, ActionListFilter filter) {
684 List<String> filteredByItems = new ArrayList<String>();
685
686 List<Predicate> crit = handleActionItemCriteria(principalId, filter, filteredByItems);
687
688 if ( LOG.isDebugEnabled() ) {
689 LOG.debug("running query to get outbox list for criteria " + crit);
690 }
691 QueryByCriteria.Builder query = QueryByCriteria.Builder.create(QueryByCriteria.Builder.fromPredicates(crit));
692 query.setMaxResults(getOutboxItemLimit());
693 QueryResults<OutboxItem> results = dataObjectService.findMatching(OutboxItem.class, query.build());
694 if ( LOG.isDebugEnabled() ) {
695 LOG.debug("found " + results.getResults().size() + " outbox items for user " + principalId);
696 }
697
698 if ( filteredByItems.isEmpty() ) {
699 filter.setFilterOn(false);
700 } else {
701 filter.setFilterOn(true);
702 }
703 filter.setFilterLegend(StringUtils.join(filteredByItems, ", "));
704
705 return results.getResults();
706 }
707
708
709
710
711
712 private Integer getOutboxItemLimit() {
713 String fetchSizeParam =
714 CoreFrameworkServiceLocator.getParameterService().getParameterValueAsString(KewApiConstants.KEW_NAMESPACE,
715 KRADConstants.DetailTypes.ACTION_LIST_DETAIL_TYPE, KewApiConstants.OUTBOX_ITEM_LIMIT);
716
717 if(StringUtils.isNotBlank(fetchSizeParam)) {
718 return Integer.parseInt(fetchSizeParam);
719 } else {
720 return DEFAULT_OUTBOX_ITEM_LIMIT;
721 }
722 }
723
724
725
726
727 @Override
728 public Collection<OutboxItem> getOutboxItemsByDocumentType(String documentTypeName) {
729 QueryResults<OutboxItem> results = dataObjectService.findMatching(OutboxItem.class,
730 QueryByCriteria.Builder.forAttribute("docName", documentTypeName).build());
731
732 return results.getResults();
733 }
734
735
736
737
738 @Override
739 public void removeOutboxItems(String principalId, List<String> outboxItems) {
740 QueryByCriteria query = QueryByCriteria.Builder.fromPredicates(
741 in("id", outboxItems));
742
743 dataObjectService.deleteMatching(OutboxItem.class, query);
744 }
745
746 @Override
747 public OutboxItem saveOutboxItem(ActionItem actionItem) {
748 return saveOutboxItem(actionItem, false);
749 }
750
751
752
753
754
755
756
757 @Override
758 public OutboxItem saveOutboxItem(ActionItem actionItem, boolean forceIntoOutbox) {
759 Boolean isUsingOutBox = true;
760 List<UserOptions> options = userOptionsService.findByUserQualified(actionItem.getPrincipalId(), KewApiConstants.USE_OUT_BOX);
761 if (options == null || options.isEmpty()){
762 isUsingOutBox = true;
763 } else {
764 for ( UserOptions u : options ) {
765 if ( !StringUtils.equals(u.getOptionVal(), "yes") ) {
766 isUsingOutBox = false;
767 break;
768 }
769 }
770 }
771
772 if (isUsingOutBox
773 && ConfigContext.getCurrentContextConfig().getOutBoxOn()
774 && getOutboxItemByDocumentIdUserId(actionItem.getDocumentId(), actionItem.getPrincipalId()) == null
775 && !routeHeaderService.getRouteHeader(actionItem.getDocumentId()).getDocRouteStatus().equals(
776 KewApiConstants.ROUTE_HEADER_SAVED_CD)) {
777
778
779 ActionRequestValue actionRequest = actionRequestService.findByActionRequestId(
780 actionItem.getActionRequestId());
781 ActionTakenValue actionTaken = actionRequest.getActionTaken();
782
783 if (forceIntoOutbox || (actionTaken != null && actionTaken.getPrincipalId().equals(actionItem.getPrincipalId()))) {
784 return dataObjectService.save(new OutboxItem(actionItem));
785 }
786
787 }
788 return null;
789 }
790
791 protected OutboxItem getOutboxItemByDocumentIdUserId(String documentId, String principalId) {
792 Map<String,String> criteria = new HashMap<String, String>(2);
793 criteria.put( "principalId", principalId );
794 criteria.put( "documentId", documentId );
795 QueryResults<OutboxItem> results = dataObjectService.findMatching(OutboxItem.class,
796 QueryByCriteria.Builder.andAttributes(criteria).build());
797 if ( results.getResults().isEmpty() ) {
798 return null;
799 }
800 return results.getResults().get(0);
801 }
802
803 @Override
804 public Collection<ActionItem> findByPrincipalId(String principalId) {
805 QueryResults<ActionItem> results = dataObjectService.findMatching(ActionItem.class,
806 QueryByCriteria.Builder.forAttribute("principalId", principalId)
807 .setOrderByAscending("documentId").build());
808
809 return results.getResults();
810 }
811
812
813
814
815 @Override
816 public DocumentRouteHeaderValue getMinimalRouteHeader(String documentId) {
817 return actionListDAO.getMinimalRouteHeader(documentId);
818 }
819
820 protected Timestamp beginningOfDay(Date date) {
821 if ( date == null ) {
822 return null;
823 }
824 Calendar cal = Calendar.getInstance();
825 cal.setTime(date);
826 cal.set(Calendar.HOUR_OF_DAY, 0);
827 cal.set(Calendar.MINUTE, 0);
828 cal.set(Calendar.SECOND, 0);
829 return new Timestamp( cal.getTimeInMillis() );
830 }
831
832 protected Timestamp endOfDay(Date date) {
833 if ( date == null ) {
834 return null;
835 }
836 Calendar cal = Calendar.getInstance();
837 cal.setTime(date);
838 cal.set(Calendar.HOUR_OF_DAY, 23);
839 cal.set(Calendar.MINUTE, 59);
840 cal.set(Calendar.SECOND, 59);
841 return new Timestamp( cal.getTimeInMillis() );
842 }
843
844 public void setDataObjectService(DataObjectService dataObjectService) {
845 this.dataObjectService = dataObjectService;
846 }
847
848 public void setNotificationService(NotificationService notificationService) {
849 this.notificationService = notificationService;
850 }
851
852 public void setDateTimeService(DateTimeService dateTimeService) {
853 this.dateTimeService = dateTimeService;
854 }
855
856 public void setActionRequestService(ActionRequestService actionRequestService) {
857 this.actionRequestService = actionRequestService;
858 }
859
860 public void setDocumentTypeService(DocumentTypeService documentTypeService) {
861 this.documentTypeService = documentTypeService;
862 }
863
864 public void setUserOptionsService(UserOptionsService userOptionsService) {
865 this.userOptionsService = userOptionsService;
866 }
867
868 public void setRouteHeaderService(RouteHeaderService routeHeaderService) {
869 this.routeHeaderService = routeHeaderService;
870 }
871 }