package eu.eudat.logic.utilities.documents.word; import com.fasterxml.jackson.core.JsonParseException; import com.fasterxml.jackson.databind.DeserializationFeature; 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.components.commons.datafield.WordListData; 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.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.*; public class WordBuilder { private static final Logger logger = LoggerFactory.getLogger(WordBuilder.class); private Map> 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 datasetProfilePages, XWPFDocument mainDocumentPart, Boolean createListing, VisibilityRuleService visibilityRuleService) { datasetProfilePages.forEach(item -> { try { createSections(item.getSections(), mainDocumentPart, ParagraphStyle.HEADER4, 0, createListing, visibilityRuleService); } catch (Exception e) { logger.error(e.getMessage(), e); } }); } private void createSections(List
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
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 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 { String comboboxType = null; switch (field.getViewStyle().getRenderStyle()) { case "researchers": case "projects": case "organizations": case "externalDatasets": case "dataRepositories": case "registries": case "services": case "tags": case "currency": comboboxType = "autocomplete"; case "combobox": { if (comboboxType == null) { comboboxType = ((ComboBoxData) field.getData()).getType(); } if (comboboxType.equals("autocomplete")) { ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY, true); if (field.getValue() == null) return null; List> mapList = new ArrayList<>(); if (!field.getValue().equals("") && field.getValue().toString() != null) { try { mapList = Arrays.asList(mapper.readValue(field.getValue().toString(), HashMap[].class)); }catch (Exception e) { logger.warn(e.getMessage(), e); Map map = new HashMap<>(); map.put("label", field.getValue().toString()); mapList.add(map); } /*try { if (field.getValue().toString().startsWith("[")) { JSONArray jsonarray = new JSONArray(field.getValue().toString()); for (int i = 0; i < jsonarray.length(); i++) { JSONObject jsonObject = jsonarray.getJSONObject(i); String id = jsonObject.get("id").toString(); String label = jsonObject.getString("label"); if (id != null && label != null) { map.put(id, label); } } } else if (field.getValue().toString().startsWith("{")) { JSONObject jsonObject = new JSONObject(field.getValue().toString()); String id = jsonObject.get("id").toString(); String label = jsonObject.getString("label"); if (id != null && label != null) { map.put(id, label); } } } catch (Exception e) { Map exMap = mapper.readValue(field.getValue().toString(), new TypeReference>() { }); return exMap.get("label"); }*/ } StringBuilder sb = new StringBuilder(); int index = 0; for (Map map: mapList) { /*if (!map.containsKey("label") && !map.containsKey("description")) { logger.error("Value is missing the \"label\" and the \"description\" attributes"); map.put("label", "unknown Name"); }*/ for (Map.Entry entry : map.entrySet()) { if (entry.getValue() != null && (entry.getKey().equals("label") || entry.getKey().equals("description") || entry.getKey().equals("name"))) { sb.append(entry.getValue().toString()); break; } } if (index != mapList.size() - 1) sb.append(", "); index++; } return sb.toString(); } else if (comboboxType.equals("wordlist")) { WordListData wordListData = (WordListData) field.getData(); if (wordListData.getOptions().isEmpty() && field.getValue() != null) { logger.warn("World List has no values but the field has"); return field.getValue().toString(); } else if (field.getValue() != null){ ComboBoxData.Option selectedOption = null; for (ComboBoxData.Option option: wordListData.getOptions()) { if (option.getValue().equals(field.getValue())) { selectedOption = option; } } return selectedOption != null ? selectedOption.getLabel() : field.getValue().toString(); } return ""; } } case "booleanDecision": if (field.getValue() != null && field.getValue().equals("true")) return "Yes"; else return "No"; case "radiobox": return field.getValue() != null ? field.getValue().toString() : null; case "checkBox": CheckBoxData data = (CheckBoxData) field.getData(); if (field.getValue() == null || field.getValue().equals("false")) return null; return data.getLabel(); case "freetext": case "datepicker": case "textarea": return field.getValue() != null ? field.getValue().toString(): ""; case "datasetIdentifier": case "validation": Map identifierData; try { ObjectMapper mapper = new ObjectMapper(); identifierData = mapper.readValue(field.getValue().toString(), HashMap.class); } catch (JsonParseException ex) { identifierData = new HashMap<>(); String parsedData = field.getValue().toString().substring(1, field.getValue().toString().length() - 1); StringTokenizer commaTokens = new StringTokenizer(parsedData, ", "); while (commaTokens.hasMoreTokens()) { String token = commaTokens.nextToken(); StringTokenizer equalTokens = new StringTokenizer(token, "="); identifierData.put(equalTokens.nextToken(), equalTokens.nextToken()); } } return "id: " + identifierData.get("identifier") + ", Validation Type: " + identifierData.get("type"); } return null; } private boolean hasVisibleFields(FieldSet compositeFields, VisibilityRuleService visibilityRuleService) { return compositeFields.getFields().stream().anyMatch(field -> visibilityRuleService.isElementVisible(field.getId())); } }