add Resource Dependency walker + Resource Minifier functionality

This commit is contained in:
Grahame Grieve 2023-05-31 06:32:55 +03:00
parent f238d1af14
commit d4d5b42aa1
5 changed files with 914 additions and 0 deletions

View File

@ -0,0 +1,39 @@
package org.hl7.fhir.convertors.misc;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import org.hl7.fhir.r5.formats.JsonParser;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.utils.ResourceMinifier;
import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.npm.NpmPackage;
import org.hl7.fhir.utilities.npm.NpmPackage.PackageResourceInformation;
public class PackageMinifier {
public static void main(String[] args) throws IOException {
new PackageMinifier().process(args[0], args[1]);
}
private void process(String source, String target) throws FileNotFoundException, IOException {
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager(true);
NpmPackage src = pcm.loadPackage(source);
NpmPackage tgt = NpmPackage.empty();
tgt.setNpm(src.getNpm().deepCopy());
tgt.getNpm().set("name", tgt.getNpm().asString("name")+".min");
ResourceMinifier min = new ResourceMinifier();
for (PackageResourceInformation pri : src.listIndexedResources()) {
if (min.isMinified(pri.getResourceType())) {
Resource res = new JsonParser().parse(src.load(pri));
min.minify(res);
tgt.addFile("package", res.fhirType()+"-"+res.getIdPart()+".json", new JsonParser().composeBytes(res), null);
}
}
tgt.save(new FileOutputStream(target));
}
}

View File

@ -0,0 +1,140 @@
package org.hl7.fhir.convertors.misc;
import java.io.IOException;
import java.io.FileOutputStream;
import java.util.Arrays;
import java.util.List;
import org.hl7.fhir.convertors.conv40_50.VersionConvertor_40_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_10_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50;
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
import org.hl7.fhir.convertors.loaders.loaderR5.NullLoaderKnowledgeProviderR5;
import org.hl7.fhir.convertors.loaders.loaderR5.R2ToR5Loader;
import org.hl7.fhir.convertors.loaders.loaderR5.R3ToR5Loader;
import org.hl7.fhir.convertors.loaders.loaderR5.R4ToR5Loader;
import org.hl7.fhir.convertors.loaders.loaderR5.R5ToR5Loader;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.context.IWorkerContext.IContextResourceLoader;
import org.hl7.fhir.r5.context.SimpleWorkerContext;
import org.hl7.fhir.r5.context.SimpleWorkerContext.SimpleWorkerContextBuilder;
import org.hl7.fhir.r5.model.CapabilityStatement;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.test.utils.TestPackageLoader;
import org.hl7.fhir.r5.utils.ResourceDependencyWalker;
import org.hl7.fhir.r5.utils.ResourceDependencyWalker.IResourceDependencyNotifier;
import org.hl7.fhir.r5.utils.ResourceMinifier;
import org.hl7.fhir.utilities.VersionUtilities;
import org.hl7.fhir.utilities.json.JsonException;
import org.hl7.fhir.utilities.json.parser.JsonParser;
import org.hl7.fhir.utilities.npm.FilesystemPackageCacheManager;
import org.hl7.fhir.utilities.npm.NpmPackage;
public class ResourceDependencyPackageBuilder {
private static final List<String> LOADED_TYPES =
Arrays.asList("StructureDefinition", "CodeSystem", "ValueSet", "CapabilityStatement", "ConceptMap", "NamingSystem", "OperationDefinition", "SearchParameter", "Questionnaire");
public static void main(String[] args) throws IOException {
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager(true);
System.out.println("Load Core");
NpmPackage src = pcm.loadPackage(VersionUtilities.packageForVersion(args[0]));
SimpleWorkerContext ctxt = new SimpleWorkerContextBuilder().withAllowLoadingDuplicates(true).fromPackage(src);
loadFromPackage(args[0], ctxt, pcm, args[1]);
NpmResourceDependencyCollector pckBuilder = new NpmResourceDependencyCollector();
pckBuilder.npm = makeNpm(args[3], ctxt.getVersion());
pckBuilder.minify = "true".equals(args[5]);
new ResourceDependencyWalker(ctxt, pckBuilder).walk(ctxt.fetchResource(CapabilityStatement.class, args[2]));
pckBuilder.npm.save(new FileOutputStream(args[4]));
}
private static NpmPackage makeNpm(String vid, String version) throws JsonException, IOException {
NpmPackage res = NpmPackage.empty();
String name = vid.substring(0, vid.indexOf('#'));
String ver = vid.substring(vid.indexOf("#")+1);
res.setNpm(JsonParser.parseObject("{\"name\": \""+name+"\", \"version\": \""+ver+"\",\"fhirVersions\": [\""+version+"\"],\"type\": \"fhir.ig\",\"tools-version\": 3}"));
return res;
}
public static class NpmResourceDependencyCollector implements IResourceDependencyNotifier {
private NpmPackage npm;
private boolean minify;
private byte[] toBytes(Resource resource) throws IOException {
if (VersionUtilities.isR5Ver(npm.fhirVersion())) {
return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(resource);
}
if (VersionUtilities.isR4Plus(npm.fhirVersion())) {
org.hl7.fhir.r4.model.Resource r4 = VersionConvertorFactory_40_50.convertResource(resource);
return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(r4);
}
if (VersionUtilities.isR3Ver(npm.fhirVersion())) {
org.hl7.fhir.dstu3.model.Resource r3 = VersionConvertorFactory_30_50.convertResource(resource);
return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(r3);
}
if (VersionUtilities.isR2Ver(npm.fhirVersion())) {
org.hl7.fhir.dstu2.model.Resource r2 = VersionConvertorFactory_10_50.convertResource(resource);
return new org.hl7.fhir.dstu2.formats.JsonParser().composeBytes(r2);
}
throw new Error("Unsupported version");
}
@Override
public void seeResource(Resource resource, String summaryId) {
if (minify) {
ResourceMinifier min = new ResourceMinifier();
if (min.isMinified(resource.fhirType())) {
resource = resource.copy();
min.minify(resource);
} else {
return;
}
}
try {
npm.addFile("package", resource.fhirType()+"-"+resource.getIdPart()+".json", toBytes(resource), null);
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void brokenLink(String link) {
System.err.println("Broken Link: " +link);
}
}
private static void loadFromPackage(String version, SimpleWorkerContext ctxt, FilesystemPackageCacheManager pcm, String pid) throws FHIRException, IOException {
NpmPackage npm = pcm.loadPackage(pid);
for (String dep : npm.dependencies()) {
if (!VersionUtilities.isCorePackage(dep)) {
loadFromPackage(version, ctxt, pcm, dep);
}
}
System.out.println("Load "+pid);
ctxt.loadFromPackage(npm, getLoader(version));
}
private static IContextResourceLoader getLoader(String version) {
if (VersionUtilities.isR2Ver(version)) {
return new R2ToR5Loader(LOADED_TYPES, new NullLoaderKnowledgeProviderR5());
}
if (VersionUtilities.isR3Ver(version)) {
return new R3ToR5Loader(LOADED_TYPES, new NullLoaderKnowledgeProviderR5());
}
if (VersionUtilities.isR4Ver(version)) {
return new R4ToR5Loader(LOADED_TYPES, new NullLoaderKnowledgeProviderR5(), version);
}
if (VersionUtilities.isR5Ver(version)) {
return new R5ToR5Loader(LOADED_TYPES, new NullLoaderKnowledgeProviderR5());
}
return null;
}
}

View File

@ -0,0 +1,418 @@
package org.hl7.fhir.r5.utils;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CanonicalType;
import org.hl7.fhir.r5.model.CapabilityStatement;
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestComponent;
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceComponent;
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceOperationComponent;
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent;
import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.CodeSystem.PropertyComponent;
import org.hl7.fhir.r5.model.ConceptMap;
import org.hl7.fhir.r5.model.ConceptMap.AdditionalAttributeComponent;
import org.hl7.fhir.r5.model.ConceptMap.ConceptMapGroupComponent;
import org.hl7.fhir.r5.model.ConceptMap.SourceElementComponent;
import org.hl7.fhir.r5.model.ConceptMap.TargetElementComponent;
import org.hl7.fhir.r5.model.DomainResource;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingAdditionalComponent;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
import org.hl7.fhir.r5.model.NamingSystem;
import org.hl7.fhir.r5.model.OperationDefinition;
import org.hl7.fhir.r5.model.OperationDefinition.OperationDefinitionParameterComponent;
import org.hl7.fhir.r5.model.Questionnaire;
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemAnswerOptionComponent;
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemComponent;
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemEnableWhenComponent;
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemInitialComponent;
import org.hl7.fhir.r5.model.Reference;
import org.hl7.fhir.r5.model.RelatedArtifact;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.SearchParameter;
import org.hl7.fhir.r5.model.SearchParameter.SearchParameterComponentComponent;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.UsageContext;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionComponent;
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionContainsComponent;
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionParameterComponent;
import org.hl7.fhir.r5.model.ValueSet.ValueSetExpansionPropertyComponent;
import org.hl7.fhir.utilities.Utilities;
public class ResourceDependencyWalker {
public interface IResourceDependencyNotifier {
public void seeResource(Resource resource, String summaryId);
public void brokenLink(String link);
}
public class NullResourceDependencyNotifier implements IResourceDependencyNotifier {
@Override
public void seeResource(Resource resource, String summaryId) {
System.out.println(summaryId);
}
@Override
public void brokenLink(String link) {
System.err.println("Broken Link: " +link);
}
}
private IResourceDependencyNotifier notifier = new NullResourceDependencyNotifier();
private IWorkerContext context;
private Set<String> processedLinks = new HashSet<>();
private Set<Resource> processedResources = new HashSet<>();
public ResourceDependencyWalker(IWorkerContext context, IResourceDependencyNotifier notifier) {
super();
this.notifier = notifier;
this.context = context;
}
public ResourceDependencyWalker(IWorkerContext context) {
super();
this.context = context;
}
private void notify(Resource resource, String prefix) {
String summary = null;
if (resource instanceof CanonicalResource) {
summary = ((CanonicalResource) resource).getVersionedUrl();
} else {
summary = resource.fhirType()+"/"+resource.getIdPart();
}
if (resource.getSourcePackage() != null) {
summary = summary + " from "+resource.getSourcePackage();
}
notifier.seeResource(resource, prefix+summary);
}
public void walk(Resource res) {
notify(res, "Find Dependencies for ");
processedResources.add(res);
doWalk(res);
}
private void walkIntoLink(String value, CanonicalResource source) {
if (value != null ) {
String key = source.getSourcePackage() == null ? value : value+" from "+source.getSourcePackage().getVID();
if (!processedLinks.contains(key)) {
processedLinks.add(key);
Resource tgt = context.fetchResource(Resource.class, value, source);
if (tgt == null && Utilities.charCount(value, '/') == 1) {
tgt = context.fetchResourceById(value.substring(0, value.indexOf('/')), value.substring(value.indexOf('/')+1));
}
if (tgt == null) {
notifier.brokenLink(key);
} else {
if (!processedResources.contains(tgt) && !isCore(tgt)) {
processedResources.add(tgt);
notify(tgt, "Depends On ");
doWalk(tgt);
}
}
}
}
}
private boolean isCore(Resource tgt) {
return tgt.hasSourcePackage() && "hl7.fhir.r5.core".equals(tgt.getSourcePackage().getId());
}
private void doWalk(Resource res) {
if (res instanceof StructureDefinition) {
walkSD((StructureDefinition) res);
} else if (res instanceof ValueSet) {
walkVS((ValueSet) res);
} else if (res instanceof CodeSystem) {
walkCS((CodeSystem) res);
} else if (res instanceof CapabilityStatement) {
walkCS((CapabilityStatement) res);
} else if (res instanceof ConceptMap) {
walkCM((ConceptMap) res);
} else if (res instanceof NamingSystem) {
walkNS((NamingSystem) res);
} else if (res instanceof OperationDefinition) {
walkOD((OperationDefinition) res);
} else if (res instanceof SearchParameter) {
walkSP((SearchParameter) res);
} else if (res instanceof Questionnaire) {
walkQ((Questionnaire) res);
} else {
throw new Error("Resource "+res.fhirType()+" not Processed yet");
}
}
private void walkSP(SearchParameter sp) {
walkCR(sp);
walkIntoLink(sp.getDerivedFrom(), sp);
for (SearchParameterComponentComponent spc : sp.getComponent()) {
walkIntoLink(spc.getDefinition(), sp);
}
}
private void walkQ(Questionnaire q) {
walkCR(q);
walkCT(q.getDerivedFrom(), q);
for (QuestionnaireItemComponent item : q.getItem()) {
walkQItem(item, q);
}
}
private void walkQItem(QuestionnaireItemComponent item, Questionnaire q) {
walkIntoLink(item.getDefinition(), q);
walkIntoLink(item.getAnswerValueSet(), q);
for (QuestionnaireItemEnableWhenComponent ew : item.getEnableWhen()) {
if (ew.hasAnswerReference()) {
walkIntoLink(ew.getAnswerReference().getReference(), q);
}
}
for (QuestionnaireItemAnswerOptionComponent ao : item.getAnswerOption()) {
if (ao.hasValueReference()) {
walkIntoLink(ao.getValueReference().getReference(), q);
}
}
for (QuestionnaireItemInitialComponent iv : item.getInitial()) {
if (iv.hasValueReference()) {
walkIntoLink(iv.getValueReference().getReference(), q);
}
}
walkIntoLink(item.getDefinition(), q);
for (QuestionnaireItemComponent child : item.getItem()) {
walkQItem(child, q);
}
}
private void walkOD(OperationDefinition od) {
walkCR(od);
walkIntoLink(od.getBase(), od);
walkIntoLink(od.getInputProfile(), od);
walkIntoLink(od.getOutputProfile(), od);
for (OperationDefinitionParameterComponent p : od.getParameter()) {
walkODP(od, p);
}
}
private void walkODP(OperationDefinition od, OperationDefinitionParameterComponent p) {
walkCT(p.getTargetProfile(), od);
walkIntoLink(p.getBinding().getValueSet(), od);
for (OperationDefinitionParameterComponent pp : p.getPart()) {
walkODP(od, pp);
}
}
private void walkNS(NamingSystem ns) {
walkCR(ns);
}
private void walkCM(ConceptMap cm) {
walkCR(cm);
walkRA(cm.getRelatedArtifact(), cm);
for (org.hl7.fhir.r5.model.ConceptMap.PropertyComponent prop : cm.getProperty()) {
walkIntoLink(prop.getUri(), cm);
}
for (AdditionalAttributeComponent attr : cm.getAdditionalAttribute()) {
walkIntoLink(attr.getUri(), cm);
}
walkIntoLink(cm.getSourceScope().primitiveValue(), cm);
walkIntoLink(cm.getTargetScope().primitiveValue(), cm);
for (ConceptMapGroupComponent group : cm.getGroup()) {
walkIntoLink(group.getSource(), cm);
walkIntoLink(group.getTarget(), cm);
walkIntoLink(group.getUnmapped().getValueSet(), cm);
walkIntoLink(group.getUnmapped().getOtherMap(), cm);
for (SourceElementComponent elem : group.getElement()) {
walkIntoLink(elem.getValueSet(), cm);
for (TargetElementComponent tgt : elem.getTarget()) {
walkIntoLink(tgt.getValueSet(), cm);
}
}
}
}
private void walkCS(CapabilityStatement cs) {
walkCR(cs);
walkCT(cs.getInstantiates(), cs);
walkCT(cs.getImports(), cs);
walkCT(cs.getImplementationGuide(), cs);
for (CapabilityStatementRestComponent rest : cs.getRest()) {
for (CapabilityStatementRestResourceComponent res : rest.getResource()) {
walkIntoLink(res.getProfile(), cs);
walkCT(res.getSupportedProfile(), cs);
for (CapabilityStatementRestResourceSearchParamComponent srch : res.getSearchParam()) {
walkIntoLink(srch.getDefinition(), cs);
}
for (CapabilityStatementRestResourceOperationComponent op : res.getOperation()) {
walkIntoLink(op.getDefinition(), cs);
}
}
for (CapabilityStatementRestResourceSearchParamComponent srch : rest.getSearchParam()) {
walkIntoLink(srch.getDefinition(), cs);
}
for (CapabilityStatementRestResourceOperationComponent op : rest.getOperation()) {
walkIntoLink(op.getDefinition(), cs);
}
}
}
private void walkCS(CodeSystem cs) {
walkCR(cs);
walkRA(cs.getRelatedArtifact(), cs);
if (cs.hasValueSet()) {
walkIntoLink(cs.getValueSet(), cs);
}
if (cs.hasSupplements()) {
walkIntoLink(cs.getSupplements(), cs);
}
for (PropertyComponent p : cs.getProperty()) {
if (p.hasUri()) {
walkIntoLink(p.getUri(), cs);
}
}
}
private void walkVS(ValueSet vs) {
walkCR(vs);
walkRA(vs.getRelatedArtifact(), vs);
for (ConceptSetComponent inc : vs.getCompose().getInclude()) {
walkVSInc(inc, vs);
}
for (ConceptSetComponent inc : vs.getCompose().getExclude()) {
walkVSInc(inc, vs);
}
if (vs.hasExpansion()) {
ValueSetExpansionComponent exp = vs.getExpansion();
for (ValueSetExpansionParameterComponent p : exp.getParameter()) {
if (p.hasValueUriType()) {
walkIntoLink(p.getValueUriType().primitiveValue(), vs);
}
}
for (ValueSetExpansionPropertyComponent p : exp.getProperty()) {
if (p.hasUri()) {
walkIntoLink(p.getUri(), vs);
}
}
for (ValueSetExpansionContainsComponent cc : exp.getContains()) {
walkCC(cc, vs);
}
}
}
private void walkCC(ValueSetExpansionContainsComponent cc, ValueSet vs) {
walkIntoLink(cc.getSystem(), vs);
for (ValueSetExpansionContainsComponent ccc : cc.getContains()) {
walkCC(ccc, vs);
}
}
private void walkVSInc(ConceptSetComponent inc, ValueSet vs) {
walkCT(inc.getValueSet(), vs);
walkIntoLink(inc.getSystem(), vs);
}
private void walkCT(List<CanonicalType> list, CanonicalResource source) {
for (CanonicalType ct : list) {
walkIntoLink(ct.getValue(), source);
}
}
private void walkRA(List<RelatedArtifact> list, CanonicalResource source) {
for (RelatedArtifact ra : list) {
walkRA(ra, source);
}
}
private void walkRA(RelatedArtifact ra, CanonicalResource source) {
if (ra.hasResource()) {
walkIntoLink(ra.getResource(), source);
}
if (ra.hasResourceReference()) {
walkIntoLink(ra.getResourceReference().getReference(), source);
}
}
private void walkSD(StructureDefinition sd) {
walkCR(sd);
walkIntoLink(sd.getBaseDefinition(), sd);
for (ElementDefinition ed : sd.getDifferential().getElement()) {
walkED(ed, sd);
}
}
private void walkED(ElementDefinition ed, StructureDefinition sd) {
for (TypeRefComponent type : ed.getType()) {
if (Utilities.isAbsoluteUrl(type.getCode())) {
walkIntoLink(type.getCode(), sd);
}
walkCT(type.getProfile(), sd);
walkCT(type.getTargetProfile(), sd);
}
walkCT(ed.getValueAlternatives(), sd);
if (ed.hasBinding()) {
ElementDefinitionBindingComponent b = ed.getBinding();
if (b.hasValueSet()) {
walkIntoLink(b.getValueSet(), sd);
}
for (ElementDefinitionBindingAdditionalComponent ab : b.getAdditional()) {
if (ab.hasValueSet()) {
walkIntoLink(ab.getValueSet(), sd);
}
if (ab.hasUsage()) {
walkUsage(ab.getUsage(), sd);
}
}
}
}
private void walkUsage(List<UsageContext> usageList, CanonicalResource source) {
for (UsageContext usage : usageList) {
walkUsage(usage, source);
}
}
private void walkUsage(UsageContext usage, CanonicalResource source) {
if (usage.hasValueReference()) {
walkReference(usage.getValueReference(), source);
}
}
private void walkReference(Reference ref, CanonicalResource source) {
if (ref.hasReference()) {
walkIntoLink(ref.getReference(), source);
}
}
private void walkCR(CanonicalResource cr) {
walkDR(cr);
walkUsage(cr.getUseContext(), cr);
}
private void walkDR(DomainResource dr) {
walkRes(dr);
for (Resource res : dr.getContained()) {
walk(res);
}
}
private void walkRes(Resource res) {
// nothing
}
}

View File

@ -0,0 +1,308 @@
package org.hl7.fhir.r5.utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CapabilityStatement;
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestComponent;
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceComponent;
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceOperationComponent;
import org.hl7.fhir.r5.model.CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent;
import org.hl7.fhir.r5.model.CapabilityStatement.ResourceInteractionComponent;
import org.hl7.fhir.r5.model.CapabilityStatement.SystemInteractionComponent;
import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.CodeSystem.CodeSystemFilterComponent;
import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionComponent;
import org.hl7.fhir.r5.model.CodeSystem.PropertyComponent;
import org.hl7.fhir.r5.model.ConceptMap;
import org.hl7.fhir.r5.model.ConceptMap.AdditionalAttributeComponent;
import org.hl7.fhir.r5.model.ConceptMap.ConceptMapGroupComponent;
import org.hl7.fhir.r5.model.ConceptMap.SourceElementComponent;
import org.hl7.fhir.r5.model.ConceptMap.TargetElementComponent;
import org.hl7.fhir.r5.model.DomainResource;
import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingAdditionalComponent;
import org.hl7.fhir.r5.model.NamingSystem;
import org.hl7.fhir.r5.model.NamingSystem.NamingSystemUniqueIdComponent;
import org.hl7.fhir.r5.model.OperationDefinition;
import org.hl7.fhir.r5.model.OperationDefinition.OperationDefinitionOverloadComponent;
import org.hl7.fhir.r5.model.OperationDefinition.OperationDefinitionParameterComponent;
import org.hl7.fhir.r5.model.Questionnaire;
import org.hl7.fhir.r5.model.Questionnaire.QuestionnaireItemComponent;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.utilities.Utilities;
public class ResourceMinifier {
private static final List<String> VALIDATION_EXTENSIONS =
Arrays.asList(ToolingExtensions.EXT_OBLIGATION_INHERITS, ToolingExtensions.EXT_OBLIGATION_PROFILE_FLAG);
public boolean isMinified(String resName) {
return Utilities.existsInList(resName, "StructureDefinition", "CodeSystem", "ValueSet", "CapabilityStatement",
"ConceptMap", "NamingSystem", "OperationDefinition", "SearchParameter", "Questionnaire");
}
public void minify(Resource res) {
if (res instanceof StructureDefinition) {
minifySD((StructureDefinition) res);
}
if (res instanceof ValueSet) {
minifyVS((ValueSet) res);
}
if (res instanceof CodeSystem) {
minifyCS((CodeSystem) res);
}
if (res instanceof CapabilityStatement) {
minifyCS((CapabilityStatement) res);
}
if (res instanceof ConceptMap) {
minifyCM((ConceptMap) res);
}
if (res instanceof NamingSystem) {
minifyNS((NamingSystem) res);
}
if (res instanceof OperationDefinition) {
minifyOD((OperationDefinition) res);
}
if (res instanceof Questionnaire) {
minifyQ((Questionnaire) res);
}
}
private void minifyQ(Questionnaire q) {
minCR(q);
q.setApprovalDate(null);
q.setLastReviewDate(null);
q.setEffectivePeriod(null);
q.setCode(null);
for (QuestionnaireItemComponent item : q.getItem()) {
minifyQItem(item);
}
}
private void minifyQItem(QuestionnaireItemComponent item) {
item.setCode(null);
item.setPrefix(null);
item.setText(null);
for (QuestionnaireItemComponent child : item.getItem()) {
minifyQItem(child);
}
}
private void minifyOD(OperationDefinition od) {
minCR(od);
od.setComment(null);
for (OperationDefinitionParameterComponent p : od.getParameter()) {
minifyODP(p);
}
for (OperationDefinitionOverloadComponent ol : od.getOverload()) {
ol.setComment(null);
}
}
private void minifyODP(OperationDefinitionParameterComponent p) {
p.setDocumentation(null);
for (OperationDefinitionParameterComponent pp : p.getPart()) {
minifyODP(pp);
}
}
private void minifyNS(NamingSystem ns) {
minCR(ns);
ns.setApprovalDate(null);
ns.setLastReviewDate(null);
ns.setEffectivePeriod(null);
ns.setTopic(null);
ns.setAuthor(null);
ns.setEditor(null);
ns.setReviewer(null);
ns.setEndorser(null);
ns.setRelatedArtifact(null);
ns.setUsage(null);
for (NamingSystemUniqueIdComponent id : ns.getUniqueId()) {
id.setComment(null);
}
}
private void minifyCM(ConceptMap cm) {
minCR(cm);
cm.setApprovalDate(null);
cm.setLastReviewDate(null);
cm.setEffectivePeriod(null);
cm.setTopic(null);
cm.setAuthor(null);
cm.setEditor(null);
cm.setReviewer(null);
cm.setEndorser(null);
cm.setRelatedArtifact(null);
for (org.hl7.fhir.r5.model.ConceptMap.PropertyComponent prop : cm.getProperty()) {
prop.setDescription(null);
}
for (AdditionalAttributeComponent attr : cm.getAdditionalAttribute()) {
attr.setDescription(null);
}
for (ConceptMapGroupComponent group : cm.getGroup()) {
for (SourceElementComponent elem : group.getElement()) {
for (TargetElementComponent tgt : elem.getTarget()) {
tgt.setComment(null);
}
}
}
}
private void minifyCS(CapabilityStatement cs) {
minCR(cs);
cs.setSoftware(null);
cs.setImplementation(null);
for (CapabilityStatementRestComponent rest : cs.getRest()) {
rest.setDocumentation(null);
rest.setSecurity(null);
for (CapabilityStatementRestResourceComponent res : rest.getResource()) {
res.setDocumentation(null);
for (ResourceInteractionComponent intr : res.getInteraction()) {
intr.setDocumentation(null);
}
for (CapabilityStatementRestResourceSearchParamComponent srch : res.getSearchParam()) {
srch.setDocumentation(null);
}
for (CapabilityStatementRestResourceOperationComponent op : res.getOperation()) {
op.setDocumentation(null);
}
}
for (SystemInteractionComponent intr : rest.getInteraction()) {
intr.setDocumentation(null);
}
for (CapabilityStatementRestResourceSearchParamComponent srch : rest.getSearchParam()) {
srch.setDocumentation(null);
}
for (CapabilityStatementRestResourceOperationComponent op : rest.getOperation()) {
op.setDocumentation(null);
}
}
cs.setMessaging(null);
cs.setDocument(null);
}
private void minifyCS(CodeSystem cs) {
minCR(cs);
cs.setApprovalDate(null);
cs.setLastReviewDate(null);
cs.setEffectivePeriod(null);
cs.setTopic(null);
cs.setAuthor(null);
cs.setEditor(null);
cs.setReviewer(null);
cs.setEndorser(null);
cs.setRelatedArtifact(null);
for (CodeSystemFilterComponent filter : cs.getFilter()) {
filter.setDescription(null);
}
for (PropertyComponent prop : cs.getProperty()) {
prop.setDescription(null);
}
for (ConceptDefinitionComponent cc : cs.getConcept()) {
minify(cc);
}
}
private void minify(ConceptDefinitionComponent cc) {
cc.setDefinition(null);
for (ConceptDefinitionComponent ccc : cc.getConcept()) {
minify(ccc);
}
}
private void minifyVS(ValueSet vs) {
minCR(vs);
vs.setApprovalDate(null);
vs.setLastReviewDate(null);
vs.setEffectivePeriod(null);
vs.setTopic(null);
vs.setAuthor(null);
vs.setEditor(null);
vs.setReviewer(null);
vs.setEndorser(null);
vs.setRelatedArtifact(null);
// can't remove anything else
}
private void minifySD(StructureDefinition sd) {
minCR(sd);
sd.setKeyword(null);
sd.setMapping(null);
sd.setSnapshot(null);
for (ElementDefinition ed : sd.getDifferential().getElement()) {
minifyED(ed);
}
}
private void minifyED(ElementDefinition ed) {
ed.setLabel(null);
ed.setCode(null);
ed.getSlicing().setDescription(null);
ed.setShort(null);
ed.setDefinition(null);
ed.setComment(null);
ed.setRequirements(null);
ed.setAlias(null);
ed.setDefaultValue(null);
ed.setOrderMeaning(null);
ed.setMeaningWhenMissing(null);
ed.setExample(null);
ed.setIsModifierReason(null);
ed.getBinding().setDescription(null);
for (ElementDefinitionBindingAdditionalComponent abn : ed.getBinding().getAdditional()) {
abn.setDocumentation(null);
abn.setShortDoco(null);
}
ed.setMapping(null);
}
private void minCR(CanonicalResource cr) {
minDR(cr);
cr.setIdentifier(null);
cr.setPublisher(null);
cr.setContact(null);
cr.setDescription(null);
cr.setPurpose(null);
cr.setCopyright(null);
cr.setCopyrightLabel(null);
}
private void minDR(DomainResource dr) {
minRes(dr);
dr.setText(null);
List<Resource> del = new ArrayList<>();
for (Resource res : dr.getContained()) {
if (isMinified(res.fhirType())) {
minify(res);
} else {
del.add(res);
}
}
dr.getContained().removeAll(del);
dr.getExtension().removeIf(ext -> !Utilities.existsInList(ext.getUrl(), VALIDATION_EXTENSIONS));
}
private void minRes(Resource res) {
res.setMeta(null);
res.setImplicitRules(null);
}
}

View File

@ -719,6 +719,15 @@ public class NpmPackage {
return npm;
}
/**
* should only use this when npm == null
*
* @param npm
*/
public void setNpm(JsonObject npm) {
this.npm = npm;
}
/**
* convenience method for getting the package name
* @return