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