View Javadoc
1   /**
2    * Copyright 2005-2015 The Kuali Foundation
3    *
4    * Licensed under the Educational Community License, Version 2.0 (the "License");
5    * you may not use this file except in compliance with the License.
6    * You may obtain a copy of the License at
7    *
8    * http://www.opensource.org/licenses/ecl2.php
9    *
10   * Unless required by applicable law or agreed to in writing, software
11   * distributed under the License is distributed on an "AS IS" BASIS,
12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13   * See the License for the specific language governing permissions and
14   * limitations under the License.
15   */
16  package org.kuali.rice.kew.actionitem;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.apache.commons.lang.builder.ToStringBuilder;
20  import org.joda.time.DateTime;
21  import org.kuali.rice.core.api.delegation.DelegationType;
22  import org.kuali.rice.core.api.util.RiceConstants;
23  import org.kuali.rice.kew.api.KewApiConstants;
24  import org.kuali.rice.kew.api.KewApiServiceLocator;
25  import org.kuali.rice.kew.api.action.ActionItemContract;
26  import org.kuali.rice.kew.api.action.RecipientType;
27  import org.kuali.rice.kew.api.actionlist.DisplayParameters;
28  import org.kuali.rice.kew.api.doctype.DocumentTypePolicy;
29  import org.kuali.rice.kew.api.preferences.Preferences;
30  import org.kuali.rice.kew.api.util.CodeTranslator;
31  import org.kuali.rice.kew.doctype.bo.DocumentType;
32  import org.kuali.rice.kew.routeheader.DocumentRouteHeaderValue;
33  import org.kuali.rice.kew.service.KEWServiceLocator;
34  import org.kuali.rice.kim.api.group.Group;
35  import org.kuali.rice.kim.api.identity.principal.EntityNamePrincipalName;
36  import org.kuali.rice.kim.api.identity.principal.Principal;
37  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
38  import org.kuali.rice.krad.data.jpa.PortableSequenceGenerator;
39  import org.kuali.rice.krad.exception.ValidationException;
40  
41  import javax.persistence.CascadeType;
42  import javax.persistence.Column;
43  import javax.persistence.FetchType;
44  import javax.persistence.GeneratedValue;
45  import javax.persistence.Id;
46  import javax.persistence.JoinColumn;
47  import javax.persistence.ManyToOne;
48  import javax.persistence.MappedSuperclass;
49  import javax.persistence.Transient;
50  import java.io.Serializable;
51  import java.sql.Timestamp;
52  import java.util.HashMap;
53  import java.util.Map;
54  
55  /**
56   * This is the model for action items. These are displayed as the action list as well.  Mapped to ActionItemService.
57   * NOTE: This object contains denormalized fields that have been copied from related ActionRequestValue and DocumentRouteHeaderValue
58   * objects for performance reasons.  These should be preserved and their related objects should not be added to the OJB
59   * mapping as we do not want them loaded for each ActionItem object.
60   *
61   * @author Kuali Rice Team (rice.collab@kuali.org)
62   *
63   */
64  @MappedSuperclass
65  public class ActionItemBase implements ActionItemContract, Serializable {
66  
67      private static final long serialVersionUID = -1079562205125660151L;
68  
69      @Id
70      @GeneratedValue(generator = "KREW_ACTN_ITM_S")
71      @PortableSequenceGenerator(name = "KREW_ACTN_ITM_S")
72      @Column(name = "ACTN_ITM_ID")
73      private String id;
74  
75      @Column(name = "PRNCPL_ID")
76      private String principalId;
77      
78      @Column(name = "ASND_DT")
79      private Timestamp dateAssigned;
80  
81      @Column(name = "RQST_CD")
82      private String actionRequestCd;
83  
84      @Column(name = "ACTN_RQST_ID")
85      private String actionRequestId;
86  
87      @Column(name = "DOC_HDR_ID")
88      private String documentId;
89  
90      @Column(name = "GRP_ID")
91      private String groupId;
92  
93      @Column(name = "DOC_HDR_TTL")
94      private String docTitle;
95  
96      @Column(name = "DOC_TYP_LBL")
97      private String docLabel;
98  
99      @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 }