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