com.hcl.domino.jna.richtext.op.RepeatTableRowOperation Maven / Gradle / Ivy
/*
* ==========================================================================
* Copyright (C) 2019-2022 HCL America, Inc. ( http://www.hcl.com/ )
* All rights reserved.
* ==========================================================================
* Licensed under the Apache License, Version 2.0 (the "License"). You may
* not use this file except in compliance with the License. You may obtain a
* copy of the License at .
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
* ==========================================================================
*/
package com.hcl.domino.jna.richtext.op;
import java.text.MessageFormat;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.function.BiFunction;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import com.hcl.domino.commons.richtext.RichTextUtil;
import com.hcl.domino.commons.richtext.conversion.PatternBasedTextReplacementConversion;
import com.hcl.domino.data.Document;
import com.hcl.domino.data.DocumentClass;
import com.hcl.domino.data.Item;
import com.hcl.domino.design.DesignElement;
import com.hcl.domino.design.GenericFormOrSubform;
import com.hcl.domino.design.RichTextBuilder.RichTextBuilderContext;
import com.hcl.domino.design.RichTextBuilder.RichTextBuilderOperation;
import com.hcl.domino.richtext.RichTextRecordList;
import com.hcl.domino.richtext.RichTextTableParser;
import com.hcl.domino.richtext.RichTextWriter;
import com.hcl.domino.richtext.records.CDField;
import com.hcl.domino.richtext.records.CDPreTableBegin;
import com.hcl.domino.richtext.records.CDTableBegin;
import com.hcl.domino.richtext.records.CDTableCell;
import com.hcl.domino.richtext.records.CDTableEnd;
import com.hcl.domino.richtext.records.CDText;
import com.hcl.domino.richtext.records.RichTextRecord;
/**
* RichText builder operation to repeat a specified table row and apply text replacements
* on each repetition
*
* @author Karsten Lehmann
*/
public class RepeatTableRowOperation implements RichTextBuilderOperation {
private String itemName;
private int reqRowIdx;
private int nrOfRows;
private Map> rowFunctions;
public RepeatTableRowOperation(String itemName, int rowIdx, int nrOfRows,
Map> rowFunctions) {
this.itemName = itemName;
this.reqRowIdx = rowIdx;
this.nrOfRows = nrOfRows;
this.rowFunctions = rowFunctions==null ? Collections.emptyMap() : rowFunctions;
}
@Override
public Document apply(RichTextBuilderContext> ctx, Document doc) {
//create a copy of the existing richtext for iteration
Document docCopy = doc.copyToDatabase(doc.getParentDatabase());
//remove richtext item from work doc
while (doc.hasItem(itemName)) {
doc.removeItem(itemName);
}
//rebuild richtext item in work doc
try (RichTextWriter rtWriter = doc.createRichTextItem(itemName);) {
RichTextRecordList rt = docCopy.getRichTextItem(itemName);
ListIterator> rtIterator = rt.listIterator();
RichTextTableParser tableParser = new RichTextTableParser(rtIterator) {
@Override
public boolean cellFound(int tableIndex, short rowIdx, short colIdx, CDTableCell cellRecord,
Collection> cellContent) {
//cell parsing not required here
return true;
}
@Override
public boolean tableBeginFound(int tableIndex, Collection> tableHeaderRecords,
CDTableBegin tableBegin, Collection> nonRowRecords) {
CDPreTableBegin preTableBegin = tableHeaderRecords
.stream()
.filter(CDPreTableBegin.class::isInstance)
.map(CDPreTableBegin.class::cast)
.findFirst()
.orElse(null);
if (preTableBegin!=null) {
if (preTableBegin.getRows() > reqRowIdx) {
//correct total number of rows if there enough
preTableBegin.setRows((short) (preTableBegin.getRows() + nrOfRows - 1));
}
}
tableHeaderRecords.forEach(rtWriter::addRichTextRecord);
rtWriter.addRichTextRecord(tableBegin);
nonRowRecords.forEach(rtWriter::addRichTextRecord);
return true;
}
@Override
public boolean rowFound(int tableIndex, short rowIndex, Collection> records) {
if (rowIndex < reqRowIdx) {
//row is before repeat
records.forEach(rtWriter::addRichTextRecord);
}
else if (rowIndex == reqRowIdx) {
for (int i=0; i rowRecord : records) {
if (rowRecord instanceof CDTableBegin) {
nestedTableDepth++;
}
else if (rowRecord instanceof CDTableEnd) {
nestedTableDepth--;
}
else if (nestedTableDepth==0 && rowRecord instanceof CDTableCell) {
CDTableCell cellRecord = (CDTableCell) rowRecord;
short newRowNumber = (short) (rowIndex + nrOfRows - 1);
cellRecord.setRow(newRowNumber);
rtWriter.addRichTextRecord(rowRecord);
}
else {
rtWriter.addRichTextRecord(rowRecord);
}
}
}
return true;
}
private void addRowRecordsWithPlaceholders(int idx, Collection> records,
Document doc, RichTextWriter rtWriter) {
Document docTmp = doc.getParentDatabase().createDocument();
try (RichTextWriter tmpWriter = docTmp.createRichTextItem("body")) {
records.forEach(tmpWriter::addRichTextRecord);
}
rowFunctions.entrySet()
.stream()
.forEach((entry) -> {
Pattern pattern = entry.getKey();
BiFunction fct = entry.getValue();
docTmp.convertRichTextItem("body", new PatternBasedTextReplacementConversion(pattern,
(matcher, fontStyle, tmpRichTextWriter) -> {
Object newContent = fct.apply(idx, matcher);
if (newContent==null) {
newContent = "";
}
if (newContent instanceof String) {
String newContentStr = (String) newContent;
if (newContentStr.length()>0) {
tmpRichTextWriter.addRichTextRecord(CDText.class, (newContentTxtRecord) -> {
newContentTxtRecord.setStyle(fontStyle);
newContentTxtRecord.setText(newContentStr);
});
}
}
else if (newContent instanceof RichTextBuilderContext>) {
Document docToInsert = null;
Object result = ((RichTextBuilderContext>)newContent).build();
if (result instanceof Document) {
docToInsert = (Document) result;
}
else if (result instanceof DesignElement) {
docToInsert = ((DesignElement)result).getDocument();
}
if (docToInsert!=null) {
// tmpRichTextWriter.addRichText(docToInsert, ((RichTextBuilderContext>)newContent).getItemName());
RichTextUtil.addOtherRichTextItem(docTmp, tmpRichTextWriter, docToInsert,
((RichTextBuilderContext>)newContent).getItemName(), true);
}
}
else if (newContent instanceof GenericFormOrSubform>) {
Document docToInsert = ((GenericFormOrSubform>)newContent).getDocument();
// tmpRichTextWriter.addRichText(docToInsert, "$body");
RichTextUtil.addOtherRichTextItem(docTmp, tmpRichTextWriter, docToInsert, "$body", true);
}
else if (newContent instanceof Document) {
Set docClass = ((Document)newContent).getDocumentClass();
String otherRTItemName = docClass.contains(DocumentClass.DATA) ? "body" : "$body";
// tmpRichTextWriter.addRichText((Document) newContent, otherRTItemName);
RichTextUtil.addOtherRichTextItem(docTmp, tmpRichTextWriter, (Document) newContent, otherRTItemName, true);
}
else {
throw new IllegalArgumentException(MessageFormat.format("Invalid replacement value type: {0}", newContent.getClass().getName()));
}
}));
});
List> fixedRecords = new ArrayList<>();
docTmp.getRichTextItem("body")
.stream()
.forEach((record) -> {
if (record instanceof CDTableCell) {
CDTableCell cellRecord = (CDTableCell) record;
//fix row index
short oldRowIndex = cellRecord.getRow();
short newRowIndex = (short) (oldRowIndex + idx);
cellRecord.setRow(newRowIndex);
}
fixedRecords.add(record);
});
if (doc.getDocumentClass().contains(DocumentClass.FORM)) {
//copy LS code for fields
Set fieldNames = fixedRecords
.stream()
.filter(CDField.class::isInstance)
.map(CDField.class::cast)
.map(CDField::getName)
.collect(Collectors.toSet());
for (String currFieldName : fieldNames) {
Optional- lsCodeItem = docTmp.getFirstItem("$$" + currFieldName);
if (lsCodeItem.isPresent()) {
lsCodeItem.get().copyToDocument(doc, false);
}
}
}
fixedRecords.forEach(rtWriter::addRichTextRecord);
}
@Override
public boolean tableEndFound(int tableIndex, CDTableEnd tableEnd) {
rtWriter.addRichTextRecord(tableEnd);
//stop parsing after first table:
return false;
}
@Override
public boolean nonTableRecordFound(RichTextRecord> record) {
rtWriter.addRichTextRecord(record);
return true;
}
};
tableParser.parse();
//flush remaining records
rtIterator.forEachRemaining(rtWriter::addRichTextRecord);
}
return doc;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy