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}