From df2d02a813152631b2f047422a9c94d72573b720 Mon Sep 17 00:00:00 2001
From: Martin Weise <martin.weise@tuwien.ac.at>
Date: Tue, 28 Sep 2021 18:18:06 +0200
Subject: [PATCH] =?UTF-8?q?added=20metadata=20functionality=C2=A7?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

---
 .../api/zenodo/deposit/AccessRightDto.java    |  18 +++
 .../api/zenodo/deposit/AccessTypeDto.java     |  20 ---
 .../{ContributorDto.java => CreatorDto.java}  |   8 +-
 .../deposit/DepositChangeRequestDto.java      |  14 ++
 ...Dto.java => DepositChangeResponseDto.java} |  15 +-
 .../zenodo/deposit/DepositResponseDto.java    |  62 ++++++++
 .../api/zenodo/deposit/ImageTypeDto.java      |  30 ++--
 .../api/zenodo/deposit/LicenseTypeDto.java    |  21 ++-
 .../api/zenodo/deposit/MetadataDto.java       |  27 ++++
 .../zenodo/deposit/PublicationTypeDto.java    |  84 ++++++----
 .../api/zenodo/deposit/UploadTypeDto.java     |  52 ++++---
 .../at/tuwien/endpoints/FileEndpoint.java     |  25 +++
 ...ionEndpoint.java => MetadataEndpoint.java} |  10 +-
 .../src/test/java/at/tuwien/BaseUnitTest.java |  59 +++++--
 .../java/at/tuwien/mapper/MapperUnitTest.java |  64 ++++++++
 .../MetadataServiceIntegrationTest.java       |  58 +++++++
 .../service/MetadataServiceUnitTest.java      | 147 ++++++++++++++++++
 .../service/ZenodoServiceIntegrationTest.java |  47 ------
 .../tuwien/service/ZenodoServiceUnitTest.java |  81 ----------
 .../src/test/resources/intercept.py           |  16 ++
 .../test/resources/zenodo-deposits-store.json |  29 ++++
 .../resources/zenodo-deposits-update.json     |  52 +++++++
 .../java/at/tuwien/config/ZenodoConfig.java   |   5 +-
 .../tuwien/exception/ZenodoApiException.java  |   2 +-
 .../exception/ZenodoNotFoundException.java    |  21 +++
 .../at/tuwien/service/CitationService.java    |  17 --
 .../java/at/tuwien/service/FileService.java   |   8 +
 .../at/tuwien/service/MetadataService.java    |  21 +++
 .../at/tuwien/service/ZenodoFileService.java  |   9 ++
 .../tuwien/service/ZenodoMetadataService.java |  88 +++++++++++
 .../java/at/tuwien/service/ZenodoService.java |  71 ---------
 31 files changed, 835 insertions(+), 346 deletions(-)
 create mode 100644 fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/AccessRightDto.java
 delete mode 100644 fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/AccessTypeDto.java
 rename fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/{ContributorDto.java => CreatorDto.java} (64%)
 create mode 100644 fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/DepositChangeRequestDto.java
 rename fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/{DepositDto.java => DepositChangeResponseDto.java} (65%)
 create mode 100644 fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/DepositResponseDto.java
 create mode 100644 fda-citation-service/rest-service/src/main/java/at/tuwien/endpoints/FileEndpoint.java
 rename fda-citation-service/rest-service/src/main/java/at/tuwien/endpoints/{CitationEndpoint.java => MetadataEndpoint.java} (55%)
 create mode 100644 fda-citation-service/rest-service/src/test/java/at/tuwien/mapper/MapperUnitTest.java
 create mode 100644 fda-citation-service/rest-service/src/test/java/at/tuwien/service/MetadataServiceIntegrationTest.java
 create mode 100644 fda-citation-service/rest-service/src/test/java/at/tuwien/service/MetadataServiceUnitTest.java
 delete mode 100644 fda-citation-service/rest-service/src/test/java/at/tuwien/service/ZenodoServiceIntegrationTest.java
 delete mode 100644 fda-citation-service/rest-service/src/test/java/at/tuwien/service/ZenodoServiceUnitTest.java
 create mode 100755 fda-citation-service/rest-service/src/test/resources/intercept.py
 create mode 100644 fda-citation-service/rest-service/src/test/resources/zenodo-deposits-store.json
 create mode 100644 fda-citation-service/rest-service/src/test/resources/zenodo-deposits-update.json
 create mode 100644 fda-citation-service/services/src/main/java/at/tuwien/exception/ZenodoNotFoundException.java
 delete mode 100644 fda-citation-service/services/src/main/java/at/tuwien/service/CitationService.java
 create mode 100644 fda-citation-service/services/src/main/java/at/tuwien/service/FileService.java
 create mode 100644 fda-citation-service/services/src/main/java/at/tuwien/service/MetadataService.java
 create mode 100644 fda-citation-service/services/src/main/java/at/tuwien/service/ZenodoFileService.java
 create mode 100644 fda-citation-service/services/src/main/java/at/tuwien/service/ZenodoMetadataService.java
 delete mode 100644 fda-citation-service/services/src/main/java/at/tuwien/service/ZenodoService.java

diff --git a/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/AccessRightDto.java b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/AccessRightDto.java
new file mode 100644
index 0000000000..9f8d1b4f74
--- /dev/null
+++ b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/AccessRightDto.java
@@ -0,0 +1,18 @@
+package at.tuwien.api.zenodo.deposit;
+
+import com.fasterxml.jackson.annotation.JsonProperty;
+
+public enum AccessRightDto {
+
+    @JsonProperty("open")
+    OPEN,
+
+    @JsonProperty("embargoed")
+    EMBARGOED,
+
+    @JsonProperty("restricted")
+    RESTRICTED,
+
+    @JsonProperty("closed")
+    CLOSED;
+}
diff --git a/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/AccessTypeDto.java b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/AccessTypeDto.java
deleted file mode 100644
index d35b07377d..0000000000
--- a/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/AccessTypeDto.java
+++ /dev/null
@@ -1,20 +0,0 @@
-package at.tuwien.api.zenodo.deposit;
-
-public enum AccessTypeDto {
-
-    OPEN("open"),
-    EMBARGOED("embargoed"),
-    RESTRICTED("restricted"),
-    CLOSED("closed");
-
-    private final String type;
-
-    AccessTypeDto(final String type) {
-        this.type = type;
-    }
-
-    @Override
-    public String toString() {
-        return type;
-    }
-}
diff --git a/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/ContributorDto.java b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/CreatorDto.java
similarity index 64%
rename from fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/ContributorDto.java
rename to fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/CreatorDto.java
index de5aa9d21b..7c7f0738bd 100644
--- a/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/ContributorDto.java
+++ b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/CreatorDto.java
@@ -1,6 +1,6 @@
 package at.tuwien.api.zenodo.deposit;
 
-import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonInclude;
 import lombok.*;
 
 @Getter
@@ -8,11 +8,9 @@ import lombok.*;
 @Builder
 @NoArgsConstructor
 @AllArgsConstructor
-public class ContributorDto {
+@JsonInclude(JsonInclude.Include.NON_NULL)
+public class CreatorDto {
 
-    /**
-     * e.g. Rauber, Andreas
-     */
     private String name;
 
     private String affiliation;
diff --git a/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/DepositChangeRequestDto.java b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/DepositChangeRequestDto.java
new file mode 100644
index 0000000000..c7aa055d57
--- /dev/null
+++ b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/DepositChangeRequestDto.java
@@ -0,0 +1,14 @@
+package at.tuwien.api.zenodo.deposit;
+
+import lombok.*;
+
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class DepositChangeRequestDto {
+
+    private MetadataDto metadata;
+
+}
diff --git a/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/DepositDto.java b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/DepositChangeResponseDto.java
similarity index 65%
rename from fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/DepositDto.java
rename to fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/DepositChangeResponseDto.java
index fb1adb87ba..60318ef04e 100644
--- a/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/DepositDto.java
+++ b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/DepositChangeResponseDto.java
@@ -1,9 +1,11 @@
 package at.tuwien.api.zenodo.deposit;
 
 import at.tuwien.api.zenodo.files.FileDto;
+import com.fasterxml.jackson.annotation.JsonFormat;
 import com.fasterxml.jackson.annotation.JsonProperty;
 import lombok.*;
 
+import java.time.Instant;
 import java.util.List;
 
 @Getter
@@ -11,12 +13,13 @@ import java.util.List;
 @Builder
 @NoArgsConstructor
 @AllArgsConstructor
-/**
- * TODO add created, modified, embargodate with +00:00 timezone
- */
-public class DepositDto {
+public class DepositChangeResponseDto {
 
-    private String description;
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX")
+    private Instant created;
+
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSXXX")
+    private Instant modified;
 
     @JsonProperty("conceptrecid")
     private Long conceptRecId;
@@ -35,7 +38,7 @@ public class DepositDto {
     @JsonProperty("prereserve_doi")
     private Boolean prereserveDoi;
 
-    private ContributorDto[] contributors;
+    private CreatorDto[] contributors;
 
     private List<FileDto> files;
 
diff --git a/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/DepositResponseDto.java b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/DepositResponseDto.java
new file mode 100644
index 0000000000..dee78afe09
--- /dev/null
+++ b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/DepositResponseDto.java
@@ -0,0 +1,62 @@
+package at.tuwien.api.zenodo.deposit;
+
+import at.tuwien.api.zenodo.files.FileDto;
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonProperty;
+import lombok.*;
+
+import java.time.Instant;
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Getter
+@Setter
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class DepositResponseDto {
+
+    /**
+     * {@link Instant} without timezone seems broken
+     */
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS")
+    private LocalDateTime created;
+
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSS")
+    private LocalDateTime modified;
+
+    private String description;
+
+    @JsonProperty("conceptrecid")
+    private Long conceptRecId;
+
+    private Long owner;
+
+    @JsonProperty("access_conditions")
+    private String accessConditions;
+
+    private String doi;
+
+    private LinksDto links;
+
+    private MetadataDto metadata;
+
+    @JsonProperty("prereserve_doi")
+    private Boolean prereserveDoi;
+
+    private CreatorDto[] contributors;
+
+    private List<FileDto> files;
+
+    private Long id;
+
+    @JsonProperty("record_id")
+    private Long recordId;
+
+    private String state;
+
+    private Boolean submitted;
+
+    private String title;
+
+}
diff --git a/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/ImageTypeDto.java b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/ImageTypeDto.java
index fd2d74b3e6..5536e9ff89 100644
--- a/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/ImageTypeDto.java
+++ b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/ImageTypeDto.java
@@ -1,22 +1,24 @@
 package at.tuwien.api.zenodo.deposit;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
+
 public enum ImageTypeDto {
 
-    FIGURE("figure"),
-    PLOT("plot"),
-    DRAWING("drawing"),
-    DIAGRAM("diagram"),
-    PHOTO("photo"),
-    OTHER("other");
+    @JsonProperty("figure")
+    FIGURE,
+
+    @JsonProperty("plot")
+    PLOT,
+
+    @JsonProperty("drawing")
+    DRAWING,
 
-    private final String type;
+    @JsonProperty("diagram")
+    DIAGRAM,
 
-    ImageTypeDto(final String type) {
-        this.type = type;
-    }
+    @JsonProperty("photo")
+    PHOTO,
 
-    @Override
-    public String toString() {
-        return type;
-    }
+    @JsonProperty("other")
+    OTHER;
 }
diff --git a/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/LicenseTypeDto.java b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/LicenseTypeDto.java
index 9b5889065a..8f791d8bd0 100644
--- a/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/LicenseTypeDto.java
+++ b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/LicenseTypeDto.java
@@ -1,22 +1,21 @@
 package at.tuwien.api.zenodo.deposit;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
+
 /**
  * @apiNote https://sandbox.zenodo.org/api/licenses/
  */
 public enum LicenseTypeDto {
 
-    BSD("bsd-license"),
-    CC_NC("cc-nc"),
-    CC_BY("cc-by");
+    @JsonProperty("bsd-license")
+    BSD,
 
-    private final String type;
+    @JsonProperty("cc-nc")
+    CC_NC,
 
-    LicenseTypeDto(final String type) {
-        this.type = type;
-    }
+    @JsonProperty("cc-by")
+    CC_BY,
 
-    @Override
-    public String toString() {
-        return type;
-    }
+    @JsonProperty("CC0-1.0")
+    CC0_1_0;
 }
diff --git a/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/MetadataDto.java b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/MetadataDto.java
index 5ee5a8bb9c..0bf0a66300 100644
--- a/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/MetadataDto.java
+++ b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/MetadataDto.java
@@ -1,16 +1,43 @@
 package at.tuwien.api.zenodo.deposit;
 
+import com.fasterxml.jackson.annotation.JsonFormat;
+import com.fasterxml.jackson.annotation.JsonInclude;
 import com.fasterxml.jackson.annotation.JsonProperty;
+import com.fasterxml.jackson.annotation.JsonValue;
 import lombok.*;
 
+import java.time.Instant;
+import java.util.Date;
+
 @Getter
 @Setter
 @Builder
 @NoArgsConstructor
 @AllArgsConstructor
+@JsonInclude(JsonInclude.Include.NON_NULL)
 public class MetadataDto {
 
+    private String title;
+
+    @JsonProperty("upload_type")
+    private UploadTypeDto uploadType;
+
     @JsonProperty("prereserve_doi")
     private PreserveDoiDto prereserveDoi;
 
+    private String description;
+
+    private String doi;
+
+//    private LicenseTypeDto license;
+
+    @JsonProperty("publication_date")
+    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
+    private Date publicationDate;
+
+    @JsonProperty("access_right")
+    private AccessRightDto accessRight;
+
+    private CreatorDto[] creators;
+
 }
diff --git a/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/PublicationTypeDto.java b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/PublicationTypeDto.java
index 2585932bf9..958034c1c3 100644
--- a/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/PublicationTypeDto.java
+++ b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/PublicationTypeDto.java
@@ -1,34 +1,60 @@
 package at.tuwien.api.zenodo.deposit;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
+
 public enum PublicationTypeDto {
 
-    ANNOTATION_COLLECTION("annotationcollection"),
-    BOOK("book"),
-    SECTION("section"),
-    CONFERENCE_PAPER("conferencepaper"),
-    DATA_MANAGEMENT_PLAN("datamanagementplan"),
-    ARTICLE("article"),
-    PATENT("patent"),
-    PREPRINT("preprint"),
-    PROJECT_DELIVERABLE("deliverable"),
-    PROJECT_MILESTONE("milestone"),
-    PROPOSAL("proposal"),
-    REPORT("report"),
-    SOFTWARE_DOCUMENTATION("softwaredocumentation"),
-    TAXONOMIC_TREATMENT("taxonomictreatment"),
-    TECHNICAL_NOTE("technicalnote"),
-    THESIS("thesis"),
-    WORKING_PAPER("workingpaper"),
-    OTHER("other");
-
-    private final String type;
-
-    PublicationTypeDto(final String type) {
-        this.type = type;
-    }
-
-    @Override
-    public String toString() {
-        return type;
-    }
+    @JsonProperty("annotationcollection")
+    ANNOTATION_COLLECTION,
+
+    @JsonProperty("book")
+    BOOK,
+
+    @JsonProperty("section")
+    SECTION,
+
+    @JsonProperty("conferencepaper")
+    CONFERENCE_PAPER,
+
+    @JsonProperty("datamanagementplan")
+    DATA_MANAGEMENT_PLAN,
+
+    @JsonProperty("article")
+    ARTICLE,
+
+    @JsonProperty("patent")
+    PATENT,
+
+    @JsonProperty("preprint")
+    PREPRINT,
+
+    @JsonProperty("deliverable")
+    PROJECT_DELIVERABLE,
+
+    @JsonProperty("milestone")
+    PROJECT_MILESTONE,
+
+    @JsonProperty("proposal")
+    PROPOSAL,
+
+    @JsonProperty("report")
+    REPORT,
+
+    @JsonProperty("softwaredocumentation")
+    SOFTWARE_DOCUMENTATION,
+
+    @JsonProperty("taxonomictreatment")
+    TAXONOMIC_TREATMENT,
+
+    @JsonProperty("technicalnote")
+    TECHNICAL_NOTE,
+
+    @JsonProperty("thesis")
+    THESIS,
+
+    @JsonProperty("workingpaper")
+    WORKING_PAPER,
+
+    @JsonProperty("other")
+    OTHER;
 }
diff --git a/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/UploadTypeDto.java b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/UploadTypeDto.java
index 745ca4cf74..0089aaefff 100644
--- a/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/UploadTypeDto.java
+++ b/fda-citation-service/api/src/main/java/at/tuwien/api/zenodo/deposit/UploadTypeDto.java
@@ -1,26 +1,36 @@
 package at.tuwien.api.zenodo.deposit;
 
+import com.fasterxml.jackson.annotation.JsonProperty;
+
 public enum UploadTypeDto {
 
-    PUBLICATION("publication"),
-    POSTER("poster"),
-    PRESENTATION("presentation"),
-    DATASET("dataset"),
-    IMAGE("image"),
-    VIDEO("video"),
-    SOFTWARE("software"),
-    LESSON("lesson"),
-    PHYSICAL_OBJECT("physicalobject"),
-    OTHER("other");
-
-    private final String type;
-
-    UploadTypeDto(final String type) {
-        this.type = type;
-    }
-
-    @Override
-    public String toString() {
-        return type;
-    }
+    @JsonProperty("publication")
+    PUBLICATION,
+
+    @JsonProperty("poster")
+    POSTER,
+
+    @JsonProperty("presentation")
+    PRESENTATION,
+
+    @JsonProperty("dataset")
+    DATASET,
+
+    @JsonProperty("image")
+    IMAGE,
+
+    @JsonProperty("video")
+    VIDEO,
+
+    @JsonProperty("software")
+    SOFTWARE,
+
+    @JsonProperty("lesson")
+    LESSON,
+
+    @JsonProperty("physicalobject")
+    PHYSICAL_OBJECT,
+
+    @JsonProperty("other")
+    OTHER;
 }
diff --git a/fda-citation-service/rest-service/src/main/java/at/tuwien/endpoints/FileEndpoint.java b/fda-citation-service/rest-service/src/main/java/at/tuwien/endpoints/FileEndpoint.java
new file mode 100644
index 0000000000..d07c993b9e
--- /dev/null
+++ b/fda-citation-service/rest-service/src/main/java/at/tuwien/endpoints/FileEndpoint.java
@@ -0,0 +1,25 @@
+package at.tuwien.endpoints;
+
+import at.tuwien.service.MetadataService;
+import lombok.extern.log4j.Log4j2;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.CrossOrigin;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+@Log4j2
+@CrossOrigin(origins = "*")
+@RestController
+@RequestMapping("/api/database/{id}/table/{tableid}/file")
+public class FileEndpoint {
+
+    private final MetadataService citationService;
+
+    @Autowired
+    public FileEndpoint(MetadataService citationService) {
+        this.citationService = citationService;
+    }
+
+
+
+}
diff --git a/fda-citation-service/rest-service/src/main/java/at/tuwien/endpoints/CitationEndpoint.java b/fda-citation-service/rest-service/src/main/java/at/tuwien/endpoints/MetadataEndpoint.java
similarity index 55%
rename from fda-citation-service/rest-service/src/main/java/at/tuwien/endpoints/CitationEndpoint.java
rename to fda-citation-service/rest-service/src/main/java/at/tuwien/endpoints/MetadataEndpoint.java
index 2005192549..b19bb4c433 100644
--- a/fda-citation-service/rest-service/src/main/java/at/tuwien/endpoints/CitationEndpoint.java
+++ b/fda-citation-service/rest-service/src/main/java/at/tuwien/endpoints/MetadataEndpoint.java
@@ -1,6 +1,6 @@
 package at.tuwien.endpoints;
 
-import at.tuwien.service.CitationService;
+import at.tuwien.service.MetadataService;
 import lombok.extern.log4j.Log4j2;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
@@ -8,13 +8,13 @@ import org.springframework.web.bind.annotation.*;
 @Log4j2
 @CrossOrigin(origins = "*")
 @RestController
-@RequestMapping("/api/database/{id}/table/{tableid}/cite")
-public class CitationEndpoint {
+@RequestMapping("/api/database/{id}/table/{tableid}/metadata")
+public class MetadataEndpoint {
 
-    private final CitationService citationService;
+    private final MetadataService citationService;
 
     @Autowired
-    public CitationEndpoint(CitationService citationService) {
+    public MetadataEndpoint(MetadataService citationService) {
         this.citationService = citationService;
     }
 
diff --git a/fda-citation-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java b/fda-citation-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java
index 8cbca16dd2..8466f80fec 100644
--- a/fda-citation-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java
+++ b/fda-citation-service/rest-service/src/test/java/at/tuwien/BaseUnitTest.java
@@ -1,15 +1,12 @@
 package at.tuwien;
 
-import at.tuwien.api.zenodo.deposit.ContributorDto;
-import at.tuwien.api.zenodo.deposit.DepositDto;
-import at.tuwien.api.zenodo.deposit.LicenseTypeDto;
+import at.tuwien.api.zenodo.deposit.*;
 import at.tuwien.api.zenodo.files.FileDto;
 import at.tuwien.api.zenodo.files.FileLinksDto;
 import org.apache.commons.lang.RandomStringUtils;
 import org.springframework.test.context.TestPropertySource;
 
 import java.time.Instant;
-import java.time.LocalDateTime;
 import java.time.temporal.ChronoUnit;
 import java.util.List;
 
@@ -28,8 +25,17 @@ public abstract class BaseUnitTest {
     public final static Long DEPOSIT_1_CONCEPT_RECORD_ID = 143L;
     public final static Long DEPOSIT_1_OWNER = 144L;
 
-    public final static String CONTRIBUTOR_1_NAME = "von Goethe, Johann Wolfang";
-    public final static String CONTRIBUTOR_1_AFFILIATION = "Universität Leipzig";
+    public final static String METADATA_1_TITLE = "My super dataset";
+    public final static UploadTypeDto METADATA_1_UPLOAD_TYPE = UploadTypeDto.DATASET;
+    public final static String METADATA_1_DESCRIPTION = "The dataset contains 1000 records of ...";
+
+    public final static String CREATOR_1_NAME = "First1 Last1";
+    public final static String CREATOR_1_AFFIL = "TU Wien";
+    public final static String CREATOR_1_ORCID = "0000-0002-5713-0725";
+
+    public final static String CREATOR_2_NAME = "First2 Last2";
+    public final static String CREATOR_2_AFFIL = "TU Graz";
+    public final static String CREATOR_2_ORCID = "0000-0002-2606-4059";
 
     public final static Long DEPOSIT_2_ID = 2L;
     public final static String DEPOSIT_2_TITLE = "Test Document " + RandomStringUtils.randomAlphanumeric(10);
@@ -52,31 +58,56 @@ public abstract class BaseUnitTest {
     public final static String DEPOSIT_1_DOI = "10.5072/zenodo.542201";
     public final static Long DEPOSIT_1_REC_ID = 542201L;
 
-    public final static FileLinksDto FILE_1_LINKS_DTO = FileLinksDto.builder()
+    public final static CreatorDto CREATOR_1 = CreatorDto.builder()
+            .name(CREATOR_1_NAME)
+            .affiliation(CREATOR_1_AFFIL)
+            .orcid(CREATOR_1_ORCID)
+            .build();
+
+    public final static CreatorDto CREATOR_2 = CreatorDto.builder()
+            .name(CREATOR_2_NAME)
+            .affiliation(CREATOR_2_AFFIL)
+            .orcid(CREATOR_2_ORCID)
+            .build();
+
+    public final static MetadataDto METADATA_1 = MetadataDto.builder()
+            .creators(new CreatorDto[]{CREATOR_1, CREATOR_2})
+            .description(METADATA_1_DESCRIPTION)
+            .title(METADATA_1_TITLE)
+            .uploadType(METADATA_1_UPLOAD_TYPE)
+            .build();
+
+    public final static FileLinksDto FILE_1_LINKS = FileLinksDto.builder()
             .download(FILE_1_LINKS_DOWNLOAD)
             .self(FILE_1_LINKS_SELF)
             .build();
 
-    public final static FileDto FILE_1_DTO = FileDto.builder()
+    public final static FileDto FILE_1 = FileDto.builder()
             .checksum(FILE_1_CHECKSUM)
             .filename(FILE_1_NAME)
             .id(FILE_1_ID)
             .filesize(FILE_1_SIZE)
-            .links(FILE_1_LINKS_DTO)
+            .links(FILE_1_LINKS)
             .build();
 
-    public final static DepositDto DEPOSIT_1_RETURN_DTO = DepositDto.builder()
+    public final static DepositChangeResponseDto DEPOSIT_1 = DepositChangeResponseDto.builder()
             .id(DEPOSIT_1_ID)
+            .created(DEPOSIT_1_CREATED)
+            .modified(DEPOSIT_1_MODIFIED)
             .title(DEPOSIT_1_TITLE)
             .state(DEPOSIT_1_STATE)
             .submitted(DEPOSIT_1_SUBMITTED)
             .recordId(DEPOSIT_1_RECORD_ID)
-            .files(List.of(FILE_1_DTO))
+            .files(List.of(FILE_1))
             .build();
 
-    public final static ContributorDto CONTRIBUTOR_1_DTO = ContributorDto.builder()
-            .name(CONTRIBUTOR_1_NAME)
-            .affiliation(CONTRIBUTOR_1_AFFILIATION)
+    public final static DepositResponseDto DEPOSIT_2 = DepositResponseDto.builder()
+            .id(DEPOSIT_1_ID)
+            .title(DEPOSIT_1_TITLE)
+            .state(DEPOSIT_1_STATE)
+            .submitted(DEPOSIT_1_SUBMITTED)
+            .recordId(DEPOSIT_1_RECORD_ID)
+            .files(List.of(FILE_1))
             .build();
 
 }
diff --git a/fda-citation-service/rest-service/src/test/java/at/tuwien/mapper/MapperUnitTest.java b/fda-citation-service/rest-service/src/test/java/at/tuwien/mapper/MapperUnitTest.java
new file mode 100644
index 0000000000..f35c430a53
--- /dev/null
+++ b/fda-citation-service/rest-service/src/test/java/at/tuwien/mapper/MapperUnitTest.java
@@ -0,0 +1,64 @@
+package at.tuwien.mapper;
+
+import at.tuwien.BaseUnitTest;
+import at.tuwien.api.zenodo.deposit.DepositChangeResponseDto;
+import at.tuwien.api.zenodo.deposit.DepositResponseDto;
+import at.tuwien.config.ReadyConfig;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import org.apache.commons.io.FileUtils;
+import org.junit.jupiter.api.Test;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.util.ResourceUtils;
+
+import java.io.IOException;
+import java.net.URI;
+import java.net.URISyntaxException;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+
+@SpringBootTest
+public class MapperUnitTest extends BaseUnitTest {
+
+    @MockBean
+    private ReadyConfig readyConfig;
+
+    @Autowired
+    private ObjectMapper objectMapper;
+
+    @Test
+    public void listDeposits_success() throws IOException {
+        final String json = FileUtils.readFileToString(ResourceUtils.getFile("classpath:zenodo-deposits-list.json"));
+
+        /* test */
+        final DepositResponseDto[] response = objectMapper.readValue(json, DepositResponseDto[].class);
+        assertEquals(10, response.length);
+    }
+
+    @Test
+    public void storeDeposits_success() throws IOException, URISyntaxException {
+        final String json = FileUtils.readFileToString(ResourceUtils.getFile("classpath:zenodo-deposits-store.json"));
+
+        /* test */
+        final DepositChangeResponseDto response = objectMapper.readValue(json, DepositChangeResponseDto.class);
+        assertEquals(926290, response.getConceptRecId());
+        assertEquals(0, response.getFiles().size());
+        assertEquals(926291, response.getId());
+        assertEquals(new URI("https://sandbox.zenodo.org/api/files/dbea7621-8308-45af-b6af-9e12394dcc1b"), response.getLinks().getBucket());
+        assertEquals(new URI("https://sandbox.zenodo.org/deposit/926291"), response.getLinks().getHtml());
+        assertEquals(new URI("https://sandbox.zenodo.org/api/deposit/depositions/926291/actions/discard"), response.getLinks().getDiscard());
+        assertEquals(new URI("https://sandbox.zenodo.org/api/deposit/depositions/926291/actions/edit"), response.getLinks().getEdit());
+        assertEquals(new URI("https://sandbox.zenodo.org/api/deposit/depositions/926291/files"), response.getLinks().getFiles());
+        assertEquals(new URI("https://sandbox.zenodo.org/api/deposit/depositions/926291/actions/publish"), response.getLinks().getPublish());
+        assertEquals(new URI("https://sandbox.zenodo.org/api/deposit/depositions/926291"), response.getLinks().getSelf());
+        assertEquals("10.5072/zenodo.926291", response.getMetadata().getPrereserveDoi().getDoi());
+        assertEquals(93513L, response.getOwner());
+        assertEquals(926291L, response.getRecordId());
+        assertEquals("unsubmitted", response.getState());
+        assertEquals(false, response.getSubmitted());
+        assertEquals("", response.getTitle());
+    }
+
+
+}
\ No newline at end of file
diff --git a/fda-citation-service/rest-service/src/test/java/at/tuwien/service/MetadataServiceIntegrationTest.java b/fda-citation-service/rest-service/src/test/java/at/tuwien/service/MetadataServiceIntegrationTest.java
new file mode 100644
index 0000000000..2882b21eee
--- /dev/null
+++ b/fda-citation-service/rest-service/src/test/java/at/tuwien/service/MetadataServiceIntegrationTest.java
@@ -0,0 +1,58 @@
+package at.tuwien.service;
+
+import at.tuwien.BaseUnitTest;
+import at.tuwien.api.zenodo.deposit.*;
+import at.tuwien.config.ReadyConfig;
+import at.tuwien.exception.ZenodoApiException;
+import at.tuwien.exception.ZenodoAuthenticationException;
+import at.tuwien.exception.ZenodoNotFoundException;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+
+@SpringBootTest
+@ExtendWith(SpringExtension.class)
+public class MetadataServiceIntegrationTest extends BaseUnitTest {
+
+    @MockBean
+    private ReadyConfig readyConfig;
+
+    @Autowired
+    private ZenodoMetadataService zenodoService;
+
+    @Test
+    public void listDeposit_succeeds() throws ZenodoApiException, ZenodoAuthenticationException {
+
+        /* test */
+        zenodoService.listCitations();
+    }
+
+    @Test
+    public void createDeposit_succeeds() throws ZenodoApiException, ZenodoAuthenticationException {
+
+        /* test */
+        final DepositChangeResponseDto response = zenodoService.storeCitation();
+        Assertions.assertNotNull(response.getId());
+    }
+
+    @Test
+    public void updateDeposit_succeeds() throws ZenodoApiException, ZenodoAuthenticationException,
+            ZenodoNotFoundException {
+        final DepositChangeRequestDto request = DepositChangeRequestDto.builder()
+                .metadata(METADATA_1)
+               .build();
+        final DepositChangeResponseDto response = zenodoService.storeCitation();
+
+        /* test */
+        final DepositChangeResponseDto response2 = zenodoService.updateCitation(response.getId(), request);
+        Assertions.assertNotNull(response2.getId());
+        Assertions.assertEquals(METADATA_1_TITLE, response2.getTitle());
+        Assertions.assertEquals(METADATA_1_TITLE, response2.getMetadata().getTitle());
+        Assertions.assertEquals(METADATA_1_DESCRIPTION, response2.getMetadata().getDescription());
+    }
+
+}
\ No newline at end of file
diff --git a/fda-citation-service/rest-service/src/test/java/at/tuwien/service/MetadataServiceUnitTest.java b/fda-citation-service/rest-service/src/test/java/at/tuwien/service/MetadataServiceUnitTest.java
new file mode 100644
index 0000000000..a9c65f173e
--- /dev/null
+++ b/fda-citation-service/rest-service/src/test/java/at/tuwien/service/MetadataServiceUnitTest.java
@@ -0,0 +1,147 @@
+package at.tuwien.service;
+
+import at.tuwien.BaseUnitTest;
+import at.tuwien.api.zenodo.deposit.DepositChangeResponseDto;
+import at.tuwien.api.zenodo.deposit.DepositResponseDto;
+import at.tuwien.api.zenodo.deposit.DepositChangeRequestDto;
+import at.tuwien.api.zenodo.deposit.MetadataDto;
+import at.tuwien.config.ReadyConfig;
+import at.tuwien.exception.ZenodoApiException;
+import at.tuwien.exception.ZenodoAuthenticationException;
+import at.tuwien.exception.ZenodoNotFoundException;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtendWith;
+import org.mockito.Mockito;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.boot.test.mock.mockito.MockBean;
+import org.springframework.http.HttpEntity;
+import org.springframework.http.HttpMethod;
+import org.springframework.http.HttpStatus;
+import org.springframework.http.ResponseEntity;
+import org.springframework.test.context.junit.jupiter.SpringExtension;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.List;
+
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+import static org.mockito.ArgumentMatchers.anyString;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.*;
+
+@SpringBootTest
+@ExtendWith(SpringExtension.class)
+public class MetadataServiceUnitTest extends BaseUnitTest {
+
+    @MockBean
+    private ReadyConfig readyConfig;
+
+    @Autowired
+    private ZenodoMetadataService zenodoService;
+
+    @MockBean
+    private RestTemplate zenodoTemplate;
+
+    @Test
+    public void listCitations_succeeds() throws ZenodoApiException, ZenodoAuthenticationException {
+        when(zenodoTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(null), eq(DepositResponseDto[].class), anyString()))
+                .thenReturn(ResponseEntity.ok(new DepositResponseDto[]{DEPOSIT_2}));
+
+        /* test */
+        final List<DepositResponseDto> response = zenodoService.listCitations();
+        assertEquals(1, response.size());
+    }
+
+    @Test
+    public void listCitations_empty_fails() {
+        when(zenodoTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(null), eq(DepositResponseDto[].class), anyString()))
+                .thenReturn(ResponseEntity.ok().build());
+
+        /* test */
+        assertThrows(ZenodoApiException.class, () -> {
+            zenodoService.listCitations();
+        });
+    }
+
+    @Test
+    public void storeCitation_succeed() throws ZenodoApiException, ZenodoAuthenticationException {
+        when(zenodoTemplate.exchange(anyString(), eq(HttpMethod.POST), Mockito.<HttpEntity<String>>any(), eq(DepositChangeResponseDto.class), anyString()))
+                .thenReturn(ResponseEntity.status(HttpStatus.CREATED)
+                        .body(DEPOSIT_1));
+
+        /* test */
+        final DepositChangeResponseDto response = zenodoService.storeCitation();
+        assertEquals(DEPOSIT_1_CREATED, response.getCreated());
+        assertEquals(DEPOSIT_1_MODIFIED, response.getModified());
+    }
+
+    @Test
+    public void deleteCitation_succeeds() throws ZenodoApiException, ZenodoAuthenticationException {
+        when(zenodoTemplate.exchange(anyString(), eq(HttpMethod.DELETE), eq(null), eq(String.class), anyLong(), anyString()))
+                .thenReturn(ResponseEntity.status(HttpStatus.CREATED)
+                        .build());
+
+        /* test */
+        zenodoService.deleteCitation(DEPOSIT_1_ID);
+    }
+
+    @Test
+    public void deleteCitation_fails() {
+        when(zenodoTemplate.exchange(anyString(), eq(HttpMethod.DELETE), eq(null), eq(String.class), anyLong(), anyString()))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .build());
+
+        /* test */
+        assertThrows(ZenodoApiException.class, () -> {
+            zenodoService.deleteCitation(DEPOSIT_1_ID);
+        });
+    }
+
+    @Test
+    public void updateCitation_succeeds() throws ZenodoApiException, ZenodoAuthenticationException,
+            ZenodoNotFoundException {
+        final DepositChangeRequestDto request = DepositChangeRequestDto.builder()
+                .metadata(METADATA_1)
+                .build();
+        when(zenodoTemplate.exchange(anyString(), eq(HttpMethod.PUT), Mockito.<HttpEntity<DepositChangeRequestDto>>any(), eq(DepositChangeResponseDto.class), eq(DEPOSIT_1_ID), anyString()))
+                .thenReturn(ResponseEntity.status(HttpStatus.OK)
+                        .body(DEPOSIT_1));
+
+        /* test */
+        zenodoService.updateCitation(DEPOSIT_1_ID, request);
+    }
+
+    @Test
+    public void updateCitation_only1orcid_fails() {
+        final MetadataDto m = METADATA_1;
+        m.getCreators()[1].setOrcid(null);
+        final DepositChangeRequestDto request = DepositChangeRequestDto.builder()
+                .metadata(m)
+                .build();
+        when(zenodoTemplate.exchange(anyString(), eq(HttpMethod.PUT), Mockito.<HttpEntity<DepositChangeRequestDto>>any(), eq(DepositChangeResponseDto.class), eq(DEPOSIT_1_ID), anyString()))
+                .thenReturn(ResponseEntity.status(HttpStatus.BAD_REQUEST)
+                        .build());
+
+        /* test */
+        assertThrows(ZenodoNotFoundException.class, () -> {
+            zenodoService.updateCitation(DEPOSIT_1_ID, request);
+        });
+    }
+
+    @Test
+    public void updateCitation_notExists_fails() {
+        final DepositChangeRequestDto request = DepositChangeRequestDto.builder()
+                .metadata(METADATA_1)
+                .build();
+        when(zenodoTemplate.exchange(anyString(), eq(HttpMethod.PUT), Mockito.<HttpEntity<DepositChangeRequestDto>>any(), eq(DepositChangeResponseDto.class), eq(DEPOSIT_1_ID), anyString()))
+                .thenReturn(ResponseEntity.status(HttpStatus.BAD_REQUEST)
+                        .build());
+
+        /* test */
+        assertThrows(ZenodoNotFoundException.class, () -> {
+            zenodoService.updateCitation(DEPOSIT_1_ID, request);
+        });
+    }
+
+}
\ No newline at end of file
diff --git a/fda-citation-service/rest-service/src/test/java/at/tuwien/service/ZenodoServiceIntegrationTest.java b/fda-citation-service/rest-service/src/test/java/at/tuwien/service/ZenodoServiceIntegrationTest.java
deleted file mode 100644
index 23bc8d1eeb..0000000000
--- a/fda-citation-service/rest-service/src/test/java/at/tuwien/service/ZenodoServiceIntegrationTest.java
+++ /dev/null
@@ -1,47 +0,0 @@
-package at.tuwien.service;
-
-import at.tuwien.BaseUnitTest;
-import at.tuwien.api.zenodo.deposit.DepositDto;
-import at.tuwien.config.ReadyConfig;
-import at.tuwien.exception.ZenodoApiException;
-import at.tuwien.exception.ZenodoAuthenticationException;
-import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
-import org.springframework.web.client.RestTemplate;
-
-import java.util.List;
-
-@SpringBootTest
-@ExtendWith(SpringExtension.class)
-public class ZenodoServiceIntegrationTest extends BaseUnitTest {
-
-    @MockBean
-    private ReadyConfig readyConfig;
-
-    @Autowired
-    private ZenodoService zenodoService;
-
-    @Autowired
-    private RestTemplate zenodoTemplate;
-
-    @Test
-    public void listDeposit_succeeds() throws ZenodoApiException, ZenodoAuthenticationException {
-
-        /* test */
-        zenodoService.listCitations();
-    }
-
-    @Test
-    public void createDeposit_succeeds() throws ZenodoApiException, ZenodoAuthenticationException {
-
-        /* test */
-        final DepositDto response = zenodoService.storeCitation();
-        Assertions.assertNotNull(response.getId());
-    }
-
-}
\ No newline at end of file
diff --git a/fda-citation-service/rest-service/src/test/java/at/tuwien/service/ZenodoServiceUnitTest.java b/fda-citation-service/rest-service/src/test/java/at/tuwien/service/ZenodoServiceUnitTest.java
deleted file mode 100644
index dc667aaac0..0000000000
--- a/fda-citation-service/rest-service/src/test/java/at/tuwien/service/ZenodoServiceUnitTest.java
+++ /dev/null
@@ -1,81 +0,0 @@
-package at.tuwien.service;
-
-import at.tuwien.BaseUnitTest;
-import at.tuwien.api.zenodo.deposit.DepositDto;
-import at.tuwien.config.ReadyConfig;
-import at.tuwien.exception.ZenodoApiException;
-import at.tuwien.exception.ZenodoAuthenticationException;
-import org.junit.jupiter.api.Test;
-import org.junit.jupiter.api.extension.ExtendWith;
-import org.mockito.Mockito;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.boot.test.context.SpringBootTest;
-import org.springframework.boot.test.mock.mockito.MockBean;
-import org.springframework.http.HttpEntity;
-import org.springframework.http.HttpMethod;
-import org.springframework.http.HttpStatus;
-import org.springframework.http.ResponseEntity;
-import org.springframework.test.context.junit.jupiter.SpringExtension;
-import org.springframework.web.client.RestTemplate;
-
-import java.util.List;
-
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
-import static org.mockito.Mockito.*;
-
-@SpringBootTest
-@ExtendWith(SpringExtension.class)
-public class ZenodoServiceUnitTest extends BaseUnitTest {
-
-    @MockBean
-    private ReadyConfig readyConfig;
-
-    @Autowired
-    private ZenodoService zenodoService;
-
-    @MockBean
-    private RestTemplate zenodoTemplate;
-
-    @Test
-    public void listCitations_succeeds() throws ZenodoApiException, ZenodoAuthenticationException {
-        when(zenodoTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(null), eq(DepositDto[].class), anyString()))
-                .thenReturn(ResponseEntity.ok(new DepositDto[]{DEPOSIT_1_RETURN_DTO}));
-
-        /* test */
-        final List<DepositDto> response = zenodoService.listCitations();
-        assertEquals(1, response.size());
-    }
-
-    @Test
-    public void listCitations_empty_fails() {
-        when(zenodoTemplate.exchange(anyString(), eq(HttpMethod.GET), eq(null), eq(DepositDto[].class), anyString()))
-                .thenReturn(ResponseEntity.ok().build());
-
-        /* test */
-        assertThrows(ZenodoApiException.class, () -> {
-            zenodoService.listCitations();
-        });
-    }
-
-    @Test
-    public void storeCitation_succeed() throws ZenodoApiException, ZenodoAuthenticationException {
-        when(zenodoTemplate.exchange(anyString(), eq(HttpMethod.POST), Mockito.<HttpEntity<String>>any(), eq(DepositDto.class), anyString()))
-                .thenReturn(ResponseEntity.status(HttpStatus.CREATED)
-                        .body(DEPOSIT_1_RETURN_DTO));
-
-        /* test */
-        final DepositDto response = zenodoService.storeCitation();
-    }
-
-    @Test
-    public void deleteCitation_succeeds() {
-    }
-
-    @Test
-    public void deleteCitation_noId_fails() {
-    }
-
-}
\ No newline at end of file
diff --git a/fda-citation-service/rest-service/src/test/resources/intercept.py b/fda-citation-service/rest-service/src/test/resources/intercept.py
new file mode 100755
index 0000000000..d2d36630b3
--- /dev/null
+++ b/fda-citation-service/rest-service/src/test/resources/intercept.py
@@ -0,0 +1,16 @@
+#!/usr/bin/env python3
+import socket
+
+HOST = ''                 # Symbolic name meaning all available interfaces
+PORT = 50000              # Arbitrary non-privileged port
+s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+s.bind((HOST, PORT))
+s.listen(1)
+
+conn, addr = s.accept()
+print ('Connected by' + str(addr))
+while 1:
+  data = conn.recv(1024)
+  if not data: break
+  print("===> recv " + str(data))
+conn.close()
\ No newline at end of file
diff --git a/fda-citation-service/rest-service/src/test/resources/zenodo-deposits-store.json b/fda-citation-service/rest-service/src/test/resources/zenodo-deposits-store.json
new file mode 100644
index 0000000000..02d6717024
--- /dev/null
+++ b/fda-citation-service/rest-service/src/test/resources/zenodo-deposits-store.json
@@ -0,0 +1,29 @@
+{
+  "conceptrecid": "926290",
+  "created": "2021-09-28T13:56:35.790196+00:00",
+  "files": [],
+  "id": 926291,
+  "links": {
+    "bucket": "https://sandbox.zenodo.org/api/files/dbea7621-8308-45af-b6af-9e12394dcc1b",
+    "discard": "https://sandbox.zenodo.org/api/deposit/depositions/926291/actions/discard",
+    "edit": "https://sandbox.zenodo.org/api/deposit/depositions/926291/actions/edit",
+    "files": "https://sandbox.zenodo.org/api/deposit/depositions/926291/files",
+    "html": "https://sandbox.zenodo.org/deposit/926291",
+    "latest_draft": "https://sandbox.zenodo.org/api/deposit/depositions/926291",
+    "latest_draft_html": "https://sandbox.zenodo.org/deposit/926291",
+    "publish": "https://sandbox.zenodo.org/api/deposit/depositions/926291/actions/publish",
+    "self": "https://sandbox.zenodo.org/api/deposit/depositions/926291"
+  },
+  "metadata": {
+    "prereserve_doi": {
+      "doi": "10.5072/zenodo.926291",
+      "recid": 926291
+    }
+  },
+  "modified": "2021-09-28T13:56:35.790216+00:00",
+  "owner": 93513,
+  "record_id": 926291,
+  "state": "unsubmitted",
+  "submitted": false,
+  "title": ""
+}
\ No newline at end of file
diff --git a/fda-citation-service/rest-service/src/test/resources/zenodo-deposits-update.json b/fda-citation-service/rest-service/src/test/resources/zenodo-deposits-update.json
new file mode 100644
index 0000000000..29be08f9e5
--- /dev/null
+++ b/fda-citation-service/rest-service/src/test/resources/zenodo-deposits-update.json
@@ -0,0 +1,52 @@
+{
+  "conceptrecid": "926408",
+  "created": "2021-09-28T15:52:19.833120+00:00",
+  "doi": "",
+  "doi_url": "https://doi.org/",
+  "files": [],
+  "id": 926409,
+  "links": {
+    "bucket": "https://sandbox.zenodo.org/api/files/5e50707f-e9f2-4de7-aed1-28bd7ddcdff8",
+    "discard": "https://sandbox.zenodo.org/api/deposit/depositions/926409/actions/discard",
+    "edit": "https://sandbox.zenodo.org/api/deposit/depositions/926409/actions/edit",
+    "files": "https://sandbox.zenodo.org/api/deposit/depositions/926409/files",
+    "html": "https://sandbox.zenodo.org/deposit/926409",
+    "latest_draft": "https://sandbox.zenodo.org/api/deposit/depositions/926409",
+    "latest_draft_html": "https://sandbox.zenodo.org/deposit/926409",
+    "newversion": "https://sandbox.zenodo.org/api/deposit/depositions/926409/actions/newversion",
+    "publish": "https://sandbox.zenodo.org/api/deposit/depositions/926409/actions/publish",
+    "registerconceptdoi": "https://sandbox.zenodo.org/api/deposit/depositions/926409/actions/registerconceptdoi",
+    "self": "https://sandbox.zenodo.org/api/deposit/depositions/926409"
+  },
+  "metadata": {
+    "access_right": "open",
+    "creators": [
+      {
+        "affiliation": "TU Wien",
+        "name": "First1 Last1",
+        "orcid": "0000-0002-5713-0725"
+      },
+      {
+        "affiliation": "TU Graz",
+        "name": "First2 Last2",
+        "orcid": "0000-0002-2606-4059"
+      }
+    ],
+    "description": "The dataset contains 1000 records of ...",
+    "doi": "",
+    "license": "CC0-1.0",
+    "prereserve_doi": {
+      "doi": "10.5072/zenodo.926409",
+      "recid": 926409
+    },
+    "publication_date": "2021-09-28",
+    "title": "My super dataset",
+    "upload_type": "dataset"
+  },
+  "modified": "2021-09-28T15:52:20.135553+00:00",
+  "owner": 93513,
+  "record_id": 926409,
+  "state": "unsubmitted",
+  "submitted": false,
+  "title": "My super dataset"
+}
\ No newline at end of file
diff --git a/fda-citation-service/services/src/main/java/at/tuwien/config/ZenodoConfig.java b/fda-citation-service/services/src/main/java/at/tuwien/config/ZenodoConfig.java
index 799605475c..dc89fd5279 100644
--- a/fda-citation-service/services/src/main/java/at/tuwien/config/ZenodoConfig.java
+++ b/fda-citation-service/services/src/main/java/at/tuwien/config/ZenodoConfig.java
@@ -4,6 +4,7 @@ import at.tuwien.exception.ZenodoAuthenticationException;
 import at.tuwien.utils.ZenodoTemplateInterceptor;
 import com.fasterxml.jackson.databind.DeserializationFeature;
 import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.SerializationFeature;
 import com.fasterxml.jackson.datatype.jdk8.Jdk8Module;
 import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
 import lombok.Getter;
@@ -17,9 +18,7 @@ import org.springframework.web.util.DefaultUriBuilderFactory;
 import org.springframework.web.util.UriBuilderFactory;
 
 import javax.validation.constraints.NotNull;
-import java.time.ZoneId;
 import java.util.List;
-import java.util.TimeZone;
 
 @Log4j2
 @Configuration
@@ -46,8 +45,6 @@ public class ZenodoConfig {
     public ObjectMapper objectMapper() {
         return new ObjectMapper()
                 .findAndRegisterModules()
-                .disable(DeserializationFeature.ADJUST_DATES_TO_CONTEXT_TIME_ZONE)
-                .setTimeZone(TimeZone.getTimeZone(ZoneId.of("Europe/Vienna")))
                 .registerModule(new JavaTimeModule())
                 .registerModule(new Jdk8Module());
     }
diff --git a/fda-citation-service/services/src/main/java/at/tuwien/exception/ZenodoApiException.java b/fda-citation-service/services/src/main/java/at/tuwien/exception/ZenodoApiException.java
index 17f1b15d32..a2eaedfb5f 100644
--- a/fda-citation-service/services/src/main/java/at/tuwien/exception/ZenodoApiException.java
+++ b/fda-citation-service/services/src/main/java/at/tuwien/exception/ZenodoApiException.java
@@ -3,7 +3,7 @@ package at.tuwien.exception;
 import org.springframework.http.HttpStatus;
 import org.springframework.web.bind.annotation.ResponseStatus;
 
-@ResponseStatus(code = HttpStatus.FORBIDDEN)
+@ResponseStatus(code = HttpStatus.BAD_REQUEST)
 public class ZenodoApiException extends Exception {
 
     public ZenodoApiException(String msg) {
diff --git a/fda-citation-service/services/src/main/java/at/tuwien/exception/ZenodoNotFoundException.java b/fda-citation-service/services/src/main/java/at/tuwien/exception/ZenodoNotFoundException.java
new file mode 100644
index 0000000000..7795fbffd4
--- /dev/null
+++ b/fda-citation-service/services/src/main/java/at/tuwien/exception/ZenodoNotFoundException.java
@@ -0,0 +1,21 @@
+package at.tuwien.exception;
+
+import org.springframework.http.HttpStatus;
+import org.springframework.web.bind.annotation.ResponseStatus;
+
+@ResponseStatus(code = HttpStatus.NOT_FOUND)
+public class ZenodoNotFoundException extends Exception {
+
+    public ZenodoNotFoundException(String msg) {
+        super(msg);
+    }
+
+    public ZenodoNotFoundException(String msg, Throwable thr) {
+        super(msg, thr);
+    }
+
+    public ZenodoNotFoundException(Throwable thr) {
+        super(thr);
+    }
+
+}
diff --git a/fda-citation-service/services/src/main/java/at/tuwien/service/CitationService.java b/fda-citation-service/services/src/main/java/at/tuwien/service/CitationService.java
deleted file mode 100644
index a05302aa3e..0000000000
--- a/fda-citation-service/services/src/main/java/at/tuwien/service/CitationService.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package at.tuwien.service;
-
-import at.tuwien.api.zenodo.deposit.DepositDto;
-import at.tuwien.exception.ZenodoApiException;
-import at.tuwien.exception.ZenodoAuthenticationException;
-import org.springframework.stereotype.Service;
-
-import java.util.List;
-
-@Service
-public interface CitationService {
-    List<DepositDto> listCitations() throws ZenodoAuthenticationException, ZenodoApiException;
-
-    DepositDto storeCitation() throws ZenodoAuthenticationException, ZenodoApiException;
-
-    DepositDto deleteCitation(Long id) throws ZenodoAuthenticationException, ZenodoApiException;
-}
diff --git a/fda-citation-service/services/src/main/java/at/tuwien/service/FileService.java b/fda-citation-service/services/src/main/java/at/tuwien/service/FileService.java
new file mode 100644
index 0000000000..c88a53972b
--- /dev/null
+++ b/fda-citation-service/services/src/main/java/at/tuwien/service/FileService.java
@@ -0,0 +1,8 @@
+package at.tuwien.service;
+
+import org.springframework.stereotype.Service;
+
+@Service
+public interface FileService {
+
+}
diff --git a/fda-citation-service/services/src/main/java/at/tuwien/service/MetadataService.java b/fda-citation-service/services/src/main/java/at/tuwien/service/MetadataService.java
new file mode 100644
index 0000000000..b1102305cd
--- /dev/null
+++ b/fda-citation-service/services/src/main/java/at/tuwien/service/MetadataService.java
@@ -0,0 +1,21 @@
+package at.tuwien.service;
+
+import at.tuwien.api.zenodo.deposit.*;
+import at.tuwien.exception.ZenodoApiException;
+import at.tuwien.exception.ZenodoAuthenticationException;
+import at.tuwien.exception.ZenodoNotFoundException;
+import org.springframework.stereotype.Service;
+
+import java.util.List;
+
+@Service
+public interface MetadataService {
+    List<DepositResponseDto> listCitations() throws ZenodoAuthenticationException, ZenodoApiException;
+
+    DepositChangeResponseDto storeCitation() throws ZenodoAuthenticationException, ZenodoApiException;
+
+    DepositChangeResponseDto updateCitation(Long id, DepositChangeRequestDto data) throws ZenodoAuthenticationException,
+            ZenodoApiException, ZenodoNotFoundException;
+
+    void deleteCitation(Long id) throws ZenodoAuthenticationException, ZenodoApiException;
+}
diff --git a/fda-citation-service/services/src/main/java/at/tuwien/service/ZenodoFileService.java b/fda-citation-service/services/src/main/java/at/tuwien/service/ZenodoFileService.java
new file mode 100644
index 0000000000..c9653292a0
--- /dev/null
+++ b/fda-citation-service/services/src/main/java/at/tuwien/service/ZenodoFileService.java
@@ -0,0 +1,9 @@
+package at.tuwien.service;
+
+import org.springframework.stereotype.Service;
+
+@Service
+public class ZenodoFileService implements FileService {
+
+
+}
diff --git a/fda-citation-service/services/src/main/java/at/tuwien/service/ZenodoMetadataService.java b/fda-citation-service/services/src/main/java/at/tuwien/service/ZenodoMetadataService.java
new file mode 100644
index 0000000000..4b9c63d05d
--- /dev/null
+++ b/fda-citation-service/services/src/main/java/at/tuwien/service/ZenodoMetadataService.java
@@ -0,0 +1,88 @@
+package at.tuwien.service;
+
+import at.tuwien.api.zenodo.deposit.*;
+import at.tuwien.config.ZenodoConfig;
+import at.tuwien.exception.ZenodoApiException;
+import at.tuwien.exception.ZenodoAuthenticationException;
+import at.tuwien.exception.ZenodoNotFoundException;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.*;
+import org.springframework.stereotype.Service;
+import org.springframework.web.client.RestTemplate;
+
+import java.util.Arrays;
+import java.util.List;
+
+@Service
+public class ZenodoMetadataService implements MetadataService {
+
+    private final RestTemplate zenodoRestTemplate;
+    private final ZenodoConfig zenodoConfig;
+
+    @Autowired
+    public ZenodoMetadataService(RestTemplate zenodoRestTemplate, ZenodoConfig zenodoConfig) {
+        this.zenodoRestTemplate = zenodoRestTemplate;
+        this.zenodoConfig = zenodoConfig;
+    }
+
+    @Override
+    public List<DepositResponseDto> listCitations() throws ZenodoAuthenticationException, ZenodoApiException {
+        final ResponseEntity<DepositResponseDto[]> response = zenodoRestTemplate.exchange("/api/deposit/depositions?access_token={token}",
+                HttpMethod.GET, null, DepositResponseDto[].class, zenodoConfig.getApiKey());
+        if (response.getStatusCode().equals(HttpStatus.UNAUTHORIZED)) {
+            throw new ZenodoAuthenticationException("Token is missing or invalid.");
+        }
+        if (response.getBody() == null) {
+            throw new ZenodoApiException("Endpoint returned null body");
+        }
+        return Arrays.asList(response.getBody());
+    }
+
+    @Override
+    public DepositChangeResponseDto storeCitation() throws ZenodoAuthenticationException, ZenodoApiException {
+        final ResponseEntity<DepositChangeResponseDto> response = zenodoRestTemplate.exchange("/api/deposit/depositions?access_token={token}",
+                HttpMethod.POST, new HttpEntity<>("{}"), DepositChangeResponseDto.class, zenodoConfig.getApiKey());
+        if (response.getStatusCode().equals(HttpStatus.UNAUTHORIZED)) {
+            throw new ZenodoAuthenticationException("Token is missing or invalid.");
+        }
+        if (response.getStatusCode().equals(HttpStatus.BAD_REQUEST)) { // 400
+            throw new ZenodoApiException("Failed to store citation.");
+        }
+        if (response.getBody() == null) {
+            throw new ZenodoApiException("Endpoint returned null body");
+        }
+        return response.getBody();
+    }
+
+    @Override
+    public DepositChangeResponseDto updateCitation(Long id, DepositChangeRequestDto data) throws ZenodoAuthenticationException,
+            ZenodoApiException, ZenodoNotFoundException {
+        final ResponseEntity<DepositChangeResponseDto> response = zenodoRestTemplate.exchange("/api/deposit/depositions/{deposit_id}?access_token={token}",
+                HttpMethod.PUT, new HttpEntity<>(data), DepositChangeResponseDto.class, id, zenodoConfig.getApiKey());
+        if (response.getStatusCode().equals(HttpStatus.UNAUTHORIZED)) {
+            throw new ZenodoAuthenticationException("Token is missing or invalid.");
+        }
+        if (response.getStatusCode().equals(HttpStatus.BAD_REQUEST)) {
+            throw new ZenodoNotFoundException("Could not get the citation.");
+        }
+        if (!response.getStatusCode().equals(HttpStatus.OK)) {
+            throw new ZenodoAuthenticationException("Could not update the citation.");
+        }
+        if (response.getBody() == null) {
+            throw new ZenodoApiException("Endpoint returned null body");
+        }
+        return response.getBody();
+    }
+
+    @Override
+    public void deleteCitation(Long id) throws ZenodoAuthenticationException, ZenodoApiException {
+        final ResponseEntity<String> response = zenodoRestTemplate.exchange("/api/deposit/depositions/{deposit_id}?access_token={token}",
+                HttpMethod.DELETE, null, String.class, id, zenodoConfig.getApiKey());
+        if (response.getStatusCode().equals(HttpStatus.UNAUTHORIZED)) {
+            throw new ZenodoAuthenticationException("Token is missing or invalid.");
+        }
+        if (!response.getStatusCode().equals(HttpStatus.CREATED)) {
+            throw new ZenodoApiException("Could not delete the deposit");
+        }
+    }
+}
diff --git a/fda-citation-service/services/src/main/java/at/tuwien/service/ZenodoService.java b/fda-citation-service/services/src/main/java/at/tuwien/service/ZenodoService.java
deleted file mode 100644
index 8174b6b430..0000000000
--- a/fda-citation-service/services/src/main/java/at/tuwien/service/ZenodoService.java
+++ /dev/null
@@ -1,71 +0,0 @@
-package at.tuwien.service;
-
-import at.tuwien.api.zenodo.deposit.DepositDto;
-import at.tuwien.config.ZenodoConfig;
-import at.tuwien.exception.ZenodoApiException;
-import at.tuwien.exception.ZenodoAuthenticationException;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.http.*;
-import org.springframework.stereotype.Service;
-import org.springframework.web.client.RestTemplate;
-
-import java.util.Arrays;
-import java.util.List;
-
-@Service
-public class ZenodoService implements CitationService {
-
-    private final RestTemplate zenodoRestTemplate;
-    private final ZenodoConfig zenodoConfig;
-
-    @Autowired
-    public ZenodoService(RestTemplate zenodoRestTemplate, ZenodoConfig zenodoConfig) {
-        this.zenodoRestTemplate = zenodoRestTemplate;
-        this.zenodoConfig = zenodoConfig;
-    }
-
-    @Override
-    public List<DepositDto> listCitations() throws ZenodoAuthenticationException, ZenodoApiException {
-        final ResponseEntity<DepositDto[]> response = zenodoRestTemplate.exchange("/api/deposit/depositions?access_token={token}",
-                HttpMethod.GET, null, DepositDto[].class, zenodoConfig.getApiKey());
-        if (response.getStatusCode().equals(HttpStatus.UNAUTHORIZED)) {
-            throw new ZenodoAuthenticationException("Token is missing or invalid.");
-        }
-        if (response.getBody() == null) {
-            throw new ZenodoApiException("Endpoint returned null body");
-        }
-        return Arrays.asList(response.getBody());
-    }
-
-    @Override
-    public DepositDto storeCitation() throws ZenodoAuthenticationException, ZenodoApiException {
-        final ResponseEntity<DepositDto> response = zenodoRestTemplate.exchange("/api/deposit/depositions?access_token={token}",
-                HttpMethod.POST, new HttpEntity<>("{}"), DepositDto.class, zenodoConfig.getApiKey());
-        if (response.getStatusCode().equals(HttpStatus.UNAUTHORIZED)) {
-            throw new ZenodoAuthenticationException("Token is missing or invalid.");
-        }
-        if (response.getBody() == null) {
-            throw new ZenodoApiException("Endpoint returned null body");
-        }
-        if (response.getBody().getState().equals("error")) {
-            throw new ZenodoApiException("Status returned error or is unknown");
-        }
-        return response.getBody();
-    }
-
-    @Override
-    public DepositDto deleteCitation(Long id) throws ZenodoAuthenticationException, ZenodoApiException {
-        final ResponseEntity<DepositDto> response = zenodoRestTemplate.exchange("/api/deposit/depositions/{deposit_id}?access_token={token}",
-                HttpMethod.POST, null, DepositDto.class, id, zenodoConfig.getApiKey());
-        if (response.getStatusCode().equals(HttpStatus.UNAUTHORIZED)) {
-            throw new ZenodoAuthenticationException("Token is missing or invalid.");
-        }
-        if (response.getBody() == null) {
-            throw new ZenodoApiException("Endpoint returned null body");
-        }
-        if (response.getBody().getState().equals("error")) {
-            throw new ZenodoApiException("Status returned error or is unknown");
-        }
-        return response.getBody();
-    }
-}
-- 
GitLab