Compare commits

...

27 Commits

Author SHA1 Message Date
Efstratios Giannopoulos 8fc3fcd561 Add page titles 2024-06-11 11:45:32 +03:00
Efstratios Giannopoulos 8ea888f130 bug fix 2024-06-03 14:32:02 +03:00
Efstratios Giannopoulos 11ac5d183e HtmlToWorldBuilder.java: In method "parseProperties()" set default run fontSize to 11 & added cases for headers H1-H6 & if alignment is JUSTIFY set alignment to "both". 2024-05-31 09:56:28 +03:00
Efstratios Giannopoulos 45e8f5e5b0 dmp label fallback 2024-05-30 14:12:44 +03:00
amentis d733d3edff update contact 2024-05-29 12:05:57 +03:00
amentis 30dcf8043a dmp file name as dmp model label 2024-05-28 09:58:50 +03:00
amentis eabfe8a668 dmp file name as dmp model label 2024-05-28 09:44:10 +03:00
Efstratios Giannopoulos af0927d3e8 contact bug fix 2024-05-24 14:52:44 +03:00
Efstratios Giannopoulos 36fcfe188d fix formatter 2024-05-24 12:23:08 +03:00
Efstratios Giannopoulos ebf4c92f1b no message 2024-05-23 16:54:28 +03:00
Efstratios Giannopoulos 159070a940 update commons models 2024-05-22 17:41:54 +03:00
Efstratios Giannopoulos 0ddf095a3a bug fix 2024-05-16 10:54:48 +03:00
Efstratios Giannopoulos af0a6655c6 add maxInMemorySizeInBytes 2024-05-15 16:32:55 +03:00
Efstratios Giannopoulos 169f0a71ff more logging 2024-05-10 14:02:38 +03:00
Efstratios Giannopoulos efe03306f5 no message 2024-05-10 12:31:57 +03:00
Efstratios Giannopoulos 669809d911 add logging 2024-05-10 12:29:07 +03:00
Efstratios Giannopoulos 4ab7e3d925 bug fix 2024-05-10 10:15:10 +03:00
Efstratios Giannopoulos 4527634953 support shared storage 2024-05-09 14:22:31 +03:00
Efstratios Giannopoulos a96f62abf8 Support image 2024-05-09 14:08:46 +03:00
Efstratios Giannopoulos 62f69d2ea5 bug fixes 2024-05-09 12:39:25 +03:00
Efstratios Giannopoulos e3a9e552a7 update commons 2024-05-03 13:30:47 +03:00
Efstratios Giannopoulos 892a41455e update commons 2024-05-03 10:23:03 +03:00
Efstratios Giannopoulos e5fbf5d0ca rename to OpenCDMP 2024-04-26 16:26:11 +03:00
Efstratios Giannopoulos b981876d86 update common models 2024-04-25 12:14:35 +03:00
Alexandros Mandilaras 69f7ae7c34 add sonar dockerfile and update build profile 2024-04-23 15:48:28 +03:00
Efstratios Giannopoulos 3f4a397893 update pom 2024-04-19 11:39:46 +03:00
Efstratios Giannopoulos 442cf7b860 add exportEntityTypes importEntityTypes 2024-04-17 17:56:16 +03:00
46 changed files with 1233 additions and 580 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
.idea/
target/
logs/

View File

@ -5,9 +5,9 @@ ARG MAVEN_ACCOUNT_USR
ARG MAVEN_ACCOUNT_PSW
ARG REVISION
ARG PROFILE
ARG DEV_PROFILE_URL
ENV server_username=$MAVEN_ACCOUNT_USR
ENV server_password=$MAVEN_ACCOUNT_PSW
ARG CITE_MAVEN_REPO_URL
COPY pom.xml /build/
COPY core /build/core/
@ -19,9 +19,9 @@ RUN rm -f /build/web/src/main/resources/config/*-dev.yml
WORKDIR /build/
RUN mvn -Drevision=${REVISION} -DdevProfileUrl=${DEV_PROFILE_URL} -P${PROFILE} dependency:go-offline
# Build project
RUN mvn -Drevision=${REVISION} -DdevProfileUrl=${DEV_PROFILE_URL} -P${PROFILE} clean package
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} clean
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} install
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} package
######################################## Run Stage ########################################
FROM eclipse-temurin:21

28
Dockerfile.Sonar Normal file
View File

@ -0,0 +1,28 @@
####################################### Build stage #######################################
FROM maven:3.9-eclipse-temurin-21-alpine
ARG MAVEN_ACCOUNT_USR
ARG MAVEN_ACCOUNT_PSW
ARG REVISION
ARG PROFILE
ARG ORACLE_URL
ARG ORACLE_TOKEN
ENV server_username=$MAVEN_ACCOUNT_USR
ENV server_password=$MAVEN_ACCOUNT_PSW
ARG CITE_MAVEN_REPO_URL
COPY pom.xml /build/
COPY core /build/core/
COPY web /build/web/
COPY settings.xml /root/.m2/settings.xml
RUN rm -f /build/web/src/main/resources/config/*-dev.yml
RUN rm -f /build/web/src/main/resources/logging/*.xml
COPY oracle.local.cite.gr.crt $JAVA_HOME/conf/security
RUN cd "$JAVA_HOME"/conf/security && keytool -cacerts -storepass changeit -noprompt -trustcacerts -importcert -alias oraclecert -file oracle.local.cite.gr.crt
WORKDIR /build/
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} clean
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} install
RUN mvn -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} package
RUN mvn sonar:sonar -Drevision=${REVISION} -DciteMavenRepoUrl=${CITE_MAVEN_REPO_URL} -P${PROFILE} -Dsonar.projectKey=OpenDMP:file-transformer-docx -Dsonar.login=${ORACLE_TOKEN} -Dsonar.host.url=${ORACLE_URL} -Dsonar.projectName='OpenDMP file-transformer-docx'

View File

@ -3,7 +3,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>gr.cite.opendmp</groupId>
<groupId>org.opencdmp</groupId>
<artifactId>file-transformer-document-parent</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
@ -50,6 +50,16 @@
<artifactId>jsoup</artifactId>
<version>1.17.2</version>
</dependency>
<dependency>
<groupId>gr.cite</groupId>
<artifactId>logging</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>gr.cite</groupId>
<artifactId>exceptions</artifactId>
<version>2.2.0</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>

View File

@ -1,36 +0,0 @@
package eu.eudat.file.transformer.service.pdf;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.MediaType;
import org.springframework.http.client.MultipartBodyBuilder;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.WebClient;
import java.util.UUID;
@Component
public class PdfServiceImpl implements PdfService {
private final PdfServiceProperties pdfServiceProperties;
public PdfServiceImpl(PdfServiceProperties pdfServiceProperties) {
this.pdfServiceProperties = pdfServiceProperties;
}
@Override
public byte[] convertToPDF(byte[] file) {
WebClient webClient = WebClient.builder().baseUrl(pdfServiceProperties.getUrl()).build();
MultipartBodyBuilder builder = new MultipartBodyBuilder();
builder.part("files", new ByteArrayResource(file)).filename(UUID.randomUUID() + ".docx");
return webClient.post().uri("forms/libreoffice/convert")
.headers(httpHeaders -> {
httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
httpHeaders.add("Content-disposition", "attachment; filename=" + UUID.randomUUID() + ".pdf");
httpHeaders.add("Content-type", "application/pdf");
})
.body(BodyInserters.fromMultipartData(builder.build()))
.retrieve().bodyToMono(byte[].class).block();
}
}

View File

@ -1,18 +0,0 @@
package eu.eudat.file.transformer.service.pdf;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.ConstructorBinding;
@ConfigurationProperties(prefix = "pdf.converter")
public class PdfServiceProperties {
private final String url;
@ConstructorBinding
public PdfServiceProperties(String url) {
this.url = url;
}
public String getUrl() {
return url;
}
}

View File

@ -0,0 +1,15 @@
package org.opencdmp.filetransformer.docx.audit;
import gr.cite.tools.logging.EventId;
public class AuditableAction {
public static final EventId FileTransformer_ExportDmp = new EventId(1000, "FileTransformer_ExportDmp");
public static final EventId FileTransformer_ExportDescription = new EventId(1001, "FileTransformer_ExportDescription");
public static final EventId FileTransformer_ImportFileToDmp = new EventId(1002, "FileTransformer_ImportFileToDmp");
public static final EventId FileTransformer_ImportFileToDescription = new EventId(1003, "FileTransformer_ImportFileToDescription");
public static final EventId FileTransformer_GetSupportedFormats = new EventId(1004, "FileTransformer_GetSupportedFormats");
}

View File

@ -1,4 +1,4 @@
package eu.eudat.file.transformer.model;
package org.opencdmp.filetransformer.docx.model;
public class PidLink {
private String pid;

View File

@ -1,9 +1,9 @@
package eu.eudat.file.transformer.model.enums;
package org.opencdmp.filetransformer.docx.model.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import eu.eudat.commonmodels.enums.EnumUtils;
import eu.eudat.commonmodels.enums.EnumValueProvider;
import org.opencdmp.commonmodels.enums.EnumUtils;
import org.opencdmp.commonmodels.enums.EnumValueProvider;
import java.util.Map;

View File

@ -1,9 +1,9 @@
package eu.eudat.file.transformer.model.enums;
package org.opencdmp.filetransformer.docx.model.enums;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonValue;
import eu.eudat.commonmodels.enums.EnumUtils;
import eu.eudat.commonmodels.enums.EnumValueProvider;
import org.opencdmp.commonmodels.enums.EnumUtils;
import org.opencdmp.commonmodels.enums.EnumValueProvider;
import java.util.Map;
@ -12,7 +12,7 @@ public enum ParagraphStyle implements EnumValueProvider<Integer> {
private final Integer value;
private ParagraphStyle(Integer value) {
ParagraphStyle(Integer value) {
this.value = value;
}

View File

@ -1,4 +1,4 @@
package eu.eudat.file.transformer.model.interfaces;
package org.opencdmp.filetransformer.docx.model.interfaces;
/**
* Created by ikalyvas on 2/27/2018.

View File

@ -1,4 +1,4 @@
package eu.eudat.file.transformer.service.pdf;
package org.opencdmp.filetransformer.docx.service.pdf;
public interface PdfService {
byte[] convertToPDF(byte[] file);

View File

@ -1,4 +1,4 @@
package eu.eudat.file.transformer.service.pdf;
package org.opencdmp.filetransformer.docx.service.pdf;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

View File

@ -0,0 +1,71 @@
package org.opencdmp.filetransformer.docx.service.pdf;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.ByteArrayResource;
import org.springframework.http.MediaType;
import org.springframework.http.client.MultipartBodyBuilder;
import org.springframework.stereotype.Component;
import org.springframework.web.reactive.function.BodyInserters;
import org.springframework.web.reactive.function.client.ExchangeFilterFunction;
import org.springframework.web.reactive.function.client.WebClient;
import reactor.core.publisher.Mono;
import java.util.UUID;
@Component
public class PdfServiceImpl implements PdfService {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(PdfServiceImpl.class));
private final PdfServiceProperties pdfServiceProperties;
public PdfServiceImpl(PdfServiceProperties pdfServiceProperties) {
this.pdfServiceProperties = pdfServiceProperties;
}
@Override
public byte[] convertToPDF(byte[] file) {
WebClient webClient = WebClient.builder().filters(exchangeFilterFunctions -> {
exchangeFilterFunctions.add(logRequest());
exchangeFilterFunctions.add(logResponse());
}).baseUrl(pdfServiceProperties.getUrl()) .codecs(codecs -> codecs
.defaultCodecs()
.maxInMemorySize(this.pdfServiceProperties.getMaxInMemorySizeInBytes())
).build();
MultipartBodyBuilder builder = new MultipartBodyBuilder();
builder.part("files", new ByteArrayResource(file)).filename(UUID.randomUUID() + ".docx");
return webClient.post().uri("forms/libreoffice/convert")
.headers(httpHeaders -> {
httpHeaders.setContentType(MediaType.MULTIPART_FORM_DATA);
httpHeaders.add("Content-disposition", "attachment; filename=" + UUID.randomUUID() + ".pdf");
httpHeaders.add("Content-type", "application/pdf");
})
.body(BodyInserters.fromMultipartData(builder.build()))
.retrieve().bodyToMono(byte[].class).block();
}
private static ExchangeFilterFunction logRequest() {
return ExchangeFilterFunction.ofRequestProcessor(clientRequest -> {
logger.debug(new MapLogEntry("Request").And("method", clientRequest.method().toString()).And("url", clientRequest.url()));
return Mono.just(clientRequest);
});
}
private static ExchangeFilterFunction logResponse() {
return ExchangeFilterFunction.ofResponseProcessor(response -> {
if (response.statusCode().isError()) {
return response.mutate().build().bodyToMono(String.class)
.flatMap(body -> {
logger.error(new MapLogEntry("Response").And("method", response.request().getMethod().toString()).And("url", response.request().getURI()).And("status", response.statusCode()).And("body", body));
return Mono.just(response);
});
}
return Mono.just(response);
});
}
}

View File

@ -0,0 +1,26 @@
package org.opencdmp.filetransformer.docx.service.pdf;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.ConstructorBinding;
@ConfigurationProperties(prefix = "pdf.converter")
public class PdfServiceProperties {
private String url;
private int maxInMemorySizeInBytes;
public String getUrl() {
return url;
}
public void setUrl(String url) {
this.url = url;
}
public int getMaxInMemorySizeInBytes() {
return maxInMemorySizeInBytes;
}
public void setMaxInMemorySizeInBytes(int maxInMemorySizeInBytes) {
this.maxInMemorySizeInBytes = maxInMemorySizeInBytes;
}
}

View File

@ -1,6 +1,6 @@
package eu.eudat.file.transformer.service.pid;
package org.opencdmp.filetransformer.docx.service.pid;
import eu.eudat.file.transformer.model.PidLink;
import org.opencdmp.filetransformer.docx.model.PidLink;
import java.util.List;

View File

@ -1,8 +1,9 @@
package eu.eudat.file.transformer.service.pid;
package org.opencdmp.filetransformer.docx.service.pid;
import com.fasterxml.jackson.databind.ObjectMapper;
import eu.eudat.file.transformer.service.wordfiletransformer.WordFileTransformerServiceProperties;
import eu.eudat.file.transformer.model.PidLink;
import gr.cite.tools.logging.LoggerService;
import org.opencdmp.filetransformer.docx.service.wordfiletransformer.WordFileTransformerServiceProperties;
import org.opencdmp.filetransformer.docx.model.PidLink;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
@ -13,7 +14,7 @@ import java.util.List;
@Component
public class PidServiceImpl implements PidService {
private static final Logger logger = LoggerFactory.getLogger(PidServiceImpl.class);
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(PidServiceImpl.class));
private final WordFileTransformerServiceProperties properties;
private final ObjectMapper objectMapper = new ObjectMapper();
private List<PidLink> pidLinks = null;

View File

@ -1,4 +1,4 @@
package eu.eudat.file.transformer.service.storage;
package org.opencdmp.filetransformer.docx.service.storage;
public interface FileStorageService {
String storeFile(byte[] data);

View File

@ -1,4 +1,4 @@
package eu.eudat.file.transformer.service.storage;
package org.opencdmp.filetransformer.docx.service.storage;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

View File

@ -1,5 +1,7 @@
package eu.eudat.file.transformer.service.storage;
package org.opencdmp.filetransformer.docx.service.storage;
import gr.cite.tools.logging.LoggerService;
import org.opencdmp.filetransformer.docx.service.wordfiletransformer.WordFileTransformerService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@ -16,7 +18,7 @@ import java.util.UUID;
@Service
public class FileStorageServiceImpl implements FileStorageService {
private final static Logger logger = LoggerFactory.getLogger(FileStorageServiceImpl.class);
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(WordFileTransformerService.class));
private final FileStorageServiceProperties properties;

View File

@ -1,4 +1,4 @@
package eu.eudat.file.transformer.service.storage;
package org.opencdmp.filetransformer.docx.service.storage;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.boot.context.properties.bind.ConstructorBinding;

View File

@ -1,64 +1,77 @@
package eu.eudat.file.transformer.service.wordfiletransformer;
package org.opencdmp.filetransformer.docx.service.wordfiletransformer;
import eu.eudat.commonmodels.enums.DescriptionStatus;
import eu.eudat.commonmodels.enums.DmpAccessType;
import eu.eudat.commonmodels.enums.DmpBlueprintSystemFieldType;
import eu.eudat.commonmodels.enums.DmpStatus;
import eu.eudat.commonmodels.models.dmp.DmpBlueprintValueModel;
import eu.eudat.commonmodels.models.dmp.DmpModel;
import eu.eudat.commonmodels.models.FileEnvelopeModel;
import eu.eudat.commonmodels.models.description.DescriptionModel;
import eu.eudat.commonmodels.models.descriptiotemplate.DescriptionTemplateModel;
import eu.eudat.commonmodels.models.dmpblueprint.*;
import eu.eudat.commonmodels.models.dmpreference.DmpReferenceModel;
import eu.eudat.commonmodels.models.reference.ReferenceModel;
import eu.eudat.file.transformer.interfaces.FileTransformerClient;
import eu.eudat.file.transformer.interfaces.FileTransformerConfiguration;
import eu.eudat.file.transformer.model.enums.FileFormats;
import eu.eudat.file.transformer.models.misc.FileFormat;
import eu.eudat.file.transformer.service.pdf.PdfService;
import eu.eudat.file.transformer.model.enums.ParagraphStyle;
import eu.eudat.file.transformer.service.storage.FileStorageService;
import eu.eudat.file.transformer.service.wordfiletransformer.visibility.VisibilityServiceImpl;
import eu.eudat.file.transformer.service.wordfiletransformer.word.WordBuilder;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.exception.MyApplicationException;
import gr.cite.tools.logging.LoggerService;
import org.opencdmp.commonmodels.enums.*;
import org.opencdmp.commonmodels.models.UserContactInfoModel;
import org.opencdmp.commonmodels.models.dmp.DmpBlueprintValueModel;
import org.opencdmp.commonmodels.models.dmp.DmpContactModel;
import org.opencdmp.commonmodels.models.dmp.DmpModel;
import org.opencdmp.commonmodels.models.FileEnvelopeModel;
import org.opencdmp.commonmodels.models.description.DescriptionModel;
import org.opencdmp.commonmodels.models.descriptiotemplate.DescriptionTemplateModel;
import org.opencdmp.commonmodels.models.dmpblueprint.*;
import org.opencdmp.commonmodels.models.dmpreference.DmpReferenceModel;
import org.opencdmp.commonmodels.models.reference.ReferenceModel;
import org.opencdmp.filetransformerbase.enums.FileTransformerEntityType;
import org.opencdmp.filetransformerbase.interfaces.FileTransformerClient;
import org.opencdmp.filetransformerbase.interfaces.FileTransformerConfiguration;
import org.opencdmp.filetransformer.docx.model.enums.FileFormats;
import org.opencdmp.filetransformerbase.models.misc.FileFormat;
import org.opencdmp.filetransformer.docx.service.pdf.PdfService;
import org.opencdmp.filetransformer.docx.model.enums.ParagraphStyle;
import org.opencdmp.filetransformer.docx.service.storage.FileStorageService;
import org.opencdmp.filetransformer.docx.service.wordfiletransformer.visibility.VisibilityServiceImpl;
import org.opencdmp.filetransformer.docx.service.wordfiletransformer.word.WordBuilder;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.context.MessageSource;
import org.springframework.context.annotation.Scope;
import org.springframework.context.i18n.LocaleContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.ResourceUtils;
import org.springframework.web.context.annotation.RequestScope;
import javax.management.InvalidApplicationException;
import java.io.*;
import java.math.BigInteger;
import java.text.DecimalFormat;
import java.time.Instant;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
@RequestScope
public class WordFileTransformerService implements FileTransformerClient {
private final static Logger logger = LoggerFactory.getLogger(WordFileTransformerService.class);
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(WordFileTransformerService.class));
private final static List<FileFormat> FILE_FORMATS = List.of(
new FileFormat(FileFormats.PDF.getValue(), true, "fa-file-pdf-o"),
new FileFormat(FileFormats.DOCX.getValue(), true, "fa-file-word-o"));
private final static List<FileTransformerEntityType> FILE_TRANSFORMER_ENTITY_TYPES = List.of(
FileTransformerEntityType.Dmp, FileTransformerEntityType.Description);
private final WordFileTransformerServiceProperties wordFileTransformerServiceProperties;
private final PdfService pdfService;
private final WordBuilder wordBuilder;
private final FileStorageService storageService;
private final MessageSource messageSource;
@Autowired
public WordFileTransformerService(
WordFileTransformerServiceProperties wordFileTransformerServiceProperties,
PdfService pdfService, WordBuilder wordBuilder, FileStorageService storageService) {
PdfService pdfService, WordBuilder wordBuilder, FileStorageService storageService, MessageSource messageSource) {
this.wordFileTransformerServiceProperties = wordFileTransformerServiceProperties;
this.pdfService = pdfService;
this.wordBuilder = wordBuilder;
this.storageService = storageService;
this.messageSource = messageSource;
}
@Override
@ -71,7 +84,7 @@ public class WordFileTransformerService implements FileTransformerClient {
bytes = this.pdfService.convertToPDF(bytes);
yield this.getDmpFileName(dmp, ".pdf");
}
default -> throw new InvalidApplicationException("Invalid type " + fileFormat);
default -> throw new MyApplicationException("Invalid type " + fileFormat);
};
FileEnvelopeModel wordFile = new FileEnvelopeModel();
@ -95,7 +108,7 @@ public class WordFileTransformerService implements FileTransformerClient {
bytes = this.pdfService.convertToPDF(bytes);
yield this.getDescriptionFileName(descriptionModel, ".pdf");
}
default -> throw new InvalidApplicationException("Invalid type " + fileFormat);
default -> throw new MyApplicationException("Invalid type " + fileFormat);
};
FileEnvelopeModel wordFile = new FileEnvelopeModel();
@ -112,12 +125,12 @@ public class WordFileTransformerService implements FileTransformerClient {
@Override
public DmpModel importDmp(FileEnvelopeModel envelope) {
throw new UnsupportedOperationException("import not supported");
throw new MyApplicationException("import not supported");
}
@Override
public DescriptionModel importDescription(FileEnvelopeModel envelope) {
throw new UnsupportedOperationException("import not supported");
throw new MyApplicationException("import not supported");
}
@Override
@ -126,6 +139,7 @@ public class WordFileTransformerService implements FileTransformerClient {
configuration.setFileTransformerId(this.wordFileTransformerServiceProperties.getTransformerId());
configuration.setExportVariants(FILE_FORMATS);
configuration.setImportVariants(null);
configuration.setExportEntityTypes(FILE_TRANSFORMER_ENTITY_TYPES);
configuration.setUseSharedStorage(this.wordFileTransformerServiceProperties.isUseSharedStorage());
return configuration;
}
@ -144,11 +158,11 @@ public class WordFileTransformerService implements FileTransformerClient {
private byte[] buildDmpWordDocument(DmpModel dmpEntity) throws IOException, InvalidApplicationException {
if (dmpEntity == null) throw new IllegalArgumentException("DmpEntity required");
if (dmpEntity == null) throw new MyApplicationException("DmpEntity required");
DmpBlueprintModel dmpBlueprintModel = dmpEntity.getDmpBlueprint();
if (dmpBlueprintModel == null) throw new IllegalArgumentException("DmpBlueprint required");
if (dmpBlueprintModel.getDefinition() == null) throw new IllegalArgumentException("DmpBlueprint Definition required");
if (dmpBlueprintModel.getDefinition().getSections() == null) throw new IllegalArgumentException("DmpBlueprint Section required");
if (dmpBlueprintModel == null) throw new MyApplicationException("DmpBlueprint required");
if (dmpBlueprintModel.getDefinition() == null) throw new MyApplicationException("DmpBlueprint Definition required");
if (dmpBlueprintModel.getDefinition().getSections() == null) throw new MyApplicationException("DmpBlueprint Section required");
XWPFDocument document = new XWPFDocument(new FileInputStream(ResourceUtils.getFile(this.wordFileTransformerServiceProperties.getWordDmpTemplate())));
@ -201,7 +215,7 @@ public class WordFileTransformerService implements FileTransformerClient {
final boolean isFinalized = dmpEntity.getStatus() != null && dmpEntity.getStatus().equals(DmpStatus.Finalized);
final boolean isPublic = dmpEntity.getPublicAfter() != null && dmpEntity.getPublicAfter().isAfter(Instant.now());
List<DescriptionModel> descriptions = dmpEntity.getDescriptions().stream()
List<DescriptionModel> descriptions = dmpEntity.getDescriptions() == null ? new ArrayList<>() : dmpEntity.getDescriptions().stream()
.filter(item -> item.getStatus() != DescriptionStatus.Canceled)
.filter(item -> !isPublic && !isFinalized || item.getStatus() == DescriptionStatus.Finalized)
.filter(item -> item.getSectionId().equals(sectionModel.getId()))
@ -213,8 +227,8 @@ public class WordFileTransformerService implements FileTransformerClient {
}
private void buildSectionDescriptions(XWPFDocument document, List<DescriptionModel> descriptions) {
if (document == null) throw new IllegalArgumentException("Document required");
if (descriptions == null) throw new IllegalArgumentException("Descriptions required");
if (document == null) throw new MyApplicationException("Document required");
if (descriptions == null) throw new MyApplicationException("Descriptions required");
List<DescriptionTemplateModel> descriptionTemplateModels = descriptions.stream().map(DescriptionModel::getDescriptionTemplate).toList();
if (descriptionTemplateModels.isEmpty()) return;
@ -233,8 +247,8 @@ public class WordFileTransformerService implements FileTransformerClient {
}
private void buildSectionDescription(XWPFDocument document, DescriptionModel descriptionModel) {
if (document == null) throw new IllegalArgumentException("Document required");
if (descriptionModel == null) throw new IllegalArgumentException("DescriptionModel required");
if (document == null) throw new MyApplicationException("Document required");
if (descriptionModel == null) throw new MyApplicationException("DescriptionModel required");
DescriptionTemplateModel descriptionTemplateModelFileModel = descriptionModel.getDescriptionTemplate();
@ -271,7 +285,7 @@ public class WordFileTransformerService implements FileTransformerClient {
try {
this.wordBuilder.build(document, descriptionModel.getDescriptionTemplate(), descriptionModel.getProperties(), new VisibilityServiceImpl(descriptionModel.getVisibilityStates()));
} catch (IOException e) {
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
// Page break at the end of the Dataset.
@ -281,8 +295,8 @@ public class WordFileTransformerService implements FileTransformerClient {
private void buildDmpSectionField(DmpModel dmpEntity, XWPFDocument document, FieldModel fieldModel) throws InvalidApplicationException {
if (fieldModel == null) throw new IllegalArgumentException("Field required");
if (fieldModel.getCategory() == null) throw new IllegalArgumentException("Field is required" + fieldModel.getId() + " " + fieldModel.getLabel());
if (fieldModel == null) throw new MyApplicationException("Field required");
if (fieldModel.getCategory() == null) throw new MyApplicationException("Field is required" + fieldModel.getId() + " " + fieldModel.getLabel());
switch (fieldModel.getCategory()){
case System -> {
buildDmpSectionSystemField(dmpEntity, document, (SystemFieldModel) fieldModel);
@ -291,20 +305,20 @@ public class WordFileTransformerService implements FileTransformerClient {
case ReferenceType -> {
buildDmpSectionReferenceTypeField(dmpEntity, document, (ReferenceTypeFieldModel) fieldModel);
}
default -> throw new InvalidApplicationException("Invalid type " + fieldModel.getCategory());
default -> throw new MyApplicationException("Invalid type " + fieldModel.getCategory());
}
}
private void buildDmpSectionReferenceTypeField(DmpModel dmpEntity, XWPFDocument document, ReferenceTypeFieldModel referenceField) {
if (referenceField == null) throw new IllegalArgumentException("ReferenceField required");
if (dmpEntity == null) throw new IllegalArgumentException("DmpEntity required");
if (document == null) throw new IllegalArgumentException("Document required");
if (referenceField.getReferenceType() == null) throw new IllegalArgumentException("ReferenceField type required");
if (referenceField == null) throw new MyApplicationException("ReferenceField required");
if (dmpEntity == null) throw new MyApplicationException("DmpEntity required");
if (document == null) throw new MyApplicationException("Document required");
if (referenceField.getReferenceType() == null) throw new MyApplicationException("ReferenceField type required");
if (referenceField.getReferenceType().getCode() == null && !referenceField.getReferenceType().getCode().isBlank()) throw new IllegalArgumentException("ReferenceField type code required");
XWPFParagraph systemFieldParagraph = document.createParagraph();
XWPFRun runSyStemFieldTitle = systemFieldParagraph.createRun();
runSyStemFieldTitle.setText(referenceField.getLabel() + ": ");
runSyStemFieldTitle.setText(this.getReferenceFieldLabel(referenceField) + ": ");
runSyStemFieldTitle.setColor("000000");
List<ReferenceModel> referenceModels = this.getReferenceModelOfTypeCode(dmpEntity, referenceField.getReferenceType().getCode(), referenceField.getId());
@ -319,17 +333,24 @@ public class WordFileTransformerService implements FileTransformerClient {
}
}
private void buildDmpSectionSystemField(DmpModel dmpEntity, XWPFDocument document, SystemFieldModel systemField) throws InvalidApplicationException {
if (systemField == null) throw new IllegalArgumentException("SystemField required");
if (dmpEntity == null) throw new IllegalArgumentException("DmpEntity required");
if (document == null) throw new IllegalArgumentException("Document required");
private String getReferenceFieldLabel(ReferenceTypeFieldModel referenceTypeField) {
if (referenceTypeField == null) return "";
if (referenceTypeField.getLabel() != null && !referenceTypeField.getLabel().isBlank()) return referenceTypeField.getLabel();
return referenceTypeField.getReferenceType().getName();
}
private void buildDmpSectionSystemField(DmpModel dmpEntity, XWPFDocument document, SystemFieldModel systemField) {
if (systemField == null) throw new MyApplicationException("SystemField required");
if (dmpEntity == null) throw new MyApplicationException("DmpEntity required");
if (document == null) throw new MyApplicationException("Document required");
if (DmpBlueprintSystemFieldType.Language.equals(systemField.getSystemFieldType()) || DmpBlueprintSystemFieldType.User.equals(systemField.getSystemFieldType())) return;
XWPFParagraph systemFieldParagraph = document.createParagraph();
XWPFRun runSyStemFieldTitle = systemFieldParagraph.createRun();
runSyStemFieldTitle.setText(systemField.getLabel() + ": ");
runSyStemFieldTitle.setText(this.getSystemFieldLabel(systemField) + ": ");
runSyStemFieldTitle.setColor("000000");
switch (systemField.getSystemFieldType()) {
@ -349,9 +370,20 @@ public class WordFileTransformerService implements FileTransformerClient {
}
break;
case Contact:
if (dmpEntity.getCreator() != null) {
List<String> contacts = new ArrayList<>();
if (dmpEntity.getProperties() != null && dmpEntity.getProperties().getContacts() != null && !dmpEntity.getProperties().getContacts().isEmpty()) {
for (DmpContactModel contactModel : dmpEntity.getProperties().getContacts()){
String contact;
contact = (contactModel.getLastName() == null ? "" : contactModel.getLastName()) + " " + (contactModel.getFirstName() == null ? "" : contactModel.getFirstName());
if (contactModel.getEmail() != null && !contactModel.getEmail().isEmpty()) contact = contact + " (" + contactModel.getEmail() +")";
contacts.add(contact.trim());
}
}
if (!contacts.isEmpty()) {
XWPFRun runContact = systemFieldParagraph.createRun();
runContact.setText(dmpEntity.getCreator() == null ? "" : dmpEntity.getCreator().getName());
runContact.setText(String.join(", ", contacts));
runContact.setColor("116a78");
}
break;
@ -359,12 +391,27 @@ public class WordFileTransformerService implements FileTransformerClient {
case Language:
break;
default:
throw new InvalidApplicationException("Invalid type " + systemField.getSystemFieldType());
throw new MyApplicationException("Invalid type " + systemField.getSystemFieldType());
}
}
private String getSystemFieldLabel(SystemFieldModel systemField) {
if (systemField == null) return "";
if (systemField.getLabel() != null && !systemField.getLabel().isBlank()) return systemField.getLabel();
private void buildDmpSectionExtraField(DmpModel dmpEntity, XWPFDocument document, ExtraFieldModel extraFieldModel) throws InvalidApplicationException {
if (extraFieldModel == null) throw new IllegalArgumentException("ExtraFieldModel required");
return switch (systemField.getSystemFieldType()) {
case Title -> this.messageSource.getMessage("SystemField_Title_Label", new Object[]{}, LocaleContextHolder.getLocale());
case Description -> this.messageSource.getMessage("SystemField_Description_Label", new Object[]{}, LocaleContextHolder.getLocale());
case AccessRights -> this.messageSource.getMessage("SystemField_AccessRights_Label", new Object[]{}, LocaleContextHolder.getLocale());
case Contact -> this.messageSource.getMessage("SystemField_Contact_Label", new Object[]{}, LocaleContextHolder.getLocale());
case User -> this.messageSource.getMessage("SystemField_User_Label", new Object[]{}, LocaleContextHolder.getLocale());
case Language -> this.messageSource.getMessage("SystemField_Language_Label", new Object[]{}, LocaleContextHolder.getLocale());
default -> throw new MyApplicationException("Invalid type " + systemField.getSystemFieldType());
};
}
private void buildDmpSectionExtraField(DmpModel dmpEntity, XWPFDocument document, ExtraFieldModel extraFieldModel) {
if (extraFieldModel == null) throw new MyApplicationException("ExtraFieldModel required");
XWPFParagraph extraFieldParagraph = document.createParagraph();
extraFieldParagraph.setSpacingBetween(1.0);
XWPFRun runExtraFieldLabel = extraFieldParagraph.createRun();
@ -373,42 +420,56 @@ public class WordFileTransformerService implements FileTransformerClient {
XWPFRun runExtraFieldInput = extraFieldParagraph.createRun();
DmpBlueprintValueModel dmpBlueprintValueModel = dmpEntity.getProperties() != null && dmpEntity.getProperties().getDmpBlueprintValues() != null ? dmpEntity.getProperties().getDmpBlueprintValues().stream().filter(x -> extraFieldModel.getId().equals(x.getFieldId())).findFirst().orElse(null) : null;
if (dmpBlueprintValueModel != null && dmpBlueprintValueModel.getValue() != null) {
if (dmpBlueprintValueModel != null) {
switch (extraFieldModel.getDataType()) {
case RichTex:
wordBuilder.addParagraphContent(dmpBlueprintValueModel.getValue(), document, ParagraphStyle.HTML, BigInteger.ZERO, 0);
if(dmpBlueprintValueModel.getValue() != null && !dmpBlueprintValueModel.getValue().isBlank()) wordBuilder.addParagraphContent(dmpBlueprintValueModel.getValue(), document, ParagraphStyle.HTML, BigInteger.ZERO, 0);
break;
case Number:
case Text:
if(dmpBlueprintValueModel.getNumberValue() != null) {
runExtraFieldInput.setText(DecimalFormat.getNumberInstance().format(dmpBlueprintValueModel.getNumberValue()));
runExtraFieldInput.setColor("116a78");
}
break;
case Date:
runExtraFieldInput.setText(dmpBlueprintValueModel.getValue());
runExtraFieldInput.setColor("116a78");
if(dmpBlueprintValueModel.getDateValue() != null){
runExtraFieldInput.setText(DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.systemDefault()).format(dmpBlueprintValueModel.getDateValue()));
runExtraFieldInput.setColor("116a78");
}
break;
case Text:
if(dmpBlueprintValueModel.getValue() != null && !dmpBlueprintValueModel.getValue().isBlank()) {
runExtraFieldInput.setText(dmpBlueprintValueModel.getValue());
runExtraFieldInput.setColor("116a78");
}
break;
default:
throw new InvalidApplicationException("Invalid type " + extraFieldModel.getDataType());
throw new MyApplicationException("Invalid type " + extraFieldModel.getDataType());
}
}
}
private String getDmpFileName(DmpModel dmpModel, String extension){
if (dmpModel == null) throw new IllegalArgumentException("DmpEntity required");
if (dmpModel == null) throw new MyApplicationException("DmpEntity required");
List<ReferenceModel> grants = this.getReferenceModelOfTypeCode(dmpModel, this.wordFileTransformerServiceProperties.getGrantReferenceCode(), null);
String fileName;
String fileName = null;
if (dmpModel.getLabel() != null){
return dmpModel.getLabel() + extension;
}
if (!grants.isEmpty() && grants.getFirst().getLabel() != null) {
fileName = "DMP_" + grants.getFirst().getLabel();
fileName += "_" + dmpModel.getVersion();
}
else {
fileName = "DMP_" + dmpModel.getLabel();
}
fileName += "_" + dmpModel.getVersion();
return fileName + extension;
}
private byte[] buildDescriptionWordDocument(DescriptionModel descriptionModel) throws IOException {
if (descriptionModel == null) throw new IllegalArgumentException("DmpEntity required");
if (descriptionModel == null) throw new MyApplicationException("DmpEntity required");
DmpModel dmpEntity = descriptionModel.getDmp();
if (dmpEntity == null) throw new IllegalArgumentException("Dmp is invalid");
if (dmpEntity == null) throw new MyApplicationException("Dmp is invalid");
XWPFDocument document = new XWPFDocument(new FileInputStream(ResourceUtils.getFile(this.wordFileTransformerServiceProperties.getWordDescriptionTemplate())));
this.wordBuilder.fillFirstPage(dmpEntity, descriptionModel, document, true);
@ -445,7 +506,7 @@ public class WordFileTransformerService implements FileTransformerClient {
}
private String getDescriptionFileName(DescriptionModel descriptionModel, String extension){
if (descriptionModel == null) throw new IllegalArgumentException("DmpEntity required");
if (descriptionModel == null) throw new MyApplicationException("DmpEntity required");
String fileName = descriptionModel.getLabel().replaceAll("[^a-zA-Z0-9+ ]", "");
return fileName + extension;

View File

@ -1,4 +1,4 @@
package eu.eudat.file.transformer.service.wordfiletransformer;
package org.opencdmp.filetransformer.docx.service.wordfiletransformer;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.context.annotation.Configuration;

View File

@ -1,4 +1,4 @@
package eu.eudat.file.transformer.service.wordfiletransformer;
package org.opencdmp.filetransformer.docx.service.wordfiletransformer;
import org.springframework.boot.context.properties.ConfigurationProperties;

View File

@ -1,4 +1,4 @@
package eu.eudat.file.transformer.service.wordfiletransformer.visibility;
package org.opencdmp.filetransformer.docx.service.wordfiletransformer.visibility;
import java.util.Objects;

View File

@ -1,4 +1,4 @@
package eu.eudat.file.transformer.service.wordfiletransformer.visibility;
package org.opencdmp.filetransformer.docx.service.wordfiletransformer.visibility;
import java.util.Map;

View File

@ -1,6 +1,6 @@
package eu.eudat.file.transformer.service.wordfiletransformer.visibility;
package org.opencdmp.filetransformer.docx.service.wordfiletransformer.visibility;
import eu.eudat.commonmodels.models.description.VisibilityStateModel;
import org.opencdmp.commonmodels.models.description.VisibilityStateModel;
import java.util.HashMap;
import java.util.List;

View File

@ -1,4 +1,4 @@
package eu.eudat.file.transformer.service.wordfiletransformer.word;
package org.opencdmp.filetransformer.docx.service.wordfiletransformer.word;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.XmlCursor;
@ -21,7 +21,7 @@ public class HtmlToWorldBuilder implements NodeVisitor {
private final float indentation;
private Boolean isIdentationUsed;
private XWPFNumbering numbering;
private Queue<BigInteger> abstractNumId;
private final Queue<BigInteger> abstractNumId;
private BigInteger numberingLevel;
private XmlCursor cursor;
@ -75,6 +75,7 @@ public class HtmlToWorldBuilder implements NodeVisitor {
private void parseProperties(Node node) {
properties.entrySet().forEach(stringBooleanEntry -> {
this.run.setFontSize(11);
switch (stringBooleanEntry.getKey()) {
case "i" :
case "em":
@ -121,6 +122,9 @@ public class HtmlToWorldBuilder implements NodeVisitor {
if (stringBooleanEntry.getValue()) {
if (node.hasAttr("align")) {
String alignment = node.attr("align");
if(alignment.toUpperCase(Locale.ROOT).equals("JUSTIFY")) {
alignment = "both";
}
this.paragraph.setAlignment(ParagraphAlignment.valueOf(alignment.toUpperCase(Locale.ROOT)));
}
}
@ -213,6 +217,28 @@ public class HtmlToWorldBuilder implements NodeVisitor {
this.run.addBreak();
}
break;
case "h1":
System.out.println(this.run.getFontSize());
this.run.setFontSize(24);
break;
case "h2":
this.run.setFontSize(20);
break;
case "h3":
this.run.setFontSize(16);
break;
case "h4":
this.run.setFontSize(14);
this.run.setBold(stringBooleanEntry.getValue());
break;
case "h5":
this.run.setFontSize(14);
break;
case "h6":
this.run.setFontSize(11);
this.run.setBold(stringBooleanEntry.getValue());
this.run.setCapitalized(stringBooleanEntry.getValue());
break;
}
});
}

View File

@ -1,11 +1,11 @@
package eu.eudat.file.transformer.service.wordfiletransformer.word;
package org.opencdmp.filetransformer.docx.service.wordfiletransformer.word;
import eu.eudat.commonmodels.models.description.DescriptionModel;
import eu.eudat.commonmodels.models.description.PropertyDefinitionModel;
import eu.eudat.commonmodels.models.descriptiotemplate.DescriptionTemplateModel;
import eu.eudat.commonmodels.models.dmp.DmpModel;
import eu.eudat.file.transformer.model.enums.ParagraphStyle;
import eu.eudat.file.transformer.service.wordfiletransformer.visibility.VisibilityService;
import org.opencdmp.commonmodels.models.description.DescriptionModel;
import org.opencdmp.commonmodels.models.description.PropertyDefinitionModel;
import org.opencdmp.commonmodels.models.descriptiotemplate.DescriptionTemplateModel;
import org.opencdmp.commonmodels.models.dmp.DmpModel;
import org.opencdmp.filetransformer.docx.model.enums.ParagraphStyle;
import org.opencdmp.filetransformer.docx.service.wordfiletransformer.visibility.VisibilityService;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;

View File

@ -1,23 +1,26 @@
package eu.eudat.file.transformer.service.wordfiletransformer.word;
package org.opencdmp.filetransformer.docx.service.wordfiletransformer.word;
import eu.eudat.commonmodels.enums.FieldType;
import eu.eudat.commonmodels.models.description.DescriptionModel;
import eu.eudat.commonmodels.models.description.PropertyDefinitionFieldSetItemModel;
import eu.eudat.commonmodels.models.description.PropertyDefinitionFieldSetModel;
import eu.eudat.commonmodels.models.description.PropertyDefinitionModel;
import eu.eudat.commonmodels.models.descriptiotemplate.*;
import eu.eudat.commonmodels.models.descriptiotemplate.fielddata.*;
import eu.eudat.commonmodels.models.dmp.DmpModel;
import eu.eudat.commonmodels.models.dmpreference.DmpReferenceModel;
import eu.eudat.commonmodels.models.reference.ReferenceFieldModel;
import eu.eudat.commonmodels.models.reference.ReferenceModel;
import eu.eudat.file.transformer.service.storage.FileStorageServiceProperties;
import eu.eudat.file.transformer.service.wordfiletransformer.WordFileTransformerServiceProperties;
import eu.eudat.file.transformer.model.PidLink;
import eu.eudat.file.transformer.model.interfaces.ApplierWithValue;
import eu.eudat.file.transformer.service.pid.PidService;
import eu.eudat.file.transformer.model.enums.ParagraphStyle;
import eu.eudat.file.transformer.service.wordfiletransformer.visibility.VisibilityService;
import gr.cite.tools.exception.MyApplicationException;
import org.opencdmp.commonmodels.enums.FieldType;
import org.opencdmp.commonmodels.models.FileEnvelopeModel;
import org.opencdmp.commonmodels.models.description.DescriptionModel;
import org.opencdmp.commonmodels.models.description.PropertyDefinitionFieldSetItemModel;
import org.opencdmp.commonmodels.models.description.PropertyDefinitionFieldSetModel;
import org.opencdmp.commonmodels.models.description.PropertyDefinitionModel;
import org.opencdmp.commonmodels.models.descriptiotemplate.*;
import org.opencdmp.commonmodels.models.descriptiotemplate.fielddata.*;
import org.opencdmp.commonmodels.models.dmp.DmpModel;
import org.opencdmp.commonmodels.models.dmpreference.DmpReferenceModel;
import org.opencdmp.commonmodels.models.reference.ReferenceFieldModel;
import org.opencdmp.commonmodels.models.reference.ReferenceModel;
import org.opencdmp.filetransformer.docx.service.storage.FileStorageService;
import org.opencdmp.filetransformer.docx.service.storage.FileStorageServiceProperties;
import org.opencdmp.filetransformer.docx.service.wordfiletransformer.WordFileTransformerServiceProperties;
import org.opencdmp.filetransformer.docx.model.PidLink;
import org.opencdmp.filetransformer.docx.model.interfaces.ApplierWithValue;
import org.opencdmp.filetransformer.docx.service.pid.PidService;
import org.opencdmp.filetransformer.docx.model.enums.ParagraphStyle;
import org.opencdmp.filetransformer.docx.service.wordfiletransformer.visibility.VisibilityService;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.usermodel.*;
@ -26,6 +29,7 @@ import org.apache.xmlbeans.XmlObject;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.select.NodeTraversor;
import org.opencdmp.filetransformerbase.interfaces.FileTransformerConfiguration;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@ -37,16 +41,11 @@ import javax.imageio.ImageIO;
import javax.imageio.ImageReader;
import javax.imageio.stream.ImageInputStream;
import javax.management.InvalidApplicationException;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.*;
import java.math.BigInteger;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;
import static org.apache.poi.xwpf.usermodel.Document.*;
@ -66,17 +65,17 @@ public class WordBuilderImpl implements WordBuilder {
private Integer indent;
private Integer imageCount;
private final CTAbstractNum cTAbstractNum;
private final FileStorageServiceProperties fileStorageServiceProperties;
private final FileStorageService fileStorageService;
private final WordFileTransformerServiceProperties wordFileTransformerServiceProperties;
private final PidService pidService;
private final Map<ParagraphStyle, ApplierWithValue<XWPFDocument, Object, XWPFParagraph>> options = new HashMap<>();
private final Map<ParagraphStyle, ApplierWithValue<XWPFTableCell, Object, XWPFParagraph>> optionsInTable = new HashMap<>();
public WordBuilderImpl(FileStorageServiceProperties fileStorageServiceProperties, WordFileTransformerServiceProperties wordFileTransformerServiceProperties, PidService pidService) {
this.fileStorageServiceProperties = fileStorageServiceProperties;
this.wordFileTransformerServiceProperties = wordFileTransformerServiceProperties;
public WordBuilderImpl(FileStorageService fileStorageService, WordFileTransformerServiceProperties wordFileTransformerServiceProperties, PidService pidService) {
this.fileStorageService = fileStorageService;
this.wordFileTransformerServiceProperties = wordFileTransformerServiceProperties;
this.pidService = pidService;
this.cTAbstractNum = CTAbstractNum.Factory.newInstance();
this.cTAbstractNum = CTAbstractNum.Factory.newInstance();
this.cTAbstractNum.setAbstractNumId(BigInteger.valueOf(1));
this.indent = 0;
this.imageCount = 0;
@ -111,8 +110,8 @@ public class WordBuilderImpl implements WordBuilder {
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"));
if (item instanceof FileEnvelopeModel)
run.setText(((FileEnvelopeModel)item).getFilename());
run.setFontSize(11);
run.setItalic(true);
return paragraph;
@ -204,14 +203,22 @@ public class WordBuilderImpl implements WordBuilder {
paragraph.setSpacingAfter(0);
paragraph.setAlignment(ParagraphAlignment.CENTER); //GK: Center the image if it is too small
XWPFRun run = paragraph.createRun();
String imageId = ((Map<String, String>) item).get("id");
String fileName = ((Map<String, String>) item).get("name");
String fileType = ((Map<String, String>) item).get("type");
int format;
format = IMAGE_TYPE_MAP.getOrDefault(fileType, 0);
FileEnvelopeModel itemTyped = (FileEnvelopeModel)item;
if (itemTyped == null) return paragraph;
try {
FileInputStream image = new FileInputStream(fileStorageServiceProperties.getTemp() + imageId);
ImageInputStream iis = ImageIO.createImageInputStream(new File(fileStorageServiceProperties.getTemp() + imageId));
String fileName = itemTyped.getFilename();
String fileType = itemTyped.getMimeType();
int format;
format = IMAGE_TYPE_MAP.getOrDefault(fileType, 0);
byte[] file;
if (this.wordFileTransformerServiceProperties.isUseSharedStorage() && itemTyped.getFileRef() != null && !itemTyped.getFileRef().isBlank()) {
file = this.fileStorageService.readFile(itemTyped.getFileRef());
} else {
file = itemTyped.getFile();
}
InputStream image = new ByteArrayInputStream(file);
ImageInputStream iis = ImageIO.createImageInputStream(new ByteArrayInputStream(file));
Iterator<ImageReader> readers = ImageIO.getImageReaders(iis);
if (readers.hasNext()) {
ImageReader reader = readers.next();
@ -222,17 +229,17 @@ public class WordBuilderImpl implements WordBuilder {
float ratio = initialImageHeight / (float) initialImageWidth;
int marginLeftInDXA = (int) mainDocumentPart.getDocument().getBody().getSectPr().getPgMar().getLeft();
int marginRightInDXA = (int) mainDocumentPart.getDocument().getBody().getSectPr().getPgMar().getRight();
int pageWidthInDXA = (int) mainDocumentPart.getDocument().getBody().getSectPr().getPgSz().getW();
int marginLeftInDXA = this.toIntFormBigInteger(mainDocumentPart.getDocument().getBody().getSectPr().getPgMar().getLeft());
int marginRightInDXA = this.toIntFormBigInteger(mainDocumentPart.getDocument().getBody().getSectPr().getPgMar().getRight());
int pageWidthInDXA = this.toIntFormBigInteger(mainDocumentPart.getDocument().getBody().getSectPr().getPgSz().getW());
int pageWidth = Math.round((pageWidthInDXA - marginLeftInDXA - marginRightInDXA) / (float) 20); // /20 converts dxa to points
int imageWidth = Math.round(initialImageWidth * (float) 0.75); // *0.75 converts pixels to points
int width = Math.min(imageWidth, pageWidth);
int marginTopInDXA = (int) mainDocumentPart.getDocument().getBody().getSectPr().getPgMar().getTop();
int marginBottomInDXA = (int) mainDocumentPart.getDocument().getBody().getSectPr().getPgMar().getBottom();
int pageHeightInDXA = (int) mainDocumentPart.getDocument().getBody().getSectPr().getPgSz().getH();
int marginTopInDXA = this.toIntFormBigInteger(mainDocumentPart.getDocument().getBody().getSectPr().getPgMar().getTop());
int marginBottomInDXA = this.toIntFormBigInteger(mainDocumentPart.getDocument().getBody().getSectPr().getPgMar().getBottom());
int pageHeightInDXA = this.toIntFormBigInteger(mainDocumentPart.getDocument().getBody().getSectPr().getPgSz().getH());
int pageHeight = Math.round((pageHeightInDXA - marginTopInDXA - marginBottomInDXA) / (float) 20); // /20 converts dxa to points
int imageHeight = Math.round(initialImageHeight * ((float) 0.75)); // *0.75 converts pixels to points
@ -255,12 +262,22 @@ public class WordBuilderImpl implements WordBuilder {
captionRun.setText("Image " + imageCount);
}
} catch (IOException | InvalidFormatException e) {
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return paragraph;
});
}
private int toIntFormBigInteger(Object object){
try {
if (object instanceof BigInteger) return ((BigInteger) object).intValue();
return (int) object;
} catch (Exception e){
logger.error(e.getMessage(), e);
return 0;
}
}
@Override
public void build(XWPFDocument document, DescriptionTemplateModel descriptionTemplate, PropertyDefinitionModel propertyDefinitionModel, VisibilityService visibilityService) {
@ -268,23 +285,28 @@ public class WordBuilderImpl implements WordBuilder {
}
private void createPages(List<PageModel> datasetProfilePages, PropertyDefinitionModel propertyDefinitionModel, XWPFDocument mainDocumentPart, VisibilityService visibilityService) {
datasetProfilePages.stream().filter(item -> item.getSections() != null).forEach(item -> {
try {
if (visibilityService.isVisible(item.getId(), null)) {
createSections(item.getSections(), propertyDefinitionModel, mainDocumentPart, 0, false, item.getOrdinal() + 1, null, visibilityService);
for (PageModel item : datasetProfilePages) {
if (item.getSections() != null) {
try {
XWPFParagraph paragraph = addParagraphContent(item.getOrdinal() + 1 + " " + item.getTitle(), mainDocumentPart, ParagraphStyle.HEADER5, numId, 0);
mainDocumentPart.getPosOfParagraph(paragraph);
if (visibilityService.isVisible(item.getId(), null)) {
createSections(item.getSections(), propertyDefinitionModel, mainDocumentPart, 1, false, item.getOrdinal() + 1, null, visibilityService);
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
}
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
});
}
private void createSections(List<SectionModel> sections, PropertyDefinitionModel propertyDefinitionModel, XWPFDocument mainDocumentPart, Integer indent, Boolean createListing, Integer page, String sectionString, VisibilityService visibilityService) {
private boolean createSections(List<SectionModel> sections, PropertyDefinitionModel propertyDefinitionModel, XWPFDocument mainDocumentPart, Integer indent, Boolean createListing, Integer page, String sectionString, VisibilityService visibilityService) {
if (createListing) this.addListing(indent, false, true);
boolean hasValue = false;
boolean hasAnySectionValue = false;
for (SectionModel section : sections) {
if (!visibilityService.isVisible(section.getId(), null)) continue;
boolean hasValue = false;
int paragraphPos = -1;
String tempSectionString = sectionString != null ? sectionString + "." + (section.getOrdinal() + 1) : "" + (section.getOrdinal() + 1);
if (!createListing) {
@ -292,7 +314,7 @@ public class WordBuilderImpl implements WordBuilder {
paragraphPos = mainDocumentPart.getPosOfParagraph(paragraph);
}
if (section.getSections() != null) {
createSections(section.getSections(), propertyDefinitionModel, mainDocumentPart, indent + 1, createListing, page, tempSectionString, visibilityService);
hasValue = createSections(section.getSections(), propertyDefinitionModel, mainDocumentPart, indent + 1, createListing, page, tempSectionString, visibilityService);
}
if (section.getFieldSets() != null) {
hasValue = createFieldSetFields(section.getFieldSets(), propertyDefinitionModel, mainDocumentPart, indent + 1, createListing, page, tempSectionString, visibilityService);
@ -301,7 +323,10 @@ public class WordBuilderImpl implements WordBuilder {
if (!hasValue && paragraphPos > -1) {
mainDocumentPart.removeBodyElement(paragraphPos);
}
hasAnySectionValue = hasAnySectionValue || hasValue;
}
return hasAnySectionValue;
}
@ -326,7 +351,7 @@ public class WordBuilderImpl implements WordBuilder {
// CTDecimalNumber number = paragraph.getCTP().getPPr().getNumPr().addNewIlvl();
// number.setVal(BigInteger.valueOf(indent));
paragraphPos = mainDocumentPart.getPosOfParagraph(paragraph);
if (!fieldSetModel.getMultiplicity().getTableView() && propertyDefinitionFieldSetItemModels.size() > 1) {
if (fieldSetModel.getMultiplicity() != null && !fieldSetModel.getMultiplicity().getTableView() && propertyDefinitionFieldSetItemModels.size() > 1) {
XWPFParagraph paragraphInner = addParagraphContent(c + ". ", mainDocumentPart, ParagraphStyle.TEXT, numId, indent);
paragraphPosInner = mainDocumentPart.getPosOfParagraph(paragraphInner);
hasMultiplicityItems = true;
@ -336,7 +361,7 @@ public class WordBuilderImpl implements WordBuilder {
XWPFTable tbl = null;
XWPFTableRow row = null;
int numOfRows = 0;
if (fieldSetModel.getMultiplicity().getTableView()) {
if (fieldSetModel.getMultiplicity() != null && fieldSetModel.getMultiplicity().getTableView()) {
tbl = mainDocumentPart.createTable();
tbl.setTableAlignment(TableRowAlign.CENTER);
mainDocumentPart.createParagraph();
@ -344,7 +369,7 @@ public class WordBuilderImpl implements WordBuilder {
numOfRows = tbl.getRows().size();
row = tbl.createRow();
}
if (fieldSetModel.getMultiplicity().getTableView()) {
if (fieldSetModel.getMultiplicity() != null && fieldSetModel.getMultiplicity().getTableView()) {
hasValue = createFieldsInTable(fieldSetModel, propertyDefinitionFieldSetItemModels.getFirst(), row, indent, createListing, hasMultiplicityItems, numOfRows, visibilityService);
numOfRows++;
} else {
@ -360,7 +385,7 @@ public class WordBuilderImpl implements WordBuilder {
if (propertyDefinitionFieldSetItemModels.size() > 1) {
for (PropertyDefinitionFieldSetItemModel multiplicityFieldset : propertyDefinitionFieldSetItemModels.stream().skip(1).toList()) {
paragraphPosInner = -1;
if (!fieldSetModel.getMultiplicity().getTableView() && !createListing) {
if (fieldSetModel.getMultiplicity() != null && !fieldSetModel.getMultiplicity().getTableView() && !createListing) {
c++;
// addParagraphContent(c + ". ", mainDocumentPart, ParagraphStyle.HEADER6, numId);
XWPFParagraph paragraphInner = addParagraphContent(c + ". ", mainDocumentPart, ParagraphStyle.TEXT, numId, indent);
@ -370,7 +395,7 @@ public class WordBuilderImpl implements WordBuilder {
}
// hasValue = createFields(multiplicityFieldset.getFields(), mainDocumentPart, 3, createListing, visibilityRuleService, hasMultiplicityItems);
boolean hasValueInner = false;
if (fieldSetModel.getMultiplicity().getTableView()) {
if (fieldSetModel.getMultiplicity() != null && fieldSetModel.getMultiplicity().getTableView() && tbl != null) {
row = tbl.createRow();
hasValueInner = createFieldsInTable(fieldSetModel, multiplicityFieldset, row, indent, createListing, hasMultiplicityItems, numOfRows, visibilityService);
numOfRows++;
@ -388,7 +413,7 @@ public class WordBuilderImpl implements WordBuilder {
}
}
if (multiplicityItems == 1) {
String text = mainDocumentPart.getLastParagraph().getRuns().get(0).getText(0);
String text = mainDocumentPart.getLastParagraph().getRuns().getFirst().getText(0);
if (text.equals("a. ")) {
mainDocumentPart.getLastParagraph().removeRun(0);
}
@ -450,107 +475,74 @@ public class WordBuilderImpl implements WordBuilder {
for (FieldModel field : tempFields) {
if (field.getIncludeInExport() && visibilityService.isVisible(field.getId(), propertyDefinitionFieldSetItemModel.getOrdinal())) {
if (!createListing) {
try {
eu.eudat.commonmodels.models.description.FieldModel fieldValueModel = propertyDefinitionFieldSetItemModel.getFields().getOrDefault(field.getId(), null);
if (field.getData().getFieldType().equals(FieldType.UPLOAD)) {
boolean isImage = false;
for (UploadDataModel.UploadOptionModel type : ((UploadDataModel) field.getData()).getTypes()) {
String fileFormat = type.getValue();
if (IMAGE_TYPE_MAP.containsKey(fileFormat)) {
isImage = true;
break;
}
org.opencdmp.commonmodels.models.description.FieldModel fieldValueModel = propertyDefinitionFieldSetItemModel.getFields().getOrDefault(field.getId(), null);
if (field.getData().getFieldType().equals(FieldType.UPLOAD)) {
boolean isImage = false;
for (UploadDataModel.UploadOptionModel type : ((UploadDataModel) field.getData()).getTypes()) {
String fileFormat = type.getValue();
if (IMAGE_TYPE_MAP.containsKey(fileFormat)) {
isImage = true;
break;
}
if (isImage) {
if (fieldValueModel != null && fieldValueModel.getTextValue() != null && !fieldValueModel.getTextValue().isEmpty()) {
XWPFParagraph paragraph = addCellContent(fieldValueModel.getTextValue(), mainDocumentPart, ParagraphStyle.IMAGE, numId, 0, numOfRows, numOfCells, 0); //TODO
if (paragraph != null) {
hasValue = true;
}
if (hasMultiplicityItems) {
hasMultiplicityItems = false;
}
}
}
} else if (fieldValueModel != null) {
this.indent = indent;
String format = this.formatter(field, fieldValueModel);
Boolean hasMultiAutoComplete = false;
boolean isResearcher = false;
if (field.getData() instanceof LabelAndMultiplicityDataModel) {
hasMultiAutoComplete = ((LabelAndMultiplicityDataModel) field.getData()).getMultipleSelect();
}
if (field.getData() instanceof SelectDataModel) {
hasMultiAutoComplete = ((SelectDataModel) field.getData()).getMultipleSelect();
}
if (field.getData() instanceof ReferenceTypeDataModel) {
hasMultiAutoComplete = ((ReferenceTypeDataModel) field.getData()).getMultipleSelect();
isResearcher = ((ReferenceTypeDataModel) field.getData()).getReferenceType().getCode().equals(this.wordFileTransformerServiceProperties.getResearcherReferenceCode());
}
if (format != null && !format.isEmpty()) {
boolean isMultiAutoComplete = hasMultiAutoComplete != null && 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.getData().getFieldType().equals(FieldType.RICH_TEXT_AREA) ? 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.getFirst();
}
}
}
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.getData().getFieldType().equals(FieldType.RICH_TEXT_AREA) ? ParagraphStyle.HTML : ParagraphStyle.TEXT, numId, indent, numOfRows, numOfCells, 0);
}
if (isImage) {
if (fieldValueModel != null && fieldValueModel.getTextValue() != null && !fieldValueModel.getTextValue().isEmpty()) {
XWPFParagraph paragraph = addCellContent(fieldValueModel.getFile(), mainDocumentPart, ParagraphStyle.IMAGE, numId, 0, numOfRows, numOfCells, 0);
if (paragraph != null) {
hasValue = true;
}
if (hasMultiplicityItems) {
hasMultiplicityItems = false;
}
}
}
} else if (fieldValueModel != null) {
this.indent = indent;
boolean isResearcher = false;
if (field.getData() instanceof ReferenceTypeDataModel) {
isResearcher = ((ReferenceTypeDataModel) field.getData()).getReferenceType().getCode().equals(this.wordFileTransformerServiceProperties.getResearcherReferenceCode());
}
List<String> extractValues = this.extractValues(field, fieldValueModel);
if (!extractValues.isEmpty()){
int numOfValuesInCell = 0;
for (String extractValue : extractValues){
boolean orcidResearcher = false;
String orcId = null;
if (isResearcher && extractValue.contains("orcid:")) {
orcId = extractValue.substring(extractValue.indexOf(':') + 1, extractValue.indexOf(')'));
extractValue = extractValue.substring(0, extractValue.indexOf(':') + 1) + " ";
orcidResearcher = true;
}
if (extractValues.size() > 1) extractValue = "" + extractValue;
if (hasMultiplicityItems) {
XWPFParagraph paragraph = mainDocumentPart.getCell(mainDocumentPart.getTableCells().size()).addParagraph();
paragraph.createRun().setText(extractValue);
if (orcidResearcher) {
XWPFHyperlinkRun run = paragraph.createHyperlinkRun("https://orcid.org/" + orcId);
run.setText(orcId);
run.setUnderline(UnderlinePatterns.SINGLE);
run.setColor("0000FF");
paragraph.createRun().setText(")");
}
hasValue = true;
hasMultiplicityItems = false;
} else {
XWPFParagraph paragraph = addCellContent(extractValue, mainDocumentPart, field.getData().getFieldType().equals(FieldType.RICH_TEXT_AREA) ? ParagraphStyle.HTML : ParagraphStyle.TEXT, numId, indent, numOfRows, numOfCells, numOfValuesInCell);
if (paragraph != null) {
numOfValuesInCell++;
if (orcidResearcher) {
XWPFHyperlinkRun run = paragraph.createHyperlinkRun("https://orcid.org/" + orcId);
run.setText(orcId);
run.setUnderline(UnderlinePatterns.SINGLE);
run.setColor("0000FF");
paragraph.createRun().setText(")");
}
hasValue = true;
}
}
}
}
} catch (InvalidApplicationException e) {
logger.error(e.getMessage(), e);
}
}
numOfCells++;
@ -595,8 +587,7 @@ public class WordBuilderImpl implements WordBuilder {
for (FieldModel field : tempFields) {
if (field.getIncludeInExport() && visibilityService.isVisible(field.getId(), propertyDefinitionFieldSetItemModel.getOrdinal())) {
if (!createListing) {
try {
eu.eudat.commonmodels.models.description.FieldModel fieldValueModel = propertyDefinitionFieldSetItemModel.getFields().getOrDefault(field.getId(), null);
org.opencdmp.commonmodels.models.description.FieldModel fieldValueModel = propertyDefinitionFieldSetItemModel.getFields().getOrDefault(field.getId(), null);
if (field.getData() != null) {
if (field.getData().getFieldType().equals(FieldType.UPLOAD)) {
boolean isImage = false;
@ -609,7 +600,7 @@ public class WordBuilderImpl implements WordBuilder {
}
if (isImage) {
if (fieldValueModel.getTextValue() != null && !fieldValueModel.getTextValue().isEmpty()) {
XWPFParagraph paragraph = addParagraphContent(fieldValueModel.getTextValue(), mainDocumentPart, ParagraphStyle.IMAGE, numId, 0); //TODO
XWPFParagraph paragraph = addParagraphContent(fieldValueModel.getFile(), mainDocumentPart, ParagraphStyle.IMAGE, numId, 0); //TODO
if (paragraph != null) {
hasValue = true;
}
@ -620,7 +611,6 @@ public class WordBuilderImpl implements WordBuilder {
}
} else if (fieldValueModel != null) {
this.indent = indent;
String format = this.formatter(field, fieldValueModel);
boolean isMultiAutoComplete = false;
boolean isResearcher = false;
boolean isOrganization = false;
@ -642,77 +632,63 @@ public class WordBuilderImpl implements WordBuilder {
if (isOrganization || isExternalDataset || isPublication) {
if (fieldValueModel.getReferences() != null) {
for (ReferenceModel referenceModel : fieldValueModel.getReferences())
createHypeLink(mainDocumentPart, format, referenceModel.getDefinition().getFields().stream().filter(x -> x.getCode().equals("pidTypeField")).map(ReferenceFieldModel::getValue).findFirst().orElse(null), referenceModel.getReference(), hasMultiplicityItems, isMultiAutoComplete && fieldValueModel.getReferences().size() > 1);
for (ReferenceModel referenceModel : fieldValueModel.getReferences()) {
String label = "";
if (referenceModel.getLabel() != null && !referenceModel.getLabel().isBlank()) {
label = referenceModel.getLabel();
}
if (referenceModel.getDescription() != null && !referenceModel.getDescription().isBlank()) {
label = (label.isBlank() ? "" : " ") + referenceModel.getDescription();
}
createHypeLink(mainDocumentPart, label, referenceModel.getDefinition().getFields().stream().filter(x -> x.getCode().equals("pidTypeField")).map(ReferenceFieldModel::getValue).findFirst().orElse(null), referenceModel.getReference(), hasMultiplicityItems, isMultiAutoComplete && fieldValueModel.getReferences().size() > 1);
}
if (hasMultiplicityItems) hasMultiplicityItems = false;
hasValue = true;
}
} else {
if (format != null && !format.isEmpty()) {
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;
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) {
mainDocumentPart.getLastParagraph().createRun().setText(format);
if (orcidResearcher) {
XWPFHyperlinkRun run = mainDocumentPart.getLastParagraph().createHyperlinkRun("https://orcid.org/" + orcId);
run.setText(orcId);
run.setUnderline(UnderlinePatterns.SINGLE);
run.setColor("0000FF");
mainDocumentPart.getLastParagraph().createRun().setText(")");
}
hasMultiplicityItems = false;
} else {
XWPFParagraph paragraph = addParagraphContent(format, mainDocumentPart, field.getData().getFieldType().equals(FieldType.RICH_TEXT_AREA) ? ParagraphStyle.HTML : ParagraphStyle.TEXT, numId, indent);
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.getFirst();
List<String> extractValues = this.extractValues(field, fieldValueModel);
if (!extractValues.isEmpty()){
for (String extractValue : extractValues){
boolean orcidResearcher = false;
String orcId = null;
if (isResearcher && extractValue.contains("orcid:")) {
orcId = extractValue.substring(extractValue.indexOf(':') + 1, extractValue.indexOf(')'));
extractValue = extractValue.substring(0, extractValue.indexOf(':') + 1) + " ";
orcidResearcher = true;
}
}
}
if (format != null) {
if (hasMultiplicityItems) {
mainDocumentPart.getLastParagraph().createRun().setText(format);
hasMultiplicityItems = false;
hasValue = true;
} else {
XWPFParagraph paragraph = addParagraphContent(format, mainDocumentPart, field.getData().getFieldType().equals(FieldType.RICH_TEXT_AREA) ? ParagraphStyle.HTML : ParagraphStyle.TEXT, numId, indent);
if (paragraph != null) {
if (extractValues.size() > 1) extractValue = "" + extractValue;
if (hasMultiplicityItems) {
mainDocumentPart.getLastParagraph().createRun().setText(extractValue);
if (orcidResearcher) {
XWPFHyperlinkRun run = mainDocumentPart.getLastParagraph().createHyperlinkRun("https://orcid.org/" + orcId);
run.setText(orcId);
run.setUnderline(UnderlinePatterns.SINGLE);
run.setColor("0000FF");
mainDocumentPart.getLastParagraph().createRun().setText(")");
}
hasValue = true;
hasMultiplicityItems = false;
} else {
XWPFParagraph paragraph = addParagraphContent(extractValue, mainDocumentPart, field.getData().getFieldType().equals(FieldType.RICH_TEXT_AREA) ? ParagraphStyle.HTML : ParagraphStyle.TEXT, numId, indent);
if (paragraph != null) {
if (orcidResearcher) {
XWPFHyperlinkRun run = paragraph.createHyperlinkRun("https://orcid.org/" + orcId);
run.setText(orcId);
run.setUnderline(UnderlinePatterns.SINGLE);
run.setColor("0000FF");
paragraph.createRun().setText(")");
}
hasValue = true;
}
}
}
}
}
}
}
} catch (InvalidApplicationException e) {
throw new RuntimeException(e);
}
}
}
}
@ -720,31 +696,29 @@ public class WordBuilderImpl implements WordBuilder {
}
private 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);
}
if (content == null) return 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;
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;
}
@ -785,31 +759,31 @@ public class WordBuilderImpl implements WordBuilder {
}
}
private String formatter(FieldModel field, eu.eudat.commonmodels.models.description.FieldModel fieldValueModel) throws InvalidApplicationException {
private List<String> extractValues(FieldModel field, org.opencdmp.commonmodels.models.description.FieldModel fieldValueModel) {
List<String> values = new ArrayList<>();
if (fieldValueModel == null || field == null || field.getData() == null) {
return null;
return values;
}
switch (field.getData().getFieldType()) {
case REFERENCE_TYPES: {
List<String> values = new ArrayList<>();
if (fieldValueModel.getReferences() != null && !fieldValueModel.getReferences().isEmpty()) {
for (ReferenceModel referenceModel : fieldValueModel.getReferences()) {
if (referenceModel != null) {
String label = "";
if (referenceModel.getLabel() != null && !referenceModel.getLabel().isBlank()) {
values.add(referenceModel.getLabel());
label = referenceModel.getLabel();
}
if (referenceModel.getDescription() != null && !referenceModel.getDescription().isBlank()) {
values.add(referenceModel.getLabel());
label = (label.isBlank() ? "" : " ") + referenceModel.getDescription();
}
if (!label.isBlank()) values.add(label);
}
}
}
return String.join(", ", values);
break;
}
case TAGS:
case SELECT: {
List<String> values = new ArrayList<>();
if (fieldValueModel.getTextListValue() != null && !fieldValueModel.getTextListValue().isEmpty()) {
SelectDataModel selectDataModel = (SelectDataModel) field.getData();
if (selectDataModel != null && selectDataModel.getOptions() != null && !selectDataModel.getOptions().isEmpty()) {
@ -818,49 +792,59 @@ public class WordBuilderImpl implements WordBuilder {
}
}
}
return String.join(", ", values);
break;
}
case BOOLEAN_DECISION:
if (fieldValueModel.getTextValue() != null && fieldValueModel.getTextValue().equals("true")) return "Yes";
if (fieldValueModel.getTextValue() != null && fieldValueModel.getTextValue().equals("false")) return "No";
return null;
if (fieldValueModel.getBooleanValue() != null && fieldValueModel.getBooleanValue()) values.add("Yes");
if (fieldValueModel.getBooleanValue() != null && !fieldValueModel.getBooleanValue()) values.add("No");
break;
case RADIO_BOX:
RadioBoxDataModel radioBoxDataModel = (RadioBoxDataModel) field.getData();
if (fieldValueModel.getTextValue() != null && radioBoxDataModel != null && radioBoxDataModel.getOptions() != null) {
for (RadioBoxDataModel.RadioBoxOptionModel option : radioBoxDataModel.getOptions()) {
if (option.getValue().equals(fieldValueModel.getTextValue()) || option.getLabel().equals(fieldValueModel.getTextValue())) return option.getLabel();
if (option.getValue().equals(fieldValueModel.getTextValue()) || option.getLabel().equals(fieldValueModel.getTextValue())) {
values.add(option.getLabel());
break;
}
}
}
return null;
case CHECK_BOX:
break;
case CHECK_BOX: {
LabelDataModel checkBoxData = (LabelDataModel) field.getData();
if (fieldValueModel.getTextValue() == null || fieldValueModel.getTextValue().equals("false")) return null;
return checkBoxData != null ? checkBoxData.getLabel() : null;
if (fieldValueModel.getBooleanValue() != null && fieldValueModel.getBooleanValue() && checkBoxData != null && checkBoxData.getLabel() != null) values.add(checkBoxData.getLabel());
break;
}
case DATE_PICKER: {
return fieldValueModel.getDateValue() != null ? DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.systemDefault()).format(fieldValueModel.getDateValue()) : "";
if (fieldValueModel.getDateValue() != null) values.add(DateTimeFormatter.ofPattern("yyyy-MM-dd").withZone(ZoneId.systemDefault()).format(fieldValueModel.getDateValue()));
break;
}
case FREE_TEXT:
case TEXT_AREA:
case RICH_TEXT_AREA:
return fieldValueModel.getTextValue() != null ? fieldValueModel.getTextValue() : "";
case RICH_TEXT_AREA: {
if (fieldValueModel.getTextValue() != null && !fieldValueModel.getTextValue().isBlank()) values.add(fieldValueModel.getTextValue());
break;
}
case DATASET_IDENTIFIER:
case VALIDATION:
case VALIDATION: {
if (fieldValueModel.getExternalIdentifier() != null) {
return "id: " + fieldValueModel.getExternalIdentifier().getIdentifier() + ", Type: " + fieldValueModel.getExternalIdentifier().getType();
values.add("id: " + fieldValueModel.getExternalIdentifier().getIdentifier() + ", Type: " + fieldValueModel.getExternalIdentifier().getType());
}
return "";
break;
}
case UPLOAD:
case INTERNAL_ENTRIES_DESCRIPTIONS:
case INTERNAL_ENTRIES_DMPS:
return null;
break;
default:
throw new InvalidApplicationException("Invalid type " + field.getData().getFieldType());
throw new MyApplicationException("Invalid type " + field.getData().getFieldType());
}
return values;
}
@Override
public int findPosOfPoweredBy(XWPFDocument document) {
if (document == null) throw new IllegalArgumentException("Document required");
if (document == null) throw new MyApplicationException("Document required");
if (document.getParagraphs() == null) return -1;
for (XWPFParagraph p : document.getParagraphs()) {
@ -892,8 +876,8 @@ public class WordBuilderImpl implements WordBuilder {
@Override
public void fillFirstPage(DmpModel dmpEntity, DescriptionModel descriptionModel, XWPFDocument document, boolean isDescription) {
if (dmpEntity == null) throw new IllegalArgumentException("DmpEntity required");
if (document == null) throw new IllegalArgumentException("Document required");
if (dmpEntity == null) throw new MyApplicationException("DmpEntity required");
if (document == null) throw new MyApplicationException("Document required");
int parPos = 0;
int descrParPos = -1;
@ -911,21 +895,21 @@ public class WordBuilderImpl implements WordBuilder {
this.replaceTextSegment(p, "'{ARGOS.DATASET.TITLE}'", descriptionModel.getLabel());
}
String researchersNames = "";
StringBuilder researchersNames = new StringBuilder();
int i = 0;
for (ReferenceModel researcher : researchers) {
i++;
researchersNames += researcher.getLabel() + (i < researchers.size() ? ", " : "");
researchersNames.append(researcher.getLabel()).append(i < researchers.size() ? ", " : "");
}
this.replaceTextSegment(p, "'{ARGOS.DMP.RESEARCHERS}'", researchersNames, 15);
this.replaceTextSegment(p, "'{ARGOS.DMP.RESEARCHERS}'", researchersNames.toString(), 15);
String organisationsNames = "";
StringBuilder organisationsNames = new StringBuilder();
i = 0;
for (ReferenceModel organisation : organizations) {
i++;
organisationsNames += organisation.getLabel() + (i < organizations.size() ? ", " : "");
organisationsNames.append(organisation.getLabel()).append(i < organizations.size() ? ", " : "");
}
this.replaceTextSegment(p, "'{ARGOS.DMP.ORGANIZATIONS}'", organisationsNames, 15);
this.replaceTextSegment(p, "'{ARGOS.DMP.ORGANIZATIONS}'", organisationsNames.toString(), 15);
if (this.textSegmentExists(p, "'{ARGOS.DMP.DESCRIPTION}'")) {
descrParPos = parPos;
@ -938,27 +922,27 @@ public class WordBuilderImpl implements WordBuilder {
this.replaceTextSegment(p, "'{ARGOS.DATASET.DESCRIPTION}'", "");
}
}
if ((descrParPos != -1) && (dmpEntity != null) && (dmpEntity.getDescription() != null) && !isDescription) {
if ((descrParPos != -1) && (dmpEntity.getDescription() != null) && !isDescription) {
XmlCursor cursor = descrPar.getCTP().newCursor();
cursor.toNextSibling();
Document htmlDoc = Jsoup.parse(((String) dmpEntity.getDescription()).replaceAll("\n", "<br>"));
Document htmlDoc = Jsoup.parse((dmpEntity.getDescription()).replaceAll("\n", "<br>"));
HtmlToWorldBuilder htmlToWorldBuilder = new HtmlToWorldBuilder(descrPar, 0, cursor);
NodeTraversor.traverse(htmlToWorldBuilder, htmlDoc);
}
if ((descrParPos != -1) && (descriptionModel != null) && (descriptionModel.getDescription() != null) && isDescription) {
XmlCursor cursor = descrPar.getCTP().newCursor();
cursor.toNextSibling();
Document htmlDoc = Jsoup.parse(((String) descriptionModel.getDescription()).replaceAll("\n", "<br>"));
Document htmlDoc = Jsoup.parse((descriptionModel.getDescription()).replaceAll("\n", "<br>"));
HtmlToWorldBuilder htmlToWorldBuilder = new HtmlToWorldBuilder(descrPar, 0, cursor);
NodeTraversor.traverse(htmlToWorldBuilder, htmlDoc);
}
XWPFTable tbl = document.getTables().get(0);
XWPFTable tbl = document.getTables().getFirst();
Iterator<XWPFTableRow> it = tbl.getRows().iterator();
it.next(); // skip first row
if (it.hasNext() && !funders.isEmpty()) {
XWPFParagraph p = it.next().getCell(0).getParagraphs().get(0);
XWPFParagraph p = it.next().getCell(0).getParagraphs().getFirst();
XWPFRun run = p.createRun();
run.setText(funders.getFirst().getLabel());
run.setFontSize(15);
@ -967,7 +951,7 @@ public class WordBuilderImpl implements WordBuilder {
it = tbl.getRows().iterator();
it.next();
if (it.hasNext() && !grants.isEmpty()) {
XWPFParagraph p = it.next().getCell(1).getParagraphs().get(0);
XWPFParagraph p = it.next().getCell(1).getParagraphs().getFirst();
XWPFRun run = p.createRun();
String text = grants.getFirst().getLabel();
String reference = grants.getFirst().getReference();
@ -982,12 +966,8 @@ public class WordBuilderImpl implements WordBuilder {
}
private boolean textSegmentExists(XWPFParagraph paragraph, String textToFind) {
TextSegment foundTextSegment = null;
PositionInParagraph startPos = new PositionInParagraph(0, 0, 0);
while ((foundTextSegment = this.searchText(paragraph, textToFind, startPos)) != null) {
return true;
}
return false;
return this.searchText(paragraph, textToFind, startPos) != null;
}
private void replaceTextSegment(XWPFParagraph paragraph, String textToFind, String replacement) {
@ -995,12 +975,12 @@ public class WordBuilderImpl implements WordBuilder {
}
private void replaceTextSegment(XWPFParagraph paragraph, String textToFind, String replacement, Integer fontSize) {
TextSegment foundTextSegment = null;
TextSegment foundTextSegment;
PositionInParagraph startPos = new PositionInParagraph(0, 0, 0);
while((foundTextSegment = this.searchText(paragraph, textToFind, startPos)) != null) { // search all text segments having text to find
System.out.println(foundTextSegment.getBeginRun()+":"+foundTextSegment.getBeginText()+":"+foundTextSegment.getBeginChar());
System.out.println(foundTextSegment.getEndRun()+":"+foundTextSegment.getEndText()+":"+foundTextSegment.getEndChar());
logger.debug(foundTextSegment.getBeginRun()+":"+foundTextSegment.getBeginText()+":"+foundTextSegment.getBeginChar());
logger.debug(foundTextSegment.getEndRun()+":"+foundTextSegment.getEndText()+":"+foundTextSegment.getEndChar());
// maybe there is text before textToFind in begin run
XWPFRun beginRun = paragraph.getRuns().get(foundTextSegment.getBeginRun());
@ -1050,63 +1030,61 @@ public class WordBuilderImpl implements WordBuilder {
//CTR ctRun = rArray[runPos];
CTR ctRun = runs.get(runPos).getCTR();
XmlCursor c = ctRun.newCursor();
c.selectPath("./*");
try {
while (c.toNextSelection()) {
XmlObject o = c.getObject();
if (o instanceof CTText) {
if (textPos >= startText) {
String candidate = ((CTText) o).getStringValue();
if (runPos == startRun) {
charPos = startChar;
} else {
charPos = 0;
}
try (c) {
c.selectPath("./*");
while (c.toNextSelection()) {
XmlObject o = c.getObject();
if (o instanceof CTText) {
if (textPos >= startText) {
String candidate = ((CTText) o).getStringValue();
if (runPos == startRun) {
charPos = startChar;
} else {
charPos = 0;
}
for (; charPos < candidate.length(); charPos++) {
if ((candidate.charAt(charPos) == searched.charAt(0)) && (candCharPos == 0)) {
beginTextPos = textPos;
beginCharPos = charPos;
beginRunPos = runPos;
newList = true;
}
if (candidate.charAt(charPos) == searched.charAt(candCharPos)) {
if (candCharPos + 1 < searched.length()) {
candCharPos++;
} else if (newList) {
TextSegment segment = new TextSegment();
segment.setBeginRun(beginRunPos);
segment.setBeginText(beginTextPos);
segment.setBeginChar(beginCharPos);
segment.setEndRun(runPos);
segment.setEndText(textPos);
segment.setEndChar(charPos);
return segment;
}
} else {
candCharPos = 0;
}
}
}
textPos++;
} else if (o instanceof CTProofErr) {
c.removeXml();
} else if (o instanceof CTRPr) {
//do nothing
} else {
candCharPos = 0;
}
}
} finally {
c.dispose();
}
for (; charPos < candidate.length(); charPos++) {
if ((candidate.charAt(charPos) == searched.charAt(0)) && (candCharPos == 0)) {
beginTextPos = textPos;
beginCharPos = charPos;
beginRunPos = runPos;
newList = true;
}
if (candidate.charAt(charPos) == searched.charAt(candCharPos)) {
if (candCharPos + 1 < searched.length()) {
candCharPos++;
} else if (newList) {
TextSegment segment = new TextSegment();
segment.setBeginRun(beginRunPos);
segment.setBeginText(beginTextPos);
segment.setBeginChar(beginCharPos);
segment.setEndRun(runPos);
segment.setEndText(textPos);
segment.setEndChar(charPos);
return segment;
}
} else {
candCharPos = 0;
}
}
}
textPos++;
} else if (o instanceof CTProofErr) {
c.removeXml();
} else if (o instanceof CTRPr) {
//do nothing
} else {
candCharPos = 0;
}
}
}
}
return null;
}
@Override
public void fillFooter(DmpModel dmpEntity, DescriptionModel descriptionModel, XWPFDocument document) {
if (dmpEntity == null) throw new IllegalArgumentException("DmpEntity required");
if (dmpEntity == null) throw new MyApplicationException("DmpEntity required");
List<ReferenceModel> licences = this.getReferenceModelOfTypeCode(dmpEntity, this.wordFileTransformerServiceProperties.getLicenceReferenceCode());
document.getFooterList().forEach(xwpfFooter -> {

19
pom.xml
View File

@ -5,11 +5,11 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>3.2.3</version>
<version>3.2.4</version>
<relativePath/>
</parent>
<groupId>gr.cite.opendmp</groupId>
<groupId>org.opencdmp</groupId>
<artifactId>file-transformer-document-parent</artifactId>
<version>${revision}</version>
<packaging>pom</packaging>
@ -18,24 +18,31 @@
<maven.compiler.source>21</maven.compiler.source>
<maven.compiler.target>21</maven.compiler.target>
<maven.compiler.release>21</maven.compiler.release>
<log4j.version>1.2.17</log4j.version>
<log4j2.version>2.15.0</log4j2.version>
<revision>1.0.0-SNAPSHOT</revision>
</properties>
<dependencies>
<dependency>
<groupId>gr.cite.opendmp</groupId>
<groupId>org.opencdmp</groupId>
<artifactId>file-transformer-base</artifactId>
<version>0.0.11</version>
<version>0.0.22</version>
</dependency>
<dependency>
<groupId>org.yaml</groupId>
<artifactId>snakeyaml</artifactId>
<version>2.0</version>
<version>2.2</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.26.0</version>
<version>1.26.1</version>
</dependency>
<dependency>
<groupId>gr.cite</groupId>
<artifactId>logging</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>

View File

@ -1,29 +1,33 @@
<settings>
<pluginGroups>
<pluginGroup>org.sonarsource.scanner.maven</pluginGroup>
</pluginGroups>
<servers>
<server>
<id>ossrh</id>
<username>${server_username}</username>
<password>${server_password}</password>
</server>
<server>
<id>dev</id>
<id>cite-repo</id>
<username>${server_username}</username>
<password>${server_password}</password>
</server>
</servers>
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>true</activeByDefault>
</activation>
<id>release</id>
<repositories>
<repository>
<id>dev</id>
<name>Dev Profile</name>
<url>${devProfileUrl}</url>
<id>central</id>
<name>Central Repository</name>
<url>https://repo.maven.apache.org/maven2</url>
<layout>default</layout>
<snapshots>
<enabled>false</enabled>
</snapshots>
</repository>
<repository>
<id>cite-repo</id>
<name>CITE Maven Repo</name>
<url>${citeMavenRepoUrl}</url>
</repository>
</repositories>
</profile>
</profiles>
</settings>
</settings>

View File

@ -3,7 +3,7 @@
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>gr.cite.opendmp</groupId>
<groupId>org.opencdmp</groupId>
<artifactId>file-transformer-document-parent</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
@ -22,7 +22,7 @@
<dependencies>
<dependency>
<groupId>gr.cite.opendmp</groupId>
<groupId>org.opencdmp</groupId>
<artifactId>file-transformer-document</artifactId>
<version>${revision}</version>
</dependency>
@ -33,7 +33,7 @@
<dependency>
<groupId>gr.cite</groupId>
<artifactId>oidc-authn</artifactId>
<version>2.1.0</version>
<version>2.2.2</version>
</dependency>
<dependency>
<groupId>gr.cite</groupId>
@ -44,7 +44,12 @@
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
</dependencies>
<dependency>
<groupId>gr.cite</groupId>
<artifactId>exceptions</artifactId>
<version>2.2.0</version>
</dependency>
</dependencies>
<build>
<plugins>

View File

@ -1,42 +0,0 @@
package eu.eudat.file.transformer.web.controller;
import eu.eudat.commonmodels.models.FileEnvelopeModel;
import eu.eudat.commonmodels.models.description.DescriptionModel;
import eu.eudat.commonmodels.models.dmp.DmpModel;
import eu.eudat.file.transformer.interfaces.FileTransformerClient;
import eu.eudat.file.transformer.interfaces.FileTransformerConfiguration;
import eu.eudat.file.transformer.service.wordfiletransformer.WordFileTransformerService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
@RestController
@RequestMapping("/api/file-transformer")
public class FileTransformerController implements eu.eudat.file.transformer.interfaces.FileTransformerController {
private final FileTransformerClient fileTransformerExecutor;
@Autowired
public FileTransformerController(WordFileTransformerService fileTransformerExecutor) {
this.fileTransformerExecutor = fileTransformerExecutor;
}
public FileEnvelopeModel exportDmp(@RequestBody DmpModel dmpDepositModel, @RequestParam(value = "format",required = false)String format) throws Exception {
return fileTransformerExecutor.exportDmp(dmpDepositModel, format);
}
public FileEnvelopeModel exportDescription(@RequestBody DescriptionModel descriptionModel, @RequestParam(value = "format",required = false)String format) throws Exception {
return fileTransformerExecutor.exportDescription(descriptionModel, format);
}
public DmpModel importFileToDmp(@RequestBody FileEnvelopeModel fileEnvelope) {
return fileTransformerExecutor.importDmp(fileEnvelope);
}
public DescriptionModel importFileToDescription(@RequestBody FileEnvelopeModel fileEnvelope) {
return fileTransformerExecutor.importDescription(fileEnvelope);
}
public FileTransformerConfiguration getSupportedFormats() {
return fileTransformerExecutor.getConfiguration();
}
}

View File

@ -1,10 +1,11 @@
package eu.eudat.file.transformer;
package org.opencdmp.filetransformer.docx;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication(scanBasePackages = {
"eu.eudat.file.transformer",
"org.opencdmp.filetransformerbase",
"org.opencdmp.filetransformer.docx.*",
"gr.cite.tools",
"gr.cite.commons"
})

View File

@ -1,4 +1,4 @@
package eu.eudat.file.transformer.web.config;
package org.opencdmp.filetransformer.docx.web.config;
import gr.cite.commons.web.oidc.configuration.WebSecurityProperties;
import gr.cite.commons.web.oidc.configuration.filter.ApiKeyFilter;

View File

@ -0,0 +1,91 @@
package org.opencdmp.filetransformer.docx.web.controller;
import gr.cite.tools.auditing.AuditService;
import gr.cite.tools.logging.LoggerService;
import gr.cite.tools.logging.MapLogEntry;
import org.opencdmp.commonmodels.models.FileEnvelopeModel;
import org.opencdmp.commonmodels.models.description.DescriptionModel;
import org.opencdmp.commonmodels.models.dmp.DmpModel;
import org.opencdmp.filetransformer.docx.audit.AuditableAction;
import org.opencdmp.filetransformerbase.interfaces.FileTransformerClient;
import org.opencdmp.filetransformerbase.interfaces.FileTransformerConfiguration;
import org.opencdmp.filetransformer.docx.service.wordfiletransformer.WordFileTransformerService;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.AbstractMap;
import java.util.Map;
@RestController
@RequestMapping("/api/file-transformer")
public class FileTransformerController implements org.opencdmp.filetransformerbase.interfaces.FileTransformerController {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(FileTransformerController.class));
private final FileTransformerClient fileTransformerExecutor;
private final AuditService auditService;
@Autowired
public FileTransformerController(FileTransformerClient fileTransformerExecutor, AuditService auditService) {
this.fileTransformerExecutor = fileTransformerExecutor;
this.auditService = auditService;
}
public FileEnvelopeModel exportDmp(@RequestBody DmpModel dmpDepositModel, @RequestParam(value = "format",required = false)String format) throws Exception {
logger.debug(new MapLogEntry("exportDmp " + DmpModel.class.getSimpleName()).And("dmpDepositModel", dmpDepositModel).And("format", format));
FileEnvelopeModel model = fileTransformerExecutor.exportDmp(dmpDepositModel, format);
this.auditService.track(AuditableAction.FileTransformer_ExportDmp, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("dmpDepositModel", dmpDepositModel),
new AbstractMap.SimpleEntry<String, Object>("format", format)
));
return model;
}
public FileEnvelopeModel exportDescription(@RequestBody DescriptionModel descriptionModel, @RequestParam(value = "format",required = false)String format) throws Exception {
logger.debug(new MapLogEntry("exportDescription " + DescriptionModel.class.getSimpleName()).And("descriptionModel", descriptionModel).And("format", format));
FileEnvelopeModel model = fileTransformerExecutor.exportDescription(descriptionModel, format);
this.auditService.track(AuditableAction.FileTransformer_ExportDescription, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("descriptionModel", descriptionModel),
new AbstractMap.SimpleEntry<String, Object>("format", format)
));
return model;
}
public DmpModel importFileToDmp(@RequestBody FileEnvelopeModel fileEnvelope) {
logger.debug(new MapLogEntry("importFileToDmp " + FileEnvelopeModel.class.getSimpleName()).And("fileEnvelope", fileEnvelope));
DmpModel model = fileTransformerExecutor.importDmp(fileEnvelope);
this.auditService.track(AuditableAction.FileTransformer_ImportFileToDmp, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("fileEnvelope", fileEnvelope)
));
return model;
}
public DescriptionModel importFileToDescription(@RequestBody FileEnvelopeModel fileEnvelope) {
logger.debug(new MapLogEntry("importFileToDescription " + FileEnvelopeModel.class.getSimpleName()).And("fileEnvelope", fileEnvelope));
DescriptionModel model = fileTransformerExecutor.importDescription(fileEnvelope);
this.auditService.track(AuditableAction.FileTransformer_ImportFileToDescription, Map.ofEntries(
new AbstractMap.SimpleEntry<String, Object>("importFileToDescription ", fileEnvelope)
));
return model;
}
public FileTransformerConfiguration getSupportedFormats() {
logger.debug(new MapLogEntry("getSupportedFormats"));
FileTransformerConfiguration model = fileTransformerExecutor.getConfiguration();
this.auditService.track(AuditableAction.FileTransformer_GetSupportedFormats);
return model;
}
}

View File

@ -0,0 +1,202 @@
package org.opencdmp.filetransformer.docx.web.controller.controllerhandler;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import gr.cite.tools.exception.*;
import gr.cite.tools.logging.LoggerService;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;
import org.springframework.web.context.request.WebRequest;
import java.text.MessageFormat;
import java.util.HashMap;
import java.util.Map;
@RestControllerAdvice
@ControllerAdvice
public class GlobalExceptionHandler {
private static final LoggerService logger = new LoggerService(LoggerFactory.getLogger(GlobalExceptionHandler.class));
private final ObjectMapper objectMapper;
public GlobalExceptionHandler() {
this.objectMapper = new ObjectMapper();
this.objectMapper.registerModule(new JavaTimeModule());
}
@ExceptionHandler(Exception.class)
public ResponseEntity<?> handleUnexpectedErrors(Exception exception, WebRequest request) throws Exception {
HandledException handled = this.handleException(exception, request);
this.log(handled.getLevel(), exception, MessageFormat.format("returning code {0} and payload {1}", handled.getStatusCode(), handled.getMessage()));
return new ResponseEntity<>(handled.getMessage(), handled.getStatusCode());
}
public String toJsonSafe(Object item) {
if (item == null) return null;
try {
return this.objectMapper.writeValueAsString(item);
} catch (Exception ex) {
return null;
}
}
public void log(System.Logger.Level level, Exception e, String message) {
if (level != null) {
switch (level) {
case TRACE:
logger.trace(message, e);
break;
case DEBUG:
logger.debug(message, e);
break;
case INFO:
logger.info(message, e);
break;
case WARNING:
logger.warn(message, e);
break;
case ERROR:
logger.error(message, e);
break;
default:
logger.error(e);
}
} else {
logger.error(e);
}
}
public HandledException handleException(Exception exception, WebRequest request) throws Exception {
HttpStatus statusCode;
Map<String, Object> result;
System.Logger.Level logLevel;
switch (exception){
case MyNotFoundException myNotFoundException -> {
logLevel = System.Logger.Level.DEBUG;
statusCode = HttpStatus.NOT_FOUND;
int code = myNotFoundException.getCode();
if (code > 0) {
result = Map.ofEntries(
Map.entry("code", code),
Map.entry("error", myNotFoundException.getMessage())
);
}
else {
result = Map.ofEntries(
Map.entry("error", myNotFoundException.getMessage())
);
}
}
case MyUnauthorizedException myUnauthorizedException -> {
logLevel = System.Logger.Level.DEBUG;
statusCode = HttpStatus.UNAUTHORIZED;
int code = myUnauthorizedException.getCode();
if (code > 0) {
result = Map.ofEntries(
Map.entry("code", code),
Map.entry("error", myUnauthorizedException.getMessage())
);
}
else {
result = Map.ofEntries(
Map.entry("error", myUnauthorizedException.getMessage())
);
}
}
case MyForbiddenException myForbiddenException -> {
logLevel = System.Logger.Level.DEBUG;
statusCode = HttpStatus.FORBIDDEN;
int code = myForbiddenException.getCode();
if (code > 0) {
result = Map.ofEntries(
Map.entry("code", code),
Map.entry("error", myForbiddenException.getMessage())
);
}
else {
result = Map.ofEntries(
Map.entry("error", myForbiddenException.getMessage())
);
}
}
case MyValidationException myValidationException -> {
logLevel = System.Logger.Level.DEBUG;
statusCode = HttpStatus.BAD_REQUEST;
int code = myValidationException.getCode();
result = new HashMap<>();
if (code > 0) result.put("code", code);
if (myValidationException.getMessage() != null) result.put("error", myValidationException.getMessage());
if (myValidationException.getErrors() != null) result.put("message", myValidationException.getErrors());
}
case MyApplicationException myApplicationException -> {
logLevel = System.Logger.Level.ERROR;
statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
int code = myApplicationException.getCode();
if (code > 0) {
result = Map.ofEntries(
Map.entry("code", code),
Map.entry("error", myApplicationException.getMessage())
);
}
else {
result = Map.ofEntries(
Map.entry("error", myApplicationException.getMessage())
);
}
}
default -> {
logLevel = System.Logger.Level.ERROR;
statusCode = HttpStatus.INTERNAL_SERVER_ERROR;
result = Map.ofEntries(
Map.entry("error", "System error")
);
}
}
String serialization = this.toJsonSafe(result);
return new HandledException(statusCode, serialization, logLevel);
}
public static class HandledException{
public HttpStatus statusCode;
public String message;
public System.Logger.Level level;
public HandledException(HttpStatus statusCode, String message, System.Logger.Level level) {
this.statusCode = statusCode;
this.message = message;
this.level = level;
}
public HttpStatus getStatusCode() {
return statusCode;
}
public void setStatusCode(HttpStatus statusCode) {
this.statusCode = statusCode;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public System.Logger.Level getLevel() {
return level;
}
public void setLevel(System.Logger.Level level) {
this.level = level;
}
}
}

View File

@ -7,6 +7,8 @@ spring:
optional:classpath:config/storage.yml[.yml], optional:classpath:config/storage-${spring.profiles.active}.yml[.yml], optional:file:../config/storage-${spring.profiles.active}.yml[.yml],
optional:classpath:config/security.yml[.yml], optional:classpath:config/security-${spring.profiles.active}.yml[.yml], optional:file:../config/security-${spring.profiles.active}.yml[.yml],
optional:classpath:config/cache.yml[.yml], optional:classpath:config/cache-${spring.profiles.active}.yml[.yml], optional:file:../config/cache-${spring.profiles.active}.yml[.yml],
optional:classpath:config/logging.yml[.yml], optional:classpath:config/logging-${spring.profiles.active}.yml[.yml], optional:file:../config/logging-${spring.profiles.active}.yml[.yml],
optional:classpath:config/word-file-transformer.yml[.yml], optional:classpath:config/word-file-transformer-${spring.profiles.active}.yml[.yml], optional:file:../config/word-file-transformer-${spring.profiles.active}.yml[.yml],
optional:classpath:config/pdf.yml[.yml], optional:classpath:config/pdf-${spring.profiles.active}.yml[.yml], optional:file:../config/pdf-${spring.profiles.active}.yml[.yml]
optional:classpath:config/pdf.yml[.yml], optional:classpath:config/pdf-${spring.profiles.active}.yml[.yml], optional:file:../config/pdf-${spring.profiles.active}.yml[.yml],
optional:classpath:config/idpclaims.yml[.yml], optional:classpath:config/idpclaims-${spring.profiles.active}.yml[.yml], optional:file:../config/idpclaims-${spring.profiles.active}.yml[.yml]

View File

@ -0,0 +1,41 @@
idpclient:
claims:
mapping:
Subject:
- type: sub
Name:
- type: name
Client:
- type: client_id
AuthenticationMethod:
- type: amr
NotBefore:
- type: nbf
AuthenticatedAt:
- type: auth_time
ExpiresAt:
- type: exp
Email:
- type: email
Roles:
- type: resource_access
path: dmp_zenodo_bridge.roles
Scope:
- type: scope
AccessToken:
- type: x-access-token
visibility: SENSITIVE
IssuedAt:
- type: iat
Issuer:
- type: iss
Audience:
- type: aud
TokenType:
- type: typ
AuthorizedParty:
- type: azp
Authorities:
- type: authorities
ExternalProviderName:
- type: identity_provider

View File

@ -0,0 +1,36 @@
logging:
config: classpath:logging/logback-${spring.profiles.active}.xml
context:
request:
requestIdKey: req.id
requestRemoteHostKey: req.remoteHost
requestUriKey: req.requestURI
requestQueryStringKey: req.queryString
requestUrlKey : req.requestURL
requestMethodKey: req.method
requestUserAgentKey: req.userAgent
requestForwardedForKey: req.xForwardedFor
requestSchemeKey: req.scheme
requestRemoteAddressKey: req.remoteAddr
requestRemotePortKey: req.remotePort
requestRemoteUserKey: req.remoteUser
principal:
subjectKey: usr.subject
nameKey: usr.name
clientKey: usr.client
audit:
enable: true
requestRemoteHostKey: req.remoteHost
requestUriKey: req.requestURI
requestQueryStringKey: req.queryString
requestUrlKey : req.requestURL
requestMethodKey: req.method
requestUserAgentKey: req.userAgent
requestForwardedForKey: req.xForwardedFor
requestSchemeKey: req.scheme
requestRemoteAddressKey: req.remoteAddr
requestRemotePortKey: req.remotePort
requestRemoteUserKey: req.remoteUser
principalSubjectKey: usr.subject
principalNameKey: usr.name
principalClientKey: usr.client

View File

@ -0,0 +1,35 @@
logging:
context:
request:
requestIdKey: req.id
requestRemoteHostKey: req.remoteHost
requestUriKey: req.requestURI
requestQueryStringKey: req.queryString
requestUrlKey : req.requestURL
requestMethodKey: req.method
requestUserAgentKey: req.userAgent
requestForwardedForKey: req.xForwardedFor
requestSchemeKey: req.scheme
requestRemoteAddressKey: req.remoteAddr
requestRemotePortKey: req.remotePort
requestRemoteUserKey: req.remoteUser
principal:
subjectKey: usr.subject
nameKey: usr.name
clientKey: usr.client
audit:
enable: true
requestRemoteHostKey: req.remoteHost
requestUriKey: req.requestURI
requestQueryStringKey: req.queryString
requestUrlKey : req.requestURL
requestMethodKey: req.method
requestUserAgentKey: req.userAgent
requestForwardedForKey: req.xForwardedFor
requestSchemeKey: req.scheme
requestRemoteAddressKey: req.remoteAddr
requestRemotePortKey: req.remotePort
requestRemoteUserKey: req.remoteUser
principalSubjectKey: usr.subject
principalNameKey: usr.name
principalClientKey: usr.client

View File

@ -1,3 +1,4 @@
pdf:
converter:
url: ${PDF_CONVERTER_URL}
url: ${PDF_CONVERTER_URL}
maxInMemorySizeInBytes: 6554000

View File

@ -0,0 +1,62 @@
<configuration debug="true">
<include resource="org/springframework/boot/logging/logback/defaults.xml"/>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%date{ISO8601} [%thread] %-5level %logger{36} [%X{req.id}] - %message%n</Pattern>
</encoder>
</appender>
<appender name="TROUBLESHOOTING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/logging.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/logging.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>15</maxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%date{ISO8601} [%thread] %-5level %logger{36} [%X{req.id}] - %message%n</Pattern>
</encoder>
</appender>
<appender name="AUDITING" class="ch.qos.logback.core.rolling.RollingFileAppender">
<file>logs/auditing.log</file>
<rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
<fileNamePattern>logs/auditing.%d{yyyy-MM-dd}.%i.log</fileNamePattern>
<timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
<maxFileSize>100MB</maxFileSize>
</timeBasedFileNamingAndTriggeringPolicy>
<maxHistory>15</maxHistory>
</rollingPolicy>
<encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder">
<Pattern>%date{ISO8601} - %X{req.id} - %message%n</Pattern>
</encoder>
</appender>
<logger name="org.springframework.web" level="INFO" additivity="false">
<appender-ref ref="TROUBLESHOOTING"/>
<appender-ref ref="STDOUT"/>
</logger>
<logger name="org.hibernate" level="INFO" additivity="false">
<appender-ref ref="TROUBLESHOOTING"/>
<appender-ref ref="STDOUT"/>
</logger>
<logger name="gr.cite" level="DEBUG" additivity="false">
<appender-ref ref="TROUBLESHOOTING"/>
<appender-ref ref="STDOUT"/>
</logger>
<logger name="org.opencdmp" level="DEBUG" additivity="false">
<appender-ref ref="TROUBLESHOOTING"/>
<appender-ref ref="STDOUT"/>
</logger>
<logger name="audit" level="INFO" additivity="false">
<appender-ref ref="AUDITING"/>
<appender-ref ref="STDOUT"/>
</logger>
<root level="info">
<appender-ref ref="TROUBLESHOOTING"/>
<appender-ref ref="STDOUT"/>
</root>
</configuration>

View File

@ -0,0 +1,25 @@
validation.empty=Value cannot be empty
validation.hashempty=Hash must be set
validation.lowerthanmin=Value must be larger than {value}
validation.largerthanmax=Value must be less than {value}
validation.invalidid=Not valid id
General_ItemNotFound=Item {0} of type {1} not found
Validation_Required={0} is required
Validation_OverPosting=Too much info
Validation_MaxLength={0} too long
Validation_UnexpectedValue=Unexpected value in field {0}
Validation_Unique= {0} must be unique
Validation.LowerThanMin= value must be equal or larger than {0}
Validation.LessThenEqual= value {0} must be equal or less than {1}
Validation.LargerThenEqual= value {0} must be equal or larger than {1}
Validation.MissingFields= missing fields: {0}
Validation.InvalidDescriptionTemplateMultiplicity= {0} can not be used
Validation.InvalidDescriptionTemplateMultiplicityOnDMP= Description Templates has multiplicity errors
Validation_UrlRequired={0} is not valid url
SystemField_Title_Label=Title
SystemField_Description_Label=Description
SystemField_AccessRights_Label=Access
SystemField_Contact_Label=Contact
SystemField_User_Label=User
SystemField_Language_Label=Language

View File

@ -0,0 +1,18 @@
validation.empty=Value cannot be empty
validation.hashempty=Hash must be set
validation.lowerthanmin=Value must be larger than {value}
validation.largerthanmax=Value must be less than {value}
validation.invalidid=Not valid id
General_ItemNotFound=Item {0} of type {1} not found
Validation_Required={0} is required
Validation_OverPosting=Too much info
Validation_MaxLength={0} too long
Validation_UnexpectedValue=Unexpected value in field {0}
Validation_Unique= {0} must be unique
Validation.LowerThanMin= value must be equal or larger than {0}
Validation.LessThenEqual= value {0} must be equal or less than {1}
Validation.LargerThenEqual= value {0} must be equal or larger than {1}
Validation.MissingFields= missing fields: {0}
Validation.InvalidDescriptionTemplateMultiplicity= {0} can not be used
Validation.InvalidDescriptionTemplateMultiplicityOnDMP= Description Templates has multiplicity errors
Validation_UrlRequired={0} is not valid url