diff --git a/src/main/java/org/broadinstitute/dsde/consent/ontology/datause/DataUseMatchCasesV3.java b/src/main/java/org/broadinstitute/dsde/consent/ontology/datause/DataUseMatchCasesV3.java index c02fb3fe..7a5ac5c2 100644 --- a/src/main/java/org/broadinstitute/dsde/consent/ontology/datause/DataUseMatchCasesV3.java +++ b/src/main/java/org/broadinstitute/dsde/consent/ontology/datause/DataUseMatchCasesV3.java @@ -10,6 +10,7 @@ public class DataUseMatchCasesV3 { + // rationale for failures private static final String HMB_F1 = "The GRU Research Purpose does not match the HMB data use limitations."; private static final String HMB_F2 = "The HMB Research Purpose does not match the Disease-Specific data use limitations."; private static final String HMB_F3 = "The HMB Research Purpose does not match the POA data use limitations."; @@ -17,6 +18,17 @@ public class DataUseMatchCasesV3 { private static final String MDS_F1 = "The Methods development Research Purpose does not match the Disease-Specific data use limitations."; private static final String POA_F1 = "The Populations, Origins, Ancestry Research Purpose does not match the HMB or Disease-Specific data use limitation."; private static final String NCU_F1 = "The Commercial Use Research Purpose does not match the No Commercial Use data use limitation."; + + // rationale for approvals - based on dataset terms + private static final String DS_APPROVE_GRU = "The proposed disease-specific research is within the bounds of the general research use permissions of the dataset(s)"; + private static final String DS_APPROVE_HMB = "The proposed disease-specific research is within the bounds of the health, medical, biomedical use permissions of the dataset(s)"; + private static final String HMB_APPROVE_HMB = "The proposed health, medical, biomedical research is within the bounds of the health, medical, biomedical use permissions of the dataset(s)"; + private static final String HMB_APPROVE_GRU = "The proposed health, medical, biomedical research is within the bounds of the general research use permissions of the dataset(s)"; + private static final String POA_APPROVE_GRU = "The proposed population, origins, and/or ancestry research is within the bounds of the general research use permissions of the dataset(s)"; + private static final String POA_APPROVE_POA = "The proposed population, origins, and/or ancestry research is within the bounds of the population, origins, and/or ancestry use permissions of the dataset(s)"; + private static final String MDS_APPROVE = "Methods research is permitted on controlled-access data so long as it is not expressly prohibited"; + + // rationale for abstain cases private static final String ABSTAIN = "The Research Purpose does not result in DUOS Decision."; /** @@ -44,11 +56,11 @@ static MatchResult matchDiseases( } // Approve dataset GRU condition if (purposeDSX && datasetGRU) { - return MatchResult.from(MatchResultType.APPROVE, Collections.emptyList()); + return MatchResult.from(MatchResultType.APPROVE, Collections.singletonList(DS_APPROVE_GRU)); } // Approve dataset HMB condition if (purposeDSX && datasetHMB) { - return MatchResult.from(MatchResultType.APPROVE, Collections.emptyList()); + return MatchResult.from(MatchResultType.APPROVE, Collections.singletonList(DS_APPROVE_HMB)); } // We want all-purpose disease IDs to be a subclass of any dataset disease ID @@ -104,12 +116,12 @@ static MatchResult matchHMB(DataUseV3 purpose, DataUseV3 dataset) { // Approve dataset GRU condition if (datasetGRU) { - return MatchResult.from(MatchResultType.APPROVE, Collections.emptyList()); + return MatchResult.from(MatchResultType.APPROVE, Collections.singletonList(HMB_APPROVE_GRU)); } // Approve dataset HMB condition if (purposeHMB && datasetHMB) { - return MatchResult.from(MatchResultType.APPROVE, Collections.emptyList()); + return MatchResult.from(MatchResultType.APPROVE, Collections.singletonList(HMB_APPROVE_HMB)); } else { return MatchResult.from(failures.isEmpty() ? MatchResultType.APPROVE : MatchResultType.DENY, @@ -134,12 +146,12 @@ static MatchResult matchPOA(DataUseV3 purpose, DataUseV3 dataset) { // Approve dataset GRU condition if (datasetGRU) { - return MatchResult.from(MatchResultType.APPROVE, Collections.emptyList()); + return MatchResult.from(MatchResultType.APPROVE, Collections.singletonList(POA_APPROVE_GRU)); } // Approve dataset POA condition if (purposePOA && datasetPOA) { - return MatchResult.from(MatchResultType.APPROVE, Collections.emptyList()); + return MatchResult.from(MatchResultType.APPROVE, Collections.singletonList(POA_APPROVE_POA)); } List failures = new ArrayList<>(); @@ -175,22 +187,22 @@ static MatchResult matchMDS(DataUseV3 purpose, DataUseV3 dataset, MatchResultTyp // Approve dataset GRU condition if (datasetGRU) { - return MatchResult.from(MatchResultType.APPROVE, Collections.emptyList()); + return MatchResult.from(MatchResultType.APPROVE, Collections.singletonList(MDS_APPROVE)); } // Approve dataset HMB condition if (purposeMDS && datasetHMB) { - return MatchResult.from(MatchResultType.APPROVE, Collections.emptyList()); + return MatchResult.from(MatchResultType.APPROVE, Collections.singletonList(MDS_APPROVE)); } // Approve dataset POA condition if (purposeMDS && datasetPOA) { - return MatchResult.from(MatchResultType.APPROVE, Collections.emptyList()); + return MatchResult.from(MatchResultType.APPROVE, Collections.singletonList(MDS_APPROVE)); } // short-circuit if there is a disease match if (diseaseMatch == MatchResultType.APPROVE) { - return MatchResult.from(MatchResultType.APPROVE, Collections.emptyList()); + return MatchResult.from(MatchResultType.APPROVE, Collections.singletonList(MDS_APPROVE)); } else { return MatchResult.from(MatchResultType.DENY, Collections.singletonList(MDS_F1)); } diff --git a/src/main/java/org/broadinstitute/dsde/consent/ontology/datause/MatchV3ResponseEntity.java b/src/main/java/org/broadinstitute/dsde/consent/ontology/datause/MatchV3ResponseEntity.java index 5b6f713f..352cd8e0 100644 --- a/src/main/java/org/broadinstitute/dsde/consent/ontology/datause/MatchV3ResponseEntity.java +++ b/src/main/java/org/broadinstitute/dsde/consent/ontology/datause/MatchV3ResponseEntity.java @@ -8,20 +8,20 @@ public class MatchV3ResponseEntity { private final MatchResultType result; private final DataUseMatchPairV3 matchPair; - private final List failureReasons; + private final List rationale; public MatchV3ResponseEntity(MatchResultType result, DataUseMatchPairV3 matchPair, - List failureReasons) { + List rationale) { this.result = result; this.matchPair = matchPair; - this.failureReasons = failureReasons; + this.rationale = rationale; } public ImmutableMap get() { return ImmutableMap.of( "result", this.result, "matchPair", this.matchPair, - "failureReasons", this.failureReasons); + "rationale", this.rationale); } public MatchResultType getResult() { @@ -31,8 +31,7 @@ public MatchResultType getResult() { public DataUseMatchPairV3 getMatchPair() { return this.matchPair; } - - public List getFailureReasons() { - return this.failureReasons; + public List getRationale() { + return this.rationale; } } diff --git a/src/main/java/org/broadinstitute/dsde/consent/ontology/resources/MatchResource.java b/src/main/java/org/broadinstitute/dsde/consent/ontology/resources/MatchResource.java index 9af56fa8..f1a7e052 100644 --- a/src/main/java/org/broadinstitute/dsde/consent/ontology/resources/MatchResource.java +++ b/src/main/java/org/broadinstitute/dsde/consent/ontology/resources/MatchResource.java @@ -51,13 +51,13 @@ public Response matchDataUse(final DataUseMatchPair matchPair) { ImmutablePair> matchResult = dataUseMatcher.matchPurposeAndDatasetV2( purpose, dataset); boolean match = matchResult.getLeft(); - List failures = matchResult.getRight(); + List rationale = matchResult.getRight(); return Response .ok() .entity(ImmutableMap.of( "result", match, "matchPair", matchPair, - "failureReasons", failures)) + "rationale", rationale)) .type(MediaType.APPLICATION_JSON) .build(); } @@ -97,11 +97,11 @@ public Response matchDataUseV3(final DataUseMatchPairV3 matchPair) { if (purpose != null && dataset != null) { MatchResult matchResult = dataUseMatcherV3.matchPurposeAndDatasetV3(purpose, dataset); MatchResultType match = matchResult.getMatchResultType(); - List failures = matchResult.getMessage(); + List rationale = matchResult.getMessage(); // nosemgrep return Response .ok() - .entity(new MatchV3ResponseEntity(match, matchPair, failures).get()) + .entity(new MatchV3ResponseEntity(match, matchPair, rationale).get()) .type(MediaType.APPLICATION_JSON) .build(); } diff --git a/src/main/resources/assets/api-docs.yaml b/src/main/resources/assets/api-docs.yaml index 51fd3957..34d318c3 100644 --- a/src/main/resources/assets/api-docs.yaml +++ b/src/main/resources/assets/api-docs.yaml @@ -360,7 +360,7 @@ definitions: matchPair: $ref: '#/definitions/DataUseMatchPair' description: The provided purpose and consent - failureReasons: + rationale: type: array items: type: string @@ -387,12 +387,12 @@ definitions: matchPair: $ref: '#/definitions/DataUseMatchPairV3' description: The provided purpose and consent - failureReasons: + rationale: type: array items: type: string description: | - Optional list of reasons why a match result may have failed. Only supported in + List of reasons why a match result occurred. Only supported in in versions 2 and higher TranslateParagraph: diff --git a/src/test/java/org/broadinstitute/dsde/consent/ontology/datause/DataUseMatcherV3Test.java b/src/test/java/org/broadinstitute/dsde/consent/ontology/datause/DataUseMatcherV3Test.java index 45045dd8..013d1f58 100644 --- a/src/test/java/org/broadinstitute/dsde/consent/ontology/datause/DataUseMatcherV3Test.java +++ b/src/test/java/org/broadinstitute/dsde/consent/ontology/datause/DataUseMatcherV3Test.java @@ -257,7 +257,6 @@ public void testAbstainDecision_ethicsApprovalRequired() { private void assertApprove(DataUseV3 purpose, DataUseV3 dataset) { MatchResult match = matchPurposeAndDataset(purpose, dataset); assertTrue(Approve(match.getMatchResultType())); - assertTrue(match.getMessage().isEmpty()); } private void assertDeny(DataUseV3 purpose, DataUseV3 dataset) { diff --git a/src/test/java/org/broadinstitute/dsde/consent/ontology/resources/MatchResourceTest.java b/src/test/java/org/broadinstitute/dsde/consent/ontology/resources/MatchResourceTest.java index bad9a1f9..78dbd7c3 100644 --- a/src/test/java/org/broadinstitute/dsde/consent/ontology/resources/MatchResourceTest.java +++ b/src/test/java/org/broadinstitute/dsde/consent/ontology/resources/MatchResourceTest.java @@ -131,7 +131,7 @@ public void testOKV3ResponseApprove() { MatchV3ResponseEntity entity = new Gson().fromJson(stringEntity, MatchV3ResponseEntity.class); assertEquals(MatchResultType.APPROVE, entity.getResult()); assertEquals(pair, entity.getMatchPair()); - assertEquals(Collections.emptyList(), entity.getFailureReasons()); + assertEquals(Collections.emptyList(), entity.getRationale()); } } @@ -152,7 +152,7 @@ public void testOKV3ResponseDeny() { MatchV3ResponseEntity entity = new Gson().fromJson(stringEntity, MatchV3ResponseEntity.class); assertEquals(deny, entity.getResult()); assertEquals(pair, entity.getMatchPair()); - assertEquals(Collections.emptyList(), entity.getFailureReasons()); + assertEquals(Collections.emptyList(), entity.getRationale()); } } @@ -173,7 +173,7 @@ public void testOKV3ResponseAbstain() { MatchV3ResponseEntity entity = new Gson().fromJson(stringEntity, MatchV3ResponseEntity.class); assertEquals(abstain, entity.getResult()); assertEquals(pair, entity.getMatchPair()); - assertEquals(Collections.emptyList(), entity.getFailureReasons()); + assertEquals(Collections.emptyList(), entity.getRationale()); } }