Skip to content

Commit 35a03bd

Browse files
rushtongCopilot
andauthored
DT-2957: Update the API call for getting DAR details for a dataset ID (#2822)
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
1 parent 748d8fd commit 35a03bd

File tree

17 files changed

+496
-259
lines changed

17 files changed

+496
-259
lines changed

src/main/java/org/broadinstitute/consent/http/ConsentModule.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -537,11 +537,7 @@ MailMessageDAO providesMailMessageDAO() {
537537

538538
@Provides
539539
MetricsService providesMetricsService() {
540-
return new MetricsService(
541-
providesDatasetDAO(),
542-
providesDataAccessRequestDAO(),
543-
providesDARCollectionDAO(),
544-
providesElectionDAO());
540+
return new MetricsService(providesDatasetDAO(), providesDataAccessRequestDAO());
545541
}
546542

547543
@Provides

src/main/java/org/broadinstitute/consent/http/db/DataAccessRequestDAO.java

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -101,6 +101,61 @@ AND dar.collection_id NOT IN (
101101
""")
102102
List<DataAccessRequest> findApprovedDARsByDatasetId(@Bind("datasetId") Integer datasetId);
103103

104+
/**
105+
* This query finds DARs submitted on dar-dataset combinations where the most recent vote is true
106+
* similar to {@link #findApprovedDARsByDatasetId(Integer datasetId) findApprovedDARsByDatasetId}.
107+
* The primary difference is that we want to include expired DARs to show in dataset usage
108+
* metrics.
109+
*
110+
* @param datasetId The dataset id
111+
* @return List of approved DARs for the dataset
112+
*/
113+
@UseRowReducer(DataAccessRequestReducer.class)
114+
@SqlQuery(
115+
"""
116+
SELECT dar.id, dar.reference_id, dar.collection_id, dar.parent_id, dar.user_id,
117+
dar.create_date, dar.submission_date, dar.update_date, dar.data, dar.era_commons_id,
118+
dar.approving_so_id, dar.approving_so_timestamp, dar.requires_so_approval,
119+
dar.closeout_so_approval_timestamp, dar.closeout_approving_so_id,
120+
dd.dataset_id, collection.dar_code
121+
FROM data_access_request dar
122+
LEFT JOIN dar_collection collection on collection.collection_id = dar.collection_id
123+
INNER JOIN dar_dataset dd ON dd.reference_id = dar.reference_id
124+
INNER JOIN (
125+
SELECT DISTINCT e.reference_id, e.dataset_id, LAST_VALUE(v.vote)
126+
OVER(
127+
PARTITION BY e.reference_id, e.dataset_id
128+
ORDER BY v.create_date
129+
RANGE BETWEEN
130+
UNBOUNDED PRECEDING AND
131+
UNBOUNDED FOLLOWING
132+
) last_vote
133+
FROM election e
134+
INNER JOIN vote v ON e.election_id = v.election_id AND v.vote IS NOT NULL
135+
AND LOWER(e.election_type) = 'dataaccess'
136+
AND LOWER(v.type) IN ('final', 'radar_approve')) final_access_vote ON final_access_vote.reference_id = dar.reference_id AND final_access_vote.dataset_id = dd.dataset_id
137+
WHERE dd.dataset_id = :datasetId
138+
AND dar.submission_date IS NOT NULL
139+
AND final_access_vote.last_vote = TRUE
140+
AND (LOWER(dar.data->>'status') != 'archived' OR dar.data->>'status' IS NULL)
141+
-- Pull in all closeouts for this dataset. Closeouts do not have elections,
142+
-- but we want to include them in the dataset usage metrics.
143+
UNION
144+
SELECT dar.id, dar.reference_id, dar.collection_id, dar.parent_id, dar.user_id,
145+
dar.create_date, dar.submission_date, dar.update_date, dar.data, dar.era_commons_id,
146+
dar.approving_so_id, dar.approving_so_timestamp, dar.requires_so_approval,
147+
dar.closeout_so_approval_timestamp, dar.closeout_approving_so_id,
148+
dd.dataset_id, collection.dar_code
149+
FROM data_access_request dar
150+
LEFT JOIN dar_collection collection on collection.collection_id = dar.collection_id
151+
INNER JOIN dar_dataset dd ON dd.reference_id = dar.reference_id
152+
WHERE dd.dataset_id = :datasetId
153+
AND dar.submission_date IS NOT NULL
154+
AND data ->> 'closeoutSupplement' IS NOT NULL
155+
""")
156+
List<DataAccessRequest> findSummaryMetricApprovedDARsByDatasetIdIncludesExpired(
157+
@Bind("datasetId") Integer datasetId);
158+
104159
/**
105160
* This query finds dataset ids on dar-dataset combinations where the most recent vote is true.
106161
* This includes datasets that are a part of expired DARs, UNLIKE findApprovedDARsByDatasetId. The
@@ -305,11 +360,6 @@ void updateDataByReferenceId(
305360
""")
306361
void deleteByReferenceId(@Bind("referenceId") String referenceId);
307362

308-
@SqlUpdate("DELETE FROM data_access_request WHERE reference_id IN (<referenceIds>)")
309-
void deleteByReferenceIds(
310-
@BindList(value = "referenceIds", onEmpty = EmptyHandling.NULL_STRING)
311-
List<String> referenceIds);
312-
313363
@SqlUpdate(
314364
"""
315365
UPDATE data_access_request
@@ -494,16 +544,6 @@ INSERT INTO dar_dataset (reference_id, dataset_id)
494544
""")
495545
void deleteDARDatasetRelationByReferenceId(@Bind("referenceId") String referenceId);
496546

497-
/**
498-
* Delete rows which have a referenceId that is in the list referenceIds
499-
*
500-
* @param referenceIds List<String>
501-
*/
502-
@SqlUpdate("DELETE FROM dar_dataset WHERE reference_id in (<referenceIds>)")
503-
void deleteDARDatasetRelationByReferenceIds(
504-
@BindList(value = "referenceIds", onEmpty = EmptyHandling.NULL_STRING)
505-
List<String> referenceIds);
506-
507547
/**
508548
* Returns all dataset_ids that match any of the referenceIds inside the "referenceIds" list
509549
*

src/main/java/org/broadinstitute/consent/http/db/ElectionDAO.java

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -151,25 +151,6 @@ List<Election> findOpenElectionsByReferenceIds(
151151
@BindList(value = "referenceIds", onEmpty = EmptyHandling.NULL_STRING)
152152
List<String> referenceIds);
153153

154-
@SqlQuery(
155-
"""
156-
SELECT distinct *
157-
FROM election e
158-
INNER JOIN
159-
(SELECT reference_id, MAX(create_date) max_date
160-
FROM election e WHERE LOWER(e.election_type) = LOWER(:type)
161-
GROUP BY reference_id) election_view
162-
ON election_view.max_date = e.create_date
163-
AND election_view.reference_id = e.reference_id
164-
WHERE e.reference_id in (<referenceIds>)
165-
AND LOWER(e.election_type) = LOWER(:type)
166-
""")
167-
@UseRowMapper(SimpleElectionMapper.class)
168-
List<Election> findLastElectionsByReferenceIdsAndType(
169-
@BindList(value = "referenceIds", onEmpty = EmptyHandling.NULL_STRING)
170-
List<String> referenceIds,
171-
@Bind("type") String type);
172-
173154
@SqlQuery(
174155
"""
175156
SELECT e.* FROM election e
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
package org.broadinstitute.consent.http.models;
2+
3+
import java.sql.Timestamp;
4+
5+
public record DarMetricsSummary(
6+
Timestamp updateDate,
7+
String projectTitle,
8+
String darCode,
9+
String nonTechRus,
10+
String referenceId,
11+
Boolean expired) {
12+
13+
public DarMetricsSummary(DataAccessRequest dar) {
14+
this(
15+
dar != null ? dar.getUpdateDate() : null,
16+
dar != null && dar.getData() != null ? dar.getData().getProjectTitle() : null,
17+
dar != null ? dar.getDarCode() : null,
18+
dar != null && dar.getData() != null ? dar.getData().getNonTechRus() : null,
19+
dar != null ? dar.getReferenceId() : null,
20+
dar == null || dar.getSubmissionDate() == null || dar.getExpired());
21+
}
22+
}
Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,10 @@
11
package org.broadinstitute.consent.http.models;
22

33
import java.util.List;
4-
import org.broadinstitute.consent.http.service.MetricsService.DarMetricsSummary;
54

65
public class DatasetMetrics {
76

8-
private Dataset dataset;
97
private List<DarMetricsSummary> dars;
10-
private List<Election> elections;
11-
12-
public Dataset getDataset() {
13-
return dataset;
14-
}
15-
16-
public void setDataset(Dataset dataset) {
17-
this.dataset = dataset;
18-
}
198

209
public List<DarMetricsSummary> getDars() {
2110
return dars;
@@ -24,12 +13,4 @@ public List<DarMetricsSummary> getDars() {
2413
public void setDars(List<DarMetricsSummary> dars) {
2514
this.dars = dars;
2615
}
27-
28-
public List<Election> getElections() {
29-
return elections;
30-
}
31-
32-
public void setElections(List<Election> elections) {
33-
this.elections = elections;
34-
}
3516
}

src/main/java/org/broadinstitute/consent/http/resources/MetricsResource.java

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,20 @@
11
package org.broadinstitute.consent.http.resources;
22

33
import com.google.inject.Inject;
4+
import io.dropwizard.auth.Auth;
5+
import jakarta.annotation.security.PermitAll;
46
import jakarta.ws.rs.GET;
57
import jakarta.ws.rs.Path;
68
import jakarta.ws.rs.PathParam;
79
import jakarta.ws.rs.Produces;
810
import jakarta.ws.rs.core.Response;
11+
import java.util.List;
12+
import org.broadinstitute.consent.http.models.DarMetricsSummary;
913
import org.broadinstitute.consent.http.models.DatasetMetrics;
14+
import org.broadinstitute.consent.http.models.DuosUser;
1015
import org.broadinstitute.consent.http.service.MetricsService;
1116

12-
@Path("/metrics")
17+
@Path("{api : (api/)?}metrics")
1318
public class MetricsResource extends Resource {
1419

1520
private final MetricsService metricsService;
@@ -19,6 +24,12 @@ public MetricsResource(MetricsService metricsService) {
1924
this.metricsService = metricsService;
2025
}
2126

27+
/**
28+
* @deprecated
29+
* @param datasetId the id of the dataset for which to generate metrics
30+
* @return Response containing DatasetMetrics for the given datasetId
31+
*/
32+
@Deprecated(forRemoval = true, since = "2026-02-23")
2233
@GET
2334
@Path("/dataset/{datasetId}")
2435
@Produces("application/json")
@@ -30,4 +41,19 @@ public Response getDatasetMetricsData(@PathParam("datasetId") Integer datasetId)
3041
return createExceptionResponse(e);
3142
}
3243
}
44+
45+
@SuppressWarnings("unused")
46+
@GET
47+
@Path("/dar-summaries/{datasetId}")
48+
@Produces("application/json")
49+
@PermitAll
50+
public Response getDarSummaryData(
51+
@Auth DuosUser user, @PathParam("datasetId") Integer datasetId) {
52+
try {
53+
List<DarMetricsSummary> summaries = metricsService.generateDarSummaries(datasetId);
54+
return Response.ok().entity(summaries).build();
55+
} catch (Exception e) {
56+
return createExceptionResponse(e);
57+
}
58+
}
3359
}
Lines changed: 10 additions & 85 deletions
Original file line numberDiff line numberDiff line change
@@ -1,115 +1,40 @@
11
package org.broadinstitute.consent.http.service;
22

3-
import com.fasterxml.jackson.annotation.JsonProperty;
43
import com.google.inject.Inject;
54
import jakarta.ws.rs.NotFoundException;
6-
import java.sql.Timestamp;
7-
import java.util.Collections;
85
import java.util.List;
9-
import java.util.Map;
10-
import java.util.Objects;
11-
import java.util.function.Function;
12-
import java.util.stream.Collectors;
13-
import org.broadinstitute.consent.http.db.DarCollectionDAO;
146
import org.broadinstitute.consent.http.db.DataAccessRequestDAO;
157
import org.broadinstitute.consent.http.db.DatasetDAO;
16-
import org.broadinstitute.consent.http.db.ElectionDAO;
17-
import org.broadinstitute.consent.http.models.DarCollection;
8+
import org.broadinstitute.consent.http.models.DarMetricsSummary;
189
import org.broadinstitute.consent.http.models.DataAccessRequest;
1910
import org.broadinstitute.consent.http.models.Dataset;
2011
import org.broadinstitute.consent.http.models.DatasetMetrics;
21-
import org.broadinstitute.consent.http.models.Election;
2212

2313
public class MetricsService {
2414

2515
private final DatasetDAO dataSetDAO;
2616
private final DataAccessRequestDAO darDAO;
27-
private final DarCollectionDAO darCollectionDAO;
28-
private final ElectionDAO electionDAO;
2917

3018
@Inject
31-
public MetricsService(
32-
DatasetDAO dataSetDAO,
33-
DataAccessRequestDAO darDAO,
34-
DarCollectionDAO darCollectionDAO,
35-
ElectionDAO electionDAO) {
19+
public MetricsService(DatasetDAO dataSetDAO, DataAccessRequestDAO darDAO) {
3620
this.dataSetDAO = dataSetDAO;
3721
this.darDAO = darDAO;
38-
this.darCollectionDAO = darCollectionDAO;
39-
this.electionDAO = electionDAO;
40-
}
41-
42-
public static class DarMetricsSummary {
43-
44-
final Timestamp updateDate;
45-
@JsonProperty final String projectTitle;
46-
@JsonProperty final String darCode;
47-
@JsonProperty final String nonTechRus;
48-
@JsonProperty final String referenceId;
49-
50-
public DarMetricsSummary(DataAccessRequest dar, String darCode) {
51-
if (dar != null && dar.data != null) {
52-
this.updateDate = dar.getUpdateDate();
53-
this.projectTitle = dar.data.getProjectTitle();
54-
this.darCode = darCode;
55-
this.nonTechRus = dar.data.getNonTechRus();
56-
this.referenceId = dar.getReferenceId();
57-
} else {
58-
this.updateDate = null;
59-
this.projectTitle = null;
60-
this.darCode = null;
61-
this.nonTechRus = null;
62-
this.referenceId = null;
63-
}
64-
}
6522
}
6623

6724
public DatasetMetrics generateDatasetMetrics(Integer datasetId) {
68-
6925
DatasetMetrics metrics = new DatasetMetrics();
26+
List<DarMetricsSummary> darMetricsSummaries = generateDarSummaries(datasetId);
27+
metrics.setDars(darMetricsSummaries);
28+
return metrics;
29+
}
7030

71-
// get datasetDTO with properties and data use restrictions
31+
public List<DarMetricsSummary> generateDarSummaries(Integer datasetId) {
7232
Dataset dataset = dataSetDAO.findDatasetById(datasetId);
7333
if (dataset == null) {
7434
throw new NotFoundException("Dataset with specified ID does not exist.");
7535
}
76-
77-
// find dars with the given datasetId in their list of datasetIds, datasetId is a String so it
78-
// can be converted to jsonb in query
79-
// convert all dars into smaller objects that only contain the information needed
80-
List<DataAccessRequest> dars = darDAO.findApprovedDARsByDatasetId(datasetId);
81-
List<Integer> darCollectionIds = dars.stream().map(DataAccessRequest::getCollectionId).toList();
82-
List<DarCollection> darCollections =
83-
darCollectionIds.isEmpty()
84-
? List.of()
85-
: darCollectionDAO.findDARCollectionByCollectionIds(darCollectionIds);
86-
Map<Integer, DarCollection> collectionMap =
87-
darCollections.stream()
88-
.collect(Collectors.toMap(DarCollection::getDarCollectionId, Function.identity()));
89-
90-
List<DarMetricsSummary> darInfo =
91-
dars.stream()
92-
.map(
93-
dar -> {
94-
DarCollection collection = collectionMap.get(dar.getCollectionId());
95-
String darCode = Objects.nonNull(collection) ? collection.getDarCode() : null;
96-
return new DarMetricsSummary(dar, darCode);
97-
})
98-
.collect(Collectors.toList());
99-
100-
// if there are associated dars, find associated access elections so we know how many and which
101-
// dars are approved/denied
102-
List<String> referenceIds =
103-
dars.stream().map(dar -> (dar.referenceId)).collect(Collectors.toList());
104-
if (!referenceIds.isEmpty()) {
105-
List<Election> elections =
106-
electionDAO.findLastElectionsByReferenceIdsAndType(referenceIds, "DataAccess");
107-
metrics.setElections(elections);
108-
} else {
109-
metrics.setElections(Collections.emptyList());
110-
}
111-
metrics.setDataset(dataset);
112-
metrics.setDars(darInfo);
113-
return metrics;
36+
List<DataAccessRequest> dars =
37+
darDAO.findSummaryMetricApprovedDARsByDatasetIdIncludesExpired(datasetId);
38+
return dars.stream().map(DarMetricsSummary::new).toList();
11439
}
11540
}

0 commit comments

Comments
 (0)