001package org.hl7.fhir.convertors.misc; 002 003/* 004 Copyright (c) 2011+, HL7, Inc. 005 All rights reserved. 006 007 Redistribution and use in source and binary forms, with or without modification, 008 are permitted provided that the following conditions are met: 009 010 * Redistributions of source code must retain the above copyright notice, this 011 list of conditions and the following disclaimer. 012 * Redistributions in binary form must reproduce the above copyright notice, 013 this list of conditions and the following disclaimer in the documentation 014 and/or other materials provided with the distribution. 015 * Neither the name of HL7 nor the names of its contributors may be used to 016 endorse or promote products derived from this software without specific 017 prior written permission. 018 019 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND 020 ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 021 WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 022 IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 023 INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 024 NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 025 PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 026 WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 027 ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 028 POSSIBILITY OF SUCH DAMAGE. 029 030 */ 031 032 033import org.hl7.fhir.r4.model.CodeSystem; 034import org.hl7.fhir.r4.model.CodeSystem.CodeSystemContentMode; 035import org.hl7.fhir.r4.model.CodeSystem.ConceptDefinitionComponent; 036import org.hl7.fhir.r4.model.CodeSystem.PropertyType; 037import org.hl7.fhir.r4.model.CodeType; 038import org.hl7.fhir.r4.model.ContactPoint.ContactPointSystem; 039import org.hl7.fhir.r4.model.DateTimeType; 040import org.hl7.fhir.r4.model.Enumerations.PublicationStatus; 041import org.hl7.fhir.utilities.xml.XMLUtil; 042import org.w3c.dom.Document; 043import org.w3c.dom.Element; 044import org.xml.sax.SAXException; 045 046import javax.xml.parsers.DocumentBuilder; 047import javax.xml.parsers.DocumentBuilderFactory; 048import javax.xml.parsers.ParserConfigurationException; 049import java.io.FileInputStream; 050import java.io.IOException; 051 052public class CountryCodesConverter { 053 054 055 private String source; 056 private String dest; 057 058 public static void main(String[] args) throws Exception { 059 CountryCodesConverter self = new CountryCodesConverter(); 060 self.source = args[0]; 061 self.dest = args[1]; 062 self.execute(); 063 } 064 065 private void execute() throws ParserConfigurationException, SAXException, IOException { 066 Document src = load(); 067 CodeSystem cs1 = new CodeSystem(); 068 CodeSystem cs2 = new CodeSystem(); 069 CodeSystem cs3 = new CodeSystem(); 070 setMetadata(src, cs1, "iso3166", "urn:iso:std:iso:3166", "", ""); 071 setMetadata(src, cs2, "iso3166-2", "urn:iso:std:iso:3166:-2", "Part2", " Part 2"); 072 cs1.addProperty().setCode("canonical").setDescription("The 2 letter code that identifies the same country (so 2/3/numeric codes can be aligned)").setType(PropertyType.CODE); 073 cs2.addProperty().setCode("country").setDescription("The 2 letter code that identifies the country for the subdivision").setType(PropertyType.CODE); 074 for (Element e : XMLUtil.getNamedChildren(src.getDocumentElement(), "country")) { 075 System.out.println(e.getAttribute("id")); 076 String c2 = XMLUtil.getNamedChildText(e, "alpha-2-code"); 077 String c3 = XMLUtil.getNamedChildText(e, "alpha-3-code"); 078 String cN = XMLUtil.getNamedChildText(e, "numeric-code"); 079 Element n = XMLUtil.getNamedChildByAttribute(e, "short-name", "lang3code", "eng"); 080 if (n == null) 081 n = XMLUtil.getNamedChildByAttribute(e, "short-name-upper-case", "lang3code", "eng"); 082 if (n == null) 083 continue; 084 String name = n.getTextContent(); 085 n = XMLUtil.getNamedChildByAttribute(e, "full-name", "lang3code", "eng"); 086 if (n == null) 087 n = XMLUtil.getNamedChildByAttribute(e, "full-name-upper-case", "lang3code", "eng"); 088 if (n == null) 089 n = XMLUtil.getNamedChildByAttribute(e, "short-name", "lang3code", "eng"); 090 if (n == null) 091 n = XMLUtil.getNamedChildByAttribute(e, "short-name-upper-case", "lang3code", "eng"); 092 String desc = n.getTextContent(); 093 ConceptDefinitionComponent cc = cs1.addConcept(); 094 cc.setCode(c2); 095 cc.setDisplay(name); 096 cc.setDefinition(desc); 097 poplang(e, cc); 098 if (c3 != null) { 099 cc = cs1.addConcept(); 100 cc.setCode(c3); 101 cc.setDisplay(name); 102 cc.setDefinition(desc); 103 cc.addProperty().setCode("canonical").setValue(new CodeType(c2)); 104 poplang(e, cc); 105 } 106 if (cN != null) { 107 cc = cs1.addConcept(); 108 cc.setCode(cN); 109 cc.setDisplay(name); 110 cc.setDefinition(desc); 111 cc.addProperty().setCode("canonical").setValue(new CodeType(c2)); 112 poplang(e, cc); 113 } 114 for (Element sd : XMLUtil.getNamedChildren(e, "subdivision")) { 115 cc = cs2.addConcept(); 116 cc.setCode(XMLUtil.getNamedChildText(sd, "subdivision-code")); 117 Element l = XMLUtil.getNamedChild(sd, "subdivision-locale"); 118 cc.setDisplay(XMLUtil.getNamedChildText(l, "subdivision-locale-name")); 119 cc.addProperty().setCode("country").setValue(new CodeType(c2)); 120 } 121 } 122 cs1.setCount(cs1.getConcept().size()); 123 cs2.setCount(cs2.getConcept().size()); 124 throw new Error("Needs revisiting"); 125// new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(dest, "4.0.1", "package", "CodeSstem-iso3166.json")), cs1); 126// new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(dest, "3.0.2", "package", "CodeSstem-iso3166.json")), cs1); // format hasn't changed 127// new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(dest, "4.0.1", "package", "CodeSstem-iso3166-2.json")), cs2); 128// new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(new FileOutputStream(Utilities.path(dest, "3.0.2", "package", "CodeSstem-iso3166-2.json")), cs2); // format hasn't changed 129 } 130 131 public void setMetadata(Document src, CodeSystem cs, String id, String url, String partName, String partTitle) { 132 cs.setId(id); 133 cs.setUrl(url); 134 cs.setName("ISOCountryCodes" + partName); 135 cs.setTitle("ISO Country Codes (ISO-3166)" + partTitle); 136 cs.setVersion(XMLUtil.getFirstChild(src.getDocumentElement()).getAttribute("version")); 137 cs.setStatus(PublicationStatus.ACTIVE); 138 cs.setExperimental(false); 139 cs.addContact().setName("FHIR Project Team").addTelecom().setSystem(ContactPointSystem.URL).setValue("http://hl7.org/fhir"); 140 cs.setDateElement(new DateTimeType(src.getDocumentElement().getAttribute("generated"))); 141 cs.setCopyright("Copyright ISO. See https://www.iso.org/obp/ui/#search/code/"); 142 cs.setCaseSensitive(true); 143 cs.setContent(CodeSystemContentMode.COMPLETE); 144 cs.setLanguage("en"); 145 } 146 147 public void poplang(Element e, ConceptDefinitionComponent cc) { 148 for (Element el : XMLUtil.getNamedChildren(e, "short-name")) { 149 if (!el.getAttribute("lang3code").equals("eng")) { 150 String l2 = lang3To2(el.getAttribute("lang3code")); 151 if (l2 != null) 152 cc.addDesignation().setLanguage(l2).setValue(el.getTextContent()); 153 } 154 } 155 } 156 157 private String lang3To2(String lang) { 158 if ("abk".equals(lang)) return "ab"; 159 if ("aar".equals(lang)) return "aa"; 160 if ("afr".equals(lang)) return "af"; 161 if ("aka".equals(lang)) return "ak"; 162 if ("sqi".equals(lang)) return "sq"; 163 if ("amh".equals(lang)) return "am"; 164 if ("ara".equals(lang)) return "ar"; 165 if ("arg".equals(lang)) return "an"; 166 if ("hye".equals(lang)) return "hy"; 167 if ("asm".equals(lang)) return "as"; 168 if ("ava".equals(lang)) return "av"; 169 if ("ave".equals(lang)) return "ae"; 170 if ("aym".equals(lang)) return "ay"; 171 if ("aze".equals(lang)) return "az"; 172 if ("bam".equals(lang)) return "bm"; 173 if ("bak".equals(lang)) return "ba"; 174 if ("eus".equals(lang)) return "eu"; 175 if ("bel".equals(lang)) return "be"; 176 if ("ben".equals(lang)) return "bn"; 177 if ("bih".equals(lang)) return "bh"; 178 if ("bis".equals(lang)) return "bi"; 179 if ("bos".equals(lang)) return "bs"; 180 if ("bre".equals(lang)) return "br"; 181 if ("bul".equals(lang)) return "bg"; 182 if ("mya".equals(lang)) return "my"; 183 if ("cat".equals(lang)) return "ca"; 184 if ("khm".equals(lang)) return "km"; 185 if ("cha".equals(lang)) return "ch"; 186 if ("che".equals(lang)) return "ce"; 187 if ("nya".equals(lang)) return "ny"; 188 if ("zho".equals(lang)) return "zh"; 189 if ("chu".equals(lang)) return "cu"; 190 if ("chv".equals(lang)) return "cv"; 191 if ("cor".equals(lang)) return "kw"; 192 if ("cos".equals(lang)) return "co"; 193 if ("cre".equals(lang)) return "cr"; 194 if ("hrv".equals(lang)) return "hr"; 195 if ("ces".equals(lang)) return "cs"; 196 if ("dan".equals(lang)) return "da"; 197 if ("div".equals(lang)) return "dv"; 198 if ("nld".equals(lang)) return "nl"; 199 if ("dzo".equals(lang)) return "dz"; 200 if ("eng".equals(lang)) return "en"; 201 if ("epo".equals(lang)) return "eo"; 202 if ("est".equals(lang)) return "et"; 203 if ("ewe".equals(lang)) return "ee"; 204 if ("fao".equals(lang)) return "fo"; 205 if ("fij".equals(lang)) return "fj"; 206 if ("fin".equals(lang)) return "fi"; 207 if ("fra".equals(lang)) return "fr"; 208 if ("ful".equals(lang)) return "ff"; 209 if ("gla".equals(lang)) return "gd"; 210 if ("glg".equals(lang)) return "gl"; 211 if ("lug".equals(lang)) return "lg"; 212 if ("kat".equals(lang)) return "ka"; 213 if ("deu".equals(lang)) return "de"; 214 if ("ell".equals(lang)) return "el"; 215 if ("grn".equals(lang)) return "gn"; 216 if ("guj".equals(lang)) return "gu"; 217 if ("hat".equals(lang)) return "ht"; 218 if ("hau".equals(lang)) return "ha"; 219 if ("heb".equals(lang)) return "he"; 220 if ("her".equals(lang)) return "hz"; 221 if ("hin".equals(lang)) return "hi"; 222 if ("hmo".equals(lang)) return "ho"; 223 if ("hun".equals(lang)) return "hu"; 224 if ("isl".equals(lang)) return "is"; 225 if ("ido".equals(lang)) return "io"; 226 if ("ibo".equals(lang)) return "ig"; 227 if ("ind".equals(lang)) return "id"; 228 if ("ina".equals(lang)) return "ia"; 229 if ("ile".equals(lang)) return "ie"; 230 if ("iku".equals(lang)) return "iu"; 231 if ("ipk".equals(lang)) return "ik"; 232 if ("gle".equals(lang)) return "ga"; 233 if ("ita".equals(lang)) return "it"; 234 if ("jpn".equals(lang)) return "ja"; 235 if ("jav".equals(lang)) return "jv"; 236 if ("kal".equals(lang)) return "kl"; 237 if ("kan".equals(lang)) return "kn"; 238 if ("kau".equals(lang)) return "kr"; 239 if ("kas".equals(lang)) return "ks"; 240 if ("kaz".equals(lang)) return "kk"; 241 if ("kik".equals(lang)) return "ki"; 242 if ("kin".equals(lang)) return "rw"; 243 if ("kir".equals(lang)) return "ky"; 244 if ("kom".equals(lang)) return "kv"; 245 if ("kon".equals(lang)) return "kg"; 246 if ("kor".equals(lang)) return "ko"; 247 if ("kua".equals(lang)) return "kj"; 248 if ("kur".equals(lang)) return "ku"; 249 if ("lao".equals(lang)) return "lo"; 250 if ("lat".equals(lang)) return "la"; 251 if ("lav".equals(lang)) return "lv"; 252 if ("lim".equals(lang)) return "li"; 253 if ("lin".equals(lang)) return "ln"; 254 if ("lit".equals(lang)) return "lt"; 255 if ("lub".equals(lang)) return "lu"; 256 if ("ltz".equals(lang)) return "lb"; 257 if ("mkd".equals(lang)) return "mk"; 258 if ("mlg".equals(lang)) return "mg"; 259 if ("msa".equals(lang)) return "ms"; 260 if ("mal".equals(lang)) return "ml"; 261 if ("mlt".equals(lang)) return "mt"; 262 if ("glv".equals(lang)) return "gv"; 263 if ("mri".equals(lang)) return "mi"; 264 if ("mar".equals(lang)) return "mr"; 265 if ("mah".equals(lang)) return "mh"; 266 if ("mon".equals(lang)) return "mn"; 267 if ("nau".equals(lang)) return "na"; 268 if ("nav".equals(lang)) return "nv"; 269 if ("ndo".equals(lang)) return "ng"; 270 if ("nep".equals(lang)) return "ne"; 271 if ("nde".equals(lang)) return "nd"; 272 if ("sme".equals(lang)) return "se"; 273 if ("nor".equals(lang)) return "no"; 274 if ("nob".equals(lang)) return "nb"; 275 if ("nno".equals(lang)) return "nn"; 276 if ("oci".equals(lang)) return "oc"; 277 if ("oji".equals(lang)) return "oj"; 278 if ("ori".equals(lang)) return "or"; 279 if ("orm".equals(lang)) return "om"; 280 if ("oss".equals(lang)) return "os"; 281 if ("pli".equals(lang)) return "pi"; 282 if ("pan".equals(lang)) return "pa"; 283 if ("pus".equals(lang)) return "ps"; 284 if ("fas".equals(lang)) return "fa"; 285 if ("pol".equals(lang)) return "pl"; 286 if ("por".equals(lang)) return "pt"; 287 if ("que".equals(lang)) return "qu"; 288 if ("ron".equals(lang)) return "ro"; 289 if ("roh".equals(lang)) return "rm"; 290 if ("run".equals(lang)) return "rn"; 291 if ("rus".equals(lang)) return "ru"; 292 if ("smo".equals(lang)) return "sm"; 293 if ("sag".equals(lang)) return "sg"; 294 if ("san".equals(lang)) return "sa"; 295 if ("srd".equals(lang)) return "sc"; 296 if ("srp".equals(lang)) return "sr"; 297 if ("sna".equals(lang)) return "sn"; 298 if ("iii".equals(lang)) return "ii"; 299 if ("snd".equals(lang)) return "sd"; 300 if ("sin".equals(lang)) return "si"; 301 if ("slk".equals(lang)) return "sk"; 302 if ("slv".equals(lang)) return "sl"; 303 if ("som".equals(lang)) return "so"; 304 if ("nbl".equals(lang)) return "nr"; 305 if ("sot".equals(lang)) return "st"; 306 if ("spa".equals(lang)) return "es"; 307 if ("sun".equals(lang)) return "su"; 308 if ("swa".equals(lang)) return "sw"; 309 if ("ssw".equals(lang)) return "ss"; 310 if ("swe".equals(lang)) return "sv"; 311 if ("tgl".equals(lang)) return "tl"; 312 if ("tah".equals(lang)) return "ty"; 313 if ("tgk".equals(lang)) return "tg"; 314 if ("tam".equals(lang)) return "ta"; 315 if ("tat".equals(lang)) return "tt"; 316 if ("tel".equals(lang)) return "te"; 317 if ("tha".equals(lang)) return "th"; 318 if ("bod".equals(lang)) return "bo"; 319 if ("tir".equals(lang)) return "ti"; 320 if ("ton".equals(lang)) return "to"; 321 if ("tso".equals(lang)) return "ts"; 322 if ("tsn".equals(lang)) return "tn"; 323 if ("tur".equals(lang)) return "tr"; 324 if ("tuk".equals(lang)) return "tk"; 325 if ("twi".equals(lang)) return "tw"; 326 if ("uig".equals(lang)) return "ug"; 327 if ("ukr".equals(lang)) return "uk"; 328 if ("urd".equals(lang)) return "ur"; 329 if ("uzb".equals(lang)) return "uz"; 330 if ("ven".equals(lang)) return "ve"; 331 if ("vie".equals(lang)) return "vi"; 332 if ("vol".equals(lang)) return "vo"; 333 if ("wln".equals(lang)) return "wa"; 334 if ("cym".equals(lang)) return "cy"; 335 if ("fry".equals(lang)) return "fy"; 336 if ("wol".equals(lang)) return "wo"; 337 if ("xho".equals(lang)) return "xh"; 338 if ("yid".equals(lang)) return "yi"; 339 if ("yor".equals(lang)) return "yo"; 340 if ("zha".equals(lang)) return "za"; 341 if ("zul".equals(lang)) return "zu"; 342 if ("pap".equals(lang)) return "pap"; 343 if ("gil".equals(lang)) return "gil"; 344 if ("002".equals(lang)) return null; 345 if ("cnr".equals(lang)) return "cnr"; 346 if ("niu".equals(lang)) return "niu"; 347 if ("tpi".equals(lang)) return "tpi"; 348 if ("pau".equals(lang)) return "pau"; 349 if ("crs".equals(lang)) return null; 350 if ("tkl".equals(lang)) return "tkl"; 351 if ("tet".equals(lang)) return "tet"; 352 if ("tvl".equals(lang)) return "tvl"; 353 if ("nso".equals(lang)) return "nso"; 354 throw new Error("unknown 3 letter lang code " + lang); 355 } 356 357 private Document load() throws ParserConfigurationException, SAXException, IOException { 358 DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance(); 359 factory.setNamespaceAware(true); 360 DocumentBuilder builder = factory.newDocumentBuilder(); 361 362 return builder.parse(new FileInputStream(source)); 363 } 364 365 366}