argos/dmp-backend/web/src/main/java/eu/eudat/logic/utilities/documents/word/WordBuilder.java

287 lines
14 KiB
Java

package eu.eudat.logic.utilities.documents.word;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.logic.services.forms.VisibilityRuleService;
import eu.eudat.logic.utilities.documents.types.ParagraphStyle;
import eu.eudat.logic.utilities.interfaces.ApplierWithValue;
import eu.eudat.models.data.components.commons.datafield.CheckBoxData;
import eu.eudat.models.data.components.commons.datafield.ComboBoxData;
import eu.eudat.models.data.user.components.datasetprofile.Field;
import eu.eudat.models.data.user.components.datasetprofile.FieldSet;
import eu.eudat.models.data.user.components.datasetprofile.Section;
import eu.eudat.models.data.user.composite.DatasetProfilePage;
import eu.eudat.models.data.user.composite.PagedDatasetProfile;
import org.apache.poi.xwpf.usermodel.*;
import org.json.JSONArray;
import org.json.JSONObject;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTAbstractNum;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTDecimalNumber;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.CTLvl;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STNumberFormat;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.IOException;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class WordBuilder {
private static final Logger logger = LoggerFactory.getLogger(WordBuilder.class);
private Map<ParagraphStyle, ApplierWithValue<XWPFDocument, String, XWPFParagraph>> options = new HashMap<>();
private CTAbstractNum cTAbstractNum;
private BigInteger numId;
public WordBuilder() {
this.cTAbstractNum = CTAbstractNum.Factory.newInstance();
this.cTAbstractNum.setAbstractNumId(BigInteger.valueOf(1));
this.buildOptions();
}
private void buildOptions() {
this.options.put(ParagraphStyle.TEXT, (mainDocumentPart, item) -> {
XWPFParagraph paragraph = mainDocumentPart.createParagraph();
XWPFRun run = paragraph.createRun();
if (item != null)
run.setText(" " + item);
run.setFontSize(11);
return paragraph;
});
this.options.put(ParagraphStyle.TITLE, (mainDocumentPart, item) -> {
XWPFParagraph paragraph = mainDocumentPart.createParagraph();
paragraph.setStyle("Title");
paragraph.setAlignment(ParagraphAlignment.CENTER);
XWPFRun run = paragraph.createRun();
run.setText(item);
run.setBold(true);
run.setFontSize(14);
return paragraph;
});
this.options.put(ParagraphStyle.HEADER1, (mainDocumentPart, item) -> {
XWPFParagraph paragraph = mainDocumentPart.createParagraph();
paragraph.setStyle("Heading1");
XWPFRun run = paragraph.createRun();
run.setText(item);
// run.setBold(true);
// run.setFontSize(12);
// run.setStyle("0");
return paragraph;
});
this.options.put(ParagraphStyle.HEADER2, (mainDocumentPart, item) -> {
XWPFParagraph paragraph = mainDocumentPart.createParagraph();
paragraph.setStyle("Heading2");
XWPFRun run = paragraph.createRun();
run.setText(" " + item);
// run.setBold(true);
// run.setFontSize(12);
return paragraph;
});
this.options.put(ParagraphStyle.HEADER3, (mainDocumentPart, item) -> {
XWPFParagraph paragraph = mainDocumentPart.createParagraph();
paragraph.setStyle("Heading3");
XWPFRun run = paragraph.createRun();
run.setText(" " + item);
// run.setBold(true);
// run.setFontSize(11);
return paragraph;
});
this.options.put(ParagraphStyle.HEADER4, (mainDocumentPart, item) -> {
XWPFParagraph paragraph = mainDocumentPart.createParagraph();
paragraph.setStyle("Heading4");
XWPFRun run = paragraph.createRun();
run.setText(item);
return paragraph;
});
this.options.put(ParagraphStyle.HEADER5, (mainDocumentPart, item) -> {
XWPFParagraph paragraph = mainDocumentPart.createParagraph();
paragraph.setStyle("Heading5");
XWPFRun run = paragraph.createRun();
run.setText(" " + item);
return paragraph;
});
this.options.put(ParagraphStyle.HEADER6, (mainDocumentPart, item) -> {
XWPFParagraph paragraph = mainDocumentPart.createParagraph();
paragraph.setStyle("Heading6");
XWPFRun run = paragraph.createRun();
run.setText(" " + item);
return paragraph;
});
this.options.put(ParagraphStyle.FOOTER, (mainDocumentPart, item) -> {
XWPFParagraph paragraph = mainDocumentPart.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText(item);
return paragraph;
});
this.options.put(ParagraphStyle.COMMENT, (mainDocumentPart, item) -> {
XWPFParagraph paragraph = mainDocumentPart.createParagraph();
XWPFRun run = paragraph.createRun();
run.setText(item);
run.setItalic(true);
return paragraph;
});
}
public XWPFDocument build(XWPFDocument document, PagedDatasetProfile pagedDatasetProfile, VisibilityRuleService visibilityRuleService) throws IOException {
createPages(pagedDatasetProfile.getPages(), document, true, visibilityRuleService);
XWPFAbstractNum abstractNum = new XWPFAbstractNum(cTAbstractNum);
XWPFNumbering numbering = document.createNumbering();
BigInteger abstractNumID = numbering.addAbstractNum(abstractNum);
this.numId = numbering.addNum(abstractNumID);
createPages(pagedDatasetProfile.getPages(), document, false, visibilityRuleService);
return document;
}
private void createPages(List<DatasetProfilePage> datasetProfilePages, XWPFDocument mainDocumentPart, Boolean createListing, VisibilityRuleService visibilityRuleService) {
datasetProfilePages.forEach(item -> {
createSections(item.getSections(), mainDocumentPart, ParagraphStyle.HEADER4, 0, createListing, visibilityRuleService);
});
}
private void createSections(List<Section> sections, XWPFDocument mainDocumentPart, ParagraphStyle style, Integer indent, Boolean createListing, VisibilityRuleService visibilityRuleService) {
if (createListing) this.addListing(mainDocumentPart, indent, false, true);
sections.forEach(section -> {
if (visibilityRuleService.isElementVisible(section.getId())) {
if (!createListing) {
XWPFParagraph paragraph = addParagraphContent(section.getNumbering() + " " + section.getTitle(), mainDocumentPart, style, numId);
CTDecimalNumber number = paragraph.getCTP().getPPr().getNumPr().addNewIlvl();
number.setVal(BigInteger.valueOf(indent));
}
createSections(section.getSections(), mainDocumentPart, ParagraphStyle.HEADER5, 1, createListing, visibilityRuleService);
createCompositeFields(section.getCompositeFields(), mainDocumentPart, 2, createListing, visibilityRuleService);
}
});
}
private void createCompositeFields(List<FieldSet> compositeFields, XWPFDocument mainDocumentPart, Integer indent, Boolean createListing, VisibilityRuleService visibilityRuleService) {
if (createListing) this.addListing(mainDocumentPart, indent, true, true);
compositeFields.forEach(compositeField -> {
if (visibilityRuleService.isElementVisible(compositeField.getId()) && hasVisibleFields(compositeField, visibilityRuleService)) {
if (compositeField.getTitle() != null && !compositeField.getTitle().isEmpty() && !createListing) {
XWPFParagraph paragraph = addParagraphContent(compositeField.getNumbering() + " " + compositeField.getTitle(), mainDocumentPart, ParagraphStyle.HEADER6, numId);
CTDecimalNumber number = paragraph.getCTP().getPPr().getNumPr().addNewIlvl();
number.setVal(BigInteger.valueOf(indent));
}
createFields(compositeField.getFields(), mainDocumentPart, 3, createListing, visibilityRuleService);
if (compositeField.getMultiplicityItems() != null && !compositeField.getMultiplicityItems().isEmpty()) {
for (FieldSet multiplicityFieldset : compositeField.getMultiplicityItems()) {
createFields(multiplicityFieldset.getFields(), mainDocumentPart, 3, createListing, visibilityRuleService);
}
}
if (compositeField.getHasCommentField() && compositeField.getCommentFieldValue() != null && !compositeField.getCommentFieldValue().isEmpty() && !createListing) {
XWPFParagraph paragraph = addParagraphContent("Comment: " + compositeField.getCommentFieldValue(), mainDocumentPart, ParagraphStyle.COMMENT, numId);
CTDecimalNumber number = paragraph.getCTP().getPPr().getNumPr().addNewIlvl();
number.setVal(BigInteger.valueOf(indent));
}
}
});
}
private void createFields(List<Field> fields, XWPFDocument mainDocumentPart, Integer indent, Boolean createListing, VisibilityRuleService visibilityRuleService) {
if (createListing) this.addListing(mainDocumentPart, indent, false, false);
fields.forEach(field -> {
if (visibilityRuleService.isElementVisible(field.getId())) {
if (!createListing) {
try {
XWPFParagraph paragraph = addParagraphContent(this.formatter(field), mainDocumentPart, ParagraphStyle.TEXT, numId);
CTDecimalNumber number = paragraph.getCTP().getPPr().getNumPr().addNewIlvl();
number.setVal(BigInteger.valueOf(indent));
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
}
});
}
public XWPFParagraph addParagraphContent(String text, XWPFDocument mainDocumentPart, ParagraphStyle style, BigInteger numId) {
XWPFParagraph paragraph = this.options.get(style).apply(mainDocumentPart, text);
if (numId != null) {
paragraph.setNumID(numId);
}
return paragraph;
}
private void addListing(XWPFDocument document, int indent, Boolean question, Boolean hasIndication) {
CTLvl cTLvl = this.cTAbstractNum.addNewLvl();
String textLevel = "";
for (int i = 0; i <= indent; i++) {
textLevel += "%" + (i + 1) + ".";
}
if (question) {
cTLvl.addNewNumFmt().setVal(STNumberFormat.DECIMAL);
cTLvl.setIlvl(BigInteger.valueOf(indent));
} else if (!question && hasIndication) {
cTLvl.addNewNumFmt().setVal(STNumberFormat.DECIMAL);
cTLvl.setIlvl(BigInteger.valueOf(indent));
}
if (!question && !hasIndication) {
cTLvl.addNewNumFmt().setVal(STNumberFormat.NONE);
cTLvl.setIlvl(BigInteger.valueOf(indent));
}
}
private String formatter(Field field) throws IOException {
switch (field.getViewStyle().getRenderStyle()) {
case "combobox": {
String comboboxType = ((ComboBoxData) field.getData()).getType();
if (comboboxType.equals("autocomplete")) {
ObjectMapper mapper = new ObjectMapper();
if (field.getValue() == null) return null;
Map<String, String> map = new HashMap<>();
if (!field.getValue().equals("")) {
try {
JSONArray jsonarray = new JSONArray(field.getValue().toString());
for (int i = 0; i < jsonarray.length(); i++) {
JSONObject jsonobject = jsonarray.getJSONObject(i);
String id = jsonobject.getString("id");
String label = jsonobject.getString("label");
if (id != null && label != null) {
map.put(id, label);
}
}
} catch (Exception e) {
Map<String, String> exMap = mapper.readValue(field.getValue().toString(), new TypeReference<Map<String, String>>() {
});
return exMap.get("label");
}
}
StringBuilder sb = new StringBuilder();
int index = 0;
for (Map.Entry<String, String> entry : map.entrySet()) {
sb.append(entry.getValue());
if (index != map.size() - 1) sb.append(", ");
index++;
}
return sb.toString();
} else if (comboboxType.equals("wordlist")) {
return field.getValue().toString();
}
}
case "booleanDecision":
if (field.getValue() != null && field.getValue().equals("true")) return "Yes";
else return "No";
case "radiobox":
return field.getValue().toString();
case "checkBox":
CheckBoxData data = (CheckBoxData) field.getData();
if (field.getValue() == null || field.getValue().equals("false")) return null;
return data.getLabel();
case "freetext":
return field.getValue().toString();
case "textarea":
return field.getValue().toString();
case "datepicker":
return field.getValue().toString();
}
return null;
}
private boolean hasVisibleFields(FieldSet compositeFields, VisibilityRuleService visibilityRuleService) {
return compositeFields.getFields().stream().anyMatch(field -> visibilityRuleService.isElementVisible(field.getId()));
}
}