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