org.hl7.fhir.r5.conformance.R5ExtensionsLoader Maven / Gradle / Ivy
package org.hl7.fhir.r5.conformance;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.conformance.R5ExtensionsLoader.Loadable;
import org.hl7.fhir.r5.context.ContextUtilities;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.formats.JsonParser;
import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CanonicalType;
import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
import org.hl7.fhir.r5.model.PackageInformation;
import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule;
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.r5.utils.ResourceSorters;
import org.hl7.fhir.utilities.FileUtilities;
import org.hl7.fhir.utilities.MarkedToMoveToAdjunctPackage;
import org.hl7.fhir.utilities.Utilities;
import org.hl7.fhir.utilities.npm.BasePackageCacheManager;
import org.hl7.fhir.utilities.npm.NpmPackage;
import org.hl7.fhir.utilities.npm.NpmPackage.PackageResourceInformation;
@MarkedToMoveToAdjunctPackage
public class R5ExtensionsLoader {
public static class CanonicalResourceSortByUrl implements Comparator> {
@Override
public int compare(Loadable arg0, Loadable arg1) {
return arg0.info.getUrl().compareTo(arg1.info.getUrl());
}
}
public class Loadable {
public Loadable(PackageResourceInformation info, NpmPackage source) {
this.info = info;
this.source = source;
}
private T resource;
private NpmPackage source;
private PackageResourceInformation info;
public T getResource() throws FHIRFormatError, FileNotFoundException, IOException {
if (resource == null) {
CanonicalResource r = (CanonicalResource) json.parse(source.load(info));
r.setWebPath(Utilities.pathURL(source.getWebLocation(), r.fhirType().toLowerCase()+ "-"+r.getId().toLowerCase()+".html"));
resource = (T) r;
}
return resource;
}
}
private BasePackageCacheManager pcm;
private int count;
private NpmPackage pckCore;
private Map> valueSets;
private Map> codeSystems;
private List> structures;
private IWorkerContext context;
private JsonParser json;
public R5ExtensionsLoader(BasePackageCacheManager pcm, IWorkerContext context) {
super();
this.pcm = pcm;
this.context = context;
valueSets = new HashMap<>();
codeSystems = new HashMap<>();
structures = new ArrayList<>();
}
public void load() throws FHIRException, IOException {
pckCore = pcm.loadPackage("hl7.fhir.r5.core", "5.0.0");
loadDetails(pckCore);
}
private void loadDetails(NpmPackage pck) throws IOException {
json = new JsonParser();
String[] types = new String[] { "StructureDefinition", "ValueSet", "CodeSystem" };
for (PackageResourceInformation pri : pck.listIndexedResources(types)) {
if (pri.getResourceType().equals("CodeSystem")) {
codeSystems.put(pri.getUrl(), new Loadable(pri, pck));
codeSystems.put(pri.getUrl()+"|"+pri.getVersion(), new Loadable(pri, pck));
} else if (pri.getResourceType().equals("ValueSet")) {
valueSets.put(pri.getUrl(), new Loadable(pri, pck));
valueSets.put(pri.getUrl()+"|"+pri.getVersion(), new Loadable(pri, pck));
} else if (pri.getResourceType().equals("StructureDefinition")) {
structures.add(new Loadable(pri, pck));
}
}
}
// public void loadR5Extensions() throws FHIRException, IOException {
// count = 0;
// List typeNames = new ContextUtilities(context).getTypeNames();
// for (Loadable lsd : structures) {
// if (lsd.info.getStatedType().equals("Extension") && !context.hasResource(StructureDefinition.class, lsd.info.getUrl())) {
// StructureDefinition sd = lsd.getResource();
// if (sd.getDerivation() == TypeDerivationRule.CONSTRAINT) {
// if (survivesStrippingTypes(sd, context, typeNames)) {
// count++;
// sd.setWebPath(Utilities.pathURL(pckExt.getWebLocation(), "extension-"+sd.getId().toLowerCase()+".html"));
// registerTerminologies(sd);
// context.cacheResourceFromPackage(sd, new PackageInformation(lsd.source));
// }
// }
// }
// }
// }
public void loadR5SpecialTypes(List types) throws FHIRException, IOException {
for (Loadable lsd : structures) {
if (Utilities.existsInList(lsd.info.getId(), types)) {
StructureDefinition sd = lsd.getResource();
count++;
List rl = new ArrayList<>();
for (ElementDefinition ed : sd.getDifferential().getElement()) {
if (!stripTypes(ed, sd, types)) {
rl.add(ed);
}
}
sd.getDifferential().getElement().removeAll(rl);
rl.clear();
for (ElementDefinition ed : sd.getSnapshot().getElement()) {
if (!stripTypes(ed, sd, types)) {
rl.add(ed);
}
}
sd.getSnapshot().getElement().removeAll(rl);
sd.setWebPath(Utilities.pathURL(lsd.source.getWebLocation(), sd.getId().toLowerCase()+".html"));
registerTerminologies(sd);
context.cacheResourceFromPackage(sd, new PackageInformation(lsd.source));
}
}
}
private boolean stripTypes(ElementDefinition ed, StructureDefinition sd, List types) {
if (!ed.getPath().contains(".") || !ed.hasType()) {
return true;
}
ed.getType().removeIf(tr -> context.fetchTypeDefinition(tr.getWorkingCode()) == null);
if (!ed.hasType()) {
return false;
}
for (TypeRefComponent tr : ed.getType()) {
if (tr.hasTargetProfile()) {
tr.getTargetProfile().removeIf(n -> !context.hasResource(StructureDefinition.class, n.asStringValue()) && !n.asStringValue().equals(sd.getUrl()) && !types.contains(tail(n.asStringValue())));
if (!tr.hasTargetProfile()) {
return false;
}
}
}
return true;
}
private Object tail(String s) {
if (s == null || !s.contains("/")) {
return s;
}
return s.substring(s.lastIndexOf("/")+1);
}
private void registerTerminologies(StructureDefinition sd) throws FHIRFormatError, FileNotFoundException, IOException {
for (ElementDefinition ed : sd.getSnapshot().getElement()) {
if (ed.hasBinding() && ed.getBinding().hasValueSet()) {
String vsu = ed.getBinding().getValueSet();
ValueSet vs = valueSets.containsKey(vsu) ? valueSets.get(vsu).getResource() : null;
if (vs != null) {
vsu = makeR5Url(vsu);
ed.getBinding().setValueSet(vsu);
if (!context.hasResource(ValueSet.class, vsu)) {
vs.setUrl(removeVersion(vsu));
loadValueSet(vs, context, valueSets, codeSystems);
}
}
}
}
}
private String removeVersion(String url) {
if (url.contains("|")) {
url = url.substring(0, url.indexOf("|"));
}
return url;
}
private String makeR5Url(String url) {
return url.replace("/fhir/", "/fhir/5.0/");
}
private void loadValueSet(ValueSet vs, IWorkerContext context, Map> valueSets, Map> codeSystems) throws FHIRFormatError, FileNotFoundException, IOException {
context.cacheResourceFromPackage(vs, vs.getSourcePackage());
for (ConceptSetComponent inc : vs.getCompose().getInclude()) {
for (CanonicalType t : inc.getValueSet()) {
String vsu = t.getValue();
ValueSet vsi = valueSets.containsKey(vsu) ? valueSets.get(vsu).getResource() : null;
if (vsi != null) {
vsu = makeR5Url(vsu);
t.setValue(vsu);
vsi.setUrl(vsu);
if (!context.hasResource(ValueSet.class, vsu)) {
loadValueSet(vsi, context, valueSets, codeSystems);
}
}
}
if (inc.hasSystem()) {
CodeSystem cs;
if (inc.hasVersion()) {
cs = codeSystems.containsKey(inc.getSystem()+"|"+inc.getVersion()) ? codeSystems.get(inc.getSystem()+"|"+inc.getVersion()).getResource() : null;
} else {
cs = codeSystems.containsKey(inc.getSystem()) ? codeSystems.get(inc.getSystem()).getResource() : null;
}
if (cs != null) {
String csu = makeR5Url(inc.getSystem());
cs.setUrl(csu);
inc.setSystem(csu);
if (!context.hasResource(CodeSystem.class, csu)) {
context.cacheResourceFromPackage(cs, cs.getSourcePackage());
}
}
}
}
}
private boolean survivesStrippingTypes(StructureDefinition sd, IWorkerContext context, List typeNames) {
for (ElementDefinition ed : sd.getDifferential().getElement()) {
stripTypes(ed, context, typeNames);
}
for (ElementDefinition ed : sd.getSnapshot().getElement()) {
if (!stripTypes(ed, context, typeNames)) {
return false;
}
}
return true;
}
private boolean stripTypes(ElementDefinition ed, IWorkerContext context, List typeNames) {
if (!ed.getPath().contains(".") || !ed.hasType()) {
return true;
}
ed.getType().removeIf(tr -> !typeNames.contains(tr.getWorkingCode()));
if (!ed.hasType()) {
return false;
}
for (TypeRefComponent tr : ed.getType()) {
if (tr.hasTargetProfile()) {
tr.getTargetProfile().removeIf(n -> !context.hasResource(StructureDefinition.class, n.asStringValue()));
if (!tr.hasTargetProfile()) {
return false;
}
}
}
return true;
}
public BasePackageCacheManager getPcm() {
return pcm;
}
public int getCount() {
return count;
}
public byte[] getMap() throws IOException {
return pckCore.hasFile("other", "spec.internals") ? FileUtilities.streamToBytes(pckCore.load("other", "spec.internals")) : null;
}
public NpmPackage getPckCore() {
return pckCore;
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy