Merge pull request #491 from hapifhir/gg-202105-bugfixes-2
* Validator: Load code systems from known packages on the fly
This commit is contained in:
commit
5a11851ec7
|
@ -3,6 +3,12 @@
|
||||||
* Snapshot generator: fix problem checking types on logical models
|
* Snapshot generator: fix problem checking types on logical models
|
||||||
* Do not flag internal references as suspicious
|
* Do not flag internal references as suspicious
|
||||||
* XMLParser allows passing a schema location
|
* XMLParser allows passing a schema location
|
||||||
|
* XMLParser allows passing a schema location
|
||||||
* Issue 484 https://github.com/hapifhir/org.hl7.fhir.core/issues/484
|
* Issue 484 https://github.com/hapifhir/org.hl7.fhir.core/issues/484
|
||||||
* Adding Kotlin to the build process
|
* Adding Kotlin to the build process
|
||||||
* random cleaning up in convertors
|
* random cleaning up in convertors
|
||||||
|
* Validator: Load code systems from known packages on the fly
|
||||||
|
* Validator: better handle invalid v3 dates
|
||||||
|
* Renderer: Render OperationDefinition.InputProfile and OutputProfile
|
||||||
|
* Important: Allow more valid schemas for Utilities.isAbsoluteUrl
|
||||||
|
* Validator: remove notes about extensible bindings if profile extensible binding is valid
|
||||||
|
|
|
@ -267,7 +267,7 @@ public class StructureMap30_50 {
|
||||||
VersionConvertor_30_50.copyElement(src, tgt);
|
VersionConvertor_30_50.copyElement(src, tgt);
|
||||||
if (src.hasContext())
|
if (src.hasContext())
|
||||||
tgt.setContextElement(VersionConvertor_30_50.convertId(src.getContextElement()));
|
tgt.setContextElement(VersionConvertor_30_50.convertId(src.getContextElement()));
|
||||||
if (src.hasContextType() && src.getContextType() == org.hl7.fhir.dstu3.model.StructureMap.StructureMapContextType.VARIABLE)
|
if (src.hasContextType() && src.getContextType() != org.hl7.fhir.dstu3.model.StructureMap.StructureMapContextType.VARIABLE)
|
||||||
throw new Error("This conversion is not supported. Consult code maintainers"); // this should never happens - no one knows what the intent was here.
|
throw new Error("This conversion is not supported. Consult code maintainers"); // this should never happens - no one knows what the intent was here.
|
||||||
if (src.hasElement())
|
if (src.hasElement())
|
||||||
tgt.setElementElement(VersionConvertor_30_50.convertString(src.getElementElement()));
|
tgt.setElementElement(VersionConvertor_30_50.convertString(src.getElementElement()));
|
||||||
|
|
|
@ -205,6 +205,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
protected TerminologyCache txCache;
|
protected TerminologyCache txCache;
|
||||||
protected TimeTracker clock;
|
protected TimeTracker clock;
|
||||||
private boolean tlogging = true;
|
private boolean tlogging = true;
|
||||||
|
private ICanonicalResourceLocator locator;
|
||||||
|
|
||||||
public BaseWorkerContext() throws FileNotFoundException, IOException, FHIRException {
|
public BaseWorkerContext() throws FileNotFoundException, IOException, FHIRException {
|
||||||
txCache = new TerminologyCache(lock, null);
|
txCache = new TerminologyCache(lock, null);
|
||||||
|
@ -498,9 +499,17 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public CodeSystem fetchCodeSystem(String system) {
|
public CodeSystem fetchCodeSystem(String system) {
|
||||||
|
CodeSystem cs;
|
||||||
synchronized (lock) {
|
synchronized (lock) {
|
||||||
return codeSystems.get(system);
|
cs = codeSystems.get(system);
|
||||||
}
|
}
|
||||||
|
if (cs == null && locator != null) {
|
||||||
|
locator.findResource(system);
|
||||||
|
synchronized (lock) {
|
||||||
|
cs = codeSystems.get(system);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return cs;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -2002,4 +2011,12 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public ICanonicalResourceLocator getLocator() {
|
||||||
|
return locator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setLocator(ICanonicalResourceLocator locator) {
|
||||||
|
this.locator = locator;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -170,6 +170,10 @@ public interface IWorkerContext {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public interface ICanonicalResourceLocator {
|
||||||
|
void findResource(String url); // if it can be found, put it in the context
|
||||||
|
}
|
||||||
|
|
||||||
public interface IContextResourceLoader {
|
public interface IContextResourceLoader {
|
||||||
/**
|
/**
|
||||||
* @return List of the resource types that shoud be loaded
|
* @return List of the resource types that shoud be loaded
|
||||||
|
|
|
@ -468,8 +468,12 @@ public class XmlParser extends ParserBase {
|
||||||
|
|
||||||
private String convertForDateFormatFromExternal(String fmt, String av) throws FHIRException {
|
private String convertForDateFormatFromExternal(String fmt, String av) throws FHIRException {
|
||||||
if ("v3".equals(fmt)) {
|
if ("v3".equals(fmt)) {
|
||||||
|
try {
|
||||||
DateTimeType d = DateTimeType.parseV3(av);
|
DateTimeType d = DateTimeType.parseV3(av);
|
||||||
return d.asStringValue();
|
return d.asStringValue();
|
||||||
|
} catch (Exception e) {
|
||||||
|
return av; // not at all clear what to do in this case.
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
throw new FHIRException(context.formatMessage(I18nConstants.UNKNOWN_DATA_FORMAT_, fmt));
|
throw new FHIRException(context.formatMessage(I18nConstants.UNKNOWN_DATA_FORMAT_, fmt));
|
||||||
}
|
}
|
||||||
|
|
|
@ -50,6 +50,26 @@ public class OperationDefinitionRenderer extends TerminologyRenderer {
|
||||||
x.para().tx("URL: [base]/"+c.getValue()+"/[id]/$"+opd.getCode());
|
x.para().tx("URL: [base]/"+c.getValue()+"/[id]/$"+opd.getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (opd.hasInputProfile()) {
|
||||||
|
XhtmlNode p = x.para();
|
||||||
|
p.tx("Input parameters Profile: ");
|
||||||
|
StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, opd.getInputProfile());
|
||||||
|
if (sd == null) {
|
||||||
|
p.pre().tx(opd.getInputProfile());
|
||||||
|
} else {
|
||||||
|
p.ah(sd.getUserString("path")).tx(sd.present());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (opd.hasOutputProfile()) {
|
||||||
|
XhtmlNode p = x.para();
|
||||||
|
p.tx("Output parameters Profile: ");
|
||||||
|
StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, opd.getOutputProfile());
|
||||||
|
if (sd == null) {
|
||||||
|
p.pre().tx(opd.getOutputProfile());
|
||||||
|
} else {
|
||||||
|
p.ah(sd.getUserString("path")).tx(sd.present());
|
||||||
|
}
|
||||||
|
}
|
||||||
x.para().tx("Parameters");
|
x.para().tx("Parameters");
|
||||||
XhtmlNode tbl = x.table( "grid");
|
XhtmlNode tbl = x.table( "grid");
|
||||||
XhtmlNode tr = tbl.tr();
|
XhtmlNode tr = tbl.tr();
|
||||||
|
|
|
@ -1093,10 +1093,12 @@ public class Utilities {
|
||||||
|
|
||||||
|
|
||||||
public static boolean isAbsoluteUrl(String ref) {
|
public static boolean isAbsoluteUrl(String ref) {
|
||||||
return ref != null && (ref.startsWith("http:") || ref.startsWith("https:") || ref.startsWith("urn:uuid:") || ref.startsWith("urn:oid:") ||
|
if (ref != null && ref.contains(":")) {
|
||||||
Utilities.startsWithInList(ref, "urn:iso:", "urn:iso-iec:", "urn:iso-cie:", "urn:iso-astm:", "urn:iso-ieee:", "urn:iec:")); // rfc5141
|
String scheme = ref.substring(0, ref.indexOf(":"));
|
||||||
|
return existsInList(scheme, "http", "https", "urn") || isToken(scheme) || Utilities.startsWithInList(ref, "urn:iso:", "urn:iso-iec:", "urn:iso-cie:", "urn:iso-astm:", "urn:iso-ieee:", "urn:iec:"); // rfc5141
|
||||||
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public static boolean equivalent(String l, String r) {
|
public static boolean equivalent(String l, String r) {
|
||||||
if (Utilities.noString(l) && Utilities.noString(r))
|
if (Utilities.noString(l) && Utilities.noString(r))
|
||||||
|
|
|
@ -814,7 +814,7 @@ public class NpmPackage {
|
||||||
// }
|
// }
|
||||||
|
|
||||||
public String getWebLocation() {
|
public String getWebLocation() {
|
||||||
if (npm.has("url")) {
|
if (npm.has("url") && npm.get("url").isJsonPrimitive()) {
|
||||||
return PackageHacker.fixPackageUrl(npm.get("url").getAsString());
|
return PackageHacker.fixPackageUrl(npm.get("url").getAsString());
|
||||||
} else {
|
} else {
|
||||||
return JSONUtil.str(npm, "canonical");
|
return JSONUtil.str(npm, "canonical");
|
||||||
|
|
|
@ -833,7 +833,7 @@ public class BaseValidator {
|
||||||
String targetUrl = null;
|
String targetUrl = null;
|
||||||
String version = "";
|
String version = "";
|
||||||
String resourceType = null;
|
String resourceType = null;
|
||||||
if (ref.startsWith("http") || ref.startsWith("urn")) {
|
if (ref.startsWith("http:") || ref.startsWith("urn:") || Utilities.isAbsoluteUrl(ref)) {
|
||||||
// We've got an absolute reference, no need to calculate
|
// We've got an absolute reference, no need to calculate
|
||||||
if (ref.contains("/_history/")) {
|
if (ref.contains("/_history/")) {
|
||||||
targetUrl = ref.substring(0, ref.indexOf("/_history/") - 1);
|
targetUrl = ref.substring(0, ref.indexOf("/_history/") - 1);
|
||||||
|
|
|
@ -9,6 +9,7 @@ import org.hl7.fhir.convertors.txClient.TerminologyClientFactory;
|
||||||
import org.hl7.fhir.exceptions.DefinitionException;
|
import org.hl7.fhir.exceptions.DefinitionException;
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
import org.hl7.fhir.r5.conformance.ProfileUtilities;
|
||||||
|
import org.hl7.fhir.r5.context.IWorkerContext.ICanonicalResourceLocator;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
|
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
|
||||||
import org.hl7.fhir.r5.context.SimpleWorkerContext;
|
import org.hl7.fhir.r5.context.SimpleWorkerContext;
|
||||||
import org.hl7.fhir.r5.elementmodel.Element;
|
import org.hl7.fhir.r5.elementmodel.Element;
|
||||||
|
@ -134,6 +135,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IPackageInst
|
||||||
@Getter @Setter private PrintWriter mapLog;
|
@Getter @Setter private PrintWriter mapLog;
|
||||||
@Getter @Setter private boolean debug = false;
|
@Getter @Setter private boolean debug = false;
|
||||||
@Getter @Setter private IValidatorResourceFetcher fetcher;
|
@Getter @Setter private IValidatorResourceFetcher fetcher;
|
||||||
|
@Getter @Setter private ICanonicalResourceLocator locator;
|
||||||
@Getter @Setter private boolean assumeValidRestReferences;
|
@Getter @Setter private boolean assumeValidRestReferences;
|
||||||
@Getter @Setter private boolean noExtensibleBindingMessages;
|
@Getter @Setter private boolean noExtensibleBindingMessages;
|
||||||
@Getter @Setter private boolean securityChecks;
|
@Getter @Setter private boolean securityChecks;
|
||||||
|
|
|
@ -4,6 +4,7 @@ import com.google.gson.JsonObject;
|
||||||
import org.hl7.fhir.convertors.txClient.TerminologyClientFactory;
|
import org.hl7.fhir.convertors.txClient.TerminologyClientFactory;
|
||||||
import org.hl7.fhir.exceptions.FHIRException;
|
import org.hl7.fhir.exceptions.FHIRException;
|
||||||
import org.hl7.fhir.r5.context.IWorkerContext;
|
import org.hl7.fhir.r5.context.IWorkerContext;
|
||||||
|
import org.hl7.fhir.r5.context.IWorkerContext.ICanonicalResourceLocator;
|
||||||
import org.hl7.fhir.r5.elementmodel.Element;
|
import org.hl7.fhir.r5.elementmodel.Element;
|
||||||
import org.hl7.fhir.r5.model.CanonicalResource;
|
import org.hl7.fhir.r5.model.CanonicalResource;
|
||||||
import org.hl7.fhir.r5.terminologies.TerminologyClient;
|
import org.hl7.fhir.r5.terminologies.TerminologyClient;
|
||||||
|
@ -26,7 +27,7 @@ import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
public class StandAloneValidatorFetcher implements IValidatorResourceFetcher {
|
public class StandAloneValidatorFetcher implements IValidatorResourceFetcher, ICanonicalResourceLocator {
|
||||||
|
|
||||||
List<String> mappingsUris = new ArrayList<>();
|
List<String> mappingsUris = new ArrayList<>();
|
||||||
private FilesystemPackageCacheManager pcm;
|
private FilesystemPackageCacheManager pcm;
|
||||||
|
@ -63,7 +64,7 @@ public class StandAloneValidatorFetcher implements IValidatorResourceFetcher {
|
||||||
url = url.substring(0, url.lastIndexOf("|"));
|
url = url.substring(0, url.lastIndexOf("|"));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (type.equals("uri") && isMappingUri(url)) {
|
if (type != null && type.equals("uri") && isMappingUri(url)) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -128,6 +129,7 @@ public class StandAloneValidatorFetcher implements IValidatorResourceFetcher {
|
||||||
pidMap.put(pid+"|"+ver, null);
|
pidMap.put(pid+"|"+ver, null);
|
||||||
}
|
}
|
||||||
if (pi != null) {
|
if (pi != null) {
|
||||||
|
context.loadFromPackage(pi, null);
|
||||||
return pi.hasCanonical(url);
|
return pi.hasCanonical(url);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,4 +251,12 @@ public class StandAloneValidatorFetcher implements IValidatorResourceFetcher {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void findResource(String url) {
|
||||||
|
try {
|
||||||
|
resolveURL(null, null, url, null);
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -246,7 +246,9 @@ public class ValidationService {
|
||||||
validator.setSecurityChecks(cliContext.isSecurityChecks());
|
validator.setSecurityChecks(cliContext.isSecurityChecks());
|
||||||
validator.setCrumbTrails(cliContext.isCrumbTrails());
|
validator.setCrumbTrails(cliContext.isCrumbTrails());
|
||||||
validator.setShowTimes(cliContext.isShowTimes());
|
validator.setShowTimes(cliContext.isShowTimes());
|
||||||
validator.setFetcher(new StandAloneValidatorFetcher(validator.getPcm(), validator.getContext(), validator));
|
StandAloneValidatorFetcher fetcher = new StandAloneValidatorFetcher(validator.getPcm(), validator.getContext(), validator);
|
||||||
|
validator.setFetcher(fetcher);
|
||||||
|
validator.getContext().setLocator(fetcher);
|
||||||
validator.getBundleValidationRules().addAll(cliContext.getBundleValidationRules());
|
validator.getBundleValidationRules().addAll(cliContext.getBundleValidationRules());
|
||||||
TerminologyCache.setNoCaching(cliContext.isNoInternalCaching());
|
TerminologyCache.setNoCaching(cliContext.isNoInternalCaching());
|
||||||
validator.prepare(); // generate any missing snapshots
|
validator.prepare(); // generate any missing snapshots
|
||||||
|
|
|
@ -1052,6 +1052,9 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
|
||||||
res = false;
|
res = false;
|
||||||
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, vr.getMessage());
|
txWarning(errors, vr.getTxLink(), IssueType.CODEINVALID, element.line(), element.col(), path, false, vr.getMessage());
|
||||||
} else {
|
} else {
|
||||||
|
if (binding.getStrength() == BindingStrength.EXTENSIBLE) {
|
||||||
|
removeTrackedMessagesForLocation(errors, element, path);
|
||||||
|
}
|
||||||
res = false;
|
res = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
2
pom.xml
2
pom.xml
|
@ -19,7 +19,7 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<hapi_fhir_version>5.1.0</hapi_fhir_version>
|
<hapi_fhir_version>5.1.0</hapi_fhir_version>
|
||||||
<validator_test_case_version>1.1.62</validator_test_case_version>
|
<validator_test_case_version>1.1.63-SNAPSHOT</validator_test_case_version>
|
||||||
<junit_jupiter_version>5.7.1</junit_jupiter_version>
|
<junit_jupiter_version>5.7.1</junit_jupiter_version>
|
||||||
<junit_platform_launcher_version>1.7.1</junit_platform_launcher_version>
|
<junit_platform_launcher_version>1.7.1</junit_platform_launcher_version>
|
||||||
<maven_surefire_version>3.0.0-M4</maven_surefire_version>
|
<maven_surefire_version>3.0.0-M4</maven_surefire_version>
|
||||||
|
|
Loading…
Reference in New Issue