HtmlToWorldBuilder.java & WordBuilder.java: Added methods for exporting inputs of a question as table.

This commit is contained in:
Konstantina Galouni 2022-11-08 14:39:23 +02:00
parent 37724380e9
commit 2bbf89e779
2 changed files with 253 additions and 5 deletions

View File

@ -25,6 +25,14 @@ public class HtmlToWorldBuilder implements NodeVisitor {
private BigInteger numberingLevel; private BigInteger numberingLevel;
private XmlCursor cursor; private XmlCursor cursor;
public static HtmlToWorldBuilder convertInTable(XWPFTableCell document, Document htmlDocument, float indentation) {
XWPFParagraph paragraph = document.addParagraph();
paragraph.setIndentFromLeft(Math.round(400 * indentation));
HtmlToWorldBuilder htmlToWorldBuilder = new HtmlToWorldBuilder(paragraph, indentation, null);
NodeTraversor.traverse(htmlToWorldBuilder, htmlDocument);
return htmlToWorldBuilder;
}
public static HtmlToWorldBuilder convert(XWPFDocument document, Document htmlDocument, float indentation) { public static HtmlToWorldBuilder convert(XWPFDocument document, Document htmlDocument, float indentation) {
XWPFParagraph paragraph = document.createParagraph(); XWPFParagraph paragraph = document.createParagraph();
paragraph.setIndentFromLeft(Math.round(400 * indentation)); paragraph.setIndentFromLeft(Math.round(400 * indentation));

View File

@ -65,6 +65,7 @@ public class WordBuilder {
).collect(Collectors.toMap(objects -> (String)objects[0], o -> (Integer)o[1])); ).collect(Collectors.toMap(objects -> (String)objects[0], o -> (Integer)o[1]));
private Map<ParagraphStyle, ApplierWithValue<XWPFDocument, Object, XWPFParagraph>> options = new HashMap<>(); private Map<ParagraphStyle, ApplierWithValue<XWPFDocument, Object, XWPFParagraph>> options = new HashMap<>();
private Map<ParagraphStyle, ApplierWithValue<XWPFTableCell, Object, XWPFParagraph>> optionsInTable = new HashMap<>();
private CTAbstractNum cTAbstractNum; private CTAbstractNum cTAbstractNum;
private BigInteger numId; private BigInteger numId;
private Integer indent; private Integer indent;
@ -78,6 +79,42 @@ public class WordBuilder {
this.imageCount = 0; this.imageCount = 0;
this.mapper = new ObjectMapper(); this.mapper = new ObjectMapper();
this.buildOptions(environment); this.buildOptions(environment);
this.buildOptionsInTable(environment);
}
private void buildOptionsInTable(Environment environment) {
this.optionsInTable.put(ParagraphStyle.TEXT, (mainDocumentPart, item) -> {
XWPFParagraph paragraph = mainDocumentPart.addParagraph();
XWPFRun run = paragraph.createRun();
if (item != null)
run.setText("" + item);
run.setFontSize(11);
return paragraph;
});
this.optionsInTable.put(ParagraphStyle.HTML, (mainDocumentPart, item) -> {
Document htmlDoc = Jsoup.parse(((String)item).replaceAll("\n", "<br>"));
HtmlToWorldBuilder htmlToWorldBuilder = HtmlToWorldBuilder.convertInTable(mainDocumentPart, htmlDoc, 0);
return htmlToWorldBuilder.getParagraph();
});
this.optionsInTable.put(ParagraphStyle.TITLE, (mainDocumentPart, item) -> {
XWPFParagraph paragraph = mainDocumentPart.addParagraph();
paragraph.setStyle("Title");
paragraph.setAlignment(ParagraphAlignment.CENTER);
XWPFRun run = paragraph.createRun();
run.setText((String)item);
run.setBold(true);
run.setFontSize(14);
return paragraph;
});
this.optionsInTable.put(ParagraphStyle.IMAGE, (mainDocumentPart, item) -> {
XWPFParagraph paragraph = mainDocumentPart.addParagraph();
XWPFRun run = paragraph.createRun();
if (item != null)
run.setText(((Map<String, String>)item).get("name"));
run.setFontSize(11);
run.setItalic(true);
return paragraph;
});
} }
private void buildOptions(Environment environment) { private void buildOptions(Environment environment) {
@ -91,7 +128,6 @@ public class WordBuilder {
}); });
this.options.put(ParagraphStyle.HTML, (mainDocumentPart, item) -> { this.options.put(ParagraphStyle.HTML, (mainDocumentPart, item) -> {
Document htmlDoc = Jsoup.parse(((String)item).replaceAll("\n", "<br>")); Document htmlDoc = Jsoup.parse(((String)item).replaceAll("\n", "<br>"));
// HtmlToWorldBuilder htmlToWorldBuilder = HtmlToWorldBuilder.convert(mainDocumentPart, htmlDoc, indent > 0 ? (indent/2.0F) * 0.8F : 0.8F);
HtmlToWorldBuilder htmlToWorldBuilder = HtmlToWorldBuilder.convert(mainDocumentPart, htmlDoc, this.indent); HtmlToWorldBuilder htmlToWorldBuilder = HtmlToWorldBuilder.convert(mainDocumentPart, htmlDoc, this.indent);
return htmlToWorldBuilder.getParagraph(); return htmlToWorldBuilder.getParagraph();
}); });
@ -287,6 +323,7 @@ public class WordBuilder {
if (createListing) this.addListing(mainDocumentPart, indent, true, true); if (createListing) this.addListing(mainDocumentPart, indent, true, true);
boolean hasValue = false; boolean hasValue = false;
boolean returnedValue = false; boolean returnedValue = false;
for (FieldSet compositeField: compositeFields) { for (FieldSet compositeField: compositeFields) {
if (visibilityRuleService.isElementVisible(compositeField.getId()) && hasVisibleFields(compositeField, visibilityRuleService)) { if (visibilityRuleService.isElementVisible(compositeField.getId()) && hasVisibleFields(compositeField, visibilityRuleService)) {
char c = 'a'; char c = 'a';
@ -299,14 +336,30 @@ public class WordBuilder {
// CTDecimalNumber number = paragraph.getCTP().getPPr().getNumPr().addNewIlvl(); // CTDecimalNumber number = paragraph.getCTP().getPPr().getNumPr().addNewIlvl();
// number.setVal(BigInteger.valueOf(indent)); // number.setVal(BigInteger.valueOf(indent));
paragraphPos = mainDocumentPart.getPosOfParagraph(paragraph); paragraphPos = mainDocumentPart.getPosOfParagraph(paragraph);
if(compositeField.getMultiplicityItems() != null && !compositeField.getMultiplicityItems().isEmpty()){ if(!compositeField.getMultiplicity().getTableView() && compositeField.getMultiplicityItems() != null && !compositeField.getMultiplicityItems().isEmpty()){
XWPFParagraph paragraphInner = addParagraphContent(c + ". ", mainDocumentPart, ParagraphStyle.TEXT, numId, indent); XWPFParagraph paragraphInner = addParagraphContent(c + ". ", mainDocumentPart, ParagraphStyle.TEXT, numId, indent);
paragraphPosInner = mainDocumentPart.getPosOfParagraph(paragraphInner); paragraphPosInner = mainDocumentPart.getPosOfParagraph(paragraphInner);
hasMultiplicityItems = true; hasMultiplicityItems = true;
multiplicityItems++; multiplicityItems++;
} }
} }
hasValue = createFields(compositeField.getFields(), mainDocumentPart, indent, createListing, visibilityRuleService, hasMultiplicityItems); XWPFTable tbl = null;
XWPFTableRow row = null;
int numOfRows = 0;
if(compositeField.getMultiplicity().getTableView()) {
tbl = mainDocumentPart.createTable();
tbl.setTableAlignment(TableRowAlign.CENTER);
mainDocumentPart.createParagraph();
createHeadersInTable(compositeField.getFields(), tbl, visibilityRuleService);
numOfRows = tbl.getRows().size();
row = tbl.createRow();
}
if(compositeField.getMultiplicity().getTableView()) {
hasValue = createFieldsInTable(compositeField.getFields(), row, indent, createListing, visibilityRuleService, hasMultiplicityItems, numOfRows);
numOfRows++;
} else {
hasValue = createFields(compositeField.getFields(), mainDocumentPart, indent, createListing, visibilityRuleService, hasMultiplicityItems);
}
if(hasValue){ if(hasValue){
returnedValue = true; returnedValue = true;
} else if(paragraphPosInner > -1){ } else if(paragraphPosInner > -1){
@ -318,7 +371,7 @@ public class WordBuilder {
List<FieldSet> list = compositeField.getMultiplicityItems().stream().sorted(Comparator.comparingInt(FieldSet::getOrdinal)).collect(Collectors.toList()); List<FieldSet> list = compositeField.getMultiplicityItems().stream().sorted(Comparator.comparingInt(FieldSet::getOrdinal)).collect(Collectors.toList());
for (FieldSet multiplicityFieldset : list) { for (FieldSet multiplicityFieldset : list) {
paragraphPosInner = -1; paragraphPosInner = -1;
if(!createListing){ if(!compositeField.getMultiplicity().getTableView() && !createListing){
c++; c++;
// addParagraphContent(c + ". ", mainDocumentPart, ParagraphStyle.HEADER6, numId); // addParagraphContent(c + ". ", mainDocumentPart, ParagraphStyle.HEADER6, numId);
XWPFParagraph paragraphInner = addParagraphContent(c + ". ", mainDocumentPart, ParagraphStyle.TEXT, numId, indent); XWPFParagraph paragraphInner = addParagraphContent(c + ". ", mainDocumentPart, ParagraphStyle.TEXT, numId, indent);
@ -327,7 +380,14 @@ public class WordBuilder {
multiplicityItems++; multiplicityItems++;
} }
// hasValue = createFields(multiplicityFieldset.getFields(), mainDocumentPart, 3, createListing, visibilityRuleService, hasMultiplicityItems); // hasValue = createFields(multiplicityFieldset.getFields(), mainDocumentPart, 3, createListing, visibilityRuleService, hasMultiplicityItems);
boolean hasValueInner = createFields(multiplicityFieldset.getFields(), mainDocumentPart, indent, createListing, visibilityRuleService, hasMultiplicityItems); boolean hasValueInner = false;
if(compositeField.getMultiplicity().getTableView()) {
row = tbl.createRow();
hasValueInner = createFieldsInTable(multiplicityFieldset.getFields(), row, indent, createListing, visibilityRuleService, hasMultiplicityItems, numOfRows);
numOfRows++;
} else {
hasValueInner = createFields(multiplicityFieldset.getFields(), mainDocumentPart, indent, createListing, visibilityRuleService, hasMultiplicityItems);
}
// if(hasValue){ // if(hasValue){
if(hasValueInner){ if(hasValueInner){
hasValue = true; hasValue = true;
@ -355,9 +415,159 @@ public class WordBuilder {
} }
} }
} }
return returnedValue; return returnedValue;
} }
private void createHeadersInTable(List<Field> fields, XWPFTable table, VisibilityRuleService visibilityRuleService) {
boolean atLeastOneHeader = false;
List<Field> tempFields = fields.stream().sorted(Comparator.comparingInt(Field::getOrdinal)).collect(Collectors.toList());
int index = 0;
XWPFTableRow row = table.getRow(0);
for (Field field: tempFields) {
if (visibilityRuleService.isElementVisible(field.getId()) && field.getExport()) {
XWPFTableCell cell;
if(index == 0) {
cell = row.getCell(0);
} else {
cell = row.createCell();
}
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.valueOf("CENTER"));
String label = ((FieldData) field.getData()).getLabel();
if(label != null && label != "") {
XWPFParagraph paragraph = cell.getParagraphs().get(0);
paragraph.setIndentationFirstLine(50);
XWPFRun run = paragraph.createRun();
run.setText(label);
run.setBold(true);
run.setFontSize(12);
paragraph.setAlignment(ParagraphAlignment.CENTER);
paragraph.setSpacingBefore(100);
atLeastOneHeader = true;
}
}
index++;
}
if(!atLeastOneHeader) {
table.removeRow(0);
}
}
private Boolean createFieldsInTable(List<Field> fields, XWPFTableRow mainDocumentPart, Integer indent, Boolean createListing, VisibilityRuleService visibilityRuleService, boolean hasMultiplicityItems, int numOfRows) {
int numOfCells = 0;
boolean hasValue = false;
List<Field> tempFields = fields.stream().sorted(Comparator.comparingInt(Field::getOrdinal)).collect(Collectors.toList());
for (Field field: tempFields) {
if (visibilityRuleService.isElementVisible(field.getId()) && field.getExport()) {
if (!createListing) {
try {
if(field.getViewStyle().getRenderStyle().equals("upload")){
boolean isImage = false;
for(UploadData.Option type: ((UploadData)field.getData()).getTypes()){
String fileFormat = type.getValue();
if(IMAGE_TYPE_MAP.containsKey(fileFormat)){
isImage = true;
break;
}
}
if(isImage){
if (field.getValue() != null && !field.getValue().toString().isEmpty()) {
XWPFParagraph paragraph = addCellContent(mapper.convertValue(field.getValue(), Map.class), mainDocumentPart, ParagraphStyle.IMAGE, numId, 0, numOfRows, numOfCells, 0);
if (paragraph != null) {
hasValue = true;
}
if(hasMultiplicityItems){
hasMultiplicityItems = false;
}
}
}
}
else if (field.getValue() != null && !field.getValue().toString().isEmpty()) {
this.indent = indent;
String format = this.formatter(field);
if (field.getViewStyle().getRenderStyle().equals("tags")) {
format = getCommaSeparatedFormatsFromJson(format, "name");
} else if (field.getViewStyle().getRenderStyle().equals("combobox") && field.getData() instanceof AutoCompleteData) {
format = getCommaSeparatedFormatsFromJson(format, "label");
}
boolean isResearcher = field.getViewStyle().getRenderStyle().equals("researchers");
if(format != null && !format.isEmpty()){
Object hasMultiAutoComplete = mapper.convertValue(field.getData(), Map.class).get("multiAutoComplete");
boolean isMultiAutoComplete = hasMultiAutoComplete != null && (boolean)hasMultiAutoComplete;
boolean arrayStringFormat = format.charAt(0) == '[';
if(arrayStringFormat || isMultiAutoComplete){
List<String> values = (arrayStringFormat) ? Arrays.asList(format.substring(1, format.length() - 1).split(",[ ]*")) : Arrays.asList(format.split(",[ ]*"));
if(values.size() > 1) {
boolean orcidResearcher;
int numOfValuesInCell = 0;
for (String val : values) {
orcidResearcher = false;
String orcId = null;
if(isResearcher && val.contains("orcid:")){
orcId = val.substring(val.indexOf(':') + 1, val.indexOf(')'));
val = val.substring(0, val.indexOf(':') + 1) + " ";
orcidResearcher = true;
}
format = "" + val;
if(hasMultiplicityItems){
XWPFParagraph paragraph = mainDocumentPart.getCell(mainDocumentPart.getTableCells().size()).addParagraph();
paragraph.createRun().setText(format);
if(orcidResearcher){
XWPFHyperlinkRun run = paragraph.createHyperlinkRun("https://orcid.org/" + orcId);
run.setText(orcId);
run.setUnderline(UnderlinePatterns.SINGLE);
run.setColor("0000FF");
paragraph.createRun().setText(")");
}
hasMultiplicityItems = false;
}
else{
XWPFParagraph paragraph = addCellContent(format, mainDocumentPart, field.getViewStyle().getRenderStyle().equals("richTextarea") ? ParagraphStyle.HTML : ParagraphStyle.TEXT, numId, indent, numOfRows, numOfCells, numOfValuesInCell);
numOfValuesInCell++;
if(orcidResearcher){
XWPFHyperlinkRun run = paragraph.createHyperlinkRun("https://orcid.org/" + orcId);
run.setText(orcId);
run.setUnderline(UnderlinePatterns.SINGLE);
run.setColor("0000FF");
paragraph.createRun().setText(")");
}
if (paragraph != null) {
hasValue = true;
}
}
format = null;
}
}
else if(values.size() == 1){
format = values.get(0);
}
}
}
if(hasMultiplicityItems && format != null){
XWPFParagraph paragraph = mainDocumentPart.getCell(mainDocumentPart.getTableCells().size()).addParagraph();
paragraph.createRun().setText(format);
hasMultiplicityItems = false;
hasValue = true;
}
else{
XWPFParagraph paragraph = addCellContent(format, mainDocumentPart, field.getViewStyle().getRenderStyle().equals("richTextarea") ? ParagraphStyle.HTML : ParagraphStyle.TEXT, numId, indent, numOfRows, numOfCells, 0);
if (paragraph != null) {
hasValue = true;
}
}
}
} catch (IOException e) {
logger.error(e.getMessage(), e);
}
}
numOfCells++;
}
}
return hasValue;
}
private Boolean createFields(List<Field> fields, XWPFDocument mainDocumentPart, Integer indent, Boolean createListing, VisibilityRuleService visibilityRuleService, boolean hasMultiplicityItems) { private Boolean createFields(List<Field> fields, XWPFDocument mainDocumentPart, Integer indent, Boolean createListing, VisibilityRuleService visibilityRuleService, boolean hasMultiplicityItems) {
if (createListing) this.addListing(mainDocumentPart, indent, false, false); if (createListing) this.addListing(mainDocumentPart, indent, false, false);
boolean hasValue = false; boolean hasValue = false;
@ -491,6 +701,36 @@ public class WordBuilder {
} }
} }
public XWPFParagraph addCellContent(Object content, XWPFTableRow mainDocumentPart, ParagraphStyle style, BigInteger numId, int indent, int numOfRows, int numOfCells, int numOfValuesInCell) {
if (content != null) {
if (content instanceof String && ((String)content).isEmpty()) {
return null;
}
this.indent = indent;
XWPFTableCell cell;
if(numOfRows > 0 || numOfValuesInCell > 0) {
cell = mainDocumentPart.getCell(numOfCells);
} else {
cell = mainDocumentPart.createCell();
}
cell.setVerticalAlignment(XWPFTableCell.XWPFVertAlign.valueOf("CENTER"));
if(numOfValuesInCell == 0) {
cell.removeParagraph(0);
}
XWPFParagraph paragraph = this.optionsInTable.get(style).apply(cell, content);
if (paragraph != null) {
paragraph.setAlignment(ParagraphAlignment.CENTER);
paragraph.setSpacingBefore(100);
if (numId != null) {
paragraph.setNumID(numId);
}
return paragraph;
}
}
return null;
}
public XWPFParagraph addParagraphContent(Object content, XWPFDocument mainDocumentPart, ParagraphStyle style, BigInteger numId, int indent) { public XWPFParagraph addParagraphContent(Object content, XWPFDocument mainDocumentPart, ParagraphStyle style, BigInteger numId, int indent) {
// this.indent = 0; // this.indent = 0;
if (content != null) { if (content != null) {