diff --git a/pom.xml b/pom.xml
index f44b0e08a0..f82a63ccb3 100644
--- a/pom.xml
+++ b/pom.xml
@@ -769,6 +769,12 @@
json-smart
2.4.9
+
+ net.minidev
+ asm
+ 1.0.2
+ test
+
org.apache.commons
commons-lang3
diff --git a/src/main/java/org/ohdsi/webapi/cdmresults/service/CDMCacheService.java b/src/main/java/org/ohdsi/webapi/cdmresults/service/CDMCacheService.java
index a4ec88b38e..e3870609d4 100644
--- a/src/main/java/org/ohdsi/webapi/cdmresults/service/CDMCacheService.java
+++ b/src/main/java/org/ohdsi/webapi/cdmresults/service/CDMCacheService.java
@@ -145,9 +145,9 @@ private void cacheRecordsById(Source source, List ids) {
PreparedStatementRenderer psr = getPartialPreparedStatementRenderer(source, idsSlice);
Set cachedIds = loadCache(source, psr, mapper, jdbcTemplate);
// in this batch, need to save any concepts that were not found when loading cache
- idsSlice.removeAll(cachedIds);
- if (!idsSlice.isEmpty()) { // store zeros in cache
- List zeroConcepts = idsSlice.stream().map(id -> {
+ List notFoundIds = new ArrayList(CollectionUtils.subtract(idsSlice, cachedIds));
+ if (!notFoundIds.isEmpty()) { // store zeros in cache
+ List zeroConcepts = notFoundIds.stream().map(id -> {
CDMCacheEntity ce = new CDMCacheEntity();
ce.setConceptId(id);
ce.setRecordCount(0L);
diff --git a/src/main/resources/ddl/results/achilles_result_concept_count.sql b/src/main/resources/ddl/results/achilles_result_concept_count.sql
new file mode 100644
index 0000000000..b11087a543
--- /dev/null
+++ b/src/main/resources/ddl/results/achilles_result_concept_count.sql
@@ -0,0 +1,8 @@
+IF OBJECT_ID('@results_schema.achilles_result_concept_count', 'U') IS NULL
+CREATE TABLE @results_schema.achilles_result_concept_count (
+ concept_id int,
+ record_count bigint,
+ descendant_record_count bigint,
+ person_count bigint,
+ descendant_person_count bigint
+);
\ No newline at end of file
diff --git a/src/test/java/org/ohdsi/webapi/test/CDMResultsServiceIT.java b/src/test/java/org/ohdsi/webapi/test/CDMResultsServiceIT.java
new file mode 100644
index 0000000000..72635bad7a
--- /dev/null
+++ b/src/test/java/org/ohdsi/webapi/test/CDMResultsServiceIT.java
@@ -0,0 +1,81 @@
+package org.ohdsi.webapi.test;
+
+import com.odysseusinc.arachne.commons.types.DBMSType;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.ohdsi.circe.helper.ResourceHelper;
+import org.ohdsi.sql.SqlRender;
+import org.ohdsi.sql.SqlTranslate;
+import org.ohdsi.webapi.source.SourceRepository;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.http.ResponseEntity;
+
+public class CDMResultsServiceIT extends WebApiIT {
+ private static final String CDM_RESULTS_FILE_PATH = "/database/cdm_results.sql";
+
+ @Value("${cdmResultsService.endpoint.conceptRecordCount}")
+ private String conceptRecordCountEndpoint;
+
+ @Autowired
+ private SourceRepository sourceRepository;
+
+ @Before
+ public void init() throws Exception {
+ truncateTable(String.format("%s.%s", "public", "source"));
+ resetSequence(String.format("%s.%s", "public", "source_sequence"));
+ sourceRepository.saveAndFlush(getCdmSource());
+ prepareCdmSchema();
+ prepareResultSchema();
+ addCDMResults();
+ }
+
+ private void addCDMResults() {
+ String resultSql = SqlRender.renderSql(ResourceHelper.GetResourceAsString(
+ CDM_RESULTS_FILE_PATH),
+ new String[] { "results_schema" }, new String[] { RESULT_SCHEMA_NAME });
+ String sql = SqlTranslate.translateSql(resultSql, DBMSType.POSTGRESQL.getOhdsiDB());
+ jdbcTemplate.execute(sql);
+ }
+
+ @Test
+ public void requestConceptRecordCounts_firstTime_returnsResults() {
+
+ // Arrange
+ List conceptIds = Arrays.asList(1);
+ Map queryParameters = new HashMap();
+ queryParameters.put("sourceName", SOURCE_KEY);
+
+ List>> list = new ArrayList<>();
+ @SuppressWarnings("unchecked")
+ Class>>> returnClass = (Class>>>)list.getClass();
+
+ // Act
+ final ResponseEntity>>> entity = getRestTemplate().postForEntity(this.conceptRecordCountEndpoint, conceptIds,
+ returnClass, queryParameters );
+
+ // Assertion
+ assertOK(entity);
+ List>> results = entity.getBody();
+ assertEquals(1, results.size());
+ LinkedHashMap> resultHashMap = results.get(0);
+ assertEquals(1, resultHashMap.size());
+ assertTrue(resultHashMap.containsKey("1"));
+ List counts = resultHashMap.get("1");
+ assertEquals(100, counts.get(0).intValue());
+ assertEquals(101, counts.get(1).intValue());
+ assertEquals(102, counts.get(2).intValue());
+ assertEquals(103, counts.get(3).intValue());
+ }
+}
diff --git a/src/test/java/org/ohdsi/webapi/test/WebApiIT.java b/src/test/java/org/ohdsi/webapi/test/WebApiIT.java
index dd7dd57c0d..ed2af1e0c5 100644
--- a/src/test/java/org/ohdsi/webapi/test/WebApiIT.java
+++ b/src/test/java/org/ohdsi/webapi/test/WebApiIT.java
@@ -64,7 +64,8 @@ public abstract class WebApiIT {
"/ddl/results/pathway_analysis_codes.sql",
"/ddl/results/pathway_analysis_events.sql",
"/ddl/results/pathway_analysis_paths.sql",
- "/ddl/results/pathway_analysis_stats.sql"
+ "/ddl/results/pathway_analysis_stats.sql",
+ "/ddl/results/achilles_result_concept_count.sql"
);
diff --git a/src/test/resources/application-test.properties b/src/test/resources/application-test.properties
index f11c6df1b7..3d9a789b5b 100644
--- a/src/test/resources/application-test.properties
+++ b/src/test/resources/application-test.properties
@@ -1,6 +1,7 @@
baseUri=http://localhost:${local.server.port}${server.context-path}
security.db.datasource.url=http://localhost:${datasource.url}/arachne_portal_enterprise
vocabularyservice.endpoint=${baseUri}/vocabulary
+cdmResultsService.endpoint=${baseUri}/cdmresults
#GET vocabularies
vocabularyservice.endpoint.vocabularies=${vocabularyservice.endpoint}/vocabularies
#GET domains
@@ -10,6 +11,9 @@ vocabularyservice.endpoint.concept=${vocabularyservice.endpoint}/concept/1
#GET cohortdefinitions
cohortdefinitionservice.endpoint.cohortdefinitions=${baseUri}/cohortdefinition
+#POST cdmResults
+cdmResultsService.endpoint.conceptRecordCount=${cdmResultsService.endpoint}/{sourceName}/conceptRecordCount
+
#Example application service
exampleservice.endpoint=${baseUri}/example
diff --git a/src/test/resources/database/cdm_results.sql b/src/test/resources/database/cdm_results.sql
new file mode 100644
index 0000000000..ce261c3c5a
--- /dev/null
+++ b/src/test/resources/database/cdm_results.sql
@@ -0,0 +1,2 @@
+insert into @results_schema.achilles_result_concept_count (concept_id, record_count, descendant_record_count, person_count, descendant_person_count)
+values (1,100,101,102,103);
\ No newline at end of file