001package org.hl7.fhir.convertors.misc; 002 003 004import java.io.FileInputStream; 005import java.io.FileNotFoundException; 006import java.io.FileOutputStream; 007import java.io.IOException; 008import java.util.HashMap; 009import java.util.Map; 010 011import org.fhir.ucum.Utilities; 012import org.hl7.fhir.exceptions.FHIRException; 013import org.hl7.fhir.r5.formats.IParser.OutputStyle; 014import org.hl7.fhir.r5.formats.JsonParser; 015import org.hl7.fhir.r5.model.BooleanType; 016import org.hl7.fhir.r5.model.CodeSystem; 017import org.hl7.fhir.r5.model.CodeSystem.CodeSystemHierarchyMeaning; 018import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent; 019import org.hl7.fhir.r5.model.CodeSystem.PropertyType; 020import org.hl7.fhir.r5.model.CodeType; 021import org.hl7.fhir.utilities.CSVReader; 022import org.hl7.fhir.utilities.filesystem.ManagedFileAccess; 023 024public class ICFImporter { 025 026 public static void main(String[] args) throws FHIRException, FileNotFoundException, IOException { 027 new ICFImporter().doImport(args[0], args[1]); 028 029 } 030 031 private void doImport(String src, String dst) throws FHIRException, FileNotFoundException, IOException { 032 CSVReader csv = new CSVReader(ManagedFileAccess.inStream(src)); 033 csv.setDelimiter('\t'); 034 csv.readHeaders(); 035 036 CodeSystem cs = new CodeSystem(); 037 cs.setId("icf"); 038 cs.setUrl("http://id.who.int/icd/release/11/beta/icf"); 039 cs.setVersion("2023-06"); 040 cs.setName("WHOICF"); 041 cs.setTitle("WHO ICF"); 042 cs.setHierarchyMeaning(CodeSystemHierarchyMeaning.CLASSIFIEDWITH); 043 cs.setCopyright("© World Health Organization 2022\r\nSome rights reserved. This work is available under the Creative Commons Attribution-NoDerivatives 3.0 IGO license (CC BY-ND 3.0 IGO further specified at [[https://icd.who.int/en/docs/ICD11-license.pdf]]). \r\nUnder the terms of this license, you may copy and redistribute the work, provided the work is appropriately cited, as indicated below. In any use of this work, there should be no suggestion that WHO endorses any specific organization, products or services. The use of the WHO logo is not permitted. This license does not allow you to produce adaptations of the work (including translations) without permission from WHO.\r\nAny mediation relating to disputes arising under the license shall be conducted in accordance with the mediation rules of the World Intellectual Property Organization.\r\nThis FHIR version of ICD-11 was generated to support the FHIR Community. The definitive version of ICD-11 is available from [[https://icd.who.int/browse11/l-m/en]].\r\n"); 044 045 cs.addProperty().setCode("icd11-uri").setDescription("Entity URI to map to ICD_11").setType(PropertyType.CODE); 046 cs.addProperty().setCode("kind").setDescription("Whether concept is chapter, block, or category").setType(PropertyType.CODE); 047 cs.addProperty().setCode("IsResidual").setDescription("True if the concept is not completely defined by ICD-11").setType(PropertyType.BOOLEAN); 048 Map<String, ConceptDefinitionComponent> codes = new HashMap<>(); 049 050 int lastChapter = 0; 051 int lastBlock = 0; 052 while (csv.line()) { 053 String kind = csv.cell("ClassKind"); 054 String code = csv.cell("Code"); 055 if (Utilities.noString(code)) { 056 code = csv.cell("BlockId"); 057 } 058 ConceptDefinitionComponent c = new ConceptDefinitionComponent(); 059 c.setCode(code); 060 c.setDisplay(fixDisplay(csv.cell("Title"))); 061 c.addProperty().setCode("uri").setValue(new CodeType(csv.cell("Linearization (release) URI"))); 062 c.addProperty().setCode("kind").setValue(new CodeType(kind)); 063 String b = csv.cell("IsResidual").toLowerCase(); 064 if (!"false".equals(b)) { 065 c.addProperty().setCode("IsResidual").setValue(new BooleanType(b)); 066 } 067 int level = Integer.parseInt(csv.cell("DepthInKind")); 068 String id = kind+"-"+level; 069 String parentId = null; 070 switch (kind) { 071 case "chapter": 072 parentId = null; 073 lastChapter = level; 074 break; 075 case "block": 076 parentId = "chapter-"+lastChapter; 077 lastBlock = level; 078 break; 079 case "category": 080 parentId = "block-"+lastBlock; 081 break; 082 } 083 if (level > 1) { 084 parentId = kind+"-"+(level - 1); 085 } 086 System.out.println(code+" "+kind+" "+level+" "+id+" "+parentId+" ("+lastChapter+" "+lastBlock+")"); 087 if (parentId == null) { 088 cs.getConcept().add(c); 089 } else { 090 ConceptDefinitionComponent p = codes.get(parentId); 091 p.getConcept().add(c); 092 } 093 codes.put(id, c); 094 for (int i = level + 1; i < 100; i++) { 095 if (codes.containsKey(i)) { 096 codes.remove(i); 097 } 098 } 099 100 } 101 csv.close(); 102 new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(dst), cs); 103 } 104// 105// private String processLink(String cell) { 106// String[] p = cell.split("\\\"\\\""); 107// return p[1]; 108// } 109 110 private String fixDisplay(String cell) { 111 int i = 0; 112 while (i < cell.length() && (cell.charAt(i) == ' ' || cell.charAt(i) == '-')) { 113 i++; 114 } 115 return cell.substring(i); 116 } 117 118}