Merge pull request #1753 from hapifhir/2024-09-gg-connectathon
2024 09 gg connectathon
This commit is contained in:
commit
09ad0005b2
|
@ -25,8 +25,10 @@ import org.hl7.fhir.r4.model.StringType;
|
|||
import org.hl7.fhir.r5.model.CodeType;
|
||||
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingAdditionalComponent;
|
||||
import org.hl7.fhir.r5.model.UsageContext;
|
||||
import org.hl7.fhir.r5.utils.ToolingExtensions;
|
||||
|
||||
public class ElementDefinition40_50 {
|
||||
|
||||
public static org.hl7.fhir.r5.model.ElementDefinition convertElementDefinition(org.hl7.fhir.r4.model.ElementDefinition src) throws FHIRException {
|
||||
if (src == null) return null;
|
||||
org.hl7.fhir.r5.model.ElementDefinition tgt = new org.hl7.fhir.r5.model.ElementDefinition();
|
||||
|
@ -616,7 +618,7 @@ public class ElementDefinition40_50 {
|
|||
if (src == null) return null;
|
||||
org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent tgt = new org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent();
|
||||
ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().copyElement(src, tgt,
|
||||
"http://hl7.org/fhir/5.0/StructureDefinition/extension-ElementDefinition.binding.additional");
|
||||
"http://hl7.org/fhir/5.0/StructureDefinition/extension-ElementDefinition.binding.additional", ToolingExtensions.EXT_BINDING_ADDITIONAL);
|
||||
if (src.hasStrength()) tgt.setStrengthElement(Enumerations40_50.convertBindingStrength(src.getStrengthElement()));
|
||||
if (src.hasDescription()) tgt.setDescriptionElement(String40_50.convertStringToMarkdown(src.getDescriptionElement()));
|
||||
if (src.hasValueSet()) tgt.setValueSetElement(Canonical40_50.convertCanonical(src.getValueSetElement()));
|
||||
|
@ -624,6 +626,9 @@ public class ElementDefinition40_50 {
|
|||
for (org.hl7.fhir.r4.model.Extension ext : src.getExtensionsByUrl("http://hl7.org/fhir/5.0/StructureDefinition/extension-ElementDefinition.binding.additional")) {
|
||||
tgt.addAdditional(convertAdditional(ext));
|
||||
}
|
||||
for (org.hl7.fhir.r4.model.Extension ext : src.getExtensionsByUrl(ToolingExtensions.EXT_BINDING_ADDITIONAL)) {
|
||||
tgt.addAdditional(convertAdditional(ext));
|
||||
}
|
||||
return tgt;
|
||||
}
|
||||
|
||||
|
@ -652,12 +657,12 @@ public class ElementDefinition40_50 {
|
|||
return tgt;
|
||||
}
|
||||
|
||||
private static Extension convertAdditional(ElementDefinitionBindingAdditionalComponent src) {
|
||||
private static org.hl7.fhir.r4.model.Extension convertAdditional(ElementDefinitionBindingAdditionalComponent src) {
|
||||
if (src == null) return null;
|
||||
Extension tgt = new Extension();
|
||||
org.hl7.fhir.r4.model.Extension tgt = new Extension(ToolingExtensions.EXT_BINDING_ADDITIONAL);
|
||||
ConversionContext40_50.INSTANCE.getVersionConvertor_40_50().copyElement(src, tgt);
|
||||
if (src.hasPurpose()) {
|
||||
tgt.addExtension(new Extension("purpose", new CodeType(src.getPurposeElement().primitiveValue())));
|
||||
tgt.addExtension(new Extension("purpose", new org.hl7.fhir.r4.model.CodeType(src.getPurposeElement().primitiveValue())));
|
||||
}
|
||||
if (src.hasValueSet()) {
|
||||
tgt.addExtension(new Extension("valueSet", Canonical40_50.convertCanonical(src.getValueSetElement())));
|
||||
|
|
|
@ -33,9 +33,11 @@ import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_40;
|
|||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_30_50;
|
||||
import org.hl7.fhir.convertors.factory.VersionConvertorFactory_40_50;
|
||||
import org.hl7.fhir.r5.model.Enumeration;
|
||||
import org.hl7.fhir.r5.model.Enumerations.FHIRVersion;
|
||||
import org.hl7.fhir.r5.model.Enumerations.FHIRVersionEnumFactory;
|
||||
import org.hl7.fhir.r5.model.ImplementationGuide;
|
||||
import org.hl7.fhir.r5.model.Resource;
|
||||
import org.hl7.fhir.r5.model.StructureDefinition;
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
|
@ -237,7 +239,7 @@ public class NpmPackageVersionConverter {
|
|||
return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(VersionConvertorFactory_14_30.convertResource(VersionConvertorFactory_10_30.convertResource(res)));
|
||||
} else if (VersionUtilities.isR3Ver(version)) {
|
||||
return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(VersionConvertorFactory_10_30.convertResource(res));
|
||||
} else if (VersionUtilities.isR4Ver(version)) {
|
||||
} else if (VersionUtilities.isR4Ver(version) || VersionUtilities.isR4BVer(version)) {
|
||||
return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(VersionConvertorFactory_10_40.convertResource(res));
|
||||
} else if (VersionUtilities.isR5Plus(version)) {
|
||||
return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(VersionConvertorFactory_10_50.convertResource(res));
|
||||
|
@ -251,7 +253,7 @@ public class NpmPackageVersionConverter {
|
|||
return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(res);
|
||||
} else if (VersionUtilities.isR3Ver(version)) {
|
||||
return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(VersionConvertorFactory_14_30.convertResource(res));
|
||||
} else if (VersionUtilities.isR4Ver(version)) {
|
||||
} else if (VersionUtilities.isR4Ver(version) || VersionUtilities.isR4BVer(version)) {
|
||||
return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(VersionConvertorFactory_14_40.convertResource(res));
|
||||
} else if (VersionUtilities.isR5Plus(version)) {
|
||||
return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(VersionConvertorFactory_14_50.convertResource(res));
|
||||
|
@ -265,7 +267,7 @@ public class NpmPackageVersionConverter {
|
|||
return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(VersionConvertorFactory_14_30.convertResource(res));
|
||||
} else if (VersionUtilities.isR3Ver(version)) {
|
||||
return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(res);
|
||||
} else if (VersionUtilities.isR4Ver(version)) {
|
||||
} else if (VersionUtilities.isR4Ver(version) || VersionUtilities.isR4BVer(version)) {
|
||||
return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(VersionConvertorFactory_30_40.convertResource(res));
|
||||
} else if (VersionUtilities.isR5Plus(version)) {
|
||||
return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(VersionConvertorFactory_30_50.convertResource(res));
|
||||
|
@ -279,7 +281,21 @@ public class NpmPackageVersionConverter {
|
|||
return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(VersionConvertorFactory_14_40.convertResource(res));
|
||||
} else if (VersionUtilities.isR3Ver(version)) {
|
||||
return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(VersionConvertorFactory_30_40.convertResource(res, new BaseAdvisor_30_40(false)));
|
||||
} else if (VersionUtilities.isR4Ver(version)) {
|
||||
} else if (VersionUtilities.isR4Ver(version) || VersionUtilities.isR4BVer(version)) {
|
||||
return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(res);
|
||||
} else if (VersionUtilities.isR5Plus(version)) {
|
||||
return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(VersionConvertorFactory_40_50.convertResource(res));
|
||||
}
|
||||
} else if (VersionUtilities.isR4BVer(currentVersion)) {
|
||||
org.hl7.fhir.r4.model.Resource res = new org.hl7.fhir.r4.formats.JsonParser().parse(cnt);
|
||||
convertResourceR4B(res);
|
||||
if (VersionUtilities.isR2Ver(version)) {
|
||||
return new org.hl7.fhir.dstu2.formats.JsonParser().composeBytes(VersionConvertorFactory_10_40.convertResource(res, new PR2Handler()));
|
||||
} else if (VersionUtilities.isR2BVer(version)) {
|
||||
return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(VersionConvertorFactory_14_40.convertResource(res));
|
||||
} else if (VersionUtilities.isR3Ver(version)) {
|
||||
return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(VersionConvertorFactory_30_40.convertResource(res, new BaseAdvisor_30_40(false)));
|
||||
} else if (VersionUtilities.isR4Ver(version) || VersionUtilities.isR4BVer(version)) {
|
||||
return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(res);
|
||||
} else if (VersionUtilities.isR5Plus(version)) {
|
||||
return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(VersionConvertorFactory_40_50.convertResource(res));
|
||||
|
@ -293,7 +309,7 @@ public class NpmPackageVersionConverter {
|
|||
return new org.hl7.fhir.dstu2016may.formats.JsonParser().composeBytes(VersionConvertorFactory_14_50.convertResource(res));
|
||||
} else if (VersionUtilities.isR3Ver(version)) {
|
||||
return new org.hl7.fhir.dstu3.formats.JsonParser().composeBytes(VersionConvertorFactory_30_50.convertResource(res, new BaseAdvisor_30_50(false)));
|
||||
} else if (VersionUtilities.isR4Ver(version)) {
|
||||
} else if (VersionUtilities.isR4Ver(version) || VersionUtilities.isR4BVer(version)) {
|
||||
return new org.hl7.fhir.r4.formats.JsonParser().composeBytes(VersionConvertorFactory_40_50.convertResource(res));
|
||||
} else if (VersionUtilities.isR5Plus(version)) {
|
||||
return new org.hl7.fhir.r5.formats.JsonParser().composeBytes(res);
|
||||
|
@ -311,6 +327,10 @@ public class NpmPackageVersionConverter {
|
|||
org.hl7.fhir.dstu2.model.ImplementationGuide ig = (org.hl7.fhir.dstu2.model.ImplementationGuide) res;
|
||||
ig.setFhirVersion(version);
|
||||
}
|
||||
if (res instanceof org.hl7.fhir.dstu2.model.StructureDefinition) {
|
||||
org.hl7.fhir.dstu2.model.StructureDefinition sd = (org.hl7.fhir.dstu2.model.StructureDefinition) res;
|
||||
sd.setFhirVersion(version);
|
||||
}
|
||||
}
|
||||
|
||||
private void convertResourceR2B(org.hl7.fhir.dstu2016may.model.Resource res) {
|
||||
|
@ -318,6 +338,10 @@ public class NpmPackageVersionConverter {
|
|||
org.hl7.fhir.dstu2016may.model.ImplementationGuide ig = (org.hl7.fhir.dstu2016may.model.ImplementationGuide) res;
|
||||
ig.setFhirVersion(version);
|
||||
}
|
||||
if (res instanceof org.hl7.fhir.dstu2016may.model.StructureDefinition) {
|
||||
org.hl7.fhir.dstu2016may.model.StructureDefinition sd = (org.hl7.fhir.dstu2016may.model.StructureDefinition) res;
|
||||
sd.setFhirVersion(version);
|
||||
}
|
||||
}
|
||||
|
||||
private void convertResourceR3(org.hl7.fhir.dstu3.model.Resource res) {
|
||||
|
@ -325,6 +349,10 @@ public class NpmPackageVersionConverter {
|
|||
org.hl7.fhir.dstu3.model.ImplementationGuide ig = (org.hl7.fhir.dstu3.model.ImplementationGuide) res;
|
||||
ig.setFhirVersion(version);
|
||||
}
|
||||
if (res instanceof org.hl7.fhir.dstu3.model.StructureDefinition) {
|
||||
org.hl7.fhir.dstu3.model.StructureDefinition sd = (org.hl7.fhir.dstu3.model.StructureDefinition) res;
|
||||
sd.setFhirVersion(version);
|
||||
}
|
||||
}
|
||||
|
||||
private void convertResourceR4(org.hl7.fhir.r4.model.Resource res) {
|
||||
|
@ -334,6 +362,23 @@ public class NpmPackageVersionConverter {
|
|||
ig.getFhirVersion().add(new org.hl7.fhir.r4.model.Enumeration<>(new org.hl7.fhir.r4.model.Enumerations.FHIRVersionEnumFactory(), version));
|
||||
ig.setPackageId(packageId);
|
||||
}
|
||||
if (res instanceof org.hl7.fhir.r4.model.StructureDefinition) {
|
||||
org.hl7.fhir.r4.model.StructureDefinition sd = (org.hl7.fhir.r4.model.StructureDefinition) res;
|
||||
sd.setFhirVersion(org.hl7.fhir.r4.model.Enumerations.FHIRVersion.fromCode(version));
|
||||
}
|
||||
}
|
||||
|
||||
private void convertResourceR4B(org.hl7.fhir.r4.model.Resource res) {
|
||||
if (res instanceof org.hl7.fhir.r4.model.ImplementationGuide) {
|
||||
org.hl7.fhir.r4.model.ImplementationGuide ig = (org.hl7.fhir.r4.model.ImplementationGuide) res;
|
||||
ig.getFhirVersion().clear();
|
||||
ig.getFhirVersion().add(new org.hl7.fhir.r4.model.Enumeration<>(new org.hl7.fhir.r4.model.Enumerations.FHIRVersionEnumFactory(), version));
|
||||
ig.setPackageId(packageId);
|
||||
}
|
||||
if (res instanceof org.hl7.fhir.r4.model.StructureDefinition) {
|
||||
org.hl7.fhir.r4.model.StructureDefinition sd = (org.hl7.fhir.r4.model.StructureDefinition) res;
|
||||
sd.setFhirVersion(org.hl7.fhir.r4.model.Enumerations.FHIRVersion.fromCode(version));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
@ -344,6 +389,10 @@ public class NpmPackageVersionConverter {
|
|||
ig.getFhirVersion().add(new Enumeration<>(new FHIRVersionEnumFactory(), version));
|
||||
ig.setPackageId(packageId);
|
||||
}
|
||||
if (res instanceof StructureDefinition) {
|
||||
StructureDefinition sd = (StructureDefinition) res;
|
||||
sd.setFhirVersion(FHIRVersion.fromCode(version));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -45,10 +45,10 @@ public class VSACImporter extends OIDBasedValueSetImporter {
|
|||
|
||||
public static void main(String[] args) throws FHIRException, IOException, ParseException, URISyntaxException {
|
||||
VSACImporter self = new VSACImporter();
|
||||
self.process(args[0], args[1], args[2], "true".equals(args[3]));
|
||||
self.process(args[0], args[1], args[2], "true".equals(args[3]), "true".equals(args[4]));
|
||||
}
|
||||
|
||||
private void process(String source, String dest, String apiKey, boolean onlyNew) throws FHIRException, IOException, URISyntaxException {
|
||||
private void process(String source, String dest, String apiKey, boolean onlyNew, boolean onlyActive) throws FHIRException, IOException, URISyntaxException {
|
||||
CSVReader csv = new CSVReader(ManagedFileAccess.inStream(source));
|
||||
csv.readHeaders();
|
||||
Map<String, String> errs = new HashMap<>();
|
||||
|
@ -75,13 +75,20 @@ public class VSACImporter extends OIDBasedValueSetImporter {
|
|||
|
||||
System.out.println("Loading");
|
||||
List<String> oids = new ArrayList<>();
|
||||
List<String> allOids = new ArrayList<>();
|
||||
while (csv.line()) {
|
||||
String status = csv.cell("Expansion Status");
|
||||
if (!onlyActive || "Active".equals(status)) {
|
||||
String oid = csv.cell("OID");
|
||||
allOids.add(oid);
|
||||
if (!onlyNew || !(ManagedFileAccess.file(Utilities.path(dest, "ValueSet-" + oid + ".json")).exists())) {
|
||||
oids.add(oid);
|
||||
}
|
||||
}
|
||||
}
|
||||
Collections.sort(oids);
|
||||
System.out.println("Cleaning");
|
||||
cleanValueSets(allOids, dest);
|
||||
System.out.println("Go: "+oids.size()+" oids");
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
|
@ -108,6 +115,7 @@ public class VSACImporter extends OIDBasedValueSetImporter {
|
|||
errs.put(oid, e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
OperationOutcome oo = new OperationOutcome();
|
||||
for (String oid : errs.keySet()) {
|
||||
oo.addIssue().setSeverity(IssueSeverity.ERROR).setCode(IssueType.EXCEPTION).setDiagnostics(errs.get(oid)).addLocation(oid);
|
||||
|
@ -116,6 +124,22 @@ public class VSACImporter extends OIDBasedValueSetImporter {
|
|||
System.out.println("Done. " + i + " ValueSets in "+Utilities.describeDuration(System.currentTimeMillis() - tt));
|
||||
}
|
||||
|
||||
private void cleanValueSets(List<String> allOids, String dest) throws IOException {
|
||||
cleanValueSets(allOids, new File(Utilities.path(dest)));
|
||||
}
|
||||
|
||||
private void cleanValueSets(List<String> allOids, File file) {
|
||||
for (File f : file.listFiles()) {
|
||||
if (f.getName().startsWith("ValueSet-")) {
|
||||
String oid = f.getName().substring(9).replace(".json", "");
|
||||
if (!allOids.contains(oid)) {
|
||||
f.delete();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private long estimate(int i, int size, long tt) {
|
||||
long elapsed = System.currentTimeMillis() - tt;
|
||||
long average = elapsed / i;
|
||||
|
@ -201,7 +225,7 @@ public class VSACImporter extends OIDBasedValueSetImporter {
|
|||
}
|
||||
vs.setName(makeValidName(vs.getName()));
|
||||
JurisdictionUtilities.setJurisdictionCountry(vs.getJurisdiction(), "US");
|
||||
new JsonParser().setOutputStyle(OutputStyle.PRETTY).compose(ManagedFileAccess.outStream(Utilities.path(dest, "ValueSet-" + oid + ".json")), vs);
|
||||
new JsonParser().setOutputStyle(OutputStyle.NORMAL).compose(ManagedFileAccess.outStream(Utilities.path(dest, "ValueSet-" + oid + ".json")), vs);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2923,7 +2923,7 @@ public class ProfileUtilities {
|
|||
|
||||
private ElementDefinitionBindingAdditionalComponent getMatchingAdditionalBinding(ElementDefinitionBindingComponent nb,ElementDefinitionBindingAdditionalComponent ab) {
|
||||
for (ElementDefinitionBindingAdditionalComponent t : nb.getAdditional()) {
|
||||
if (t.getValueSet() != null && t.getValueSet().equals(ab.getValueSet()) && t.getPurpose() == ab.getPurpose()) {
|
||||
if (t.getValueSet() != null && t.getValueSet().equals(ab.getValueSet()) && t.getPurpose() == ab.getPurpose() && !ab.hasUsage()) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1471,15 +1471,15 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
|||
}
|
||||
|
||||
protected ValueSetExpander constructValueSetExpanderSimple(ValidationOptions options) {
|
||||
return new ValueSetExpander(this, new TerminologyOperationContext(this, options)).setDebug(logger.isDebugLogging());
|
||||
return new ValueSetExpander(this, new TerminologyOperationContext(this, options, "expansion")).setDebug(logger.isDebugLogging());
|
||||
}
|
||||
|
||||
protected ValueSetValidator constructValueSetCheckerSimple(ValidationOptions options, ValueSet vs, ValidationContextCarrier ctxt) {
|
||||
return new ValueSetValidator(this, new TerminologyOperationContext(this, options), options, vs, ctxt, expParameters, terminologyClientManager);
|
||||
return new ValueSetValidator(this, new TerminologyOperationContext(this, options, "validation"), options, vs, ctxt, expParameters, terminologyClientManager);
|
||||
}
|
||||
|
||||
protected ValueSetValidator constructValueSetCheckerSimple( ValidationOptions options, ValueSet vs) {
|
||||
return new ValueSetValidator(this, new TerminologyOperationContext(this, options), options, vs, expParameters, terminologyClientManager);
|
||||
return new ValueSetValidator(this, new TerminologyOperationContext(this, options, "validation"), options, vs, expParameters, terminologyClientManager);
|
||||
}
|
||||
|
||||
protected Parameters constructParameters(TerminologyClientContext tcd, ValueSet vs, boolean hierarchical) {
|
||||
|
|
|
@ -36,7 +36,7 @@ public class AdditionalBindingsRenderer {
|
|||
private String valueSet;
|
||||
private String doco;
|
||||
private String docoShort;
|
||||
private UsageContext usage;
|
||||
private List<UsageContext> usages = new ArrayList<UsageContext>();
|
||||
private boolean any = false;
|
||||
private boolean isUnchanged = false;
|
||||
private boolean matched = false;
|
||||
|
@ -72,7 +72,7 @@ public class AdditionalBindingsRenderer {
|
|||
isUnchanged = isUnchanged && ((valueSet==null && compare.valueSet==null) || valueSet.equals(compare.valueSet));
|
||||
isUnchanged = isUnchanged && ((doco==null && compare.doco==null) || doco.equals(compare.doco));
|
||||
isUnchanged = isUnchanged && ((docoShort==null && compare.docoShort==null) || docoShort.equals(compare.docoShort));
|
||||
isUnchanged = isUnchanged && ((usage==null && compare.usage==null) || usage.equals(compare.usage));
|
||||
isUnchanged = isUnchanged && ((usages==null && compare.usages==null) || usages.equals(compare.usages));
|
||||
return isUnchanged;
|
||||
}
|
||||
}
|
||||
|
@ -175,7 +175,11 @@ public class AdditionalBindingsRenderer {
|
|||
abr.valueSet = ext.getExtensionString("valueSet");
|
||||
abr.doco = ext.getExtensionString("documentation");
|
||||
abr.docoShort = ext.getExtensionString("shortDoco");
|
||||
abr.usage = (ext.hasExtension("usage")) && ext.getExtensionByUrl("usage").hasValueUsageContext() ? ext.getExtensionByUrl("usage").getValueUsageContext() : null;
|
||||
for (Extension x : ext.getExtensionsByUrl("usage")) {
|
||||
if (x.hasValueUsageContext()) {
|
||||
abr.usages.add(x.getValueUsageContext());
|
||||
}
|
||||
}
|
||||
abr.any = "any".equals(ext.getExtensionString("scope"));
|
||||
abr.isUnchanged = ext.hasUserData(ProfileUtilities.UD_DERIVATION_EQUALS);
|
||||
return abr;
|
||||
|
@ -187,7 +191,7 @@ public class AdditionalBindingsRenderer {
|
|||
abr.valueSet = ab.getValueSet();
|
||||
abr.doco = ab.getDocumentation();
|
||||
abr.docoShort = ab.getShortDoco();
|
||||
abr.usage = ab.hasUsage() ? ab.getUsageFirstRep() : null;
|
||||
abr.usages.addAll(ab.getUsage());
|
||||
abr.any = ab.getAny();
|
||||
abr.isUnchanged = ab.hasUserData(ProfileUtilities.UD_DERIVATION_EQUALS);
|
||||
return abr;
|
||||
|
@ -220,7 +224,7 @@ public class AdditionalBindingsRenderer {
|
|||
boolean any = false;
|
||||
for (AdditionalBindingDetail binding : bindings) {
|
||||
doco = doco || binding.getDoco(fullDoco)!=null || (binding.compare!=null && binding.compare.getDoco(fullDoco)!=null);
|
||||
usage = usage || binding.usage != null || (binding.compare!=null && binding.compare.usage!=null);
|
||||
usage = usage || !binding.usages.isEmpty() || (binding.compare!=null && !binding.compare.usages.isEmpty());
|
||||
any = any || binding.any || (binding.compare!=null && binding.compare.any);
|
||||
}
|
||||
|
||||
|
@ -283,9 +287,12 @@ public class AdditionalBindingsRenderer {
|
|||
renderPurpose(purpose, binding.compare.purpose);
|
||||
}
|
||||
if (usage) {
|
||||
if (binding.usage != null) {
|
||||
// TODO: This isn't rendered at all yet. Ideally, we want it to render with comparison...
|
||||
new DataRenderer(context).renderBase(new RenderingStatus(), tr.td(), binding.usage);
|
||||
if (!binding.usages.isEmpty()) {
|
||||
XhtmlNode td = tr.td();
|
||||
for (UsageContext uc : binding.usages) {
|
||||
td.sep(", ");
|
||||
new DataRenderer(context).renderBase(new RenderingStatus(), td, uc);
|
||||
}
|
||||
} else {
|
||||
tr.td();
|
||||
}
|
||||
|
|
|
@ -1302,6 +1302,10 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
|||
}
|
||||
|
||||
protected void renderCoding(RenderingStatus status, XhtmlNode x, ResourceWrapper c) {
|
||||
renderCoding(status, x, c, true);
|
||||
}
|
||||
|
||||
protected void renderCoding(RenderingStatus status, XhtmlNode x, ResourceWrapper c, boolean details) {
|
||||
String s = "";
|
||||
if (c.has("display"))
|
||||
s = context.getTranslated(c.child("display"));
|
||||
|
@ -1311,11 +1315,14 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
|||
if (Utilities.noString(s))
|
||||
s = c.primitiveValue("code");
|
||||
|
||||
if (context.isTechnicalMode()) {
|
||||
x.addText(s+" "+context.formatPhrase(RenderingContext.DATA_REND_DETAILS_STATED, displaySystem(c.primitiveValue("system")), c.primitiveValue("code"), " = '", lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")), c.primitiveValue("display"), "')"));
|
||||
} else
|
||||
if (context.isTechnicalMode() && details) {
|
||||
String d = c.primitiveValue("display") == null ? lookupCode(c.primitiveValue("system"), c.primitiveValue("version"), c.primitiveValue("code")): c.primitiveValue("display");
|
||||
d = context.formatPhrase(d == null || d.equals(c.primitiveValue("code")) ? RenderingContext.DATA_REND_DETAILS_STATED_ND : RenderingContext.DATA_REND_DETAILS_STATED, displaySystem(c.primitiveValue("system")), c.primitiveValue("code"), d);
|
||||
x.addText(s+" "+d);
|
||||
} else {
|
||||
x.span(null, "{"+c.primitiveValue("system")+" "+c.primitiveValue("code")+"}").addText(s);
|
||||
}
|
||||
}
|
||||
|
||||
public String displayCodeableConcept(ResourceWrapper cc) {
|
||||
String s = context.getTranslated(cc.child("Text"));
|
||||
|
@ -1860,8 +1867,8 @@ public class DataRenderer extends Renderer implements CodeResolver {
|
|||
}
|
||||
|
||||
public void renderUsageContext(RenderingStatus status, XhtmlNode x, ResourceWrapper u) throws FHIRFormatError, DefinitionException, IOException {
|
||||
renderCoding(status, x, u.child("code"));
|
||||
x.tx(": ");
|
||||
renderCoding(status, x, u.child("code"), false);
|
||||
x.tx(" = ");
|
||||
renderDataType(status, x, u.child("value"));
|
||||
}
|
||||
|
||||
|
|
|
@ -42,12 +42,14 @@ public class TerminologyOperationContext {
|
|||
private IWorkerContext worker;
|
||||
private boolean original;
|
||||
private ValidationOptions options;
|
||||
private String name;
|
||||
|
||||
public TerminologyOperationContext(IWorkerContext worker, ValidationOptions options) {
|
||||
public TerminologyOperationContext(IWorkerContext worker, ValidationOptions options, String name) {
|
||||
super();
|
||||
this.worker = worker;
|
||||
this.original = true;
|
||||
this.options = options;
|
||||
this.name = name;
|
||||
|
||||
if (EXPANSION_DEAD_TIME_SECS == 0 || debugging) {
|
||||
deadTime = 0;
|
||||
|
@ -56,13 +58,14 @@ public class TerminologyOperationContext {
|
|||
}
|
||||
}
|
||||
|
||||
private TerminologyOperationContext(ValidationOptions options) {
|
||||
private TerminologyOperationContext(ValidationOptions options, String name) {
|
||||
super();
|
||||
this.options = options;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public TerminologyOperationContext copy() {
|
||||
TerminologyOperationContext ret = new TerminologyOperationContext(this.options);
|
||||
TerminologyOperationContext ret = new TerminologyOperationContext(this.options, name);
|
||||
ret.worker = worker;
|
||||
ret.contexts.addAll(contexts);
|
||||
ret.deadTime = deadTime;
|
||||
|
@ -71,7 +74,7 @@ public class TerminologyOperationContext {
|
|||
|
||||
public void deadCheck() {
|
||||
if (deadTime != 0 && System.currentTimeMillis() > deadTime) {
|
||||
throw new TerminologyServiceProtectionException(worker.formatMessage(I18nConstants.VALUESET_TOO_COSTLY_TIME, contexts.get(0), EXPANSION_DEAD_TIME_SECS), TerminologyServiceErrorClass.TOO_COSTLY, IssueType.TOOCOSTLY);
|
||||
throw new TerminologyServiceProtectionException(worker.formatMessage(I18nConstants.VALUESET_TOO_COSTLY_TIME, contexts.get(0), EXPANSION_DEAD_TIME_SECS, name), TerminologyServiceErrorClass.TOO_COSTLY, IssueType.TOOCOSTLY);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -36,6 +36,10 @@ public class PackageHackerR5 {
|
|||
r.hack("http://terminology.hl7.org/CodeSystem/v2-0360-2.3.1", "2.3.1");
|
||||
}
|
||||
|
||||
if ("http://hl7.org/fhir/ValueSet/languages".equals(r.getUrl())) {
|
||||
r.getResource().setExperimental(false);
|
||||
}
|
||||
|
||||
if ("http://hl7.org/fhir/StructureDefinition/iso21090-nullFlavor".equals(r.getUrl()) && "4.0.1".equals(r.getVersion())) {
|
||||
StructureDefinition sd = (StructureDefinition) r.getResource();
|
||||
for (ElementDefinition ed : sd.getSnapshot().getElement()) {
|
||||
|
|
|
@ -18,7 +18,9 @@ public class I18nConstants {
|
|||
public static final String BAD_FILE_PATH_ERROR = "Bad_file_path_error";
|
||||
public static final String BASE_PROFILE__HAS_NO_TYPE = "Base_profile__has_no_type";
|
||||
public static final String BASE__DERIVED_PROFILES_HAVE_DIFFERENT_TYPES____VS___ = "Base__Derived_profiles_have_different_types____vs___";
|
||||
public static final String BINDING_ADDITIONAL = "BINDING_ADDITIONAL";
|
||||
public static final String BINDING_ADDITIONAL_D = "BINDING_ADDITIONAL_D";
|
||||
public static final String BINDING_ADDITIONAL_UC = "BINDING_ADDITIONAL_UC";
|
||||
public static final String BINDING_ADDITIONAL_USAGE = "BINDING_ADDITIONAL_USAGE";
|
||||
public static final String BINDING_MAX = "BINDING_MAX";
|
||||
public static final String BUNDLE_BUNDLE_ENTRY_CANONICAL = "Bundle_BUNDLE_Entry_Canonical";
|
||||
public static final String BUNDLE_BUNDLE_ENTRY_DOCUMENT = "Bundle_BUNDLE_Entry_Document";
|
||||
|
@ -1111,4 +1113,7 @@ public class I18nConstants {
|
|||
public static final String SD_BASE_EXPERIMENTAL = "SD_BASE_EXPERIMENTAL";
|
||||
public static final String SD_ED_EXPERIMENTAL_BINDING = "SD_ED_EXPERIMENTAL_BINDING";
|
||||
public static final String VALIDATION_NO_EXPERIMENTAL_CONTENT = "VALIDATION_NO_EXPERIMENTAL_CONTENT";
|
||||
public static final String SD_ED_ADDITIONAL_BINDING_USAGE_UNKNOWN = "SD_ED_ADDITIONAL_BINDING_USAGE_UNKNOWN";
|
||||
public static final String SD_ED_ADDITIONAL_BINDING_USAGE_INVALID_ELEMENT = "SD_ED_ADDITIONAL_BINDING_USAGE_INVALID_ELEMENT";
|
||||
public static final String SD_ED_ADDITIONAL_BINDING_USAGE_INVALID_TYPE = "SD_ED_ADDITIONAL_BINDING_USAGE_INVALID_TYPE";
|
||||
}
|
||||
|
|
|
@ -214,6 +214,7 @@ public class RenderingI18nContext extends I18nBase {
|
|||
public static final String DATA_REND_DATA = "DATA_REND_DATA";
|
||||
public static final String DATA_REND_DETAILS = "DATA_REND_DETAILS";
|
||||
public static final String DATA_REND_DETAILS_STATED = "DATA_REND_DETAILS_STATED";
|
||||
public static final String DATA_REND_DETAILS_STATED_ND = "DATA_REND_DETAILS_STATED_ND";
|
||||
public static final String DATA_REND_DICOM = "DATA_REND_DICOM";
|
||||
public static final String DATA_REND_DIM = "DATA_REND_DIM";
|
||||
public static final String DATA_REND_DURATION = "DATA_REND_DURATION";
|
||||
|
|
|
@ -12,6 +12,7 @@ import java.util.Map;
|
|||
|
||||
import org.hl7.fhir.utilities.TextFile;
|
||||
import org.hl7.fhir.utilities.Utilities;
|
||||
import org.hl7.fhir.utilities.VersionUtilities;
|
||||
import org.hl7.fhir.utilities.filesystem.ManagedFileAccess;
|
||||
import org.hl7.fhir.utilities.json.model.JsonArray;
|
||||
import org.hl7.fhir.utilities.json.model.JsonObject;
|
||||
|
@ -43,7 +44,44 @@ public class PackageHacker {
|
|||
// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/6.0.0-ballot2/hl7.fhir.r6.search.tgz");
|
||||
|
||||
// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/us/core/v311/package.tgz", "http://hl7.org/fhir/us/core/STU3.1.1");
|
||||
new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/us/core/v700/package.tgz", "http://hl7.org/fhir/us/core/STU7");
|
||||
// new PackageHacker().edit("/Users/grahamegrieve/web/hl7.org/fhir/us/core/v700/package.tgz", "http://hl7.org/fhir/us/core/STU7");
|
||||
|
||||
PackageHacker self = new PackageHacker();
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/1.0.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/1.0.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/2.0.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/2.0.0/hl7.terminology.r4b.tgz");
|
||||
self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/2.1.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/2.1.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/3.0.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/3.0.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/3.1.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/3.1.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/4.0.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/4.0.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/5.0.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/5.0.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/5.1.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/5.1.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/5.2.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/5.2.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/5.3.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/5.3.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/5.4.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/5.4.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/5.5.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/5.5.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/6.0.0/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/6.0.0/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/6.0.1/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/6.0.1/hl7.terminology.r4b.tgz");
|
||||
// self.cloneToR4B("/Users/grahamegrieve/web/terminology.hl7.org/6.0.2/hl7.terminology.r4.tgz", "/Users/grahamegrieve/web/terminology.hl7.org/6.0.2/hl7.terminology.r4b.tgz");
|
||||
}
|
||||
|
||||
private void cloneToR4B(String src, String dst) throws IOException {
|
||||
FileInputStream fs = ManagedFileAccess.inStream(src);
|
||||
NpmPackage pck = NpmPackage.fromPackage(fs);
|
||||
System.out.println(nice(pck.getNpm()));
|
||||
JsonObject json = pck.getNpm();
|
||||
String name = json.asString("name");
|
||||
json.remove("name");
|
||||
json.add("name", name.replace(".r4", ".r4b"));
|
||||
json.remove("fhirVersions");
|
||||
json.remove("dependencies");
|
||||
JsonArray fv = new JsonArray();
|
||||
json.add("fhirVersions", fv);
|
||||
fv.add("4.3.0");
|
||||
JsonObject dep = new JsonObject();
|
||||
json.add("dependencies", dep);
|
||||
dep.add(VersionUtilities.packageForVersion("4.3.0"), "4.3.0");
|
||||
pck.save(new FileOutputStream(dst));
|
||||
}
|
||||
|
||||
// private void massEdit(File dir) throws IOException {
|
||||
|
|
|
@ -13,7 +13,9 @@ Attempt_to_a_slice_an_element_that_does_not_repeat__from__in_ = Attempt to a sli
|
|||
Attempt_to_replace_element_name_for_a_nonchoice_type=Attempt to replace element name for a non-choice type
|
||||
Attempt_to_use_Terminology_server_when_no_Terminology_server_is_available = Attempt to use Terminology server when no Terminology server is available
|
||||
Attempt_to_use_a_snapshot_on_profile__as__before_it_is_generated = Attempt to use a snapshot on profile ''{0}'' as {1} before it is generated
|
||||
BINDING_ADDITIONAL = {0} specified in an additional binding
|
||||
BINDING_ADDITIONAL_D = {0} specified in an additional binding
|
||||
BINDING_ADDITIONAL_UC = {0} specified in an additional binding which applies because {1}
|
||||
BINDING_ADDITIONAL_USAGE = {0} = {1}
|
||||
BINDING_MAX = {0} specified in the max binding
|
||||
BUNDLE_BUNDLE_ENTRY_FOUND_MULTIPLE = Found {0} matches for ''{1}'' in the bundle ({2})
|
||||
BUNDLE_BUNDLE_ENTRY_FOUND_MULTIPLE_FRAGMENT = Found {0} matches for fragment {2} in resource ''{1}'' in the bundle ({3})
|
||||
|
@ -1029,7 +1031,7 @@ VALUESET_SUPPLEMENT_MISSING_one = Required supplement not found: {1}
|
|||
VALUESET_SUPPLEMENT_MISSING_other = Required supplements not found: {1}
|
||||
VALUESET_TOO_COSTLY = The value set ''{0}'' expansion has too many codes to display ({1})
|
||||
VALUESET_TOO_COSTLY_COUNT = The value set ''{0}'' expansion has {2} codes, which is too many to display ({1})
|
||||
VALUESET_TOO_COSTLY_TIME = The value set ''{0}'' expansion took too long to process (>{1}sec)
|
||||
VALUESET_TOO_COSTLY_TIME = The value set ''{0}'' {2} took too long to process (>{1}sec)
|
||||
VALUESET_UNC_SYSTEM_WARNING = Unknown System ''{0}'' specified, so Concepts and Filters can''t be checked (Details: {1})
|
||||
VALUESET_UNC_SYSTEM_WARNING_VER = Unknown System/Version ''{0}'' specified, so Concepts and Filters can''t be checked (Details: {1})
|
||||
VALUESET_UNKNOWN_FILTER_PROPERTY = The property ''{0}'' is not known for the system ''{1}'', so may not be understood by the terminology ecosystem. Known properties for this system: {2}
|
||||
|
@ -1143,3 +1145,6 @@ NO_VALID_DISPLAY_AT_ALL = Cannot validate display Name ''{0}'' for {1}#{2}: No d
|
|||
SD_BASE_EXPERIMENTAL = The definition builds on ''{0}'' which is experimental, but this definition is not labeled as experimental
|
||||
SD_ED_EXPERIMENTAL_BINDING = The definition for the element ''{0}'' binds to the value set ''{1}'' which is experimental, but this structure is not labeled as experimental
|
||||
VALIDATION_NO_EXPERIMENTAL_CONTENT = Experimental content is not allowed in this context
|
||||
SD_ED_ADDITIONAL_BINDING_USAGE_UNKNOWN = The Usage Context {0}#{1} is not recognised and may not be correct
|
||||
SD_ED_ADDITIONAL_BINDING_USAGE_INVALID_ELEMENT = The Usage Context {0}#{1} is a reference to an element that does not exist
|
||||
SD_ED_ADDITIONAL_BINDING_USAGE_INVALID_TYPE = The Usage Context value must be of type {1} not {0}
|
||||
|
|
|
@ -207,7 +207,8 @@ DATA_REND_COND = Condition
|
|||
DATA_REND_COUNT = Count {0}
|
||||
DATA_REND_DATA = Data: {0}
|
||||
DATA_REND_DETAILS = (Details: {0} code
|
||||
DATA_REND_DETAILS_STATED = (Details: {0} code {1} {2} {3} '', stated as '' {4} {5}
|
||||
DATA_REND_DETAILS_STATED = (Details: {0} code {1} = ''{2}'')
|
||||
DATA_REND_DETAILS_STATED_ND = (Details: {0} code {1})
|
||||
DATA_REND_DICOM = DICOM
|
||||
DATA_REND_DIM = Dimensions: {0}
|
||||
DATA_REND_DURATION = Duration {0}
|
||||
|
|
|
@ -1192,6 +1192,34 @@ public class BaseValidator implements IValidationContextResourceLoader, IMessagi
|
|||
}
|
||||
|
||||
|
||||
protected int countFragmentMatches(Element element, String fragment, NodeStack stack) {
|
||||
int count = countFragmentMatches(element, fragment);
|
||||
if (count == 0 && element.isResource() && element.hasParentForValidator()) {
|
||||
Element bnd = getElementBundle(element);
|
||||
if (bnd != null) {
|
||||
// in this case, we look into the parent - if there is one - and if it's a bundle, we look at the entries (but not in them)
|
||||
for (Element be : bnd.getChildrenByName("entry")) {
|
||||
String id = be.getIdBase();
|
||||
if (fragment.equals(id)) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
private Element getElementBundle(Element element) {
|
||||
Element p = element.getParentForValidator();
|
||||
if (p != null) {
|
||||
Element b = p.getParentForValidator();
|
||||
if (b != null && b.fhirType().equals("Bundle")) {
|
||||
return b;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected int countFragmentMatches(Element element, String fragment) {
|
||||
int count = 0;
|
||||
if (fragment.equals(element.getIdBase())) {
|
||||
|
|
|
@ -217,6 +217,7 @@ import org.hl7.fhir.validation.instance.type.ValueSetValidator;
|
|||
import org.hl7.fhir.validation.instance.utils.*;
|
||||
import org.w3c.dom.Document;
|
||||
|
||||
|
||||
/**
|
||||
* Thinking of using this in a java program? Don't!
|
||||
* You should use one of the wrappers instead. Either in HAPI, or use ValidationEngine
|
||||
|
@ -1356,19 +1357,20 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
BindingStrength strength = binding.getStrength();
|
||||
Extension maxVS = binding.getExtensionByUrl(ToolingExtensions.EXT_MAX_VALUESET);
|
||||
|
||||
checkDisp = validateBindingCodeableConcept(errors, path, element, profile, stack, bh, checkDisp, checked, cc, vsRef, valueset, strength, maxVS, true);
|
||||
checkDisp = validateBindingCodeableConcept(errors, path, element, profile, stack, bh, checkDisp, checked, cc, vsRef, valueset, strength, maxVS, true, null);
|
||||
// } else if (binding.hasValueSet()) {
|
||||
// hint(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_BINDING_CANTCHECK);
|
||||
} else if (!noBindingMsgSuppressed) {
|
||||
hint(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_BINDING_NOSOURCE, path);
|
||||
}
|
||||
for (ElementDefinitionBindingAdditionalComponent ab : binding.getAdditional()) {
|
||||
if (isTestableBinding(ab) && isInScope(ab)) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (isTestableBinding(ab) && isInScope(ab, profile, getResource(stack), b)) {
|
||||
String vsRef = ab.getValueSet();
|
||||
ValueSet valueset = resolveBindingReference(profile, vsRef, profile.getUrl(), profile);
|
||||
BindingStrength strength = convertPurposeToStrength(ab.getPurpose());
|
||||
|
||||
checkDisp = validateBindingCodeableConcept(errors, path, element, profile, stack, bh, checkDisp, checked, cc, vsRef, valueset, strength, null, false) && checkDisp;
|
||||
checkDisp = validateBindingCodeableConcept(errors, path, element, profile, stack, bh, checkDisp, checked, cc, vsRef, valueset, strength, null, false, b.toString()) && checkDisp;
|
||||
}
|
||||
}
|
||||
} catch (CheckCodeOnServerException e) {
|
||||
|
@ -1394,25 +1396,186 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return checkDisp;
|
||||
}
|
||||
|
||||
private boolean isInScope(ElementDefinitionBindingAdditionalComponent ab) {
|
||||
private boolean isInScope(ElementDefinitionBindingAdditionalComponent ab, StructureDefinition profile, Element resource, StringBuilder b) {
|
||||
if (ab.getUsage().isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
boolean ok = true;
|
||||
for (UsageContext usage : ab.getUsage()) {
|
||||
if (isInScope(usage)) {
|
||||
if (!isInScope(usage, profile, resource, b)) {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
private boolean isInScope(UsageContext usage, StructureDefinition profile, Element resource, StringBuilder b) {
|
||||
if (isKnownUsage(usage)) {
|
||||
return true;
|
||||
}
|
||||
if (usage.getCode().hasSystem() && (usage.getCode().getSystem().equals(profile.getUrl()) || usage.getCode().getSystem().equals(profile.getVersionedUrl()))) {
|
||||
// if it's not a defined usage from external sources, it might match something in the data content
|
||||
List<Element> items = findDataValue(resource, usage.getCode().getCode());
|
||||
if (matchesUsage(items, usage.getValue())) {
|
||||
b.append(context.formatMessage(I18nConstants.BINDING_ADDITIONAL_USAGE, displayCoding(usage.getCode()), display(usage.getValue())));
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return ab.getUsage().isEmpty();
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isInScope(UsageContext usage) {
|
||||
if (isKnownUsage(usage)) {
|
||||
private String displayCoding(Coding value) {
|
||||
return value.getCode();
|
||||
}
|
||||
|
||||
private String displayCodeableConcept(CodeableConcept value) {
|
||||
for (Coding c : value.getCoding()) {
|
||||
String s = displayCoding(c);
|
||||
if (s != null) {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
return value.getText();
|
||||
}
|
||||
|
||||
private String display(DataType value) {
|
||||
switch (value.fhirType()) {
|
||||
case "Coding" : return displayCoding((Coding) value);
|
||||
case "CodeableConcept" : return displayCodeableConcept((CodeableConcept) value);
|
||||
}
|
||||
return value.fhirType();
|
||||
}
|
||||
|
||||
private boolean matchesUsage(List<Element> items, DataType value) {
|
||||
for (Element item : items) {
|
||||
if (matchesUsage(item, value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
private String display(List<Element> items) {
|
||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||
for (Element item : items) {
|
||||
display(b, item);
|
||||
}
|
||||
return b.toString();
|
||||
}
|
||||
|
||||
private void display(CommaSeparatedStringBuilder b, Element item) {
|
||||
if (item.isPrimitive()) {
|
||||
b.append(item.primitiveValue());
|
||||
} else if (item.fhirType().equals("CodeableConcept")) {
|
||||
for (Element c : item.getChildren("coding")) {
|
||||
b.append(c.getNamedChildValue("code"));
|
||||
}
|
||||
} else {
|
||||
b.append(item.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private boolean matchesUsage(Element item, DataType value) {
|
||||
switch (value.fhirType()) {
|
||||
case "CodeableConcept": return matchesUsageCodeableConcept(item, (CodeableConcept) value);
|
||||
case "Quantity": return false;
|
||||
case "Range": return false;
|
||||
case "Reference": return false;
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean matchesUsageCodeableConcept(Element item, CodeableConcept value) {
|
||||
switch (item.fhirType()) {
|
||||
case "CodeableConcept": return matchesUsageCodeableConceptCodeableConcept(item, value);
|
||||
case "Coding": return matchesUsageCodeableConceptCoding(item, value);
|
||||
default: return false;
|
||||
}
|
||||
}
|
||||
|
||||
private boolean matchesUsageCodeableConceptCoding(Element item, CodeableConcept value) {
|
||||
String system = item.getNamedChildValue("system");
|
||||
String version = item.getNamedChildValue("version");
|
||||
String code = item.getNamedChildValue("code");
|
||||
for (Coding c : value.getCoding()) {
|
||||
if (system == null || !system.equals(c.getSystem())) {
|
||||
return false;
|
||||
}
|
||||
if (code == null || !code.equals(c.getCode())) {
|
||||
return false;
|
||||
}
|
||||
if (c.hasVersion()) {
|
||||
if (version == null || !version.equals(c.getVersion())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean matchesUsageCodeableConceptCodeableConcept(Element item, CodeableConcept value) {
|
||||
for (Element code : item.getChildren("coding")) {
|
||||
if (matchesUsageCodeableConceptCoding(code, value)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private List<Element> findDataValue(Element resource, String code) {
|
||||
List<Element> items = new ArrayList<Element>();
|
||||
if (resource != null) {
|
||||
findDataValues(items, resource, code);
|
||||
}
|
||||
return items;
|
||||
}
|
||||
|
||||
private void findDataValues(List<Element> items, Element element, String path) {
|
||||
if (element.getPath() == null) {
|
||||
return;
|
||||
}
|
||||
if (pathMatches(element.getPath(), path)) {
|
||||
items.add(element);
|
||||
} else if (element.hasChildren() && path.startsWith(element.getPath())) {
|
||||
for (Element child : element.getChildren()) {
|
||||
findDataValues(items, child, path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean pathMatches(String actualPath, String pathSpec) {
|
||||
String[] ap = actualPath.split("\\.");
|
||||
String[] ps = pathSpec.split("\\.");
|
||||
if (ap.length != ps.length) {
|
||||
return false;
|
||||
}
|
||||
for (int i = 0; i < ap.length; i++) {
|
||||
if (!pathSegmentMatches(ap[i], ps[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean pathSegmentMatches(String ap, String ps) {
|
||||
if (ps.contains("[")) {
|
||||
return ap.equals(ps);
|
||||
} else {
|
||||
if (ap.contains("[")) {
|
||||
ap = ap.substring(0, ap.indexOf("["));
|
||||
}
|
||||
return ap.equals(ps);
|
||||
}
|
||||
}
|
||||
|
||||
private BindingStrength convertPurposeToStrength(AdditionalBindingPurposeVS purpose) {
|
||||
switch (purpose) {
|
||||
case MAXIMUM: return BindingStrength.REQUIRED;
|
||||
case EXTENSIBLE: return BindingStrength.EXTENSIBLE;
|
||||
case PREFERRED: return BindingStrength.PREFERRED;
|
||||
case REQUIRED: return BindingStrength.REQUIRED;
|
||||
default: return null;
|
||||
|
@ -1424,7 +1587,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
|
||||
private boolean validateBindingCodeableConcept(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, NodeStack stack, BooleanHolder bh, boolean checkDisp, BooleanHolder checked,
|
||||
CodeableConcept cc, String vsRef, ValueSet valueset, BindingStrength strength, Extension maxVS, boolean base) throws CheckCodeOnServerException {
|
||||
CodeableConcept cc, String vsRef, ValueSet valueset, BindingStrength strength, Extension maxVS, boolean base, String usageNote) throws CheckCodeOnServerException {
|
||||
if (valueset == null) {
|
||||
CodeSystem cs = context.fetchCodeSystem(vsRef);
|
||||
if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(vsRef))) {
|
||||
|
@ -1436,12 +1599,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
BindingContext bc = base ? BindingContext.BASE : BindingContext.ADDITIONAL;
|
||||
if (!cc.hasCoding()) {
|
||||
if (strength == BindingStrength.REQUIRED)
|
||||
bh.see(rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CODE_VALUESET, describeReference(vsRef, valueset, bc)));
|
||||
bh.see(rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CODE_VALUESET, describeReference(vsRef, valueset, bc, usageNote)));
|
||||
else if (strength == BindingStrength.EXTENSIBLE) {
|
||||
if (maxVS != null)
|
||||
bh.see(rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CODE_VALUESETMAX, describeReference(ToolingExtensions.readStringFromExtension(maxVS)), valueset.getVersionedUrl()));
|
||||
else if (!noExtensibleWarnings) {
|
||||
warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CODE_VALUESET_EXT, describeReference(vsRef, valueset, bc));
|
||||
warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CODE_VALUESET_EXT, describeReference(vsRef, valueset, bc, usageNote));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@ -1493,15 +1656,15 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
// we've already handled the warnings / errors about this, and set the status correctly. We don't need to do anything more?
|
||||
} else {
|
||||
if (strength == BindingStrength.REQUIRED) {
|
||||
bh.see(txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_1_CC, describeReference(vsRef, valueset, bc), ccSummary(cc)));
|
||||
bh.see(txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_1_CC, describeReference(vsRef, valueset, bc, usageNote), ccSummary(cc)));
|
||||
} else if (strength == BindingStrength.EXTENSIBLE) {
|
||||
if (maxVS != null)
|
||||
bh.see(checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringFromExtension(maxVS), cc, stack));
|
||||
if (!noExtensibleWarnings)
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_2_CC, describeReference(vsRef, valueset, bc), ccSummary(cc));
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_2_CC, describeReference(vsRef, valueset, bc, usageNote), ccSummary(cc));
|
||||
} else if (strength == BindingStrength.PREFERRED) {
|
||||
if (baseOnly) {
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_3_CC, describeReference(vsRef, valueset, bc), ccSummary(cc));
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_3_CC, describeReference(vsRef, valueset, bc, usageNote), ccSummary(cc));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1648,7 +1811,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
BindingStrength strength = binding.getStrength();
|
||||
Extension vsMax = binding.getExtensionByUrl(ToolingExtensions.EXT_MAX_VALUESET);
|
||||
|
||||
validateBindingCodeableConcept(errors, path, element, profile, stack, ok, false, new BooleanHolder(), cc, vsRef, valueset, strength, vsMax, true);
|
||||
validateBindingCodeableConcept(errors, path, element, profile, stack, ok, false, new BooleanHolder(), cc, vsRef, valueset, strength, vsMax, true, null);
|
||||
|
||||
// special case: if the logical model has both CodeableConcept and Coding mappings, we'll also check the first coding.
|
||||
if (getMapping("http://hl7.org/fhir/terminology-pattern", logical, logical.getSnapshot().getElementFirstRep()).contains("Coding")) {
|
||||
|
@ -1660,11 +1823,12 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
hint(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_BINDING_NOSOURCE, path);
|
||||
}
|
||||
for (ElementDefinitionBindingAdditionalComponent ab : binding.getAdditional()) {
|
||||
if (isTestableBinding(ab) && isInScope(ab)) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (isTestableBinding(ab) && isInScope(ab, profile, getResource(stack), b)) {
|
||||
String vsRef = ab.getValueSet();
|
||||
ValueSet valueset = resolveBindingReference(profile, vsRef, profile.getUrl(), profile);
|
||||
BindingStrength strength = convertPurposeToStrength(ab.getPurpose());
|
||||
validateBindingCodeableConcept(errors, path, element, profile, stack, ok, false, new BooleanHolder(), cc, vsRef, valueset, strength, null, false);
|
||||
validateBindingCodeableConcept(errors, path, element, profile, stack, ok, false, new BooleanHolder(), cc, vsRef, valueset, strength, null, false, b.toString());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1698,18 +1862,19 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
BindingStrength strength = binding.getStrength();
|
||||
Extension vsMax = binding.getExtensionByUrl(ToolingExtensions.EXT_MAX_VALUESET);
|
||||
|
||||
ok = validateBindingTerminologyCoding(errors, path, element, profile, stack, ok, c, code, system, display, vsRef, valueset, strength, vsMax, true);
|
||||
ok = validateBindingTerminologyCoding(errors, path, element, profile, stack, ok, c, code, system, display, vsRef, valueset, strength, vsMax, true, null);
|
||||
} else if (binding.hasValueSet()) {
|
||||
hint(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_BINDING_CANTCHECK);
|
||||
} else if (!inCodeableConcept && !noBindingMsgSuppressed) {
|
||||
hint(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_BINDING_NOSOURCE, path);
|
||||
}
|
||||
for (ElementDefinitionBindingAdditionalComponent ab : binding.getAdditional()) {
|
||||
if (isTestableBinding(ab) && isInScope(ab)) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (isTestableBinding(ab) && isInScope(ab, profile, getResource(stack), b)) {
|
||||
String vsRef = ab.getValueSet();
|
||||
ValueSet valueset = resolveBindingReference(profile, vsRef, profile.getUrl(), profile);
|
||||
BindingStrength strength = convertPurposeToStrength(ab.getPurpose());
|
||||
ok = validateBindingTerminologyCoding(errors, path, element, profile, stack, ok, c, code, system, display, vsRef, valueset, strength, null, true) && ok;
|
||||
ok = validateBindingTerminologyCoding(errors, path, element, profile, stack, ok, c, code, system, display, vsRef, valueset, strength, null, true, b.toString()) && ok;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1728,7 +1893,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
|
||||
private boolean validateBindingTerminologyCoding(List<ValidationMessage> errors, String path, Element element,
|
||||
StructureDefinition profile, NodeStack stack, boolean ok, Coding c, String code, String system, String display,
|
||||
String vsRef, ValueSet valueset, BindingStrength strength, Extension vsMax, boolean base) {
|
||||
String vsRef, ValueSet valueset, BindingStrength strength, Extension vsMax, boolean base, String usageNote) {
|
||||
if (valueset == null) {
|
||||
CodeSystem cs = context.fetchCodeSystem(vsRef);
|
||||
if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(vsRef))) {
|
||||
|
@ -1754,27 +1919,27 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_BINDING_NOSERVER, system+"#"+code);
|
||||
else if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure()) {
|
||||
if (strength == BindingStrength.REQUIRED)
|
||||
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_4a, describeReference(vsRef, valueset, bc), vr.getMessage(), system+"#"+code);
|
||||
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_4a, describeReference(vsRef, valueset, bc, usageNote), vr.getMessage(), system+"#"+code);
|
||||
else if (strength == BindingStrength.EXTENSIBLE) {
|
||||
if (vsMax != null)
|
||||
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringFromExtension(vsMax), c, stack);
|
||||
else if (!noExtensibleWarnings)
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_5, describeReference(vsRef, valueset, bc));
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_5, describeReference(vsRef, valueset, bc, usageNote));
|
||||
} else if (strength == BindingStrength.PREFERRED) {
|
||||
if (baseOnly) {
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_6, describeReference(vsRef, valueset, bc));
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_6, describeReference(vsRef, valueset, bc, usageNote));
|
||||
}
|
||||
}
|
||||
} else if (strength == BindingStrength.REQUIRED)
|
||||
ok= txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_4, describeReference(vsRef, valueset, bc), (vr.getMessage() != null ? " (error message = " + vr.getMessage() + ")" : ""), system+"#"+code) && ok;
|
||||
ok= txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_4, describeReference(vsRef, valueset, bc, usageNote), (vr.getMessage() != null ? " (error message = " + vr.getMessage() + ")" : ""), system+"#"+code) && ok;
|
||||
else if (strength == BindingStrength.EXTENSIBLE) {
|
||||
if (vsMax != null)
|
||||
ok = checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringFromExtension(vsMax), c, stack) && ok;
|
||||
else
|
||||
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_5, describeReference(vsRef, valueset, bc), (vr.getMessage() != null ? " (error message = " + vr.getMessage() + ")" : ""), system+"#"+code);
|
||||
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_5, describeReference(vsRef, valueset, bc, usageNote), (vr.getMessage() != null ? " (error message = " + vr.getMessage() + ")" : ""), system+"#"+code);
|
||||
} else if (strength == BindingStrength.PREFERRED) {
|
||||
if (baseOnly) {
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_6, describeReference(vsRef, valueset, bc), (vr.getMessage() != null ? " (error message = " + vr.getMessage() + ")" : ""), system+"#"+code);
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_6, describeReference(vsRef, valueset, bc, usageNote), (vr.getMessage() != null ? " (error message = " + vr.getMessage() + ")" : ""), system+"#"+code);
|
||||
}
|
||||
}
|
||||
} else if (vr != null && vr.getMessage() != null){
|
||||
|
@ -1896,9 +2061,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
timeTracker.tx(t, "vc "+cc.toString());
|
||||
if (!vr.isOk()) {
|
||||
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure())
|
||||
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_7, describeReference(maxVSUrl, valueset, BindingContext.MAXVS), vr.getMessage());
|
||||
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_7, describeReference(maxVSUrl, valueset, BindingContext.MAXVS, null), vr.getMessage());
|
||||
else
|
||||
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_8, describeReference(maxVSUrl, valueset, BindingContext.MAXVS), ccSummary(cc)) && ok;
|
||||
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_8, describeReference(maxVSUrl, valueset, BindingContext.MAXVS, null), ccSummary(cc)) && ok;
|
||||
}
|
||||
} catch (CheckCodeOnServerException e) {
|
||||
if (STACK_TRACE) e.getCause().printStackTrace();
|
||||
|
@ -1936,9 +2101,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
timeTracker.tx(t, "vc "+c.getSystem()+"#"+c.getCode()+" '"+c.getDisplay()+"'");
|
||||
if (!vr.isOk()) {
|
||||
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure())
|
||||
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_9, describeReference(maxVSUrl, valueset, BindingContext.MAXVS), vr.getMessage(), c.getSystem()+"#"+c.getCode());
|
||||
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_9, describeReference(maxVSUrl, valueset, BindingContext.MAXVS, null), vr.getMessage(), c.getSystem()+"#"+c.getCode());
|
||||
else
|
||||
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_10, describeReference(maxVSUrl, valueset, BindingContext.MAXVS), c.getSystem(), c.getCode()) && ok;
|
||||
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_10, describeReference(maxVSUrl, valueset, BindingContext.MAXVS, null), c.getSystem(), c.getCode()) && ok;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (STACK_TRACE) e.printStackTrace();
|
||||
|
@ -1966,9 +2131,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
timeTracker.tx(t, "vc "+value);
|
||||
if (!vr.isOk()) {
|
||||
if (vr.getErrorClass() != null && vr.getErrorClass().isInfrastructure())
|
||||
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_9, describeReference(maxVSUrl, valueset, BindingContext.BASE), vr.getMessage(), value);
|
||||
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_9, describeReference(maxVSUrl, valueset, BindingContext.BASE, null), vr.getMessage(), value);
|
||||
else {
|
||||
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_11, describeReference(maxVSUrl, valueset, BindingContext.BASE), vr.getMessage()) && ok;
|
||||
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_11, describeReference(maxVSUrl, valueset, BindingContext.BASE, null), vr.getMessage()) && ok;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -2029,7 +2194,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
BindingStrength strength = binding.getStrength();
|
||||
Extension vsMax = binding.getExtensionByUrl(ToolingExtensions.EXT_MAX_VALUESET);
|
||||
|
||||
ok = validateBindingCodedElement(errors, path, element, profile, stack, theCode, theSystem, ok, checked, c, vsRef, valueset, strength, vsMax, true);
|
||||
ok = validateBindingCodedElement(errors, path, element, profile, stack, theCode, theSystem, ok, checked, c, vsRef, valueset, strength, vsMax, true, null);
|
||||
// } else if (binding.hasValueSet()) {
|
||||
// hint(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_BINDING_CANTCHECK);
|
||||
|
||||
|
@ -2038,12 +2203,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
|
||||
for (ElementDefinitionBindingAdditionalComponent ab : binding.getAdditional()) {
|
||||
if (isTestableBinding(ab) && isInScope(ab)) {
|
||||
StringBuilder b = new StringBuilder();
|
||||
if (isTestableBinding(ab) && isInScope(ab, profile, getResource(stack), b)) {
|
||||
String vsRef = ab.getValueSet();
|
||||
ValueSet valueset = resolveBindingReference(profile, vsRef, profile.getUrl(), profile);
|
||||
BindingStrength strength = convertPurposeToStrength(ab.getPurpose());
|
||||
|
||||
ok = validateBindingCodedElement(errors, path, element, profile, stack, theCode, theSystem, ok, checked, c, vsRef, valueset, strength, null, false) && ok;
|
||||
ok = validateBindingCodedElement(errors, path, element, profile, stack, theCode, theSystem, ok, checked, c, vsRef, valueset, strength, null, false, b.toString()) && ok;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
|
@ -2068,9 +2234,19 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return ok;
|
||||
}
|
||||
|
||||
private Element getResource(NodeStack stack) {
|
||||
if (stack.getElement().isResource()) {
|
||||
return stack.getElement();
|
||||
}
|
||||
if (stack.getParent() == null) {
|
||||
return null;
|
||||
}
|
||||
return getResource(stack.getParent());
|
||||
}
|
||||
|
||||
private boolean validateBindingCodedElement(List<ValidationMessage> errors, String path, Element element,
|
||||
StructureDefinition profile, NodeStack stack, String theCode, String theSystem, boolean ok, BooleanHolder checked,
|
||||
Coding c, String vsRef, ValueSet valueset, BindingStrength strength, Extension vsMax, boolean base) {
|
||||
Coding c, String vsRef, ValueSet valueset, BindingStrength strength, Extension vsMax, boolean base, String usageNote) {
|
||||
if (valueset == null) {
|
||||
CodeSystem cs = context.fetchCodeSystem(vsRef);
|
||||
if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(vsRef))) {
|
||||
|
@ -2098,28 +2274,28 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_BINDING_NOSERVER, theSystem+"#"+theCode);
|
||||
else if (vr.getErrorClass() != null && !vr.getErrorClass().isInfrastructure()) {
|
||||
if (strength == BindingStrength.REQUIRED)
|
||||
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_4a, describeReference(vsRef, valueset, bc), vr.getMessage(), theSystem+"#"+theCode) && ok;
|
||||
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_4a, describeReference(vsRef, valueset, bc, usageNote), vr.getMessage(), theSystem+"#"+theCode) && ok;
|
||||
else if (strength == BindingStrength.EXTENSIBLE) {
|
||||
if (vsMax != null)
|
||||
checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringFromExtension(vsMax), c, stack);
|
||||
else if (!noExtensibleWarnings)
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_5, describeReference(vsRef, valueset, bc), theSystem+"#"+theCode);
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_5, describeReference(vsRef, valueset, bc, usageNote), theSystem+"#"+theCode);
|
||||
} else if (strength == BindingStrength.PREFERRED) {
|
||||
if (baseOnly) {
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_6, describeReference(vsRef, valueset, bc), theSystem+"#"+theCode);
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_CONFIRM_6, describeReference(vsRef, valueset, bc, usageNote), theSystem+"#"+theCode);
|
||||
}
|
||||
}
|
||||
} else if (strength == BindingStrength.REQUIRED)
|
||||
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_12, describeReference(vsRef, valueset, bc), getErrorMessage(vr.getMessage()), theSystem+"#"+theCode) && ok;
|
||||
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_12, describeReference(vsRef, valueset, bc, usageNote), getErrorMessage(vr.getMessage()), theSystem+"#"+theCode) && ok;
|
||||
else if (strength == BindingStrength.EXTENSIBLE) {
|
||||
if (vsMax != null)
|
||||
ok = checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringFromExtension(vsMax), c, stack) && ok;
|
||||
else if (!noExtensibleWarnings) {
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_13, describeReference(vsRef, valueset, bc), getErrorMessage(vr.getMessage()), c.getSystem()+"#"+c.getCode());
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_13, describeReference(vsRef, valueset, bc, usageNote), getErrorMessage(vr.getMessage()), c.getSystem()+"#"+c.getCode());
|
||||
}
|
||||
} else if (strength == BindingStrength.PREFERRED) {
|
||||
if (baseOnly) {
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_14, describeReference(vsRef, valueset, bc), getErrorMessage(vr.getMessage()), theSystem+"#"+theCode);
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_14, describeReference(vsRef, valueset, bc, usageNote), getErrorMessage(vr.getMessage()), theSystem+"#"+theCode);
|
||||
}
|
||||
}
|
||||
} else if (vr != null && vr.getMessage() != null) {
|
||||
|
@ -3017,7 +3193,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
// check that no illegal elements and attributes have been used
|
||||
ok = checkInnerNames(errors, e, path, xhtml.getChildNodes(), false) && ok;
|
||||
ok = checkUrls(errors, e, path, xhtml.getChildNodes()) && ok;
|
||||
ok = checkIdRefs(errors, e, path, xhtml, resource) && ok;
|
||||
ok = checkIdRefs(errors, e, path, xhtml, resource, node) && ok;
|
||||
if (true) {
|
||||
ok = checkReferences(valContext, errors, e, path, "div", xhtml, resource) && ok;
|
||||
}
|
||||
|
@ -3466,11 +3642,11 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return ok;
|
||||
}
|
||||
|
||||
private boolean checkIdRefs(List<ValidationMessage> errors, Element e, String path, XhtmlNode node, Element resource) {
|
||||
private boolean checkIdRefs(List<ValidationMessage> errors, Element e, String path, XhtmlNode node, Element resource, NodeStack stack) {
|
||||
boolean ok = true;
|
||||
if (node.getNodeType() == NodeType.Element && node.getAttribute("idref") != null) {
|
||||
String idref = node.getAttribute("idref");
|
||||
int count = countFragmentMatches(resource, idref);
|
||||
int count = countFragmentMatches(resource, idref, stack);
|
||||
if (count == 0) {
|
||||
ok = warning(errors, "2023-12-01", IssueType.INVALID, e.line(), e.col(), path, idref == null, I18nConstants.XHTML_IDREF_NOT_FOUND, idref) && ok;
|
||||
} else if (count > 1) {
|
||||
|
@ -3479,7 +3655,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
if (node.hasChildren()) {
|
||||
for (XhtmlNode child : node.getChildNodes()) {
|
||||
checkIdRefs(errors, e, path, child, resource);
|
||||
checkIdRefs(errors, e, path, child, resource, stack);
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
|
@ -3563,15 +3739,15 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
} else if (vr.getErrorClass() != null && vr.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) {
|
||||
txWarning(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, vr.getMessage());
|
||||
} else if (binding.getStrength() == BindingStrength.REQUIRED) {
|
||||
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_16, value, describeReference(binding.getValueSet(), vs, BindingContext.BASE), getErrorMessage(vr.getMessage())) && ok;
|
||||
ok = txRule(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_16, value, describeReference(binding.getValueSet(), vs, BindingContext.BASE, null), getErrorMessage(vr.getMessage())) && ok;
|
||||
} else if (binding.getStrength() == BindingStrength.EXTENSIBLE) {
|
||||
if (binding.hasExtension(ToolingExtensions.EXT_MAX_VALUESET))
|
||||
ok = checkMaxValueSet(errors, path, element, profile, ToolingExtensions.readStringExtension(binding, ToolingExtensions.EXT_MAX_VALUESET), value, stack) && ok;
|
||||
else if (!noExtensibleWarnings && !isOkExtension(value, vs))
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_17, value, describeReference(binding.getValueSet(), vs, BindingContext.BASE), getErrorMessage(vr.getMessage()));
|
||||
txWarningForLaterRemoval(element, errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_17, value, describeReference(binding.getValueSet(), vs, BindingContext.BASE, null), getErrorMessage(vr.getMessage()));
|
||||
} else if (binding.getStrength() == BindingStrength.PREFERRED) {
|
||||
if (baseOnly) {
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_18, value, describeReference(binding.getValueSet(), vs, BindingContext.BASE), getErrorMessage(vr.getMessage()));
|
||||
txHint(errors, NO_RULE_DATE, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_NOVALID_18, value, describeReference(binding.getValueSet(), vs, BindingContext.BASE, null), getErrorMessage(vr.getMessage()));
|
||||
}
|
||||
}
|
||||
} else if (vr != null && vr.getMessage() != null){
|
||||
|
@ -4279,7 +4455,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
return false;
|
||||
}
|
||||
|
||||
private String describeReference(String reference, CanonicalResource target, BindingContext ctxt) {
|
||||
private String describeReference(String reference, CanonicalResource target, BindingContext ctxt, String usageNote) {
|
||||
if (reference == null && target == null)
|
||||
return "null";
|
||||
String res = null;
|
||||
|
@ -4297,7 +4473,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
}
|
||||
switch (ctxt) {
|
||||
case ADDITIONAL: return context.formatMessage(I18nConstants.BINDING_ADDITIONAL, res);
|
||||
case ADDITIONAL: return context.formatMessage(Utilities.noString(usageNote) ? I18nConstants.BINDING_ADDITIONAL_D : I18nConstants.BINDING_ADDITIONAL_UC, res, usageNote);
|
||||
case MAXVS: return context.formatMessage(I18nConstants.BINDING_MAX, res);
|
||||
default: return res;
|
||||
}
|
||||
|
@ -5891,6 +6067,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
Element div = text.getNamedChild("div", false);
|
||||
if (lang != null && div != null) {
|
||||
XhtmlNode xhtml = div.getXhtml();
|
||||
if (xhtml != null) {
|
||||
String l = xhtml.getAttribute("lang");
|
||||
String xl = xhtml.getAttribute("xml:lang");
|
||||
if (l == null && xl == null) {
|
||||
|
@ -5909,6 +6086,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// security tags are a set (system|code)
|
||||
Element meta = element.getNamedChild(META, false);
|
||||
if (meta != null) {
|
||||
|
@ -7439,6 +7617,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
}
|
||||
|
||||
|
||||
public long timeNoTX() {
|
||||
return (timeTracker.getOverall() - timeTracker.getTxTime()) / 1000000;
|
||||
}
|
||||
public String reportTimes() {
|
||||
String s = String.format("Times (ms): overall = %d:4, tx = %d, sd = %d, load = %d, fpe = %d, spec = %d", timeTracker.getOverall() / 1000000, timeTracker.getTxTime() / 1000000, timeTracker.getSdTime() / 1000000, timeTracker.getLoadTime() / 1000000, timeTracker.getFpeTime() / 1000000, timeTracker.getSpecTime() / 1000000);
|
||||
timeTracker.reset();
|
||||
|
@ -7853,5 +8034,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
|||
this.noExperimentalContent = noExperimentalContent;
|
||||
}
|
||||
|
||||
public void resetTimes() {
|
||||
timeTracker.reset();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -191,7 +191,7 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
//e.printStackTrace();
|
||||
rule(errors, NO_RULE_DATE, IssueType.EXCEPTION, stack.getLiteralPath(), false, I18nConstants.ERROR_GENERATING_SNAPSHOT, e.getMessage());
|
||||
ok = false;
|
||||
}
|
||||
|
@ -525,7 +525,7 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), characteristics.contains("can-bind") , I18nConstants.SD_ILLEGAL_CHARACTERISTICS, "Binding", typeCodes) && ok;
|
||||
}
|
||||
Element binding = element.getNamedChild("binding", false);
|
||||
ok = validateBinding(errors, binding, stack.push(binding, -1, null, null), typeCodes, snapshot, path, experimental) && ok;
|
||||
ok = validateBinding(errors, binding, stack.push(binding, -1, null, null), typeCodes, snapshot, path, experimental, sd) && ok;
|
||||
} else {
|
||||
// this is a good idea but there's plenty of cases where the rule isn't met; maybe one day it's worth investing the time to exclude these cases and bring this rule back
|
||||
// String bt = boundType(typeCodes);
|
||||
|
@ -989,7 +989,7 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
return null;
|
||||
}
|
||||
|
||||
private boolean validateBinding(List<ValidationMessage> errors, Element binding, NodeStack stack, Set<String> typeCodes, boolean snapshot, String path, boolean experimental) {
|
||||
private boolean validateBinding(List<ValidationMessage> errors, Element binding, NodeStack stack, Set<String> typeCodes, boolean snapshot, String path, boolean experimental, StructureDefinition profile) {
|
||||
boolean ok = true;
|
||||
if (bindableType(typeCodes) == null) {
|
||||
ok = rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), !snapshot, I18nConstants.SD_ED_BIND_NO_BINDABLE, path, typeCodes.toString()) && ok;
|
||||
|
@ -1019,6 +1019,119 @@ public class StructureDefinitionValidator extends BaseValidator {
|
|||
}
|
||||
}
|
||||
}
|
||||
if (binding.hasChildren("additional")) {
|
||||
int i = 0;
|
||||
for (Element ab : binding.getChildren("additional")) {
|
||||
ok = validateAdditionalBinding(errors, ab, stack.push(ab, i, null, null), snapshot, path, experimental) && ok;
|
||||
i++;
|
||||
}
|
||||
}
|
||||
if (binding.hasExtension(ToolingExtensions.EXT_BINDING_ADDITIONAL)) {
|
||||
int i = 0;
|
||||
for (Element ab : binding.getChildren("extension")) {
|
||||
String url = ab.getNamedChildValue("url");
|
||||
if (ToolingExtensions.EXT_BINDING_ADDITIONAL.equals(url)) {
|
||||
ok = validateAdditionalBindingExtension(errors, ab, stack.push(ab, i, null, null), snapshot, path, experimental, profile) && ok;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
private boolean validateAdditionalBinding(List<ValidationMessage> errors, Element binding, NodeStack stack, boolean snapshot, String path, boolean experimental) {
|
||||
boolean ok = true;
|
||||
|
||||
if (binding.hasChild("valueSet", false)) {
|
||||
Element valueSet = binding.getNamedChild("valueSet", false);
|
||||
String ref = valueSet.hasPrimitiveValue() ? valueSet.primitiveValue() : valueSet.getNamedChildValue("reference", false);
|
||||
if (warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), !snapshot || ref != null, I18nConstants.SD_ED_SHOULD_BIND_WITH_VS, path)) {
|
||||
Resource vs = context.fetchResource(Resource.class, ref);
|
||||
|
||||
// just because we can't resolve it directly doesn't mean that terminology server can't. Check with it
|
||||
|
||||
if (warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs != null || serverSupportsValueSet(ref), I18nConstants.SD_ED_BIND_UNKNOWN_VS, path, ref)) {
|
||||
if (vs != null) {
|
||||
if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs instanceof ValueSet, I18nConstants.SD_ED_BIND_NOT_VS, path, ref, vs.fhirType())) {
|
||||
ValueSet vsr = (ValueSet) vs;
|
||||
warning(errors, "2024-09-17", IssueType.BUSINESSRULE, stack.getLiteralPath(), !vsr.getExperimental() || experimental, I18nConstants.SD_ED_EXPERIMENTAL_BINDING, path, ref);
|
||||
} else {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (binding.hasChildren("usage")) {
|
||||
for (Element usage : binding.getChildren("usage")) {
|
||||
warning(errors, "2024-09-20", IssueType.BUSINESSRULE, stack.getLiteralPath(), false, "test");
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
private boolean validateAdditionalBindingExtension(List<ValidationMessage> errors, Element binding, NodeStack stack, boolean snapshot, String path, boolean experimental, StructureDefinition profile) {
|
||||
boolean ok = true;
|
||||
|
||||
if (binding.hasExtension("valueSet")) {
|
||||
Element valueSet = binding.getExtension("valueSet");
|
||||
Element vv = valueSet.getNamedChild("value");
|
||||
String ref = vv.hasPrimitiveValue() ? vv.primitiveValue() : vv.getNamedChildValue("reference", false);
|
||||
if (warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), !snapshot || ref != null, I18nConstants.SD_ED_SHOULD_BIND_WITH_VS, path)) {
|
||||
Resource vs = context.fetchResource(Resource.class, ref);
|
||||
|
||||
// just because we can't resolve it directly doesn't mean that terminology server can't. Check with it
|
||||
|
||||
if (warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs != null || serverSupportsValueSet(ref), I18nConstants.SD_ED_BIND_UNKNOWN_VS, path, ref)) {
|
||||
if (vs != null) {
|
||||
if (rule(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, stack.getLiteralPath(), vs instanceof ValueSet, I18nConstants.SD_ED_BIND_NOT_VS, path, ref, vs.fhirType())) {
|
||||
ValueSet vsr = (ValueSet) vs;
|
||||
warning(errors, "2024-09-17", IssueType.BUSINESSRULE, stack.getLiteralPath(), !vsr.getExperimental() || experimental, I18nConstants.SD_ED_EXPERIMENTAL_BINDING, path, ref);
|
||||
} else {
|
||||
ok = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (binding.hasExtension("usage")) {
|
||||
int i = 0;
|
||||
for (Element usage : binding.getChildren("extension")) {
|
||||
String url = usage.getNamedChildValue("url");
|
||||
if ("usage".equals(url)) {
|
||||
Element uv = usage.getNamedChild("value");
|
||||
ok = validateAdditionalBindingUsage(errors, uv, stack.push(uv, -1, null, null), path, profile) && ok;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
private boolean validateAdditionalBindingUsage(List<ValidationMessage> errors, Element usage, NodeStack stack, String path, StructureDefinition profile) {
|
||||
boolean ok = true;
|
||||
Element cc = usage.getNamedChild("code");
|
||||
if (cc != null) {
|
||||
String system = cc.getNamedChildValue("system");
|
||||
String code = cc.getNamedChildValue("code");
|
||||
if (system != null && system.equals(profile.getUrl())) {
|
||||
ElementDefinition ed = profile.getDifferential().getElementByPath(code);
|
||||
if (ed == null) {
|
||||
ed = profile.getSnapshot().getElementByPath(code);
|
||||
}
|
||||
if (ed == null) {
|
||||
ok = false;
|
||||
rule(errors, "2024-09-17", IssueType.BUSINESSRULE, stack.getLiteralPath(), false, I18nConstants.SD_ED_ADDITIONAL_BINDING_USAGE_INVALID_ELEMENT, system, code);
|
||||
} else {
|
||||
if (usage.hasChild("value")) {
|
||||
String t = usage.getNamedChild("value").fhirType();
|
||||
ok = rule(errors, "2024-09-20", IssueType.BUSINESSRULE, stack.getLiteralPath(), "CodeableConcept".equals(t), I18nConstants.SD_ED_ADDITIONAL_BINDING_USAGE_INVALID_TYPE, t, "CodeableConcept") && ok;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
warning(errors, "2024-09-17", IssueType.BUSINESSRULE, stack.getLiteralPath(), false, I18nConstants.SD_ED_ADDITIONAL_BINDING_USAGE_UNKNOWN, system, code);
|
||||
}
|
||||
}
|
||||
return ok;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,42 @@
|
|||
-------------------------------------------------------------------------------------
|
||||
{"code" : {
|
||||
"system" : "http://hl7.org/fhir/test/StructureDefinition/additional-bindings-profile-cs",
|
||||
"code" : "digital-access"
|
||||
}, "valueSet" :null, "langs":"en-US", "useServer":"true", "useClient":"false", "guessSystem":"false", "activeOnly":"false", "membershipOnly":"false", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
|
||||
"resourceType" : "Parameters",
|
||||
"parameter" : [{
|
||||
"name" : "profile-url",
|
||||
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
|
||||
}]
|
||||
}}####
|
||||
v: {
|
||||
"code" : "digital-access",
|
||||
"system" : "http://hl7.org/fhir/test/StructureDefinition/additional-bindings-profile-cs",
|
||||
"severity" : "error",
|
||||
"error" : "A definition for CodeSystem 'http://hl7.org/fhir/test/StructureDefinition/additional-bindings-profile-cs' could not be found, so the code cannot be validated",
|
||||
"class" : "CODESYSTEM_UNSUPPORTED",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "http://hl7.org/fhir/test/StructureDefinition/additional-bindings-profile-cs",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
"extension" : [{
|
||||
"url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server",
|
||||
"valueUrl" : "http://tx-dev.fhir.org/r4"
|
||||
}],
|
||||
"severity" : "error",
|
||||
"code" : "not-found",
|
||||
"details" : {
|
||||
"coding" : [{
|
||||
"system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
||||
"code" : "not-found"
|
||||
}],
|
||||
"text" : "A definition for CodeSystem 'http://hl7.org/fhir/test/StructureDefinition/additional-bindings-profile-cs' could not be found, so the code cannot be validated"
|
||||
},
|
||||
"location" : ["Coding.system"],
|
||||
"expression" : ["Coding.system"]
|
||||
}]
|
||||
}
|
||||
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
|
@ -0,0 +1,83 @@
|
|||
-------------------------------------------------------------------------------------
|
||||
{"code" : {
|
||||
"system" : "http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes",
|
||||
"code" : "digital-access-x"
|
||||
}, "valueSet" :null, "langs":"en-US", "useServer":"true", "useClient":"false", "guessSystem":"false", "activeOnly":"false", "membershipOnly":"false", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
|
||||
"resourceType" : "Parameters",
|
||||
"parameter" : [{
|
||||
"name" : "profile-url",
|
||||
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
|
||||
}]
|
||||
}}####
|
||||
v: {
|
||||
"code" : "digital-access-x",
|
||||
"system" : "http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes",
|
||||
"severity" : "error",
|
||||
"error" : "A definition for CodeSystem 'http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes' could not be found, so the code cannot be validated",
|
||||
"class" : "CODESYSTEM_UNSUPPORTED",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
"extension" : [{
|
||||
"url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server",
|
||||
"valueUrl" : "http://tx-dev.fhir.org/r4"
|
||||
}],
|
||||
"severity" : "error",
|
||||
"code" : "not-found",
|
||||
"details" : {
|
||||
"coding" : [{
|
||||
"system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
||||
"code" : "not-found"
|
||||
}],
|
||||
"text" : "A definition for CodeSystem 'http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes' could not be found, so the code cannot be validated"
|
||||
},
|
||||
"location" : ["Coding.system"],
|
||||
"expression" : ["Coding.system"]
|
||||
}]
|
||||
}
|
||||
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
||||
{"code" : {
|
||||
"system" : "http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes",
|
||||
"code" : "digital-access"
|
||||
}, "valueSet" :null, "langs":"en-US", "useServer":"true", "useClient":"false", "guessSystem":"false", "activeOnly":"false", "membershipOnly":"false", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
|
||||
"resourceType" : "Parameters",
|
||||
"parameter" : [{
|
||||
"name" : "profile-url",
|
||||
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
|
||||
}]
|
||||
}}####
|
||||
v: {
|
||||
"code" : "digital-access",
|
||||
"system" : "http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes",
|
||||
"severity" : "error",
|
||||
"error" : "A definition for CodeSystem 'http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes' could not be found, so the code cannot be validated",
|
||||
"class" : "CODESYSTEM_UNSUPPORTED",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
"extension" : [{
|
||||
"url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server",
|
||||
"valueUrl" : "http://tx-dev.fhir.org/r4"
|
||||
}],
|
||||
"severity" : "error",
|
||||
"code" : "not-found",
|
||||
"details" : {
|
||||
"coding" : [{
|
||||
"system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
||||
"code" : "not-found"
|
||||
}],
|
||||
"text" : "A definition for CodeSystem 'http://hl7.org/fhir/us/sdoh-clinicalcare/CodeSystem/SDOHCC-CodeSystemTemporaryCodes' could not be found, so the code cannot be validated"
|
||||
},
|
||||
"location" : ["Coding.system"],
|
||||
"expression" : ["Coding.system"]
|
||||
}]
|
||||
}
|
||||
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
|
@ -82,3 +82,45 @@ v: {
|
|||
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
||||
{"code" : {
|
||||
"system" : "http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips",
|
||||
"code" : "no-allergy-info",
|
||||
"display" : "No information about allergies"
|
||||
}, "valueSet" :null, "langs":"en-NZ", "useServer":"true", "useClient":"false", "guessSystem":"false", "activeOnly":"false", "membershipOnly":"false", "displayWarningMode":"false", "versionFlexible":"false", "profile": {
|
||||
"resourceType" : "Parameters",
|
||||
"parameter" : [{
|
||||
"name" : "profile-url",
|
||||
"valueString" : "http://hl7.org/fhir/ExpansionProfile/dc8fd4bc-091a-424a-8a3b-6198ef146891"
|
||||
}]
|
||||
}}####
|
||||
v: {
|
||||
"code" : "no-allergy-info",
|
||||
"system" : "http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips",
|
||||
"severity" : "error",
|
||||
"error" : "A definition for CodeSystem 'http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips' could not be found, so the code cannot be validated",
|
||||
"class" : "CODESYSTEM_UNSUPPORTED",
|
||||
"server" : "http://tx-dev.fhir.org/r4",
|
||||
"unknown-systems" : "http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips",
|
||||
"issues" : {
|
||||
"resourceType" : "OperationOutcome",
|
||||
"issue" : [{
|
||||
"extension" : [{
|
||||
"url" : "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-server",
|
||||
"valueUrl" : "http://tx-dev.fhir.org/r4"
|
||||
}],
|
||||
"severity" : "error",
|
||||
"code" : "not-found",
|
||||
"details" : {
|
||||
"coding" : [{
|
||||
"system" : "http://hl7.org/fhir/tools/CodeSystem/tx-issue-type",
|
||||
"code" : "not-found"
|
||||
}],
|
||||
"text" : "A definition for CodeSystem 'http://hl7.org/fhir/uv/ips/CodeSystem/absent-unknown-uv-ips' could not be found, so the code cannot be validated"
|
||||
},
|
||||
"location" : ["Coding.system"],
|
||||
"expression" : ["Coding.system"]
|
||||
}]
|
||||
}
|
||||
|
||||
}
|
||||
-------------------------------------------------------------------------------------
|
||||
|
|
Loading…
Reference in New Issue