Skip to content

Commit 6c17c9d

Browse files
authored
Merge pull request #11741 from IQSS/11710-find-dataverses-for-linking
11710 find dataverses for linking
2 parents 94fa2fb + 0982ff2 commit 6c17c9d

File tree

16 files changed

+951
-46
lines changed

16 files changed

+951
-46
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
### New API endpoint for retrieving a list of Dataverse Collections to which a given Dataset or Dataverse Collection may be linked
2+
3+
-The end point also takes in a search term which currently must be part of the collections' names.
4+
-The user calling this API must have Link Dataset or Link Dataverse permission on the Dataverse Collections returned.
5+
-If the Collection has already been linked to the given Dataset or Collection, it will not be returned.

doc/sphinx-guides/source/api/native-api.rst

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -732,6 +732,50 @@ Note: you must have "Add Dataset" permission in the given collection to invoke t
732732

733733
.. _featured-collections:
734734

735+
List Dataverse Collections to Which a Given Dataset or Dataverse Collection May Be Linked
736+
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
737+
738+
The user may provide a search term to limit the list of Dataverse Collections returned. The search term will be compared to the name of the Dataverse Collections.
739+
The response is a JSON array of the ids, aliases, and names of the Dataverse collections to which a given Dataset or Dataverse Collection may be linked:
740+
741+
For a given Dataverse Collection:
742+
743+
.. code-block:: bash
744+
745+
export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
746+
export SERVER_URL=https://demo.dataverse.org
747+
export OBJECT_TYPE=dataverse
748+
export ID=collectionAlias
749+
export SEARCH_TERM=searchOn
750+
751+
curl -H "X-Dataverse-key:$API_TOKEN" -X GET "$SERVER_URL/api/dataverses/$ID/$OBJECT_TYPE/linkingDataverses?searchTerm=$SEARCH_TERM"
752+
753+
The fully expanded example above (without environment variables) looks like this:
754+
755+
.. code-block:: bash
756+
757+
curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X GET "https://demo.dataverse.org/api/dataverses/collectionAlias/dataverse/linkingDataverses?searchTerm=searchOn"
758+
759+
For a given Dataset:
760+
761+
.. code-block:: bash
762+
763+
export API_TOKEN=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
764+
export SERVER_URL=https://demo.dataverse.org
765+
export OBJECT_TYPE=dataset
766+
export PERSISTENT_IDENTIFIER=doi:10.5072/FK2/J8SJZB
767+
export SEARCH_TERM=searchOn
768+
769+
curl -H "X-Dataverse-key:$API_TOKEN" -X GET "$SERVER_URL/api/dataverses/:persistentId/$OBJECT_TYPE/linkingDataverses?searchTerm=SEARCH_TERM&persistentId=$PERSISTENT_IDENTIFIER"
770+
771+
The fully expanded example above (without environment variables) looks like this:
772+
773+
.. code-block:: bash
774+
775+
curl -H "X-Dataverse-key:xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" -X GET "https://demo.dataverse.org/api/dataverses/:persistentId/dataset/linkingDataverses?searchTerm=searchOn&persistentId=doi:10.5072/FK2/J8SJZB"
776+
777+
You may also add an optional "alreadyLinked=true" parameter to return collections which are already linked to the given Dataset or Dataverse Collection.
778+
735779
List Featured Collections for a Dataverse Collection
736780
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
737781

src/main/java/edu/harvard/iq/dataverse/DatasetLinkingDataverse.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import jakarta.persistence.Id;
1010
import jakarta.persistence.Index;
1111
import jakarta.persistence.JoinColumn;
12+
import jakarta.persistence.NamedNativeQuery;
1213
import jakarta.persistence.NamedQueries;
1314
import jakarta.persistence.NamedQuery;
1415
import jakarta.persistence.OneToOne;
@@ -35,6 +36,18 @@
3536
@NamedQuery(name = "DatasetLinkingDataverse.findIdsByLinkingDataverseId",
3637
query = "SELECT o.dataset.id FROM DatasetLinkingDataverse AS o WHERE o.linkingDataverse.id = :linkingDataverseId")
3738
})
39+
40+
@NamedNativeQuery(
41+
name = "DatasetLinkingDataverse.findByDatasetIdAndLinkingDataverseName",
42+
query = """
43+
select o.linkingDataverse_id from DatasetLinkingDataverse as o
44+
LEFT JOIN dataverse dv ON dv.id = o.linkingDataverse_id
45+
WHERE o.dataset_id =? AND ((LOWER(dv.name) LIKE ? and ((SUBSTRING(LOWER(dv.name),0,(LENGTH(dv.name)-9)) LIKE ?)
46+
or (SUBSTRING(LOWER(dv.name),0,(LENGTH(dv.name)-9)) LIKE ?)))
47+
or (LOWER(dv.name) NOT LIKE ? and ((LOWER(dv.name) LIKE ?)
48+
or (LOWER(dv.name) LIKE ?))))"""
49+
)
50+
3851
public class DatasetLinkingDataverse implements Serializable {
3952
private static final long serialVersionUID = 1L;
4053
@Id

src/main/java/edu/harvard/iq/dataverse/DatasetLinkingServiceBean.java

Lines changed: 38 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
*/
66
package edu.harvard.iq.dataverse;
77

8+
import jakarta.ejb.EJB;
89
import java.util.ArrayList;
910
import java.util.List;
1011
import java.util.logging.Logger;
@@ -13,7 +14,6 @@
1314
import jakarta.persistence.EntityManager;
1415
import jakarta.persistence.NoResultException;
1516
import jakarta.persistence.PersistenceContext;
16-
import jakarta.persistence.Query;
1717
import jakarta.persistence.TypedQuery;
1818

1919
/**
@@ -28,6 +28,9 @@ public class DatasetLinkingServiceBean implements java.io.Serializable {
2828
@PersistenceContext(unitName = "VDCNet-ejbPU")
2929
private EntityManager em;
3030

31+
@EJB
32+
DataverseServiceBean dataverseService;
33+
3134

3235

3336
public List<Dataset> findLinkedDatasets(Long dataverseId) {
@@ -41,13 +44,42 @@ public List<Dataset> findLinkedDatasets(Long dataverseId) {
4144
}
4245

4346
public List<Dataverse> findLinkingDataverses(Long datasetId) {
47+
return findLinkingDataverses(datasetId, "");
48+
}
49+
50+
public List<Dataverse> findLinkingDataverses(Long datasetId, String searchTerm) {
4451
List<Dataverse> retList = new ArrayList<>();
45-
TypedQuery<DatasetLinkingDataverse> typedQuery = em.createNamedQuery("DatasetLinkingDataverse.findByDatasetId", DatasetLinkingDataverse.class)
46-
.setParameter("datasetId", datasetId);
47-
for (DatasetLinkingDataverse datasetLinkingDataverse : typedQuery.getResultList()) {
48-
retList.add(datasetLinkingDataverse.getLinkingDataverse());
52+
if (searchTerm == null || searchTerm.isEmpty()) {
53+
TypedQuery<DatasetLinkingDataverse> typedQuery = em.createNamedQuery("DatasetLinkingDataverse.findByDatasetId", DatasetLinkingDataverse.class)
54+
.setParameter("datasetId", datasetId);
55+
for (DatasetLinkingDataverse datasetLinkingDataverse : typedQuery.getResultList()) {
56+
retList.add(datasetLinkingDataverse.getLinkingDataverse());
57+
}
58+
return retList;
59+
60+
} else {
61+
62+
String pattern = searchTerm.toLowerCase();
63+
64+
String pattern1 = pattern + "%";
65+
String pattern2 = "% " + pattern + "%";
66+
67+
// Adjust the queries for very short, 1 and 2-character patterns:
68+
if (pattern.length() == 1) {
69+
pattern1 = pattern;
70+
pattern2 = pattern + " %";
71+
}
72+
TypedQuery<Long> typedQuery
73+
= em.createNamedQuery("DatasetLinkingDataverse.findByDatasetIdAndLinkingDataverseName", Long.class)
74+
.setParameter(1, datasetId).setParameter(2, "%dataverse").setParameter(3, pattern1)
75+
.setParameter(4, pattern2).setParameter(5, "%dataverse").setParameter(6, pattern1).setParameter(7, pattern2);
76+
77+
for (Long id : typedQuery.getResultList()) {
78+
retList.add(dataverseService.find(id));
79+
}
80+
return retList;
4981
}
50-
return retList;
82+
5183
}
5284

5385
public void save(DatasetLinkingDataverse datasetLinkingDataverse) {

src/main/java/edu/harvard/iq/dataverse/DataverseLinkingDataverse.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
import jakarta.persistence.Id;
1414
import jakarta.persistence.Index;
1515
import jakarta.persistence.JoinColumn;
16+
import jakarta.persistence.NamedNativeQuery;
1617
import jakarta.persistence.NamedQueries;
1718
import jakarta.persistence.NamedQuery;
1819
import jakarta.persistence.OneToOne;
@@ -39,6 +40,16 @@
3940
@NamedQuery(name = "DataverseLinkingDataverse.findIdsByLinkingDataverseId",
4041
query = "SELECT o.dataverse.id FROM DataverseLinkingDataverse AS o WHERE o.linkingDataverse.id = :linkingDataverseId")
4142
})
43+
@NamedNativeQuery(
44+
name = "DataverseLinkingDataverse.findByDataverseIdAndLinkingDataverseName",
45+
query = """
46+
select o.linkingDataverse_id from DataverseLinkingDataverse as o
47+
LEFT JOIN dataverse dv ON dv.id = o.linkingDataverse_id
48+
WHERE o.dataverse_id =? AND ((LOWER(dv.name) LIKE ? and ((SUBSTRING(LOWER(dv.name),0,(LENGTH(dv.name)-9)) LIKE ?)
49+
or (SUBSTRING(LOWER(dv.name),0,(LENGTH(dv.name)-9)) LIKE ?)))
50+
or (LOWER(dv.name) NOT LIKE ? and ((LOWER(dv.name) LIKE ?)
51+
or (LOWER(dv.name) LIKE ?))))"""
52+
)
4253
public class DataverseLinkingDataverse implements Serializable {
4354
private static final long serialVersionUID = 1L;
4455
@Id

src/main/java/edu/harvard/iq/dataverse/DataverseLinkingServiceBean.java

Lines changed: 33 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -43,12 +43,41 @@ public List<Dataverse> findLinkedDataverses(Long linkingDataverseId) {
4343
}
4444

4545
public List<Dataverse> findLinkingDataverses(Long dataverseId) {
46+
47+
return findLinkingDataverses(dataverseId, "");
48+
}
49+
50+
public List<Dataverse> findLinkingDataverses(Long dataverseId, String searchTerm) {
4651
List<Dataverse> retList = new ArrayList<>();
47-
TypedQuery<DataverseLinkingDataverse> typedQuery = em.createNamedQuery("DataverseLinkingDataverse.findByDataverseId", DataverseLinkingDataverse.class)
48-
.setParameter("dataverseId", dataverseId);
49-
for (DataverseLinkingDataverse dataverseLinkingDataverse : typedQuery.getResultList()) {
50-
retList.add(dataverseLinkingDataverse.getLinkingDataverse());
52+
if (searchTerm == null || searchTerm.isEmpty()) {
53+
TypedQuery<DataverseLinkingDataverse> typedQuery = em.createNamedQuery("DataverseLinkingDataverse.findByDataverseId", DataverseLinkingDataverse.class)
54+
.setParameter("dataverseId", dataverseId);
55+
for (DataverseLinkingDataverse dataverseLinkingDataverse : typedQuery.getResultList()) {
56+
retList.add(dataverseLinkingDataverse.getLinkingDataverse());
57+
}
58+
59+
} else {
60+
61+
String pattern = searchTerm.toLowerCase();
62+
63+
String pattern1 = pattern + "%";
64+
String pattern2 = "% " + pattern + "%";
65+
66+
// Adjust the queries for very short, 1 and 2-character patterns:
67+
if (pattern.length() == 1) {
68+
pattern1 = pattern;
69+
pattern2 = pattern + " %";
70+
}
71+
TypedQuery<Long> typedQuery
72+
= em.createNamedQuery("DataverseLinkingDataverse.findByDataverseIdAndLinkingDataverseName", Long.class)
73+
.setParameter(1, dataverseId).setParameter(2, "%dataverse").setParameter(3, pattern1)
74+
.setParameter(4, pattern2).setParameter(5, "%dataverse").setParameter(6, pattern1).setParameter(7, pattern2);
75+
76+
for (Long id : typedQuery.getResultList()) {
77+
retList.add(dataverseService.find(id));
78+
}
5179
}
80+
5281
return retList;
5382
}
5483

src/main/java/edu/harvard/iq/dataverse/DataverseServiceBean.java

Lines changed: 71 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -505,35 +505,99 @@ public List<Dataverse> filterByAliasQuery(String filterQuery) {
505505
return ret;
506506
}
507507

508-
public List<Dataverse> filterDataversesForLinking(String query, DataverseRequest req, Dataset dataset) {
508+
public List<Dataverse> filterDataversesForLinking(String query, DataverseRequest req, DvObject dvo) {
509509

510510
List<Dataverse> dataverseList = new ArrayList<>();
511511

512512
List<Dataverse> results = filterDataversesByNamePattern(query);
513-
514-
if (results == null || results.size() == 0) {
515-
return null;
513+
514+
if (results == null || results.isEmpty()) {
515+
return null;
516+
}
517+
518+
Dataset linkedDataset = null;
519+
Dataverse linkedDataverse = null;
520+
List<Object> alreadyLinkeddv_ids;
521+
522+
if ((dvo instanceof Dataset)) {
523+
linkedDataset = (Dataset) dvo;
524+
alreadyLinkeddv_ids = em.createNativeQuery("SELECT linkingdataverse_id FROM datasetlinkingdataverse WHERE dataset_id = " + linkedDataset.getId()).getResultList();
525+
} else {
526+
linkedDataverse = (Dataverse) dvo;
527+
alreadyLinkeddv_ids = em.createNativeQuery("SELECT linkingdataverse_id FROM dataverselinkingdataverse WHERE dataverse_id = " + linkedDataverse.getId()).getResultList();
516528
}
517529

518-
List<Object> alreadyLinkeddv_ids = em.createNativeQuery("SELECT linkingdataverse_id FROM datasetlinkingdataverse WHERE dataset_id = " + dataset.getId()).getResultList();
519530
List<Dataverse> remove = new ArrayList<>();
520531

521532
if (alreadyLinkeddv_ids != null && !alreadyLinkeddv_ids.isEmpty()) {
522533
alreadyLinkeddv_ids.stream().map((testDVId) -> this.find(testDVId)).forEachOrdered((removeIt) -> {
523534
remove.add(removeIt);
524535
});
525536
}
526-
537+
538+
if (dvo instanceof Dataverse dataverse) {
539+
remove.add(dataverse);
540+
}
541+
527542
for (Dataverse res : results) {
528543
if (!remove.contains(res)) {
529-
if (this.permissionService.requestOn(req, res).has(Permission.LinkDataset)) {
544+
if ((linkedDataset != null && this.permissionService.requestOn(req, res).has(Permission.LinkDataset))
545+
|| (linkedDataverse != null && this.permissionService.requestOn(req, res).has(Permission.LinkDataverse))) {
530546
dataverseList.add(res);
531547
}
532548
}
533549
}
534550

535551
return dataverseList;
536552
}
553+
554+
public List<Dataverse> removeUnlinkableDataverses(List<Dataverse> allWithPerms, DvObject dvo) {
555+
List<Dataverse> dataverseList = new ArrayList<>();
556+
Dataset linkedDataset = null;
557+
Dataverse linkedDataverse = null;
558+
List<Object> alreadyLinkeddv_ids;
559+
560+
if ((dvo instanceof Dataset)) {
561+
linkedDataset = (Dataset) dvo;
562+
alreadyLinkeddv_ids = em.createNativeQuery("SELECT linkingdataverse_id FROM datasetlinkingdataverse WHERE dataset_id = " + linkedDataset.getId()).getResultList();
563+
} else {
564+
linkedDataverse = (Dataverse) dvo;
565+
alreadyLinkeddv_ids = em.createNativeQuery("SELECT linkingdataverse_id FROM dataverselinkingdataverse WHERE dataverse_id = " + linkedDataverse.getId()).getResultList();
566+
}
567+
568+
List<Dataverse> remove = new ArrayList<>();
569+
570+
if (alreadyLinkeddv_ids != null && !alreadyLinkeddv_ids.isEmpty()) {
571+
alreadyLinkeddv_ids.stream().map((testDVId) -> this.find(testDVId)).forEachOrdered((removeIt) -> {
572+
remove.add(removeIt);
573+
});
574+
}
575+
576+
577+
if (dvo instanceof Dataverse dataverse) {
578+
remove.add(dataverse);
579+
}
580+
581+
DvObject testDVO = dvo;
582+
//Remove DVO's parent up to Root
583+
while (testDVO != null) {
584+
if (testDVO.getOwner() == null) {
585+
break; // we are at the root; which by definition is metadata block root, regardless of the value
586+
}
587+
remove.add((Dataverse) testDVO.getOwner());
588+
testDVO = testDVO.getOwner();
589+
}
590+
591+
for (Dataverse res : allWithPerms) {
592+
if (!remove.contains(res)) {
593+
dataverseList.add(res);
594+
}
595+
}
596+
597+
return dataverseList;
598+
}
599+
600+
537601
public List<Dataverse> filterDataversesForUnLinking(String query, DataverseRequest req, Dataset dataset) {
538602
List<Object> alreadyLinkeddv_ids = em.createNativeQuery("SELECT linkingdataverse_id FROM datasetlinkingdataverse WHERE dataset_id = " + dataset.getId()).getResultList();
539603
List<Dataverse> dataverseList = new ArrayList<>();

0 commit comments

Comments
 (0)