View Javadoc

1   /**
2    * Copyright 2005-2011 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.kns.web.struts.form;
17  
18  import org.apache.commons.lang.StringUtils;
19  import org.apache.struts.action.ActionErrors;
20  import org.apache.struts.action.ActionMapping;
21  import org.apache.struts.upload.FormFile;
22  import org.kuali.rice.core.api.CoreApiServiceLocator;
23  import org.kuali.rice.core.api.util.RiceKeyConstants;
24  import org.kuali.rice.core.framework.services.CoreFrameworkServiceLocator;
25  import org.kuali.rice.core.web.format.NoOpStringFormatter;
26  import org.kuali.rice.core.web.format.TimestampAMPMFormatter;
27  import org.kuali.rice.kew.api.WorkflowDocument;
28  import org.kuali.rice.kew.api.exception.WorkflowException;
29  import org.kuali.rice.kim.api.KimConstants;
30  import org.kuali.rice.kim.api.identity.Person;
31  import org.kuali.rice.kim.api.services.KimApiServiceLocator;
32  import org.kuali.rice.kns.datadictionary.HeaderNavigation;
33  import org.kuali.rice.kns.datadictionary.KNSDocumentEntry;
34  import org.kuali.rice.kns.util.WebUtils;
35  import org.kuali.rice.kns.web.derivedvaluesetter.DerivedValuesSetter;
36  import org.kuali.rice.kns.web.ui.HeaderField;
37  import org.kuali.rice.krad.bo.AdHocRoutePerson;
38  import org.kuali.rice.krad.bo.AdHocRouteWorkgroup;
39  import org.kuali.rice.krad.bo.Note;
40  import org.kuali.rice.krad.datadictionary.DataDictionary;
41  import org.kuali.rice.krad.document.Document;
42  import org.kuali.rice.krad.service.KRADServiceLocator;
43  import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
44  import org.kuali.rice.krad.service.ModuleService;
45  import org.kuali.rice.krad.service.SessionDocumentService;
46  import org.kuali.rice.krad.util.GlobalVariables;
47  import org.kuali.rice.krad.util.KRADConstants;
48  import org.kuali.rice.krad.util.MessageMap;
49  import org.kuali.rice.krad.util.ObjectUtils;
50  import org.kuali.rice.krad.util.UrlFactory;
51  import org.springframework.util.AutoPopulatingList;
52  
53  import javax.servlet.http.HttpServletRequest;
54  import java.io.Serializable;
55  import java.util.ArrayList;
56  import java.util.HashMap;
57  import java.util.List;
58  import java.util.Map;
59  import java.util.Properties;
60  
61  /**
62   * TODO we should not be referencing kew constants from this class and wedding ourselves to that workflow application This class is
63   * the base action form for all documents.
64   */
65  public abstract class KualiDocumentFormBase extends KualiForm implements Serializable {
66      private static final long serialVersionUID = 916061016201941821L;
67  
68  	private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(KualiDocumentFormBase.class);
69  
70      private Document document;
71      private String annotation = "";
72      private String command;
73  
74      private String docId;
75      private String docTypeName;
76  
77      private List<String> additionalScriptFiles;
78  
79      private AdHocRoutePerson newAdHocRoutePerson;
80      private AdHocRouteWorkgroup newAdHocRouteWorkgroup;
81  
82      private Note newNote;
83      
84      //TODO: is this still needed? I think it's obsolete now
85      private List boNotes;
86      
87      protected FormFile attachmentFile = new BlankFormFile();
88  
89      protected Map editingMode;
90      protected Map documentActions;
91      protected boolean suppressAllButtons;
92      
93      protected Map adHocActionRequestCodes;
94      private boolean returnToActionList;
95  
96      // for session enhancement
97      private String formKey;
98      private String docNum;
99      
100 
101     
102     /**
103      * Stores the error map from previous requests, so that we can continue to display error messages displayed during a previous request
104      */
105     private MessageMap errorMapFromPreviousRequest;
106     
107 	/***
108      * @see KualiForm#addRequiredNonEditableProperties()
109      */
110     @Override
111     public void addRequiredNonEditableProperties(){
112     	super.addRequiredNonEditableProperties();
113     	registerRequiredNonEditableProperty(KRADConstants.DOCUMENT_TYPE_NAME);
114     	registerRequiredNonEditableProperty(KRADConstants.FORM_KEY);
115     	registerRequiredNonEditableProperty(KRADConstants.NEW_NOTE_NOTE_TYPE_CODE);
116     }
117 
118 	/**
119 	 * @return the docNum
120 	 */
121 	public String getDocNum() {
122 		return this.docNum;
123 	}
124 
125 	/**
126 	 * @param docNum
127 	 *            the docNum to set
128 	 */
129 	public void setDocNum(String docNum) {
130 		this.docNum = docNum;
131 	}
132     
133     /**
134      * no args constructor that just initializes things for us
135      */
136     @SuppressWarnings("unchecked")
137 	public KualiDocumentFormBase() {
138         super();
139         
140         instantiateDocument();
141         newNote = new Note();
142         this.editingMode = new HashMap();
143         //this.additionalScriptFiles = new AutoPopulatingList(String.class);
144         this.additionalScriptFiles = new AutoPopulatingList<String>(String.class);
145 
146         // set the initial record for persons up
147         newAdHocRoutePerson = new AdHocRoutePerson();
148 
149         // set the initial record for workgroups up
150         newAdHocRouteWorkgroup = new AdHocRouteWorkgroup();
151 
152         // to make sure it posts back the correct time
153         setFormatterType("document.documentHeader.note.finDocNotePostedDttmStamp", TimestampAMPMFormatter.class);
154         setFormatterType("document.documentHeader.note.attachment.finDocNotePostedDttmStamp", TimestampAMPMFormatter.class);
155         //TODO: Chris - Notes: remove the above and change the below from boNotes when notes are finished
156         //overriding note formatter to make sure they post back the full timestamp
157         setFormatterType("document.documentHeader.boNote.notePostedTimestamp",TimestampAMPMFormatter.class);
158         setFormatterType("document.documentBusinessObject.boNote.notePostedTimestamp",TimestampAMPMFormatter.class);
159 
160         setFormatterType("editingMode", NoOpStringFormatter.class);
161         setFormatterType("editableAccounts", NoOpStringFormatter.class);
162 
163         setDocumentActions(new HashMap());
164         suppressAllButtons = false;
165         
166         initializeHeaderNavigationTabs();
167     }
168 
169     /**
170      * Setup workflow doc in the document.
171      */
172     @Override
173     public void populate(HttpServletRequest request) {
174         super.populate(request);
175 
176         WorkflowDocument workflowDocument = null;
177 
178         if (hasDocumentId()) {
179             // populate workflowDocument in documentHeader, if needed
180         	// KULRICE-4444 Obtain Document Header using the Workflow Service to minimize overhead
181             try {
182                 SessionDocumentService sessionDocumentService = KRADServiceLocatorWeb.getSessionDocumentService();
183             	workflowDocument = sessionDocumentService.getDocumentFromSession( GlobalVariables.getUserSession(), getDocument().getDocumentNumber());
184          	 	if ( workflowDocument == null)
185          	 	{
186                     // gets the workflow document from doc service, doc service will also set the workflow document in the
187                     // user's session
188          	 		Person person = KimApiServiceLocator.getPersonService().getPersonByPrincipalName(KRADConstants.SYSTEM_USER);
189          	 		workflowDocument = KRADServiceLocatorWeb.getWorkflowDocumentService().loadWorkflowDocument(getDocument().getDocumentNumber(), person);
190          	 	 	sessionDocumentService.addDocumentToUserSession(GlobalVariables.getUserSession(), workflowDocument);
191          	 	 	if (workflowDocument == null)
192          	 	 	{
193          	 	 		throw new WorkflowException("Unable to retrieve workflow document # " + getDocument().getDocumentNumber() + " from workflow document service createWorkflowDocument");
194          	 	 	}
195          	 	 	else
196          	 	 	{
197          	 	 	LOG.debug("Retrieved workflow Document ID: " + workflowDocument.getDocumentId());
198          	 	 	}
199          	 	}
200 
201                 getDocument().getDocumentHeader().setWorkflowDocument(workflowDocument);
202             } catch (WorkflowException e) {
203                 LOG.warn("Error while instantiating workflowDoc", e);
204                 throw new RuntimeException("error populating documentHeader.workflowDocument", e);
205             }
206         } 
207         if (workflowDocument != null) {
208 	        //Populate Document Header attributes
209 	        populateHeaderFields(workflowDocument);
210         }
211     }
212     
213     protected String getPersonInquiryUrlLink(Person user, String linkBody) {
214         StringBuffer urlBuffer = new StringBuffer();
215         
216         if(user != null && StringUtils.isNotEmpty(linkBody) ) {
217         	ModuleService moduleService = KRADServiceLocatorWeb.getKualiModuleService().getResponsibleModuleService(Person.class);
218         	Map<String, String[]> parameters = new HashMap<String, String[]>();
219         	parameters.put(KimConstants.AttributeConstants.PRINCIPAL_ID, new String[] { user.getPrincipalId() });
220         	String inquiryUrl = moduleService.getExternalizableBusinessObjectInquiryUrl(Person.class, parameters);
221             if(!StringUtils.equals(KimConstants.EntityTypes.SYSTEM, user.getEntityTypeCode())){
222 	            urlBuffer.append("<a href='");
223 	            urlBuffer.append(inquiryUrl);
224 	            urlBuffer.append("' ");
225 	            urlBuffer.append("target='_blank'");
226 	            urlBuffer.append("title='Person Inquiry'>");
227 	            urlBuffer.append(linkBody);
228 	            urlBuffer.append("</a>");
229             } else{
230             	urlBuffer.append(linkBody);
231             }
232         }
233         
234         return urlBuffer.toString();
235     }
236     
237     protected String getDocumentHandlerUrl(String documentId) {
238         Properties parameters = new Properties();
239         parameters.put(KRADConstants.PARAMETER_DOC_ID, documentId);
240         parameters.put(KRADConstants.PARAMETER_COMMAND, KRADConstants.METHOD_DISPLAY_DOC_SEARCH_VIEW);
241         return UrlFactory.parameterizeUrl(
242                 KRADServiceLocator.getKualiConfigurationService().getPropertyValueAsString(
243                         KRADConstants.WORKFLOW_URL_KEY) + "/" + KRADConstants.DOC_HANDLER_ACTION, parameters);
244     }
245     
246     protected String buildHtmlLink(String url, String linkBody) {
247         StringBuffer urlBuffer = new StringBuffer();
248         
249         if(StringUtils.isNotEmpty(url) && StringUtils.isNotEmpty(linkBody) ) {
250             urlBuffer.append("<a href='").append(url).append("'>").append(linkBody).append("</a>");
251         }
252         
253         return urlBuffer.toString();
254     }
255     
256     /**
257 	 * This method is used to populate the list of header field objects (see {@link KualiForm#getDocInfo()}) displayed on
258 	 * the Kuali document form display pages.
259 	 * 
260 	 * @param workflowDocument - the workflow document of the document being displayed (null is allowed)
261 	 */
262 	public void populateHeaderFields(WorkflowDocument workflowDocument) {
263 		getDocInfo().clear();
264 		getDocInfo().addAll(getStandardHeaderFields(workflowDocument));
265 	}
266 
267 	/**
268 	 * This method returns a list of {@link HeaderField} objects that are used by default on Kuali document display pages. To
269 	 * use this list and override an individual {@link HeaderField} object the id constants from
270 	 * {@link org.kuali.rice.krad.util.KRADConstants.DocumentFormHeaderFieldIds} can be used to identify items from the list.
271 	 * 
272 	 * @param workflowDocument - the workflow document of the document being displayed (null is allowed)
273 	 * @return a list of the standard fields displayed by default for all Kuali documents
274 	 */
275     protected List<HeaderField> getStandardHeaderFields(WorkflowDocument workflowDocument) {
276     	List<HeaderField> headerFields = new ArrayList<HeaderField>();
277     	setNumColumns(2);
278     	// check for a document template number as that will dictate column numbering
279     	HeaderField docTemplateNumber = null;
280         if ((ObjectUtils.isNotNull(getDocument())) && (ObjectUtils.isNotNull(getDocument().getDocumentHeader())) && (StringUtils.isNotBlank(getDocument().getDocumentHeader().getDocumentTemplateNumber()))) {
281 			String templateDocumentNumber = getDocument().getDocumentHeader().getDocumentTemplateNumber();
282 			docTemplateNumber = new HeaderField(KRADConstants.DocumentFormHeaderFieldIds.DOCUMENT_TEMPLATE_NUMBER, "DataDictionary.DocumentHeader.attributes.documentTemplateNumber",
283 					templateDocumentNumber,	buildHtmlLink(getDocumentHandlerUrl(templateDocumentNumber), templateDocumentNumber));
284 		}
285         //Document Number    	
286         HeaderField docNumber = new HeaderField("DataDictionary.DocumentHeader.attributes.documentNumber", workflowDocument != null? getDocument().getDocumentNumber() : null);
287         docNumber.setId(KRADConstants.DocumentFormHeaderFieldIds.DOCUMENT_NUMBER);
288         HeaderField docStatus = new HeaderField("DataDictionary.AttributeReferenceDummy.attributes.workflowDocumentStatus", workflowDocument != null? workflowDocument.getStatus().getLabel() : null);
289         docStatus.setId(KRADConstants.DocumentFormHeaderFieldIds.DOCUMENT_WORKFLOW_STATUS);
290         String initiatorNetworkId = null;
291         Person user = null;
292     	if (workflowDocument != null) {
293        		if (getInitiator() == null) {
294     			LOG.warn("User Not Found while attempting to build inquiry link for document header fields");
295     		} else {
296     			user = getInitiator();
297     			initiatorNetworkId = getInitiator().getPrincipalName();
298     		}
299     	}
300         String inquiryUrl = getPersonInquiryUrlLink(user, workflowDocument != null? initiatorNetworkId:null);
301 
302         HeaderField docInitiator = new HeaderField(KRADConstants.DocumentFormHeaderFieldIds.DOCUMENT_INITIATOR, "DataDictionary.AttributeReferenceDummy.attributes.initiatorNetworkId",
303         workflowDocument != null? initiatorNetworkId : null, workflowDocument != null? inquiryUrl : null);
304         
305         String createDateStr = null;
306         if(workflowDocument != null && workflowDocument.getDateCreated() != null) {
307             createDateStr = CoreApiServiceLocator.getDateTimeService().toString(workflowDocument.getDateCreated().toDate(), "hh:mm a MM/dd/yyyy");
308         }
309         
310         HeaderField docCreateDate = new HeaderField("DataDictionary.AttributeReferenceDummy.attributes.createDate", createDateStr);
311         docCreateDate.setId(KRADConstants.DocumentFormHeaderFieldIds.DOCUMENT_CREATE_DATE);
312         if (ObjectUtils.isNotNull(docTemplateNumber)) {
313         	setNumColumns(3);
314         }
315         
316         headerFields.add(docNumber);
317         headerFields.add(docStatus);
318         if (ObjectUtils.isNotNull(docTemplateNumber)) {
319         	headerFields.add(docTemplateNumber);
320         }
321         headerFields.add(docInitiator);
322         headerFields.add(docCreateDate);
323         if (ObjectUtils.isNotNull(docTemplateNumber)) {
324         	// adding an empty field so implementors do not have to worry about additional fields being put on the wrong row
325         	headerFields.add(HeaderField.EMPTY_FIELD);
326         }
327     	return headerFields;
328     }    
329 
330     /**
331      * @see org.apache.struts.action.ActionForm#validate(org.apache.struts.action.ActionMapping,
332      *      javax.servlet.http.HttpServletRequest)
333      */
334     @Override
335     public ActionErrors validate(ActionMapping mapping, HttpServletRequest request) {
336         // check that annotation does not exceed 2000 characters
337         setAnnotation(StringUtils.stripToNull(getAnnotation()));
338         int diff = StringUtils.defaultString(getAnnotation()).length() - KRADConstants.DOCUMENT_ANNOTATION_MAX_LENGTH;
339         if (diff > 0) {
340             GlobalVariables.getMessageMap().putError("annotation", RiceKeyConstants.ERROR_DOCUMENT_ANNOTATION_MAX_LENGTH_EXCEEDED, new String[] { Integer.toString(KRADConstants.DOCUMENT_ANNOTATION_MAX_LENGTH), Integer.toString(diff) });
341         }
342         return super.validate(mapping, request);
343     }
344 
345     /**
346      * @return true if this document was properly initialized with a DocumentHeader and related KualiWorkflowDocument
347      */
348     final public boolean isFormDocumentInitialized() {
349         boolean initialized = false;
350 
351         if (document != null) {
352             if (document.getDocumentHeader() != null) {
353                 initialized = document.getDocumentHeader().hasWorkflowDocument();
354             }
355         }
356 
357         return initialized;
358     }
359 
360 
361     /**
362      * @return Map of editingModes for this document, as set during the most recent call to
363      *         populate(javax.servlet.http.HttpServletRequest)
364      */
365     @SuppressWarnings("unchecked")
366 	public Map getEditingMode() {
367         return editingMode;
368     }
369 
370     /**
371      * Set editingMode for this document
372      */
373     @SuppressWarnings("unchecked")
374 	public void setEditingMode(Map editingMode) {
375         this.editingMode = editingMode;
376     }
377     
378     /**
379 	 * @return the documentActions
380 	 */
381 	@SuppressWarnings("unchecked")
382 	public Map getDocumentActions() {
383 		return this.documentActions;
384 	}
385 
386 	/**
387 	 * @param documentActions the documentActions to set
388 	 */
389 	@SuppressWarnings("unchecked")
390 	public void setDocumentActions(Map documentActions) {
391 		this.documentActions = documentActions;
392 	}
393 	
394 	
395 
396 	/**
397 	 * @param adHocActionRequestCodes the adHocActionRequestCodes to set
398 	 */
399 	@SuppressWarnings("unchecked")
400 	public void setAdHocActionRequestCodes(Map adHocActionRequestCodes) {
401 		this.adHocActionRequestCodes = adHocActionRequestCodes;
402 	}
403 
404 	/**
405      * @return a map of the possible action request codes that takes into account the users context on the document
406      */
407     @SuppressWarnings("unchecked")
408 	public Map getAdHocActionRequestCodes() {
409         //Map adHocActionRequestCodes = new HashMap();
410         //KRADServiceLocatorInternal.getDocumentHelperService()
411         /*if (getWorkflowDocument() != null) {
412             if (getWorkflowDocument().isFYIRequested()) {
413                 adHocActionRequestCodes.put(KewApiConstants.ACTION_REQUEST_FYI_REQ, KewApiConstants.ACTION_REQUEST_FYI_REQ_LABEL);
414             }
415             else if (getWorkflowDocument().isAcknowledgeRequested()) {
416                 adHocActionRequestCodes.put(KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ_LABEL);
417                 adHocActionRequestCodes.put(KewApiConstants.ACTION_REQUEST_FYI_REQ, KewApiConstants.ACTION_REQUEST_FYI_REQ_LABEL);
418             }
419             else if (getWorkflowDocument().isApprovalRequested() || getWorkflowDocument().isCompletionRequested() || getWorkflowDocument().stateIsInitiated() || getWorkflowDocument().stateIsSaved()) {
420                 adHocActionRequestCodes.put(KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ, KewApiConstants.ACTION_REQUEST_ACKNOWLEDGE_REQ_LABEL);
421                 adHocActionRequestCodes.put(KewApiConstants.ACTION_REQUEST_FYI_REQ, KewApiConstants.ACTION_REQUEST_FYI_REQ_LABEL);
422                 adHocActionRequestCodes.put(KewApiConstants.ACTION_REQUEST_APPROVE_REQ, KewApiConstants.ACTION_REQUEST_APPROVE_REQ_LABEL);
423             }
424         }*/
425         return adHocActionRequestCodes;
426     }
427 
428 
429     /**
430      * @return the list of ad hoc routing persons
431      */
432     public List<AdHocRoutePerson> getAdHocRoutePersons() {
433         return document.getAdHocRoutePersons();
434     }
435 
436 
437     /**
438      * @return attachmentFile
439      */
440     public FormFile getAttachmentFile() {
441         return attachmentFile;
442     }
443 
444     /**
445      * @param attachmentFile The attachmentFile to set.
446      */
447     public void setAttachmentFile(FormFile attachmentFile) {
448         this.attachmentFile = attachmentFile;
449     }
450 
451 
452     /**
453      * set the ad hoc routing persons list
454      *
455      * @param adHocRouteRecipients
456      */
457     public void setAdHocRoutePersons(List<AdHocRoutePerson> adHocRouteRecipients) {
458         document.setAdHocRoutePersons(adHocRouteRecipients);
459     }
460 
461     /**
462      * get the ad hoc routing workgroup requests
463      *
464      * @return
465      */
466     public List<AdHocRouteWorkgroup> getAdHocRouteWorkgroups() {
467         return document.getAdHocRouteWorkgroups();
468     }
469 
470     /**
471      * set the ad hoc routing workgroup requests
472      *
473      * @param adHocRouteWorkgroups
474      */
475     public void setAdHocRouteWorkgroups(List<AdHocRouteWorkgroup> adHocRouteWorkgroups) {
476         document.setAdHocRouteWorkgroups(adHocRouteWorkgroups);
477     }
478 
479     /**
480      * Special getter based on index to work with multi rows for ad hoc routing to persons struts page
481      *
482      * @param index
483      * @return
484      */
485     public AdHocRoutePerson getAdHocRoutePerson(int index) {
486         while (getAdHocRoutePersons().size() <= index) {
487             getAdHocRoutePersons().add(new AdHocRoutePerson());
488         }
489         return getAdHocRoutePersons().get(index);
490     }
491 
492     /**
493      * Special getter based on index to work with multi rows for ad hoc routing to workgroups struts page
494      *
495      * @param index
496      * @return
497      */
498     public AdHocRouteWorkgroup getAdHocRouteWorkgroup(int index) {
499         while (getAdHocRouteWorkgroups().size() <= index) {
500             getAdHocRouteWorkgroups().add(new AdHocRouteWorkgroup());
501         }
502         return getAdHocRouteWorkgroups().get(index);
503     }
504 
505     /**
506      * @return the new ad hoc route person object
507      */
508     public AdHocRoutePerson getNewAdHocRoutePerson() {
509         return newAdHocRoutePerson;
510     }
511 
512     /**
513      * set the new ad hoc route person object
514      *
515      * @param newAdHocRoutePerson
516      */
517     public void setNewAdHocRoutePerson(AdHocRoutePerson newAdHocRoutePerson) {
518         this.newAdHocRoutePerson = newAdHocRoutePerson;
519     }
520 
521     /**
522      * @return the new ad hoc route workgroup object
523      */
524     public AdHocRouteWorkgroup getNewAdHocRouteWorkgroup() {
525         return newAdHocRouteWorkgroup;
526     }
527 
528     /**
529      * set the new ad hoc route workgroup object
530      *
531      * @param newAdHocRouteWorkgroup
532      */
533     public void setNewAdHocRouteWorkgroup(AdHocRouteWorkgroup newAdHocRouteWorkgroup) {
534         this.newAdHocRouteWorkgroup = newAdHocRouteWorkgroup;
535     }
536 
537     /**
538      * @return Returns the Document
539      */
540     public Document getDocument() {
541         return document;
542     }
543 
544     /**
545      * @param document
546      */
547     public void setDocument(Document document) {
548         this.document = document;
549         if(document != null && StringUtils.isNotEmpty(document.getDocumentNumber())) {
550             populateHeaderFields(document.getDocumentHeader().getWorkflowDocument());
551         }
552     }
553 
554     /**
555      * @return WorkflowDocument for this form's document
556      */
557     public WorkflowDocument getWorkflowDocument() {
558         return getDocument().getDocumentHeader().getWorkflowDocument();
559     }
560     
561     /**
562 	 *  Null-safe check to see if the workflow document object exists before attempting to retrieve it.
563      *  (Which, if called, will throw an exception.)
564 	 */
565     public boolean isHasWorkflowDocument() {
566     	if ( getDocument() == null || getDocument().getDocumentHeader() == null ) {
567     		return false;
568     	}
569     	return getDocument().getDocumentHeader().hasWorkflowDocument();
570     }
571 
572     /**
573      * TODO rk implemented to account for caps coming from kuali user service from workflow
574      */
575     public boolean isUserDocumentInitiator() {
576         if (getWorkflowDocument() != null) {
577             return getWorkflowDocument().getInitiatorPrincipalId().equalsIgnoreCase(
578             		GlobalVariables.getUserSession().getPrincipalId());
579         }
580         return false;
581     }
582 
583     public Person getInitiator() {
584     	String initiatorPrincipalId = getWorkflowDocument().getInitiatorPrincipalId();
585     	return KimApiServiceLocator.getPersonService().getPerson(initiatorPrincipalId);
586     }
587 
588     /**
589      * @return true if the workflowDocument associated with this form is currently enroute
590      */
591     public boolean isDocumentEnRoute() {
592         return getWorkflowDocument().isEnroute();
593     }
594 
595     /**
596      * @param annotation The annotation to set.
597      */
598     public void setAnnotation(String annotation) {
599         this.annotation = annotation;
600     }
601 
602     /**
603      * @return Returns the annotation.
604      */
605     public String getAnnotation() {
606         return annotation;
607     }
608 
609     /**
610      * @return returns the command that was passed from workflow
611      */
612     public String getCommand() {
613         return command;
614     }
615 
616     /**
617      * setter for the command that was passed from workflow on the url
618      *
619      * @param command
620      */
621     public void setCommand(String command) {
622         this.command = command;
623     }
624 
625     /**
626      * @return returns the docId that was passed from workflow on the url
627      */
628     public String getDocId() {
629         return docId;
630     }
631 
632     /**
633      * setter for the docId that was passed from workflow on the url
634      *
635      * @param docId
636      */
637     public void setDocId(String docId) {
638         this.docId = docId;
639     }
640 
641     /**
642      * getter for the docTypeName that was passed from workflow on the url
643      *
644      * @return
645      */
646     public String getDocTypeName() {
647         return docTypeName;
648     }
649 
650     /**
651      * setter for the docTypeName that was passed from workflow on the url
652      *
653      * @param docTypeName
654      */
655     public void setDocTypeName(String docTypeName) {
656         this.docTypeName = docTypeName;
657     }
658 
659     /**
660      * getter for convenience that will return the initiators network id
661      *
662      * @return
663      */
664     public String getInitiatorNetworkId() {
665         return this.getWorkflowDocument().getInitiatorPrincipalId();
666     }
667 
668     /**
669      * Gets the suppressAllButtons attribute.
670      *
671      * @return Returns the suppressAllButtons.
672      */
673     public final boolean isSuppressAllButtons() {
674         return suppressAllButtons;
675     }
676 
677     /**
678      * Sets the suppressAllButtons attribute value.
679      *
680      * @param suppressAllButtons The suppressAllButtons to set.
681      */
682     public final void setSuppressAllButtons(boolean suppressAllButtons) {
683         this.suppressAllButtons = suppressAllButtons;
684     }
685 
686     /**
687      * @return true if this form's getDocument() method returns a Document, and if that Document's getDocumentHeaderId method
688      *         returns a non-null
689      */
690     public boolean hasDocumentId() {
691         boolean hasDocId = false;
692 
693         Document d = getDocument();
694         if (d != null) {
695             String docHeaderId = d.getDocumentNumber();
696 
697             hasDocId = StringUtils.isNotBlank(docHeaderId);
698         }
699 
700         return hasDocId;
701     }
702 
703     /**
704      * Sets flag indicating whether upon completion of approve, blanketApprove, cancel, or disapprove, the user should be returned
705      * to the actionList instead of to the portal
706      *
707      * @param returnToActionList
708      */
709     public void setReturnToActionList(boolean returnToActionList) {
710         this.returnToActionList = returnToActionList;
711     }
712 
713     public boolean isReturnToActionList() {
714         return returnToActionList;
715     }
716 
717     public List<String> getAdditionalScriptFiles() {
718         return additionalScriptFiles;
719     }
720 
721     public void setAdditionalScriptFiles(List<String> additionalScriptFiles) {
722         this.additionalScriptFiles = additionalScriptFiles;
723     }
724 
725     public void setAdditionalScriptFile( int index, String scriptFile ) {
726         additionalScriptFiles.set( index, scriptFile );
727 	}
728 
729     public String getAdditionalScriptFile( int index ) {
730         return additionalScriptFiles.get( index );
731     }
732 
733     public Note getNewNote() {
734         return newNote;
735     }
736 
737     public void setNewNote(Note newNote) {
738         this.newNote = newNote;
739     }
740 
741     /**
742      * Gets the boNotes attribute. 
743      * @return Returns the boNotes.
744      */
745     @SuppressWarnings("unchecked")
746 	public List getBoNotes() {
747         return boNotes;
748     }
749 
750     /**
751      * Sets the boNotes attribute value.
752      * @param boNotes The boNotes to set.
753      */
754     @SuppressWarnings("unchecked")
755 	public void setBoNotes(List boNotes) {
756         this.boNotes = boNotes;
757     }
758 
759     public String getFormKey() {
760         return this.formKey;
761     }
762 
763     public void setFormKey(String formKey) {
764         this.formKey = formKey;
765     }
766 
767     /* Reset method
768      * This is initially created for session document implementation
769      * @param mapping
770      * @param request
771      */
772     @Override
773     public void reset(ActionMapping mapping, HttpServletRequest request) {
774     	super.reset(mapping, request);
775         this.setMethodToCall(null);
776         this.setRefreshCaller(null);
777         this.setAnchor(null);
778         this.setCurrentTabIndex(0);
779         
780     }
781 
782     
783     /**
784      * Adds the attachment file size to the list of max file sizes.
785      * 
786      * @see org.kuali.rice.krad.web.struts.pojo.PojoFormBase#customInitMaxUploadSizes()
787      */
788     @Override
789     protected void customInitMaxUploadSizes() {
790         super.customInitMaxUploadSizes();
791         addMaxUploadSize(CoreFrameworkServiceLocator.getParameterService().getParameterValueAsString(KRADConstants.KRAD_NAMESPACE, KRADConstants.DetailTypes.DOCUMENT_DETAIL_TYPE, KRADConstants.ATTACHMENT_MAX_FILE_SIZE_PARM_NM));
792     }
793 
794     
795     
796 	/**
797 	 * This overridden method ...
798 	 * IMPORTANT: any overrides of this method must ensure that nothing in the HTTP request will be used to determine whether document is in session 
799 	 * 
800 	 * @see org.kuali.rice.krad.web.struts.pojo.PojoFormBase#shouldPropertyBePopulatedInForm(java.lang.String, javax.servlet.http.HttpServletRequest)
801 	 */
802 	@Override
803 	public boolean shouldPropertyBePopulatedInForm(String requestParameterName, HttpServletRequest request) {
804 		for ( String prefix : KRADConstants.ALWAYS_VALID_PARAMETER_PREFIXES ) {
805 			if (requestParameterName.startsWith(prefix)) {
806 				return true;
807 			}
808 		}
809 
810 		if (StringUtils.equalsIgnoreCase(getMethodToCall(), KRADConstants.DOC_HANDLER_METHOD)) {
811 			return true;
812 		}
813 		if (WebUtils.isDocumentSession(getDocument(), this)) {
814 			return isPropertyEditable(requestParameterName) || isPropertyNonEditableButRequired(requestParameterName);
815 		}
816 		return true;
817 	}
818 
819 	/**
820 	 * This overridden method ...
821 	 * 
822 	 * @see KualiForm#shouldMethodToCallParameterBeUsed(java.lang.String, java.lang.String, javax.servlet.http.HttpServletRequest)
823 	 */
824 	@Override
825 	public boolean shouldMethodToCallParameterBeUsed(
826 			String methodToCallParameterName,
827 			String methodToCallParameterValue, HttpServletRequest request) {
828 		if (StringUtils.equals(methodToCallParameterName, KRADConstants.DISPATCH_REQUEST_PARAMETER) &&
829 				StringUtils.equals(methodToCallParameterValue, KRADConstants.DOC_HANDLER_METHOD)) {
830 			return true;
831 		}
832 		return super.shouldMethodToCallParameterBeUsed(methodToCallParameterName,
833 				methodToCallParameterValue, request);
834 	}
835 	
836 	public MessageMap getMessageMapFromPreviousRequest() {
837 		return this.errorMapFromPreviousRequest;
838 	}
839 	
840 	public void setMessageMapFromPreviousRequest(MessageMap errorMapFromPreviousRequest) {
841 		this.errorMapFromPreviousRequest = errorMapFromPreviousRequest;
842 	}
843 	
844 	@Override
845 	public void setDerivedValuesOnForm(HttpServletRequest request) {
846 		super.setDerivedValuesOnForm(request);
847 
848 		String docTypeName = getDocTypeName();
849 		if (StringUtils.isNotBlank(docTypeName)) {
850 			DataDictionary dataDictionary = KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary();
851 
852             Class<? extends DerivedValuesSetter> derivedValuesSetterClass = null;
853             KNSDocumentEntry documentEntry = (KNSDocumentEntry) dataDictionary.getDocumentEntry(docTypeName);
854             derivedValuesSetterClass = (documentEntry).getDerivedValuesSetterClass();
855 
856 			if (derivedValuesSetterClass != null) {
857 				DerivedValuesSetter derivedValuesSetter = null;
858 				try {
859 					derivedValuesSetter = derivedValuesSetterClass.newInstance();
860 				}
861 
862 				catch (Exception e) {
863 					LOG.error("Unable to instantiate class " + derivedValuesSetterClass.getName(), e);
864 					throw new RuntimeException("Unable to instantiate class " + derivedValuesSetterClass.getName(), e);
865 				}
866 				derivedValuesSetter.setDerivedValues(this, request);
867 			}
868 		}
869 	}
870 	
871 	protected String getDefaultDocumentTypeName() {
872 		return "";
873 	}
874 	
875 	/** will instatiate a new document setting it on the form if {@link KualiDocumentFormBase#getDefaultDocumentTypeName()} is overriden to return a valid value. */
876 	protected void instantiateDocument() {
877 		if (document == null && StringUtils.isNotBlank(getDefaultDocumentTypeName())) {
878 			Class<? extends Document> documentClass = getDocumentClass();
879 			try {
880 				Document document = documentClass.newInstance();
881 				setDocument(document);
882 			} catch (Exception e) {
883 				LOG.error("Unable to instantiate document class " + documentClass.getName() + " document type " + getDefaultDocumentTypeName());
884 				throw new RuntimeException(e);
885 			}
886 		}
887 	}
888 	
889 	/** gets the document class from the datadictionary if {@link KualiDocumentFormBase#getDefaultDocumentTypeName()} is overriden to return a valid value otherwise behavior is nondeterministic. */
890 	private Class<? extends Document> getDocumentClass() {
891 		return KRADServiceLocatorWeb.getDataDictionaryService().getDocumentClassByTypeName(getDefaultDocumentTypeName());
892 	}
893 	
894 	/**initializes the header tabs from what is defined in the datadictionary if {@link KualiDocumentFormBase#getDefaultDocumentTypeName()} is overriden to return a valid value. */
895     protected void initializeHeaderNavigationTabs() {
896     	if (StringUtils.isNotBlank(getDefaultDocumentTypeName())) {
897     		final KNSDocumentEntry docEntry = (KNSDocumentEntry) KRADServiceLocatorWeb.getDataDictionaryService().getDataDictionary().getDocumentEntry(getDocumentClass().getName());
898     		final List<HeaderNavigation> navList = docEntry.getHeaderNavigationList();
899     		final HeaderNavigation[] list = new HeaderNavigation[navList.size()];
900     		super.setHeaderNavigationTabs(navList.toArray(list));
901     	}
902     } 
903 }