package edu.harvard.iq.dataverse.api;
import com.jayway.restassured.http.ContentType;
import com.jayway.restassured.path.json.JsonPath;
import java.io.File;
import java.io.IOException;
import com.jayway.restassured.response.Response;
import java.util.UUID;
import java.util.logging.Logger;
import javax.json.Json;
import javax.json.JsonArrayBuilder;
import javax.json.JsonObject;
import javax.json.JsonObjectBuilder;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import static com.jayway.restassured.RestAssured.given;
import com.jayway.restassured.path.xml.XmlPath;
import java.io.StringReader;
import java.io.StringWriter;
import javax.xml.transform.OutputKeys;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import static junit.framework.Assert.assertEquals;
import org.junit.Ignore;
public class BatchImportIT {
private static final Logger logger = Logger.getLogger(BatchImportIT.class.getCanonicalName());
private static final String builtinUserKey = "burrito";
private static final String keyString = "X-Dataverse-key";
private static String EMPTY_STRING = "";
private static final String idKey = "id";
private static final String apiTokenKey = "apiToken";
private static final String usernameKey = "userName";
private static final String emailKey = "email";
private static String username1;
private static String username2;
private static String apiToken1;
private static String apiToken2;
private static String dataverseAlias;
private static int datasetId;
private static String importDirectoryAndDataverseAliasMustMatch = "batchImportDv";
public BatchImportIT() {
}
@BeforeClass
public static void setUpClass() {
Response createUserResponse = createUser(getRandomUsername(), "firstName", "lastName");
// createUserResponse.prettyPrint();
assertEquals(200, createUserResponse.getStatusCode());
JsonPath createdUser1 = JsonPath.from(createUserResponse.body().asString());
apiToken1 = createdUser1.getString("data." + apiTokenKey);
username1 = createdUser1.getString("data.user." + usernameKey);
Response makeSuperuserResponse = makeSuperuser(username1);
assertEquals(200, makeSuperuserResponse.getStatusCode());
Response createUserResponse1 = createUser(getRandomUsername(), "firstName", "lastName");
// createUserResponse.prettyPrint();
assertEquals(200, createUserResponse1.getStatusCode());
JsonPath createdUser2 = JsonPath.from(createUserResponse1.body().asString());
apiToken2 = createdUser2.getString("data." + apiTokenKey);
username2 = createdUser2.getString("data.user." + usernameKey);
dataverseAlias = "dv" + getRandomIdentifier();
Response createDataverseResponse = createDataverse(dataverseAlias, apiToken1);
// createDataverseResponse.prettyPrint();
// assertEquals(201, createDataverseResponse.getStatusCode());
}
@AfterClass
public static void tearDownClass() {
boolean disabled = false;
if (disabled) {
return;
}
Response destroyDatasetResponse = destroyDataset(datasetId, apiToken1);
destroyDatasetResponse.prettyPrint();
// assertEquals(200, destroyDatasetResponse.getStatusCode());
Response deleteDataverseResponse = deleteDataverse(dataverseAlias, apiToken1);
// deleteDataverseResponse.prettyPrint();
// assertEquals(200, deleteDataverseResponse.getStatusCode());
Response deleteUser1Response = deleteUser(username1);
// deleteUser1Response.prettyPrint();
assertEquals(200, deleteUser1Response.getStatusCode());
Response deleteUser2Response = deleteUser(username2);
// deleteUser2Response.prettyPrint();
assertEquals(200, deleteUser2Response.getStatusCode());
}
@Before
public void setUp() {
}
@After
public void tearDown() {
}
@Test
public void roundTripDdi() throws Exception {
String directoryPath = "scripts/issues/907/" + importDirectoryAndDataverseAliasMustMatch;
String absoluteDirectoryPath = new File(directoryPath).getAbsolutePath();
String parentDataverse = dataverseAlias;
Response migrateResponse = migrate(absoluteDirectoryPath, parentDataverse, apiToken1);
// migrateResponse.prettyPrint();
Thread.sleep(500);
Response listDatasetsResponse = listDatasets(parentDataverse, apiToken1);
// listDatasetsResponse.prettyPrint();
XmlPath xmlPath = new XmlPath(listDatasetsResponse.body().asString());
String datasetUrlFromSword = xmlPath.getString("feed.entry[0].id");
if (datasetUrlFromSword != null && !datasetUrlFromSword.isEmpty()) {
String persistentIdentifier = datasetUrlFromSword.substring(68);
Response indexDatasetResponse = indexDataset(persistentIdentifier);
// indexDatasetResponse.prettyPrint();
datasetId = JsonPath.from(indexDatasetResponse.body().asString()).getInt("data.id");
Response datasetAsJsonResponse = getDatasetAsJson(datasetId, apiToken1);
// datasetAsJsonResponse.prettyPrint();
String title = JsonPath.from(datasetAsJsonResponse.body().asString()).getString("data.latestVersion.metadataBlocks.citation.fields[0].value");
String persistentUrl = JsonPath.from(datasetAsJsonResponse.body().asString()).getString("data.persistentUrl");
logger.info(title + " - " + persistentUrl);
boolean ddiFromDto = false;
Response datasetAsDdi = getDatasetAsDdi(persistentIdentifier, ddiFromDto, apiToken1);
String minimalDdiMethod = datasetAsDdi.prettyPrint();
ddiFromDto = true;
Response datasetAsDdiFromDto = getDatasetAsDdi(persistentIdentifier, ddiFromDto, apiToken1);
String fromDto = datasetAsDdiFromDto.prettyPrint();
/**
* Parity with the minimal DDI export is a step along the way. It
* demonstrates that we are producing valid DDI according to
* http://guides.dataverse.org/en/latest/developers/tools.html#msv
* but the next step will be producing a full DDI similar to what is
* being imported in this round trip test.
*/
boolean parityWithMinimalDdiExport = false;
if (parityWithMinimalDdiExport) {
assertEquals(minimalDdiMethod, fromDto);
}
// File originalFile = new File(absoluteDirectoryPath).listFiles()[0];
// String originalPretty = prettyFormat(new String(Files.readAllBytes(Paths.get(originalFile.getAbsolutePath()))));
// String exportedPretty = prettyFormat(datasetAsDdi.body().asString());
// logger.fine("original: " + originalPretty);
// logger.fine("exported: " + exportedPretty);
boolean doneWithDdiExportIssue2579 = false;
if (doneWithDdiExportIssue2579) {
/**
* @todo Implement DDI export
* https://github.com/IQSS/dataverse/issues/2579
*/
// assertEquals(exportedPretty, originalPretty);
}
} else {
boolean ddiFromDto = false;
Response datasetAsDdi = getDatasetAsDdi("junkDoi", ddiFromDto, apiToken1);
datasetAsDdi.prettyPrint();
assertEquals(404, datasetAsDdi.getStatusCode());
}
}
public static String prettyFormat(String input, int indent) {
try {
Source source = new StreamSource(new StringReader(input));
StringWriter stringWriter = new StringWriter();
StreamResult streamResult = new StreamResult(stringWriter);
TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
transformer.transform(source, streamResult);
return streamResult.getWriter().toString();
} catch (IllegalArgumentException | TransformerException ex) {
logger.fine("Exception while pretty printing XML: " + ex);
return null;
}
}
public static String prettyFormat(String input) {
return prettyFormat(input, 2);
}
@Test
public void ensureDdiExportIsSuperuserOnlyForNow() throws Exception {
boolean ddiFromDto = false;
Response datasetAsDdiNonSuperuser = getDatasetAsDdi("junkDoi", ddiFromDto, apiToken2);
// datasetAsDdiNonSuperuser.prettyPrint();
assertEquals(403, datasetAsDdiNonSuperuser.getStatusCode());
Response datasetAsDdiInvalidApiToken = getDatasetAsDdi("junkDoi", ddiFromDto, "junkToken");
// datasetAsDdiInvalidApiToken.prettyPrint();
assertEquals(403, datasetAsDdiInvalidApiToken.getStatusCode());
}
private Response migrate(String filename, String parentDataverse, String apiToken) throws IOException {
if (filename == null || filename.isEmpty()) {
throw new IOException("null or empty filename");
}
logger.info(parentDataverse + "dataverse targeted for import of " + filename);
Response response = given()
.contentType("application/atom+xml")
.get("/api/batch/migrate/?dv=" + parentDataverse + "&key=" + apiToken + "&path=" + filename + "&createDV=true");
return response;
}
private static Response createUser(String username, String firstName, String lastName) {
String userAsJson = getUserAsJsonString(username, firstName, lastName);
String password = getPassword(userAsJson);
Response response = given()
.body(userAsJson)
.contentType(ContentType.JSON)
.post("/api/builtin-users?key=" + builtinUserKey + "&password=" + password);
return response;
}
private static Response makeSuperuser(String userToMakeSuperuser) {
Response response = given().post("/api/admin/superuser/" + userToMakeSuperuser);
return response;
}
private static Response deleteUser(String username) {
Response deleteUserResponse = given()
.delete("/api/admin/authenticatedUsers/" + username + "/");
return deleteUserResponse;
}
private static Response createDataverse(String alias, String apiToken) {
JsonArrayBuilder contactArrayBuilder = Json.createArrayBuilder();
contactArrayBuilder.add(Json.createObjectBuilder().add("contactEmail", getEmailFromUserName(getRandomIdentifier())));
JsonArrayBuilder subjectArrayBuilder = Json.createArrayBuilder();
subjectArrayBuilder.add("Other");
JsonObject dvData = Json.createObjectBuilder()
.add("alias", alias)
.add("name", alias)
.add("dataverseContacts", contactArrayBuilder)
.add("dataverseSubjects", subjectArrayBuilder)
.build();
Response createDataverseResponse = given()
.body(dvData.toString()).contentType(ContentType.JSON)
.when().post("/api/dataverses/:root?key=" + apiToken);
return createDataverseResponse;
}
private static Response deleteDataverse(String doomed, String apiToken) {
return given().delete("/api/dataverses/" + doomed + "?key=" + apiToken);
}
private Response getSwordStatement(String persistentId, String apiToken) {
Response swordStatementResponse = given()
.auth().basic(apiToken, EMPTY_STRING)
.get("/dvn/api/data-deposit/v1.1/swordv2/statement/study/" + persistentId);
return swordStatementResponse;
}
private Response listDatasets(String dataverseAlias, String apiToken) {
Response swordStatementResponse = given()
.auth().basic(apiToken, EMPTY_STRING)
.get("/dvn/api/data-deposit/v1.1/swordv2/collection/dataverse/" + dataverseAlias);
return swordStatementResponse;
}
private Response indexDataset(String persistentIdentifier) {
Response response = given()
.get("/api/admin/index/dataset?persistentId=" + persistentIdentifier);
return response;
}
private Response getDatasetAsJson(int datasetId, String apiToken) {
Response response = given()
.header(keyString, apiToken)
.get("/api/datasets/" + datasetId);
return response;
}
private Response getDatasetAsDdi(String persistentIdentifier, boolean dto, String apiToken) {
Response response = given()
.header(keyString, apiToken)
.get("/api/datasets/ddi?persistentId=" + persistentIdentifier + "&dto=" + dto);
return response;
}
private static Response destroyDataset(Integer datasetId, String apiToken) {
return given()
.header(keyString, apiToken)
.delete("/api/datasets/" + datasetId + "/destroy");
}
private static String getRandomUsername() {
return "user" + getRandomIdentifier().substring(0, 8);
}
private static String getRandomIdentifier() {
return UUID.randomUUID().toString().substring(0, 8);
}
private static String getUserAsJsonString(String username, String firstName, String lastName) {
JsonObjectBuilder builder = Json.createObjectBuilder();
builder.add(usernameKey, username);
builder.add("firstName", firstName);
builder.add("lastName", lastName);
builder.add(emailKey, getEmailFromUserName(username));
String userAsJson = builder.build().toString();
logger.fine("User to create: " + userAsJson);
return userAsJson;
}
private static String getPassword(String jsonStr) {
String password = JsonPath.from(jsonStr).get(usernameKey);
return password;
}
private static String getEmailFromUserName(String username) {
return username + "@mailinator.com";
}
}