Skip to content

Commit ceac280

Browse files
IanMMarshallIan Marshall
andauthored
7386 icd10cmloader is not creating required extensions for concepts (#7392)
* Fix logic in Icd10CmLoader to append 7th character extensions to the leaf-level concepts in the hierarchy (rather than to just the immediate child concepts). * Fix logic in Icd10CmLoader to append 7th character extensions to the leaf-level concepts in the hierarchy (rather than to just the immediate child concepts). * Fix logic in Icd10CmLoader to append 7th character extensions to the leaf-level concepts in the hierarchy (rather than to just the immediate child concepts). --------- Co-authored-by: Ian Marshall <[email protected]>
1 parent 95ac342 commit ceac280

File tree

5 files changed

+399
-43
lines changed

5 files changed

+399
-43
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
---
2+
type: fix
3+
issue: 7386
4+
title: "A bug was fixed in Icd10CmLoader where applicable 7th character extensions were not being appended to all child codes."

hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/icd10cm/Icd10CmLoader.java

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929

3030
import java.io.IOException;
3131
import java.io.Reader;
32+
import java.util.List;
3233

3334
import static org.apache.commons.lang3.StringUtils.isNotBlank;
3435

@@ -37,10 +38,7 @@ public class Icd10CmLoader {
3738
private final TermCodeSystemVersion myCodeSystemVersion;
3839
private int myConceptCount;
3940
private static final String SEVEN_CHR_DEF = "sevenChrDef";
40-
private static final String VERSION = "version";
4141
private static final String EXTENSION = "extension";
42-
private static final String CHAPTER = "chapter";
43-
private static final String SECTION = "section";
4442
private static final String DIAG = "diag";
4543
private static final String NAME = "name";
4644
private static final String DESC = "desc";
@@ -70,16 +68,16 @@ public void load(Reader theReader) throws IOException, SAXException {
7068
for (Element nextChapter : XmlUtil.getChildrenByTagName(documentElement, "chapter")) {
7169
for (Element nextSection : XmlUtil.getChildrenByTagName(nextChapter, "section")) {
7270
for (Element nextDiag : XmlUtil.getChildrenByTagName(nextSection, "diag")) {
73-
extractCode(nextDiag, null);
71+
extractCode(nextDiag, null, null);
7472
}
7573
}
7674
}
7775
}
7876

79-
private void extractCode(Element theDiagElement, TermConcept theParentConcept) {
77+
private void extractCode(Element theDiagElement, TermConcept theParentConcept, List<Element> theParentSevenChrDef) {
8078
String code = theDiagElement.getElementsByTagName(NAME).item(0).getTextContent();
8179
String display = theDiagElement.getElementsByTagName(DESC).item(0).getTextContent();
82-
80+
List<Element> mySevenChrDef = null;
8381
TermConcept concept;
8482
if (theParentConcept == null) {
8583
concept = myCodeSystemVersion.addConcept();
@@ -90,21 +88,46 @@ private void extractCode(Element theDiagElement, TermConcept theParentConcept) {
9088
concept.setCode(code);
9189
concept.setDisplay(display);
9290

93-
for (Element nextChildDiag : XmlUtil.getChildrenByTagName(theDiagElement, DIAG)) {
94-
extractCode(nextChildDiag, concept);
95-
if (XmlUtil.getChildrenByTagName(theDiagElement, SEVEN_CHR_DEF).size() != 0) {
96-
extractExtension(theDiagElement, nextChildDiag, concept);
91+
// Check for seventh character definitions. If none exist at this level,
92+
// use seventh character definitions inherited from parent level.
93+
if (!XmlUtil.getChildrenByTagName(theDiagElement, SEVEN_CHR_DEF).isEmpty()) {
94+
mySevenChrDef = XmlUtil.getChildrenByTagName(theDiagElement, SEVEN_CHR_DEF);
95+
} else if (theParentSevenChrDef != null) {
96+
mySevenChrDef = theParentSevenChrDef.stream().toList();
97+
}
98+
99+
// If this concept has no children, apply the seventh character definitions.
100+
// Otherwise create the children.
101+
if (mySevenChrDef != null
102+
&& XmlUtil.getChildrenByTagName(theDiagElement, DIAG).isEmpty()) {
103+
if (theParentConcept == null) {
104+
// This is a root concept. Add the extensions as children of the current concept.
105+
extractExtension(mySevenChrDef, theDiagElement, concept, true);
106+
} else {
107+
// This is a child concept. Add the extensions as siblings of the current concept
108+
extractExtension(mySevenChrDef, theDiagElement, theParentConcept, false);
109+
}
110+
} else {
111+
for (Element nextChildDiag : XmlUtil.getChildrenByTagName(theDiagElement, DIAG)) {
112+
extractCode(nextChildDiag, concept, mySevenChrDef);
97113
}
98114
}
99115

100116
myConceptCount++;
101117
}
102118

103-
private void extractExtension(Element theDiagElement, Element theChildDiag, TermConcept theParentConcept) {
104-
for (Element nextChrNote : XmlUtil.getChildrenByTagName(theDiagElement, SEVEN_CHR_DEF)) {
119+
private void extractExtension(
120+
List<Element> theSevenChrDefElement,
121+
Element theChildDiag,
122+
TermConcept theParentConcept,
123+
boolean isRootCode) {
124+
for (Element nextChrNote : theSevenChrDefElement) {
105125
for (Element nextExtension : XmlUtil.getChildrenByTagName(nextChrNote, EXTENSION)) {
106126
String baseCode =
107127
theChildDiag.getElementsByTagName(NAME).item(0).getTextContent();
128+
if (isRootCode) {
129+
baseCode = baseCode + ".";
130+
}
108131
String sevenChar = nextExtension.getAttributes().item(0).getNodeValue();
109132
String baseDef = theChildDiag.getElementsByTagName(DESC).item(0).getTextContent();
110133
String sevenCharDef = nextExtension.getTextContent();
@@ -127,12 +150,10 @@ private String getExtendedDisplay(String theBaseDef, String theSevenCharDef) {
127150
*/
128151
private String getExtendedCode(String theBaseCode, String theSevenChar) {
129152
String placeholder = "X";
130-
String code = theBaseCode;
131-
for (int i = code.length(); i < 7; i++) {
132-
code += placeholder;
133-
}
134-
code += theSevenChar;
135-
return code;
153+
StringBuilder code = new StringBuilder(theBaseCode);
154+
code.append(placeholder.repeat(Math.max(0, 7 - code.length())));
155+
code.append(theSevenChar);
156+
return code.toString();
136157
}
137158

138159
public int getConceptCount() {

hapi-fhir-jpaserver-test-r4/src/test/java/ca/uhn/fhir/jpa/term/TerminologyLoaderSvcIcd10cmJpaTest.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,26 +9,24 @@
99
import org.junit.jupiter.api.BeforeEach;
1010
import org.junit.jupiter.api.Test;
1111

12-
import java.io.IOException;
1312
import java.nio.charset.StandardCharsets;
1413
import java.util.ArrayList;
1514
import java.util.List;
1615

1716
import static org.junit.jupiter.api.Assertions.assertEquals;
1817

19-
public class TerminologyLoaderSvcIcd10cmJpaTest extends BaseJpaR4Test {
18+
class TerminologyLoaderSvcIcd10cmJpaTest extends BaseJpaR4Test {
2019
private TermLoaderSvcImpl mySvc;
21-
private ZipCollectionBuilder myFiles;
2220

2321
@BeforeEach
22+
@Override
2423
public void before() {
2524
mySvc = new TermLoaderSvcImpl(myTerminologyDeferredStorageSvc, myTermCodeSystemStorageSvc);
2625

27-
myFiles = new ZipCollectionBuilder();
2826
}
2927

3028
@Test
31-
public void testLoadIcd10cm() throws IOException {
29+
void testLoadIcd10cm() {
3230
String filename = "icd/icd10cm_tabular_2021.xml";
3331

3432
String resource = ClasspathUtil.loadResource(filename);
@@ -44,7 +42,7 @@ public void testLoadIcd10cm() throws IOException {
4442
assertEquals(0, myTermValueSetDao.count());
4543
assertEquals(0, myTermConceptMapDao.count());
4644
assertEquals(1, myResourceTableDao.count());
47-
assertEquals(43, myTermConceptDao.count());
45+
assertEquals(95, myTermConceptDao.count());
4846
TermCodeSystem codeSystem = myTermCodeSystemDao.findByCodeSystemUri(ITermLoaderSvc.ICD10CM_URI);
4947

5048
assertEquals("2021", codeSystem.getCurrentVersion().getCodeSystemVersionId());

0 commit comments

Comments
 (0)