diff --git a/doc/release-notes/8551-sword-license.md b/doc/release-notes/8551-sword-license.md
new file mode 100644
index 00000000000..90b7180ac77
--- /dev/null
+++ b/doc/release-notes/8551-sword-license.md
@@ -0,0 +1 @@
+As of Dataverse 5.10, "NONE" is no longer supported as a valid license when creating a dataset using the SWORD API. The API Guide has been updated to reflect this. Additionally, if you specify an invalid license, a list of available licenses will be returned in the response.
diff --git a/doc/sphinx-guides/source/api/sword-atom-entry.xml b/doc/sphinx-guides/source/api/sword-atom-entry.xml
index d47a3dd4f56..8d73653e93e 100755
--- a/doc/sphinx-guides/source/api/sword-atom-entry.xml
+++ b/doc/sphinx-guides/source/api/sword-atom-entry.xml
@@ -27,8 +27,8 @@
United States
Canada
- NONE
- Downloader will not use the Materials in any way prohibited by applicable laws.
+ CC0 1.0
+
Peets, J., & Stumptown, J. (2013). Roasting at Home. New England Journal of Coffee, 3(1), 22-34.
diff --git a/doc/sphinx-guides/source/api/sword.rst b/doc/sphinx-guides/source/api/sword.rst
index d853994f073..d4f56ddb5b4 100755
--- a/doc/sphinx-guides/source/api/sword.rst
+++ b/doc/sphinx-guides/source/api/sword.rst
@@ -65,6 +65,8 @@ Differences in Dataverse Software 4 from DVN 3.x lead to a few minor backward in
- The Service Document will show a single API Terms of Use rather than root level and Dataverse collection level Deposit Terms of Use.
+- As of Dataverse Software 5.10, ``NONE`` is no longer supported as a license.
+
New features as of v1.1
-----------------------
@@ -80,7 +82,7 @@ New features as of v1.1
- "Contributor" can now be populated and the "Type" (Editor, Funder, Researcher, etc.) can be specified with an XML attribute. For example: ``CaffeineForAll``
-- "License" can now be set with ``dcterms:license`` and the possible values are "CC0" and "NONE". "License" interacts with "Terms of Use" (``dcterms:rights``) in that if you include ``dcterms:rights`` in the XML, the license will be set to "NONE". If you don't include ``dcterms:rights``, the license will default to "CC0". It is invalid to specify "CC0" as a license and also include ``dcterms:rights``; an error will be returned. For backwards compatibility, ``dcterms:rights`` is allowed to be blank (i.e. ````) but blank values will not be persisted to the database and the license will be set to "NONE".
+- "License" can now be set with ``dcterms:license`` and the possible values determined by the installation ("CC0 1.0" and "CC BY 4.0" by default). "License" interacts with "Terms of Use" (``dcterms:rights``) in that if you include ``dcterms:rights`` in the XML and don't include ``dcterms:license``, the license will be "Custom Dataset Terms" and "Terms of Use" will be populated. If you don't include ``dcterms:rights``, the default license will be used. It is invalid to specify a license and also include ``dcterms:rights``; an error will be returned. For backwards compatibility, ``dcterms:rights`` is allowed to be blank (i.e. ````) but blank values will not be persisted to the database and the license will be set to "Custom Dataset Terms".
- "Contact E-mail" is automatically populated from dataset owner's email.
@@ -143,9 +145,9 @@ Dublin Core Terms (DC Terms) Qualified Mapping - Dataverse Project DB Element Cr
+-----------------------------+----------------------------------------------+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+
|dcterms:coverage | otherGeographicCoverage | | General information on the geographic coverage of the Dataset. |
+-----------------------------+----------------------------------------------+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+
-|dcterms:license | license | | Set the license to CC0 (default in a Dataverse installation for new Datasets), otherwise enter "NONE" and fill in the dcterms:rights field. |
+|dcterms:license | license | | Set the license. Alternatively, use the dcterms:rights field instead. |
+-----------------------------+----------------------------------------------+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+
-|dcterms:rights | termsofuse | | If not using CC0, enter any terms of use or restrictions for the Dataset. |
+|dcterms:rights | termsofuse | | If not using dcterms:license, enter any terms of use or restrictions for the Dataset. |
+-----------------------------+----------------------------------------------+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+
|dcterms:isReferencedBy | publicationCitation | | The publication (journal article, book, other work) that uses this dataset (include citation, permanent identifier (DOI), and permanent URL). |
+-----------------------------+----------------------------------------------+--------------+-------------------------------------------------------------------------------------------------------------------------------------------------------------+
diff --git a/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java
index 7e45381d410..46c38e04153 100644
--- a/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java
+++ b/src/main/java/edu/harvard/iq/dataverse/api/datadeposit/SwordServiceBean.java
@@ -12,6 +12,7 @@
import edu.harvard.iq.dataverse.license.License;
import edu.harvard.iq.dataverse.license.LicenseServiceBean;
import edu.harvard.iq.dataverse.util.BundleUtil;
+import java.util.ArrayList;
import java.util.List;
import java.util.Map;
@@ -186,7 +187,13 @@ public void setDatasetLicenseAndTermsOfUse(DatasetVersion datasetVersionToMutate
setTermsOfUse(datasetVersionToMutate, dcterms, null);
} else {
License licenseToSet = licenseServiceBean.getByNameOrUri(licenseProvided);
- if (licenseToSet == null) throw new SwordError("Couldn't find an active license with: " + licenseProvided);
+ if (licenseToSet == null || !licenseToSet.isActive()) {
+ List licenses = new ArrayList<>();
+ for (License license : licenseServiceBean.listAllActive()) {
+ licenses.add(license.getName());
+ }
+ throw new SwordError("Couldn't find an active license with: " + licenseProvided + ". Valid licenses: " + licenses);
+ }
terms.setLicense(licenseToSet);
setTermsOfUse(datasetVersionToMutate, dcterms, licenseToSet);
}
@@ -204,7 +211,7 @@ private void setTermsOfUse(DatasetVersion datasetVersionToMutate, Map 0) {
- throw new SwordError("Terms of Use (dcterms:rights) can not be specified in combination with a license. A Custom License can be used instead.");
+ throw new SwordError("Terms of Use (dcterms:rights) cannot be specified in combination with a license.");
}
} else {
if (numRightsProvided != 1) {
diff --git a/src/test/java/edu/harvard/iq/dataverse/api/SwordIT.java b/src/test/java/edu/harvard/iq/dataverse/api/SwordIT.java
index ea6709cb915..29173d3bd76 100644
--- a/src/test/java/edu/harvard/iq/dataverse/api/SwordIT.java
+++ b/src/test/java/edu/harvard/iq/dataverse/api/SwordIT.java
@@ -5,6 +5,9 @@
import com.jayway.restassured.response.Response;
import edu.harvard.iq.dataverse.GlobalId;
import edu.harvard.iq.dataverse.api.datadeposit.SwordConfigurationImpl;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Paths;
import java.util.List;
import java.util.Map;
@@ -195,6 +198,13 @@ public void testCreateDataverseCreateDatasetUploadFileDownloadFileEditTitle() {
String persistentId = UtilIT.getDatasetPersistentIdFromSwordResponse(createDatasetResponse);
logger.info("persistent id: " + persistentId);
+ Response getJson = UtilIT.nativeGetUsingPersistentId(persistentId, apiToken);
+ getJson.prettyPrint();
+ getJson.then().assertThat()
+ .statusCode(OK.getStatusCode())
+ .body("data.latestVersion.license.name", equalTo("CC0 1.0"))
+ .body("data.latestVersion.license.uri", equalTo("http://creativecommons.org/publicdomain/zero/1.0"));
+
Response atomEntryUnAuth = UtilIT.getSwordAtomEntry(persistentId, apiTokenNoPrivs);
atomEntryUnAuth.prettyPrint();
atomEntryUnAuth.then().assertThat()
@@ -638,6 +648,107 @@ public void testCreateDatasetPublishDestroy() {
}
+
+ @Test
+ public void testLicenses() {
+
+ Response createUser = UtilIT.createRandomUser();
+ String username = UtilIT.getUsernameFromResponse(createUser);
+ String apiToken = UtilIT.getApiTokenFromResponse(createUser);
+
+ Response createDataverse = UtilIT.createRandomDataverse(apiToken);
+ createDataverse.prettyPrint();
+ createDataverse.then().assertThat()
+ .statusCode(CREATED.getStatusCode());
+ String dataverseAlias = UtilIT.getAliasFromResponse(createDataverse);
+
+ String title = "License to Kill";
+ String description = "Spies in 1989";
+ String license = "NONE";
+ Response failToCreateDataset1 = UtilIT.createDatasetViaSwordApi(dataverseAlias, title, description, license, apiToken);
+ failToCreateDataset1.prettyPrint();
+ // As of 5.10 and PR #7920, you cannot pass NONE as a license.
+ failToCreateDataset1.then().assertThat()
+ .statusCode(BAD_REQUEST.getStatusCode());
+
+ String rights = "Call me";
+ Response failToCreateDataset2 = UtilIT.createDatasetViaSwordApi(dataverseAlias, title, description, license, rights, apiToken);
+ failToCreateDataset2.prettyPrint();
+ // You can't pass both license and rights
+ failToCreateDataset2.then().assertThat()
+ .statusCode(BAD_REQUEST.getStatusCode());
+
+ license = "CC0 1.0";
+ Response createDataset = UtilIT.createDatasetViaSwordApi(dataverseAlias, title, description, license, apiToken);
+ createDataset.prettyPrint();
+ createDataset.then().assertThat()
+ .statusCode(CREATED.getStatusCode());
+
+ String persistentId = UtilIT.getDatasetPersistentIdFromSwordResponse(createDataset);
+
+ Response getJson = UtilIT.nativeGetUsingPersistentId(persistentId, apiToken);
+ getJson.prettyPrint();
+ getJson.then().assertThat()
+ .statusCode(OK.getStatusCode())
+ .body("data.latestVersion.license.name", equalTo("CC0 1.0"))
+ .body("data.latestVersion.license.uri", equalTo("http://creativecommons.org/publicdomain/zero/1.0"))
+ .body("data.latestVersion.termsOfUse", equalTo(null));
+ }
+
+ @Test
+ public void testCustomTerms() {
+
+ Response createUser = UtilIT.createRandomUser();
+ String username = UtilIT.getUsernameFromResponse(createUser);
+ String apiToken = UtilIT.getApiTokenFromResponse(createUser);
+
+ Response createDataverse = UtilIT.createRandomDataverse(apiToken);
+ createDataverse.prettyPrint();
+ createDataverse.then().assertThat()
+ .statusCode(CREATED.getStatusCode());
+ String dataverseAlias = UtilIT.getAliasFromResponse(createDataverse);
+
+ String title = "Terms of Endearment";
+ String description = "Aurora, etc.";
+ String license = null;
+ String rights = "Call me";
+ Response createDataset = UtilIT.createDatasetViaSwordApi(dataverseAlias, title, description, license, rights, apiToken);
+ createDataset.prettyPrint();
+ createDataset.then().assertThat()
+ .statusCode(CREATED.getStatusCode());
+
+ String persistentId = UtilIT.getDatasetPersistentIdFromSwordResponse(createDataset);
+
+ Response getJson = UtilIT.nativeGetUsingPersistentId(persistentId, apiToken);
+ getJson.prettyPrint();
+ getJson.then().assertThat()
+ .statusCode(OK.getStatusCode())
+ .body("data.latestVersion.termsOfUse", equalTo("Call me"))
+ .body("data.latestVersion.license", equalTo(null));
+ }
+
+ @Test
+ public void testXmlExampleInGuides() throws IOException {
+
+ Response createUser = UtilIT.createRandomUser();
+ String username = UtilIT.getUsernameFromResponse(createUser);
+ String apiToken = UtilIT.getApiTokenFromResponse(createUser);
+
+ Response createDataverse = UtilIT.createRandomDataverse(apiToken);
+ createDataverse.prettyPrint();
+ createDataverse.then().assertThat()
+ .statusCode(CREATED.getStatusCode());
+ String dataverseAlias = UtilIT.getAliasFromResponse(createDataverse);
+
+ File exampleFile = new File("doc/sphinx-guides/source/api/sword-atom-entry.xml");
+ String xmlIn = new String(java.nio.file.Files.readAllBytes(Paths.get(exampleFile.getAbsolutePath())));
+ Response createDataset = UtilIT.createDatasetViaSwordApiFromXML(dataverseAlias, xmlIn, apiToken);
+ createDataset.prettyPrint();
+ createDataset.then().assertThat()
+ .statusCode(CREATED.getStatusCode());
+
+ }
+
/**
* This test requires the root dataverse to have been published already.
*
diff --git a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java
index 23672c45916..7b9b5f3b129 100644
--- a/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java
+++ b/src/test/java/edu/harvard/iq/dataverse/api/UtilIT.java
@@ -436,7 +436,18 @@ static Response createDatasetViaSwordApi(String dataverseToCreateDatasetIn, Stri
return createDatasetViaSwordApiFromXML(dataverseToCreateDatasetIn, xmlIn, apiToken);
}
- private static Response createDatasetViaSwordApiFromXML(String dataverseToCreateDatasetIn, String xmlIn, String apiToken) {
+ static Response createDatasetViaSwordApi(String dataverseToCreateDatasetIn, String title, String description, String license, String apiToken) {
+ String nullRights = null;
+ String xmlIn = getDatasetXml(title, "Lastname, Firstname", description, license, nullRights);
+ return createDatasetViaSwordApiFromXML(dataverseToCreateDatasetIn, xmlIn, apiToken);
+ }
+
+ static Response createDatasetViaSwordApi(String dataverseToCreateDatasetIn, String title, String description, String license, String rights, String apiToken) {
+ String xmlIn = getDatasetXml(title, "Lastname, Firstname", description, license, rights);
+ return createDatasetViaSwordApiFromXML(dataverseToCreateDatasetIn, xmlIn, apiToken);
+ }
+
+ public static Response createDatasetViaSwordApiFromXML(String dataverseToCreateDatasetIn, String xmlIn, String apiToken) {
Response createDatasetResponse = given()
.auth().basic(apiToken, EMPTY_STRING)
.body(xmlIn)
@@ -534,11 +545,27 @@ static Response loadMetadataBlock(String apiToken, byte[] body) {
}
static private String getDatasetXml(String title, String author, String description) {
+ String nullLicense = null;
+ String nullRights = null;
+ return getDatasetXml(title, author, description, nullLicense, nullRights);
+ }
+
+ static private String getDatasetXml(String title, String author, String description, String license, String rights) {
+ String optionalLicense = "";
+ if (license != null) {
+ optionalLicense = " " + license + "\n";
+ }
+ String optionalRights = "";
+ if (rights != null) {
+ optionalRights = " " + rights + "\n";
+ }
String xmlIn = "\n"
+ "\n"
+ " " + title + "\n"
+ " " + author + "\n"
+ " " + description + "\n"
+ + optionalLicense
+ + optionalRights
+ "\n"
+ "";
return xmlIn;