001package org.hl7.fhir.convertors.misc;
002
003import java.io.File;
004import java.io.FileInputStream;
005import java.io.FileOutputStream;
006import java.io.IOException;
007
008import org.hl7.fhir.r5.elementmodel.Manager.FhirFormat;
009import org.hl7.fhir.utilities.IniFile;
010import org.hl7.fhir.utilities.Utilities;
011import org.hl7.fhir.utilities.VersionUtilities;
012import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
013
014@SuppressWarnings("checkstyle:systemout")
015public class OIDAssigner {
016
017
018  public static void main(String[] args) throws Exception {
019    new OIDAssigner().execute(args[0], args[1], args[2]);
020  }
021
022  private void execute(String oidSource, String folder, String version) throws IOException {
023   IniFile oids = new IniFile(oidSource);
024   File f = ManagedFileAccess.file(folder);
025   process(oids, f, version);
026  }
027
028  private void process(IniFile oids, File folder, String version) {
029    for (File f : folder.listFiles()) {
030      if (f.isDirectory()) {
031        if (!Utilities.existsInList(f.getName(), "invariant-tests")) {
032          process(oids, f, version);
033        }
034      } else if (f.getName().endsWith(".xml")) {
035        processFile(oids, f, version, FhirFormat.XML);
036      } else if (f.getName().endsWith(".json")) {
037        processFile(oids, f, version, FhirFormat.JSON);
038      }
039    }    
040  }
041
042  private void processFile(IniFile oids, File f, String version, FhirFormat fmt) {
043    switch (VersionUtilities.getMajMin(version)) {
044    case "1.0" : processFileR2(oids, f, fmt);
045    case "3.0" : processFileR3(oids, f, fmt);
046    case "4.0" : processFileR4(oids, f, fmt);
047    case "4.3" : processFileR4B(oids, f, fmt);
048    case "5.0" : processFileR5(oids, f, fmt);
049    }    
050  }
051
052  private void processFileR2(IniFile oids, File f, FhirFormat fmt) {
053    org.hl7.fhir.dstu2.formats.IParser parser = fmt == FhirFormat.JSON ? new  org.hl7.fhir.dstu2.formats.JsonParser() : new org.hl7.fhir.dstu2.formats.XmlParser();
054    try {
055      boolean save = false;
056      org.hl7.fhir.dstu2.model.Resource r = parser.parse(ManagedFileAccess.inStream(f));
057      if (r instanceof org.hl7.fhir.dstu2.model.ValueSet) { 
058        org.hl7.fhir.dstu2.model.ValueSet vs = (org.hl7.fhir.dstu2.model.ValueSet) r;
059        boolean hasOid = isOid(vs.getIdentifier());
060        if (!hasOid) {
061          String oid = getOid(oids, "ValueSet", vs.getUrl());
062          vs.setIdentifier(new org.hl7.fhir.dstu2.model.Identifier().setSystem("urn:ietf:rfc:3986").setValue("urn:oid:"+oid));
063          save = true;
064        }
065      }
066      if (r instanceof org.hl7.fhir.dstu2.model.ConceptMap) { 
067        org.hl7.fhir.dstu2.model.ConceptMap cm = (org.hl7.fhir.dstu2.model.ConceptMap) r;
068        boolean hasOid = isOid(cm.getIdentifier());
069        if (!hasOid) {
070          String oid = getOid(oids, "ConceptMap", cm.getUrl());
071          cm.setIdentifier(new org.hl7.fhir.dstu2.model.Identifier().setSystem("urn:ietf:rfc:3986").setValue("urn:oid:"+oid));
072          save = true;
073        }
074      }
075      if (r instanceof org.hl7.fhir.dstu2.model.StructureDefinition) { 
076        org.hl7.fhir.dstu2.model.StructureDefinition sd = (org.hl7.fhir.dstu2.model.StructureDefinition) r;
077        boolean hasOid = false;
078        for (org.hl7.fhir.dstu2.model.Identifier id : sd.getIdentifier()) {
079          if (isOid(id)) {
080            hasOid = true;
081          }
082        }
083        if (!hasOid) {
084          String oid = getOid(oids, "StructureDefinition", sd.getUrl());
085          sd.getIdentifier().add(new org.hl7.fhir.dstu2.model.Identifier().setSystem("urn:ietf:rfc:3986").setValue("urn:oid:"+oid));
086          save = true;
087        }
088      }
089      if (save) {
090        parser.setOutputStyle(org.hl7.fhir.dstu2.formats.IParser.OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(f), r);
091      }
092    } catch (Exception e) {
093      if (!e.getMessage().contains("wrong namespace")) {
094        System.out.println("Error processing "+f.getAbsolutePath()+": "+e.getMessage());
095        e.printStackTrace();
096      }
097    }    
098  }
099
100
101  private void processFileR3(IniFile oids, File f, FhirFormat fmt) {
102    org.hl7.fhir.dstu3.formats.IParser parser = fmt == FhirFormat.JSON ? new  org.hl7.fhir.dstu3.formats.JsonParser() : new org.hl7.fhir.dstu3.formats.XmlParser();
103    try {
104      boolean save = false;
105      org.hl7.fhir.dstu3.model.Resource r = parser.parse(ManagedFileAccess.inStream(f));
106      if (r instanceof org.hl7.fhir.dstu3.model.CodeSystem) { 
107        org.hl7.fhir.dstu3.model.CodeSystem cs = (org.hl7.fhir.dstu3.model.CodeSystem) r;
108        boolean hasOid = isOid(cs.getIdentifier());
109        if (!hasOid) {
110          String oid = getOid(oids, "CodeSystem", cs.getUrl());
111          cs.setIdentifier(new org.hl7.fhir.dstu3.model.Identifier().setSystem("urn:ietf:rfc:3986").setValue("urn:oid:"+oid));
112          save = true;
113        }
114      }
115      if (r instanceof org.hl7.fhir.dstu3.model.ValueSet) { 
116        org.hl7.fhir.dstu3.model.ValueSet vs = (org.hl7.fhir.dstu3.model.ValueSet) r;
117        boolean hasOid = false;
118        for (org.hl7.fhir.dstu3.model.Identifier id : vs.getIdentifier()) {
119          if (isOid(id)) {
120            hasOid = true;
121          }
122        }
123        if (!hasOid) {
124          String oid = getOid(oids, "ValueSet", vs.getUrl());
125          vs.getIdentifier().add(new org.hl7.fhir.dstu3.model.Identifier().setSystem("urn:ietf:rfc:3986").setValue("urn:oid:"+oid));
126          save = true;
127        }
128      }
129      if (r instanceof org.hl7.fhir.dstu3.model.ConceptMap) { 
130        org.hl7.fhir.dstu3.model.ConceptMap cm = (org.hl7.fhir.dstu3.model.ConceptMap) r;
131        boolean hasOid = isOid(cm.getIdentifier());
132        if (!hasOid) {
133          String oid = getOid(oids, "ConceptMap", cm.getUrl());
134          cm.setIdentifier(new org.hl7.fhir.dstu3.model.Identifier().setSystem("urn:ietf:rfc:3986").setValue("urn:oid:"+oid));
135          save = true;
136        }
137      }
138      if (r instanceof org.hl7.fhir.dstu3.model.StructureDefinition) { 
139        org.hl7.fhir.dstu3.model.StructureDefinition sd = (org.hl7.fhir.dstu3.model.StructureDefinition) r;
140        boolean hasOid = false;
141        for (org.hl7.fhir.dstu3.model.Identifier id : sd.getIdentifier()) {
142          if (isOid(id)) {
143            hasOid = true;
144          }
145        }
146        if (!hasOid) {
147          String oid = getOid(oids, "StructureDefinition", sd.getUrl());
148          sd.getIdentifier().add(new org.hl7.fhir.dstu3.model.Identifier().setSystem("urn:ietf:rfc:3986").setValue("urn:oid:"+oid));
149          save = true;
150        }
151      }
152      if (save) {
153        parser.setOutputStyle(org.hl7.fhir.dstu3.formats.IParser.OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(f), r);
154      }
155    } catch (Exception e) {
156      if (!e.getMessage().contains("wrong namespace")) {
157        System.out.println("Error processing "+f.getAbsolutePath()+": "+e.getMessage());
158        e.printStackTrace();
159      }
160    }    
161  }
162
163
164  private void processFileR4(IniFile oids, File f, FhirFormat fmt) {
165    org.hl7.fhir.r4.formats.IParser parser = fmt == FhirFormat.JSON ? new  org.hl7.fhir.r4.formats.JsonParser() : new org.hl7.fhir.r4.formats.XmlParser();
166    try {
167      boolean save = false;
168      org.hl7.fhir.r4.model.Resource r = parser.parse(ManagedFileAccess.inStream(f));
169      if (r instanceof org.hl7.fhir.r4.model.CodeSystem) { 
170        org.hl7.fhir.r4.model.CodeSystem cs = (org.hl7.fhir.r4.model.CodeSystem) r;
171        boolean hasOid = false;
172        for (org.hl7.fhir.r4.model.Identifier id : cs.getIdentifier()) {
173          if (isOid(id)) {
174            hasOid = true;
175          }
176        }
177        if (!hasOid) {
178          String oid = getOid(oids, "CodeSystem", cs.getUrl());
179          cs.getIdentifier().add(new org.hl7.fhir.r4.model.Identifier().setSystem("urn:ietf:rfc:3986").setValue("urn:oid:"+oid));
180          save = true;
181        }
182      }
183      if (r instanceof org.hl7.fhir.r4.model.ValueSet) { 
184        org.hl7.fhir.r4.model.ValueSet vs = (org.hl7.fhir.r4.model.ValueSet) r;
185        boolean hasOid = false;
186        for (org.hl7.fhir.r4.model.Identifier id : vs.getIdentifier()) {
187          if (isOid(id)) {
188            hasOid = true;
189          }
190        }
191        if (!hasOid) {
192          String oid = getOid(oids, "ValueSet", vs.getUrl());
193          vs.getIdentifier().add(new org.hl7.fhir.r4.model.Identifier().setSystem("urn:ietf:rfc:3986").setValue("urn:oid:"+oid));
194          save = true;
195        }
196      }
197      if (r instanceof org.hl7.fhir.r4.model.ConceptMap) { 
198        org.hl7.fhir.r4.model.ConceptMap cm = (org.hl7.fhir.r4.model.ConceptMap) r;
199        boolean hasOid = isOid(cm.getIdentifier());
200        if (!hasOid) {
201          String oid = getOid(oids, "ConceptMap", cm.getUrl());
202          cm.setIdentifier(new org.hl7.fhir.r4.model.Identifier().setSystem("urn:ietf:rfc:3986").setValue("urn:oid:"+oid));
203          save = true;
204        }
205      }
206      if (r instanceof org.hl7.fhir.r4.model.StructureDefinition) { 
207        org.hl7.fhir.r4.model.StructureDefinition sd = (org.hl7.fhir.r4.model.StructureDefinition) r;
208        boolean hasOid = false;
209        for (org.hl7.fhir.r4.model.Identifier id : sd.getIdentifier()) {
210          if (isOid(id)) {
211            hasOid = true;
212          }
213        }
214        if (!hasOid) {
215          String oid = getOid(oids, "StructureDefinition", sd.getUrl());
216          sd.getIdentifier().add(new org.hl7.fhir.r4.model.Identifier().setSystem("urn:ietf:rfc:3986").setValue("urn:oid:"+oid));
217          save = true;
218        }
219      }
220      if (save) {
221        parser.setOutputStyle(org.hl7.fhir.r4.formats.IParser.OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(f), r);
222      }
223    } catch (Exception e) {
224      if (!e.getMessage().contains("wrong namespace")) {
225        System.out.println("Error processing "+f.getAbsolutePath()+": "+e.getMessage());
226        e.printStackTrace();
227      }
228    }    
229  }
230
231  private void processFileR4B(IniFile oids, File f, FhirFormat fmt) {
232    org.hl7.fhir.r4b.formats.IParser parser = fmt == FhirFormat.JSON ? new  org.hl7.fhir.r4b.formats.JsonParser() : new org.hl7.fhir.r4b.formats.XmlParser();
233    try {
234      boolean save = false;
235      org.hl7.fhir.r4b.model.Resource r = parser.parse(ManagedFileAccess.inStream(f));
236      if (r instanceof org.hl7.fhir.r4b.model.CanonicalResource) { 
237        org.hl7.fhir.r4b.model.CanonicalResource cs = (org.hl7.fhir.r4b.model.CanonicalResource) r;
238        boolean hasOid = false;
239        for (org.hl7.fhir.r4b.model.Identifier id : cs.getIdentifier()) {
240          if (isOid(id)) {
241            hasOid = true;
242          }
243        }
244        if (!hasOid) {
245          String oid = getOid(oids, r.fhirType(), cs.getUrl());
246          cs.getIdentifier().add(new org.hl7.fhir.r4b.model.Identifier().setSystem("urn:ietf:rfc:3986").setValue("urn:oid:"+oid));
247          save = true;
248        }
249      }
250      if (save) {
251        parser.setOutputStyle(org.hl7.fhir.r4b.formats.IParser.OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(f), r);
252      }
253    } catch (Exception e) {
254      if (!e.getMessage().contains("wrong namespace")) {
255        System.out.println("Error processing "+f.getAbsolutePath()+": "+e.getMessage());
256        e.printStackTrace();
257      }
258    }    
259  }
260
261
262  private void processFileR5(IniFile oids, File f, FhirFormat fmt) {
263    org.hl7.fhir.r5.formats.IParser parser = fmt == FhirFormat.JSON ? new  org.hl7.fhir.r5.formats.JsonParser() : new org.hl7.fhir.r5.formats.XmlParser();
264    try {
265      boolean save = false;
266      org.hl7.fhir.r5.model.Resource r = parser.parse(ManagedFileAccess.inStream(f));
267      if (r instanceof org.hl7.fhir.r5.model.CanonicalResource) { 
268        org.hl7.fhir.r5.model.CanonicalResource cs = (org.hl7.fhir.r5.model.CanonicalResource) r;
269        cs.getIdentifier().removeIf(id -> Utilities.existsInList(id.getValue(), 
270            "urn:oid:2.16.840.1.113883.4.642.3.3343","urn:oid:2.16.840.1.113883.4.642.8.4","urn:oid:2.16.840.1.113883.4.642.10.7","urn:oid:2.16.840.1.113883.4.642.11.11","urn:oid:2.16.840.1.113883.4.642.17.4","urn:oid:2.16.840.1.113883.4.642.30.5","urn:oid:2.16.840.1.113883.4.642.34.1"));
271        boolean hasOid = false;
272        for (org.hl7.fhir.r5.model.Identifier id : cs.getIdentifier()) {
273          if (isOid(id)) {
274            hasOid = true;
275          }
276        }
277        String url = cs.getUrl();
278        if (url == null) {
279          String id = cs.getId();
280          if (id == null && Utilities.existsInList(cs.fhirType(), "CodeSystem", "ValueSet")) {
281            id = f.getName();
282            id = id.substring(0, id.lastIndexOf("."));
283            id = id.replace(cs.fhirType().toLowerCase()+"-", "");
284          }
285          if (id != null) {
286            url = "http://hl7.org/fhir/"+cs.fhirType()+"/"+id;
287          }
288        }
289        if (!hasOid && url != null) {
290          String oid = getOid(oids, r.fhirType(), url);
291          cs.getIdentifier().add(new org.hl7.fhir.r5.model.Identifier().setSystem("urn:ietf:rfc:3986").setValue("urn:oid:"+oid));
292          save = true;
293        }
294      }
295      if (save) {
296        parser.setOutputStyle(org.hl7.fhir.r5.formats.IParser.OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(f), r);
297      }
298    } catch (Exception e) {
299      if (!e.getMessage().contains("wrong namespace")) {
300        System.out.println("Error processing "+f.getAbsolutePath()+": "+e.getMessage());
301        e.printStackTrace();
302      }
303    }    
304  }
305 
306  private boolean isOid(org.hl7.fhir.dstu2.model.Identifier id) {
307    return "urn:ietf:rfc:3986".equals(id.getSystem()) && id.hasValue() && id.getValue().startsWith("urn:oid:");
308  }
309
310  private boolean isOid(org.hl7.fhir.dstu3.model.Identifier id) {
311    return "urn:ietf:rfc:3986".equals(id.getSystem()) && id.hasValue() && id.getValue().startsWith("urn:oid:");
312  }
313
314  private boolean isOid(org.hl7.fhir.r4.model.Identifier id) {
315    return "urn:ietf:rfc:3986".equals(id.getSystem()) && id.hasValue() && id.getValue().startsWith("urn:oid:");
316  }
317
318  private boolean isOid(org.hl7.fhir.r4b.model.Identifier id) {
319    return "urn:ietf:rfc:3986".equals(id.getSystem()) && id.hasValue() && id.getValue().startsWith("urn:oid:");
320  }
321
322  private boolean isOid(org.hl7.fhir.r5.model.Identifier id) {
323    return "urn:ietf:rfc:3986".equals(id.getSystem()) && id.hasValue() && id.getValue().startsWith("urn:oid:");
324  }
325
326  private String getOid(IniFile oids, String rt, String url) {
327    String root = oids.getStringProperty("Roots", rt);
328    if (root == null) {
329      throw new Error("no OID.ini entry for "+rt);
330    }
331    String oid = oids.getStringProperty(rt, url);
332    if (oid != null) {
333      return oid;
334    }
335    int key = oids.hasProperty("Key", rt) ? oids.getIntegerProperty("Key", rt) : 0;
336    key++;
337    oid = root+"."+key;
338    oids.setIntegerProperty("Key", rt, key, null);
339    oids.setStringProperty(rt, url, oid, null);
340    oids.save();
341    return oid;
342  }
343}