
001package org.hl7.fhir.r5.utils.xver; 002 003import org.hl7.fhir.exceptions.FHIRException; 004import org.hl7.fhir.r5.context.IWorkerContext; 005import org.hl7.fhir.r5.model.ElementDefinition; 006import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent; 007import org.hl7.fhir.r5.model.Enumerations.FHIRVersion; 008import org.hl7.fhir.r5.model.Enumerations.PublicationStatus; 009import org.hl7.fhir.r5.model.StructureDefinition; 010import org.hl7.fhir.r5.model.StructureDefinition.ExtensionContextType; 011import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; 012import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule; 013import org.hl7.fhir.r5.model.UriType; 014import org.hl7.fhir.utilities.MarkedToMoveToAdjunctPackage; 015import org.hl7.fhir.utilities.Utilities; 016import org.hl7.fhir.utilities.VersionUtilities; 017import org.hl7.fhir.utilities.json.model.JsonElement; 018import org.hl7.fhir.utilities.json.model.JsonObject; 019import org.hl7.fhir.utilities.json.parser.JsonParser; 020import org.hl7.fhir.utilities.npm.PackageHacker; 021 022import java.io.IOException; 023import java.util.Date; 024import java.util.HashMap; 025import java.util.Map; 026 027@MarkedToMoveToAdjunctPackage 028public class XVerExtensionManagerOld extends XVerExtensionManager { 029 030 private Map<String, JsonObject> lists = new HashMap<>(); 031 032 public XVerExtensionManagerOld(IWorkerContext context) { 033 super(context); 034 } 035 036 @Override 037 public XVerExtensionStatus status(String url) throws FHIRException { 038 if (url.length() < 54) { 039 return XVerExtensionStatus.Invalid; 040 } 041 url = url.replace("%5Bx%5D", "[x]"); 042 String v = url.substring(20, 23); 043 String e = url.substring(54); 044 if (!lists.containsKey(v)) { 045 if (context.hasBinaryKey("xver-paths-"+v+".json")) { 046 try { 047 lists.put(v, JsonParser.parseObject(context.getBinaryForKey("xver-paths-"+v+".json"))); 048 } catch (IOException e1) { 049 throw new FHIRException(e); 050 } 051 } else { 052 return XVerExtensionStatus.BadVersion; 053 } 054 } 055 JsonObject root = lists.get(v); 056 JsonObject path = root.getJsonObject(e); 057 if (path == null) { 058 path = root.getJsonObject(e+"[x]"); 059 } 060 if (path == null) { 061 return XVerExtensionStatus.Unknown; 062 } 063 if (path.has("elements") || path.has("types")) { 064 return XVerExtensionStatus.Valid; 065 } else { 066 return XVerExtensionStatus.Invalid; 067 } 068 } 069 070 @Override 071 public StructureDefinition getDefinition(String url) { 072 url = url.replace("%5Bx%5D", "[x]"); 073 String verSource = url.substring(20, 23); 074 String verTarget = VersionUtilities.getMajMin(context.getVersion()); 075 String e = url.substring(54); 076 String r = e.contains(".") ? e.substring(0, e.indexOf(".")) : e; 077 JsonObject root = lists.get(verSource); 078 JsonObject path = root.getJsonObject(e); 079 if (path == null) { 080 path = root.getJsonObject(e+"[x]"); 081 } 082 083 StructureDefinition sd = new StructureDefinition(); 084 sd.setUserData(XVER_EXT_MARKER, "true"); 085 sd.setUserData(XVER_VER_MARKER, verSource); 086 if (context.getResourceNamesAsSet().contains(r)) { 087 sd.setWebPath(Utilities.pathURL(context.getSpecUrl(), r.toLowerCase()+"-definitions.html#"+e)); 088 } else { 089 sd.setWebPath(PackageHacker.fixPackageUrl("https://hl7.org/fhir/versions.html#extensions")); 090 } 091 sd.setUrl(url); 092 sd.setVersion(context.getVersion()); 093 sd.setFhirVersion(FHIRVersion.fromCode(context.getVersion())); 094 sd.setKind(StructureDefinitionKind.COMPLEXTYPE); 095 sd.setType("Extension"); 096 sd.setDerivation(TypeDerivationRule.CONSTRAINT); 097 sd.setName("Extension-"+verSource+"-"+e); 098 sd.setTitle("Extension Definition for "+e+" for Version "+verSource); 099 sd.setStatus(PublicationStatus.ACTIVE); 100 sd.setExperimental(false); 101 sd.setDate(new Date()); 102 sd.setPublisher("FHIR Project"); 103 sd.setPurpose("Defined so the validator can validate cross version extensions (see http://hl7.org/fhir/versions.html#extensions)"); 104 sd.setAbstract(false); 105 sd.addContext().setType(ExtensionContextType.ELEMENT).setExpression(head(e)); 106 sd.setBaseDefinition("http://hl7.org/fhir/StructureDefinition/Extension"); 107 if (path.has("types")) { 108 sd.getDifferential().addElement().setPath("Extension.extension").setMax("0"); 109 sd.getDifferential().addElement().setPath("Extension.url").setFixed(new UriType(url)); 110 ElementDefinition val = sd.getDifferential().addElement().setPath("Extension.value[x]").setMin(1); 111 populateTypes(path, val, verSource, verTarget); 112 } else if (path.has("elements")) { 113 for (JsonElement i : path.forceArray("elements").getItems()) { 114 String apath = e+"."+i.asString(); 115 JsonObject elt = root.getJsonObject(apath); 116 if (elt != null) { 117 genExtensionContents(root, apath, verSource, verTarget, sd, i, elt, "Extension.extension"); 118 } 119 } 120 sd.getDifferential().addElement().setPath("Extension.url").setFixed(new UriType(url)); 121 sd.getDifferential().addElement().setPath("Extension.value[x]").setMax("0"); 122 } else { 123 throw new FHIRException("Internal error - attempt to define extension for "+url+" when it is invalid"); 124 } 125 if (path.has("modifier") && path.asBoolean("modifier")) { 126 ElementDefinition baseDef = new ElementDefinition("Extension"); 127 sd.getDifferential().getElement().add(0, baseDef); 128 baseDef.setIsModifier(true); 129 } 130 return sd; 131 } 132 133 private void genExtensionContents(JsonObject root, String apath, String verSource, String verTarget, StructureDefinition sd, JsonElement i, JsonObject elt, String epath) { 134 String s = i.asString().replace("[x]", ""); 135 sd.getDifferential().addElement().setPath(epath).setSliceName(s); 136 if (elt.has("types")) { 137 sd.getDifferential().addElement().setPath(epath+".extension").setMax("0"); 138 sd.getDifferential().addElement().setPath(epath+".url").setFixed(new UriType(s)); 139 ElementDefinition val = sd.getDifferential().addElement().setPath(epath+".value[x]").setMin(1); 140 populateTypes(elt, val, verSource, verTarget); 141 } else if (elt.has("elements")) { 142 for (JsonElement ic : elt.forceArray("elements").getItems()) { 143 String apathC = apath+"."+ic.asString(); 144 JsonObject eltC = root.getJsonObject(apathC); 145 if (eltC != null) { 146 genExtensionContents(root, apathC, verSource, verTarget, sd, ic, eltC, epath+".extension"); 147 } 148 } 149 sd.getDifferential().addElement().setPath(epath+".url").setFixed(new UriType(s)); 150 sd.getDifferential().addElement().setPath(epath+".value[x]").setMax("0"); 151 } else { 152 throw new FHIRException("Internal error - unknown element "+apath); 153 } 154 } 155 156 private void populateTypes(JsonObject path, ElementDefinition val, String verSource, String verTarget) { 157 for (JsonElement i : path.forceArray("types").getItems()) { 158 String s = i.asString(); 159 if (!s.startsWith("!")) { 160 if (s.contains("(")) { 161 String t = s.substring(0, s.indexOf("(")); 162 TypeRefComponent tr = val.addType().setCode(translateDataType(verTarget, t)); 163 if (hasTargets(tr.getCode()) ) { 164 s = s.substring(t.length()+1); 165 for (String p : s.substring(0, s.length()-1).split("\\|")) { 166 if ("Any".equals(p)) { 167 tr.addTargetProfile("http://hl7.org/fhir/StructureDefinition/Resource"); 168 } else if (p.contains(",")) { 169 for (String pp : p.split("\\,")) { 170 if (isResource(pp)) { 171 tr.addTargetProfile("http://hl7.org/fhir/StructureDefinition/"+pp); 172 } 173 } 174 } else if (isResource(p)) { 175 tr.addTargetProfile("http://hl7.org/fhir/StructureDefinition/"+p); 176 } 177 } 178 } 179 } else { 180 val.addType().setCode(translateDataType(verTarget, s)); 181 } 182 } 183 } 184 } 185 private boolean isResource(String p) { 186 return context.getResourceNames().contains(p); 187 } 188 189 private boolean hasTargets(String dt) { 190 return Utilities.existsInList(dt, "canonical", "Reference", "CodeableReference"); 191 } 192 193 private String translateDataType(String v, String dt) { 194 if (VersionUtilities.versionMatches("1.0.x", v) || VersionUtilities.versionMatches("1.4.x", v)) { 195 return translateToR2(dt); 196 } else if (VersionUtilities.versionMatches("3.0.x", v)) { 197 return translateToR3(dt); 198 } else { 199 return dt; 200 } 201 } 202 203 private String translateToR3(String dt) { 204 if ("canonical".equals(dt)) { 205 return "uri"; 206 } else if ("url".equals(dt)) { 207 return "uri"; 208 } else { 209 return dt; 210 } 211 } 212 213 private String translateToR2(String dt) { 214 if ("canonical".equals(dt)) { 215 return "uri"; 216 } else if ("url".equals(dt)) { 217 return "uri"; 218 } else if ("uuid".equals(dt)) { 219 return "id"; 220 } else { 221 return dt; 222 } 223 } 224 225 private String head(String id) { 226 if (id.contains(".")) { 227 return id.substring(0, id.lastIndexOf(".")); 228 } else { 229 return id; 230 } 231 } 232 233}