Skip to content

Commit c9be6f8

Browse files
Merge pull request #219 from MeasureAuthoringTool/MAT-10219
MAT-10219 namespace registery endpoint
2 parents 4e347d3 + 6471e0c commit c9be6f8

7 files changed

Lines changed: 167 additions & 0 deletions

File tree

src/main/java/gov/cms/madie/cqllibraryservice/controllers/CqlLibraryController.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,7 @@ public class CqlLibraryController {
5151
private final CqlDifferentiatorService cqlDifferentiatorService;
5252
private final CqlLibraryLockService cqlLibraryLockService;
5353
private final AppConfigService appConfigService;
54+
private final NamespaceService namespaceService;
5455

5556
@PutMapping("/searches")
5657
public ResponseEntity<Page<LibraryListDTO>> fetchLibrariesByCriteria(
@@ -77,6 +78,11 @@ public ResponseEntity<List<String>> getAllOwners(
7778
return ResponseEntity.status(HttpStatus.OK).body(results);
7879
}
7980

81+
@GetMapping("/namespaces")
82+
public ResponseEntity<List<NamespaceDTO>> getAllNamespaces() {
83+
return ResponseEntity.ok(namespaceService.getAllNamespaces());
84+
}
85+
8086
@GetMapping("/{id}")
8187
public ResponseEntity<CqlLibrary> getCqlLibrary(
8288
@PathVariable("id") String id, Principal principal) {
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
package gov.cms.madie.cqllibraryservice.dto;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Builder;
5+
import lombok.Data;
6+
import lombok.NoArgsConstructor;
7+
8+
@Data
9+
@Builder
10+
@NoArgsConstructor
11+
@AllArgsConstructor
12+
public class NamespaceDTO {
13+
14+
private String namespaceCanonical;
15+
private String namespacePrefix;
16+
}

src/main/java/gov/cms/madie/cqllibraryservice/repositories/ExternalLibraryRepository.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,11 @@
11
package gov.cms.madie.cqllibraryservice.repositories;
22

3+
import gov.cms.madie.cqllibraryservice.dto.NamespaceDTO;
34
import gov.cms.madie.cqllibraryservice.models.ExternalLibrary;
5+
import org.springframework.data.mongodb.repository.Aggregation;
46
import org.springframework.data.mongodb.repository.MongoRepository;
57

8+
import java.util.List;
69
import java.util.Optional;
710

811
public interface ExternalLibraryRepository extends MongoRepository<ExternalLibrary, String> {
@@ -12,4 +15,20 @@ Optional<ExternalLibrary> findByPackageCanonicalAndLibraryName(
1215

1316
boolean existsByPackageCanonicalAndLibraryNameAndVersion(
1417
String canonical, String libraryName, String version);
18+
19+
/**
20+
* Returns every distinct {@code (packageCanonical, namespacePrefix)} pair present in the External
21+
* Libraries collection, sorted by canonical.
22+
*/
23+
@Aggregation(
24+
pipeline = {
25+
"{'$match': {'packageCanonical': {'$nin': [null, '']},"
26+
+ " 'namespacePrefix': {'$nin': [null, '']}}}",
27+
"{'$group': {'_id': {'canonical': '$packageCanonical', 'prefix': '$namespacePrefix'}}}",
28+
"{'$project': {'_id': 0,"
29+
+ " 'namespaceCanonical': '$_id.canonical',"
30+
+ " 'namespacePrefix': '$_id.prefix'}}",
31+
"{'$sort': {'namespaceCanonical': 1}}"
32+
})
33+
List<NamespaceDTO> findDistinctNamespaces();
1534
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package gov.cms.madie.cqllibraryservice.services;
2+
3+
import gov.cms.madie.cqllibraryservice.dto.NamespaceDTO;
4+
import gov.cms.madie.cqllibraryservice.repositories.ExternalLibraryRepository;
5+
import lombok.RequiredArgsConstructor;
6+
import lombok.extern.slf4j.Slf4j;
7+
import org.springframework.stereotype.Service;
8+
9+
import java.util.List;
10+
11+
@Slf4j
12+
@Service
13+
@RequiredArgsConstructor
14+
public class NamespaceService {
15+
16+
private final ExternalLibraryRepository externalLibraryRepository;
17+
18+
public List<NamespaceDTO> getAllNamespaces() {
19+
List<NamespaceDTO> namespaces = externalLibraryRepository.findDistinctNamespaces();
20+
log.info("Found [{}] known namespaces", namespaces.size());
21+
return namespaces;
22+
}
23+
}

src/test/java/gov/cms/madie/cqllibraryservice/controllers/CqlLibraryControllerMvcTest.java

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ public class CqlLibraryControllerMvcTest {
8686
@MockitoBean ActionLogService actionLogService;
8787
@MockitoBean private UserServiceClient userServiceClient;
8888
@MockitoBean private CqlLibraryLockService cqlLibraryLockService;
89+
@MockitoBean private NamespaceService namespaceService;
8990

9091
@Captor private ArgumentCaptor<CqlLibrary> cqlLibraryArgumentCaptor;
9192

@@ -525,6 +526,30 @@ public void testCreateCqlLibraryReturnsCreatedForUsQualityCoreWhenFlagEnabled()
525526
.andExpect(jsonPath("$.createdBy").value(TEST_USER_ID));
526527
}
527528

529+
@Test
530+
public void testGetAllNamespacesReturnsKnownNamespaces() throws Exception {
531+
when(namespaceService.getAllNamespaces())
532+
.thenReturn(
533+
List.of(
534+
NamespaceDTO.builder()
535+
.namespaceCanonical("http://hl7.org/fhir/us/qicore")
536+
.namespacePrefix("hl7.fhir.us.qicore")
537+
.build(),
538+
NamespaceDTO.builder()
539+
.namespaceCanonical("http://hl7.org/fhir/uv/cqm")
540+
.namespacePrefix("hl7.fhir.uv.cqm")
541+
.build()));
542+
mockMvc
543+
.perform(get("/cql-libraries/namespaces").with(user(TEST_USER_ID)).with(csrf()))
544+
.andExpect(status().isOk())
545+
.andExpect(jsonPath("$.length()").value(2))
546+
.andExpect(jsonPath("$[0].namespaceCanonical").value("http://hl7.org/fhir/us/qicore"))
547+
.andExpect(jsonPath("$[0].namespacePrefix").value("hl7.fhir.us.qicore"))
548+
.andExpect(jsonPath("$[1].namespaceCanonical").value("http://hl7.org/fhir/uv/cqm"))
549+
.andExpect(jsonPath("$[1].namespacePrefix").value("hl7.fhir.uv.cqm"));
550+
verify(namespaceService, times(1)).getAllNamespaces();
551+
}
552+
528553
@Test
529554
public void testGetCqlLibraryReturns404() throws Exception {
530555
doThrow(new ResourceNotFoundException("CQL Library", "Library1_ID"))

src/test/java/gov/cms/madie/cqllibraryservice/controllers/CqlLibraryControllerTest.java

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
import gov.cms.madie.cqllibraryservice.dto.LibraryListDTO;
1616
import gov.cms.madie.cqllibraryservice.dto.LibrarySearchCriteria;
1717
import gov.cms.madie.cqllibraryservice.dto.MadieFeatureFlag;
18+
import gov.cms.madie.cqllibraryservice.dto.NamespaceDTO;
1819
import gov.cms.madie.cqllibraryservice.exceptions.BadRequestObjectException;
1920
import gov.cms.madie.cqllibraryservice.exceptions.InvalidIdException;
2021
import gov.cms.madie.cqllibraryservice.exceptions.PermissionDeniedException;
@@ -57,6 +58,8 @@ class CqlLibraryControllerTest {
5758

5859
@Mock private AppConfigService appConfigService;
5960

61+
@Mock private NamespaceService namespaceService;
62+
6063
@Mock Principal principal;
6164

6265
@InjectMocks CqlLibraryController cqlLibraryController;
@@ -404,6 +407,22 @@ public void testGetAllOwners() {
404407
assertEquals(mockedResponse, result.getBody());
405408
}
406409

410+
@Test
411+
public void testGetAllNamespaces() {
412+
List<NamespaceDTO> mockedResponse =
413+
List.of(
414+
NamespaceDTO.builder()
415+
.namespaceCanonical("http://hl7.org/fhir/us/qicore")
416+
.namespacePrefix("hl7.fhir.us.qicore")
417+
.build());
418+
when(namespaceService.getAllNamespaces()).thenReturn(mockedResponse);
419+
420+
ResponseEntity<List<NamespaceDTO>> response = cqlLibraryController.getAllNamespaces();
421+
422+
assertEquals(HttpStatus.OK, response.getStatusCode());
423+
assertEquals(mockedResponse, response.getBody());
424+
}
425+
407426
@Test
408427
public void testGetCqlLibraryThrowsExceptionForNotFound() {
409428
Principal principal = mock(Principal.class);
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
package gov.cms.madie.cqllibraryservice.services;
2+
3+
import gov.cms.madie.cqllibraryservice.dto.NamespaceDTO;
4+
import gov.cms.madie.cqllibraryservice.repositories.ExternalLibraryRepository;
5+
import org.junit.jupiter.api.Test;
6+
import org.junit.jupiter.api.extension.ExtendWith;
7+
import org.mockito.InjectMocks;
8+
import org.mockito.Mock;
9+
import org.mockito.junit.jupiter.MockitoExtension;
10+
11+
import java.util.List;
12+
13+
import static org.hamcrest.MatcherAssert.assertThat;
14+
import static org.hamcrest.Matchers.equalTo;
15+
import static org.hamcrest.Matchers.is;
16+
import static org.mockito.Mockito.when;
17+
18+
@ExtendWith(MockitoExtension.class)
19+
class NamespaceServiceTest {
20+
21+
@Mock private ExternalLibraryRepository externalLibraryRepository;
22+
23+
@InjectMocks private NamespaceService namespaceService;
24+
25+
@Test
26+
void testGetAllNamespacesReturnsAllKnownNamespaces() {
27+
NamespaceDTO qiCore =
28+
NamespaceDTO.builder()
29+
.namespaceCanonical("http://hl7.org/fhir/us/qicore")
30+
.namespacePrefix("hl7.fhir.us.qicore")
31+
.build();
32+
NamespaceDTO cqfmScoring =
33+
NamespaceDTO.builder()
34+
.namespaceCanonical("http://hl7.org/fhir/uv/cqm")
35+
.namespacePrefix("hl7.fhir.uv.cqm")
36+
.build();
37+
when(externalLibraryRepository.findDistinctNamespaces())
38+
.thenReturn(List.of(qiCore, cqfmScoring));
39+
40+
List<NamespaceDTO> namespaces = namespaceService.getAllNamespaces();
41+
42+
assertThat(namespaces.size(), is(equalTo(2)));
43+
assertThat(
44+
namespaces.get(0).getNamespaceCanonical(), is(equalTo("http://hl7.org/fhir/us/qicore")));
45+
assertThat(namespaces.get(0).getNamespacePrefix(), is(equalTo("hl7.fhir.us.qicore")));
46+
assertThat(
47+
namespaces.get(1).getNamespaceCanonical(), is(equalTo("http://hl7.org/fhir/uv/cqm")));
48+
assertThat(namespaces.get(1).getNamespacePrefix(), is(equalTo("hl7.fhir.uv.cqm")));
49+
}
50+
51+
@Test
52+
void testGetAllNamespacesReturnsEmptyListWhenNoExternalLibrariesExist() {
53+
when(externalLibraryRepository.findDistinctNamespaces()).thenReturn(List.of());
54+
55+
List<NamespaceDTO> namespaces = namespaceService.getAllNamespaces();
56+
57+
assertThat(namespaces.isEmpty(), is(true));
58+
}
59+
}

0 commit comments

Comments
 (0)