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