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