
001package org.hl7.fhir.convertors.misc; 002 003import java.io.FileInputStream; 004import java.io.FileOutputStream; 005 006import org.hl7.fhir.r4.formats.IParser.OutputStyle; 007import org.hl7.fhir.r4.model.BooleanType; 008import org.hl7.fhir.r4.model.CodeSystem; 009import org.hl7.fhir.r4.model.CodeSystem.ConceptDefinitionComponent; 010import org.hl7.fhir.r4.model.CodeSystem.PropertyType; 011import org.hl7.fhir.r4.model.StringType; 012import org.hl7.fhir.r4.terminologies.CodeSystemUtilities; 013import org.hl7.fhir.utilities.CommaSeparatedStringBuilder; 014import org.hl7.fhir.utilities.TextFile; 015import org.hl7.fhir.utilities.Utilities; 016import org.hl7.fhir.utilities.filesystem.ManagedFileAccess; 017import org.hl7.fhir.utilities.json.model.JsonObject; 018import org.hl7.fhir.utilities.json.parser.JsonParser; 019 020public class SPDXImporter { 021 022 private StringBuilder b; 023 024 025 public static void main(String[] args) throws Exception { 026 new SPDXImporter().generate(args); 027 } 028 029 public void generate(String[] args) throws Exception { 030 JsonObject json = JsonParser.parseObjectFromUrl("https://raw.githubusercontent.com/spdx/license-list-data/main/json/licenses.json"); 031 CodeSystem cs = (CodeSystem) new org.hl7.fhir.r4.formats.JsonParser().parse(ManagedFileAccess.inStream(args[0])); 032 cs.getConcept().clear(); 033 cs.getProperty().clear(); 034 cs.addProperty().setCode("reference").setType(PropertyType.STRING); 035 cs.addProperty().setCode("isOsiApproved").setType(PropertyType.BOOLEAN); 036 cs.addProperty().setCode("status").setType(PropertyType.CODE).setUri("http://hl7.org/fhir/concept-properties#status"); 037 cs.addProperty().setCode("seeAlso").setType(PropertyType.STRING); 038 cs.setVersion(json.asString("licenseListVersion")); 039 ConceptDefinitionComponent cc = cs.addConcept(); 040 cc.setCode("not-open-source"); 041 cc.setDisplay("Not open source"); 042 cc.setDefinition("Not an open source license."); 043 for (JsonObject l : json.getJsonObjects("licenses")) { 044 cc = cs.addConcept(); 045 cc.setCode(l.asString("licenseId")); 046 cc.setDisplay(l.asString("name")); 047 cc.setDefinition(l.asString("name")); 048 if (l.has("reference")) { 049 cc.addProperty().setCode("reference").setValue(new StringType(l.asString("reference"))); 050 } 051 if (l.has("isOsiApproved")) { 052 cc.addProperty().setCode("isOsiApproved").setValue(new BooleanType(l.asBoolean("isOsiApproved"))); 053 } 054 if (l.asBoolean("isDeprecatedLicenseId")) { 055 cc.addProperty().setCode("status").setValue(new BooleanType(l.asBoolean("deprecated"))); 056 } 057 for (String s : l.getStrings("seeAlso")) { 058 cc.addProperty().setCode("seeAlso").setValue(new StringType(s)); 059 } 060 } 061 CodeSystemUtilities.sortAllCodes(cs); 062 new org.hl7.fhir.r4.formats.JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(args[1]), cs); 063 b = new StringBuilder(); 064 generateEnum("SPDXLicense", cs); 065 TextFile.stringToFile(b.toString(), Utilities.changeFileExt(args[1], ".java")); 066 } 067 068 private void write(String s) { 069 b.append(s); 070 } 071 072 private boolean allPlusMinus(String cc) { 073 for (char c : cc.toCharArray()) 074 if (!(c == '-' || c == '+')) 075 return false; 076 return true; 077 } 078 079 protected String makeConst(String cc) { 080 if (cc.equals("*")) 081 cc = "ASTERISK"; 082 if (Utilities.isOid(cc) && Utilities.charCount(cc, '.') > 2) 083 cc = "OID_"+cc; 084 if (cc.equals("%")) 085 cc = "pct"; 086 else if (cc.equals("<")) 087 cc = "less_Than"; 088 else if (cc.equals("<=")) 089 cc = "less_Or_Equal"; 090 else if (cc.equals(">")) 091 cc = "greater_Than"; 092 else if (cc.equals(">=")) 093 cc = "greater_Or_Equal"; 094 else if (cc.equals("=")) 095 cc = "equal"; 096 else if (cc.equals("!=")) 097 cc = "not_equal"; 098 else if (allPlusMinus(cc)) 099 cc = cc.replace("-", "Minus").replace("+", "Plus"); 100 else 101 cc = cc.replace("-", "_").replace("+", "PLUS"); 102 cc = cc.replace("(", "_").replace(")", "_"); 103 cc = cc.replace("{", "_").replace("}", "_"); 104 cc = cc.replace("<", "_").replace(">", "_"); 105 cc = cc.replace(".", "_").replace("/", "_"); 106 cc = cc.replace(":", "_"); 107 cc = cc.replace("%", "pct"); 108 if (Utilities.isInteger(cc.substring(0, 1))) 109 cc = "_"+cc; 110 cc = cc.toUpperCase(); 111 return cc; 112 } 113 114 115 private void generateEnum(String name, CodeSystem cs) throws Exception { 116 String url = cs.getUrl(); 117 CommaSeparatedStringBuilder el = new CommaSeparatedStringBuilder(); 118 119 write(" public enum "+name+" {\r\n"); 120 int l = cs.getConcept().size(); 121 int i = 0; 122 for (ConceptDefinitionComponent c : cs.getConcept()) { 123 i++; 124 String cc = Utilities.camelCase(c.getCode()); 125 cc = makeConst(cc); 126 el.append(cc); 127 128 write(" /**\r\n"); 129 write(" * "+c.getDefinition()+"\r\n"); 130 write(" */\r\n"); 131 write(" "+cc.toUpperCase()+", \r\n"); 132 } 133 write(" /**\r\n"); 134 write(" * added to help the parsers\r\n"); 135 write(" */\r\n"); 136 write(" NULL;\r\n"); 137 el.append("NULL"); 138 139 140 write(" public static "+name+" fromCode(String codeString) throws FHIRException {\r\n"); 141 write(" if (codeString == null || \"\".equals(codeString))\r\n"); 142 write(" return null;\r\n"); 143 for (ConceptDefinitionComponent c : cs.getConcept()) { 144 String cc = Utilities.camelCase(c.getCode()); 145 cc = makeConst(cc); 146 write(" if (\""+c.getCode()+"\".equals(codeString))\r\n"); 147 write(" return "+cc+";\r\n"); 148 } 149 write(" throw new FHIRException(\"Unknown "+name+" code '\"+codeString+\"'\");\r\n"); 150 write(" }\r\n"); 151 152 write(" public static boolean isValidCode(String codeString) {\r\n"); 153 write(" if (codeString == null || \"\".equals(codeString))\r\n"); 154 write(" return false;\r\n"); 155 write(" return Utilities.existsInList(codeString"); 156 for (ConceptDefinitionComponent c : cs.getConcept()) { 157 write(", \""+c.getCode()+"\""); 158 } 159 write(");\r\n"); 160 write(" }\r\n"); 161 162 write(" public String toCode() {\r\n"); 163 write(" switch (this) {\r\n"); 164 for (ConceptDefinitionComponent c : cs.getConcept()) { 165 String cc = Utilities.camelCase(c.getCode()); 166 cc = makeConst(cc); 167 write(" case "+cc+": return \""+c.getCode()+"\";\r\n"); 168 } 169 write(" case NULL: return null;\r\n"); 170 write(" default: return \"?\";\r\n"); 171 write(" }\r\n"); 172 write(" }\r\n"); 173 174 write(" public String getSystem() {\r\n"); 175 write(" switch (this) {\r\n"); 176 for (ConceptDefinitionComponent c : cs.getConcept()) { 177 String cc = Utilities.camelCase(c.getCode()); 178 cc = makeConst(cc); 179 write(" case "+cc+": return \""+cs.getUrl()+"\";\r\n"); 180 } 181 write(" case NULL: return null;\r\n"); 182 write(" default: return \"?\";\r\n"); 183 write(" }\r\n"); 184 write(" }\r\n"); 185 186 write(" public String getDefinition() {\r\n"); 187 write(" switch (this) {\r\n"); 188 for (ConceptDefinitionComponent c : cs.getConcept()) { 189 String cc = Utilities.camelCase(c.getCode()); 190 cc = makeConst(cc); 191 write(" case "+cc+": return \""+Utilities.escapeJava(c.getDefinition())+"\";\r\n"); 192 } 193 write(" case NULL: return null;\r\n"); 194 write(" default: return \"?\";\r\n"); 195 write(" }\r\n"); 196 write(" }\r\n"); 197 198 write(" public String getDisplay() {\r\n"); 199 write(" switch (this) {\r\n"); 200 for (ConceptDefinitionComponent c : cs.getConcept()) { 201 String cc = Utilities.camelCase(c.getCode()); 202 cc = makeConst(cc); 203 write(" case "+cc+": return \""+Utilities.escapeJava(Utilities.noString(c.getDisplay()) ? c.getCode() : c.getDisplay())+"\";\r\n"); 204 } 205 write(" case NULL: return null;\r\n"); 206 write(" default: return \"?\";\r\n"); 207 write(" }\r\n"); 208 write(" }\r\n"); 209 210 write(" }\r\n"); 211 write("\r\n"); 212 213 214 write(" public static class "+name+"EnumFactory implements EnumFactory<"+name+"> {\r\n"); 215 write(" public "+name+" fromCode(String codeString) throws IllegalArgumentException {\r\n"); 216 217 write(" if (codeString == null || \"\".equals(codeString))\r\n"); 218 write(" if (codeString == null || \"\".equals(codeString))\r\n"); 219 write(" return null;\r\n"); 220 for (ConceptDefinitionComponent c : cs.getConcept()) { 221 String cc = Utilities.camelCase(c.getCode()); 222 cc = makeConst(cc); 223 write(" if (\""+c.getCode()+"\".equals(codeString))\r\n"); 224 write(" return "+name+"."+cc+";\r\n"); 225 } 226 write(" throw new IllegalArgumentException(\"Unknown "+name+" code '\"+codeString+\"'\");\r\n"); 227 write(" }\r\n"); 228 write("\r\n"); 229 write(" public Enumeration<"+name+"> fromType(PrimitiveType<?> code) throws FHIRException {\r\n"); 230 write(" if (code == null)\r\n"); 231 write(" return null;\r\n"); 232 write(" if (code.isEmpty())\r\n"); 233 write(" return new Enumeration<"+name+">(this, "+name+".NULL, code);\r\n"); 234 write(" String codeString = ((PrimitiveType) code).asStringValue();\r\n"); 235 write(" if (codeString == null || \"\".equals(codeString))\r\n"); 236 write(" return new Enumeration<"+name+">(this, "+name+".NULL, code);\r\n"); 237 for (ConceptDefinitionComponent c : cs.getConcept()) { 238 String cc = Utilities.camelCase(c.getCode()); 239 cc = makeConst(cc); 240 write(" if (\""+c.getCode()+"\".equals(codeString))\r\n"); 241 write(" return new Enumeration<"+name+">(this, "+name+"."+cc+", code);\r\n"); 242 } 243 write(" throw new FHIRException(\"Unknown "+name+" code '\"+codeString+\"'\");\r\n"); 244 write(" }\r\n"); 245 write(" public String toCode("+name+" code) {\r\n"); 246 for (ConceptDefinitionComponent c : cs.getConcept()) { 247 String cc = Utilities.camelCase(c.getCode()); 248 cc = makeConst(cc); 249 write(" if (code == "+name+"."+cc+")\r\n return \""+c.getCode()+"\";\r\n"); 250 } 251 write(" return \"?\";\r\n"); 252 write(" }\r\n"); 253 254 write(" public String toSystem("+name+" code) {\r\n"); 255 write(" return code.getSystem();\r\n"); 256 write(" }\r\n"); 257 258 write(" }\r\n"); 259 write("\r\n"); 260 } 261 262} 263