diff --git a/doc/release-notes/12132-dataset-creation-with-template.md b/doc/release-notes/12132-dataset-creation-with-template.md new file mode 100644 index 00000000000..79bf72017e7 --- /dev/null +++ b/doc/release-notes/12132-dataset-creation-with-template.md @@ -0,0 +1,3 @@ +## Feature ## + +POST /dataverses/{identifier}/datasets payload JSON now allows for "templateId":$templateId to be included to set the Template on the new Dataset. diff --git a/src/main/java/edu/harvard/iq/dataverse/api/AbstractApiBean.java b/src/main/java/edu/harvard/iq/dataverse/api/AbstractApiBean.java index 4eccb16f2b3..b32b5ae8d49 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/AbstractApiBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/AbstractApiBean.java @@ -267,7 +267,7 @@ public enum Format { private final LazyRef jsonParserRef = new LazyRef<>(new Callable() { @Override public JsonParser call() throws Exception { - return new JsonParser(datasetFieldSvc, metadataBlockSvc,settingsSvc, licenseSvc, datasetTypeSvc); + return new JsonParser(datasetFieldSvc, metadataBlockSvc,settingsSvc, licenseSvc, datasetTypeSvc, templateSvc); } }); diff --git a/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java b/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java index 28a67237af1..c4e654ff597 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java @@ -419,8 +419,7 @@ public Response createDataset(@Context ContainerRequestContext crc, logger.fine("Json is: " + jsonBody); User u = getRequestUser(crc); Dataverse owner = findDataverseOrDie(parentIdtf); - Dataset ds = parseDataset(jsonBody); - ds.setOwner(owner); + Dataset ds = parseDataset(jsonBody, owner); // Will make validation happen always except for the (rare) occasion of all three conditions are true boolean validate = ! ( u.isAuthenticated() && StringUtil.isTrue(doNotValidateParam) && JvmSettings.API_ALLOW_INCOMPLETE_METADATA.lookupOptional(Boolean.class).orElse(false) ); @@ -558,8 +557,7 @@ public Response importDataset(@Context ContainerRequestContext crc, return error(Status.FORBIDDEN, "Not a superuser"); } Dataverse owner = findDataverseOrDie(parentIdtf); - Dataset ds = parseDataset(jsonBody); - ds.setOwner(owner); + Dataset ds = parseDataset(jsonBody, owner); if (ds.getVersions().isEmpty()) { return badRequest("Supplied json must contain a single dataset version."); @@ -649,9 +647,9 @@ public Response importDatasetDdi(@Context ContainerRequestContext crc, return error(Status.FORBIDDEN, "Not a superuser"); } Dataverse owner = findDataverseOrDie(parentIdtf); - Dataset ds = null; + Dataset ds; try { - ds = jsonParser().parseDataset(importService.ddiToJson(xml)); + ds = jsonParser().parseDataset(importService.ddiToJson(xml), owner); DataverseUtil.checkMetadataLangauge(ds, owner, settingsService.getBaseMetadataLanguageMap(null, true)); } catch (JsonParseException jpe) { return badRequest("Error parsing data as Json: "+jpe.getMessage()); @@ -663,7 +661,6 @@ public Response importDatasetDdi(@Context ContainerRequestContext crc, swordService.addDatasetSubjectIfMissing(ds.getLatestVersion()); - ds.setOwner(owner); if (nonEmpty(pidParam)) { if (!GlobalId.verifyImportCharacters(pidParam)) { return badRequest("PID parameter contains characters that are not allowed by the Dataverse application. On import, the PID must only contain characters specified in this regex: " + BundleUtil.getStringFromBundle("pid.allowedCharacters")); @@ -774,9 +771,9 @@ public Response recreateDataset(@Context ContainerRequestContext crc, } } - private Dataset parseDataset(String datasetJson) throws WrappedResponse { + private Dataset parseDataset(String datasetJson, Dataverse owner) throws WrappedResponse { try { - return jsonParser().parseDataset(JsonUtil.getJsonObject(datasetJson)); + return jsonParser().parseDataset(JsonUtil.getJsonObject(datasetJson), owner); } catch (JsonParsingException | JsonParseException jpe) { String message = jpe.getLocalizedMessage(); logger.log(Level.SEVERE, "Error parsing dataset JSON. message: {0}", message); diff --git a/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportGenericServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportGenericServiceBean.java index d75ea42e433..d9207a27e70 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportGenericServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportGenericServiceBean.java @@ -1,17 +1,9 @@ package edu.harvard.iq.dataverse.api.imports; import com.google.gson.Gson; - -import edu.harvard.iq.dataverse.Dataset; -import edu.harvard.iq.dataverse.DatasetFieldCompoundValue; -import edu.harvard.iq.dataverse.DatasetFieldConstant; -import edu.harvard.iq.dataverse.DatasetFieldServiceBean; -import edu.harvard.iq.dataverse.DatasetFieldType; -import edu.harvard.iq.dataverse.DatasetVersion; -import edu.harvard.iq.dataverse.ForeignMetadataFieldMapping; -import edu.harvard.iq.dataverse.ForeignMetadataFormatMapping; -import edu.harvard.iq.dataverse.MetadataBlockServiceBean; -import edu.harvard.iq.dataverse.api.dto.*; +import edu.harvard.iq.dataverse.*; +import edu.harvard.iq.dataverse.api.dto.DatasetDTO; +import edu.harvard.iq.dataverse.api.dto.DatasetVersionDTO; import edu.harvard.iq.dataverse.api.dto.FieldDTO; import edu.harvard.iq.dataverse.api.dto.MetadataBlockDTO; import edu.harvard.iq.dataverse.dataset.DatasetTypeServiceBean; @@ -24,33 +16,28 @@ import edu.harvard.iq.dataverse.util.json.JsonParseException; import edu.harvard.iq.dataverse.util.json.JsonParser; import edu.harvard.iq.dataverse.util.xml.XmlUtil; - -import java.io.File; -import java.io.FileInputStream; -import java.io.FileNotFoundException; -import java.io.IOException; -import java.io.StringReader; -import java.util.*; -import java.util.Map; -import java.util.logging.Level; -import java.util.logging.Logger; import jakarta.ejb.EJB; import jakarta.ejb.EJBException; import jakarta.ejb.Stateless; import jakarta.inject.Named; import jakarta.json.Json; -import javax.xml.stream.XMLStreamConstants; -import javax.xml.stream.XMLStreamException; -import javax.xml.stream.XMLStreamReader; import jakarta.json.JsonObject; import jakarta.json.JsonReader; import jakarta.persistence.EntityManager; import jakarta.persistence.NoResultException; import jakarta.persistence.PersistenceContext; -import javax.xml.stream.XMLInputFactory; import net.handle.hdllib.HandleException; import net.handle.hdllib.HandleResolver; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamConstants; +import javax.xml.stream.XMLStreamException; +import javax.xml.stream.XMLStreamReader; +import java.io.*; +import java.util.*; +import java.util.logging.Level; +import java.util.logging.Logger; + /** * @@ -81,6 +68,9 @@ public class ImportGenericServiceBean { @EJB DatasetTypeServiceBean datasetTypeService; + @EJB + TemplateServiceBean templateService; + @PersistenceContext(unitName = "VDCNet-ejbPU") private EntityManager em; @@ -117,7 +107,7 @@ public void importXML(String xmlToParse, String foreignFormat, DatasetVersion da logger.fine(json); JsonReader jsonReader = Json.createReader(new StringReader(json)); JsonObject obj = jsonReader.readObject(); - DatasetVersion dv = new JsonParser(datasetFieldSvc, blockService, settingsService, licenseService, datasetTypeService).parseDatasetVersion(obj, datasetVersion); + DatasetVersion dv = new JsonParser(datasetFieldSvc, blockService, settingsService, licenseService, datasetTypeService, templateService).parseDatasetVersion(obj, datasetVersion); } catch (XMLStreamException ex) { //Logger.getLogger("global").log(Level.SEVERE, null, ex); throw new EJBException("ERROR occurred while parsing XML fragment ("+xmlToParse.substring(0, 64)+"...); ", ex); diff --git a/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportServiceBean.java index 3a39400a598..794c2e5ca00 100644 --- a/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportServiceBean.java +++ b/src/main/java/edu/harvard/iq/dataverse/api/imports/ImportServiceBean.java @@ -13,23 +13,27 @@ import edu.harvard.iq.dataverse.dataset.DatasetTypeServiceBean; import edu.harvard.iq.dataverse.engine.command.DataverseRequest; import edu.harvard.iq.dataverse.engine.command.exception.CommandException; -import edu.harvard.iq.dataverse.engine.command.impl.CreateDatasetVersionCommand; -import edu.harvard.iq.dataverse.engine.command.impl.CreateDataverseCommand; -import edu.harvard.iq.dataverse.engine.command.impl.CreateHarvestedDatasetCommand; -import edu.harvard.iq.dataverse.engine.command.impl.CreateNewDatasetCommand; -import edu.harvard.iq.dataverse.engine.command.impl.DestroyDatasetCommand; -import edu.harvard.iq.dataverse.engine.command.impl.UpdateHarvestedDatasetCommand; +import edu.harvard.iq.dataverse.engine.command.impl.*; import edu.harvard.iq.dataverse.harvest.client.HarvestingClient; +import edu.harvard.iq.dataverse.license.LicenseServiceBean; +import edu.harvard.iq.dataverse.pidproviders.PidUtil; import edu.harvard.iq.dataverse.search.IndexServiceBean; import edu.harvard.iq.dataverse.settings.SettingsServiceBean; import edu.harvard.iq.dataverse.util.ConstraintViolationUtil; +import edu.harvard.iq.dataverse.util.DatasetFieldUtil; import edu.harvard.iq.dataverse.util.json.JsonParseException; import edu.harvard.iq.dataverse.util.json.JsonParser; import edu.harvard.iq.dataverse.util.json.JsonUtil; -import edu.harvard.iq.dataverse.license.LicenseServiceBean; -import edu.harvard.iq.dataverse.pidproviders.PidUtil; -import edu.harvard.iq.dataverse.util.DatasetFieldUtil; +import jakarta.ejb.*; +import jakarta.json.Json; +import jakarta.json.JsonObject; +import jakarta.json.JsonObjectBuilder; +import jakarta.persistence.EntityManager; +import jakarta.persistence.PersistenceContext; +import jakarta.validation.*; +import org.apache.commons.lang3.StringUtils; +import javax.xml.stream.XMLStreamException; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; @@ -43,24 +47,8 @@ import java.util.logging.Level; import java.util.logging.LogRecord; import java.util.logging.Logger; -import jakarta.ejb.EJB; -import jakarta.ejb.EJBException; -import jakarta.ejb.Stateless; -import jakarta.ejb.TransactionAttribute; -import jakarta.ejb.TransactionAttributeType; + import static jakarta.ejb.TransactionAttributeType.REQUIRES_NEW; -import jakarta.json.Json; -import jakarta.json.JsonObject; -import jakarta.json.JsonObjectBuilder; -import jakarta.persistence.EntityManager; -import jakarta.persistence.PersistenceContext; -import jakarta.validation.ConstraintViolation; -import jakarta.validation.ConstraintViolationException; -import jakarta.validation.Validation; -import jakarta.validation.Validator; -import jakarta.validation.ValidatorFactory; -import javax.xml.stream.XMLStreamException; -import org.apache.commons.lang3.StringUtils; /** * @@ -101,6 +89,9 @@ public class ImportServiceBean { @EJB DatasetTypeServiceBean datasetTypeService; + @EJB + TemplateServiceBean templateService; + /** * This is just a convenience method, for testing migration. It creates * a dummy dataverse with the directory name as dataverse name & alias. @@ -312,13 +303,13 @@ public Dataset doImportHarvestedDataset(DataverseRequest dataverseRequest, try { Dataset harvestedDataset; - JsonParser parser = new JsonParser(datasetfieldService, metadataBlockService, settingsService, licenseService, datasetTypeService, harvestingClient); + JsonParser parser = new JsonParser(datasetfieldService, metadataBlockService, settingsService, licenseService, datasetTypeService, harvestingClient, templateService); parser.setLenient(true); if (existingDataset == null) { // Creating a new dataset from scratch: - harvestedDataset = parser.parseDataset(obj); + harvestedDataset = parser.parseDataset(obj, owner); harvestedDataset.setHarvestedFrom(harvestingClient); harvestedDataset.setHarvestIdentifier(harvestIdentifier); @@ -442,9 +433,9 @@ public JsonObjectBuilder doImport(DataverseRequest dataverseRequest, Dataverse o JsonObject obj = JsonUtil.getJsonObject(json); //and call parse Json to read it into a dataset try { - JsonParser parser = new JsonParser(datasetfieldService, metadataBlockService, settingsService, licenseService, datasetTypeService); + JsonParser parser = new JsonParser(datasetfieldService, metadataBlockService, settingsService, licenseService, datasetTypeService, templateService); parser.setLenient(!importType.equals(ImportType.NEW)); - Dataset ds = parser.parseDataset(obj); + Dataset ds = parser.parseDataset(obj, owner); // For ImportType.NEW, if the user supplies a global identifier, and it's not a protocol // we support, it will be rejected. @@ -455,7 +446,6 @@ public JsonObjectBuilder doImport(DataverseRequest dataverseRequest, Dataverse o } } - ds.setOwner(owner); ds.getLatestVersion().setDatasetFields(ds.getLatestVersion().initDatasetFields()); // Check data against required constraints diff --git a/src/main/java/edu/harvard/iq/dataverse/dataverse/DataverseUtil.java b/src/main/java/edu/harvard/iq/dataverse/dataverse/DataverseUtil.java index f45a9058e7c..ac139b4cffa 100644 --- a/src/main/java/edu/harvard/iq/dataverse/dataverse/DataverseUtil.java +++ b/src/main/java/edu/harvard/iq/dataverse/dataverse/DataverseUtil.java @@ -1,8 +1,6 @@ package edu.harvard.iq.dataverse.dataverse; -import edu.harvard.iq.dataverse.Dataset; -import edu.harvard.iq.dataverse.Dataverse; -import edu.harvard.iq.dataverse.DvObjectContainer; +import edu.harvard.iq.dataverse.*; import edu.harvard.iq.dataverse.authorization.groups.impl.ipaddress.ip.IpAddress; import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser; import edu.harvard.iq.dataverse.authorization.users.User; @@ -13,9 +11,11 @@ import static edu.harvard.iq.dataverse.util.json.JsonPrinter.json; import java.io.File; import java.io.IOException; +import java.util.List; import java.util.Map; import java.util.logging.Logger; +import jakarta.enterprise.inject.spi.CDI; import jakarta.ws.rs.BadRequestException; import opennlp.tools.util.StringUtil; @@ -122,4 +122,20 @@ public static void checkMetadataLangauge(Dataset ds, Dataverse owner, Map dataverseTemplates = dataverse.getTemplates(); + if (dataverseTemplates != null && dataverseTemplates.contains(template)) { + return true; + } + if (!dataverse.isTemplateRoot() && dataverse.getOwner() != null) { + DataverseServiceBean dataverseService = CDI.current().select(DataverseServiceBean.class).get(); + List