2018-06-27 12:29:21 +02:00
|
|
|
package eu.eudat.logic.utilities.documents.word;
|
2018-03-01 10:14:10 +01:00
|
|
|
|
2018-10-19 11:59:54 +02:00
|
|
|
import com.fasterxml.jackson.core.type.TypeReference;
|
|
|
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
2018-10-08 17:14:27 +02:00
|
|
|
import eu.eudat.logic.services.forms.VisibilityRuleService;
|
2018-06-27 12:29:21 +02:00
|
|
|
import eu.eudat.logic.utilities.documents.types.ParagraphStyle;
|
2018-10-08 17:14:27 +02:00
|
|
|
import eu.eudat.logic.utilities.interfaces.ApplierWithValue;
|
2018-10-19 11:59:54 +02:00
|
|
|
import eu.eudat.models.data.components.commons.datafield.CheckBoxData;
|
|
|
|
import eu.eudat.models.data.components.commons.datafield.ComboBoxData;
|
2018-06-27 12:29:21 +02:00
|
|
|
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;
|
2018-03-01 10:14:10 +01:00
|
|
|
import org.apache.poi.xwpf.usermodel.*;
|
2019-06-07 10:37:16 +02:00
|
|
|
import org.json.JSONArray;
|
|
|
|
import org.json.JSONObject;
|
2018-03-01 10:14:10 +01:00
|
|
|
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;
|
2020-01-16 16:46:24 +01:00
|
|
|
import org.slf4j.Logger;
|
|
|
|
import org.slf4j.LoggerFactory;
|
2018-03-01 10:14:10 +01:00
|
|
|
|
2018-10-08 17:14:27 +02:00
|
|
|
import java.io.IOException;
|
2018-03-01 10:14:10 +01:00
|
|
|
import java.math.BigInteger;
|
|
|
|
import java.util.HashMap;
|
|
|
|
import java.util.List;
|
|
|
|
import java.util.Map;
|
|
|
|
|
|
|
|
public class WordBuilder {
|
2020-01-16 16:46:24 +01:00
|
|
|
private static final Logger logger = LoggerFactory.getLogger(WordBuilder.class);
|
2018-03-01 10:14:10 +01:00
|
|
|
|
2018-03-05 17:18:45 +01:00
|
|
|
private Map<ParagraphStyle, ApplierWithValue<XWPFDocument, String, XWPFParagraph>> options = new HashMap<>();
|
2018-03-01 10:14:10 +01:00
|
|
|
private CTAbstractNum cTAbstractNum;
|
|
|
|
private BigInteger numId;
|
|
|
|
|
|
|
|
public WordBuilder() {
|
|
|
|
this.cTAbstractNum = CTAbstractNum.Factory.newInstance();
|
|
|
|
this.cTAbstractNum.setAbstractNumId(BigInteger.valueOf(1));
|
2018-10-18 11:33:13 +02:00
|
|
|
this.buildOptions();
|
2018-03-01 10:14:10 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
private void buildOptions() {
|
|
|
|
this.options.put(ParagraphStyle.TEXT, (mainDocumentPart, item) -> {
|
|
|
|
XWPFParagraph paragraph = mainDocumentPart.createParagraph();
|
|
|
|
XWPFRun run = paragraph.createRun();
|
2019-05-22 10:53:30 +02:00
|
|
|
if (item != null)
|
2019-10-31 10:16:29 +01:00
|
|
|
run.setText(" " + item);
|
2018-03-01 10:14:10 +01:00
|
|
|
run.setFontSize(11);
|
|
|
|
return paragraph;
|
|
|
|
});
|
|
|
|
this.options.put(ParagraphStyle.TITLE, (mainDocumentPart, item) -> {
|
|
|
|
XWPFParagraph paragraph = mainDocumentPart.createParagraph();
|
2018-10-18 11:33:13 +02:00
|
|
|
paragraph.setStyle("Title");
|
|
|
|
paragraph.setAlignment(ParagraphAlignment.CENTER);
|
2018-03-01 10:14:10 +01:00
|
|
|
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();
|
2018-10-18 11:33:13 +02:00
|
|
|
paragraph.setStyle("Heading1");
|
2018-03-01 10:14:10 +01:00
|
|
|
XWPFRun run = paragraph.createRun();
|
|
|
|
run.setText(item);
|
2019-10-30 13:30:31 +01:00
|
|
|
// run.setBold(true);
|
|
|
|
// run.setFontSize(12);
|
|
|
|
// run.setStyle("0");
|
2018-03-01 10:14:10 +01:00
|
|
|
return paragraph;
|
|
|
|
});
|
|
|
|
this.options.put(ParagraphStyle.HEADER2, (mainDocumentPart, item) -> {
|
|
|
|
XWPFParagraph paragraph = mainDocumentPart.createParagraph();
|
2018-10-18 11:33:13 +02:00
|
|
|
paragraph.setStyle("Heading2");
|
2018-03-01 10:14:10 +01:00
|
|
|
XWPFRun run = paragraph.createRun();
|
2019-10-31 10:16:29 +01:00
|
|
|
run.setText(" " + item);
|
2019-10-30 13:30:31 +01:00
|
|
|
// run.setBold(true);
|
|
|
|
// run.setFontSize(12);
|
2018-03-01 10:14:10 +01:00
|
|
|
return paragraph;
|
|
|
|
});
|
|
|
|
this.options.put(ParagraphStyle.HEADER3, (mainDocumentPart, item) -> {
|
|
|
|
XWPFParagraph paragraph = mainDocumentPart.createParagraph();
|
2018-10-18 11:33:13 +02:00
|
|
|
paragraph.setStyle("Heading3");
|
2018-03-01 10:14:10 +01:00
|
|
|
XWPFRun run = paragraph.createRun();
|
2019-10-31 10:16:29 +01:00
|
|
|
run.setText(" " + item);
|
2019-10-30 13:30:31 +01:00
|
|
|
// 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();
|
2019-10-31 10:16:29 +01:00
|
|
|
run.setText(" " + item);
|
2018-03-01 10:14:10 +01:00
|
|
|
return paragraph;
|
|
|
|
});
|
2019-10-31 11:07:28 +01:00
|
|
|
this.options.put(ParagraphStyle.HEADER6, (mainDocumentPart, item) -> {
|
|
|
|
XWPFParagraph paragraph = mainDocumentPart.createParagraph();
|
|
|
|
paragraph.setStyle("Heading6");
|
|
|
|
XWPFRun run = paragraph.createRun();
|
|
|
|
run.setText(" " + item);
|
|
|
|
return paragraph;
|
|
|
|
});
|
2018-03-01 10:14:10 +01:00
|
|
|
this.options.put(ParagraphStyle.FOOTER, (mainDocumentPart, item) -> {
|
|
|
|
XWPFParagraph paragraph = mainDocumentPart.createParagraph();
|
|
|
|
XWPFRun run = paragraph.createRun();
|
|
|
|
run.setText(item);
|
|
|
|
return paragraph;
|
|
|
|
});
|
2018-10-22 12:34:39 +02:00
|
|
|
this.options.put(ParagraphStyle.COMMENT, (mainDocumentPart, item) -> {
|
|
|
|
XWPFParagraph paragraph = mainDocumentPart.createParagraph();
|
|
|
|
XWPFRun run = paragraph.createRun();
|
2019-10-30 13:30:31 +01:00
|
|
|
run.setText(item);
|
2018-10-22 12:34:39 +02:00
|
|
|
run.setItalic(true);
|
|
|
|
return paragraph;
|
|
|
|
});
|
2018-03-01 10:14:10 +01:00
|
|
|
}
|
|
|
|
|
2018-10-18 11:33:13 +02:00
|
|
|
public XWPFDocument build(XWPFDocument document, PagedDatasetProfile pagedDatasetProfile, VisibilityRuleService visibilityRuleService) throws IOException {
|
2018-03-05 17:18:45 +01:00
|
|
|
createPages(pagedDatasetProfile.getPages(), document, true, visibilityRuleService);
|
2018-03-01 10:14:10 +01:00
|
|
|
XWPFAbstractNum abstractNum = new XWPFAbstractNum(cTAbstractNum);
|
|
|
|
XWPFNumbering numbering = document.createNumbering();
|
|
|
|
BigInteger abstractNumID = numbering.addAbstractNum(abstractNum);
|
|
|
|
this.numId = numbering.addNum(abstractNumID);
|
2018-03-05 17:18:45 +01:00
|
|
|
createPages(pagedDatasetProfile.getPages(), document, false, visibilityRuleService);
|
2018-10-18 11:33:13 +02:00
|
|
|
return document;
|
2018-03-01 10:14:10 +01:00
|
|
|
}
|
|
|
|
|
2019-12-17 12:08:01 +01:00
|
|
|
private void createPages(List<DatasetProfilePage> datasetProfilePages, XWPFDocument mainDocumentPart, Boolean createListing, VisibilityRuleService visibilityRuleService) {
|
2018-03-01 10:14:10 +01:00
|
|
|
datasetProfilePages.forEach(item -> {
|
2020-02-26 12:37:54 +01:00
|
|
|
try {
|
|
|
|
createSections(item.getSections(), mainDocumentPart, ParagraphStyle.HEADER4, 0, createListing, visibilityRuleService);
|
|
|
|
} catch (Exception e) {
|
|
|
|
logger.error(e.getMessage(), e);
|
|
|
|
}
|
2018-03-01 10:14:10 +01:00
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-12-17 12:08:01 +01:00
|
|
|
private void createSections(List<Section> sections, XWPFDocument mainDocumentPart, ParagraphStyle style, Integer indent, Boolean createListing, VisibilityRuleService visibilityRuleService) {
|
2018-03-01 10:14:10 +01:00
|
|
|
if (createListing) this.addListing(mainDocumentPart, indent, false, true);
|
|
|
|
sections.forEach(section -> {
|
2018-03-05 17:18:45 +01:00
|
|
|
if (visibilityRuleService.isElementVisible(section.getId())) {
|
|
|
|
if (!createListing) {
|
2018-10-18 14:36:43 +02:00
|
|
|
XWPFParagraph paragraph = addParagraphContent(section.getNumbering() + " " + section.getTitle(), mainDocumentPart, style, numId);
|
2018-03-05 17:18:45 +01:00
|
|
|
CTDecimalNumber number = paragraph.getCTP().getPPr().getNumPr().addNewIlvl();
|
|
|
|
number.setVal(BigInteger.valueOf(indent));
|
|
|
|
}
|
2019-10-31 11:07:28 +01:00
|
|
|
createSections(section.getSections(), mainDocumentPart, ParagraphStyle.HEADER5, 1, createListing, visibilityRuleService);
|
2018-03-05 17:18:45 +01:00
|
|
|
createCompositeFields(section.getCompositeFields(), mainDocumentPart, 2, createListing, visibilityRuleService);
|
2018-03-01 10:14:10 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-12-17 12:08:01 +01:00
|
|
|
private void createCompositeFields(List<FieldSet> compositeFields, XWPFDocument mainDocumentPart, Integer indent, Boolean createListing, VisibilityRuleService visibilityRuleService) {
|
2018-03-01 10:14:10 +01:00
|
|
|
if (createListing) this.addListing(mainDocumentPart, indent, true, true);
|
|
|
|
compositeFields.forEach(compositeField -> {
|
2019-02-15 08:52:44 +01:00
|
|
|
if (visibilityRuleService.isElementVisible(compositeField.getId()) && hasVisibleFields(compositeField, visibilityRuleService)) {
|
2018-03-05 17:18:45 +01:00
|
|
|
if (compositeField.getTitle() != null && !compositeField.getTitle().isEmpty() && !createListing) {
|
2019-10-31 11:07:28 +01:00
|
|
|
XWPFParagraph paragraph = addParagraphContent(compositeField.getNumbering() + " " + compositeField.getTitle(), mainDocumentPart, ParagraphStyle.HEADER6, numId);
|
2018-03-05 17:18:45 +01:00
|
|
|
CTDecimalNumber number = paragraph.getCTP().getPPr().getNumPr().addNewIlvl();
|
|
|
|
number.setVal(BigInteger.valueOf(indent));
|
|
|
|
}
|
|
|
|
createFields(compositeField.getFields(), mainDocumentPart, 3, createListing, visibilityRuleService);
|
2019-10-30 13:30:31 +01:00
|
|
|
if (compositeField.getMultiplicityItems() != null && !compositeField.getMultiplicityItems().isEmpty()) {
|
2019-06-05 15:57:05 +02:00
|
|
|
for (FieldSet multiplicityFieldset : compositeField.getMultiplicityItems()) {
|
|
|
|
createFields(multiplicityFieldset.getFields(), mainDocumentPart, 3, createListing, visibilityRuleService);
|
|
|
|
}
|
|
|
|
}
|
2018-10-26 09:11:03 +02:00
|
|
|
if (compositeField.getHasCommentField() && compositeField.getCommentFieldValue() != null && !compositeField.getCommentFieldValue().isEmpty() && !createListing) {
|
2018-10-22 12:34:39 +02:00
|
|
|
XWPFParagraph paragraph = addParagraphContent("Comment: " + compositeField.getCommentFieldValue(), mainDocumentPart, ParagraphStyle.COMMENT, numId);
|
|
|
|
CTDecimalNumber number = paragraph.getCTP().getPPr().getNumPr().addNewIlvl();
|
|
|
|
number.setVal(BigInteger.valueOf(indent));
|
|
|
|
}
|
2018-03-01 10:14:10 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
2019-12-17 12:08:01 +01:00
|
|
|
private void createFields(List<Field> fields, XWPFDocument mainDocumentPart, Integer indent, Boolean createListing, VisibilityRuleService visibilityRuleService) {
|
2018-03-01 10:14:10 +01:00
|
|
|
if (createListing) this.addListing(mainDocumentPart, indent, false, false);
|
|
|
|
fields.forEach(field -> {
|
2018-03-05 17:18:45 +01:00
|
|
|
if (visibilityRuleService.isElementVisible(field.getId())) {
|
|
|
|
if (!createListing) {
|
2018-10-19 11:59:54 +02:00
|
|
|
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) {
|
2020-01-16 16:46:24 +01:00
|
|
|
logger.error(e.getMessage(), e);
|
2018-10-19 11:59:54 +02:00
|
|
|
}
|
2018-03-05 17:18:45 +01:00
|
|
|
}
|
2018-03-01 10:14:10 +01:00
|
|
|
}
|
|
|
|
});
|
|
|
|
}
|
|
|
|
|
|
|
|
public XWPFParagraph addParagraphContent(String text, XWPFDocument mainDocumentPart, ParagraphStyle style, BigInteger numId) {
|
|
|
|
XWPFParagraph paragraph = this.options.get(style).apply(mainDocumentPart, text);
|
2018-10-18 11:33:13 +02:00
|
|
|
if (numId != null) {
|
|
|
|
paragraph.setNumID(numId);
|
|
|
|
}
|
2018-03-01 10:14:10 +01:00
|
|
|
return paragraph;
|
|
|
|
}
|
|
|
|
|
2019-12-17 12:08:01 +01:00
|
|
|
private void addListing(XWPFDocument document, int indent, Boolean question, Boolean hasIndication) {
|
2018-03-01 10:14:10 +01:00
|
|
|
CTLvl cTLvl = this.cTAbstractNum.addNewLvl();
|
|
|
|
|
|
|
|
String textLevel = "";
|
|
|
|
for (int i = 0; i <= indent; i++) {
|
|
|
|
textLevel += "%" + (i + 1) + ".";
|
|
|
|
}
|
|
|
|
if (question) {
|
|
|
|
cTLvl.addNewNumFmt().setVal(STNumberFormat.DECIMAL);
|
2018-03-05 17:18:45 +01:00
|
|
|
cTLvl.setIlvl(BigInteger.valueOf(indent));
|
2018-03-01 10:14:10 +01:00
|
|
|
} else if (!question && hasIndication) {
|
|
|
|
cTLvl.addNewNumFmt().setVal(STNumberFormat.DECIMAL);
|
2018-03-05 17:18:45 +01:00
|
|
|
cTLvl.setIlvl(BigInteger.valueOf(indent));
|
2018-03-01 10:14:10 +01:00
|
|
|
}
|
|
|
|
if (!question && !hasIndication) {
|
|
|
|
cTLvl.addNewNumFmt().setVal(STNumberFormat.NONE);
|
2018-03-05 17:18:45 +01:00
|
|
|
cTLvl.setIlvl(BigInteger.valueOf(indent));
|
2018-03-01 10:14:10 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-12-17 12:08:01 +01:00
|
|
|
private String formatter(Field field) throws IOException {
|
2018-10-19 11:59:54 +02:00
|
|
|
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;
|
2019-06-07 10:37:16 +02:00
|
|
|
Map<String, String> map = new HashMap<>();
|
|
|
|
if (!field.getValue().equals("")) {
|
|
|
|
try {
|
2019-12-17 12:08:01 +01:00
|
|
|
JSONArray jsonarray = new JSONArray(field.getValue().toString());
|
2019-06-07 10:37:16 +02:00
|
|
|
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);
|
|
|
|
}
|
|
|
|
}
|
2019-12-17 12:08:01 +01:00
|
|
|
} catch (Exception e) {
|
|
|
|
Map<String, String> exMap = mapper.readValue(field.getValue().toString(), new TypeReference<Map<String, String>>() {
|
2019-06-07 10:37:16 +02:00
|
|
|
});
|
|
|
|
return exMap.get("label");
|
|
|
|
}
|
|
|
|
}
|
|
|
|
StringBuilder sb = new StringBuilder();
|
2019-12-17 12:08:01 +01:00
|
|
|
int index = 0;
|
2019-06-07 10:37:16 +02:00
|
|
|
for (Map.Entry<String, String> entry : map.entrySet()) {
|
|
|
|
sb.append(entry.getValue());
|
2019-12-17 12:08:01 +01:00
|
|
|
if (index != map.size() - 1) sb.append(", ");
|
|
|
|
index++;
|
2019-06-07 10:37:16 +02:00
|
|
|
}
|
|
|
|
return sb.toString();
|
2018-10-19 11:59:54 +02:00
|
|
|
} else if (comboboxType.equals("wordlist")) {
|
2020-02-26 12:37:54 +01:00
|
|
|
return field.getValue() != null ? field.getValue().toString() : "";
|
2018-10-19 11:59:54 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
case "booleanDecision":
|
|
|
|
if (field.getValue() != null && field.getValue().equals("true")) return "Yes";
|
|
|
|
else return "No";
|
|
|
|
case "radiobox":
|
2019-12-17 12:08:01 +01:00
|
|
|
return field.getValue().toString();
|
2018-10-19 11:59:54 +02:00
|
|
|
case "checkBox":
|
|
|
|
CheckBoxData data = (CheckBoxData) field.getData();
|
2018-10-22 12:34:39 +02:00
|
|
|
if (field.getValue() == null || field.getValue().equals("false")) return null;
|
2018-10-19 11:59:54 +02:00
|
|
|
return data.getLabel();
|
|
|
|
case "freetext":
|
2019-02-15 11:26:14 +01:00
|
|
|
case "datepicker":
|
2020-02-26 12:37:54 +01:00
|
|
|
case "textarea":
|
|
|
|
return field.getValue() != null ? field.getValue().toString(): "";
|
2018-10-19 11:59:54 +02:00
|
|
|
}
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
|
2019-02-15 08:52:44 +01:00
|
|
|
private boolean hasVisibleFields(FieldSet compositeFields, VisibilityRuleService visibilityRuleService) {
|
|
|
|
return compositeFields.getFields().stream().anyMatch(field -> visibilityRuleService.isElementVisible(field.getId()));
|
|
|
|
}
|
2018-03-01 10:14:10 +01:00
|
|
|
}
|