Merge pull request #496 from hapifhir/gg_202105_04

Gg 202105 04
This commit is contained in:
Grahame Grieve 2021-05-14 14:55:11 +10:00 committed by GitHub
commit d57fd9fa1d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
17 changed files with 149 additions and 26 deletions

View File

@ -1 +1,9 @@
* adding release notes so I can release
Validator:
* Added parameter -want-invariants-in-messages
* fix issue with dependencies on IGs that have uppercase in package IDs
Other Code Changes
* Fix displays for some codes in ConceptMap.relationship when rendering
* Add Publication Version to rendering context for future use.

View File

@ -327,9 +327,9 @@ public class ConceptMapRenderer extends TerminologyRenderer {
} else if ("equivalent".equals(code)) {
return "is equivalent to";
} else if ("source-is-narrower-than-target".equals(code)) {
return "maps to wider concept";
return "is narrower then";
} else if ("source-is-broader-than-target".equals(code)) {
return "maps to narrower target";
return "is broader than";
} else if ("not-related-to".equals(code)) {
return "is not related to";
} else {

View File

@ -21,8 +21,6 @@ import org.hl7.fhir.utilities.xhtml.XhtmlNode;
public class PatientRenderer extends ResourceRenderer {
public PatientRenderer(RenderingContext context) {
super(context);
}

View File

@ -11,6 +11,8 @@ import org.hl7.fhir.r5.conformance.ProfileUtilities.ProfileKnowledgeProvider;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.DomainResource;
import org.hl7.fhir.r5.model.Enumerations.FHIRVersion;
import org.hl7.fhir.r5.model.FhirPublication;
import org.hl7.fhir.r5.renderers.utils.Resolver.IReferenceResolver;
import org.hl7.fhir.r5.renderers.utils.Resolver.ResourceContext;
import org.hl7.fhir.r5.utils.FHIRPathEngine.IEvaluationContext;
@ -96,6 +98,7 @@ public class RenderingContext {
private QuestionnaireRendererMode questionnaireMode = QuestionnaireRendererMode.FORM;
private boolean addGeneratedNarrativeHeader = true;
private FhirPublication targetVersion;
/**
*
* @param context - access to all related resources that might be needed
@ -392,7 +395,12 @@ public class RenderingContext {
return this;
}
public FhirPublication getTargetVersion() {
return targetVersion;
}
public void setTargetVersion(FhirPublication targetVersion) {
this.targetVersion = targetVersion;
}
}

View File

@ -193,7 +193,10 @@ public interface IResourceValidator {
public boolean isNoInvariantChecks();
public IResourceValidator setNoInvariantChecks(boolean value) ;
public boolean isWantInvariantInMessage();
public IResourceValidator setWantInvariantInMessage(boolean wantInvariantInMessage);
public boolean isNoTerminologyChecks();
public IResourceValidator setNoTerminologyChecks(boolean noTerminologyChecks);
@ -300,7 +303,7 @@ public interface IResourceValidator {
org.hl7.fhir.r5.elementmodel.Element validate(Object Context, List<ValidationMessage> errors, JsonObject object) throws FHIRException;
org.hl7.fhir.r5.elementmodel.Element validate(Object Context, List<ValidationMessage> errors, JsonObject object, String profile) throws FHIRException;
org.hl7.fhir.r5.elementmodel.Element validate(Object Context, List<ValidationMessage> errors, JsonObject object, List<StructureDefinition> profile) throws FHIRException;
org.hl7.fhir.r5.elementmodel.Element validate(Object Context, List<ValidationMessage> errors, JsonObject object, List<StructureDefinition> profile) throws FHIRException;
}

View File

@ -189,6 +189,7 @@ public class I18nConstants {
public static final String INTERNAL_ERROR___TYPE_NOT_KNOWN_ = "Internal_error___type_not_known_";
public static final String INTERNAL_INT_BAD_TYPE = "Internal_INT_Bad_Type";
public static final String INTERNAL_RECURSION_DETECTION_FIND_LOOP_PATH_RECURSION____CHECK_PATHS_ARE_VALID_FOR_PATH_ = "Internal_recursion_detection_find_loop_path_recursion____check_paths_are_valid_for_path_";
public static final String INV_FAILED = "INV_FAILED";
public static final String INVALID_SLICING__THERE_IS_MORE_THAN_ONE_TYPE_SLICE_AT__BUT_ONE_OF_THEM__HAS_MIN__1_SO_THE_OTHER_SLICES_CANNOT_EXIST = "Invalid_slicing__there_is_more_than_one_type_slice_at__but_one_of_them__has_min__1_so_the_other_slices_cannot_exist";
public static final String LANGUAGE_XHTML_LANG_DIFFERENT1 = "Language_XHTML_Lang_Different1";
public static final String LANGUAGE_XHTML_LANG_DIFFERENT2 = "Language_XHTML_Lang_Different2";

View File

@ -90,9 +90,9 @@ public class FilesystemPackageCacheManager extends BasePackageCacheManager imple
public static final String PRIMARY_SERVER = "http://packages.fhir.org";
public static final String SECONDARY_SERVER = "http://packages2.fhir.org/packages";
// private static final String SECONDARY_SERVER = "http://local.fhir.org:960/packages";
public static final String PACKAGE_REGEX = "^[a-z][a-z0-9\\_\\-]*(\\.[a-z0-9\\_\\-]+)+$";
public static final String PACKAGE_VERSION_REGEX = "^[a-z][a-z0-9\\_\\-]*(\\.[a-z0-9\\_\\-]+)+\\#[a-z0-9\\-\\_]+(\\.[a-z0-9\\-\\_]+)*$";
public static final String PACKAGE_VERSION_REGEX_OPT = "^[a-z][a-z0-9\\_\\-]*(\\.[a-z0-9\\_\\-]+)+(\\#[a-z0-9\\-\\_]+(\\.[a-z0-9\\-\\_]+)*)?$";
public static final String PACKAGE_REGEX = "^[a-zA-Z][A-Za-z0-9\\_\\-]*(\\.[A-Za-z0-9\\_\\-]+)+$";
public static final String PACKAGE_VERSION_REGEX = "^[A-Za-z][A-Za-z0-9\\_\\-]*(\\.[A-Za-z0-9\\_\\-]+)+\\#[A-Za-z0-9\\-\\_]+(\\.[A-Za-z0-9\\-\\_]+)*$";
public static final String PACKAGE_VERSION_REGEX_OPT = "^[A-Za-z][A-Za-z0-9\\_\\-]*(\\.[A-Za-z0-9\\_\\-]+)+(\\#[A-Za-z0-9\\-\\_]+(\\.[A-Za-z0-9\\-\\_]+)*)?$";
private static final Logger ourLog = LoggerFactory.getLogger(FilesystemPackageCacheManager.class);
private static final String CACHE_VERSION = "3"; // second version - see wiki page
private String cacheFolder;

View File

@ -871,10 +871,20 @@ private boolean elementIsOk(String name) throws FHIRFormatError {
return s.toString();
}
private String readUntil(String sc) throws IOException
{
StringBuilder s = new StringBuilder();
while (peekChar() != 0 && sc.indexOf(peekChar()) == -1)
s.append(readChar());
readChar();
return s.toString();
}
private void parseLiteral(StringBuilder s) throws IOException, FHIRFormatError {
// UInt16 w;
readChar();
String c = readUntil(';');
String c = readUntil(";&'\"><");
if (c.equals("apos"))
s.append('\'');
else if (c.equals("quot"))
@ -1162,8 +1172,12 @@ private boolean elementIsOk(String name) throws FHIRFormatError {
s.append((char) 201D);
else if (entities.containsKey(c))
s.append(entities.get(c));
else
else if (!mustBeWellFormed) {
// we guess that this is an accidentally unescaped &
s.append("&"+c);
} else {
throw new FHIRFormatError("unable to parse character reference '" + c + "'' (last text = '" + lastText + "'" + descLoc());
}
}
private boolean isInteger(String s, int base) {

View File

@ -652,3 +652,4 @@ BUNDLE_SEARCH_ENTRY_WRONG_RESOURCE_TYPE_MODE = This is not a matching resource t
BUNDLE_SEARCH_ENTRY_WRONG_RESOURCE_TYPE_OUTCOME = This is not an OperationOutcome ({0})
BUNDLE_SEARCH_ENTRY_WRONG_RESOURCE_TYPE_NO_MODE = This is not a matching resource type for the specified search (is a search mode needed?) ({0} expecting {1})
BUNDLE_SEARCH_NO_MODE = SearchSet bundles should have search modes on the entries
INV_FAILED = Rule {0} Failed

View File

@ -1,5 +1,6 @@
package org.hl7.fhir.utilities.tests;
import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
import org.hl7.fhir.utilities.xhtml.XhtmlParser;
@ -94,5 +95,18 @@ public class XhtmlNodeTest {
@Test
public void testParseBadChars() throws FHIRFormatError, IOException {
XhtmlNode x = new XhtmlParser().parse(BaseTestingUtilities.loadTestResource("xhtml", "bad-chars.html"), "div");
}
@Test
public void testParseBadLink1() throws FHIRFormatError, IOException {
XhtmlNode x = new XhtmlParser().setMustBeWellFormed(false).parse(BaseTestingUtilities.loadTestResource("xhtml", "bad-link.html"), "div");
}
@Test
public void testParseBadLink2() throws FHIRFormatError, IOException {
Assertions.assertThrows(FHIRException.class, () -> new XhtmlParser().parse(BaseTestingUtilities.loadTestResource("xhtml", "bad-link.html"), "div"));
}
}

View File

@ -21,6 +21,7 @@ import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.formats.JsonParser;
import org.hl7.fhir.r5.formats.XmlParser;
import org.hl7.fhir.r5.model.*;
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.r5.renderers.RendererFactory;
import org.hl7.fhir.r5.renderers.utils.RenderingContext;
import org.hl7.fhir.r5.renderers.utils.RenderingContext.ResourceRendererMode;
@ -127,6 +128,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
@Getter @Setter private Map<String, byte[]> binaries = new HashMap<>();
@Getter @Setter private boolean doNative;
@Getter @Setter private boolean noInvariantChecks;
@Getter @Setter private boolean wantInvariantInMessage;
@Getter @Setter private boolean hintAboutNonMustSupport;
@Getter @Setter private boolean anyExtensionsAllowed = false;
@Getter @Setter private String version;
@ -415,12 +417,25 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
return Manager.build(getContext(), structureDefinition);
}
public DomainResource generate(String source, String version) throws FHIRException, IOException, EOperationOutcome {
public Resource generate(String source, String version) throws FHIRException, IOException, EOperationOutcome {
Content cnt = igLoader.loadContent(source, "validate", false);
Resource res = igLoader.loadResourceByVersion(version, cnt.focus, source);
RenderingContext rc = new RenderingContext(context, null, null, "http://hl7.org/fhir", "", null, ResourceRendererMode.RESOURCE);
RendererFactory.factory(res, rc).render((DomainResource) res);
return (DomainResource) res;
genResource(res, rc);
return (Resource) res;
}
public void genResource(Resource res, RenderingContext rc) throws IOException, EOperationOutcome {
if (res instanceof Bundle) {
Bundle bnd = (Bundle) res;
for (BundleEntryComponent be : bnd.getEntry()) {
if (be.hasResource()) {
genResource(be.getResource(), rc);
}
}
} else {
RendererFactory.factory(res, rc).render((DomainResource) res);
}
}
public void convert(String source, String output) throws FHIRException, IOException {
@ -463,7 +478,11 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
validator.setHintAboutNonMustSupport(hintAboutNonMustSupport);
validator.setAnyExtensionsAllowed(anyExtensionsAllowed);
validator.setNoInvariantChecks(isNoInvariantChecks());
validator.setWantInvariantInMessage(isWantInvariantInMessage());
validator.setValidationLanguage(language);
if (language != null) {
validator.getContext().setValidationMessageLanguage(Locale.forLanguageTag(language));
}
validator.setAssumeValidRestReferences(assumeValidRestReferences);
validator.setNoExtensibleWarnings(noExtensibleBindingMessages);
validator.setSecurityChecks(securityChecks);

View File

@ -36,6 +36,10 @@ public class CliContext {
private boolean noInternalCaching = false; // internal, for when debugging terminology validation
@JsonProperty("noExtensibleBindingMessages")
private boolean noExtensibleBindingMessages = false;
@JsonProperty("noInvariants")
private boolean noInvariants = false;
@JsonProperty("wantInvariantsInMessages")
private boolean wantInvariantsInMessages = false;
@JsonProperty("map")
private String map = null;
@ -441,6 +445,26 @@ public class CliContext {
this.noExtensibleBindingMessages = noExtensibleBindingMessages;
return this;
}
@JsonProperty("noInvariants")
public boolean isNoInvariants() {
return noInvariants;
}
@JsonProperty("noInvariants")
public void setNoInvariants(boolean noInvariants) {
this.noInvariants = noInvariants;
}
@JsonProperty("wantInvariantsInMessages")
public boolean isWantInvariantsInMessages() {
return wantInvariantsInMessages;
}
@JsonProperty("wantInvariantsInMessages")
public void setWantInvariantsInMessages(boolean wantInvariantsInMessages) {
this.wantInvariantsInMessages = wantInvariantsInMessages;
}
@JsonProperty("securityChecks")
public boolean isSecurityChecks() {
@ -483,6 +507,8 @@ public class CliContext {
canDoNative == that.canDoNative &&
noInternalCaching == that.noInternalCaching &&
noExtensibleBindingMessages == that.noExtensibleBindingMessages &&
noInvariants == that.noInvariants &&
wantInvariantsInMessages == that.wantInvariantsInMessages &&
Objects.equals(map, that.map) &&
Objects.equals(output, that.output) &&
Objects.equals(htmlOutput, that.htmlOutput) &&
@ -507,7 +533,7 @@ public class CliContext {
@Override
public int hashCode() {
return Objects.hash(doNative, anyExtensionsAllowed, hintAboutNonMustSupport, recursive, doDebug, assumeValidRestReferences, canDoNative, noInternalCaching, noExtensibleBindingMessages, map, output, htmlOutput, txServer, sv, txLog, mapLog, lang, fhirpath, snomedCT, targetVer, igs, questionnaireMode, profiles, sources, mode, locale, locations, crumbTrails, showTimes);
return Objects.hash(doNative, anyExtensionsAllowed, hintAboutNonMustSupport, recursive, doDebug, assumeValidRestReferences, canDoNative, noInternalCaching, noExtensibleBindingMessages, noInvariants, wantInvariantsInMessages, map, output, htmlOutput, txServer, sv, txLog, mapLog, lang, fhirpath, snomedCT, targetVer, igs, questionnaireMode, profiles, sources, mode, locale, locations, crumbTrails, showTimes);
}
@Override
@ -522,6 +548,8 @@ public class CliContext {
", canDoNative=" + canDoNative +
", noInternalCaching=" + noInternalCaching +
", noExtensibleBindingMessages=" + noExtensibleBindingMessages +
", noInvariants=" + noInvariants +
", wantInvariantsInMessages=" + wantInvariantsInMessages +
", map='" + map + '\'' +
", output='" + output + '\'' +
", htmlOutput='" + htmlOutput + '\'' +

View File

@ -143,7 +143,7 @@ public class ValidationService {
}
public void generateNarrative(CliContext cliContext, ValidationEngine validator) throws Exception {
DomainResource r = validator.generate(cliContext.getSources().get(0), cliContext.getSv());
Resource r = validator.generate(cliContext.getSources().get(0), cliContext.getSv());
System.out.println(" ...generated narrative successfully");
if (cliContext.getOutput() != null) {
validator.handleOutput(r, cliContext.getOutput(), cliContext.getSv());
@ -243,6 +243,8 @@ public class ValidationService {
validator.setSnomedExtension(cliContext.getSnomedCTCode());
validator.setAssumeValidRestReferences(cliContext.isAssumeValidRestReferences());
validator.setNoExtensibleBindingMessages(cliContext.isNoExtensibleBindingMessages());
validator.setNoInvariantChecks(cliContext.isNoInvariants());
validator.setWantInvariantInMessage(cliContext.isWantInvariantsInMessages());
validator.setSecurityChecks(cliContext.isSecurityChecks());
validator.setCrumbTrails(cliContext.isCrumbTrails());
validator.setShowTimes(cliContext.isShowTimes());

View File

@ -52,6 +52,8 @@ public class Params {
public static final String RIGHT = "-right";
public static final String NO_INTERNAL_CACHING = "-no-internal-caching";
public static final String NO_EXTENSIBLE_BINDING_WARNINGS = "-no-extensible-binding-warnings";
public static final String NO_INVARIANTS = "-no-invariants";
public static final String WANT_INVARIANTS_IN_MESSAGES = "-want-invariants-in-messages";
public static final String SECURITY_CHECKS = "-security-checks";
public static final String CRUMB_TRAIL = "-crumb-trails";
public static final String SHOW_TIMES = "-show-times";
@ -156,6 +158,10 @@ public class Params {
cliContext.setNoInternalCaching(true);
} else if (args[i].equals(NO_EXTENSIBLE_BINDING_WARNINGS)) {
cliContext.setNoExtensibleBindingMessages(true);
} else if (args[i].equals(NO_INVARIANTS)) {
cliContext.setNoInvariants(true);
} else if (args[i].equals(WANT_INVARIANTS_IN_MESSAGES)) {
cliContext.setWantInvariantsInMessages(true);
} else if (args[i].equals(HINT_ABOUT_NON_MUST_SUPPORT)) {
cliContext.setHintAboutNonMustSupport(true);
} else if (args[i].equals(TO_VERSION)) {

View File

@ -341,6 +341,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
private boolean anyExtensionsAllowed;
private boolean errorForUnknownProfiles;
private boolean noInvariantChecks;
private boolean wantInvariantInMessage;
private boolean noTerminologyChecks;
private boolean hintAboutNonMustSupport;
private boolean showMessagesFromReferences;
@ -427,6 +428,17 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return this;
}
@Override
public boolean isWantInvariantInMessage() {
return wantInvariantInMessage;
}
@Override
public IResourceValidator setWantInvariantInMessage(boolean wantInvariantInMessage) {
this.wantInvariantInMessage = wantInvariantInMessage;
return this;
}
public IValidatorResourceFetcher getFetcher() {
return this.fetcher;
}
@ -5015,20 +5027,24 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
}
if (!ok) {
if (!Utilities.noString(msg)) {
msg = " (" + msg + ")";
msg = "'" + inv.getHuman()+"' (" + msg + ")";
} else if (wantInvariantInMessage) {
msg = "'" + inv.getHuman()+"' [" + n.toString() + "]";
} else {
msg = context.formatMessage(I18nConstants.INV_FAILED, "'" + inv.getHuman()+"'");
}
if (inv.hasExtension("http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice") &&
ToolingExtensions.readBooleanExtension(inv, "http://hl7.org/fhir/StructureDefinition/elementdefinition-bestpractice")) {
if (bpWarnings == BestPracticeWarningLevel.Hint)
hint(errors, IssueType.INVARIANT, element.line(), element.col(), path, ok, inv.getKey() + ": '" + inv.getHuman()+"' " + (Utilities.noString(msg) ? "failed" : msg));
hint(errors, IssueType.INVARIANT, element.line(), element.col(), path, ok, inv.getKey() + ": " + msg);
else if (bpWarnings == BestPracticeWarningLevel.Warning)
warning(errors, IssueType.INVARIANT, element.line(), element.col(), path, ok, inv.getKey() + ": '" + inv.getHuman()+"' " + (Utilities.noString(msg) ? "failed" : msg));
warning(errors, IssueType.INVARIANT, element.line(), element.col(), path, ok, inv.getKey() + ": '" + inv.getHuman()+"' " + msg);
else if (bpWarnings == BestPracticeWarningLevel.Error)
rule(errors, IssueType.INVARIANT, element.line(), element.col(), path, ok, inv.getKey() + ": '" + inv.getHuman()+"' " + (Utilities.noString(msg) ? "failed" : msg));
rule(errors, IssueType.INVARIANT, element.line(), element.col(), path, ok, inv.getKey() + ": '" + inv.getHuman()+"' " + msg);
} else if (inv.getSeverity() == ConstraintSeverity.ERROR) {
rule(errors, IssueType.INVARIANT, element.line(), element.col(), path, ok, inv.getKey() + ": '" + inv.getHuman()+"' " + (Utilities.noString(msg) ? "failed" : msg));
rule(errors, IssueType.INVARIANT, element.line(), element.col(), path, ok, inv.getKey() + ": '" + inv.getHuman()+"' " + msg);
} else if (inv.getSeverity() == ConstraintSeverity.WARNING) {
warning(errors, IssueType.INVARIANT, element.line(), element.line(), path, ok, inv.getKey() + ": '" + inv.getHuman()+"' " + (Utilities.noString(msg) ? "failed" : msg));
warning(errors, IssueType.INVARIANT, element.line(), element.line(), path, ok, inv.getKey() + ": '" + inv.getHuman()+"' " + msg);
}
}
}

View File

@ -33,6 +33,7 @@ import org.hl7.fhir.r5.comparison.ProfileComparer.ProfileComparison;
import org.hl7.fhir.r5.comparison.ValueSetComparer;
import org.hl7.fhir.r5.comparison.ValueSetComparer.ValueSetComparison;
import org.hl7.fhir.r5.conformance.ProfileUtilities;
import org.hl7.fhir.r5.context.BaseWorkerContext;
import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.formats.JsonParser;
@ -109,7 +110,11 @@ public class ComparisonTests {
context = TestingUtilities.context();
FilesystemPackageCacheManager pcm = new FilesystemPackageCacheManager(true, ToolsVersion.TOOLS_VERSION);
NpmPackage npm = pcm.loadPackage("hl7.fhir.us.core#3.1.0");
context.loadFromPackage(npm, new R4ToR5Loader(new String[] { "CapabilityStatement", "StructureDefinition", "ValueSet", "CodeSystem", "SearchParameter", "OperationDefinition", "Questionnaire","ConceptMap","StructureMap", "NamingSystem"}, new NullLoaderKnowledgeProvider()));
BaseWorkerContext bc = (BaseWorkerContext) context;
boolean dupl = bc.isAllowLoadingDuplicates();
bc.setAllowLoadingDuplicates(true);
context.loadFromPackage(npm, new R4ToR5Loader(new String[] { "CapabilityStatement", "StructureDefinition", "ValueSet", "CodeSystem", "SearchParameter", "OperationDefinition", "Questionnaire","ConceptMap","StructureMap", "NamingSystem"}, new NullLoaderKnowledgeProvider()));
bc.setAllowLoadingDuplicates(dupl);
}
if (!new File(Utilities.path("[tmp]", "comparison")).exists()) {

View File

@ -19,7 +19,7 @@
<properties>
<hapi_fhir_version>5.1.0</hapi_fhir_version>
<validator_test_case_version>1.1.63</validator_test_case_version>
<validator_test_case_version>1.1.64-SNAPSHOT</validator_test_case_version>
<junit_jupiter_version>5.7.1</junit_jupiter_version>
<junit_platform_launcher_version>1.7.1</junit_platform_launcher_version>
<maven_surefire_version>3.0.0-M4</maven_surefire_version>