1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.web.controller;
17
18 import org.apache.commons.lang.ArrayUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.kuali.rice.core.api.config.property.ConfigurationService;
21 import org.kuali.rice.core.api.exception.RiceRuntimeException;
22 import org.kuali.rice.core.api.util.RiceKeyConstants;
23 import org.kuali.rice.kew.api.KewApiConstants;
24 import org.kuali.rice.kew.api.WorkflowDocument;
25 import org.kuali.rice.kew.api.exception.WorkflowException;
26 import org.kuali.rice.kim.api.identity.Person;
27 import org.kuali.rice.krad.bo.AdHocRouteRecipient;
28 import org.kuali.rice.krad.bo.Attachment;
29 import org.kuali.rice.krad.bo.DocumentHeader;
30 import org.kuali.rice.krad.bo.Note;
31 import org.kuali.rice.krad.document.Document;
32 import org.kuali.rice.krad.document.DocumentAuthorizer;
33 import org.kuali.rice.krad.maintenance.MaintenanceDocument;
34 import org.kuali.rice.krad.exception.DocumentAuthorizationException;
35 import org.kuali.rice.krad.exception.UnknownDocumentIdException;
36 import org.kuali.rice.krad.exception.ValidationException;
37 import org.kuali.rice.krad.rules.rule.event.AddNoteEvent;
38 import org.kuali.rice.krad.service.AttachmentService;
39 import org.kuali.rice.krad.service.BusinessObjectService;
40 import org.kuali.rice.krad.service.DataDictionaryService;
41 import org.kuali.rice.krad.service.DocumentDictionaryService;
42 import org.kuali.rice.krad.service.DocumentService;
43 import org.kuali.rice.krad.service.KRADServiceLocator;
44 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
45 import org.kuali.rice.krad.service.NoteService;
46 import org.kuali.rice.krad.uif.UifConstants.WorkflowAction;
47 import org.kuali.rice.krad.uif.UifParameters;
48 import org.kuali.rice.krad.uif.UifPropertyPaths;
49 import org.kuali.rice.krad.uif.container.CollectionGroup;
50 import org.kuali.rice.krad.uif.util.ObjectPropertyUtils;
51 import org.kuali.rice.krad.util.GlobalVariables;
52 import org.kuali.rice.krad.util.KRADConstants;
53 import org.kuali.rice.krad.util.NoteType;
54 import org.kuali.rice.krad.web.form.DocumentFormBase;
55 import org.kuali.rice.krad.web.form.UifFormBase;
56 import org.springframework.util.FileCopyUtils;
57 import org.springframework.validation.BindingResult;
58 import org.springframework.web.bind.ServletRequestBindingException;
59 import org.springframework.web.bind.annotation.ModelAttribute;
60 import org.springframework.web.bind.annotation.RequestMapping;
61 import org.springframework.web.bind.annotation.RequestMethod;
62 import org.springframework.web.multipart.MultipartFile;
63 import org.springframework.web.servlet.ModelAndView;
64
65 import javax.servlet.http.HttpServletRequest;
66 import javax.servlet.http.HttpServletResponse;
67 import java.io.FileNotFoundException;
68 import java.io.IOException;
69 import java.io.InputStream;
70 import java.util.ArrayList;
71 import java.util.List;
72 import java.util.Properties;
73
74
75
76
77
78
79
80
81
82
83
84
85 public abstract class DocumentControllerBase extends UifControllerBase {
86 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(DocumentControllerBase.class);
87
88
89
90 protected static final String[] DOCUMENT_LOAD_COMMANDS =
91 {KewApiConstants.ACTIONLIST_COMMAND, KewApiConstants.DOCSEARCH_COMMAND, KewApiConstants.SUPERUSER_COMMAND,
92 KewApiConstants.HELPDESK_ACTIONLIST_COMMAND};
93
94 private BusinessObjectService businessObjectService;
95 private DataDictionaryService dataDictionaryService;
96 private DocumentService documentService;
97 private DocumentDictionaryService documentDictionaryService;
98 private AttachmentService attachmentService;
99 private NoteService noteService;
100
101
102
103
104 @Override
105 protected abstract DocumentFormBase createInitialForm(HttpServletRequest request);
106
107
108
109
110
111
112
113
114
115
116 @RequestMapping(params = "methodToCall=docHandler")
117 public ModelAndView docHandler(@ModelAttribute("KualiForm") DocumentFormBase form, BindingResult result,
118 HttpServletRequest request, HttpServletResponse response) throws Exception {
119 String command = form.getCommand();
120
121
122 if (ArrayUtils.contains(DOCUMENT_LOAD_COMMANDS, command) && form.getDocId() != null) {
123 loadDocument(form);
124 } else if (KewApiConstants.INITIATE_COMMAND.equals(command)) {
125 createDocument(form);
126 } else {
127 LOG.error("docHandler called with invalid parameters");
128 throw new IllegalStateException("docHandler called with invalid parameters");
129 }
130
131
132
133
134
135
136 return getUIFModelAndView(form);
137 }
138
139
140
141
142
143
144
145
146 protected void loadDocument(DocumentFormBase form) throws WorkflowException {
147 String docId = form.getDocId();
148
149 LOG.debug("Loading document" + docId);
150
151 Document doc = null;
152 doc = getDocumentService().getByDocumentHeaderId(docId);
153 if (doc == null) {
154 throw new UnknownDocumentIdException(
155 "Document no longer exists. It may have been cancelled before being saved.");
156 }
157
158 WorkflowDocument workflowDocument = doc.getDocumentHeader().getWorkflowDocument();
159 if (!getDocumentDictionaryService().getDocumentAuthorizer(doc).canOpen(doc,
160 GlobalVariables.getUserSession().getPerson())) {
161 throw buildAuthorizationException("open", doc);
162 }
163
164
165
166 if (workflowDocument != doc.getDocumentHeader().getWorkflowDocument()) {
167 LOG.warn("Workflow document changed via canOpen check");
168 doc.getDocumentHeader().setWorkflowDocument(workflowDocument);
169 }
170
171 form.setDocument(doc);
172 WorkflowDocument workflowDoc = doc.getDocumentHeader().getWorkflowDocument();
173 form.setDocTypeName(workflowDoc.getDocumentTypeName());
174
175 KRADServiceLocatorWeb.getSessionDocumentService().addDocumentToUserSession(GlobalVariables.getUserSession(),
176 workflowDoc);
177 }
178
179
180
181
182
183
184
185
186 protected void createDocument(DocumentFormBase form) throws WorkflowException {
187 LOG.debug("Creating new document instance for doc type: " + form.getDocTypeName());
188 Document doc = getDocumentService().getNewDocument(form.getDocTypeName());
189
190 form.setDocument(doc);
191 form.setDocTypeName(doc.getDocumentHeader().getWorkflowDocument().getDocumentTypeName());
192 }
193
194
195
196
197
198
199
200
201 @RequestMapping(params = "methodToCall=reload")
202 public ModelAndView reload(@ModelAttribute("KualiForm") DocumentFormBase form, BindingResult result,
203 HttpServletRequest request, HttpServletResponse response) throws Exception {
204 Document document = form.getDocument();
205
206
207 form.setDocId(document.getDocumentNumber());
208 form.setCommand(DOCUMENT_LOAD_COMMANDS[1]);
209
210 GlobalVariables.getMessageMap().putInfo(KRADConstants.GLOBAL_MESSAGES, RiceKeyConstants.MESSAGE_RELOADED);
211
212
213 return docHandler(form, result, request, response);
214 }
215
216
217
218
219
220
221
222
223 @RequestMapping(params = "methodToCall=cancel")
224 @Override
225 public ModelAndView cancel(@ModelAttribute("KualiForm") UifFormBase form, BindingResult result,
226 HttpServletRequest request, HttpServletResponse response) {
227 DocumentFormBase documentForm = (DocumentFormBase) form;
228
229
230
231 performWorkflowAction(documentForm, WorkflowAction.CANCEL, false);
232
233 return returnToPrevious(form);
234 }
235
236
237
238
239
240
241
242 @RequestMapping(params = "methodToCall=save")
243 public ModelAndView save(@ModelAttribute("KualiForm") DocumentFormBase form, BindingResult result,
244 HttpServletRequest request, HttpServletResponse response) throws Exception {
245 performWorkflowAction(form, WorkflowAction.SAVE, true);
246
247 return getUIFModelAndView(form);
248 }
249
250
251
252
253
254
255
256 @RequestMapping(params = "methodToCall=route")
257 public ModelAndView route(@ModelAttribute("KualiForm") DocumentFormBase form, BindingResult result,
258 HttpServletRequest request, HttpServletResponse response) {
259 performWorkflowAction(form, WorkflowAction.ROUTE, true);
260
261 return getUIFModelAndView(form);
262 }
263
264
265
266
267
268
269
270 @RequestMapping(params = "methodToCall=blanketApprove")
271 public ModelAndView blanketApprove(@ModelAttribute("KualiForm") DocumentFormBase form, BindingResult result,
272 HttpServletRequest request, HttpServletResponse response) throws Exception {
273 performWorkflowAction(form, WorkflowAction.BLANKETAPPROVE, true);
274
275 return returnToPrevious(form);
276 }
277
278
279
280
281
282
283
284 @RequestMapping(params = "methodToCall=approve")
285 public ModelAndView approve(@ModelAttribute("KualiForm") DocumentFormBase form, BindingResult result,
286 HttpServletRequest request, HttpServletResponse response) throws Exception {
287 performWorkflowAction(form, WorkflowAction.APPROVE, true);
288
289 return returnToPrevious(form);
290 }
291
292
293
294
295
296
297
298 @RequestMapping(params = "methodToCall=disapprove")
299 public ModelAndView disapprove(@ModelAttribute("KualiForm") DocumentFormBase form, BindingResult result,
300 HttpServletRequest request, HttpServletResponse response) throws Exception {
301
302 performWorkflowAction(form, WorkflowAction.DISAPPROVE, true);
303
304 return returnToPrevious(form);
305 }
306
307
308
309
310
311
312
313 @RequestMapping(params = "methodToCall=fyi")
314 public ModelAndView fyi(@ModelAttribute("KualiForm") DocumentFormBase form, BindingResult result,
315 HttpServletRequest request, HttpServletResponse response) throws Exception {
316 performWorkflowAction(form, WorkflowAction.FYI, false);
317
318 return returnToPrevious(form);
319 }
320
321
322
323
324
325
326
327 @RequestMapping(params = "methodToCall=acknowledge")
328 public ModelAndView acknowledge(@ModelAttribute("KualiForm") DocumentFormBase form, BindingResult result,
329 HttpServletRequest request, HttpServletResponse response) throws Exception {
330 performWorkflowAction(form, WorkflowAction.ACKNOWLEDGE, false);
331
332 return returnToPrevious(form);
333 }
334
335
336
337
338
339
340
341
342
343 protected void performWorkflowAction(DocumentFormBase form, WorkflowAction action, boolean checkSensitiveData) {
344 Document document = form.getDocument();
345
346 LOG.debug("Performing workflow action " + action.name() + "for document: " + document.getDocumentNumber());
347
348
349 if (checkSensitiveData) {
350
351
352
353
354
355 }
356
357 try {
358 String successMessageKey = null;
359 switch (action) {
360 case SAVE:
361 getDocumentService().saveDocument(document);
362 successMessageKey = RiceKeyConstants.MESSAGE_SAVED;
363 break;
364 case ROUTE:
365 getDocumentService().routeDocument(document, form.getAnnotation(), combineAdHocRecipients(form));
366 successMessageKey = RiceKeyConstants.MESSAGE_ROUTE_SUCCESSFUL;
367 break;
368 case BLANKETAPPROVE:
369 getDocumentService().blanketApproveDocument(document, form.getAnnotation(), combineAdHocRecipients(
370 form));
371 successMessageKey = RiceKeyConstants.MESSAGE_ROUTE_APPROVED;
372 break;
373 case APPROVE:
374 getDocumentService().approveDocument(document, form.getAnnotation(), combineAdHocRecipients(form));
375 successMessageKey = RiceKeyConstants.MESSAGE_ROUTE_APPROVED;
376 break;
377 case DISAPPROVE:
378
379 String disapprovalNoteText = "";
380 getDocumentService().disapproveDocument(document, disapprovalNoteText);
381 successMessageKey = RiceKeyConstants.MESSAGE_ROUTE_DISAPPROVED;
382 break;
383 case FYI:
384 getDocumentService().clearDocumentFyi(document, combineAdHocRecipients(form));
385 successMessageKey = RiceKeyConstants.MESSAGE_ROUTE_FYIED;
386 break;
387 case ACKNOWLEDGE:
388 getDocumentService().acknowledgeDocument(document, form.getAnnotation(), combineAdHocRecipients(
389 form));
390 successMessageKey = RiceKeyConstants.MESSAGE_ROUTE_ACKNOWLEDGED;
391 break;
392 case CANCEL:
393 if (getDocumentService().documentExists(document.getDocumentNumber())) {
394 getDocumentService().cancelDocument(document, form.getAnnotation());
395 successMessageKey = RiceKeyConstants.MESSAGE_CANCELLED;
396 }
397 break;
398 }
399
400 if (successMessageKey != null) {
401 GlobalVariables.getMessageMap().putInfo(KRADConstants.GLOBAL_MESSAGES, successMessageKey);
402 }
403 } catch (ValidationException e) {
404
405
406 if (GlobalVariables.getMessageMap().hasNoErrors()) {
407 throw new RiceRuntimeException("Validation Exception with no error message.", e);
408 }
409 } catch (Exception e) {
410 throw new RiceRuntimeException(
411 "Exception trying to invoke action " + action.name() + "for document: " + document
412 .getDocumentNumber(), e);
413 }
414
415 form.setAnnotation("");
416 }
417
418
419
420
421
422
423 @RequestMapping(params = "methodToCall=supervisorFunctions")
424 public ModelAndView supervisorFunctions(@ModelAttribute("KualiForm") DocumentFormBase form, BindingResult result,
425 HttpServletRequest request, HttpServletResponse response) throws Exception {
426
427 String workflowSuperUserUrl = getConfigurationService().getPropertyValueAsString(KRADConstants.WORKFLOW_URL_KEY)
428 + "/" + KRADConstants.SUPERUSER_ACTION;
429
430 Properties props = new Properties();
431 props.put(UifParameters.METHOD_TO_CALL, "displaySuperUserDocument");
432 props.put(UifPropertyPaths.DOCUMENT_ID, form.getDocument().getDocumentNumber());
433
434 return performRedirect(form, workflowSuperUserUrl, props);
435 }
436
437
438
439
440
441
442
443
444 @RequestMapping(method = RequestMethod.POST, params = "methodToCall=insertNote")
445 public ModelAndView insertNote(@ModelAttribute("KualiForm") UifFormBase uifForm, BindingResult result,
446 HttpServletRequest request, HttpServletResponse response) {
447
448
449 String selectedCollectionPath = uifForm.getActionParamaterValue(UifParameters.SELLECTED_COLLECTION_PATH);
450 CollectionGroup collectionGroup = uifForm.getPostedView().getViewIndex().getCollectionGroupByPath(
451 selectedCollectionPath);
452 String addLinePath = collectionGroup.getAddLineBindingInfo().getBindingPath();
453 Object addLine = ObjectPropertyUtils.getPropertyValue(uifForm, addLinePath);
454 Note newNote = (Note) addLine;
455 newNote.setNotePostedTimestampToCurrent();
456
457 Document document = ((DocumentFormBase) uifForm).getDocument();
458
459 newNote.setRemoteObjectIdentifier(document.getNoteTarget().getObjectId());
460
461
462 String attachmentTypeCode = null;
463 MultipartFile attachmentFile = uifForm.getAttachmentFile();
464 Attachment attachment = null;
465 if (attachmentFile != null && !StringUtils.isBlank(attachmentFile.getOriginalFilename())) {
466 if (attachmentFile.getSize() == 0) {
467 GlobalVariables.getMessageMap().putError(String.format("%s.%s",
468 KRADConstants.NEW_DOCUMENT_NOTE_PROPERTY_NAME,
469 KRADConstants.NOTE_ATTACHMENT_FILE_PROPERTY_NAME), RiceKeyConstants.ERROR_UPLOADFILE_EMPTY,
470 attachmentFile.getOriginalFilename());
471 } else {
472 if (newNote.getAttachment() != null) {
473 attachmentTypeCode = newNote.getAttachment().getAttachmentTypeCode();
474 }
475
476 DocumentAuthorizer documentAuthorizer = getDocumentDictionaryService().getDocumentAuthorizer(document);
477 if (!documentAuthorizer.canAddNoteAttachment(document, attachmentTypeCode,
478 GlobalVariables.getUserSession().getPerson())) {
479 throw buildAuthorizationException("annotate", document);
480 }
481
482 try {
483 String attachmentType = null;
484 Attachment newAttachment = newNote.getAttachment();
485 if (newAttachment != null) {
486 attachmentType = newAttachment.getAttachmentTypeCode();
487 }
488
489 attachment = getAttachmentService().createAttachment(document.getNoteTarget(),
490 attachmentFile.getOriginalFilename(), attachmentFile.getContentType(),
491 (int) attachmentFile.getSize(), attachmentFile.getInputStream(), attachmentType);
492 } catch (IOException e) {
493 throw new RiceRuntimeException("Unable to store attachment", e);
494 }
495 }
496 }
497
498 Person kualiUser = GlobalVariables.getUserSession().getPerson();
499 if (kualiUser == null) {
500 throw new IllegalStateException("Current UserSession has a null Person.");
501 }
502
503 newNote.setAuthorUniversalIdentifier(kualiUser.getPrincipalId());
504
505
506 boolean rulePassed = KRADServiceLocatorWeb.getKualiRuleService().applyRules(new AddNoteEvent(document,
507 newNote));
508
509
510 if (rulePassed) {
511 newNote.refresh();
512
513 DocumentHeader documentHeader = document.getDocumentHeader();
514
515
516
517
518 if (attachment != null) {
519 newNote.addAttachment(attachment);
520 }
521
522 if (!documentHeader.getWorkflowDocument().isInitiated() && StringUtils.isNotEmpty(
523 document.getNoteTarget().getObjectId()) && !(document instanceof MaintenanceDocument && NoteType
524 .BUSINESS_OBJECT.getCode().equals(newNote.getNoteTypeCode()))) {
525
526 getNoteService().save(newNote);
527 }
528
529 }
530
531 return addLine(uifForm, result, request, response);
532 }
533
534
535
536
537
538
539 @RequestMapping(method = RequestMethod.POST, params = "methodToCall=deleteNote")
540 public ModelAndView deleteNote(@ModelAttribute("KualiForm") UifFormBase uifForm, BindingResult result,
541 HttpServletRequest request, HttpServletResponse response) {
542
543 String selectedLineIndex = uifForm.getActionParamaterValue("selectedLineIndex");
544 Document document = ((DocumentFormBase) uifForm).getDocument();
545 Note note = document.getNote(Integer.parseInt(selectedLineIndex));
546
547 Attachment attachment = note.getAttachment();
548 String attachmentTypeCode = null;
549 if (attachment != null) {
550 attachmentTypeCode = attachment.getAttachmentTypeCode();
551 }
552
553
554 Person user = GlobalVariables.getUserSession().getPerson();
555 String authorUniversalIdentifier = note.getAuthorUniversalIdentifier();
556 if (!getDocumentDictionaryService().getDocumentAuthorizer(document).canDeleteNoteAttachment(document,
557 attachmentTypeCode, authorUniversalIdentifier, user)) {
558 throw buildAuthorizationException("annotate", document);
559 }
560
561 if (attachment != null && attachment.isComplete()) {
562
563
564
565 if (note.getNoteIdentifier()
566 != null) {
567 attachment.refreshNonUpdateableReferences();
568 }
569 getAttachmentService().deleteAttachmentContents(attachment);
570 }
571
572 if (!document.getDocumentHeader().getWorkflowDocument().isInitiated()) {
573 getNoteService().deleteNote(note);
574 }
575
576 return deleteLine(uifForm, result, request, response);
577 }
578
579
580
581
582
583
584 @RequestMapping(method = RequestMethod.POST, params = "methodToCall=downloadAttachment")
585 public ModelAndView downloadAttachment(@ModelAttribute("KualiForm") UifFormBase uifForm, BindingResult result,
586 HttpServletRequest request,
587 HttpServletResponse response) throws ServletRequestBindingException, FileNotFoundException, IOException {
588
589 String selectedLineIndex = uifForm.getActionParamaterValue("selectedLineIndex");
590 Note note = ((DocumentFormBase) uifForm).getDocument().getNote(Integer.parseInt(selectedLineIndex));
591 Attachment attachment = note.getAttachment();
592 InputStream is = getAttachmentService().retrieveAttachmentContents(attachment);
593
594
595 response.setContentType(attachment.getAttachmentMimeTypeCode());
596 response.setContentLength(attachment.getAttachmentFileSize().intValue());
597 response.setHeader("Expires", "0");
598 response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
599 response.setHeader("Pragma", "public");
600 response.setHeader("Content-Disposition",
601 "attachment; filename=\"" + attachment.getAttachmentFileName() + "\"");
602
603
604 FileCopyUtils.copy(is, response.getOutputStream());
605 return null;
606 }
607
608
609
610
611
612 @RequestMapping(method = RequestMethod.POST, params = "methodToCall=cancelAttachment")
613 public ModelAndView cancelAttachment(@ModelAttribute("KualiForm") UifFormBase uifForm, BindingResult result,
614 HttpServletRequest request, HttpServletResponse response) {
615
616 uifForm.setAttachmentFile(null);
617 return getUIFModelAndView(uifForm);
618 }
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637 protected String checkAndWarnAboutSensitiveData(DocumentFormBase form, HttpServletRequest request,
638 HttpServletResponse response, String fieldName, String fieldValue, String caller,
639 String context) throws Exception {
640
641 String viewName = null;
642 Document document = form.getDocument();
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697 return viewName;
698 }
699
700
701
702
703
704
705
706
707 protected List<AdHocRouteRecipient> combineAdHocRecipients(DocumentFormBase form) {
708 Document document = form.getDocument();
709
710 List<AdHocRouteRecipient> adHocRecipients = new ArrayList<AdHocRouteRecipient>();
711 adHocRecipients.addAll(document.getAdHocRoutePersons());
712 adHocRecipients.addAll(document.getAdHocRouteWorkgroups());
713
714 return adHocRecipients;
715 }
716
717
718
719
720
721
722
723 protected DocumentAuthorizationException buildAuthorizationException(String action, Document document) {
724 return new DocumentAuthorizationException(GlobalVariables.getUserSession().getPerson().getPrincipalName(),
725 action, document.getDocumentNumber());
726 }
727
728 public BusinessObjectService getBusinessObjectService() {
729 if (this.businessObjectService == null) {
730 this.businessObjectService = KRADServiceLocator.getBusinessObjectService();
731 }
732 return this.businessObjectService;
733 }
734
735 public void setBusinessObjectService(BusinessObjectService businessObjectService) {
736 this.businessObjectService = businessObjectService;
737 }
738
739 public DataDictionaryService getDataDictionaryService() {
740 if (this.dataDictionaryService == null) {
741 this.dataDictionaryService = KRADServiceLocatorWeb.getDataDictionaryService();
742 }
743 return this.dataDictionaryService;
744 }
745
746 public void setDataDictionaryService(DataDictionaryService dataDictionaryService) {
747 this.dataDictionaryService = dataDictionaryService;
748 }
749
750 public DocumentService getDocumentService() {
751 if (this.documentService == null) {
752 this.documentService = KRADServiceLocatorWeb.getDocumentService();
753 }
754 return this.documentService;
755 }
756
757 public void setDocumentService(DocumentService documentService) {
758 this.documentService = documentService;
759 }
760
761 public DocumentDictionaryService getDocumentDictionaryService() {
762 if (this.documentDictionaryService == null) {
763 this.documentDictionaryService = KRADServiceLocatorWeb.getDocumentDictionaryService();
764 }
765 return this.documentDictionaryService;
766 }
767
768 public void setDocumentDictionaryService(DocumentDictionaryService documentDictionaryService) {
769 this.documentDictionaryService = documentDictionaryService;
770 }
771
772 public AttachmentService getAttachmentService() {
773 if (attachmentService == null) {
774 attachmentService = KRADServiceLocator.getAttachmentService();
775 }
776 return this.attachmentService;
777 }
778
779 public NoteService getNoteService() {
780 if (noteService == null) {
781 noteService = KRADServiceLocator.getNoteService();
782 }
783
784 return this.noteService;
785 }
786
787 public ConfigurationService getConfigurationService() {
788 return KRADServiceLocator.getKualiConfigurationService();
789 }
790 }