1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.rice.krad.maintenance;
17
18 import org.apache.commons.collections.CollectionUtils;
19 import org.apache.commons.lang.StringUtils;
20 import org.apache.ojb.broker.core.proxy.ProxyHelper;
21 import org.kuali.rice.core.api.util.RiceKeyConstants;
22 import org.kuali.rice.kew.api.WorkflowDocument;
23 import org.kuali.rice.kew.framework.postprocessor.DocumentRouteStatusChange;
24 import org.kuali.rice.kim.api.identity.Person;
25 import org.kuali.rice.krad.bo.DocumentAttachment;
26 import org.kuali.rice.krad.bo.DocumentHeader;
27 import org.kuali.rice.krad.bo.GlobalBusinessObject;
28 import org.kuali.rice.krad.bo.MultiDocumentAttachment;
29 import org.kuali.rice.krad.bo.Note;
30 import org.kuali.rice.krad.bo.PersistableAttachment;
31 import org.kuali.rice.krad.bo.PersistableAttachmentList;
32 import org.kuali.rice.krad.bo.PersistableBusinessObject;
33 import org.kuali.rice.krad.datadictionary.DocumentEntry;
34 import org.kuali.rice.krad.datadictionary.WorkflowAttributes;
35 import org.kuali.rice.krad.datadictionary.WorkflowProperties;
36 import org.kuali.rice.krad.document.DocumentBase;
37 import org.kuali.rice.krad.document.SessionDocument;
38 import org.kuali.rice.krad.exception.PessimisticLockingException;
39 import org.kuali.rice.krad.exception.ValidationException;
40 import org.kuali.rice.krad.rules.rule.event.KualiDocumentEvent;
41 import org.kuali.rice.krad.rules.rule.event.SaveDocumentEvent;
42 import org.kuali.rice.krad.service.DocumentDictionaryService;
43 import org.kuali.rice.krad.service.DocumentHeaderService;
44 import org.kuali.rice.krad.service.DocumentService;
45 import org.kuali.rice.krad.service.KRADServiceLocator;
46 import org.kuali.rice.krad.service.KRADServiceLocatorWeb;
47 import org.kuali.rice.krad.service.MaintenanceDocumentService;
48 import org.kuali.rice.krad.util.GlobalVariables;
49 import org.kuali.rice.krad.util.KRADConstants;
50 import org.kuali.rice.krad.util.NoteType;
51 import org.kuali.rice.krad.util.ObjectUtils;
52 import org.kuali.rice.krad.util.documentserializer.PropertySerializabilityEvaluator;
53 import org.w3c.dom.Document;
54 import org.w3c.dom.Node;
55 import org.w3c.dom.NodeList;
56 import org.xml.sax.InputSource;
57 import org.xml.sax.SAXException;
58
59 import javax.persistence.CascadeType;
60 import javax.persistence.Column;
61 import javax.persistence.Entity;
62 import javax.persistence.FetchType;
63 import javax.persistence.JoinColumn;
64 import javax.persistence.ManyToMany;
65 import javax.persistence.ManyToOne;
66 import javax.persistence.Table;
67 import javax.persistence.Transient;
68 import javax.xml.parsers.DocumentBuilder;
69 import javax.xml.parsers.DocumentBuilderFactory;
70 import javax.xml.parsers.ParserConfigurationException;
71 import java.io.IOException;
72 import java.io.StringReader;
73 import java.util.ArrayList;
74 import java.util.Collections;
75 import java.util.List;
76
77
78
79
80
81
82
83
84
85
86
87 @Entity
88 @Table(name = "KRNS_MAINT_DOC_T")
89 public class MaintenanceDocumentBase extends DocumentBase implements MaintenanceDocument, SessionDocument {
90 private static final long serialVersionUID = -505085142412593305L;
91 private static final org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(MaintenanceDocumentBase.class);
92
93 public static final String MAINTAINABLE_IMPL_CLASS = "maintainableImplClass";
94 public static final String OLD_MAINTAINABLE_TAG_NAME = "oldMaintainableObject";
95 public static final String NEW_MAINTAINABLE_TAG_NAME = "newMaintainableObject";
96 public static final String MAINTENANCE_ACTION_TAG_NAME = "maintenanceAction";
97 public static final String NOTES_TAG_NAME = "notes";
98
99 @Transient
100 private static transient DocumentDictionaryService documentDictionaryService;
101 @Transient
102 private static transient MaintenanceDocumentService maintenanceDocumentService;
103 @Transient
104 private static transient DocumentHeaderService documentHeaderService;
105 @Transient
106 private static transient DocumentService documentService;
107
108 @Transient
109 protected Maintainable oldMaintainableObject;
110 @Transient
111 protected Maintainable newMaintainableObject;
112
113 @Column(name = "DOC_CNTNT", length = 4096)
114 protected String xmlDocumentContents;
115 @Transient
116 protected boolean fieldsClearedOnCopy;
117 @Transient
118 protected boolean displayTopicFieldInNotes = false;
119 @Transient
120 protected String attachmentPropertyName;
121 @Transient
122 protected String attachmentListPropertyName;
123 @Transient
124 protected String attachmentCollectionName;
125
126 @ManyToOne(fetch = FetchType.LAZY,
127 cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}) @JoinColumn(name = "DOC_HDR_ID",
128 insertable = false, updatable = false)
129 protected DocumentAttachment attachment;
130
131 @ManyToMany(fetch = FetchType.LAZY,
132 cascade = {CascadeType.PERSIST, CascadeType.MERGE, CascadeType.REMOVE}) @JoinColumn(name = "DOC_HDR_ID",
133 insertable = false, updatable = false)
134 protected List<MultiDocumentAttachment> attachments;
135
136 public String getAttachmentPropertyName() {
137 return this.attachmentPropertyName;
138 }
139
140 public void setAttachmentPropertyName(String attachmentPropertyName) {
141 this.attachmentPropertyName = attachmentPropertyName;
142 }
143
144 public String getAttachmentListPropertyName() {
145 return this.attachmentListPropertyName;
146 }
147
148 public void setAttachmentListPropertyName(String attachmentListPropertyName) {
149 this.attachmentListPropertyName = attachmentListPropertyName;
150 }
151
152 public String getAttachmentCollectionName() {
153 return this.attachmentCollectionName;
154 }
155
156 public void setAttachmentCollectionName(String attachmentCollectionName) {
157 this.attachmentCollectionName = attachmentCollectionName;
158 }
159
160 public MaintenanceDocumentBase() {
161 super();
162 fieldsClearedOnCopy = false;
163 }
164
165
166
167
168 public MaintenanceDocumentBase(String documentTypeName) {
169 this();
170 Class clazz = getDocumentDictionaryService().getMaintainableClass(documentTypeName);
171 try {
172 oldMaintainableObject = (Maintainable) clazz.newInstance();
173 newMaintainableObject = (Maintainable) clazz.newInstance();
174
175
176 Class<?> dataObjectClazz = getDocumentDictionaryService().getMaintenanceDataObjectClass(documentTypeName);
177 oldMaintainableObject.setDataObject(dataObjectClazz.newInstance());
178 oldMaintainableObject.setDataObjectClass(dataObjectClazz);
179 newMaintainableObject.setDataObject(dataObjectClazz.newInstance());
180 newMaintainableObject.setDataObjectClass(dataObjectClazz);
181 } catch (InstantiationException e) {
182 LOG.error("Unable to initialize maintainables of type " + clazz.getName());
183 throw new RuntimeException("Unable to initialize maintainables of type " + clazz.getName());
184 } catch (IllegalAccessException e) {
185 LOG.error("Unable to initialize maintainables of type " + clazz.getName());
186 throw new RuntimeException("Unable to initialize maintainables of type " + clazz.getName());
187 }
188 }
189
190
191
192
193
194
195
196
197
198
199 @Override
200 public String getDocumentTitle() {
201 String documentTitle = "";
202
203 documentTitle = newMaintainableObject.getDocumentTitle(this);
204 if (StringUtils.isNotBlank(documentTitle)) {
205
206 return documentTitle;
207 }
208
209
210
211 String className = newMaintainableObject.getDataObject().getClass().getName();
212 String truncatedClassName = className.substring(className.lastIndexOf('.') + 1);
213 if (isOldDataObjectInDocument()) {
214 documentTitle = "Edit ";
215 } else {
216 documentTitle = "New ";
217 }
218 documentTitle += truncatedClassName + " - ";
219 documentTitle += this.getDocumentHeader().getDocumentDescription() + " ";
220 return documentTitle;
221 }
222
223
224
225
226
227
228
229 protected boolean isOldMaintainableInDocument(Document xmlDocument) {
230 boolean isOldMaintainableInExistence = false;
231 if (xmlDocument.getElementsByTagName(OLD_MAINTAINABLE_TAG_NAME).getLength() > 0) {
232 isOldMaintainableInExistence = true;
233 }
234 return isOldMaintainableInExistence;
235 }
236
237
238
239
240 @Override
241 public boolean isOldDataObjectInDocument() {
242 boolean isOldBusinessObjectInExistence = false;
243 if (oldMaintainableObject == null || oldMaintainableObject.getDataObject() == null) {
244 isOldBusinessObjectInExistence = false;
245 } else {
246 isOldBusinessObjectInExistence = oldMaintainableObject.isOldDataObjectInDocument();
247 }
248 return isOldBusinessObjectInExistence;
249 }
250
251
252
253
254 @Override
255 public boolean isNew() {
256 return MaintenanceUtils.isMaintenanceDocumentCreatingNewRecord(newMaintainableObject.getMaintenanceAction());
257 }
258
259
260
261
262 @Override
263 public boolean isEdit() {
264 if (KRADConstants.MAINTENANCE_EDIT_ACTION.equalsIgnoreCase(newMaintainableObject.getMaintenanceAction())) {
265 return true;
266 } else {
267 return false;
268 }
269 }
270
271
272
273
274 @Override
275 public boolean isNewWithExisting() {
276 if (KRADConstants.MAINTENANCE_NEWWITHEXISTING_ACTION.equalsIgnoreCase(
277 newMaintainableObject.getMaintenanceAction())) {
278 return true;
279 } else {
280 return false;
281 }
282 }
283
284
285
286
287 @Override
288 public void populateMaintainablesFromXmlDocumentContents() {
289
290
291
292 if (!StringUtils.isEmpty(xmlDocumentContents)) {
293 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
294 try {
295 DocumentBuilder builder = factory.newDocumentBuilder();
296 Document xmlDocument = builder.parse(new InputSource(new StringReader(xmlDocumentContents)));
297 String clazz = xmlDocument.getDocumentElement().getAttribute(MAINTAINABLE_IMPL_CLASS);
298 if (isOldMaintainableInDocument(xmlDocument)) {
299 oldMaintainableObject = (Maintainable) Class.forName(clazz).newInstance();
300 Object dataObject = getDataObjectFromXML(OLD_MAINTAINABLE_TAG_NAME);
301
302 String oldMaintenanceAction = getMaintenanceAction(xmlDocument, OLD_MAINTAINABLE_TAG_NAME);
303 oldMaintainableObject.setMaintenanceAction(oldMaintenanceAction);
304
305 oldMaintainableObject.setDataObject(dataObject);
306 oldMaintainableObject.setDataObjectClass(dataObject.getClass());
307 }
308 newMaintainableObject = (Maintainable) Class.forName(clazz).newInstance();
309 Object bo = getDataObjectFromXML(NEW_MAINTAINABLE_TAG_NAME);
310 newMaintainableObject.setDataObject(bo);
311 newMaintainableObject.setDataObjectClass(bo.getClass());
312
313 String newMaintenanceAction = getMaintenanceAction(xmlDocument, NEW_MAINTAINABLE_TAG_NAME);
314 newMaintainableObject.setMaintenanceAction(newMaintenanceAction);
315
316 if (newMaintainableObject.isNotesEnabled()) {
317 List<Note> notes = getNotesFromXml(NOTES_TAG_NAME);
318 setNotes(notes);
319 }
320 } catch (ParserConfigurationException e) {
321 LOG.error("Error while parsing document contents", e);
322 throw new RuntimeException("Could not load document contents from xml", e);
323 } catch (SAXException e) {
324 LOG.error("Error while parsing document contents", e);
325 throw new RuntimeException("Could not load document contents from xml", e);
326 } catch (IOException e) {
327 LOG.error("Error while parsing document contents", e);
328 throw new RuntimeException("Could not load document contents from xml", e);
329 } catch (InstantiationException e) {
330 LOG.error("Error while parsing document contents", e);
331 throw new RuntimeException("Could not load document contents from xml", e);
332 } catch (IllegalAccessException e) {
333 LOG.error("Error while parsing document contents", e);
334 throw new RuntimeException("Could not load document contents from xml", e);
335 } catch (ClassNotFoundException e) {
336 LOG.error("Error while parsing document contents", e);
337 throw new RuntimeException("Could not load document contents from xml", e);
338 }
339 }
340 }
341
342
343
344
345
346
347
348
349
350
351 protected String getMaintenanceAction(Document xmlDocument, String oldOrNewElementName) {
352
353 if (StringUtils.isBlank(oldOrNewElementName)) {
354 throw new IllegalArgumentException("oldOrNewElementName may not be blank, null, or empty-string.");
355 }
356
357 String maintenanceAction = null;
358 NodeList rootChildren = xmlDocument.getDocumentElement().getChildNodes();
359 for (int i = 0; i < rootChildren.getLength(); i++) {
360 Node rootChild = rootChildren.item(i);
361 if (oldOrNewElementName.equalsIgnoreCase(rootChild.getNodeName())) {
362 NodeList maintChildren = rootChild.getChildNodes();
363 for (int j = 0; j < maintChildren.getLength(); j++) {
364 Node maintChild = maintChildren.item(j);
365 if (MAINTENANCE_ACTION_TAG_NAME.equalsIgnoreCase(maintChild.getNodeName())) {
366 maintenanceAction = maintChild.getChildNodes().item(0).getNodeValue();
367 }
368 }
369 }
370 }
371 return maintenanceAction;
372 }
373
374
375
376
377
378
379
380 private List<Note> getNotesFromXml(String notesTagName) {
381 String notesXml = StringUtils.substringBetween(xmlDocumentContents, "<" + notesTagName + ">",
382 "</" + notesTagName + ">");
383 if (StringUtils.isBlank(notesXml)) {
384 return Collections.emptyList();
385 }
386 List<Note> notes = (List<Note>) KRADServiceLocator.getXmlObjectSerializerService().fromXml(notesXml);
387 if (notes == null) {
388 return Collections.emptyList();
389 }
390 return notes;
391 }
392
393
394
395
396
397
398
399
400
401
402
403
404 protected Object getDataObjectFromXML(String maintainableTagName) {
405 String maintXml = StringUtils.substringBetween(xmlDocumentContents, "<" + maintainableTagName + ">",
406 "</" + maintainableTagName + ">");
407 Object businessObject = KRADServiceLocator.getXmlObjectSerializerService().fromXml(maintXml);
408 return businessObject;
409 }
410
411
412
413
414 @Override
415 public void populateXmlDocumentContentsFromMaintainables() {
416 StringBuilder docContentBuffer = new StringBuilder();
417 docContentBuffer.append("<maintainableDocumentContents maintainableImplClass=\"").append(
418 newMaintainableObject.getClass().getName()).append("\">");
419
420
421 if (getNewMaintainableObject().isNotesEnabled()) {
422 docContentBuffer.append("<" + NOTES_TAG_NAME + ">");
423
424
425
426
427 List<Note> noteList = new ArrayList<Note>();
428 for (Note note : getNotes()) {
429 noteList.add(note);
430 }
431 docContentBuffer.append(KRADServiceLocator.getXmlObjectSerializerService().toXml(noteList));
432 docContentBuffer.append("</" + NOTES_TAG_NAME + ">");
433 }
434 if (oldMaintainableObject != null && oldMaintainableObject.getDataObject() != null) {
435
436 docContentBuffer.append("<" + OLD_MAINTAINABLE_TAG_NAME + ">");
437
438 Object oldBo = oldMaintainableObject.getDataObject();
439
440
441 if (oldBo instanceof PersistableBusinessObject) {
442 ObjectUtils.materializeAllSubObjects((PersistableBusinessObject) oldBo);
443 }
444
445 docContentBuffer.append(
446 KRADServiceLocator.getBusinessObjectSerializerService().serializeBusinessObjectToXml(oldBo));
447
448
449 docContentBuffer.append("<" + MAINTENANCE_ACTION_TAG_NAME + ">");
450 docContentBuffer.append(oldMaintainableObject.getMaintenanceAction());
451 docContentBuffer.append("</" + MAINTENANCE_ACTION_TAG_NAME + ">\n");
452
453 docContentBuffer.append("</" + OLD_MAINTAINABLE_TAG_NAME + ">");
454 }
455 docContentBuffer.append("<" + NEW_MAINTAINABLE_TAG_NAME + ">");
456
457 Object newBo = newMaintainableObject.getDataObject();
458
459 if (newBo instanceof PersistableBusinessObject) {
460
461 ObjectUtils.materializeAllSubObjects((PersistableBusinessObject) newBo);
462 }
463
464 docContentBuffer.append(KRADServiceLocator.getBusinessObjectSerializerService().serializeBusinessObjectToXml(
465 newBo));
466
467
468 docContentBuffer.append("<" + MAINTENANCE_ACTION_TAG_NAME + ">");
469 docContentBuffer.append(newMaintainableObject.getMaintenanceAction());
470 docContentBuffer.append("</" + MAINTENANCE_ACTION_TAG_NAME + ">\n");
471
472 docContentBuffer.append("</" + NEW_MAINTAINABLE_TAG_NAME + ">");
473 docContentBuffer.append("</maintainableDocumentContents>");
474 xmlDocumentContents = docContentBuffer.toString();
475 }
476
477
478
479
480 @Override
481 public void doRouteStatusChange(DocumentRouteStatusChange statusChangeEvent) {
482 super.doRouteStatusChange(statusChangeEvent);
483
484 WorkflowDocument workflowDocument = getDocumentHeader().getWorkflowDocument();
485 getNewMaintainableObject().doRouteStatusChange(getDocumentHeader());
486
487
488 if (workflowDocument.isProcessed()) {
489 String documentNumber = getDocumentHeader().getDocumentNumber();
490 newMaintainableObject.setDocumentNumber(documentNumber);
491
492
493 if (newMaintainableObject.getDataObject() instanceof PersistableAttachment) {
494 populateAttachmentBeforeSave();
495 }
496
497
498 if (newMaintainableObject.getDataObject() instanceof PersistableAttachmentList) {
499 populateBoAttachmentListBeforeSave();
500 }
501
502 newMaintainableObject.saveDataObject();
503
504 if (!getDocumentService().saveDocumentNotes(this)) {
505 throw new IllegalStateException(
506 "Failed to save document notes, this means that the note target was not ready for notes to be attached when it should have been.");
507 }
508
509
510 deleteDocumentAttachment();
511 deleteDocumentAttachmentList();
512
513 getMaintenanceDocumentService().deleteLocks(documentNumber);
514
515
516 if (this.checkAllowsRecordDeletion() && this.checkMaintenanceAction() &&
517 this.checkDeletePermission(newMaintainableObject.getDataObject())) {
518 newMaintainableObject.deleteDataObject();
519 }
520 }
521
522
523 if (workflowDocument.isCanceled() || workflowDocument.isDisapproved() || workflowDocument.isRecalled()) {
524
525 deleteDocumentAttachment();
526 deleteDocumentAttachmentList();
527
528 String documentNumber = getDocumentHeader().getDocumentNumber();
529 getMaintenanceDocumentService().deleteLocks(documentNumber);
530 }
531 }
532
533
534
535
536 @Override
537 public List<String> getWorkflowEngineDocumentIdsToLock() {
538 if (newMaintainableObject != null) {
539 return newMaintainableObject.getWorkflowEngineDocumentIdsToLock();
540 }
541 return Collections.emptyList();
542 }
543
544
545
546
547 @Override
548 public void prepareForSave() {
549 if (newMaintainableObject != null) {
550 newMaintainableObject.prepareForSave();
551 }
552 }
553
554
555
556
557 @Override
558 public void processAfterRetrieve() {
559
560 super.processAfterRetrieve();
561
562 populateMaintainablesFromXmlDocumentContents();
563 if (oldMaintainableObject != null) {
564 oldMaintainableObject.setDocumentNumber(documentNumber);
565 }
566 if (newMaintainableObject != null) {
567 newMaintainableObject.setDocumentNumber(documentNumber);
568 newMaintainableObject.processAfterRetrieve();
569 if (newMaintainableObject.getDataObject() instanceof PersistableAttachment) {
570 populateAttachmentForBO();
571 }
572 if (newMaintainableObject.getDataObject() instanceof PersistableAttachmentList) {
573 populateAttachmentListForBO();
574 }
575
576 checkForLockingDocument(false);
577 }
578 }
579
580
581
582
583 @Override
584 public Maintainable getNewMaintainableObject() {
585 return newMaintainableObject;
586 }
587
588
589
590
591 @Override
592 public void setNewMaintainableObject(Maintainable newMaintainableObject) {
593 this.newMaintainableObject = newMaintainableObject;
594 }
595
596
597
598
599 @Override
600 public Maintainable getOldMaintainableObject() {
601 return oldMaintainableObject;
602 }
603
604
605
606
607 @Override
608 public void setOldMaintainableObject(Maintainable oldMaintainableObject) {
609 this.oldMaintainableObject = oldMaintainableObject;
610 }
611
612
613
614
615 @Override
616 public void setDocumentNumber(String documentNumber) {
617 super.setDocumentNumber(documentNumber);
618
619
620 oldMaintainableObject.setDocumentNumber(documentNumber);
621 newMaintainableObject.setDocumentNumber(documentNumber);
622 }
623
624
625
626
627 @Override
628 public final boolean isFieldsClearedOnCopy() {
629 return fieldsClearedOnCopy;
630 }
631
632
633
634
635 @Override
636 public final void setFieldsClearedOnCopy(boolean fieldsClearedOnCopy) {
637 this.fieldsClearedOnCopy = fieldsClearedOnCopy;
638 }
639
640
641
642
643 @Override
644 public String getXmlDocumentContents() {
645 return xmlDocumentContents;
646 }
647
648
649
650
651 @Override
652 public void setXmlDocumentContents(String xmlDocumentContents) {
653 this.xmlDocumentContents = xmlDocumentContents;
654 }
655
656
657
658
659 @Override
660 public boolean getAllowsCopy() {
661 return getDocumentDictionaryService().getAllowsCopy(this);
662 }
663
664
665
666
667 @Override
668 public boolean isDisplayTopicFieldInNotes() {
669 return displayTopicFieldInNotes;
670 }
671
672
673
674
675 @Override
676 public void setDisplayTopicFieldInNotes(boolean displayTopicFieldInNotes) {
677 this.displayTopicFieldInNotes = displayTopicFieldInNotes;
678 }
679
680
681
682
683 @Override
684 public String serializeDocumentToXml() {
685 String tempXmlDocumentContents = xmlDocumentContents;
686 xmlDocumentContents = null;
687 String xmlForWorkflow = super.serializeDocumentToXml();
688 xmlDocumentContents = tempXmlDocumentContents;
689 return xmlForWorkflow;
690 }
691
692
693
694
695 @Override
696 public void prepareForSave(KualiDocumentEvent event) {
697 super.prepareForSave(event);
698 if (newMaintainableObject.getDataObject() instanceof PersistableAttachment) {
699 populateDocumentAttachment();
700 populateAttachmentForBO();
701
702 if (oldMaintainableObject.getDataObject() instanceof PersistableAttachment) {
703 ((PersistableAttachment) oldMaintainableObject.getDataObject()).setAttachmentContent(null);
704 }
705 }
706 if (newMaintainableObject.getDataObject() instanceof PersistableAttachmentList) {
707 populateDocumentAttachmentList();
708 populateAttachmentListForBO();
709 if (oldMaintainableObject.getDataObject() instanceof PersistableAttachmentList) {
710 for (PersistableAttachment pa : ((PersistableAttachmentList<PersistableAttachment>) oldMaintainableObject
711 .getDataObject()).getAttachments()) {
712 pa.setAttachmentContent(null);
713 }
714 }
715 }
716 populateXmlDocumentContentsFromMaintainables();
717 }
718
719
720
721
722
723
724 protected void refreshAttachment() {
725 if (ObjectUtils.isNull(attachment)) {
726 this.refreshReferenceObject("attachment");
727 final boolean isProxy = attachment != null && ProxyHelper.isProxy(attachment);
728 if (isProxy && ProxyHelper.getRealObject(attachment) == null) {
729 attachment = null;
730 }
731 }
732 }
733
734 protected void refreshAttachmentList() {
735 if (ObjectUtils.isNull(attachments)) {
736 this.refreshReferenceObject("attachments");
737 final boolean isProxy = attachments != null && ProxyHelper.isProxy(attachments);
738 if (isProxy && ProxyHelper.getRealObject(attachments) == null) {
739 attachments = null;
740 }
741 }
742 }
743
744 public void populateAttachmentForBO() {
745
746
747 }
748
749 public void populateDocumentAttachment() {
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780 }
781
782 public void populateAttachmentListForBO() { }
783
784 public void populateAttachmentBeforeSave() { }
785
786 public void populateDocumentAttachmentList() { }
787
788 public void populateBoAttachmentListBeforeSave() { }
789
790 public void deleteDocumentAttachment() {
791 KRADServiceLocator.getBusinessObjectService().delete(attachment);
792 attachment = null;
793 }
794
795 public void deleteDocumentAttachmentList() {
796 if (CollectionUtils.isNotEmpty(attachments)) {
797 KRADServiceLocator.getBusinessObjectService().delete(attachments);
798 attachments = null;
799 }
800 }
801
802
803
804
805
806
807 @Override
808 public void validateBusinessRules(KualiDocumentEvent event) {
809 if (GlobalVariables.getMessageMap().hasErrors()) {
810 logErrors();
811 throw new ValidationException("errors occured before business rule");
812 }
813
814
815 checkForLockingDocument(true);
816
817
818 if (newMaintainableObject != null) {
819 if (KRADServiceLocator.getPersistenceStructureService().isPersistable(
820 newMaintainableObject.getDataObject().getClass())) {
821 PersistableBusinessObject pbObject = KRADServiceLocator.getBusinessObjectService().retrieve(
822 (PersistableBusinessObject) newMaintainableObject.getDataObject());
823 Long pbObjectVerNbr = ObjectUtils.isNull(pbObject) ? null : pbObject.getVersionNumber();
824 Long newObjectVerNbr =
825 ((PersistableBusinessObject) newMaintainableObject.getDataObject()).getVersionNumber();
826
827 if (pbObjectVerNbr != null && !(pbObjectVerNbr.equals(newObjectVerNbr))) {
828 GlobalVariables.getMessageMap().putError(KRADConstants.GLOBAL_ERRORS,
829 RiceKeyConstants.ERROR_VERSION_MISMATCH);
830 throw new ValidationException(
831 "Version mismatch between the local business object and the database business object");
832 }
833 }
834 }
835
836
837 if (LOG.isInfoEnabled()) {
838 LOG.info("invoking rules engine on document " + getDocumentNumber());
839 }
840
841 boolean isValid = true;
842 isValid = KRADServiceLocatorWeb.getKualiRuleService().applyRules(event);
843
844
845 if (!isValid) {
846 logErrors();
847
848
849 throw new ValidationException("business rule evaluation failed");
850 } else if (GlobalVariables.getMessageMap().hasErrors()) {
851 logErrors();
852 if (event instanceof SaveDocumentEvent) {
853
854
855
856
857
858
859 } else {
860 throw new ValidationException(
861 "Unreported errors occured during business rule evaluation (rule developer needs to put meaningful error messages into global ErrorMap)");
862 }
863 }
864
865 LOG.debug("validation completed");
866 }
867
868 protected void checkForLockingDocument(boolean throwExceptionIfLocked) {
869 MaintenanceUtils.checkForLockingDocument(this, throwExceptionIfLocked);
870 }
871
872
873
874
875
876
877
878 @Override
879 public void postProcessSave(KualiDocumentEvent event) {
880 if (getNewMaintainableObject().getDataObject() instanceof PersistableBusinessObject) {
881 PersistableBusinessObject bo = (PersistableBusinessObject) getNewMaintainableObject().getDataObject();
882 if (bo instanceof GlobalBusinessObject) {
883 KRADServiceLocator.getBusinessObjectService().save(bo);
884 }
885 }
886
887
888
889
890
891 if (!(event instanceof SaveDocumentEvent)) {
892 getMaintenanceDocumentService().deleteLocks(this.getDocumentNumber());
893 getMaintenanceDocumentService().storeLocks(this.getNewMaintainableObject().generateMaintenanceLocks());
894 }
895 }
896
897
898
899
900 @Override
901 public Object getDocumentDataObject() {
902 return getNewMaintainableObject().getDataObject();
903 }
904
905
906
907
908
909
910
911
912
913
914
915 @Override
916 public PersistableBusinessObject getNoteTarget() {
917 if (getNewMaintainableObject() == null) {
918 throw new IllegalStateException(
919 "Failed to acquire the note target. The new maintainable object on this document is null.");
920 }
921 if (getNewMaintainableObject().isNotesEnabled()) {
922 return (PersistableBusinessObject) getDocumentDataObject();
923 }
924 return super.getNoteTarget();
925 }
926
927
928
929
930
931
932
933
934
935
936
937
938
939 @Override
940 public NoteType getNoteType() {
941 if (getNewMaintainableObject().isNotesEnabled()) {
942 return NoteType.BUSINESS_OBJECT;
943 }
944 return super.getNoteType();
945 }
946
947 @Override
948 public PropertySerializabilityEvaluator getDocumentPropertySerizabilityEvaluator() {
949 String docTypeName = "";
950 if (newMaintainableObject != null) {
951 docTypeName = getDocumentDictionaryService().getMaintenanceDocumentTypeName(
952 this.newMaintainableObject.getDataObjectClass());
953 } else {
954
955
956 if (getDocumentHeader() != null && getDocumentHeader().getWorkflowDocument() != null) {
957 docTypeName = getDocumentHeader().getWorkflowDocument().getDocumentTypeName();
958 }
959 }
960 if (!StringUtils.isBlank(docTypeName)) {
961 DocumentEntry documentEntry = getDocumentDictionaryService().getMaintenanceDocumentEntry(docTypeName);
962 if (documentEntry != null) {
963 WorkflowProperties workflowProperties = documentEntry.getWorkflowProperties();
964 WorkflowAttributes workflowAttributes = documentEntry.getWorkflowAttributes();
965 return createPropertySerializabilityEvaluator(workflowProperties, workflowAttributes);
966 } else {
967 LOG.error("Unable to obtain DD DocumentEntry for document type: '" + docTypeName + "'");
968 }
969 } else {
970 LOG.error("Unable to obtain document type name for this document: " + this);
971 }
972 LOG.error("Returning null for the PropertySerializabilityEvaluator");
973 return null;
974 }
975
976 public DocumentAttachment getAttachment() {
977 return this.attachment;
978 }
979
980 public void setAttachment(DocumentAttachment attachment) {
981 this.attachment = attachment;
982 }
983
984 public List<MultiDocumentAttachment> getAttachments() {
985 return this.attachments;
986 }
987
988 public void setAttachments(List<MultiDocumentAttachment> attachment) {
989 this.attachments = attachments;
990 }
991
992
993
994
995
996
997
998 @Override
999 protected void postRemove() {
1000 super.postRemove();
1001 getDocumentHeaderService().deleteDocumentHeader(getDocumentHeader());
1002 }
1003
1004
1005
1006
1007
1008
1009
1010 @Override
1011 protected void postLoad() {
1012 super.postLoad();
1013 setDocumentHeader(getDocumentHeaderService().getDocumentHeaderById(getDocumentNumber()));
1014 }
1015
1016
1017
1018
1019
1020
1021
1022 @Override
1023 protected void prePersist() {
1024 super.prePersist();
1025 getDocumentHeaderService().saveDocumentHeader(getDocumentHeader());
1026 }
1027
1028
1029
1030
1031
1032
1033
1034 @Override
1035 protected void preUpdate() {
1036 super.preUpdate();
1037 getDocumentHeaderService().saveDocumentHeader(getDocumentHeader());
1038 }
1039
1040
1041
1042
1043
1044
1045 public boolean isSessionDocument() {
1046 return SessionDocument.class.isAssignableFrom(this.getClass());
1047 }
1048
1049
1050
1051
1052
1053
1054
1055
1056 @Override
1057 public boolean useCustomLockDescriptors() {
1058 return (newMaintainableObject != null && newMaintainableObject.useCustomLockDescriptors());
1059 }
1060
1061
1062
1063
1064
1065
1066
1067
1068 @Override
1069 public String getCustomLockDescriptor(Person user) {
1070 if (newMaintainableObject == null) {
1071 throw new PessimisticLockingException("Maintenance Document " + getDocumentNumber() +
1072 " is using pessimistic locking with custom lock descriptors, but no new maintainable object has been defined");
1073 }
1074 return newMaintainableObject.getCustomLockDescriptor(user);
1075 }
1076
1077 protected DocumentDictionaryService getDocumentDictionaryService() {
1078 if (documentDictionaryService == null) {
1079 documentDictionaryService = KRADServiceLocatorWeb.getDocumentDictionaryService();
1080 }
1081 return documentDictionaryService;
1082 }
1083
1084 protected MaintenanceDocumentService getMaintenanceDocumentService() {
1085 if (maintenanceDocumentService == null) {
1086 maintenanceDocumentService = KRADServiceLocatorWeb.getMaintenanceDocumentService();
1087 }
1088 return maintenanceDocumentService;
1089 }
1090
1091 protected DocumentHeaderService getDocumentHeaderService() {
1092 if (documentHeaderService == null) {
1093 documentHeaderService = KRADServiceLocatorWeb.getDocumentHeaderService();
1094 }
1095 return documentHeaderService;
1096 }
1097
1098 protected DocumentService getDocumentService() {
1099 if (documentService == null) {
1100 documentService = KRADServiceLocatorWeb.getDocumentService();
1101 }
1102 return documentService;
1103 }
1104
1105
1106 protected boolean checkAllowsRecordDeletion() {
1107 Boolean allowsRecordDeletion = KRADServiceLocatorWeb.getDocumentDictionaryService().getAllowsRecordDeletion(
1108 this.getNewMaintainableObject().getDataObjectClass());
1109 if (allowsRecordDeletion != null) {
1110 return allowsRecordDeletion.booleanValue();
1111 } else {
1112 return false;
1113 }
1114 }
1115
1116
1117 protected boolean checkMaintenanceAction() {
1118 return this.getNewMaintainableObject().getMaintenanceAction().equals(KRADConstants.MAINTENANCE_DELETE_ACTION);
1119 }
1120
1121
1122 protected boolean checkDeletePermission(Object dataObject) {
1123 boolean allowsMaintain = false;
1124
1125 String maintDocTypeName = KRADServiceLocatorWeb.getDocumentDictionaryService().getMaintenanceDocumentTypeName(
1126 dataObject.getClass());
1127
1128 if (StringUtils.isNotBlank(maintDocTypeName)) {
1129 allowsMaintain = KRADServiceLocatorWeb.getDataObjectAuthorizationService().canMaintain(dataObject,
1130 GlobalVariables.getUserSession().getPerson(), maintDocTypeName);
1131 }
1132 return allowsMaintain;
1133 }
1134 }