diff --git a/.gitignore b/.gitignore
index 92322c4..2279178 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,2 +1,3 @@
.idea/
target/
+logs/
diff --git a/core/pom.xml b/core/pom.xml
index 38783d5..b57179d 100644
--- a/core/pom.xml
+++ b/core/pom.xml
@@ -50,6 +50,16 @@
jsoup
1.17.2
+
+ gr.cite
+ logging
+ 2.2.0
+
+
+ gr.cite
+ exceptions
+ 2.2.0
+
com.fasterxml.jackson.dataformat
jackson-dataformat-xml
diff --git a/core/src/main/java/org/opencdmp/filetransformer/docx/audit/AuditableAction.java b/core/src/main/java/org/opencdmp/filetransformer/docx/audit/AuditableAction.java
new file mode 100644
index 0000000..efeee57
--- /dev/null
+++ b/core/src/main/java/org/opencdmp/filetransformer/docx/audit/AuditableAction.java
@@ -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");
+
+
+}
diff --git a/core/src/main/java/org/opencdmp/filetransformer/docx/service/pid/PidServiceImpl.java b/core/src/main/java/org/opencdmp/filetransformer/docx/service/pid/PidServiceImpl.java
index e727173..e99ff25 100644
--- a/core/src/main/java/org/opencdmp/filetransformer/docx/service/pid/PidServiceImpl.java
+++ b/core/src/main/java/org/opencdmp/filetransformer/docx/service/pid/PidServiceImpl.java
@@ -1,6 +1,7 @@
package org.opencdmp.filetransformer.docx.service.pid;
import com.fasterxml.jackson.databind.ObjectMapper;
+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;
@@ -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 pidLinks = null;
diff --git a/core/src/main/java/org/opencdmp/filetransformer/docx/service/storage/FileStorageServiceImpl.java b/core/src/main/java/org/opencdmp/filetransformer/docx/service/storage/FileStorageServiceImpl.java
index 2aec273..a529d8a 100644
--- a/core/src/main/java/org/opencdmp/filetransformer/docx/service/storage/FileStorageServiceImpl.java
+++ b/core/src/main/java/org/opencdmp/filetransformer/docx/service/storage/FileStorageServiceImpl.java
@@ -1,5 +1,7 @@
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;
diff --git a/core/src/main/java/org/opencdmp/filetransformer/docx/service/wordfiletransformer/WordFileTransformerService.java b/core/src/main/java/org/opencdmp/filetransformer/docx/service/wordfiletransformer/WordFileTransformerService.java
index 3397244..e97bbe3 100644
--- a/core/src/main/java/org/opencdmp/filetransformer/docx/service/wordfiletransformer/WordFileTransformerService.java
+++ b/core/src/main/java/org/opencdmp/filetransformer/docx/service/wordfiletransformer/WordFileTransformerService.java
@@ -1,5 +1,8 @@
package org.opencdmp.filetransformer.docx.service.wordfiletransformer;
+import gr.cite.tools.exception.MyApplicationException;
+import gr.cite.tools.exception.MyApplicationException;
+import gr.cite.tools.logging.LoggerService;
import org.opencdmp.commonmodels.enums.DescriptionStatus;
import org.opencdmp.commonmodels.enums.DmpAccessType;
import org.opencdmp.commonmodels.enums.DmpBlueprintSystemFieldType;
@@ -42,7 +45,7 @@ import java.util.*;
@Component
@Scope(value = ConfigurableBeanFactory.SCOPE_PROTOTYPE)
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 FILE_FORMATS = List.of(
new FileFormat(FileFormats.PDF.getValue(), true, "fa-file-pdf-o"),
@@ -75,7 +78,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();
@@ -99,7 +102,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();
@@ -116,12 +119,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
@@ -149,11 +152,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())));
@@ -218,8 +221,8 @@ public class WordFileTransformerService implements FileTransformerClient {
}
private void buildSectionDescriptions(XWPFDocument document, List 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 descriptionTemplateModels = descriptions.stream().map(DescriptionModel::getDescriptionTemplate).toList();
if (descriptionTemplateModels.isEmpty()) return;
@@ -238,8 +241,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();
@@ -276,7 +279,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.
@@ -286,8 +289,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);
@@ -296,15 +299,15 @@ 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();
@@ -325,9 +328,9 @@ 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");
+ 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;
@@ -364,12 +367,12 @@ public class WordFileTransformerService implements FileTransformerClient {
case Language:
break;
default:
- throw new InvalidApplicationException("Invalid type " + systemField.getSystemFieldType());
+ throw new MyApplicationException("Invalid type " + systemField.getSystemFieldType());
}
}
private void buildDmpSectionExtraField(DmpModel dmpEntity, XWPFDocument document, ExtraFieldModel extraFieldModel) throws InvalidApplicationException {
- if (extraFieldModel == null) throw new IllegalArgumentException("ExtraFieldModel required");
+ if (extraFieldModel == null) throw new MyApplicationException("ExtraFieldModel required");
XWPFParagraph extraFieldParagraph = document.createParagraph();
extraFieldParagraph.setSpacingBetween(1.0);
XWPFRun runExtraFieldLabel = extraFieldParagraph.createRun();
@@ -390,13 +393,13 @@ public class WordFileTransformerService implements FileTransformerClient {
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 grants = this.getReferenceModelOfTypeCode(dmpModel, this.wordFileTransformerServiceProperties.getGrantReferenceCode(), null);
String fileName;
@@ -411,9 +414,9 @@ public class WordFileTransformerService implements FileTransformerClient {
}
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);
@@ -450,7 +453,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;
diff --git a/core/src/main/java/org/opencdmp/filetransformer/docx/service/wordfiletransformer/word/WordBuilderImpl.java b/core/src/main/java/org/opencdmp/filetransformer/docx/service/wordfiletransformer/word/WordBuilderImpl.java
index 5f18afd..267e156 100644
--- a/core/src/main/java/org/opencdmp/filetransformer/docx/service/wordfiletransformer/word/WordBuilderImpl.java
+++ b/core/src/main/java/org/opencdmp/filetransformer/docx/service/wordfiletransformer/word/WordBuilderImpl.java
@@ -1,5 +1,6 @@
package org.opencdmp.filetransformer.docx.service.wordfiletransformer.word;
+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;
@@ -273,6 +274,7 @@ public class WordBuilderImpl implements WordBuilder {
if (object instanceof BigInteger) return ((BigInteger) object).intValue();
return (int) object;
} catch (Exception e){
+ logger.error(e.getMessage(), e);
return 0;
}
}
@@ -465,50 +467,62 @@ public class WordBuilderImpl implements WordBuilder {
for (FieldModel field : tempFields) {
if (field.getIncludeInExport() && visibilityService.isVisible(field.getId(), propertyDefinitionFieldSetItemModel.getOrdinal())) {
if (!createListing) {
- try {
- 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;
+ 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.getFile(), mainDocumentPart, ParagraphStyle.IMAGE, numId, 0, numOfRows, numOfCells, 0);
+ if (paragraph != null) {
+ hasValue = true;
+ }
+ if (hasMultiplicityItems) {
+ hasMultiplicityItems = false;
}
}
- 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());
- }
+ }
+ } 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 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;
+ List 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(")");
}
- if (extractValues.size() > 1) extractValue = "• " + extractValue;
- if (hasMultiplicityItems) {
- XWPFParagraph paragraph = mainDocumentPart.getCell(mainDocumentPart.getTableCells().size()).addParagraph();
- paragraph.createRun().setText(extractValue);
+ 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);
@@ -517,26 +531,10 @@ public class WordBuilderImpl implements WordBuilder {
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++;
@@ -581,7 +579,6 @@ public class WordBuilderImpl implements WordBuilder {
for (FieldModel field : tempFields) {
if (field.getIncludeInExport() && visibilityService.isVisible(field.getId(), propertyDefinitionFieldSetItemModel.getOrdinal())) {
if (!createListing) {
- try {
org.opencdmp.commonmodels.models.description.FieldModel fieldValueModel = propertyDefinitionFieldSetItemModel.getFields().getOrDefault(field.getId(), null);
if (field.getData() != null) {
if (field.getData().getFieldType().equals(FieldType.UPLOAD)) {
@@ -684,9 +681,6 @@ public class WordBuilderImpl implements WordBuilder {
}
}
}
- } catch (InvalidApplicationException e) {
- throw new RuntimeException(e);
- }
}
}
}
@@ -757,7 +751,7 @@ public class WordBuilderImpl implements WordBuilder {
}
}
- private List extractValues(FieldModel field, org.opencdmp.commonmodels.models.description.FieldModel fieldValueModel) throws InvalidApplicationException {
+ private List extractValues(FieldModel field, org.opencdmp.commonmodels.models.description.FieldModel fieldValueModel) {
List values = new ArrayList<>();
if (fieldValueModel == null || field == null || field.getData() == null) {
return values;
@@ -834,7 +828,7 @@ public class WordBuilderImpl implements WordBuilder {
case INTERNAL_ENTRIES_DMPS:
break;
default:
- throw new InvalidApplicationException("Invalid type " + field.getData().getFieldType());
+ throw new MyApplicationException("Invalid type " + field.getData().getFieldType());
}
return values;
@@ -842,7 +836,7 @@ public class WordBuilderImpl implements WordBuilder {
@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()) {
@@ -874,8 +868,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;
@@ -1082,7 +1076,7 @@ public class WordBuilderImpl implements WordBuilder {
@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 licences = this.getReferenceModelOfTypeCode(dmpEntity, this.wordFileTransformerServiceProperties.getLicenceReferenceCode());
document.getFooterList().forEach(xwpfFooter -> {
diff --git a/pom.xml b/pom.xml
index 224a5a2..d63f4f0 100644
--- a/pom.xml
+++ b/pom.xml
@@ -37,6 +37,11 @@
commons-compress
1.26.1
+
+ gr.cite
+ logging
+ 2.2.0
+
diff --git a/web/pom.xml b/web/pom.xml
index 6c89d89..4d55b90 100644
--- a/web/pom.xml
+++ b/web/pom.xml
@@ -44,7 +44,12 @@
org.springframework.boot
spring-boot-starter-cache
-
+
+ gr.cite
+ exceptions
+ 2.2.0
+
+
diff --git a/web/src/main/java/org/opencdmp/filetransformer/docx/web/controller/FileTransformerController.java b/web/src/main/java/org/opencdmp/filetransformer/docx/web/controller/FileTransformerController.java
index 5e488eb..e6f3724 100644
--- a/web/src/main/java/org/opencdmp/filetransformer/docx/web/controller/FileTransformerController.java
+++ b/web/src/main/java/org/opencdmp/filetransformer/docx/web/controller/FileTransformerController.java
@@ -1,42 +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(WordFileTransformerService fileTransformerExecutor) {
+ 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 {
- return fileTransformerExecutor.exportDmp(dmpDepositModel, format);
+ 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("dmpDepositModel", dmpDepositModel),
+ new AbstractMap.SimpleEntry("format", format)
+ ));
+ return model;
}
public FileEnvelopeModel exportDescription(@RequestBody DescriptionModel descriptionModel, @RequestParam(value = "format",required = false)String format) throws Exception {
- return fileTransformerExecutor.exportDescription(descriptionModel, format);
+ 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("descriptionModel", descriptionModel),
+ new AbstractMap.SimpleEntry("format", format)
+ ));
+ return model;
}
public DmpModel importFileToDmp(@RequestBody FileEnvelopeModel fileEnvelope) {
- return fileTransformerExecutor.importDmp(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("fileEnvelope", fileEnvelope)
+ ));
+ return model;
}
public DescriptionModel importFileToDescription(@RequestBody FileEnvelopeModel fileEnvelope) {
- return fileTransformerExecutor.importDescription(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("importFileToDescription ", fileEnvelope)
+ ));
+ return model;
}
public FileTransformerConfiguration getSupportedFormats() {
- return fileTransformerExecutor.getConfiguration();
+ logger.debug(new MapLogEntry("getSupportedFormats"));
+
+ FileTransformerConfiguration model = fileTransformerExecutor.getConfiguration();
+
+ this.auditService.track(AuditableAction.FileTransformer_GetSupportedFormats);
+
+ return model;
}
}
diff --git a/web/src/main/java/org/opencdmp/filetransformer/docx/web/controller/controllerhandler/GlobalExceptionHandler.java b/web/src/main/java/org/opencdmp/filetransformer/docx/web/controller/controllerhandler/GlobalExceptionHandler.java
new file mode 100644
index 0000000..1441e2f
--- /dev/null
+++ b/web/src/main/java/org/opencdmp/filetransformer/docx/web/controller/controllerhandler/GlobalExceptionHandler.java
@@ -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 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;
+ }
+ }
+}
diff --git a/web/src/main/resources/config/application.yml b/web/src/main/resources/config/application.yml
index d7e494a..bbbe5fd 100644
--- a/web/src/main/resources/config/application.yml
+++ b/web/src/main/resources/config/application.yml
@@ -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]
diff --git a/web/src/main/resources/config/idpclaims.yml b/web/src/main/resources/config/idpclaims.yml
new file mode 100644
index 0000000..53bc069
--- /dev/null
+++ b/web/src/main/resources/config/idpclaims.yml
@@ -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
\ No newline at end of file
diff --git a/web/src/main/resources/config/logging-devel.yml b/web/src/main/resources/config/logging-devel.yml
new file mode 100644
index 0000000..59f65e4
--- /dev/null
+++ b/web/src/main/resources/config/logging-devel.yml
@@ -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
diff --git a/web/src/main/resources/config/logging.yml b/web/src/main/resources/config/logging.yml
new file mode 100644
index 0000000..56e152d
--- /dev/null
+++ b/web/src/main/resources/config/logging.yml
@@ -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
diff --git a/web/src/main/resources/logging/logback-devel.xml b/web/src/main/resources/logging/logback-devel.xml
new file mode 100644
index 0000000..b4d541f
--- /dev/null
+++ b/web/src/main/resources/logging/logback-devel.xml
@@ -0,0 +1,62 @@
+
+
+
+
+ %date{ISO8601} [%thread] %-5level %logger{36} [%X{req.id}] - %message%n
+
+
+
+
+ logs/logging.log
+
+ logs/logging.%d{yyyy-MM-dd}.%i.log
+
+ 100MB
+
+ 15
+
+
+ %date{ISO8601} [%thread] %-5level %logger{36} [%X{req.id}] - %message%n
+
+
+
+
+ logs/auditing.log
+
+ logs/auditing.%d{yyyy-MM-dd}.%i.log
+
+ 100MB
+
+ 15
+
+
+ %date{ISO8601} - %X{req.id} - %message%n
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file