From 05049008b40f3a7380558b90e5daaa554fbba113 Mon Sep 17 00:00:00 2001 From: Ali Sheikhi Date: Mon, 5 Aug 2024 10:48:25 +0200 Subject: [PATCH] DD-1605 Implement several dd-dataverse-cli dataset commands --- .../nl/knaw/dans/dvcli/DdDataverseCli.java | 14 +- .../dans/dvcli/command/CollectionCmd.java | 7 +- .../CollectionSetMetadataBlocksRoot.java | 4 +- .../dans/dvcli/command/DatasetAssignRole.java | 123 ++++++++++++++++++ .../knaw/dans/dvcli/command/DatasetCmd.java | 3 +- ...leteDraft.java => DatasetDeleteDraft.java} | 2 +- .../dans/dvcli/command/DatasetGetFiles.java | 47 +++++++ .../command/DatasetGetLatestVersion.java | 44 +++++++ .../dans/dvcli/command/DatasetGetVersion.java | 46 +++++++ .../dans/dvcli/command/DatasetPublish.java | 60 +++++++++ 10 files changed, 341 insertions(+), 9 deletions(-) create mode 100644 src/main/java/nl/knaw/dans/dvcli/command/DatasetAssignRole.java rename src/main/java/nl/knaw/dans/dvcli/command/{DeleteDraft.java => DatasetDeleteDraft.java} (96%) create mode 100644 src/main/java/nl/knaw/dans/dvcli/command/DatasetGetFiles.java create mode 100644 src/main/java/nl/knaw/dans/dvcli/command/DatasetGetLatestVersion.java create mode 100644 src/main/java/nl/knaw/dans/dvcli/command/DatasetGetVersion.java create mode 100644 src/main/java/nl/knaw/dans/dvcli/command/DatasetPublish.java diff --git a/src/main/java/nl/knaw/dans/dvcli/DdDataverseCli.java b/src/main/java/nl/knaw/dans/dvcli/DdDataverseCli.java index 0f54f1b..230414d 100644 --- a/src/main/java/nl/knaw/dans/dvcli/DdDataverseCli.java +++ b/src/main/java/nl/knaw/dans/dvcli/DdDataverseCli.java @@ -32,7 +32,12 @@ import nl.knaw.dans.dvcli.command.CollectionSetMetadataBlocksRoot; import nl.knaw.dans.dvcli.command.CollectionView; import nl.knaw.dans.dvcli.command.DatasetCmd; -import nl.knaw.dans.dvcli.command.DeleteDraft; +import nl.knaw.dans.dvcli.command.DatasetGetFiles; +import nl.knaw.dans.dvcli.command.DatasetDeleteDraft; +import nl.knaw.dans.dvcli.command.DatasetGetLatestVersion; +import nl.knaw.dans.dvcli.command.DatasetGetVersion; +import nl.knaw.dans.dvcli.command.DatasetPublish; +import nl.knaw.dans.dvcli.command.DatasetAssignRole; import nl.knaw.dans.dvcli.config.DdDataverseCliConfig; import nl.knaw.dans.lib.util.AbstractCommandLineApp; import nl.knaw.dans.lib.util.PicocliVersionProvider; @@ -72,7 +77,12 @@ public void configureCommandLine(CommandLine commandLine, DdDataverseCliConfig c .addSubcommand(new CollectionSetMetadataBlocksRoot()) .addSubcommand(new CollectionView())) .addSubcommand(new CommandLine(new DatasetCmd(dataverseClient)) - .addSubcommand(new DeleteDraft()) + .addSubcommand(new DatasetDeleteDraft()) + .addSubcommand(new DatasetGetFiles()) + .addSubcommand(new DatasetGetLatestVersion()) + .addSubcommand(new DatasetGetVersion()) + .addSubcommand(new DatasetPublish()) + .addSubcommand(new DatasetAssignRole()) ); log.debug("Configuring command line"); } diff --git a/src/main/java/nl/knaw/dans/dvcli/command/CollectionCmd.java b/src/main/java/nl/knaw/dans/dvcli/command/CollectionCmd.java index 1e90cd6..8bf08c4 100644 --- a/src/main/java/nl/knaw/dans/dvcli/command/CollectionCmd.java +++ b/src/main/java/nl/knaw/dans/dvcli/command/CollectionCmd.java @@ -29,12 +29,13 @@ mixinStandardHelpOptions = true, description = "Manage Dataverse collections (i.e. 'dataverses')") public class CollectionCmd extends AbstractSubcommandContainer { + public CollectionCmd(@NonNull DataverseClient dataverseClient) { + super(dataverseClient); + } + @Override protected List> getItems() throws IOException { return new SingleCollectionOrCollectionsFile(targets, dataverseClient).getCollections().toList(); } - public CollectionCmd(@NonNull DataverseClient dataverseClient) { - super(dataverseClient); - } } diff --git a/src/main/java/nl/knaw/dans/dvcli/command/CollectionSetMetadataBlocksRoot.java b/src/main/java/nl/knaw/dans/dvcli/command/CollectionSetMetadataBlocksRoot.java index 61fade6..e983b6a 100644 --- a/src/main/java/nl/knaw/dans/dvcli/command/CollectionSetMetadataBlocksRoot.java +++ b/src/main/java/nl/knaw/dans/dvcli/command/CollectionSetMetadataBlocksRoot.java @@ -17,8 +17,8 @@ import nl.knaw.dans.dvcli.action.ConsoleReport; import nl.knaw.dans.lib.dataverse.DataverseException; -import picocli.CommandLine; import picocli.CommandLine.Command; +import picocli.CommandLine.Parameters; import picocli.CommandLine.ParentCommand; import java.io.IOException; @@ -30,7 +30,7 @@ public class CollectionSetMetadataBlocksRoot extends AbstractCmd { @ParentCommand private CollectionCmd collectionCmd; - @CommandLine.Parameters(index = "0", paramLabel = "isRoot", type = Boolean.class, description = "Whether to make it a metadata blocks root.") + @Parameters(index = "0", paramLabel = "isRoot", type = Boolean.class, description = "Whether to make it a metadata blocks root.") private Boolean isRoot; @Override diff --git a/src/main/java/nl/knaw/dans/dvcli/command/DatasetAssignRole.java b/src/main/java/nl/knaw/dans/dvcli/command/DatasetAssignRole.java new file mode 100644 index 0000000..0aca04e --- /dev/null +++ b/src/main/java/nl/knaw/dans/dvcli/command/DatasetAssignRole.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2024 DANS - Data Archiving and Networked Services (info@dans.knaw.nl) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package nl.knaw.dans.dvcli.command; + +import nl.knaw.dans.dvcli.action.ConsoleReport; +import nl.knaw.dans.dvcli.action.Pair; +import nl.knaw.dans.dvcli.action.ThrowingFunction; +import nl.knaw.dans.lib.dataverse.DatasetApi; +import nl.knaw.dans.lib.dataverse.DataverseException; +import nl.knaw.dans.lib.dataverse.model.RoleAssignment; +import org.apache.commons.csv.CSVFormat; +import org.apache.commons.csv.CSVParser; +import org.apache.commons.csv.CSVRecord; +import picocli.CommandLine.ArgGroup; +import picocli.CommandLine.Command; +import picocli.CommandLine.Option; +import picocli.CommandLine.Parameters; +import picocli.CommandLine.ParentCommand; + +import java.io.IOException; +import java.io.Reader; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; + +@Command(name = "role-assignment", + mixinStandardHelpOptions = true, + description = "Manage role assignments on one or more datasets.") +public class DatasetAssignRole extends AbstractCmd { + @ParentCommand + private DatasetCmd datasetCmd; + + static class SingleAssignment { + @Parameters(index = "0", paramLabel = "role", description = "The role to assign") + String role; + + @Parameters(index = "1", paramLabel = "assigsment", description = "The identifier of the user to assign the role to") + String assigsment; + } + + static class AllArgs { + @ArgGroup(exclusive = false) + SingleAssignment singleAssignment; + + @Option(names = { "-f", "--parameters-file" }, paramLabel = "parameter-file", description = "CSV file to read parameters from. The file should have a header row with columns 'PID', 'ROLE', and 'ASSIGNMENT'.") + Path paramsFile; + } + + @ArgGroup(exclusive = true, multiplicity = "1") + private AllArgs allArgs; + + private record RoleAssignmentParams(DatasetApi collection, String role, String assignee) { + } + + private static class RoleAssignmentAction implements ThrowingFunction { + @Override + public String apply(RoleAssignmentParams roleAssignmentParams) throws IOException, DataverseException { + var assignment = new RoleAssignment(); + assignment.setAssignee(roleAssignmentParams.assignee()); + assignment.setRole(roleAssignmentParams.role()); + var r = roleAssignmentParams.collection.assignRole(assignment); + return r.getEnvelopeAsString(); + } + } + + private List> readFromFile(Path file) throws IOException { + try (Reader reader = Files.newBufferedReader(file); + CSVParser csvParser = new CSVParser(reader, CSVFormat.Builder.create(CSVFormat.DEFAULT) + .setHeader("PID", "ROLE", "ASSIGNEE") + .setSkipHeaderRecord(true) + .build())) { + + List> result = new ArrayList<>(); + + for (CSVRecord csvRecord : csvParser) { + var pid = csvRecord.get("PID"); + DatasetApi collection = datasetCmd.dataverseClient.dataset(pid); + String role = csvRecord.get("ROLE"); + String assignee = csvRecord.get("ASSIGNEE"); + + RoleAssignmentParams params = new RoleAssignmentParams(collection, role, assignee); + result.add(new Pair<>(pid, params)); + } + + return result; + } + } + + private List> getRoleAssignmentParams() throws IOException { + if (allArgs.paramsFile != null) { + return readFromFile(allArgs.paramsFile); + } + else { + return datasetCmd.getItems().stream() + .map(p -> new Pair<>(p.getFirst(), new RoleAssignmentParams(p.getSecond(), allArgs.singleAssignment.role, allArgs.singleAssignment.assigsment))) + .toList(); + } + } + + @Override + public void doCall() throws IOException, DataverseException { + datasetCmd. paramsBatchProcessorBuilder() + .labeledItems(getRoleAssignmentParams()) + .action(new RoleAssignmentAction()) + .report(new ConsoleReport<>()) + .build() + .process(); + } +} diff --git a/src/main/java/nl/knaw/dans/dvcli/command/DatasetCmd.java b/src/main/java/nl/knaw/dans/dvcli/command/DatasetCmd.java index e4c536c..fbf770e 100644 --- a/src/main/java/nl/knaw/dans/dvcli/command/DatasetCmd.java +++ b/src/main/java/nl/knaw/dans/dvcli/command/DatasetCmd.java @@ -15,6 +15,7 @@ */ package nl.knaw.dans.dvcli.command; +import lombok.NonNull; import lombok.extern.slf4j.Slf4j; import nl.knaw.dans.dvcli.action.Pair; import nl.knaw.dans.dvcli.action.SingleDatasetOrDatasetsFile; @@ -31,7 +32,7 @@ description = "Manage Dataverse datasets") @Slf4j public class DatasetCmd extends AbstractSubcommandContainer { - public DatasetCmd(DataverseClient dataverseClient) { + public DatasetCmd(@NonNull DataverseClient dataverseClient) { super(dataverseClient); } diff --git a/src/main/java/nl/knaw/dans/dvcli/command/DeleteDraft.java b/src/main/java/nl/knaw/dans/dvcli/command/DatasetDeleteDraft.java similarity index 96% rename from src/main/java/nl/knaw/dans/dvcli/command/DeleteDraft.java rename to src/main/java/nl/knaw/dans/dvcli/command/DatasetDeleteDraft.java index 63dfec2..3cbd7e6 100644 --- a/src/main/java/nl/knaw/dans/dvcli/command/DeleteDraft.java +++ b/src/main/java/nl/knaw/dans/dvcli/command/DatasetDeleteDraft.java @@ -27,7 +27,7 @@ @Command(name = "delete-draft", mixinStandardHelpOptions = true, description = "Delete the draft version of a dataset.") -public class DeleteDraft extends AbstractCmd { +public class DatasetDeleteDraft extends AbstractCmd { @ParentCommand private DatasetCmd datasetCmd; diff --git a/src/main/java/nl/knaw/dans/dvcli/command/DatasetGetFiles.java b/src/main/java/nl/knaw/dans/dvcli/command/DatasetGetFiles.java new file mode 100644 index 0000000..88836d4 --- /dev/null +++ b/src/main/java/nl/knaw/dans/dvcli/command/DatasetGetFiles.java @@ -0,0 +1,47 @@ +/* + * Copyright (C) 2024 DANS - Data Archiving and Networked Services (info@dans.knaw.nl) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package nl.knaw.dans.dvcli.command; + +import nl.knaw.dans.dvcli.action.ConsoleReport; +import nl.knaw.dans.lib.dataverse.DataverseException; +import picocli.CommandLine.Command; +import picocli.CommandLine.Parameters; +import picocli.CommandLine.ParentCommand; + +import java.io.IOException; + +@Command(name = "get-files", + mixinStandardHelpOptions = true, + description = "Get a list of file metadata.") +public class DatasetGetFiles extends AbstractCmd { + @ParentCommand + private DatasetCmd datasetCmd; + + @Parameters(index = "0", paramLabel = "version", description = "version to get file metadata from.") + private String version; + + @Override + public void doCall() throws IOException, DataverseException { + datasetCmd.batchProcessorBuilder() + .action(d -> { + var r = d.getFiles(version); + return r.getEnvelopeAsString(); + }) + .report(new ConsoleReport<>()) + .build() + .process(); + } +} diff --git a/src/main/java/nl/knaw/dans/dvcli/command/DatasetGetLatestVersion.java b/src/main/java/nl/knaw/dans/dvcli/command/DatasetGetLatestVersion.java new file mode 100644 index 0000000..2671d2a --- /dev/null +++ b/src/main/java/nl/knaw/dans/dvcli/command/DatasetGetLatestVersion.java @@ -0,0 +1,44 @@ +/* + * Copyright (C) 2024 DANS - Data Archiving and Networked Services (info@dans.knaw.nl) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package nl.knaw.dans.dvcli.command; + +import nl.knaw.dans.dvcli.action.ConsoleReport; +import nl.knaw.dans.lib.dataverse.DataverseException; +import picocli.CommandLine.Command; +import picocli.CommandLine.ParentCommand; + +import java.io.IOException; + +@Command(name = "get-latest-version", + mixinStandardHelpOptions = true, + description = "A JSON object that starts at the dataset level, most fields are replicated at the dataset version level.") +public class DatasetGetLatestVersion extends AbstractCmd { + @ParentCommand + private DatasetCmd datasetCmd; + + @Override + public void doCall() throws IOException, DataverseException { + datasetCmd.batchProcessorBuilder() + .action(d -> { + var r = d.getLatestVersion(); + return r.getEnvelopeAsString(); + }) + .report(new ConsoleReport<>()) + .build() + .process(); + } + +} diff --git a/src/main/java/nl/knaw/dans/dvcli/command/DatasetGetVersion.java b/src/main/java/nl/knaw/dans/dvcli/command/DatasetGetVersion.java new file mode 100644 index 0000000..0cf45c5 --- /dev/null +++ b/src/main/java/nl/knaw/dans/dvcli/command/DatasetGetVersion.java @@ -0,0 +1,46 @@ +/* + * Copyright (C) 2024 DANS - Data Archiving and Networked Services (info@dans.knaw.nl) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package nl.knaw.dans.dvcli.command; + +import nl.knaw.dans.dvcli.action.ConsoleReport; +import nl.knaw.dans.lib.dataverse.DataverseException; +import picocli.CommandLine.Command; +import picocli.CommandLine.Parameters; +import picocli.CommandLine.ParentCommand; + +import java.io.IOException; + +@Command(name = "get-version", + mixinStandardHelpOptions = true, + description = "Returns an object containing the dataset version metadata.") +public class DatasetGetVersion extends AbstractCmd { + @ParentCommand + private DatasetCmd datasetCmd; + @Parameters(index = "0", paramLabel = "version", description = "version to retrieve.") + String version; + + @Override + public void doCall() throws IOException, DataverseException { + datasetCmd.batchProcessorBuilder() + .action(d -> { + var r = d.getVersion(version); + return r.getEnvelopeAsString(); + }) + .report(new ConsoleReport<>()) + .build() + .process(); + } +} diff --git a/src/main/java/nl/knaw/dans/dvcli/command/DatasetPublish.java b/src/main/java/nl/knaw/dans/dvcli/command/DatasetPublish.java new file mode 100644 index 0000000..0ae8f2f --- /dev/null +++ b/src/main/java/nl/knaw/dans/dvcli/command/DatasetPublish.java @@ -0,0 +1,60 @@ +/* + * Copyright (C) 2024 DANS - Data Archiving and Networked Services (info@dans.knaw.nl) + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package nl.knaw.dans.dvcli.command; + +import nl.knaw.dans.dvcli.action.BatchProcessor; +import nl.knaw.dans.dvcli.action.ConsoleReport; +import nl.knaw.dans.lib.dataverse.DatasetApi; +import nl.knaw.dans.lib.dataverse.DataverseException; +import picocli.CommandLine.Command; +import picocli.CommandLine.Option; +import picocli.CommandLine.Parameters; +import picocli.CommandLine.ParentCommand; + +import java.io.IOException; +import java.util.EnumSet; + +@Command(name = "publish", + mixinStandardHelpOptions = true, + description = "Dataset publication result.") +public class DatasetPublish extends AbstractCmd { + @ParentCommand + private DatasetCmd datasetCmd; + + @Option(names={"-u", "--update-type"}, type =UpdateType.class, description ="'major' or 'minor' version update.") + private EnumSet updateType = EnumSet.of(UpdateType.major); + + @Option(names={"-a", "--assure-indexed"}, paramLabel = "assure-indexed", type = Boolean.class, description = "To make sure that indexing has already happened and it is set to 'true'.") + private boolean assureIsIndexed = true; + + + @Override + public void doCall() throws IOException, DataverseException { + BatchProcessor. builder() + .labeledItems(datasetCmd.getItems()) + .action(d -> { + var r = d.publish(); + return r.getEnvelopeAsString(); + }) + .report(new ConsoleReport<>()) + .delay(1000L) + .build() + .process(); + } + + enum UpdateType {major, minor} + +}