001/** 002 * Copyright 2005-2016 The Kuali Foundation 003 * 004 * Licensed under the Educational Community License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.opensource.org/licenses/ecl2.php 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package org.kuali.rice.kew.actionitem; 017 018import org.apache.commons.lang.StringUtils; 019import org.apache.commons.lang.builder.ToStringBuilder; 020import org.joda.time.DateTime; 021import org.kuali.rice.core.api.delegation.DelegationType; 022import org.kuali.rice.core.api.util.RiceConstants; 023import org.kuali.rice.kew.api.KewApiConstants; 024import org.kuali.rice.kew.api.KewApiServiceLocator; 025import org.kuali.rice.kew.api.action.ActionItemContract; 026import org.kuali.rice.kew.api.action.RecipientType; 027import org.kuali.rice.kew.api.actionlist.DisplayParameters; 028import org.kuali.rice.kew.api.doctype.DocumentTypePolicy; 029import org.kuali.rice.kew.api.preferences.Preferences; 030import org.kuali.rice.kew.api.util.CodeTranslator; 031import org.kuali.rice.kew.doctype.bo.DocumentType; 032import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue; 033import org.kuali.rice.kew.service.KEWServiceLocator; 034import org.kuali.rice.kim.api.group.Group; 035import org.kuali.rice.kim.api.identity.principal.EntityNamePrincipalName; 036import org.kuali.rice.kim.api.identity.principal.Principal; 037import org.kuali.rice.kim.api.services.KimApiServiceLocator; 038import org.kuali.rice.krad.data.jpa.PortableSequenceGenerator; 039import org.kuali.rice.krad.exception.ValidationException; 040 041import javax.persistence.CascadeType; 042import javax.persistence.Column; 043import javax.persistence.FetchType; 044import javax.persistence.GeneratedValue; 045import javax.persistence.Id; 046import javax.persistence.JoinColumn; 047import javax.persistence.ManyToOne; 048import javax.persistence.MappedSuperclass; 049import javax.persistence.Transient; 050import java.io.Serializable; 051import java.sql.Timestamp; 052import java.util.HashMap; 053import java.util.Map; 054 055/** 056 * This is the model for action items. These are displayed as the action list as well. Mapped to ActionItemService. 057 * NOTE: This object contains denormalized fields that have been copied from related ActionRequestValue and DocumentRouteHeaderValue 058 * objects for performance reasons. These should be preserved and their related objects should not be added to the OJB 059 * mapping as we do not want them loaded for each ActionItem object. 060 * 061 * @author Kuali Rice Team (rice.collab@kuali.org) 062 * 063 */ 064@MappedSuperclass 065public class ActionItemBase implements ActionItemContract, Serializable { 066 067 private static final long serialVersionUID = -1079562205125660151L; 068 069 @Id 070 @GeneratedValue(generator = "KREW_ACTN_ITM_S") 071 @PortableSequenceGenerator(name = "KREW_ACTN_ITM_S") 072 @Column(name = "ACTN_ITM_ID") 073 private String id; 074 075 @Column(name = "PRNCPL_ID") 076 private String principalId; 077 078 @Column(name = "ASND_DT") 079 private Timestamp dateAssigned; 080 081 @Column(name = "RQST_CD") 082 private String actionRequestCd; 083 084 @Column(name = "ACTN_RQST_ID") 085 private String actionRequestId; 086 087 @Column(name = "DOC_HDR_ID") 088 private String documentId; 089 090 @Column(name = "GRP_ID") 091 private String groupId; 092 093 @Column(name = "DOC_HDR_TTL") 094 private String docTitle; 095 096 @Column(name = "DOC_TYP_LBL") 097 private String docLabel; 098 099 @Column(name = "DOC_HDLR_URL") 100 private String docHandlerURL; 101 102 @Column(name = "DOC_TYP_NM") 103 private String docName; 104 105 @Column(name = "RSP_ID") 106 private String responsibilityId = "1"; 107 108 @Column(name = "ROLE_NM") 109 private String roleName; 110 111 @Column(name = "DLGN_PRNCPL_ID") 112 private String delegatorPrincipalId; 113 114 @Column(name = "DLGN_GRP_ID") 115 private String delegatorGroupId; 116 117 @Column(name = "DLGN_TYP") 118 private String delegationType; 119 120 @Column(name = "RQST_LBL") 121 private String requestLabel; 122 123 @ManyToOne(fetch = FetchType.LAZY, cascade = CascadeType.DETACH) 124 @JoinColumn(name = "DOC_HDR_ID", insertable = false, updatable = false) 125 private DocumentRouteHeaderValue routeHeader; 126 127 // used by Document Operations screen 128 @Transient 129 private String dateAssignedStringValue; 130 131 @Transient 132 private Timestamp lastApprovedDate; 133 134 @Transient 135 private Map<String, String> customActions = new HashMap<String, String>(); 136 137 @Transient 138 private String rowStyleClass; 139 140 @Transient 141 private Integer actionListIndex; 142 143 @Transient 144 private String delegatorName = ""; 145 146 @Transient 147 private String groupName = ""; 148 149 @Transient 150 private DisplayParameters displayParameters; 151 152 @Transient 153 private boolean isInitialized = false; 154 155 @Transient 156 private DocumentRouteHeaderValue minimalRouteHeader; 157 158 @Transient 159 private boolean lastApprovedDateInitialized = false; 160 161 @Transient 162 private boolean delegatorNameInitialized = false; 163 164 @Transient 165 private boolean groupNameInitialized = false; 166 167 @Deprecated 168 @Override 169 public String getActionToTake() { 170 // deprecated, always return null (see the contract javadoc for more details) 171 return null; 172 } 173 174 @Deprecated 175 @Override 176 public String getDateAssignedString() { 177 // deprecated, always return null (see the contract javadoc for more details) 178 return null; 179 } 180 181 public String getDateAssignedStringValue() { 182 if (StringUtils.isBlank(dateAssignedStringValue)) { 183 return RiceConstants.getDefaultDateFormat().format(getDateAssigned()); 184 } 185 return dateAssignedStringValue; 186 } 187 188 public void setDateAssignedStringValue(String dateAssignedStringValue) { 189 this.dateAssignedStringValue = dateAssignedStringValue; 190 } 191 192 @Override 193 public String getId() { 194 return id; 195 } 196 197 @Override 198 public String getPrincipalId() { 199 return principalId; 200 } 201 202 public Timestamp getDateAssigned() { 203 return dateAssigned; 204 } 205 206 @Override 207 public DateTime getDateTimeAssigned() { 208 return new DateTime(dateAssigned); 209 } 210 211 @Override 212 public String getActionRequestCd() { 213 return actionRequestCd; 214 } 215 216 @Override 217 public String getActionRequestId() { 218 return actionRequestId; 219 } 220 221 @Override 222 public String getDocumentId() { 223 return documentId; 224 } 225 226 @Override 227 public String getGroupId() { 228 return groupId; 229 } 230 231 @Override 232 public String getDocTitle() { 233 return docTitle; 234 } 235 236 @Override 237 public String getDocLabel() { 238 return docLabel; 239 } 240 241 @Override 242 public String getDocHandlerURL() { 243 return docHandlerURL; 244 } 245 246 @Override 247 public String getDocName() { 248 return docName; 249 } 250 251 @Override 252 public String getResponsibilityId() { 253 return responsibilityId; 254 } 255 256 @Override 257 public String getRoleName() { 258 return roleName; 259 } 260 261 @Override 262 public String getDelegatorPrincipalId() { 263 return delegatorPrincipalId; 264 } 265 266 @Override 267 public String getDelegatorGroupId() { 268 return delegatorGroupId; 269 } 270 271 @Override 272 public DelegationType getDelegationType() { 273 return DelegationType.fromCode(delegationType); 274 } 275 276 public String getRequestLabel() { 277 return this.requestLabel; 278 } 279 280 private Group getGroup(String groupId) { 281 if (StringUtils.isBlank(groupId)) { 282 return null; 283 } 284 return KimApiServiceLocator.getGroupService().getGroup(groupId); 285 } 286 287 public Group getGroup(){ 288 return getGroup(groupId); 289 } 290 291 public String getRecipientTypeCode() { 292 String recipientTypeCode = RecipientType.PRINCIPAL.getCode(); 293 if (getRoleName() != null) { 294 recipientTypeCode = RecipientType.ROLE.getCode(); 295 } 296 if (getGroupId() != null) { 297 recipientTypeCode = RecipientType.GROUP.getCode(); 298 } 299 return recipientTypeCode; 300 } 301 302 public String getActionRequestLabel() { 303 if (StringUtils.isNotBlank(getRequestLabel())) { 304 return getRequestLabel(); 305 } 306 return CodeTranslator.getActionRequestLabel(getActionRequestCd()); 307 } 308 309 public boolean isWorkgroupItem() { 310 return getGroupId() != null; 311 } 312 313 public Principal getPrincipal(){ 314 return KimApiServiceLocator.getIdentityService().getPrincipal(principalId); 315 } 316 317 public void setResponsibilityId(String responsibilityId) { 318 this.responsibilityId = responsibilityId; 319 } 320 321 public void setDocName(String docName) { 322 this.docName = docName; 323 } 324 325 public void setActionRequestCd(String actionRequestCd) { 326 this.actionRequestCd = actionRequestCd; 327 } 328 329 public void setDateAssigned(Timestamp dateAssigned) { 330 this.dateAssigned = dateAssigned; 331 } 332 333 public void setPrincipalId(String principalId) { 334 this.principalId = principalId; 335 } 336 337 public void setDocumentId(String documentId) { 338 this.documentId = documentId; 339 } 340 341 public void setId(String id) { 342 this.id = id; 343 } 344 345 public void setActionRequestId(String actionRequestId) { 346 this.actionRequestId = actionRequestId; 347 } 348 349 public void setDocHandlerURL(String docHandlerURL) { 350 this.docHandlerURL = docHandlerURL; 351 } 352 353 public void setGroupId(String groupId) { 354 this.groupId = groupId; 355 } 356 357 public void setDocLabel(String docLabel) { 358 this.docLabel = docLabel; 359 } 360 361 public void setDocTitle(String docTitle) { 362 this.docTitle = docTitle; 363 } 364 365 public void setRoleName(String roleName) { 366 this.roleName = roleName; 367 } 368 369 public void setDelegatorPrincipalId(String delegatorPrincipalId) { 370 this.delegatorPrincipalId = delegatorPrincipalId; 371 } 372 373 public void setDelegatorGroupId(String delegatorGroupId) { 374 this.delegatorGroupId = delegatorGroupId; 375 } 376 377 public void setDelegationType(DelegationType delegationType) { 378 this.delegationType = delegationType == null ? null : delegationType.getCode(); 379 } 380 381 public void setRequestLabel(String requestLabel) { 382 this.requestLabel = requestLabel; 383 } 384 385 @Deprecated 386 @Override 387 public Integer getActionItemIndex() { 388 // deprecated, always return null (see the contract javadoc for more details) 389 return null; 390 } 391 392 @Override 393 public String toString() { 394 return new ToStringBuilder(this).append("id", id) 395 .append("principalId", principalId) 396 .append("dateAssigned", dateAssigned) 397 .append("actionRequestCd", actionRequestCd) 398 .append("actionRequestId", actionRequestId) 399 .append("documentId", documentId) 400 .append("groupId", groupId) 401 .append("docTitle", docTitle) 402 .append("docLabel", docLabel) 403 .append("docHandlerURL", docHandlerURL) 404 .append("docName", docName) 405 .append("responsibilityId", responsibilityId) 406 .append("roleName", roleName) 407 .append("delegatorPrincipalId", delegatorPrincipalId) 408 .append("delegatorGroupId", delegatorGroupId) 409 .append("delegationType", delegationType) 410 .toString(); 411 } 412 413 public String getRouteHeaderRouteStatus() { 414 return getMinimalRouteHeader().getDocRouteStatus(); 415 } 416 417 public String getRouteHeaderCombinedStatus() { 418 return getMinimalRouteHeader().getCombinedStatus(); 419 } 420 421 public Timestamp getRouteHeaderCreateDate() { 422 return getMinimalRouteHeader().getCreateDate(); 423 } 424 425 public String getRouteHeaderInitiatorName() { 426 return getMinimalRouteHeader().getInitiatorDisplayName(); 427 } 428 429 public Timestamp getRouteHeaderApprovedDate() { 430 return getMinimalRouteHeader().getApprovedDate(); 431 } 432 433 public String getRouteHeaderCurrentRouteLevelName() { 434 return getMinimalRouteHeader().getCurrentRouteLevelName(); 435 } 436 437 public String getRouteHeaderInitiatorWorkflowId() { 438 return getMinimalRouteHeader().getInitiatorWorkflowId(); 439 } 440 441 public Integer getActionListIndex() { 442 return actionListIndex; 443 } 444 445 public void setActionListIndex(Integer actionListIndex) { 446 this.actionListIndex = actionListIndex; 447 } 448 449 public Timestamp getLastApprovedDate() { 450 initializeLastApprovedDate(); 451 return this.lastApprovedDate; 452 } 453 454 public Map<String, String> getCustomActions() { 455 return customActions; 456 } 457 458 public void setCustomActions(Map<String, String> customActions) { 459 this.customActions = customActions; 460 } 461 462 public String getRowStyleClass() { 463 return rowStyleClass; 464 } 465 466 public void setRowStyleClass(String rowStyleClass) { 467 this.rowStyleClass = rowStyleClass; 468 } 469 470 public String getDelegatorName() { 471 initializeDelegatorName(); 472 return delegatorName; 473 } 474 475 public String getGroupName() { 476 initializeGroupName(); 477 return groupName; 478 } 479 480 public void initialize(Preferences preferences) { 481 // always re-initialize row style class, just in case they changed a preference! 482 initializeRowStyleClass(preferences); 483 if (isInitialized) { 484 return; 485 } 486 if (KewApiConstants.PREFERENCES_YES_VAL.equals(preferences.getShowWorkgroupRequest())) { 487 initializeGroupName(); 488 } 489 if (KewApiConstants.PREFERENCES_YES_VAL.equals(preferences.getShowDelegator())) { 490 initializeDelegatorName(); 491 } 492 if (KewApiConstants.PREFERENCES_YES_VAL.equals(preferences.getShowDateApproved())) { 493 initializeLastApprovedDate(); 494 } 495 isInitialized = true; 496 } 497 498 private void initializeRowStyleClass(Preferences preferences) { 499 //set background colors for document statuses 500 String docRouteStatus = getRouteHeaderRouteStatus(); 501 if (KewApiConstants.ROUTE_HEADER_CANCEL_CD.equalsIgnoreCase(docRouteStatus)) { 502 setRowStyleClass(KewApiConstants.ACTION_LIST_COLOR_PALETTE.get(preferences.getColorCanceled())); 503 } else if (KewApiConstants.ROUTE_HEADER_DISAPPROVED_CD.equalsIgnoreCase(docRouteStatus)) { 504 setRowStyleClass(KewApiConstants.ACTION_LIST_COLOR_PALETTE.get(preferences.getColorDisapproved())); 505 } else if (KewApiConstants.ROUTE_HEADER_ENROUTE_CD.equalsIgnoreCase(docRouteStatus)) { 506 setRowStyleClass(KewApiConstants.ACTION_LIST_COLOR_PALETTE.get(preferences.getColorEnroute())); 507 } else if (KewApiConstants.ROUTE_HEADER_EXCEPTION_CD.equalsIgnoreCase(docRouteStatus)) { 508 setRowStyleClass(KewApiConstants.ACTION_LIST_COLOR_PALETTE.get(preferences.getColorException())); 509 } else if (KewApiConstants.ROUTE_HEADER_FINAL_CD.equalsIgnoreCase(docRouteStatus)) { 510 setRowStyleClass(KewApiConstants.ACTION_LIST_COLOR_PALETTE.get(preferences.getColorFinal())); 511 } else if (KewApiConstants.ROUTE_HEADER_INITIATED_CD.equalsIgnoreCase(docRouteStatus)) { 512 setRowStyleClass(KewApiConstants.ACTION_LIST_COLOR_PALETTE.get(preferences.getColorInitiated())); 513 } else if (KewApiConstants.ROUTE_HEADER_PROCESSED_CD.equalsIgnoreCase(docRouteStatus)) { 514 setRowStyleClass(KewApiConstants.ACTION_LIST_COLOR_PALETTE.get(preferences.getColorProcessed())); 515 } else if (KewApiConstants.ROUTE_HEADER_SAVED_CD.equalsIgnoreCase(docRouteStatus)) { 516 setRowStyleClass(KewApiConstants.ACTION_LIST_COLOR_PALETTE.get(preferences.getColorSaved())); 517 } 518 } 519 520 private void initializeGroupName() { 521 if (!groupNameInitialized) { 522 if (getGroupId() != null) { 523 Group group = this.getGroup(); 524 groupName = group.getName(); 525 } 526 groupNameInitialized = true; 527 } 528 } 529 530 private void initializeDelegatorName() { 531 if (!delegatorNameInitialized) { 532 if (getDelegatorPrincipalId() != null) { 533 EntityNamePrincipalName name = KimApiServiceLocator.getIdentityService().getDefaultNamesForPrincipalId(getDelegatorPrincipalId()); 534 if (name != null) { 535 delegatorName = name.getDefaultName().getCompositeName(); 536 } 537 } 538 if (getDelegatorGroupId() != null) { 539 Group delegatorGroup = KimApiServiceLocator.getGroupService().getGroup(getDelegatorGroupId()); 540 if (delegatorGroup !=null) 541 delegatorName = delegatorGroup.getName(); 542 } 543 delegatorNameInitialized = true; 544 } 545 } 546 547 private void initializeLastApprovedDate() { 548 if (!lastApprovedDateInitialized) { 549 lastApprovedDate = KEWServiceLocator.getActionTakenService().getLastApprovedDate(getDocumentId()); 550 lastApprovedDateInitialized = true; 551 } 552 } 553 554 public DisplayParameters getDisplayParameters() { 555 return displayParameters; 556 } 557 558 public void setDisplayParameters(DisplayParameters displayParameters) { 559 this.displayParameters = displayParameters; 560 } 561 562 public DocumentRouteHeaderValue getRouteHeader() { 563 return routeHeader; 564 } 565 566 public void setRouteHeader(DocumentRouteHeaderValue routeHeader) { 567 this.routeHeader = routeHeader; 568 } 569 570 public DocumentRouteHeaderValue getMinimalRouteHeader() { 571 if ( minimalRouteHeader == null ) { 572 minimalRouteHeader = KEWServiceLocator.getActionListService().getMinimalRouteHeader(documentId); 573 } 574 return minimalRouteHeader; 575 } 576 577 protected <T extends ActionItemBase> T deepCopy(Map<Object, Object> visited, Class<T> type) { 578 if (visited.containsKey(this)) { 579 return (T)visited.get(this); 580 } 581 T copy = null; 582 try { 583 copy = type.newInstance(); 584 } catch (Exception e) { 585 throw new IllegalArgumentException(e); 586 } 587 visited.put(this, copy); 588 copy.setId(id); 589 copy.setPrincipalId(principalId); 590 if (dateAssigned != null) { 591 copy.setDateAssigned(new Timestamp(dateAssigned.getTime())); 592 } 593 copy.setActionRequestCd(actionRequestCd); 594 copy.setActionRequestId(actionRequestId); 595 copy.setDocumentId(documentId); 596 copy.setGroupId(groupId); 597 copy.setDocTitle(docTitle); 598 copy.setDocLabel(docLabel); 599 copy.setDocHandlerURL(docHandlerURL); 600 copy.setDocName(docName); 601 copy.setResponsibilityId(responsibilityId); 602 copy.setRoleName(roleName); 603 copy.setDelegatorPrincipalId(delegatorPrincipalId); 604 copy.setDelegatorGroupId(delegatorGroupId); 605 copy.setDelegationType(DelegationType.fromCode(delegationType)); 606 copy.setRequestLabel(requestLabel); 607 copy.setDateAssignedStringValue(dateAssignedStringValue); 608 if (routeHeader != null) { 609 copy.setRouteHeader(routeHeader.deepCopy(visited)); 610 } 611 return copy; 612 } 613 614 /** 615 * Called from ActionList.jsp to help determine the 'target' value when building the URL. 616 * 617 * @return the value from the DOC_SEARCH_TARGET policy if it exists for this document type 618 */ 619 public String getTarget() { 620 org.kuali.rice.kew.api.doctype.DocumentType documentType = KewApiServiceLocator.getDocumentTypeService().getDocumentTypeByName(this.docName); 621 Map<DocumentTypePolicy, String> policies = documentType.getPolicies(); 622 for (DocumentTypePolicy policy : policies.keySet()) { 623 if (policy.getCode().equals(DocumentTypePolicy.DOC_SEARCH_TARGET.getCode())) { 624 return policies.get(DocumentTypePolicy.DOC_SEARCH_TARGET).toLowerCase(); 625 } 626 } 627 return null; 628 } 629 630}