Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Native file upload #16 #23

Merged
merged 5 commits into from
Nov 27, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 6 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,10 @@
Significant changes since 0.1.0

1.1.0 In progress

- feature: Support upload of files to a dataset using native API. #16
- feature: After creating a Dataset, the persistent ID is stored in the Identifier object. #22

1.0.0 2022-11-21

Increasing major version due to major updates to dependencies. However, there are no
Expand All @@ -8,7 +13,7 @@ breaking API changes in this library.
- dependencies: Major dependency updates to Spring 5.3, Lombok 18.24.
- build: fix integration tests
- build: enable integration test running through Github actions
- build: test build and test on Java 8, 11, and 17
- build: test build and test on Java 8, 11, and 17.

0.2.0 2022-11-20

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,12 @@
import org.junit.Ignore;
import org.junit.Test;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URISyntaxException;
import java.util.Arrays;
import java.util.List;

import static com.researchspace.dataverse.entities.facade.DatasetTestFactory.createFacade;
Expand Down Expand Up @@ -59,7 +62,54 @@ public void testPostSampleDataset() throws IOException, InterruptedException, UR
String toPost = FileUtils.readFileToString(exampleDatasetJson);
Identifier datasetId = dataverseOps.createDataset(toPost, dataverseAlias);
assertNotNull(datasetId.getId());
}

@Test
public void uploadFileToDataSetWithNativeApiBytes() throws IOException, URISyntaxException {
//arrange
Identifier datasetId = createADataset();
assertNotNull(datasetId.getId());
FileUploadMetadata meta = getUploadMetadata();

//act
DatasetFileList datasetFileList = datasetOps.uploadNativeFile(new byte[]{1, 2, 3, 4, 5}, meta, datasetId, "myFileName.dat");

//assert
assertNotNull(datasetFileList);
assertEquals(1, datasetFileList.getFiles().size());
assertTrue(datasetFileList.getFiles().get(0).getCategories().contains("Data"));
assertTrue(datasetFileList.getFiles().get(0).getDescription().equals(("My description.")));
assertEquals(5 ,datasetFileList.getFiles().get(0).getDataFile().getFilesize());
}

@Test
public void uploadFileToDataSetWithNativeApiInputStream() throws IOException, URISyntaxException {
// arrange
Identifier datasetId = createADataset();
assertNotNull(datasetId.getId());
FileUploadMetadata meta = getUploadMetadata();

//act
DatasetFileList datasetFileList = datasetOps.uploadNativeFile(new ByteArrayInputStream(new byte[]{1, 2, 3, 4, 5,6}), 6, meta, datasetId, "myFileName.dat");

//assert
assertNotNull(datasetFileList);
assertEquals(1, datasetFileList.getFiles().size());
DatasetFile uploadedFile = datasetFileList.getFiles().get(0);
assertTrue(uploadedFile.getCategories().contains("Data"));
assertTrue(uploadedFile.getDescription().equals(("My description.")));
assertEquals(6 ,uploadedFile.getDataFile().getFilesize());
}

private Identifier createADataset() throws MalformedURLException, URISyntaxException {
DatasetFacade facade = createFacade();
Identifier datasetId = dataverseOps.createDataset(facade, dataverseAlias);
return datasetId;
}

private FileUploadMetadata getUploadMetadata() {
return FileUploadMetadata.builder().description("My description.").categories(Arrays.asList(new String[]{"Data"}))
.directoryLabel("test/x").build();
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,13 @@
*/
package com.researchspace.dataverse.api.v1;

import com.researchspace.dataverse.entities.*;
import com.researchspace.dataverse.entities.facade.DatasetFacade;
import com.researchspace.dataverse.http.FileUploadMetadata;

import java.io.File;
import java.io.InputStream;
import java.util.List;

import com.researchspace.dataverse.entities.DataSetMetadataBlock;
import com.researchspace.dataverse.entities.Dataset;
import com.researchspace.dataverse.entities.DatasetVersion;
import com.researchspace.dataverse.entities.DataverseResponse;
import com.researchspace.dataverse.entities.DvMessage;
import com.researchspace.dataverse.entities.Identifier;
import com.researchspace.dataverse.entities.PublishedDataset;
import com.researchspace.dataverse.entities.Version;
import com.researchspace.dataverse.entities.facade.DatasetFacade;
/**
<pre>
Copyright 2016 ResearchSpace
Expand Down Expand Up @@ -48,7 +42,6 @@ public interface DatasetOperations {
*/
DatasetVersion updateDataset(DatasetFacade facade, Identifier id);


/**
* Retrieves a {@link Dataset} based on its Id.
* @param dsIdentifier
Expand All @@ -64,6 +57,28 @@ public interface DatasetOperations {
List<DatasetVersion> getDatasetVersions(Identifier dsIdentifier);

/**
* Upload a file to a dataset using Dataverse's native API (not Sword)
* @param metadata Metadata to attach to the file upload
* @param dsIdentifier The persistent identifier of the dataset
* @param data bytes of data to upload
* @param fileName The name of the file to be created on Dataverse
* @return DatasetFileList information about the uploaded file.
*/
DatasetFileList uploadNativeFile( byte[] data, FileUploadMetadata metadata, Identifier dsIdentifier, String fileName);

/**
* Upload a file to a dataset using Dataverse's native API (not Sword).
* @param metadata Metadata to attach to the file upload
* @param contentLength The length of the stream
* @param dsIdentifier The persistent identifier of the dataset
* @param data bytes of data to upload
* @param fileName The name of the file to be created on Dataverse
* @return DatasetFileList information about the uploaded file.
*/
DatasetFileList uploadNativeFile(InputStream data, long contentLength, FileUploadMetadata metadata,
Identifier dsIdentifier, String fileName);

/**
* Uploads a file to a dataset
* @param doi The DOI of the Dataset
* @param file The file to add to the DataSet
Expand Down
14 changes: 14 additions & 0 deletions src/main/java/com/researchspace/dataverse/entities/Checksum.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.researchspace.dataverse.entities;

import com.researchspace.dataverse.http.FileUploadMetadata;
import lombok.Data;

/**
* Checksum is part of the response from
* {@link com.researchspace.dataverse.api.v1.DatasetOperations#uploadNativeFile(byte[], FileUploadMetadata, Identifier, String)}
*/
@Data
public class Checksum {
private String type;
private String value;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
package com.researchspace.dataverse.entities;

import com.researchspace.dataverse.http.FileUploadMetadata;
import lombok.Data;

import java.util.List;

/**
* DatasetFile is part of the response from
* {@link com.researchspace.dataverse.api.v1.DatasetOperations#uploadNativeFile(byte[], FileUploadMetadata, Identifier, String)}
*/
@Data
public class DatasetFile {
private String description;
private String label;
private String directoryLabel;
private String datasetVersionId;
private List<String> categories;
private boolean restricted;
private int version;
private DatasetFileDetails dataFile;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package com.researchspace.dataverse.entities;

import com.researchspace.dataverse.http.FileUploadMetadata;
import lombok.Data;

import java.util.Date;

/**
* DatasetFileDetails is a subsection of the response from
* {@link com.researchspace.dataverse.api.v1.DatasetOperations#uploadNativeFile(byte[], FileUploadMetadata, Identifier, String)}
*/
@Data
public class DatasetFileDetails {
private int id;
private int filesize;
private String persistentId;
private String pidURL;
private String filename;
private String contentType;
private String description;
private String storageIdentifier;
private String rootDataFileId;
private String md5;
private Checksum checksum;
private Date creationDate;
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.researchspace.dataverse.entities;

import lombok.Data;

import java.util.List;

/**
* DatasetFileList is the response from uploading a file using the native API
*/
@Data
public class DatasetFileList {
List<DatasetFile> files;
}

Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
*/
package com.researchspace.dataverse.entities;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import lombok.Data;
/**
* <pre>
Expand Down Expand Up @@ -30,6 +31,7 @@ public class DataverseResponse <T> {

private String status;
private T data;
@JsonDeserialize(using = ObjectOrStringMessageDeserializer.class )
private String message;

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.researchspace.dataverse.entities;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.JsonNode;

import java.io.IOException;

/**
* 'message' property can be a string or an object with property 'message'; this handles both
*/
public class ObjectOrStringMessageDeserializer extends JsonDeserializer<String> {
@Override
public String deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException {

JsonNode node = jp.getCodec().readTree((jp));
if (node.isTextual()){
return node.toString();
} else if (node.isObject()){
return node.get("message").toString();
} else{
throw new IllegalArgumentException("expect a string or an object with a string property 'message'");
}

}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,19 @@
*/
package com.researchspace.dataverse.http;

import java.util.Arrays;

import com.researchspace.dataverse.api.v1.DataverseConfig;
import com.researchspace.dataverse.entities.DataverseResponse;
import com.researchspace.springrest.ext.LoggingResponseErrorHandler;
import com.researchspace.springrest.ext.RestUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;

import com.researchspace.dataverse.api.v1.DataverseConfig;
import com.researchspace.dataverse.entities.DataverseResponse;
import com.researchspace.springrest.ext.LoggingResponseErrorHandler;
import com.researchspace.springrest.ext.RestUtil;

import lombok.extern.slf4j.Slf4j;
import java.util.Arrays;

/** <pre>
Copyright 2016 ResearchSpace
Expand Down Expand Up @@ -101,8 +99,12 @@ HttpHeaders addAPIKeyToHeader() {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.add(apiHeader, apiKey);
addApiKey(headers);
return headers;
}

void addApiKey(HttpHeaders headers) {
headers.add(apiHeader, apiKey);
}

}
Loading