1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package org.kuali.ole.sys.document;
17 import java.util.ArrayList;
18 import java.util.HashMap;
19 import java.util.Iterator;
20 import java.util.List;
21 import java.util.Map;
22
23 import org.apache.commons.lang.StringUtils;
24 import org.kuali.ole.sys.OLEConstants;
25 import org.kuali.ole.sys.businessobject.AccountingLine;
26 import org.kuali.ole.sys.businessobject.AccountingLineBase;
27 import org.kuali.ole.sys.businessobject.AccountingLineParser;
28 import org.kuali.ole.sys.businessobject.AccountingLineParserBase;
29 import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntry;
30 import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySequenceHelper;
31 import org.kuali.ole.sys.businessobject.GeneralLedgerPendingEntrySourceDetail;
32 import org.kuali.ole.sys.businessobject.SourceAccountingLine;
33 import org.kuali.ole.sys.businessobject.TargetAccountingLine;
34 import org.kuali.ole.sys.context.SpringContext;
35 import org.kuali.ole.sys.document.datadictionary.FinancialSystemTransactionalDocumentEntry;
36 import org.kuali.ole.sys.document.validation.event.AccountingDocumentSaveWithNoLedgerEntryGenerationEvent;
37 import org.kuali.ole.sys.document.validation.event.AccountingLineEvent;
38 import org.kuali.ole.sys.document.validation.event.AddAccountingLineEvent;
39 import org.kuali.ole.sys.document.validation.event.DeleteAccountingLineEvent;
40 import org.kuali.ole.sys.document.validation.event.ReviewAccountingLineEvent;
41 import org.kuali.ole.sys.document.validation.event.UpdateAccountingLineEvent;
42 import org.kuali.ole.sys.service.AccountingLineService;
43 import org.kuali.ole.sys.service.GeneralLedgerPendingEntryService;
44 import org.kuali.rice.core.api.util.type.KualiDecimal;
45 import org.kuali.rice.kew.api.exception.WorkflowException;
46 import org.kuali.rice.kns.service.DataDictionaryService;
47 import org.kuali.rice.krad.document.TransactionalDocument;
48 import org.kuali.rice.krad.exception.ValidationException;
49 import org.kuali.rice.krad.rules.rule.event.KualiDocumentEvent;
50 import org.kuali.rice.krad.util.ObjectUtils;
51
52
53
54
55 public abstract class AccountingDocumentBase extends GeneralLedgerPostingDocumentBase implements AccountingDocument, GeneralLedgerPendingEntrySource {
56 protected static org.apache.log4j.Logger LOG = org.apache.log4j.Logger.getLogger(AccountingDocumentBase.class);
57
58 protected Integer nextSourceLineNumber;
59 protected Integer nextTargetLineNumber;
60 protected List sourceAccountingLines;
61 protected List targetAccountingLines;
62
63 protected transient FinancialSystemTransactionalDocumentEntry dataDictionaryEntry;
64 protected transient Class sourceAccountingLineClass;
65 protected transient Class targetAccountingLineClass;
66
67
68
69
70 public AccountingDocumentBase() {
71 super();
72 this.nextSourceLineNumber = new Integer(1);
73 this.nextTargetLineNumber = new Integer(1);
74 setSourceAccountingLines(new ArrayList());
75 setTargetAccountingLines(new ArrayList());
76 }
77
78
79
80
81 @Override
82 public List getSourceAccountingLines() {
83 return this.sourceAccountingLines;
84 }
85
86
87
88
89 @Override
90 public void setSourceAccountingLines(List sourceLines) {
91 this.sourceAccountingLines = sourceLines;
92 }
93
94
95
96
97 @Override
98 public List getTargetAccountingLines() {
99 return this.targetAccountingLines;
100 }
101
102
103
104
105 @Override
106 public void setTargetAccountingLines(List targetLines) {
107 this.targetAccountingLines = targetLines;
108 }
109
110
111
112
113
114
115
116
117 @Override
118 public void addSourceAccountingLine(SourceAccountingLine line) {
119 line.setSequenceNumber(this.getNextSourceLineNumber());
120 this.sourceAccountingLines.add(line);
121 this.nextSourceLineNumber = new Integer(this.getNextSourceLineNumber().intValue() + 1);
122 }
123
124
125
126
127
128
129
130
131 @Override
132 public void addTargetAccountingLine(TargetAccountingLine line) {
133 line.setSequenceNumber(this.getNextTargetLineNumber());
134 this.targetAccountingLines.add(line);
135 this.nextTargetLineNumber = new Integer(this.getNextTargetLineNumber().intValue() + 1);
136 }
137
138
139
140
141
142
143
144
145
146
147 @Override
148 public SourceAccountingLine getSourceAccountingLine(int index) {
149 while (getSourceAccountingLines().size() <= index) {
150 try {
151 getSourceAccountingLines().add(getSourceAccountingLineClass().newInstance());
152 }
153 catch (InstantiationException e) {
154 throw new RuntimeException("Unable to get class");
155 }
156 catch (IllegalAccessException e) {
157 throw new RuntimeException("Unable to get class");
158 }
159 }
160 return (SourceAccountingLine) getSourceAccountingLines().get(index);
161 }
162
163
164
165
166
167
168
169
170
171
172 @Override
173 public TargetAccountingLine getTargetAccountingLine(int index) {
174 while (getTargetAccountingLines().size() <= index) {
175 try {
176 getTargetAccountingLines().add(getTargetAccountingLineClass().newInstance());
177 }
178 catch (InstantiationException e) {
179 throw new RuntimeException("Unable to get class");
180 }
181 catch (IllegalAccessException e) {
182 throw new RuntimeException("Unable to get class");
183 }
184 }
185 return (TargetAccountingLine) getTargetAccountingLines().get(index);
186 }
187
188
189
190
191 @Override
192 public String getSourceAccountingLinesSectionTitle() {
193 return OLEConstants.SOURCE;
194 }
195
196
197
198
199 @Override
200 public String getTargetAccountingLinesSectionTitle() {
201 return OLEConstants.TARGET;
202 }
203
204
205
206
207
208
209
210
211 public KualiDecimal getTotalDollarAmount() {
212 return getTargetTotal().equals(KualiDecimal.ZERO) ? getSourceTotal().abs() : getTargetTotal().abs();
213 }
214
215
216
217
218 @Override
219 public KualiDecimal getSourceTotal() {
220 KualiDecimal total = KualiDecimal.ZERO;
221 AccountingLineBase al = null;
222 Iterator iter = getSourceAccountingLines().iterator();
223 while (iter.hasNext()) {
224 al = (AccountingLineBase) iter.next();
225
226 KualiDecimal amount = al.getAmount();
227 if (amount != null) {
228 total = total.add(amount);
229 }
230 }
231 return total;
232 }
233
234
235
236
237 @Override
238 public KualiDecimal getTargetTotal() {
239 KualiDecimal total = KualiDecimal.ZERO;
240 AccountingLineBase al = null;
241 Iterator iter = getTargetAccountingLines().iterator();
242 while (iter.hasNext()) {
243 al = (AccountingLineBase) iter.next();
244
245 KualiDecimal amount = al.getAmount();
246 if (amount != null) {
247 total = total.add(amount);
248 }
249 }
250 return total;
251 }
252
253
254
255
256 @Override
257 public Integer getNextSourceLineNumber() {
258 return this.nextSourceLineNumber;
259 }
260
261
262
263
264 @Override
265 public void setNextSourceLineNumber(Integer nextLineNumber) {
266 this.nextSourceLineNumber = nextLineNumber;
267 }
268
269
270
271
272 @Override
273 public Integer getNextTargetLineNumber() {
274 return this.nextTargetLineNumber;
275 }
276
277
278
279
280 @Override
281 public void setNextTargetLineNumber(Integer nextLineNumber) {
282 this.nextTargetLineNumber = nextLineNumber;
283 }
284
285
286
287
288
289
290 @Override
291 public Class getSourceAccountingLineClass() {
292 if (sourceAccountingLineClass == null) {
293 sourceAccountingLineClass = (getDataDictionaryEntry().getAccountingLineGroups() != null && getDataDictionaryEntry().getAccountingLineGroups().containsKey("source") && getDataDictionaryEntry().getAccountingLineGroups().get("source").getAccountingLineClass() != null) ? getDataDictionaryEntry().getAccountingLineGroups().get("source").getAccountingLineClass() : SourceAccountingLine.class;
294 }
295 return sourceAccountingLineClass;
296 }
297
298
299
300
301
302
303 @Override
304 public Class getTargetAccountingLineClass() {
305 if (targetAccountingLineClass == null) {
306 targetAccountingLineClass = (getDataDictionaryEntry().getAccountingLineGroups() != null && getDataDictionaryEntry().getAccountingLineGroups().containsKey("target") && getDataDictionaryEntry().getAccountingLineGroups().get("target").getAccountingLineClass() != null) ? getDataDictionaryEntry().getAccountingLineGroups().get("target").getAccountingLineClass() : TargetAccountingLine.class;
307 }
308 return targetAccountingLineClass;
309 }
310
311
312
313
314
315
316 @Override
317 public AccountingLineParser getAccountingLineParser() {
318 try {
319 if (getDataDictionaryEntry().getImportedLineParserClass() != null) {
320 return getDataDictionaryEntry().getImportedLineParserClass().newInstance();
321 }
322 }
323 catch (InstantiationException ie) {
324 throw new IllegalStateException("Accounting Line Parser class " + getDataDictionaryEntry().getImportedLineParserClass().getName() + " cannot be instantiated", ie);
325 }
326 catch (IllegalAccessException iae) {
327 throw new IllegalStateException("Illegal Access Exception while attempting to instantiate Accounting Line Parser class " + getDataDictionaryEntry().getImportedLineParserClass().getName(), iae);
328 }
329 return new AccountingLineParserBase();
330 }
331
332
333
334
335 public FinancialSystemTransactionalDocumentEntry getDataDictionaryEntry() {
336 if (dataDictionaryEntry == null) {
337 dataDictionaryEntry = (FinancialSystemTransactionalDocumentEntry) SpringContext.getBean(DataDictionaryService.class).getDataDictionary().getDocumentEntry(SpringContext.getBean(DataDictionaryService.class).getValidDocumentTypeNameByClass(getClass()));
338 }
339 return dataDictionaryEntry;
340 }
341
342 @Override
343 public String getSourceAccountingLineEntryName() {
344 return this.getSourceAccountingLineClass().getName();
345 }
346
347 @Override
348 public String getTargetAccountingLineEntryName() {
349 return this.getTargetAccountingLineClass().getName();
350 }
351
352 @Override
353 public List<GeneralLedgerPendingEntrySourceDetail> getGeneralLedgerPendingEntrySourceDetails() {
354 List<GeneralLedgerPendingEntrySourceDetail> accountingLines = new ArrayList<GeneralLedgerPendingEntrySourceDetail>();
355 if (getSourceAccountingLines() != null) {
356 Iterator iter = getSourceAccountingLines().iterator();
357 while (iter.hasNext()) {
358 accountingLines.add((GeneralLedgerPendingEntrySourceDetail) iter.next());
359 }
360 }
361 if (getTargetAccountingLines() != null) {
362 Iterator iter = getTargetAccountingLines().iterator();
363 while (iter.hasNext()) {
364 accountingLines.add((GeneralLedgerPendingEntrySourceDetail) iter.next());
365 }
366 }
367 return accountingLines;
368 }
369
370 public void customizeExplicitGeneralLedgerPendingEntry(GeneralLedgerPendingEntrySourceDetail postable, GeneralLedgerPendingEntry explicitEntry) {
371 }
372
373 public boolean customizeOffsetGeneralLedgerPendingEntry(GeneralLedgerPendingEntrySourceDetail accountingLine, GeneralLedgerPendingEntry explicitEntry, GeneralLedgerPendingEntry offsetEntry) {
374 return true;
375 }
376
377
378
379
380 @Override
381 public void toCopy() throws WorkflowException {
382 super.toCopy();
383 copyAccountingLines(false);
384 updatePostingYearForAccountingLines(getSourceAccountingLines());
385 updatePostingYearForAccountingLines(getTargetAccountingLines());
386 }
387
388
389
390
391 @Override
392 public void toErrorCorrection() throws WorkflowException {
393 super.toErrorCorrection();
394 copyAccountingLines(true);
395 }
396
397
398
399
400 protected void copyAccountingLines(boolean isErrorCorrection) {
401 if (getSourceAccountingLines() != null) {
402 for (Iterator iter = getSourceAccountingLines().iterator(); iter.hasNext();) {
403 AccountingLineBase sourceLine = (AccountingLineBase) iter.next();
404 sourceLine.setDocumentNumber(getDocumentNumber());
405 sourceLine.setVersionNumber(new Long(1));
406 if (isErrorCorrection) {
407 sourceLine.setAmount(sourceLine.getAmount().negated());
408 }
409 }
410 }
411
412 if (getTargetAccountingLines() != null) {
413 for (Iterator iter = getTargetAccountingLines().iterator(); iter.hasNext();) {
414 AccountingLineBase targetLine = (AccountingLineBase) iter.next();
415 targetLine.setDocumentNumber(getDocumentNumber());
416 targetLine.setVersionNumber(new Long(1));
417 if (isErrorCorrection) {
418 targetLine.setAmount(targetLine.getAmount().negated());
419 }
420 }
421 }
422 }
423
424
425
426
427
428
429 protected void updatePostingYearForAccountingLines(List<AccountingLine> lines) {
430 if (lines != null) {
431 for (AccountingLine line : lines) {
432 if (!line.getPostingYear().equals(getPostingYear())) {
433 line.setPostingYear(getPostingYear());
434 }
435 }
436 }
437 }
438
439
440
441
442 @Override
443 public List buildListOfDeletionAwareLists() {
444 List managedLists = super.buildListOfDeletionAwareLists();
445
446 managedLists.add(getSourceAccountingLines());
447 managedLists.add(getTargetAccountingLines());
448
449 return managedLists;
450 }
451
452 @Override
453 public void prepareForSave(KualiDocumentEvent event) {
454 if (!(event instanceof AccountingDocumentSaveWithNoLedgerEntryGenerationEvent)) {
455
456 if (!SpringContext.getBean(GeneralLedgerPendingEntryService.class).generateGeneralLedgerPendingEntries(this)) {
457 logErrors();
458 throw new ValidationException("general ledger GLPE generation failed");
459 }
460 }
461 super.prepareForSave(event);
462 }
463
464 @Override
465 public List generateSaveEvents() {
466 List events = new ArrayList();
467
468
469
470
471
472
473 List persistedSourceLines = getPersistedSourceAccountingLinesForComparison();
474 List currentSourceLines = getSourceAccountingLinesForComparison();
475
476 List sourceEvents = generateEvents(persistedSourceLines, currentSourceLines, OLEConstants.DOCUMENT_PROPERTY_NAME + "." + OLEConstants.SOURCE_ACCOUNTING_LINE_ERRORS, this);
477 for (Iterator i = sourceEvents.iterator(); i.hasNext();) {
478 AccountingLineEvent sourceEvent = (AccountingLineEvent) i.next();
479 events.add(sourceEvent);
480 }
481
482 List persistedTargetLines = getPersistedTargetAccountingLinesForComparison();
483 List currentTargetLines = getTargetAccountingLinesForComparison();
484
485 List targetEvents = generateEvents(persistedTargetLines, currentTargetLines, OLEConstants.DOCUMENT_PROPERTY_NAME + "." + OLEConstants.TARGET_ACCOUNTING_LINE_ERRORS, this);
486 for (Iterator i = targetEvents.iterator(); i.hasNext();) {
487 AccountingLineEvent targetEvent = (AccountingLineEvent) i.next();
488 events.add(targetEvent);
489 }
490
491 return events;
492 }
493
494
495
496
497
498
499 protected List getTargetAccountingLinesForComparison() {
500 return getTargetAccountingLines();
501 }
502
503
504
505
506
507
508 protected List getPersistedTargetAccountingLinesForComparison() {
509 return SpringContext.getBean(AccountingLineService.class).getByDocumentHeaderId(getTargetAccountingLineClass(), getDocumentNumber());
510 }
511
512
513
514
515
516
517 protected List getSourceAccountingLinesForComparison() {
518 return getSourceAccountingLines();
519 }
520
521
522
523
524
525
526 protected List getPersistedSourceAccountingLinesForComparison() {
527 return SpringContext.getBean(AccountingLineService.class).getByDocumentHeaderId(getSourceAccountingLineClass(), getDocumentNumber());
528 }
529
530
531
532
533
534
535
536
537
538
539
540
541 protected List generateEvents(List persistedLines, List currentLines, String errorPathPrefix, TransactionalDocument document) {
542 List addEvents = new ArrayList();
543 List updateEvents = new ArrayList();
544 List reviewEvents = new ArrayList();
545 List deleteEvents = new ArrayList();
546
547
548
549 Map persistedLineMap = buildAccountingLineMap(persistedLines);
550
551
552
553 int index = 0;
554 for (Iterator i = currentLines.iterator(); i.hasNext(); index++) {
555 String indexedErrorPathPrefix = errorPathPrefix + "[" + index + "]";
556 AccountingLine currentLine = (AccountingLine) i.next();
557 Integer key = currentLine.getSequenceNumber();
558
559 AccountingLine persistedLine = (AccountingLine) persistedLineMap.get(key);
560
561 if (persistedLine != null) {
562
563 if (!currentLine.isLike(persistedLine)) {
564 UpdateAccountingLineEvent updateEvent = new UpdateAccountingLineEvent(indexedErrorPathPrefix, document, persistedLine, currentLine);
565 updateEvents.add(updateEvent);
566 }
567 else {
568 ReviewAccountingLineEvent reviewEvent = new ReviewAccountingLineEvent(indexedErrorPathPrefix, document, currentLine);
569 reviewEvents.add(reviewEvent);
570 }
571
572 persistedLineMap.remove(key);
573 }
574 else {
575
576 AddAccountingLineEvent addEvent = new AddAccountingLineEvent(indexedErrorPathPrefix, document, currentLine);
577 addEvents.add(addEvent);
578 }
579 }
580
581
582 for (Iterator i = persistedLineMap.entrySet().iterator(); i.hasNext();) {
583
584 String groupErrorPathPrefix = errorPathPrefix + OLEConstants.ACCOUNTING_LINE_GROUP_SUFFIX;
585 Map.Entry e = (Map.Entry) i.next();
586 AccountingLine persistedLine = (AccountingLine) e.getValue();
587 DeleteAccountingLineEvent deleteEvent = new DeleteAccountingLineEvent(groupErrorPathPrefix, document, persistedLine, true);
588 deleteEvents.add(deleteEvent);
589 }
590
591
592
593
594 List lineEvents = new ArrayList();
595 lineEvents.addAll(reviewEvents);
596 lineEvents.addAll(updateEvents);
597 lineEvents.addAll(addEvents);
598 lineEvents.addAll(deleteEvents);
599
600 return lineEvents;
601 }
602
603
604
605
606
607
608 protected Map buildAccountingLineMap(List accountingLines) {
609 Map lineMap = new HashMap();
610
611 for (Iterator i = accountingLines.iterator(); i.hasNext();) {
612 AccountingLine accountingLine = (AccountingLine) i.next();
613 Integer sequenceNumber = accountingLine.getSequenceNumber();
614
615 Object oldLine = lineMap.put(sequenceNumber, accountingLine);
616
617
618 if (oldLine != null) {
619 throw new IllegalStateException("sequence number collision detected for sequence number " + sequenceNumber);
620 }
621 }
622
623 return lineMap;
624 }
625
626
627
628
629
630
631
632 @Override
633 public boolean generateGeneralLedgerPendingEntries(GeneralLedgerPendingEntrySourceDetail glpeSourceDetail, GeneralLedgerPendingEntrySequenceHelper sequenceHelper) {
634 LOG.debug("processGenerateGeneralLedgerPendingEntries(AccountingDocument, AccountingLine, GeneralLedgerPendingEntrySequenceHelper) - start");
635
636
637
638 GeneralLedgerPendingEntry explicitEntry = new GeneralLedgerPendingEntry();
639 processExplicitGeneralLedgerPendingEntry(sequenceHelper, glpeSourceDetail, explicitEntry);
640
641
642 sequenceHelper.increment();
643
644
645 GeneralLedgerPendingEntry offsetEntry = new GeneralLedgerPendingEntry(explicitEntry);
646 boolean success = processOffsetGeneralLedgerPendingEntry(sequenceHelper, glpeSourceDetail, explicitEntry, offsetEntry);
647
648 LOG.debug("processGenerateGeneralLedgerPendingEntries(AccountingDocument, AccountingLine, GeneralLedgerPendingEntrySequenceHelper) - end");
649 return success;
650 }
651
652
653
654
655
656
657
658
659
660
661
662 protected void processExplicitGeneralLedgerPendingEntry(GeneralLedgerPendingEntrySequenceHelper sequenceHelper, GeneralLedgerPendingEntrySourceDetail glpeSourceDetail, GeneralLedgerPendingEntry explicitEntry) {
663 LOG.debug("processExplicitGeneralLedgerPendingEntry(AccountingDocument, GeneralLedgerPendingEntrySequenceHelper, AccountingLine, GeneralLedgerPendingEntry) - start");
664
665
666 SpringContext.getBean(GeneralLedgerPendingEntryService.class).populateExplicitGeneralLedgerPendingEntry(this, glpeSourceDetail, sequenceHelper, explicitEntry);
667
668
669 customizeExplicitGeneralLedgerPendingEntry(glpeSourceDetail, explicitEntry);
670
671 addPendingEntry(explicitEntry);
672
673 LOG.debug("processExplicitGeneralLedgerPendingEntry(AccountingDocument, GeneralLedgerPendingEntrySequenceHelper, AccountingLine, GeneralLedgerPendingEntry) - end");
674 }
675
676
677
678
679
680
681
682
683
684
685
686 protected boolean processOffsetGeneralLedgerPendingEntry(GeneralLedgerPendingEntrySequenceHelper sequenceHelper, GeneralLedgerPendingEntrySourceDetail postable, GeneralLedgerPendingEntry explicitEntry, GeneralLedgerPendingEntry offsetEntry) {
687 LOG.debug("processOffsetGeneralLedgerPendingEntry(AccountingDocument, GeneralLedgerPendingEntrySequenceHelper, AccountingLine, GeneralLedgerPendingEntry, GeneralLedgerPendingEntry) - start");
688
689
690 boolean success = SpringContext.getBean(GeneralLedgerPendingEntryService.class).populateOffsetGeneralLedgerPendingEntry(getPostingYear(), explicitEntry, sequenceHelper, offsetEntry);
691
692
693 success &= customizeOffsetGeneralLedgerPendingEntry(postable, explicitEntry, offsetEntry);
694
695 addPendingEntry(offsetEntry);
696
697 LOG.debug("processOffsetGeneralLedgerPendingEntry(AccountingDocument, GeneralLedgerPendingEntrySequenceHelper, AccountingLine, GeneralLedgerPendingEntry, GeneralLedgerPendingEntry) - end");
698 return success;
699 }
700
701
702
703
704
705
706
707
708
709 protected String getEntryValue(String preferredString, String secondaryString) {
710 return (StringUtils.isNotBlank(preferredString) ? preferredString : secondaryString);
711 }
712
713
714
715
716 @Override
717 public abstract boolean isDebit(GeneralLedgerPendingEntrySourceDetail postable);
718
719
720
721
722
723
724
725 @Override
726 public boolean generateDocumentGeneralLedgerPendingEntries(GeneralLedgerPendingEntrySequenceHelper sequenceHelper) {
727 return true;
728 }
729
730
731
732
733
734
735
736 @Override
737 public KualiDecimal getGeneralLedgerPendingEntryAmountForDetail(GeneralLedgerPendingEntrySourceDetail postable) {
738 LOG.debug("getGeneralLedgerPendingEntryAmountForAccountingLine(AccountingLine) - start");
739
740 KualiDecimal returnKualiDecimal = postable.getAmount().abs();
741 LOG.debug("getGeneralLedgerPendingEntryAmountForAccountingLine(AccountingLine) - end");
742 return returnKualiDecimal;
743 }
744
745 @Override
746 public Class<? extends AccountingDocument> getDocumentClassForAccountingLineValueAllowedValidation() {
747 return this.getClass();
748 }
749
750
751
752
753
754 @Override
755 public boolean isDocumentFinalOrProcessed() {
756 boolean isDocumentFinalOrProcessed = false;
757 if(ObjectUtils.isNotNull(getDocumentHeader().getDocumentNumber())) {
758 if(getDocumentHeader().hasWorkflowDocument()) {
759 if(getDocumentHeader().getWorkflowDocument().isFinal() || getDocumentHeader().getWorkflowDocument().isProcessed()) {
760 isDocumentFinalOrProcessed = true;
761 }
762 }
763
764 }
765
766 return isDocumentFinalOrProcessed;
767
768 }
769 }