From b603d4c9050ebfddc251c7453ca1341763ec193c Mon Sep 17 00:00:00 2001
From: Steven Winship <39765413+stevenwinship@users.noreply.github.com>
Date: Wed, 24 Jun 2026 15:15:57 -0400
Subject: [PATCH 1/4] Extend Search API to include isLinked
---
conf/solr/schema.xml | 1 +
...11845-extend-search-api-return-islinked.md | 2 +
.../edu/harvard/iq/dataverse/Dataset.java | 43 +++-----
.../edu/harvard/iq/dataverse/Dataverse.java | 42 ++------
.../iq/dataverse/search/IndexServiceBean.java | 100 +++++-------------
.../iq/dataverse/search/SearchFields.java | 3 +
.../iq/dataverse/search/SolrSearchResult.java | 44 ++++----
.../search/SolrSearchServiceBean.java | 30 ++----
.../iq/dataverse/util/json/JsonPrinter.java | 12 +++
.../edu/harvard/iq/dataverse/api/LinkIT.java | 38 +++++--
10 files changed, 130 insertions(+), 185 deletions(-)
create mode 100644 doc/release-notes/11845-extend-search-api-return-islinked.md
diff --git a/conf/solr/schema.xml b/conf/solr/schema.xml
index 4d65b378485..905177d8c68 100644
--- a/conf/solr/schema.xml
+++ b/conf/solr/schema.xml
@@ -208,6 +208,7 @@
+
diff --git a/doc/release-notes/11845-extend-search-api-return-islinked.md b/doc/release-notes/11845-extend-search-api-return-islinked.md
new file mode 100644
index 00000000000..32bb7a7432b
--- /dev/null
+++ b/doc/release-notes/11845-extend-search-api-return-islinked.md
@@ -0,0 +1,2 @@
+## Feature Request ##
+Search API now returns "isLinked" in the JSON response for datasets and collections that are linked. "isLinked" will also be returned in direct dataset and collection lookups. This attribute will only be included when the value is true.
diff --git a/src/main/java/edu/harvard/iq/dataverse/Dataset.java b/src/main/java/edu/harvard/iq/dataverse/Dataset.java
index 39dccdcd4ea..124ba1817f5 100644
--- a/src/main/java/edu/harvard/iq/dataverse/Dataset.java
+++ b/src/main/java/edu/harvard/iq/dataverse/Dataset.java
@@ -8,38 +8,17 @@
import edu.harvard.iq.dataverse.makedatacount.DatasetExternalCitations;
import edu.harvard.iq.dataverse.makedatacount.DatasetMetrics;
import edu.harvard.iq.dataverse.settings.FeatureFlags;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.sql.Timestamp;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-import jakarta.persistence.CascadeType;
-import jakarta.persistence.ColumnResult;
-import jakarta.persistence.Entity;
-import jakarta.persistence.Index;
-import jakarta.persistence.JoinColumn;
-import jakarta.persistence.ManyToOne;
-import jakarta.persistence.NamedNativeQuery;
-import jakarta.persistence.NamedQueries;
-import jakarta.persistence.NamedQuery;
-import jakarta.persistence.OneToMany;
-import jakarta.persistence.OneToOne;
-import jakarta.persistence.OrderBy;
-import jakarta.persistence.SqlResultSetMapping;
-import jakarta.persistence.Table;
-import jakarta.persistence.Temporal;
-import jakarta.persistence.TemporalType;
-
import edu.harvard.iq.dataverse.settings.JvmSettings;
import edu.harvard.iq.dataverse.storageuse.StorageUse;
import edu.harvard.iq.dataverse.util.StringUtil;
import edu.harvard.iq.dataverse.util.SystemConfig;
+import jakarta.persistence.*;
+
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+import java.util.*;
/**
*
@@ -810,13 +789,17 @@ public HarvestingClient getHarvestedFrom() {
public void setHarvestedFrom(HarvestingClient harvestingClientConfig) {
this.harvestedFrom = harvestingClientConfig;
}
-
+
public boolean isHarvested() {
return this.harvestedFrom != null;
}
+ public boolean isLinked() {
+ return (datasetLinkingDataverses != null && datasetLinkingDataverses.size() > 0);
+ }
+
private String harvestIdentifier;
-
+
public String getHarvestIdentifier() {
return harvestIdentifier;
}
diff --git a/src/main/java/edu/harvard/iq/dataverse/Dataverse.java b/src/main/java/edu/harvard/iq/dataverse/Dataverse.java
index 31919398530..29a429f0034 100644
--- a/src/main/java/edu/harvard/iq/dataverse/Dataverse.java
+++ b/src/main/java/edu/harvard/iq/dataverse/Dataverse.java
@@ -1,44 +1,16 @@
package edu.harvard.iq.dataverse;
-import edu.harvard.iq.dataverse.dataverse.featured.DataverseFeaturedItem;
-import edu.harvard.iq.dataverse.harvest.client.HarvestingClient;
import edu.harvard.iq.dataverse.authorization.DataverseRole;
import edu.harvard.iq.dataverse.dataset.DatasetType;
+import edu.harvard.iq.dataverse.harvest.client.HarvestingClient;
import edu.harvard.iq.dataverse.search.savedsearch.SavedSearch;
import edu.harvard.iq.dataverse.storageuse.StorageUse;
import edu.harvard.iq.dataverse.util.BundleUtil;
import edu.harvard.iq.dataverse.util.SystemConfig;
+import jakarta.persistence.*;
+import jakarta.validation.constraints.*;
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Objects;
-import java.util.Set;
-import jakarta.persistence.CascadeType;
-import jakarta.persistence.CollectionTable;
-import jakarta.persistence.Column;
-import jakarta.persistence.ElementCollection;
-import jakarta.persistence.Entity;
-import jakarta.persistence.EnumType;
-import jakarta.persistence.Enumerated;
-import jakarta.persistence.FetchType;
-import jakarta.persistence.Index;
-import jakarta.persistence.JoinColumn;
-import jakarta.persistence.JoinTable;
-import jakarta.persistence.ManyToMany;
-import jakarta.persistence.ManyToOne;
-import jakarta.persistence.NamedQueries;
-import jakarta.persistence.NamedQuery;
-import jakarta.persistence.OneToMany;
-import jakarta.persistence.OneToOne;
-import jakarta.persistence.OrderBy;
-import jakarta.persistence.Table;
-import jakarta.validation.constraints.NotBlank;
-import jakarta.validation.constraints.NotEmpty;
-import jakarta.validation.constraints.NotNull;
-import jakarta.validation.constraints.Pattern;
-import jakarta.validation.constraints.Size;
+import java.util.*;
/**
*
@@ -327,7 +299,11 @@ public List getDatasetLinkingDataverses() {
public void setDatasetLinkingDataverses(List datasetLinkingDataverses) {
this.datasetLinkingDataverses = datasetLinkingDataverses;
}
-
+
+ public boolean isLinked() {
+ return (dataverseLinkingDataverses != null && dataverseLinkingDataverses.size() > 0);
+ }
+
public Set getDataverseSubjects() {
return dataverseSubjects;
}
diff --git a/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java
index 8132c5e113d..443a8ac83f8 100644
--- a/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java
+++ b/src/main/java/edu/harvard/iq/dataverse/search/IndexServiceBean.java
@@ -1,37 +1,8 @@
package edu.harvard.iq.dataverse.search;
-import edu.harvard.iq.dataverse.ControlledVocabularyValue;
-import edu.harvard.iq.dataverse.CurationStatus;
-import edu.harvard.iq.dataverse.DataFile;
-import edu.harvard.iq.dataverse.DataFileServiceBean;
-import edu.harvard.iq.dataverse.DataFileTag;
-import edu.harvard.iq.dataverse.DataTable;
-import edu.harvard.iq.dataverse.Dataset;
-import edu.harvard.iq.dataverse.DatasetField;
-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.DatasetFieldValue;
-import edu.harvard.iq.dataverse.DatasetFieldValueValidator;
-import edu.harvard.iq.dataverse.DatasetLinkingServiceBean;
-import edu.harvard.iq.dataverse.DatasetServiceBean;
-import edu.harvard.iq.dataverse.DatasetVersion;
+import edu.harvard.iq.dataverse.*;
import edu.harvard.iq.dataverse.DatasetVersion.VersionState;
-import edu.harvard.iq.dataverse.DatasetVersionFilesServiceBean;
-import edu.harvard.iq.dataverse.DatasetVersionServiceBean;
-import edu.harvard.iq.dataverse.Dataverse;
-import edu.harvard.iq.dataverse.DataverseLinkingServiceBean;
-import edu.harvard.iq.dataverse.DataverseServiceBean;
-import edu.harvard.iq.dataverse.DvObject;
import edu.harvard.iq.dataverse.DvObject.DType;
-import edu.harvard.iq.dataverse.DvObjectServiceBean;
-import edu.harvard.iq.dataverse.Embargo;
-import edu.harvard.iq.dataverse.FileMetadata;
-import edu.harvard.iq.dataverse.GlobalId;
-import edu.harvard.iq.dataverse.PermissionServiceBean;
-import edu.harvard.iq.dataverse.Retention;
-import edu.harvard.iq.dataverse.TermsOfUseAndAccess;
import edu.harvard.iq.dataverse.authorization.AuthenticationServiceBean;
import edu.harvard.iq.dataverse.authorization.providers.builtin.BuiltinUserServiceBean;
import edu.harvard.iq.dataverse.batch.util.LoggingUtil;
@@ -50,51 +21,12 @@
import edu.harvard.iq.dataverse.util.FileUtil;
import edu.harvard.iq.dataverse.util.StringUtil;
import edu.harvard.iq.dataverse.util.SystemConfig;
-import java.io.IOException;
-import java.io.InputStream;
-import java.sql.Timestamp;
-import java.text.SimpleDateFormat;
-import java.time.LocalDate;
-import java.time.ZoneOffset;
-import java.time.format.DateTimeFormatter;
-import java.time.format.DateTimeParseException;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Collection;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.HashSet;
-import java.util.LinkedHashMap;
-import java.util.List;
-import java.util.Locale;
-import java.util.Map;
-import java.util.Set;
-import java.util.concurrent.ConcurrentHashMap;
-import java.util.concurrent.Future;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.atomic.AtomicReference;
-import java.util.function.Function;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-import jakarta.ejb.AsyncResult;
-import jakarta.ejb.Asynchronous;
-import jakarta.ejb.EJB;
-import jakarta.ejb.EJBException;
-import jakarta.ejb.Stateless;
-import jakarta.ejb.TransactionAttribute;
-
-import static jakarta.ejb.TransactionAttributeType.REQUIRES_NEW;
-
+import jakarta.ejb.*;
import jakarta.inject.Inject;
import jakarta.inject.Named;
import jakarta.json.JsonObject;
import jakarta.persistence.EntityManager;
import jakarta.persistence.PersistenceContext;
-import jakarta.persistence.Query;
-
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
@@ -107,8 +39,8 @@
import org.apache.solr.common.SolrDocumentList;
import org.apache.solr.common.SolrInputDocument;
import org.apache.solr.common.params.CursorMarkParams;
-import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.metadata.Metadata;
+import org.apache.tika.parser.AutoDetectParser;
import org.apache.tika.parser.ParseContext;
import org.apache.tika.sax.BodyContentHandler;
import org.eclipse.microprofile.metrics.MetricUnits;
@@ -116,6 +48,27 @@
import org.eclipse.microprofile.metrics.annotation.Metric;
import org.xml.sax.ContentHandler;
+import java.io.IOException;
+import java.io.InputStream;
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+import java.time.LocalDate;
+import java.time.ZoneOffset;
+import java.time.format.DateTimeFormatter;
+import java.time.format.DateTimeParseException;
+import java.util.*;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.Future;
+import java.util.concurrent.Semaphore;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.function.Function;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
+
+import static jakarta.ejb.TransactionAttributeType.REQUIRES_NEW;
+
@Stateless
@Named
public class IndexServiceBean {
@@ -248,6 +201,9 @@ public Future indexDataverse(Dataverse dataverse, boolean processPaths)
solrInputDocument.addField(SearchFields.METADATA_SOURCE, rootDataverse.getName()); //rootDataverseName);
/*}*/
+ solrInputDocument.addField(SearchFields.IS_LINKED, dataverse.isLinked());
+
+
addDataverseReleaseDateToSolrDoc(solrInputDocument, dataverse);
// if (dataverse.getOwner() != null) {
// solrInputDocument.addField(SearchFields.HOST_DATAVERSE,
@@ -1063,6 +1019,8 @@ public SolrInputDocuments toSolrDocs(IndexableDataset indexableDataset, Set collections;
+ private Boolean isLinked;
+
// private boolean statePublished;
/**
* @todo Investigate/remove this "unpublishedState" variable. For files that
@@ -582,9 +576,10 @@ public JsonObjectBuilder json(boolean showRelevance, boolean showEntityIds, bool
.add("restricted", this.fileRestricted)
.add("variables", this.tabularDataCount)
.add("observations", this.observations)
- .add("canDownloadFile", this.canDownloadFile);
+ .add("canDownloadFile", this.canDownloadFile)
+ .add("isLinked", this.isLinked);
- // Now that nullSafeJsonBuilder has been instatiated, check for null before adding to it!
+ // Now that nullSafeJsonBuilder has been instantiated, check for null before adding to it!
if (showRelevance) {
nullSafeJsonBuilder.add("matches", getRelevance());
nullSafeJsonBuilder.add("score", getScore());
@@ -1135,6 +1130,15 @@ public Boolean getFileRestricted() {
public void setFileRestricted(Boolean fileRestricted) {
this.fileRestricted = fileRestricted;
}
+
+ public Boolean isLinked() {
+ return isLinked;
+ }
+
+ public void setLinked(Boolean isLinked) {
+ this.isLinked = isLinked;
+ }
+
public Boolean getCanDownloadFile() {
return canDownloadFile;
}
diff --git a/src/main/java/edu/harvard/iq/dataverse/search/SolrSearchServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/search/SolrSearchServiceBean.java
index 401bd58a70b..a25375073c4 100644
--- a/src/main/java/edu/harvard/iq/dataverse/search/SolrSearchServiceBean.java
+++ b/src/main/java/edu/harvard/iq/dataverse/search/SolrSearchServiceBean.java
@@ -12,34 +12,13 @@
import edu.harvard.iq.dataverse.settings.FeatureFlags;
import edu.harvard.iq.dataverse.util.BundleUtil;
import edu.harvard.iq.dataverse.util.SystemConfig;
-import java.io.IOException;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Calendar;
-import java.util.Collections;
-import java.util.Date;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.LinkedList;
-import java.util.List;
-import java.util.ListIterator;
-import java.util.Map;
-import java.util.Optional;
-import java.util.Set;
-import java.util.MissingResourceException;
-import java.util.logging.Level;
-import java.util.logging.Logger;
import jakarta.ejb.EJB;
import jakarta.ejb.EJBTransactionRolledbackException;
import jakarta.ejb.Stateless;
import jakarta.ejb.TransactionRolledbackLocalException;
import jakarta.inject.Inject;
import jakarta.inject.Named;
-import jakarta.json.Json;
-import jakarta.json.JsonArrayBuilder;
import jakarta.persistence.NoResultException;
-
import org.apache.commons.lang3.StringUtils;
import org.apache.solr.client.solrj.SolrQuery;
import org.apache.solr.client.solrj.SolrQuery.SortClause;
@@ -52,6 +31,12 @@
import org.apache.solr.common.SolrDocument;
import org.apache.solr.common.SolrDocumentList;
+import java.io.IOException;
+import java.lang.reflect.Field;
+import java.util.*;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
@Stateless
@Named
public class SolrSearchServiceBean implements SearchService {
@@ -544,6 +529,9 @@ public SolrQueryResponse search(
if (Boolean.TRUE.equals((Boolean) solrDocument.getFieldValue(SearchFields.IS_HARVESTED))) {
solrSearchResult.setHarvested(true);
}
+ if (Boolean.TRUE.equals(solrDocument.getFieldValue(SearchFields.IS_LINKED))) {
+ solrSearchResult.setLinked(true);
+ }
solrSearchResult.setEmbargoEndDate(embargoEndDate);
solrSearchResult.setRetentionEndDate(retentionEndDate);
diff --git a/src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java b/src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java
index 55247f7d2af..d6b3c20f32e 100644
--- a/src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java
+++ b/src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java
@@ -359,6 +359,10 @@ public static JsonObjectBuilder json(Dataverse dv, Boolean hideEmail, Boolean re
bld.add("effectiveRequiresFilesToPublishDataset", dv.getEffectiveRequiresFilesToPublishDataset());
bld.add("isReleased", dv.isReleased());
+ if (dv.isLinked()) {
+ bld.add("isLinked", true);
+ }
+
List inputLevels = dv.getDataverseFieldTypeInputLevels();
if (!inputLevels.isEmpty()) {
bld.add("inputLevels", JsonPrinter.jsonDataverseFieldTypeInputLevels(inputLevels));
@@ -613,6 +617,10 @@ public static JsonObjectBuilder json(Dataset ds, Boolean returnOwners) {
}
bld.add("datasetType", ds.getDatasetType().getName());
+ if (ds.isLinked()) {
+ bld.add("isLinked", true);
+ }
+
JsonArrayBuilder locksArrayBuilder = Json.createArrayBuilder();
for (DatasetLock lock : ds.getLocks()) {
locksArrayBuilder.add(lock.getReason().toString());
@@ -680,6 +688,10 @@ public static JsonObjectBuilder json(DatasetVersion dsv, List anonymized
.add("publicationDate", dataset.getPublicationDateFormattedYYYYMMDD())
.add("citationDate", dataset.getCitationDateFormattedYYYYMMDD())
.add("versionNote", dsv.getVersionNote());
+
+ if (dsv.getDataset().isLinked()) {
+ bld.add("isLinked", true);
+ }
if (dataset.getGuestbook() != null) {
bld.add("guestbookId", dataset.getGuestbook().getId());
}
diff --git a/src/test/java/edu/harvard/iq/dataverse/api/LinkIT.java b/src/test/java/edu/harvard/iq/dataverse/api/LinkIT.java
index dfc132c3b3f..6ea27fe07a2 100644
--- a/src/test/java/edu/harvard/iq/dataverse/api/LinkIT.java
+++ b/src/test/java/edu/harvard/iq/dataverse/api/LinkIT.java
@@ -3,22 +3,19 @@
import io.restassured.RestAssured;
import io.restassured.path.json.JsonPath;
import io.restassured.response.Response;
+import jakarta.json.Json;
+import jakarta.json.JsonArray;
+import jakarta.json.JsonObject;
+import org.junit.jupiter.api.BeforeAll;
+import org.junit.jupiter.api.Test;
import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.List;
import java.util.logging.Logger;
import static jakarta.ws.rs.core.Response.Status.*;
-import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
-import static org.junit.jupiter.api.Assertions.*;
-
-import jakarta.json.Json;
-import jakarta.json.JsonArray;
-import jakarta.json.JsonObject;
-import org.junit.jupiter.api.BeforeAll;
-import org.junit.jupiter.api.Test;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
public class LinkIT {
@@ -88,6 +85,13 @@ public void testLinkedDataset() {
assertEquals("Darwin's Finches", JsonPath.from(getLinksResponse.asString()).getString("data.linkedDatasets[0].title"));
assertEquals(datasetPid, JsonPath.from(getLinksResponse.asString()).getString("data.linkedDatasets[0].identifier"));
+ // Test that search shows the "isLinked" attribute in the result
+ Response searchResponse = UtilIT.search("id:dataset_" + datasetId + "_draft", superuserApiToken);
+ searchResponse.prettyPrint();
+ searchResponse.then().assertThat()
+ .statusCode(OK.getStatusCode())
+ .body("data.items[0].isLinked", equalTo(true));
+
// A dataset cannot be linked to its parent dataverse.
Response tryToLinkToParentDataverse = UtilIT.linkDataset(datasetPid, dataverse1Alias, superuserApiToken);
tryToLinkToParentDataverse.prettyPrint();
@@ -150,11 +154,25 @@ public void testCreateDeleteDataverseLink() {
.body("data.linkedDataverses[0].alias", equalTo(dataverseAlias))
.body("data.linkedDataverses[0].displayName", equalTo(dataverseAlias));
+ // Test that search shows the "isLinked" attribute in the result
+ Response searchResponse = UtilIT.search("dvAlias:" + dataverseAlias, apiToken);
+ searchResponse.prettyPrint();
+ searchResponse.then().assertThat()
+ .statusCode(OK.getStatusCode())
+ .body("data.items[0].isLinked", equalTo(true));
+
Response deleteLinkingDataverseResponse = UtilIT.deleteDataverseLink(dataverseAlias, dataverseAlias2, apiToken);
deleteLinkingDataverseResponse.prettyPrint();
deleteLinkingDataverseResponse.then().assertThat()
.statusCode(OK.getStatusCode())
.body("data.message", equalTo("Link from Dataverse " + dataverseAlias + " to linked Dataverse " + dataverseAlias2 + " deleted"));
+
+ // Test that search no longer shows the "isLinked" attribute in the result
+ searchResponse = UtilIT.search("dvAlias:" + dataverseAlias, apiToken);
+ searchResponse.prettyPrint();
+ searchResponse.then().assertThat()
+ .statusCode(OK.getStatusCode())
+ .body("data.items[0].isLinked", equalTo(null));
}
@Test
From 23c94aec182080a72d9ad729a029f14cabf4c8e0 Mon Sep 17 00:00:00 2001
From: Steven Winship <39765413+stevenwinship@users.noreply.github.com>
Date: Wed, 8 Jul 2026 12:05:55 -0400
Subject: [PATCH 2/4] adding back the LinkIT tests even though they are now
failing
---
.../edu/harvard/iq/dataverse/api/LinkIT.java | 27 ++++++++++++++-----
1 file changed, 21 insertions(+), 6 deletions(-)
diff --git a/src/test/java/edu/harvard/iq/dataverse/api/LinkIT.java b/src/test/java/edu/harvard/iq/dataverse/api/LinkIT.java
index a8658efa076..daa774e6d7f 100644
--- a/src/test/java/edu/harvard/iq/dataverse/api/LinkIT.java
+++ b/src/test/java/edu/harvard/iq/dataverse/api/LinkIT.java
@@ -5,12 +5,8 @@
import io.restassured.response.Response;
import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.logging.Logger;
import static jakarta.ws.rs.core.Response.Status.*;
-import static org.hamcrest.CoreMatchers.containsString;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.jupiter.api.Assertions.*;
@@ -22,8 +18,6 @@
public class LinkIT {
- private static final Logger logger = Logger.getLogger(LinkIT.class.getCanonicalName());
-
@BeforeAll
public static void setUpClass() {
RestAssured.baseURI = UtilIT.getRestAssuredBaseUri();
@@ -88,6 +82,13 @@ public void testLinkedDataset() {
assertEquals("Darwin's Finches", JsonPath.from(getLinksResponse.asString()).getString("data.linkedDatasets[0].title"));
assertEquals(datasetPid, JsonPath.from(getLinksResponse.asString()).getString("data.linkedDatasets[0].identifier"));
+ // Test that search shows the "isLinked" attribute in the result
+ Response searchResponse = UtilIT.search("id:dataset_" + datasetId + "_draft", superuserApiToken);
+ searchResponse.prettyPrint();
+ searchResponse.then().assertThat()
+ .statusCode(OK.getStatusCode())
+ .body("data.items[0].isLinked", equalTo(true));
+
// A dataset cannot be linked to its parent dataverse.
Response tryToLinkToParentDataverse = UtilIT.linkDataset(datasetPid, dataverse1Alias, superuserApiToken);
tryToLinkToParentDataverse.prettyPrint();
@@ -176,11 +177,25 @@ public void testCreateDeleteDataverseLink() {
// Undo superuser status to test that it's not required for deleting a link
UtilIT.setSuperuserStatus(username1, false);
+ // Test that search shows the "isLinked" attribute in the result
+ Response searchResponse = UtilIT.search("dvAlias:" + dataverse1Alias, apiToken1);
+ searchResponse.prettyPrint();
+ searchResponse.then().assertThat()
+ .statusCode(OK.getStatusCode())
+ .body("data.items[0].isLinked", equalTo(true));
+
Response deleteLinkingDataverseResponse = UtilIT.deleteDataverseLink(dataverse1Alias, dataverse2Alias, apiToken1);
deleteLinkingDataverseResponse.prettyPrint();
deleteLinkingDataverseResponse.then().assertThat()
.statusCode(OK.getStatusCode())
.body("data.message", equalTo("Link from Dataverse " + dataverse2Alias + " to linked Dataverse " + dataverse1Alias + " deleted"));
+
+ // Test that search no longer shows the "isLinked" attribute in the result
+ searchResponse = UtilIT.search("dvAlias:" + dataverse1Alias, apiToken1);
+ searchResponse.prettyPrint();
+ searchResponse.then().assertThat()
+ .statusCode(OK.getStatusCode())
+ .body("data.items[0].isLinked", equalTo(null));
}
@Test
From fe2c8ad8fa5716b3e026115d7516da48d63949e4 Mon Sep 17 00:00:00 2001
From: Steven Winship <39765413+stevenwinship@users.noreply.github.com>
Date: Thu, 9 Jul 2026 10:29:43 -0400
Subject: [PATCH 3/4] refactor due to merge conflicts and bug in delete
---
.../iq/dataverse/api/AbstractApiBean.java | 10 +++---
.../harvard/iq/dataverse/api/Dataverses.java | 4 +--
...eleteDataverseLinkingDataverseCommand.java | 35 ++++++-------------
.../savedsearch/SavedSearchServiceBean.java | 2 +-
4 files changed, 19 insertions(+), 32 deletions(-)
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 a23e2a92c07..fff7c280788 100644
--- a/src/main/java/edu/harvard/iq/dataverse/api/AbstractApiBean.java
+++ b/src/main/java/edu/harvard/iq/dataverse/api/AbstractApiBean.java
@@ -417,19 +417,19 @@ protected Template findTemplateInDataverseOrParentsOrDie(Long templateId, Datave
return template;
}
- protected DataverseLinkingDataverse findDataverseLinkingDataverseOrDie(String dataverseId, String linkedDataverseId) throws WrappedResponse {
+ protected DataverseLinkingDataverse findDataverseLinkingDataverseOrDie(String linkingDataverseId, String linkedDataverseId) throws WrappedResponse {
DataverseLinkingDataverse dvld;
- Dataverse dataverse = findDataverseOrDie(dataverseId);
+ Dataverse linkingDataverse = findDataverseOrDie(linkingDataverseId);
Dataverse linkedDataverse = findDataverseOrDie(linkedDataverseId);
try {
- dvld = dvLinkingService.findDataverseLinkingDataverse(dataverse.getId(), linkedDataverse.getId());
+ dvld = dvLinkingService.findDataverseLinkingDataverse(linkingDataverse.getId(), linkedDataverse.getId());
if (dvld == null) {
- throw new WrappedResponse(notFound(BundleUtil.getStringFromBundle("find.dataverselinking.error.not.found.ids", Arrays.asList(dataverseId, linkedDataverseId))));
+ throw new WrappedResponse(notFound(BundleUtil.getStringFromBundle("find.dataverselinking.error.not.found.ids", Arrays.asList(linkingDataverseId, linkedDataverseId))));
}
return dvld;
} catch (NumberFormatException nfe) {
throw new WrappedResponse(
- badRequest(BundleUtil.getStringFromBundle("find.dataverselinking.error.not.found.bad.ids", Arrays.asList(dataverseId, linkedDataverseId))));
+ badRequest(BundleUtil.getStringFromBundle("find.dataverselinking.error.not.found.bad.ids", Arrays.asList(linkingDataverseId, linkedDataverseId))));
}
}
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 85a41a836ee..a3960170b6d 100644
--- a/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java
+++ b/src/main/java/edu/harvard/iq/dataverse/api/Dataverses.java
@@ -859,7 +859,7 @@ private List parseFacets(JsonArray facetsArray) throws Wrapped
public Response deleteDataverseLinkingDataverse(@Context ContainerRequestContext crc, @PathParam("linkingDataverseId") String linkingDataverseId, @PathParam("linkedDataverseId") String linkedDataverseId) {
boolean index = true;
return response(req -> {
- execCommand(new DeleteDataverseLinkingDataverseCommand(req, findDataverseOrDie(linkingDataverseId), findDataverseLinkingDataverseOrDie(linkingDataverseId, linkedDataverseId), index));
+ execCommand(new DeleteDataverseLinkingDataverseCommand(req, findDataverseOrDie(linkedDataverseId), findDataverseLinkingDataverseOrDie(linkingDataverseId, linkedDataverseId), index));
return ok("Link from Dataverse " + linkingDataverseId + " to linked Dataverse " + linkedDataverseId + " deleted");
}, getRequestUser(crc));
}
@@ -2390,4 +2390,4 @@ private Set validateLocallyFairRoleAssigneeIdentifiers(List role
return validatedIdentifiers;
}
-}
\ No newline at end of file
+}
diff --git a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataverseLinkingDataverseCommand.java b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataverseLinkingDataverseCommand.java
index 33f88d8d768..f9317540042 100644
--- a/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataverseLinkingDataverseCommand.java
+++ b/src/main/java/edu/harvard/iq/dataverse/engine/command/impl/DeleteDataverseLinkingDataverseCommand.java
@@ -8,17 +8,14 @@
import edu.harvard.iq.dataverse.Dataverse;
import edu.harvard.iq.dataverse.DataverseLinkingDataverse;
import edu.harvard.iq.dataverse.authorization.Permission;
-import edu.harvard.iq.dataverse.authorization.users.AuthenticatedUser;
import edu.harvard.iq.dataverse.batch.util.LoggingUtil;
import edu.harvard.iq.dataverse.engine.command.AbstractCommand;
import edu.harvard.iq.dataverse.engine.command.CommandContext;
import edu.harvard.iq.dataverse.engine.command.DataverseRequest;
import edu.harvard.iq.dataverse.engine.command.RequiredPermissions;
import edu.harvard.iq.dataverse.engine.command.exception.CommandException;
-import edu.harvard.iq.dataverse.engine.command.exception.PermissionException;
import java.io.IOException;
-import java.util.Collections;
-import java.util.concurrent.Future;
+
import org.apache.solr.client.solrj.SolrServerException;
/**
@@ -30,40 +27,30 @@
public class DeleteDataverseLinkingDataverseCommand extends AbstractCommand {
private final DataverseLinkingDataverse doomed;
- private final Dataverse editedDv;
+ private final Dataverse linkedDataverse;
private final boolean index;
- public DeleteDataverseLinkingDataverseCommand(DataverseRequest aRequest, Dataverse editedDv , DataverseLinkingDataverse doomed, boolean index) {
- super(aRequest, editedDv);
- this.editedDv = editedDv;
+ public DeleteDataverseLinkingDataverseCommand(DataverseRequest aRequest, Dataverse linkedDataverse , DataverseLinkingDataverse doomed, boolean index) {
+ super(aRequest, linkedDataverse);
+ this.linkedDataverse = linkedDataverse;
this.doomed = doomed;
this.index = index;
}
@Override
public Dataverse execute(CommandContext ctxt) throws CommandException {
- Dataverse merged = ctxt.em().merge(editedDv);
- DataverseLinkingDataverse doomedAndMerged = ctxt.em().merge(doomed);
- ctxt.em().remove(doomedAndMerged);
-
- if (index) {
- //can only index merged in the onSuccess method so must index doomed linking dataverse here
- try {
- ctxt.index().indexDataverse(doomed.getLinkingDataverse());
- } catch (IOException | SolrServerException e) {
- String failureLogText = "Indexing failed for Linked Dataverse. You can kickoff a re-index of this datavese with: \r\n curl http://localhost:8080/api/admin/index/datasets/" + doomed.getLinkingDataverse().getId().toString();
- failureLogText += "\r\n" + e.getLocalizedMessage();
- LoggingUtil.writeOnSuccessFailureLog(this, failureLogText, doomed.getLinkingDataverse());
- }
- }
- return merged;
+ ctxt.em().remove(doomed);
+ return linkedDataverse;
}
@Override
public boolean onSuccess(CommandContext ctxt, Object r) {
try {
- Future retVal = ctxt.index().indexDataverse((Dataverse) r);
+ if (index) {
+ ctxt.index().indexDataverse(doomed.getDataverse());
+ ctxt.index().indexDataverse(doomed.getLinkingDataverse());
+ }
} catch (IOException | SolrServerException e) {
Dataverse dv = (Dataverse) r;
String failureLogText = "Indexing failed for Dataverse delinking. You can kickoff a re-index of this datavese with: \r\n curl http://localhost:8080/api/admin/index/datasets/" + dv.getId().toString();
diff --git a/src/main/java/edu/harvard/iq/dataverse/search/savedsearch/SavedSearchServiceBean.java b/src/main/java/edu/harvard/iq/dataverse/search/savedsearch/SavedSearchServiceBean.java
index fcb423fa492..7dd14876a8c 100644
--- a/src/main/java/edu/harvard/iq/dataverse/search/savedsearch/SavedSearchServiceBean.java
+++ b/src/main/java/edu/harvard/iq/dataverse/search/savedsearch/SavedSearchServiceBean.java
@@ -278,7 +278,7 @@ public void removeLinks(DataverseRequest dvReq, SavedSearch savedSearch) throws
Dataverse linkedDataverse = (Dataverse) dvObjectThatDefinitionPointWillLinkTo;
DataverseLinkingDataverse dvld = dvLinkingService.findDataverseLinkingDataverse(linkingDataverse.getId(), linkedDataverse.getId());
if(dvld != null) {
- Dataverse dv = commandEngine.submitInNewTransaction(new DeleteDataverseLinkingDataverseCommand(dvReq, linkingDataverse, dvld, true));
+ Dataverse dv = commandEngine.submitInNewTransaction(new DeleteDataverseLinkingDataverseCommand(dvReq, linkedDataverse, dvld, true));
}
} else if (dvObjectThatDefinitionPointWillLinkTo.isInstanceofDataset()) {
Dataset linkedDataset = (Dataset) dvObjectThatDefinitionPointWillLinkTo;
From 4c51d8656419d9efafad39c48afe443cf5171f9c Mon Sep 17 00:00:00 2001
From: Steven Winship <39765413+stevenwinship@users.noreply.github.com>
Date: Tue, 11 Aug 2026 16:27:36 -0400
Subject: [PATCH 4/4] fix bad merge
---
.../iq/dataverse/util/json/JsonPrinter.java | 134 +++++++++---------
1 file changed, 67 insertions(+), 67 deletions(-)
diff --git a/src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java b/src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java
index 55247f7d2af..f2716fe20d2 100644
--- a/src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java
+++ b/src/main/java/edu/harvard/iq/dataverse/util/json/JsonPrinter.java
@@ -101,7 +101,7 @@ public JsonPrinter() {
public static final BriefJsonPrinter brief = new BriefJsonPrinter();
public static JsonArrayBuilder asJsonArray(Collection strings) {
- JsonArrayBuilder arr = Json.createArrayBuilder();
+ JsonArrayBuilder arr = JsonUtil.createArrayBuilder();
for (String s : strings) {
arr.add(s);
}
@@ -145,7 +145,7 @@ public static JsonObjectBuilder json(FileAccessRequest fileAccessRequest) {
}
public static JsonArrayBuilder jsonRoleAssignments(List roleAssignments) {
- JsonArrayBuilder bld = Json.createArrayBuilder();
+ JsonArrayBuilder bld = JsonUtil.createArrayBuilder();
roleAssignments.forEach(roleAssignment -> bld.add(json(roleAssignment)));
return bld;
}
@@ -172,7 +172,7 @@ public static JsonObjectBuilder json(RoleAssignment ra) {
}
public static JsonArrayBuilder json(Set permissions) {
- JsonArrayBuilder bld = Json.createArrayBuilder();
+ JsonArrayBuilder bld = JsonUtil.createArrayBuilder();
permissions.forEach(p -> bld.add(p.name()));
return bld;
}
@@ -215,8 +215,8 @@ public static JsonObjectBuilder json(IpGroup grp) {
}
if ( ! ranges.isEmpty() ) {
- JsonArrayBuilder rangesBld = Json.createArrayBuilder();
- ranges.forEach( r -> rangesBld.add( Json.createArrayBuilder().add(r.get(0)).add(r.get(1))) );
+ JsonArrayBuilder rangesBld = JsonUtil.createArrayBuilder();
+ ranges.forEach( r -> rangesBld.add( JsonUtil.createArrayBuilder().add(r.get(0)).add(r.get(1))) );
bld.add("ranges", rangesBld );
}
@@ -243,7 +243,7 @@ public static JsonObjectBuilder json(MailDomainGroup grp) {
}
public static JsonArrayBuilder rolesToJson(List role) {
- JsonArrayBuilder bld = Json.createArrayBuilder();
+ JsonArrayBuilder bld = JsonUtil.createArrayBuilder();
for (DataverseRole r : role) {
bld.add(JsonPrinter.json(r));
}
@@ -251,7 +251,7 @@ public static JsonArrayBuilder rolesToJson(List role) {
}
public static JsonArrayBuilder enumsToJson(Collection collection) {
- JsonArrayBuilder arr = Json.createArrayBuilder();
+ JsonArrayBuilder arr = JsonUtil.createArrayBuilder();
for (E entry : collection) {
arr.add(entry.name());
}
@@ -259,7 +259,7 @@ public static JsonArrayBuilder enumsToJson(Collection collec
}
public static JsonArrayBuilder jsonDataverseRoles(List roles) {
- JsonArrayBuilder jsonArrayOfDataverseRoles = Json.createArrayBuilder();
+ JsonArrayBuilder jsonArrayOfDataverseRoles = JsonUtil.createArrayBuilder();
for (DataverseRole role : roles) {
jsonArrayOfDataverseRoles.add(json(role));
}
@@ -293,7 +293,7 @@ public static JsonObjectBuilder json(Workflow wf){
}
if ( wf.getSteps()!=null && !wf.getSteps().isEmpty()) {
- JsonArrayBuilder arr = Json.createArrayBuilder();
+ JsonArrayBuilder arr = JsonUtil.createArrayBuilder();
for ( WorkflowStepData stp : wf.getSteps() ) {
arr.add( jsonObjectBuilder().add("stepType", stp.getStepType())
.add("provider", stp.getProviderId())
@@ -369,7 +369,7 @@ public static JsonObjectBuilder json(Dataverse dv, Boolean hideEmail, Boolean re
}
List allowedDatasetTypes = dv.getAllowedDatasetTypes();
if (allowedDatasetTypes != null && !allowedDatasetTypes.isEmpty()) {
- JsonArrayBuilder jab = Json.createArrayBuilder();
+ JsonArrayBuilder jab = JsonUtil.createArrayBuilder();
for (DatasetType datasetType : allowedDatasetTypes) {
NullSafeJsonBuilder json = NullSafeJsonBuilder.jsonObjectBuilder()
.add("id", datasetType.getId())
@@ -385,9 +385,9 @@ public static JsonObjectBuilder json(Dataverse dv, Boolean hideEmail, Boolean re
}
public static JsonObjectBuilder jsonArray(List dataverses) {
- JsonObjectBuilder job = Json.createObjectBuilder();
+ JsonObjectBuilder job = JsonUtil.createObjectBuilder();
job.add("count", dataverses.size());
- JsonArrayBuilder jsonArrayBuilder = Json.createArrayBuilder();
+ JsonArrayBuilder jsonArrayBuilder = JsonUtil.createArrayBuilder();
for (Dataverse dataverse : dataverses) {
NullSafeJsonBuilder jsonObject = NullSafeJsonBuilder.jsonObjectBuilder();
jsonObject.add("id", dataverse.getId());
@@ -400,7 +400,7 @@ public static JsonObjectBuilder jsonArray(List dataverses) {
}
public static JsonArrayBuilder json(List dataverseContacts) {
- JsonArrayBuilder jsonArrayOfContacts = Json.createArrayBuilder();
+ JsonArrayBuilder jsonArrayOfContacts = JsonUtil.createArrayBuilder();
for (DataverseContact dataverseContact : dataverseContacts) {
NullSafeJsonBuilder contactJsonObject = NullSafeJsonBuilder.jsonObjectBuilder();
contactJsonObject.add("displayOrder", dataverseContact.getDisplayOrder());
@@ -441,7 +441,7 @@ public static JsonObjectBuilder json(GuestbookResponse gbResponse) {
}
final List cqResponses = gbResponse.getCustomQuestionResponses();
if (cqResponses != null && !cqResponses.isEmpty()) {
- JsonArrayBuilder customQuestions = Json.createArrayBuilder();
+ JsonArrayBuilder customQuestions = JsonUtil.createArrayBuilder();
for (CustomQuestionResponse cqResponse : cqResponses) {
JsonObjectBuilder cqObj = jsonObjectBuilder();
cqObj.add("question", cqResponse.getCustomQuestion().getQuestionString());
@@ -473,7 +473,7 @@ public static JsonObjectBuilder json(Guestbook guestbook) {
guestbookObject.add("responseCount", guestbook.getResponseCount());
}
if (guestbook.getCustomQuestions() != null && !guestbook.getCustomQuestions().isEmpty()) {
- JsonArrayBuilder customQuestions = Json.createArrayBuilder();
+ JsonArrayBuilder customQuestions = JsonUtil.createArrayBuilder();
for (CustomQuestion cq : guestbook.getCustomQuestions()) {
customQuestions.add(json(cq));
}
@@ -499,7 +499,7 @@ public static JsonObjectBuilder json(CustomQuestion customQuestion) {
customQuestionObject.add("type", customQuestion.getQuestionType());
customQuestionObject.add("hidden", customQuestion.isHidden());
if (customQuestion.getCustomQuestionValues() != null && !customQuestion.getCustomQuestionValues().isEmpty()) {
- JsonArrayBuilder customQuestionsValues = Json.createArrayBuilder();
+ JsonArrayBuilder customQuestionsValues = JsonUtil.createArrayBuilder();
for (CustomQuestionValue value : customQuestion.getCustomQuestionValues()) {
JsonObjectBuilder customQuestionValueObject = jsonObjectBuilder();
if (value.getId() != null) {
@@ -613,7 +613,7 @@ public static JsonObjectBuilder json(Dataset ds, Boolean returnOwners) {
}
bld.add("datasetType", ds.getDatasetType().getName());
- JsonArrayBuilder locksArrayBuilder = Json.createArrayBuilder();
+ JsonArrayBuilder locksArrayBuilder = JsonUtil.createArrayBuilder();
for (DatasetLock lock : ds.getLocks()) {
locksArrayBuilder.add(lock.getReason().toString());
}
@@ -638,8 +638,8 @@ private static void addDatasetFileCountLimit(DvObjectContainer dvo, JsonObjectBu
}
public static JsonObjectBuilder json(FileDetailsHolder ds) {
- return Json.createObjectBuilder().add(ds.getStorageID() ,
- Json.createObjectBuilder()
+ return JsonUtil.createObjectBuilder().add(ds.getStorageID() ,
+ JsonUtil.createObjectBuilder()
.add("id", ds.getStorageID() )
.add("hash", ds.getHash())
.add("mime",ds.getMime()));
@@ -773,7 +773,7 @@ public static JsonObjectBuilder jsonAsDatasetDto(DatasetVersion dsv) {
}
public static JsonArrayBuilder jsonFileMetadatas(Collection fmds) {
- JsonArrayBuilder filesArr = Json.createArrayBuilder();
+ JsonArrayBuilder filesArr = JsonUtil.createArrayBuilder();
for (FileMetadata fmd : fmds) {
filesArr.add(JsonPrinter.json(fmd));
}
@@ -828,7 +828,7 @@ public static JsonObjectBuilder json(MetadataBlock block, List fie
blockBld.add("displayName", block.getDisplayName());
blockBld.add("name", block.getName());
- final JsonArrayBuilder fieldsArray = Json.createArrayBuilder();
+ final JsonArrayBuilder fieldsArray = JsonUtil.createArrayBuilder();
Map cvocMap = (datasetFieldService==null) ? new HashMap() :datasetFieldService.getCVocConf(true);
List excludedFieldTypeList = new ArrayList<>();
// Exclude the Email field or override the exclusion of the Email field type based on the settings ExcludeEmailFromExport and ignoreSettingExcludeEmailFromExport
@@ -846,7 +846,7 @@ public static JsonArrayBuilder json(List metadataBlocks, boolean
}
public static JsonArrayBuilder json(List metadataBlocks, boolean returnDatasetFieldTypes, boolean printOnlyDisplayedOnCreateDatasetFieldTypes, Dataverse ownerDataverse, DatasetType datasetType) {
- JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
+ JsonArrayBuilder arrayBuilder = JsonUtil.createArrayBuilder();
for (MetadataBlock metadataBlock : metadataBlocks) {
arrayBuilder.add(returnDatasetFieldTypes ? json(metadataBlock, printOnlyDisplayedOnCreateDatasetFieldTypes, ownerDataverse, datasetType) : brief.json(metadataBlock));
}
@@ -867,7 +867,7 @@ public static JsonObject json(DatasetField dfv) {
if (dfv.isEmpty()) {
return null;
} else {
- JsonArrayBuilder fieldArray = Json.createArrayBuilder();
+ JsonArrayBuilder fieldArray = JsonUtil.createArrayBuilder();
Map cvocMap = (datasetFieldService==null) ? new HashMap() :datasetFieldService.getCVocConf(true);
DatasetFieldWalker.walk(dfv, new DatasetFieldsToJson(fieldArray), cvocMap);
JsonArray out = fieldArray.build();
@@ -890,7 +890,7 @@ public static JsonObjectBuilder json(MetadataBlock metadataBlock, boolean printO
List datasetFieldTypesList = metadataBlock.getDatasetFieldTypes();
Set datasetFieldTypes = filterOutDuplicateDatasetFieldTypes(datasetFieldTypesList);
- JsonObjectBuilder fieldsBuilder = Json.createObjectBuilder();
+ JsonObjectBuilder fieldsBuilder = JsonUtil.createObjectBuilder();
for (DatasetFieldType datasetFieldType : datasetFieldTypes) {
if (!datasetFieldType.isChild()) {
@@ -929,7 +929,7 @@ private static Set filterOutDuplicateDatasetFieldTypes(List fields) {
- JsonArrayBuilder fieldsJson = Json.createArrayBuilder();
+ JsonArrayBuilder fieldsJson = JsonUtil.createArrayBuilder();
for (DatasetFieldType field : fields) {
fieldsJson.add(JsonPrinter.json(field));
}
@@ -962,7 +962,7 @@ public static JsonObjectBuilder json(DatasetFieldType fld, Dataverse ownerDatave
if (fld.isControlledVocabulary()) {
// If the field has a controlled vocabulary,
// add all values to the resulting JSON
- JsonArrayBuilder jab = Json.createArrayBuilder();
+ JsonArrayBuilder jab = JsonUtil.createArrayBuilder();
for (ControlledVocabularyValue cvv : fld.getControlledVocabularyValues()) {
jab.add(cvv.getStrValue());
}
@@ -1132,7 +1132,7 @@ public static JsonObjectBuilder json(DataFile df, FileMetadata fileMetadata, boo
//Started from https://github.com/RENCI-NRIG/dataverse/, i.e. https://github.com/RENCI-NRIG/dataverse/commit/2b5a1225b42cf1caba85e18abfeb952171c6754a
public static JsonArrayBuilder jsonDT(List ldt) {
- JsonArrayBuilder ldtArr = Json.createArrayBuilder();
+ JsonArrayBuilder ldtArr = JsonUtil.createArrayBuilder();
for(DataTable dt: ldt){
ldtArr.add(JsonPrinter.json(dt));
}
@@ -1150,7 +1150,7 @@ public static JsonObjectBuilder json(DataTable dt) {
}
public static JsonArrayBuilder jsonDV(List dvl) {
- JsonArrayBuilder varArr = Json.createArrayBuilder();
+ JsonArrayBuilder varArr = JsonUtil.createArrayBuilder();
if(dvl!=null){
for (DataVariable dv: dvl){
varArr.add(JsonPrinter.json(dv));
@@ -1195,8 +1195,8 @@ public static JsonObjectBuilder json(DataVariable dv) {
}
private static JsonArrayBuilder jsonInvalidRanges(Collection invalidRanges) {
- JsonArrayBuilder invRanges = Json.createArrayBuilder();
- JsonObjectBuilder job = Json.createObjectBuilder();
+ JsonArrayBuilder invRanges = JsonUtil.createArrayBuilder();
+ JsonObjectBuilder job = JsonUtil.createObjectBuilder();
for (VariableRange vr: invalidRanges){
job.add("beginValue", vr.getBeginValue())
.add("hasBeginValueType", vr.getBeginValueType()!=null)
@@ -1216,8 +1216,8 @@ private static JsonArrayBuilder jsonInvalidRanges(Collection inva
}
private static JsonObjectBuilder jsonSumStat(Collection sumStat){
- //JsonArrayBuilder sumStatArr = Json.createArrayBuilder();
- JsonObjectBuilder sumStatObj = Json.createObjectBuilder();
+ //JsonArrayBuilder sumStatArr = JsonUtil.createArrayBuilder();
+ JsonObjectBuilder sumStatObj = JsonUtil.createObjectBuilder();
for (SummaryStatistic stat: sumStat){
String label = stat.getTypeLabel()==null ? "unknown":stat.getTypeLabel();
sumStatObj.add(label, stat.getValue());
@@ -1227,10 +1227,10 @@ private static JsonObjectBuilder jsonSumStat(Collection sumSta
private static JsonArrayBuilder jsonCatStat(Collection catStat){
- JsonArrayBuilder catArr = Json.createArrayBuilder();
+ JsonArrayBuilder catArr = JsonUtil.createArrayBuilder();
for (VariableCategory stat: catStat){
- JsonObjectBuilder catStatObj = Json.createObjectBuilder();
+ JsonObjectBuilder catStatObj = JsonUtil.createObjectBuilder();
catStatObj.add("label", stat.getLabel())
.add("value", stat.getValue())
.add("isMissing", stat.isMissing());
@@ -1243,10 +1243,10 @@ private static JsonArrayBuilder jsonCatStat(Collection catStat
}
private static JsonArrayBuilder jsonVarGroup(List varGroups) {
- JsonArrayBuilder vgArr = Json.createArrayBuilder();
+ JsonArrayBuilder vgArr = JsonUtil.createArrayBuilder();
for (VarGroup vg : varGroups) {
JsonObjectBuilder vgJson = jsonObjectBuilder().add("id", vg.getId()).add("label", vg.getLabel());
- JsonArrayBuilder jab = Json.createArrayBuilder();
+ JsonArrayBuilder jab = JsonUtil.createArrayBuilder();
for (DataVariable dvar : vg.getVarsInGroup()) {
jab.add(dvar.getId());
}
@@ -1257,7 +1257,7 @@ private static JsonArrayBuilder jsonVarGroup(List varGroups) {
}
private static JsonArrayBuilder jsonVarMetadata(Collection varMetadatas) {
- JsonArrayBuilder vmArr = Json.createArrayBuilder();
+ JsonArrayBuilder vmArr = JsonUtil.createArrayBuilder();
for (VariableMetadata vm : varMetadatas) {
JsonObjectBuilder vmJson = jsonObjectBuilder()
.add("id", vm.getId())
@@ -1272,13 +1272,13 @@ private static JsonArrayBuilder jsonVarMetadata(Collection var
.add("universe", vm.getUniverse())
.add("notes", vm.getNotes())
.add("categoryMetadatas",json(vm.getCategoriesMetadata()));
- JsonArrayBuilder jab = Json.createArrayBuilder();
+ JsonArrayBuilder jab = JsonUtil.createArrayBuilder();
}
return vmArr;
}
private static JsonArrayBuilder json(Collection categoriesMetadata) {
- JsonArrayBuilder cmArr = Json.createArrayBuilder();
+ JsonArrayBuilder cmArr = JsonUtil.createArrayBuilder();
for(CategoryMetadata cm: categoriesMetadata) {
JsonObjectBuilder job = jsonObjectBuilder()
.add("wFreq", cm.getWfreq())
@@ -1330,7 +1330,7 @@ private static JsonArrayBuilder getFileCategories(FileMetadata fmd) {
if (categories == null || categories.isEmpty()) {
return null;
}
- JsonArrayBuilder fileCategories = Json.createArrayBuilder();
+ JsonArrayBuilder fileCategories = JsonUtil.createArrayBuilder();
for (String category : categories) {
fileCategories.add(category);
}
@@ -1345,7 +1345,7 @@ public static JsonArrayBuilder getTabularFileTags(DataFile df) {
if (tags == null || tags.isEmpty()) {
return null;
}
- JsonArrayBuilder tabularTags = Json.createArrayBuilder();
+ JsonArrayBuilder tabularTags = JsonUtil.createArrayBuilder();
for (DataFileTag tag : tags) {
String label = tag.getTypeLabel();
if (label != null) {
@@ -1356,12 +1356,12 @@ public static JsonArrayBuilder getTabularFileTags(DataFile df) {
}
public static JsonObjectBuilder jsonLocallyFairRoleAssignees(Dataverse dataverse) {
- JsonArrayBuilder assignees = Json.createArrayBuilder();
+ JsonArrayBuilder assignees = JsonUtil.createArrayBuilder();
dataverse.getLocallyFAIRRoleAssigneeIdentifiers().stream()
.sorted()
.forEach(assignees::add);
- return Json.createObjectBuilder()
+ return JsonUtil.createObjectBuilder()
.add("dataverseId", dataverse.getId())
.add("dataverseAlias", dataverse.getAlias())
.add("locallyFairRoleAssignees", assignees);
@@ -1385,7 +1385,7 @@ private static class DatasetFieldsToJson implements DatasetFieldWalker.Listener
public void startField(DatasetField f) {
objectStack.push(jsonObjectBuilder());
// Invariant: all values are multiple. Differentiation between multiple and single is done at endField.
- valueArrStack.push(Json.createArrayBuilder());
+ valueArrStack.push(JsonUtil.createArrayBuilder());
DatasetFieldType typ = f.getDatasetFieldType();
objectStack.peek().add("typeName", typ.getName());
@@ -1396,7 +1396,7 @@ public void startField(DatasetField f) {
@Override
public void addExpandedValuesArray(DatasetField f) {
// Invariant: all values are multiple. Differentiation between multiple and single is done at endField.
- valueArrStack.push(Json.createArrayBuilder());
+ valueArrStack.push(JsonUtil.createArrayBuilder());
}
@Override
@@ -1448,7 +1448,7 @@ public void controlledVocabularyValue(ControlledVocabularyValue cvv) {
@Override
public void startCompoundValue(DatasetFieldCompoundValue dsfcv) {
- valueArrStack.push(Json.createArrayBuilder());
+ valueArrStack.push(JsonUtil.createArrayBuilder());
}
@Override
@@ -1490,7 +1490,7 @@ public static JsonObjectBuilder json(PrivateUrl privateUrl) {
}
public static JsonObjectBuilder json( ExplicitGroup eg ) {
- JsonArrayBuilder ras = Json.createArrayBuilder();
+ JsonArrayBuilder ras = JsonUtil.createArrayBuilder();
for (String u : eg.getContainedRoleAssgineeIdentifiers()) {
ras.add(u);
}
@@ -1504,7 +1504,7 @@ public static JsonObjectBuilder json( ExplicitGroup eg ) {
}
public static JsonArrayBuilder jsonDataverseFacets(List dataverseFacets) {
- JsonArrayBuilder dataverseFacetsJson = Json.createArrayBuilder();
+ JsonArrayBuilder dataverseFacetsJson = JsonUtil.createArrayBuilder();
for(DataverseFacet facet: dataverseFacets) {
dataverseFacetsJson.add(json(facet));
}
@@ -1550,7 +1550,7 @@ public static Collector stringsToJso
@Override
public Supplier supplier() {
- return () -> Json.createArrayBuilder();
+ return () -> JsonUtil.createArrayBuilder();
}
@Override
@@ -1561,7 +1561,7 @@ public BiConsumer accumulator() {
@Override
public BinaryOperator combiner() {
return (jab1, jab2) -> {
- JsonArrayBuilder retVal = Json.createArrayBuilder();
+ JsonArrayBuilder retVal = JsonUtil.createArrayBuilder();
jab1.build().forEach(retVal::add);
jab2.build().forEach(retVal::add);
return retVal;
@@ -1581,7 +1581,7 @@ public Set characteristics() {
}
public static JsonObjectBuilder json(Map map) {
- JsonObjectBuilder jsonObjectBuilder = Json.createObjectBuilder();
+ JsonObjectBuilder jsonObjectBuilder = JsonUtil.createObjectBuilder();
for (Map.Entry mapEntry : map.entrySet()) {
jsonObjectBuilder.add(mapEntry.getKey(), mapEntry.getValue());
}
@@ -1589,7 +1589,7 @@ public static JsonObjectBuilder json(Map map) {
}
public static JsonObjectBuilder jsonFileCountPerAccessStatusMap(Map map) {
- JsonObjectBuilder jsonObjectBuilder = Json.createObjectBuilder();
+ JsonObjectBuilder jsonObjectBuilder = JsonUtil.createObjectBuilder();
for (Map.Entry mapEntry : map.entrySet()) {
jsonObjectBuilder.add(mapEntry.getKey().toString(), mapEntry.getValue());
}
@@ -1597,7 +1597,7 @@ public static JsonObjectBuilder jsonFileCountPerAccessStatusMap(Map map) {
- JsonObjectBuilder jsonObjectBuilder = Json.createObjectBuilder();
+ JsonObjectBuilder jsonObjectBuilder = JsonUtil.createObjectBuilder();
for (Map.Entry mapEntry : map.entrySet()) {
jsonObjectBuilder.add(mapEntry.getKey().toString(), mapEntry.getValue());
}
@@ -1628,7 +1628,7 @@ public BinaryOperator> combiner() {
@Override
public Function, JsonArrayBuilder> finisher() {
return (l) -> {
- JsonArrayBuilder bld = Json.createArrayBuilder();
+ JsonArrayBuilder bld = JsonUtil.createArrayBuilder();
l.forEach( bld::add );
return bld;
};
@@ -1651,7 +1651,7 @@ public static String getMd5IfItExists(DataFile.ChecksumType checksumType, String
public static JsonObjectBuilder getChecksumTypeAndValue(DataFile.ChecksumType checksumType, String checksumValue) {
if (checksumType != null) {
- return Json.createObjectBuilder()
+ return JsonUtil.createObjectBuilder()
.add("type", checksumType.toString())
.add("value", checksumValue);
} else {
@@ -1681,8 +1681,8 @@ public static JsonObjectBuilder mapToObject(Map in) {
public static JsonObjectBuilder jsonLinkset(Dataset ds) {
return jsonObjectBuilder()
.add("anchor", ds.getPersistentURL())
- .add("cite-as", Json.createArrayBuilder().add(jsonObjectBuilder().add("href", ds.getPersistentURL())))
- .add("type", Json.createArrayBuilder().add(jsonObjectBuilder().add("href", "https://schema.org/AboutPage")))
+ .add("cite-as", JsonUtil.createArrayBuilder().add(jsonObjectBuilder().add("href", ds.getPersistentURL())))
+ .add("type", JsonUtil.createArrayBuilder().add(jsonObjectBuilder().add("href", "https://schema.org/AboutPage")))
.add("author", ds.getPersistentURL())
.add("protocol", ds.getProtocol())
.add("authority", ds.getAuthority())
@@ -1710,7 +1710,7 @@ private static JsonObjectBuilder jsonLicense(DatasetVersion dsv) {
}
public static JsonArrayBuilder jsonDataverseFieldTypeInputLevels(List inputLevels) {
- JsonArrayBuilder jsonArrayOfInputLevels = Json.createArrayBuilder();
+ JsonArrayBuilder jsonArrayOfInputLevels = JsonUtil.createArrayBuilder();
for (DataverseFieldTypeInputLevel inputLevel : inputLevels) {
NullSafeJsonBuilder inputLevelJsonObject = NullSafeJsonBuilder.jsonObjectBuilder();
inputLevelJsonObject.add("datasetFieldTypeName", inputLevel.getDatasetFieldType().getName());
@@ -1723,7 +1723,7 @@ public static JsonArrayBuilder jsonDataverseFieldTypeInputLevels(List inputLevels) {
- JsonArrayBuilder inputLevelsArrayBuilder = Json.createArrayBuilder();
+ JsonArrayBuilder inputLevelsArrayBuilder = JsonUtil.createArrayBuilder();
for (DataverseFieldTypeInputLevel inputLevel : inputLevels) {
inputLevelsArrayBuilder.add(jsonDataverseInputLevel(inputLevel));
}
@@ -1740,7 +1740,7 @@ private static JsonObjectBuilder jsonDataverseInputLevel(DataverseFieldTypeInput
}
public static JsonArrayBuilder jsonDataverseFeaturedItems(List dataverseFeaturedItems) {
- JsonArrayBuilder featuredItemsArrayBuilder = Json.createArrayBuilder();
+ JsonArrayBuilder featuredItemsArrayBuilder = JsonUtil.createArrayBuilder();
for (DataverseFeaturedItem dataverseFeaturedItem : dataverseFeaturedItems) {
featuredItemsArrayBuilder.add(json(dataverseFeaturedItem));
}
@@ -1779,7 +1779,7 @@ public static JsonObjectBuilder json(DataverseFeaturedItem dataverseFeaturedItem
}
public static JsonArrayBuilder jsonTemplates(List templates) {
- JsonArrayBuilder templatesArrayBuilder = Json.createArrayBuilder();
+ JsonArrayBuilder templatesArrayBuilder = JsonUtil.createArrayBuilder();
for (Template template : templates) {
templatesArrayBuilder.add(jsonTemplate(template));
}
@@ -1824,10 +1824,10 @@ public static JsonObjectBuilder jsonTermsOfUseAndAccess(TermsOfUseAndAccess term
}
public static JsonArrayBuilder jsonTemplateInstructions(Map templateInstructions) {
- JsonArrayBuilder jsonArrayBuilder = Json.createArrayBuilder();
+ JsonArrayBuilder jsonArrayBuilder = JsonUtil.createArrayBuilder();
for (Map.Entry entry : templateInstructions.entrySet()) {
- JsonObjectBuilder instructionObject = Json.createObjectBuilder()
+ JsonObjectBuilder instructionObject = JsonUtil.createObjectBuilder()
.add("instructionField", entry.getKey())
.add("instructionText", entry.getValue());
jsonArrayBuilder.add(instructionObject);
@@ -1849,7 +1849,7 @@ public static JsonObjectBuilder jsonStorageDriver(String storageDriverId) {
}
public static JsonArrayBuilder json(List notifications, AuthenticatedUser authenticatedUser, boolean inAppNotificationFormat) {
- JsonArrayBuilder notificationsArray = Json.createArrayBuilder();
+ JsonArrayBuilder notificationsArray = JsonUtil.createArrayBuilder();
for (UserNotification notification : notifications) {
NullSafeJsonBuilder notificationJson = jsonObjectBuilder();
@@ -1888,11 +1888,11 @@ public static JsonObjectBuilder jsonLanguage(String locale, String title) {
public static JsonArrayBuilder jsonLanguage(Map langMap) {
// returns an array of metadatalanguages
- return Json.createArrayBuilder(langMap.entrySet().stream().map(entry -> jsonLanguage(entry.getKey(), entry.getValue())).toList());
+ return JsonUtil.createArrayBuilder(langMap.entrySet().stream().map(entry -> jsonLanguage(entry.getKey(), entry.getValue())).toList());
}
public static JsonArrayBuilder jsonDatasetVersionSummaries(List summaries) {
- JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
+ JsonArrayBuilder arrayBuilder = JsonUtil.createArrayBuilder();
summaries.stream()
.filter(Objects::nonNull)
.map(JsonPrinter::json)
@@ -1934,7 +1934,7 @@ private static JsonObjectBuilder json(DatasetVersionSummary summary) {
}
public static JsonArrayBuilder jsonFileVersionSummaries(List differences) {
- JsonArrayBuilder arrayBuilder = Json.createArrayBuilder();
+ JsonArrayBuilder arrayBuilder = JsonUtil.createArrayBuilder();
differences.stream()
.filter(Objects::nonNull)
.map(diff -> jsonFileVersionDifference(diff).build())