1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.kew.routeheader;
17
18 import org.apache.commons.lang.ObjectUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.apache.log4j.Logger;
21 import org.hibernate.annotations.Fetch;
22 import org.hibernate.annotations.FetchMode;
23 import org.hibernate.annotations.GenericGenerator;
24 import org.hibernate.annotations.Parameter;
25 import org.joda.time.DateTime;
26 import org.kuali.rice.core.api.exception.RiceRuntimeException;
27 import org.kuali.rice.kew.actionitem.ActionItem;
28 import org.kuali.rice.kew.actionlist.CustomActionListAttribute;
29 import org.kuali.rice.kew.actionlist.DefaultCustomActionListAttribute;
30 import org.kuali.rice.kew.actionrequest.ActionRequestFactory;
31 import org.kuali.rice.kew.actionrequest.ActionRequestValue;
32 import org.kuali.rice.kew.actiontaken.ActionTakenValue;
33 import org.kuali.rice.kew.api.KewApiConstants;
34 import org.kuali.rice.kew.api.WorkflowRuntimeException;
35 import org.kuali.rice.kew.api.action.ActionType;
36 import org.kuali.rice.kew.api.document.Document;
37 import org.kuali.rice.kew.api.document.DocumentContract;
38 import org.kuali.rice.kew.api.document.DocumentStatus;
39 import org.kuali.rice.kew.api.document.DocumentUpdate;
40 import org.kuali.rice.kew.api.exception.InvalidActionTakenException;
41 import org.kuali.rice.kew.api.exception.WorkflowException;
42 import org.kuali.rice.kew.api.util.CodeTranslator;
43 import org.kuali.rice.kew.docsearch.DocumentSearchCriteriaEbo;
44 import org.kuali.rice.kew.docsearch.SearchableAttributeValue;
45 import org.kuali.rice.kew.doctype.ApplicationDocumentStatus;
46 import org.kuali.rice.kew.doctype.DocumentTypePolicy;
47 import org.kuali.rice.kew.doctype.bo.DocumentType;
48 import org.kuali.rice.kew.engine.CompatUtils;
49 import org.kuali.rice.kew.engine.node.Branch;
50 import org.kuali.rice.kew.engine.node.BranchState;
51 import org.kuali.rice.kew.engine.node.RouteNode;
52 import org.kuali.rice.kew.engine.node.RouteNodeInstance;
53 import org.kuali.rice.kew.api.exception.ResourceUnavailableException;
54 import org.kuali.rice.kew.mail.CustomEmailAttribute;
55 import org.kuali.rice.kew.mail.CustomEmailAttributeImpl;
56 import org.kuali.rice.kew.notes.CustomNoteAttribute;
57 import org.kuali.rice.kew.notes.CustomNoteAttributeImpl;
58 import org.kuali.rice.kew.notes.Note;
59 import org.kuali.rice.kew.service.KEWServiceLocator;
60 import org.kuali.rice.kim.api.identity.principal.Principal;
61 import org.kuali.rice.krad.bo.PersistableBusinessObjectBase;
62
63 import javax.persistence.CascadeType;
64 import javax.persistence.Column;
65 import javax.persistence.Entity;
66 import javax.persistence.FetchType;
67 import javax.persistence.GeneratedValue;
68 import javax.persistence.Id;
69 import javax.persistence.JoinColumn;
70 import javax.persistence.JoinTable;
71 import javax.persistence.ManyToMany;
72 import javax.persistence.NamedQueries;
73 import javax.persistence.NamedQuery;
74 import javax.persistence.OneToMany;
75 import javax.persistence.OrderBy;
76 import javax.persistence.Table;
77 import javax.persistence.Transient;
78 import java.sql.Timestamp;
79 import java.util.ArrayList;
80 import java.util.Collection;
81 import java.util.HashMap;
82 import java.util.Iterator;
83 import java.util.List;
84 import java.util.Map;
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122 @Entity
123 @Table(name="KREW_DOC_HDR_T")
124
125 @NamedQueries({
126 @NamedQuery(name="DocumentRouteHeaderValue.FindByDocumentId", query="select d from DocumentRouteHeaderValue as d where d.documentId = :documentId"),
127 @NamedQuery(name="DocumentRouteHeaderValue.QuickLinks.FindWatchedDocumentsByInitiatorWorkflowId", query="SELECT NEW org.kuali.rice.kew.quicklinks.WatchedDocument(documentId, docRouteStatus, docTitle) FROM DocumentRouteHeaderValue WHERE initiatorWorkflowId = :initiatorWorkflowId AND docRouteStatus IN ('"+ KewApiConstants.ROUTE_HEADER_ENROUTE_CD +"','"+ KewApiConstants.ROUTE_HEADER_EXCEPTION_CD +"') ORDER BY createDate DESC"),
128 @NamedQuery(name="DocumentRouteHeaderValue.GetAppDocId", query="SELECT d.appDocId from DocumentRouteHeaderValue as d where d.documentId = :documentId"),
129 @NamedQuery(name="DocumentRouteHeaderValue.GetAppDocStatus", query="SELECT d.appDocStatus from DocumentRouteHeaderValue as d where d.documentId = :documentId")
130 })
131 public class DocumentRouteHeaderValue extends PersistableBusinessObjectBase implements DocumentContract, DocumentSearchCriteriaEbo {
132 private static final long serialVersionUID = -4700736340527913220L;
133 private static final Logger LOG = Logger.getLogger(DocumentRouteHeaderValue.class);
134
135 public static final String CURRENT_ROUTE_NODE_NAME_DELIMITER = ", ";
136
137 @Column(name="DOC_TYP_ID")
138 private String documentTypeId;
139 @Column(name="DOC_HDR_STAT_CD")
140 private java.lang.String docRouteStatus;
141 @Column(name="RTE_LVL")
142 private java.lang.Integer docRouteLevel;
143 @Column(name="STAT_MDFN_DT")
144 private java.sql.Timestamp dateModified;
145 @Column(name="CRTE_DT")
146 private java.sql.Timestamp createDate;
147 @Column(name="APRV_DT")
148 private java.sql.Timestamp approvedDate;
149 @Column(name="FNL_DT")
150 private java.sql.Timestamp finalizedDate;
151 @Transient
152 private DocumentRouteHeaderValueContent documentContent;
153 @Column(name="TTL")
154 private java.lang.String docTitle;
155 @Column(name="APP_DOC_ID")
156 private java.lang.String appDocId;
157 @Column(name="DOC_VER_NBR")
158 private java.lang.Integer docVersion = new Integer(KewApiConstants.DocumentContentVersions.NODAL);
159 @Column(name="INITR_PRNCPL_ID")
160 private java.lang.String initiatorWorkflowId;
161 @Column(name="RTE_PRNCPL_ID")
162 private java.lang.String routedByUserWorkflowId;
163 @Column(name="RTE_STAT_MDFN_DT")
164 private java.sql.Timestamp routeStatusDate;
165 @Column(name="APP_DOC_STAT")
166 private java.lang.String appDocStatus;
167 @Column(name="APP_DOC_STAT_MDFN_DT")
168 private java.sql.Timestamp appDocStatusDate;
169
170 @Id
171 @GeneratedValue(generator="KREW_DOC_HDR_S")
172 @GenericGenerator(name="KREW_DOC_HDR_S",strategy="org.hibernate.id.enhanced.SequenceStyleGenerator",parameters={
173 @Parameter(name="sequence_name",value="KREW_DOC_HDR_S"),
174 @Parameter(name="value_column",value="id")
175 })
176 @Column(name="DOC_HDR_ID")
177 private java.lang.String documentId;
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197 @OneToMany(fetch=FetchType.EAGER, cascade={CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}, mappedBy="documentId")
198
199 @OrderBy("statusTransitionId ASC")
200 @Fetch(value = FetchMode.SELECT)
201 private List<DocumentStatusTransition> appDocStatusHistory = new ArrayList<DocumentStatusTransition>();
202
203 @OneToMany(fetch=FetchType.LAZY, cascade={CascadeType.PERSIST, CascadeType.REMOVE})
204 @JoinColumn(name="DOC_HDR_ID")
205 @OrderBy("noteId ASC")
206 private List<Note> notes = new ArrayList<Note>();
207
208 @Transient
209 private List<SearchableAttributeValue> searchableAttributeValues = new ArrayList<SearchableAttributeValue>();
210 @Transient
211 private Collection queueItems = new ArrayList();
212 @Transient
213 private boolean routingReport = false;
214 @Transient
215 private List<ActionRequestValue> simulatedActionRequests;
216
217 private static final boolean FINAL_STATE = true;
218 protected static final HashMap<String,String> legalActions;
219 protected static final HashMap<String,String> stateTransitionMap;
220
221
222 @ManyToMany(fetch=FetchType.EAGER, cascade=CascadeType.REMOVE)
223 @JoinTable(name = "KREW_INIT_RTE_NODE_INSTN_T", joinColumns = @JoinColumn(name = "DOC_HDR_ID"), inverseJoinColumns = @JoinColumn(name = "RTE_NODE_INSTN_ID"))
224 @Fetch(value = FetchMode.SELECT)
225 private List<RouteNodeInstance> initialRouteNodeInstances = new ArrayList<RouteNodeInstance>();
226
227
228 private static final String TERMINAL = "";
229
230 static {
231 stateTransitionMap = new HashMap<String,String>();
232 stateTransitionMap.put(KewApiConstants.ROUTE_HEADER_INITIATED_CD, KewApiConstants.ROUTE_HEADER_SAVED_CD + KewApiConstants.ROUTE_HEADER_ENROUTE_CD + KewApiConstants.ROUTE_HEADER_CANCEL_CD);
233
234 stateTransitionMap.put(KewApiConstants.ROUTE_HEADER_SAVED_CD, KewApiConstants.ROUTE_HEADER_SAVED_CD + KewApiConstants.ROUTE_HEADER_ENROUTE_CD + KewApiConstants.ROUTE_HEADER_CANCEL_CD + KewApiConstants.ROUTE_HEADER_PROCESSED_CD);
235
236 stateTransitionMap.put(KewApiConstants.ROUTE_HEADER_ENROUTE_CD, KewApiConstants.ROUTE_HEADER_DISAPPROVED_CD +
237 KewApiConstants.ROUTE_HEADER_CANCEL_CD + KewApiConstants.ROUTE_HEADER_PROCESSED_CD + KewApiConstants.ROUTE_HEADER_EXCEPTION_CD + KewApiConstants.ROUTE_HEADER_SAVED_CD
238 + DocumentStatus.RECALLED.getCode());
239 stateTransitionMap.put(KewApiConstants.ROUTE_HEADER_DISAPPROVED_CD, TERMINAL);
240 stateTransitionMap.put(KewApiConstants.ROUTE_HEADER_CANCEL_CD, TERMINAL);
241 stateTransitionMap.put(KewApiConstants.ROUTE_HEADER_FINAL_CD, TERMINAL);
242 stateTransitionMap.put(DocumentStatus.RECALLED.getCode(), TERMINAL);
243 stateTransitionMap.put(KewApiConstants.ROUTE_HEADER_EXCEPTION_CD, KewApiConstants.ROUTE_HEADER_EXCEPTION_CD + KewApiConstants.ROUTE_HEADER_ENROUTE_CD + KewApiConstants.ROUTE_HEADER_CANCEL_CD + KewApiConstants.ROUTE_HEADER_PROCESSED_CD + KewApiConstants.ROUTE_HEADER_DISAPPROVED_CD + KewApiConstants.ROUTE_HEADER_SAVED_CD);
244 stateTransitionMap.put(KewApiConstants.ROUTE_HEADER_PROCESSED_CD, KewApiConstants.ROUTE_HEADER_FINAL_CD + KewApiConstants.ROUTE_HEADER_PROCESSED_CD);
245
246 legalActions = new HashMap<String,String>();
247 legalActions.put(KewApiConstants.ROUTE_HEADER_INITIATED_CD, KewApiConstants.ACTION_TAKEN_FYI_CD + KewApiConstants.ACTION_TAKEN_ACKNOWLEDGED_CD + KewApiConstants.ACTION_TAKEN_SAVED_CD + KewApiConstants.ACTION_TAKEN_COMPLETED_CD + KewApiConstants.ACTION_TAKEN_ROUTED_CD + KewApiConstants.ACTION_TAKEN_CANCELED_CD + KewApiConstants.ACTION_TAKEN_ADHOC_CD + KewApiConstants.ACTION_TAKEN_ADHOC_REVOKED_CD + KewApiConstants.ACTION_TAKEN_BLANKET_APPROVE_CD + KewApiConstants.ACTION_TAKEN_MOVE_CD);
248 legalActions.put(KewApiConstants.ROUTE_HEADER_SAVED_CD, KewApiConstants.ACTION_TAKEN_FYI_CD + KewApiConstants.ACTION_TAKEN_ACKNOWLEDGED_CD + KewApiConstants.ACTION_TAKEN_SAVED_CD + KewApiConstants.ACTION_TAKEN_COMPLETED_CD + KewApiConstants.ACTION_TAKEN_ROUTED_CD + KewApiConstants.ACTION_TAKEN_APPROVED_CD + KewApiConstants.ACTION_TAKEN_CANCELED_CD + KewApiConstants.ACTION_TAKEN_ADHOC_CD + KewApiConstants.ACTION_TAKEN_ADHOC_REVOKED_CD + KewApiConstants.ACTION_TAKEN_BLANKET_APPROVE_CD + KewApiConstants.ACTION_TAKEN_MOVE_CD);
249
250
251
252 legalActions.put(KewApiConstants.ROUTE_HEADER_ENROUTE_CD,
253
254
255
256 legalActions.put(KewApiConstants.ROUTE_HEADER_EXCEPTION_CD,
257 legalActions.put(KewApiConstants.ROUTE_HEADER_FINAL_CD, KewApiConstants.ACTION_TAKEN_FYI_CD + KewApiConstants.ACTION_TAKEN_ACKNOWLEDGED_CD + KewApiConstants.ACTION_TAKEN_ADHOC_REVOKED_CD);
258 legalActions.put(KewApiConstants.ROUTE_HEADER_CANCEL_CD, KewApiConstants.ACTION_TAKEN_FYI_CD + KewApiConstants.ACTION_TAKEN_ACKNOWLEDGED_CD + KewApiConstants.ACTION_TAKEN_ADHOC_REVOKED_CD);
259 legalActions.put(KewApiConstants.ROUTE_HEADER_DISAPPROVED_CD, KewApiConstants.ACTION_TAKEN_FYI_CD + KewApiConstants.ACTION_TAKEN_ACKNOWLEDGED_CD + KewApiConstants.ACTION_TAKEN_ADHOC_REVOKED_CD);
260 legalActions.put(KewApiConstants.ROUTE_HEADER_PROCESSED_CD, KewApiConstants.ACTION_TAKEN_FYI_CD + KewApiConstants.ACTION_TAKEN_ACKNOWLEDGED_CD + KewApiConstants.ACTION_TAKEN_ADHOC_REVOKED_CD);
261 legalActions.put(DocumentStatus.RECALLED.getCode(), TERMINAL);
262 }
263
264 public DocumentRouteHeaderValue() {
265 }
266
267 public Principal getInitiatorPrincipal() {
268
269 if (getInitiatorWorkflowId() == null) {
270 return null;
271 }
272 return KEWServiceLocator.getIdentityHelperService().getPrincipal(getInitiatorWorkflowId());
273 }
274
275 public Principal getRoutedByPrincipal()
276 {
277 if (getRoutedByUserWorkflowId() == null) {
278 return null;
279 }
280 return KEWServiceLocator.getIdentityHelperService().getPrincipal(getRoutedByUserWorkflowId());
281 }
282
283 public String getInitiatorDisplayName() {
284 return KEWServiceLocator.getIdentityHelperService().getPerson(getInitiatorWorkflowId()).getName();
285 }
286
287 public String getRoutedByDisplayName() {
288 return KEWServiceLocator.getIdentityHelperService().getPerson(getRoutedByUserWorkflowId()).getName();
289 }
290
291 public String getCurrentRouteLevelName() {
292 String name = "Not Found";
293
294 if(routingReport){
295 name = "Routing Report";
296 } else if (CompatUtils.isRouteLevelDocument(this)) {
297 int routeLevelInt = getDocRouteLevel().intValue();
298 LOG.info("Getting current route level name for a Route level document: " + routeLevelInt+CURRENT_ROUTE_NODE_NAME_DELIMITER+documentId);
299 List routeLevelNodes = CompatUtils.getRouteLevelCompatibleNodeList(getDocumentType());
300 LOG.info("Route level compatible node list has " + routeLevelNodes.size() + " nodes");
301 if (routeLevelInt < routeLevelNodes.size()) {
302 name = ((RouteNode)routeLevelNodes.get(routeLevelInt)).getRouteNodeName();
303 }
304 } else {
305 List<String> currentNodeNames = getCurrentNodeNames();
306 name = StringUtils.join(currentNodeNames, CURRENT_ROUTE_NODE_NAME_DELIMITER);
307 }
308 return name;
309 }
310
311 public List<String> getCurrentNodeNames() {
312 return KEWServiceLocator.getRouteNodeService().getCurrentRouteNodeNames(getDocumentId());
313 }
314
315 public String getRouteStatusLabel() {
316 return CodeTranslator.getRouteStatusLabel(getDocRouteStatus());
317 }
318
319 public String getDocRouteStatusLabel() {
320 return CodeTranslator.getRouteStatusLabel(getDocRouteStatus());
321 }
322
323
324
325
326
327
328
329
330 public String getDocStatusPolicy() {
331 return getDocumentType().getDocumentStatusPolicy().getPolicyStringValue();
332 }
333
334 public Collection getQueueItems() {
335 return queueItems;
336 }
337
338 public void setQueueItems(Collection queueItems) {
339 this.queueItems = queueItems;
340 }
341
342 public List<ActionItem> getActionItems() {
343 return (List<ActionItem>) KEWServiceLocator.getActionListService().findByDocumentId(documentId);
344 }
345
346 public List<ActionTakenValue> getActionsTaken() {
347 return (List<ActionTakenValue>) KEWServiceLocator.getActionTakenService().findByDocumentIdIgnoreCurrentInd(documentId);
348 }
349
350 public List<ActionRequestValue> getActionRequests() {
351 if (this.simulatedActionRequests == null || this.simulatedActionRequests.isEmpty()) {
352 return KEWServiceLocator.getActionRequestService().findByDocumentIdIgnoreCurrentInd(documentId);
353 } else {
354 return this.simulatedActionRequests;
355 }
356 }
357
358 public List<ActionRequestValue> getSimulatedActionRequests() {
359 if (this.simulatedActionRequests == null) {
360 this.simulatedActionRequests = new ArrayList<ActionRequestValue>();
361 }
362 return this.simulatedActionRequests;
363 }
364
365 public void setSimulatedActionRequests(List<ActionRequestValue> simulatedActionRequests) {
366 this.simulatedActionRequests = simulatedActionRequests;
367 }
368
369 public DocumentType getDocumentType() {
370 return KEWServiceLocator.getDocumentTypeService().findById(getDocumentTypeId());
371 }
372
373 public java.lang.String getAppDocId() {
374 return appDocId;
375 }
376
377 public void setAppDocId(java.lang.String appDocId) {
378 this.appDocId = appDocId;
379 }
380
381 public java.sql.Timestamp getApprovedDate() {
382 return approvedDate;
383 }
384
385 public void setApprovedDate(java.sql.Timestamp approvedDate) {
386 this.approvedDate = approvedDate;
387 }
388
389 public java.sql.Timestamp getCreateDate() {
390 return createDate;
391 }
392
393 public void setCreateDate(java.sql.Timestamp createDate) {
394 this.createDate = createDate;
395 }
396
397 public java.lang.String getDocContent() {
398 return getDocumentContent().getDocumentContent();
399 }
400
401 public void setDocContent(java.lang.String docContent) {
402 DocumentRouteHeaderValueContent content = getDocumentContent();
403 content.setDocumentContent(docContent);
404 }
405
406 public java.lang.Integer getDocRouteLevel() {
407 return docRouteLevel;
408 }
409
410 public void setDocRouteLevel(java.lang.Integer docRouteLevel) {
411 this.docRouteLevel = docRouteLevel;
412 }
413
414 public java.lang.String getDocRouteStatus() {
415 return docRouteStatus;
416 }
417
418 public void setDocRouteStatus(java.lang.String docRouteStatus) {
419 this.docRouteStatus = docRouteStatus;
420 }
421
422 public java.lang.String getDocTitle() {
423 return docTitle;
424 }
425
426 public void setDocTitle(java.lang.String docTitle) {
427 this.docTitle = docTitle;
428 }
429
430 @Override
431 public String getDocumentTypeId() {
432 return documentTypeId;
433 }
434
435 public void setDocumentTypeId(String documentTypeId) {
436 this.documentTypeId = documentTypeId;
437 }
438
439 public java.lang.Integer getDocVersion() {
440 return docVersion;
441 }
442
443 public void setDocVersion(java.lang.Integer docVersion) {
444 this.docVersion = docVersion;
445 }
446
447 public java.sql.Timestamp getFinalizedDate() {
448 return finalizedDate;
449 }
450
451 public void setFinalizedDate(java.sql.Timestamp finalizedDate) {
452 this.finalizedDate = finalizedDate;
453 }
454
455 public java.lang.String getInitiatorWorkflowId() {
456 return initiatorWorkflowId;
457 }
458
459 public void setInitiatorWorkflowId(java.lang.String initiatorWorkflowId) {
460 this.initiatorWorkflowId = initiatorWorkflowId;
461 }
462
463 public java.lang.String getRoutedByUserWorkflowId() {
464 if ( (isEnroute()) && (StringUtils.isBlank(routedByUserWorkflowId)) ) {
465 return initiatorWorkflowId;
466 }
467 return routedByUserWorkflowId;
468 }
469
470 public void setRoutedByUserWorkflowId(java.lang.String routedByUserWorkflowId) {
471 this.routedByUserWorkflowId = routedByUserWorkflowId;
472 }
473
474 @Override
475 public String getDocumentId() {
476 return documentId;
477 }
478
479 public void setDocumentId(java.lang.String documentId) {
480 this.documentId = documentId;
481 }
482
483 public java.sql.Timestamp getRouteStatusDate() {
484 return routeStatusDate;
485 }
486
487 public void setRouteStatusDate(java.sql.Timestamp routeStatusDate) {
488 this.routeStatusDate = routeStatusDate;
489 }
490
491 public java.sql.Timestamp getDateModified() {
492 return dateModified;
493 }
494
495 public void setDateModified(java.sql.Timestamp dateModified) {
496 this.dateModified = dateModified;
497 }
498
499
500
501
502
503
504
505
506
507
508
509
510 public java.lang.String getAppDocStatus() {
511 if (appDocStatus == null || "".equals(appDocStatus)){
512 return KewApiConstants.UNKNOWN_STATUS;
513 }
514 return appDocStatus;
515 }
516
517 public void setAppDocStatus(java.lang.String appDocStatus){
518 this.appDocStatus = appDocStatus;
519 }
520
521
522
523
524
525
526
527 public String getCombinedStatus(){
528 String routeStatus = getRouteStatusLabel();
529 String appStatus = getAppDocStatus();
530 if (routeStatus != null && routeStatus.length()>0){
531 if (appStatus.length() > 0){
532 routeStatus += ", "+appStatus;
533 }
534 } else {
535 return appStatus;
536 }
537 return routeStatus;
538 }
539
540
541
542
543
544
545
546
547
548
549 public void updateAppDocStatus(java.lang.String appDocStatus) throws WorkflowRuntimeException{
550
551 if (appDocStatus != null && appDocStatus.length() > 0 && !appDocStatus.equalsIgnoreCase(this.appDocStatus)){
552 DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findById(this.getDocumentTypeId());
553 if (documentType.getValidApplicationStatuses() != null && documentType.getValidApplicationStatuses().size() > 0){
554 Iterator<ApplicationDocumentStatus> iter = documentType.getValidApplicationStatuses().iterator();
555 boolean statusValidated = false;
556 while (iter.hasNext())
557 {
558 ApplicationDocumentStatus myAppDocStat = iter.next();
559 if (appDocStatus.compareToIgnoreCase(myAppDocStat.getStatusName()) == 0)
560 {
561 statusValidated = true;
562 break;
563 }
564 }
565 if (!statusValidated){
566 WorkflowRuntimeException xpee = new WorkflowRuntimeException("AppDocStatus value " + appDocStatus + " not allowable.");
567 LOG.error("Error validating nextAppDocStatus name: " + appDocStatus + " against acceptable values.", xpee);
568 throw xpee;
569 }
570 }
571
572
573 String oldStatus = this.appDocStatus;
574 this.appDocStatus = appDocStatus;
575
576
577 setAppDocStatusDate(new Timestamp(System.currentTimeMillis()));
578
579
580 this.appDocStatusHistory.add(new DocumentStatusTransition(documentId, oldStatus, appDocStatus));
581 }
582
583 }
584
585
586 public java.sql.Timestamp getAppDocStatusDate() {
587 return appDocStatusDate;
588 }
589
590 public void setAppDocStatusDate(java.sql.Timestamp appDocStatusDate) {
591 this.appDocStatusDate = appDocStatusDate;
592 }
593
594 public Object copy(boolean preserveKeys) {
595 throw new UnsupportedOperationException("The copy method is deprecated and unimplemented!");
596 }
597
598
599
600
601 public boolean isStateInitiated() {
602 return KewApiConstants.ROUTE_HEADER_INITIATED_CD.equals(docRouteStatus);
603 }
604
605
606
607
608 public boolean isStateSaved() {
609 return KewApiConstants.ROUTE_HEADER_SAVED_CD.equals(docRouteStatus);
610 }
611
612
613
614
615 public boolean isRouted() {
616 return !(isStateInitiated() || isStateSaved());
617 }
618
619 public boolean isInException() {
620 return KewApiConstants.ROUTE_HEADER_EXCEPTION_CD.equals(docRouteStatus);
621 }
622
623 public boolean isDisaproved() {
624 return KewApiConstants.ROUTE_HEADER_DISAPPROVED_CD.equals(docRouteStatus);
625 }
626
627 public boolean isCanceled() {
628 return KewApiConstants.ROUTE_HEADER_CANCEL_CD.equals(docRouteStatus);
629 }
630
631 public boolean isFinal() {
632 return KewApiConstants.ROUTE_HEADER_FINAL_CD.equals(docRouteStatus);
633 }
634
635 public boolean isEnroute() {
636 return KewApiConstants.ROUTE_HEADER_ENROUTE_CD.equals(docRouteStatus);
637 }
638
639
640
641
642 public boolean isProcessed() {
643 return KewApiConstants.ROUTE_HEADER_PROCESSED_CD.equals(docRouteStatus);
644 }
645
646 public boolean isRoutable() {
647 return KewApiConstants.ROUTE_HEADER_ENROUTE_CD.equals(docRouteStatus) ||
648
649 KewApiConstants.ROUTE_HEADER_SAVED_CD.equals(docRouteStatus) ||
650 KewApiConstants.ROUTE_HEADER_PROCESSED_CD.equals(docRouteStatus);
651 }
652
653
654
655
656
657
658
659
660
661 public boolean isValidActionToTake(String actionCd) {
662 String actions = (String) legalActions.get(docRouteStatus);
663 return actions.contains(actionCd);
664 }
665
666 public boolean isValidStatusChange(String newStatus) {
667 return ((String) stateTransitionMap.get(getDocRouteStatus())).contains(newStatus);
668 }
669
670 public void setRouteStatus(String newStatus, boolean finalState) throws InvalidActionTakenException {
671 if (newStatus != getDocRouteStatus()) {
672
673 setRouteStatusDate(new Timestamp(System.currentTimeMillis()));
674 }
675 if (((String) stateTransitionMap.get(getDocRouteStatus())).contains(newStatus)) {
676 LOG.debug("changing status");
677 setDocRouteStatus(newStatus);
678 } else {
679 LOG.debug("unable to change status");
680 throw new InvalidActionTakenException("Document status " + CodeTranslator.getRouteStatusLabel(getDocRouteStatus()) + " cannot transition to status " + CodeTranslator
681 .getRouteStatusLabel(newStatus));
682 }
683 setDateModified(new Timestamp(System.currentTimeMillis()));
684 if (finalState) {
685 LOG.debug("setting final timeStamp");
686 setFinalizedDate(new Timestamp(System.currentTimeMillis()));
687 }
688 }
689
690
691
692
693
694
695
696 public void markDocumentProcessed() throws InvalidActionTakenException {
697 LOG.debug(this + " marked processed");
698 setRouteStatus(KewApiConstants.ROUTE_HEADER_PROCESSED_CD, !FINAL_STATE);
699 }
700
701
702
703
704
705
706
707 public void markDocumentCanceled() throws InvalidActionTakenException {
708 LOG.debug(this + " marked canceled");
709 setRouteStatus(KewApiConstants.ROUTE_HEADER_CANCEL_CD, FINAL_STATE);
710 }
711
712
713
714
715
716
717
718 public void markDocumentRecalled() throws InvalidActionTakenException {
719 LOG.debug(this + " marked recalled");
720 setRouteStatus(DocumentStatus.RECALLED.getCode(), FINAL_STATE);
721 }
722
723
724
725
726
727
728
729 public void markDocumentDisapproved() throws InvalidActionTakenException {
730 LOG.debug(this + " marked disapproved");
731 setRouteStatus(KewApiConstants.ROUTE_HEADER_DISAPPROVED_CD, FINAL_STATE);
732 }
733
734
735
736
737
738
739
740 public void markDocumentSaved() throws InvalidActionTakenException {
741 LOG.debug(this + " marked saved");
742 setRouteStatus(KewApiConstants.ROUTE_HEADER_SAVED_CD, !FINAL_STATE);
743 }
744
745
746
747
748
749
750
751 public void markDocumentInException() throws InvalidActionTakenException {
752 LOG.debug(this + " marked in exception");
753 setRouteStatus(KewApiConstants.ROUTE_HEADER_EXCEPTION_CD, !FINAL_STATE);
754 }
755
756
757
758
759
760
761
762 public void markDocumentEnroute() throws InvalidActionTakenException {
763 LOG.debug(this + " marked enroute");
764 setRouteStatus(KewApiConstants.ROUTE_HEADER_ENROUTE_CD, !FINAL_STATE);
765 }
766
767
768
769
770
771
772
773 public void markDocumentFinalized() throws InvalidActionTakenException {
774 LOG.debug(this + " marked finalized");
775 setRouteStatus(KewApiConstants.ROUTE_HEADER_FINAL_CD, FINAL_STATE);
776 }
777
778
779
780
781
782
783 public void setRouteHeaderData(Document routeHeaderVO) throws WorkflowException {
784 if (!ObjectUtils.equals(getDocTitle(), routeHeaderVO.getTitle())) {
785 KEWServiceLocator.getActionListService().updateActionItemsForTitleChange(getDocumentId(), routeHeaderVO.getTitle());
786 }
787 setDocTitle(routeHeaderVO.getTitle());
788 setAppDocId(routeHeaderVO.getApplicationDocumentId());
789 setDateModified(new Timestamp(System.currentTimeMillis()));
790 updateAppDocStatus(routeHeaderVO.getApplicationDocumentStatus());
791
792
793 for (Map.Entry<String, String> kvp : routeHeaderVO.getVariables().entrySet()) {
794 setVariable(kvp.getKey(), kvp.getValue());
795 }
796 }
797
798 public void applyDocumentUpdate(DocumentUpdate documentUpdate) {
799 if (documentUpdate != null) {
800 String thisDocTitle = getDocTitle() == null ? "" : getDocTitle();
801 String updateDocTitle = documentUpdate.getTitle() == null ? "" : documentUpdate.getTitle();
802 if (!StringUtils.equals(thisDocTitle, updateDocTitle)) {
803 KEWServiceLocator.getActionListService().updateActionItemsForTitleChange(getDocumentId(), documentUpdate.getTitle());
804 }
805 setDocTitle(updateDocTitle);
806 setAppDocId(documentUpdate.getApplicationDocumentId());
807 setDateModified(new Timestamp(System.currentTimeMillis()));
808 updateAppDocStatus(documentUpdate.getApplicationDocumentStatus());
809
810 Map<String, String> variables = documentUpdate.getVariables();
811 for (String variableName : variables.keySet()) {
812 setVariable(variableName, variables.get(variableName));
813 }
814 }
815 }
816
817
818
819
820
821 public Branch getRootBranch() {
822 if (!this.initialRouteNodeInstances.isEmpty()) {
823 return ((RouteNodeInstance) getInitialRouteNodeInstance(0)).getBranch();
824 }
825 return null;
826 }
827
828
829
830
831
832 private BranchState findVariable(String name) {
833 Branch rootBranch = getRootBranch();
834 if (rootBranch != null) {
835 List<BranchState> branchState = rootBranch.getBranchState();
836 Iterator<BranchState> it = branchState.iterator();
837 while (it.hasNext()) {
838 BranchState state = it.next();
839 if (ObjectUtils.equals(state.getKey(), BranchState.VARIABLE_PREFIX + name)) {
840 return state;
841 }
842 }
843 }
844 return null;
845 }
846
847
848
849
850
851
852 public String getVariable(String name) {
853 BranchState state = findVariable(name);
854 if (state == null) {
855 LOG.debug("Variable not found: '" + name + "'");
856 return null;
857 }
858 return state.getValue();
859 }
860
861 public void removeVariableThatContains(String name) {
862 List<BranchState> statesToRemove = new ArrayList<BranchState>();
863 for (BranchState state : this.getRootBranchState()) {
864 if (state.getKey().contains(name)) {
865 statesToRemove.add(state);
866 }
867 }
868 this.getRootBranchState().removeAll(statesToRemove);
869 }
870
871
872
873
874
875
876 public void setVariable(String name, String value) {
877 BranchState state = findVariable(name);
878 Branch rootBranch = getRootBranch();
879 if (rootBranch != null) {
880 List<BranchState> branchState = rootBranch.getBranchState();
881 if (state == null) {
882 if (value == null) {
883 LOG.debug("set non existent variable '" + name + "' to null value");
884 return;
885 }
886 LOG.debug("Adding branch state: '" + name + "'='" + value + "'");
887 state = new BranchState();
888 state.setBranch(rootBranch);
889 state.setKey(BranchState.VARIABLE_PREFIX + name);
890 state.setValue(value);
891 rootBranch.addBranchState(state);
892 } else {
893 if (value == null) {
894 LOG.debug("Removing value: " + state.getKey() + "=" + state.getValue());
895 branchState.remove(state);
896 } else {
897 LOG.debug("Setting value of variable '" + name + "' to '" + value + "'");
898 state.setValue(value);
899 }
900 }
901 }
902 }
903
904 public List<BranchState> getRootBranchState() {
905 if (this.getRootBranch() != null) {
906 return this.getRootBranch().getBranchState();
907 }
908 return null;
909 }
910
911 public CustomActionListAttribute getCustomActionListAttribute() throws WorkflowException {
912 CustomActionListAttribute customActionListAttribute = null;
913 if (this.getDocumentType() != null) {
914 customActionListAttribute = this.getDocumentType().getCustomActionListAttribute();
915 if (customActionListAttribute != null) {
916 return customActionListAttribute;
917 }
918 }
919 customActionListAttribute = new DefaultCustomActionListAttribute();
920 return customActionListAttribute;
921 }
922
923 public CustomEmailAttribute getCustomEmailAttribute() throws WorkflowException {
924 CustomEmailAttribute customEmailAttribute = null;
925 try {
926 if (this.getDocumentType() != null) {
927 customEmailAttribute = this.getDocumentType().getCustomEmailAttribute();
928 if (customEmailAttribute != null) {
929 customEmailAttribute.setRouteHeaderVO(DocumentRouteHeaderValue.to(this));
930 return customEmailAttribute;
931 }
932 }
933 } catch (Exception e) {
934 LOG.debug("Error in retrieving custom email attribute", e);
935 }
936 customEmailAttribute = new CustomEmailAttributeImpl();
937 customEmailAttribute.setRouteHeaderVO(DocumentRouteHeaderValue.to(this));
938 return customEmailAttribute;
939 }
940
941 public CustomNoteAttribute getCustomNoteAttribute() throws WorkflowException
942 {
943 CustomNoteAttribute customNoteAttribute = null;
944 try {
945 if (this.getDocumentType() != null) {
946 customNoteAttribute = this.getDocumentType().getCustomNoteAttribute();
947 if (customNoteAttribute != null) {
948 customNoteAttribute.setRouteHeaderVO(DocumentRouteHeaderValue.to(this));
949 return customNoteAttribute;
950 }
951 }
952 } catch (Exception e) {
953 LOG.debug("Error in retrieving custom note attribute", e);
954 }
955 customNoteAttribute = new CustomNoteAttributeImpl();
956 customNoteAttribute.setRouteHeaderVO(DocumentRouteHeaderValue.to(this));
957 return customNoteAttribute;
958 }
959
960 public ActionRequestValue getDocActionRequest(int index) {
961 List<ActionRequestValue> actionRequests = getActionRequests();
962 while (actionRequests.size() <= index) {
963 ActionRequestValue actionRequest = new ActionRequestFactory(this).createBlankActionRequest();
964 actionRequest.setNodeInstance(new RouteNodeInstance());
965 actionRequests.add(actionRequest);
966 }
967 return (ActionRequestValue) actionRequests.get(index);
968 }
969
970 public ActionTakenValue getDocActionTaken(int index) {
971 List<ActionTakenValue> actionsTaken = getActionsTaken();
972 while (actionsTaken.size() <= index) {
973 actionsTaken.add(new ActionTakenValue());
974 }
975 return (ActionTakenValue) actionsTaken.get(index);
976 }
977
978 public ActionItem getDocActionItem(int index) {
979 List<ActionItem> actionItems = getActionItems();
980 while (actionItems.size() <= index) {
981 actionItems.add(new ActionItem());
982 }
983 return (ActionItem) actionItems.get(index);
984 }
985
986 private RouteNodeInstance getInitialRouteNodeInstance(int index) {
987 if (initialRouteNodeInstances.size() >= index) {
988 return (RouteNodeInstance) initialRouteNodeInstances.get(index);
989 }
990 return null;
991 }
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007 public boolean isRoutingReport() {
1008 return routingReport;
1009 }
1010
1011 public void setRoutingReport(boolean routingReport) {
1012 this.routingReport = routingReport;
1013 }
1014
1015 public List<RouteNodeInstance> getInitialRouteNodeInstances() {
1016 return initialRouteNodeInstances;
1017 }
1018
1019 public void setInitialRouteNodeInstances(List<RouteNodeInstance> initialRouteNodeInstances) {
1020 this.initialRouteNodeInstances = initialRouteNodeInstances;
1021 }
1022
1023 public List<Note> getNotes() {
1024 return notes;
1025 }
1026
1027 public void setNotes(List<Note> notes) {
1028 this.notes = notes;
1029 }
1030
1031 public DocumentRouteHeaderValueContent getDocumentContent() {
1032 if (documentContent == null) {
1033 documentContent = KEWServiceLocator.getRouteHeaderService().getContent(getDocumentId());
1034 }
1035 return documentContent;
1036 }
1037
1038 public void setDocumentContent(DocumentRouteHeaderValueContent documentContent) {
1039 this.documentContent = documentContent;
1040 }
1041
1042 public List<DocumentStatusTransition> getAppDocStatusHistory() {
1043 return this.appDocStatusHistory;
1044 }
1045
1046 public void setAppDocStatusHistory(
1047 List<DocumentStatusTransition> appDocStatusHistory) {
1048 this.appDocStatusHistory = appDocStatusHistory;
1049 }
1050
1051 @Override
1052 public DocumentStatus getStatus() {
1053 return DocumentStatus.fromCode(getDocRouteStatus());
1054 }
1055
1056 @Override
1057 public DateTime getDateCreated() {
1058 if (getCreateDate() == null) {
1059 return null;
1060 }
1061 return new DateTime(getCreateDate().getTime());
1062 }
1063
1064 @Override
1065 public DateTime getDateLastModified() {
1066 if (getDateModified() == null) {
1067 return null;
1068 }
1069 return new DateTime(getDateModified().getTime());
1070 }
1071
1072 @Override
1073 public DateTime getDateApproved() {
1074 if (getApprovedDate() == null) {
1075 return null;
1076 }
1077 return new DateTime(getApprovedDate().getTime());
1078 }
1079
1080 @Override
1081 public DateTime getDateFinalized() {
1082 if (getFinalizedDate() == null) {
1083 return null;
1084 }
1085 return new DateTime(getFinalizedDate().getTime());
1086 }
1087
1088 @Override
1089 public String getTitle() {
1090 return docTitle;
1091 }
1092
1093 @Override
1094 public String getApplicationDocumentId() {
1095 return appDocId;
1096 }
1097
1098 @Override
1099 public String getInitiatorPrincipalId() {
1100 return initiatorWorkflowId;
1101 }
1102
1103 @Override
1104 public String getRoutedByPrincipalId() {
1105 return routedByUserWorkflowId;
1106 }
1107
1108 @Override
1109 public String getDocumentTypeName() {
1110 return getDocumentType().getName();
1111 }
1112
1113 @Override
1114 public String getDocumentHandlerUrl() {
1115 return getDocumentType().getResolvedDocumentHandlerUrl();
1116 }
1117
1118 @Override
1119 public String getApplicationDocumentStatus() {
1120 return appDocStatus;
1121 }
1122
1123 @Override
1124 public DateTime getApplicationDocumentStatusDate() {
1125 if (appDocStatusDate == null) {
1126 return null;
1127 }
1128 return new DateTime(appDocStatusDate.getTime());
1129 }
1130
1131 @Override
1132 public Map<String, String> getVariables() {
1133 Map<String, String> documentVariables = new HashMap<String, String>();
1134
1135
1136 Branch routeNodeInstanceBranch = getRootBranch();
1137
1138
1139 if (routeNodeInstanceBranch != null) {
1140 List<BranchState> listOfBranchStates = routeNodeInstanceBranch.getBranchState();
1141 for (BranchState bs : listOfBranchStates) {
1142 if (bs.getKey() != null && bs.getKey().startsWith(BranchState.VARIABLE_PREFIX)) {
1143 LOG.debug("Setting branch state variable on vo: " + bs.getKey() + "=" + bs.getValue());
1144 documentVariables.put(bs.getKey().substring(BranchState.VARIABLE_PREFIX.length()), bs.getValue());
1145 }
1146 }
1147 }
1148 return documentVariables;
1149 }
1150
1151 public static Document to(DocumentRouteHeaderValue documentBo) {
1152 if (documentBo == null) {
1153 return null;
1154 }
1155 Document.Builder builder = Document.Builder.create(documentBo);
1156 return builder.build();
1157 }
1158
1159 public static DocumentRouteHeaderValue from(Document document) {
1160 DocumentRouteHeaderValue documentBo = new DocumentRouteHeaderValue();
1161 documentBo.setAppDocId(document.getApplicationDocumentId());
1162 if (document.getDateApproved() != null) {
1163 documentBo.setApprovedDate(new Timestamp(document.getDateApproved().getMillis()));
1164 }
1165 if (document.getDateCreated() != null) {
1166 documentBo.setCreateDate(new Timestamp(document.getDateCreated().getMillis()));
1167 }
1168 if (StringUtils.isEmpty(documentBo.getDocContent())) {
1169 documentBo.setDocContent(KewApiConstants.DEFAULT_DOCUMENT_CONTENT);
1170 }
1171 documentBo.setDocRouteStatus(document.getStatus().getCode());
1172 documentBo.setDocTitle(document.getTitle());
1173 if (document.getDocumentTypeName() != null) {
1174 DocumentType documentType = KEWServiceLocator.getDocumentTypeService().findByName(document.getDocumentTypeName());
1175 if (documentType == null) {
1176 throw new RiceRuntimeException("Could not locate the given document type name: " + document.getDocumentTypeName());
1177 }
1178 documentBo.setDocumentTypeId(documentType.getDocumentTypeId());
1179 }
1180 if (document.getDateFinalized() != null) {
1181 documentBo.setFinalizedDate(new Timestamp(document.getDateFinalized().getMillis()));
1182 }
1183 documentBo.setInitiatorWorkflowId(document.getInitiatorPrincipalId());
1184 documentBo.setRoutedByUserWorkflowId(document.getRoutedByPrincipalId());
1185 documentBo.setDocumentId(document.getDocumentId());
1186 if (document.getDateLastModified() != null) {
1187 documentBo.setDateModified(new Timestamp(document.getDateLastModified().getMillis()));
1188 }
1189 documentBo.setAppDocStatus(document.getApplicationDocumentStatus());
1190 if (document.getApplicationDocumentStatusDate() != null) {
1191 documentBo.setAppDocStatusDate(new Timestamp(document.getApplicationDocumentStatusDate().getMillis()));
1192 }
1193
1194
1195
1196 Map<String, String> variables = document.getVariables();
1197 if( variables != null && !variables.isEmpty()){
1198 for(Map.Entry<String, String> kvp : variables.entrySet()){
1199 documentBo.setVariable(kvp.getKey(), kvp.getValue());
1200 }
1201 }
1202
1203 return documentBo;
1204 }
1205
1206 }