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

DD-1586 Added truncate-notifications with commandline input parsing #6

Merged
merged 27 commits into from
Sep 10, 2024
Merged
Show file tree
Hide file tree
Changes from 17 commits
Commits
Show all changes
27 commits
Select commit Hold shift + click to select a range
2e7d21c
Added truncate-notifications with commandline input parsing
PaulBoon Aug 27, 2024
2faf995
Added database configuration for truncate-notifications
PaulBoon Aug 27, 2024
a9e26ff
Initial database connection for truncate-notifications
PaulBoon Aug 28, 2024
adaad5b
Database connection for truncate-notifications working with a query
PaulBoon Aug 28, 2024
461084a
Database query refactoring for truncate-notifications
PaulBoon Aug 28, 2024
9d315d2
Implemented deleting notifications for specific user
PaulBoon Aug 28, 2024
d2d1532
Implemented deleting notifications for all users
PaulBoon Aug 29, 2024
828069f
Refactor notifications truncation, using batch processing
PaulBoon Aug 29, 2024
6bc1050
Throwing exceptions instead of just printing messages in notification…
PaulBoon Sep 2, 2024
e3c26cf
Merging with master
PaulBoon Sep 2, 2024
2526db9
Initial implementation of unit tests for notification truncation
PaulBoon Sep 3, 2024
a444b9a
Refactoring the Database class; extracting result now in separate fun…
PaulBoon Sep 3, 2024
b4a71ab
Added test for notification truncation of all users
PaulBoon Sep 3, 2024
53952ab
Added db settings to example config
PaulBoon Sep 3, 2024
508a2f4
Rename the dataverse setting to api
PaulBoon Sep 3, 2024
664c9d9
Refactoring
PaulBoon Sep 4, 2024
5bd03f8
Removing erroneous ';' in yml configs
PaulBoon Sep 5, 2024
c058bd1
Added @Positive annotation to numberOfRecordsToKeep
PaulBoon Sep 10, 2024
1e4defa
Renamed test functions to snake-case
PaulBoon Sep 10, 2024
46b07ef
Remove redundant use of stdin manipulation in the NotificationTruncat…
PaulBoon Sep 10, 2024
4ac4bb1
make sure database connection is closed, even if an exception is thrown
PaulBoon Sep 10, 2024
4225c36
Using try-with-resources statements in Database query and update
PaulBoon Sep 10, 2024
51fe7de
Removing @Positive annotation on numberOfRecordsToKeep
PaulBoon Sep 10, 2024
4eec9e5
Clarify the user input parameter with the notification truncation
PaulBoon Sep 10, 2024
1e9db8f
Added the delay option for notification truncate
PaulBoon Sep 10, 2024
2e24f71
Getting rid of most warnings
PaulBoon Sep 10, 2024
0dbee67
Have AbstractCmd doCall signature throw a general Exception
PaulBoon Sep 10, 2024
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
4 changes: 4 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,10 @@
<groupId>org.apache.commons</groupId>
<artifactId>commons-csv</artifactId>
</dependency>
<dependency>
<groupId>org.postgresql</groupId>
<artifactId>postgresql</artifactId>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
Expand Down
8 changes: 7 additions & 1 deletion src/main/assembly/dist/cfg/example-config.yml
Original file line number Diff line number Diff line change
@@ -1,7 +1,13 @@
dataverse:
api:
baseUrl: "http://localhost:8080"
apiKey: "your-api-token"

db:
host: localhost
database: "dvndb"
user: "dvnuser"
password: "dvnsecret"

#
# See https://www.dropwizard.io/en/latest/manual/configuration.html#logging
#
Expand Down
11 changes: 9 additions & 2 deletions src/main/java/nl/knaw/dans/dvcli/DdDataverseCli.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package nl.knaw.dans.dvcli;

import lombok.extern.slf4j.Slf4j;
import nl.knaw.dans.dvcli.action.Database;
import nl.knaw.dans.dvcli.command.CollectionAssignRole;
import nl.knaw.dans.dvcli.command.CollectionCmd;
import nl.knaw.dans.dvcli.command.CollectionCreateDataset;
Expand All @@ -33,7 +34,9 @@
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.NotificationTruncate;
import nl.knaw.dans.dvcli.config.DdDataverseCliConfig;
import nl.knaw.dans.lib.dataverse.DataverseClient;
import nl.knaw.dans.lib.util.AbstractCommandLineApp;
import nl.knaw.dans.lib.util.PicocliVersionProvider;
import picocli.CommandLine;
Expand All @@ -56,7 +59,10 @@
@Override
public void configureCommandLine(CommandLine commandLine, DdDataverseCliConfig config) {
log.debug("Building Dataverse client");
var dataverseClient = config.getDataverse().build();
var dataverseClient = config.getApi().build();
var databaseConfig = config.getDb();
var database = new Database(databaseConfig);

Check warning on line 64 in src/main/java/nl/knaw/dans/dvcli/DdDataverseCli.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/DdDataverseCli.java#L62-L64

Added lines #L62 - L64 were not covered by tests

commandLine.addSubcommand(new CommandLine(new CollectionCmd(dataverseClient))
.addSubcommand(new CollectionAssignRole())
.addSubcommand(new CollectionCreateDataset())
Expand All @@ -73,7 +79,8 @@
.addSubcommand(new CollectionView()))
.addSubcommand(new CommandLine(new DatasetCmd(dataverseClient))
.addSubcommand(new DeleteDraft())
);
)
.addSubcommand(new CommandLine(new NotificationTruncate(database)));

Check warning on line 83 in src/main/java/nl/knaw/dans/dvcli/DdDataverseCli.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/DdDataverseCli.java#L83

Added line #L83 was not covered by tests
jo-pol marked this conversation as resolved.
Show resolved Hide resolved
log.debug("Configuring command line");
}
}
132 changes: 132 additions & 0 deletions src/main/java/nl/knaw/dans/dvcli/action/Database.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
/*
* Copyright (C) 2024 DANS - Data Archiving and Networked Services ([email protected])
*
* 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.action;

import lombok.extern.slf4j.Slf4j;
import nl.knaw.dans.dvcli.config.DdDataverseDatabaseConfig;

import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.List;

/**
* Provides access to the Dataverse Database (Postgres).
* Some actions are not supported by the Dataverse API (yet)
* and must be done by direct access to the database.
*
* Note that the sql input strings are not filtered in any way,
* so don't put user input in there!
*/
@Slf4j
public class Database {

public Database(DdDataverseDatabaseConfig config) {
this.host = config.getHost();
this.database = config.getDatabase();
this.user = config.getUser();
this.password = config.getPassword();
}

Check warning on line 45 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L40-L45

Added lines #L40 - L45 were not covered by tests

Connection connection = null;

Check warning on line 47 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L47

Added line #L47 was not covered by tests

String port = "5432"; // Fixed port for Postgres

Check warning on line 49 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L49

Added line #L49 was not covered by tests

String host;
String database;
String user;
String password;

public void connect() throws ClassNotFoundException, SQLException {
Class.forName("org.postgresql.Driver");

Check warning on line 57 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L57

Added line #L57 was not covered by tests
if (connection == null) {
log.debug("Starting connecting to database");
connection = DriverManager
.getConnection("jdbc:postgresql://" + host + ":" + port + "/" + database,

Check warning on line 61 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L59-L61

Added lines #L59 - L61 were not covered by tests
user,
password);
}

}

Check warning on line 66 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L66

Added line #L66 was not covered by tests

public void close() {
try {
if (connection != null) {
log.debug("Close connection to database");
connection.close();

Check warning on line 72 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L71-L72

Added lines #L71 - L72 were not covered by tests
}
} catch (SQLException e) {
System.err.println( "Database error: " + e.getClass().getName() + " " + e.getMessage() );

Check warning on line 75 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L74-L75

Added lines #L74 - L75 were not covered by tests
} finally {
connection = null;

Check warning on line 77 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L77

Added line #L77 was not covered by tests
}
}

Check warning on line 79 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L79

Added line #L79 was not covered by tests

public List<List<String>> query(String sql) throws SQLException {
return query(sql, false);

Check warning on line 82 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L82

Added line #L82 was not covered by tests
}

public List<List<String>> query(String sql, Boolean startResultWithColumnNames) throws SQLException {
log.debug("Qerying database with: " + sql);

Check warning on line 86 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L86

Added line #L86 was not covered by tests

Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery( sql );
List<List<String>> rows = extractResult(rs, startResultWithColumnNames);

Check warning on line 90 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L88-L90

Added lines #L88 - L90 were not covered by tests

rs.close();
stmt.close();

Check warning on line 93 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L92-L93

Added lines #L92 - L93 were not covered by tests

return rows;

Check warning on line 95 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L95

Added line #L95 was not covered by tests
}

List<List<String>> extractResult(ResultSet rs, Boolean startResultWithColumnNames) throws SQLException {
List<List<String>> rows = new ArrayList<>();

Check warning on line 99 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L99

Added line #L99 was not covered by tests
// get column names
int numColumns = rs.getMetaData().getColumnCount();

Check warning on line 101 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L101

Added line #L101 was not covered by tests
if (startResultWithColumnNames) {
List<String> columnNames = new ArrayList<String>();

Check warning on line 103 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L103

Added line #L103 was not covered by tests
for (int i = 1; i <= numColumns; i++) {
columnNames.add(rs.getMetaData().getColumnName(i));

Check warning on line 105 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L105

Added line #L105 was not covered by tests
}
// make it the first row, for simplicity, a bit like with a csv file
rows.add(columnNames);

Check warning on line 108 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L108

Added line #L108 was not covered by tests
}

// get the data rows
while (rs.next()) {
List<String> row = new ArrayList<String>();

Check warning on line 113 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L113

Added line #L113 was not covered by tests
for (int i = 1; i <= numColumns; i++) {
row.add(rs.getString(i));

Check warning on line 115 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L115

Added line #L115 was not covered by tests
}
rows.add(row);
}
return rows;

Check warning on line 119 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L117-L119

Added lines #L117 - L119 were not covered by tests
}

public int update(String sql) throws SQLException {
log.debug("Updating database with: " + sql);
int rowCount = 0;

Check warning on line 124 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L123-L124

Added lines #L123 - L124 were not covered by tests

Statement stmt = connection.createStatement();
rowCount = stmt.executeUpdate( sql );
stmt.close();

Check warning on line 128 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L126-L128

Added lines #L126 - L128 were not covered by tests

return rowCount;

Check warning on line 130 in src/main/java/nl/knaw/dans/dvcli/action/Database.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/action/Database.java#L130

Added line #L130 was not covered by tests
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,5 +35,5 @@ public Integer call() throws Exception {
}
}

public abstract void doCall() throws IOException, DataverseException;
public abstract void doCall() throws Exception, DataverseException;
PaulBoon marked this conversation as resolved.
Show resolved Hide resolved
}
161 changes: 161 additions & 0 deletions src/main/java/nl/knaw/dans/dvcli/command/NotificationTruncate.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,161 @@
/*
* Copyright (C) 2024 DANS - Data Archiving and Networked Services ([email protected])
*
* 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 lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
import nl.knaw.dans.dvcli.action.BatchProcessor;
import nl.knaw.dans.dvcli.action.ConsoleReport;
import nl.knaw.dans.dvcli.action.Database;
import nl.knaw.dans.dvcli.action.Pair;
import nl.knaw.dans.dvcli.action.ThrowingFunction;
import nl.knaw.dans.dvcli.config.DdDataverseDatabaseConfig;

import picocli.CommandLine;

import java.io.IOException;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

@CommandLine.Command(name = "truncate-notifications",
mixinStandardHelpOptions = true,
description = "Remove user notifications but keep up to a specified amount.",
sortOptions = false)
@Slf4j
public class NotificationTruncate extends AbstractCmd {
protected Database db;
public NotificationTruncate(@NonNull Database database) {
this.db = database;
}


@CommandLine.ArgGroup(exclusive = true, multiplicity = "1")
UserOptions users;

static class UserOptions {
@CommandLine.Option(names = { "--user" }, required = true,
description = "The user whose notifications to truncate.")
int user; // a number, preventing accidental SQL injection
jo-pol marked this conversation as resolved.
Show resolved Hide resolved
// This id is visible for 'superusers' in the Dataverse Dashboard

@CommandLine.Option(names = { "--all-users" }, required = true,
description = "Truncate notifications for all users.")
boolean allUsers;
}

@CommandLine.Parameters(index = "0", paramLabel = "number-of-records-to-keep",
description = "The number of notification records to keep.")
private int numberOfRecordsToKeep;

private record NotificationTruncateParams(Database db, int userId, int numberOfRecordsToKeep) {
}

protected <NotificationTruncateParams> BatchProcessor.BatchProcessorBuilder<NotificationTruncate.NotificationTruncateParams, String> paramsBatchProcessorBuilder() throws IOException {
PaulBoon marked this conversation as resolved.
Show resolved Hide resolved
return BatchProcessor.<NotificationTruncate.NotificationTruncateParams, String> builder();

}

private static class NotificationTruncateAction implements ThrowingFunction<NotificationTruncate.NotificationTruncateParams, String, Exception> {

@Override
public String apply(NotificationTruncateParams notificationTruncateParams) throws Exception {
// Dry-run; show what will be deleted
//List<List<String>> results = notificationTruncateParams.db.query(String.format("SELECT * FROM usernotification WHERE user_id = '%d' AND id NOT IN (SELECT id FROM usernotification WHERE user_id = '%d' ORDER BY senddate DESC LIMIT %d);",
// notificationTruncateParams.userId, notificationTruncateParams.userId,
// notificationTruncateParams.numberOfRecordsToKeep), true
//);
//return "Notifications for user " + notificationTruncateParams.userId + " that will be deleted: \n"
// + getResultsAsString(results);

// Actually delete the notifications
try {
log.info("Deleting notifications for user with id " + notificationTruncateParams.userId);
int rowCount = notificationTruncateParams.db.update(String.format("DELETE FROM usernotification WHERE user_id = '%d' AND id NOT IN (SELECT id FROM usernotification WHERE user_id = '%d' ORDER BY senddate DESC LIMIT %d);",
notificationTruncateParams.userId, notificationTruncateParams.userId,
notificationTruncateParams.numberOfRecordsToKeep));
return "Deleted " + rowCount + " record(s) for user with id " + notificationTruncateParams.userId;
} catch (SQLException e) {
throw new Exception("Error deleting notifications for user with id " + notificationTruncateParams.userId, e);

Check warning on line 92 in src/main/java/nl/knaw/dans/dvcli/command/NotificationTruncate.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/command/NotificationTruncate.java#L91-L92

Added lines #L91 - L92 were not covered by tests
}
}
}

@Override
public void doCall() throws Exception {
// validate input
if (numberOfRecordsToKeep < 0) {
PaulBoon marked this conversation as resolved.
Show resolved Hide resolved
throw new Exception("Number of records to keep must be a positive integer, now it was " + numberOfRecordsToKeep + ".");
}

// Connect to database
//db = new Database(dbCfg);
db.connect();

paramsBatchProcessorBuilder()
.labeledItems(getItems())
.action(new NotificationTruncate.NotificationTruncateAction())
.delay(10L) // 10 ms, database should be able to handle this
PaulBoon marked this conversation as resolved.
Show resolved Hide resolved
.report(new ConsoleReport<>())
.build()
.process();

db.close(); // Not called if anny exception is thrown above!
PaulBoon marked this conversation as resolved.
Show resolved Hide resolved
}

protected List<Pair<String, NotificationTruncateParams>> getItems() throws Exception {
List<Pair<String, NotificationTruncateParams>> items = new ArrayList<>();
try {
if (users.allUsers) {
getUserIds(db).forEach(user_id -> items.add(new Pair<>(Integer.toString(user_id),
new NotificationTruncateParams(db, user_id, numberOfRecordsToKeep))));
} else {
// single user
items.add(new Pair<>(Integer.toString(users.user),

Check warning on line 127 in src/main/java/nl/knaw/dans/dvcli/command/NotificationTruncate.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/command/NotificationTruncate.java#L127

Added line #L127 was not covered by tests
new NotificationTruncateParams(db, users.user, numberOfRecordsToKeep)));
}
} catch (SQLException e) {
throw new Exception("Error getting user ids: ", e);

Check warning on line 131 in src/main/java/nl/knaw/dans/dvcli/command/NotificationTruncate.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/command/NotificationTruncate.java#L130-L131

Added lines #L130 - L131 were not covered by tests
}
return items;
}

// get the user_id for all users that need truncation
private List<Integer> getUserIds(Database db) throws SQLException {
List<Integer> users = new ArrayList<Integer>();
// Could just get all users with notifications
// String sql = "SELECT DISTINCT user_id FROM usernotification;";
// Instead we want only users with to many notifications
String sql = String.format("SELECT user_id FROM usernotification GROUP BY user_id HAVING COUNT(user_id) > %d;", numberOfRecordsToKeep);
List<List<String>> results = db.query(sql);
for (List<String> row : results) {
users.add(Integer.parseInt(row.get(0)));
}
return users;
}

private static String getResultsAsString(List<List<String>> results) {
// Note that the first row could be the column names
StringBuilder sb = new StringBuilder();

Check warning on line 152 in src/main/java/nl/knaw/dans/dvcli/command/NotificationTruncate.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/command/NotificationTruncate.java#L152

Added line #L152 was not covered by tests
for (List<String> row : results) {
for (String cell : row) {
sb.append(cell).append(" ");
}
sb.append("\n");
}
return sb.toString();

Check warning on line 159 in src/main/java/nl/knaw/dans/dvcli/command/NotificationTruncate.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/command/NotificationTruncate.java#L155-L159

Added lines #L155 - L159 were not covered by tests
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,14 @@
import io.dropwizard.core.Configuration;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NonNull;
import nl.knaw.dans.lib.util.DataverseClientFactory;

@Data
@EqualsAndHashCode(callSuper = true)
public class DdDataverseCliConfig extends Configuration {
private DataverseClientFactory dataverse;
private DataverseClientFactory api;

Check warning on line 28 in src/main/java/nl/knaw/dans/dvcli/config/DdDataverseCliConfig.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/config/DdDataverseCliConfig.java#L28

Added line #L28 was not covered by tests

@NonNull
private DdDataverseDatabaseConfig db = new DdDataverseDatabaseConfig();

Check warning on line 31 in src/main/java/nl/knaw/dans/dvcli/config/DdDataverseCliConfig.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/nl/knaw/dans/dvcli/config/DdDataverseCliConfig.java#L30-L31

Added lines #L30 - L31 were not covered by tests
}
Loading