From 884bfbeed5dfa04c26fe5100a60a4fa64d6bbe7f Mon Sep 17 00:00:00 2001 From: Michael Lawley Date: Mon, 13 Mar 2017 10:10:04 +1000 Subject: [PATCH] Add ValueSet expansion support, fix profile bugs HapiWorkerContext needed ValueSet expansion support for validation, now that resources are found and loaded. ParserBase had a bug when comparing names (was not looking at IdPart) Profiles had errors in FHIRPaths using invalid $context name --- .../hapi/validation/HapiWorkerContext.java | 30 ++++++++++++++++--- .../dstu2016may/metamodel/ParserBase.java | 26 ++++++++-------- .../profile/profiles-resources.xml | 12 ++++---- .../dstu2016may/profile/profiles-types.xml | 4 +-- 4 files changed, 47 insertions(+), 25 deletions(-) diff --git a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/HapiWorkerContext.java b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/HapiWorkerContext.java index 424565e0b6a..c8287125e33 100644 --- a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/HapiWorkerContext.java +++ b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/HapiWorkerContext.java @@ -31,13 +31,18 @@ import org.hl7.fhir.dstu2016may.model.ValueSet.ConceptReferenceComponent; import org.hl7.fhir.dstu2016may.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.dstu2016may.model.ValueSet.ValueSetExpansionComponent; import org.hl7.fhir.dstu2016may.model.ValueSet.ValueSetExpansionContainsComponent; +import org.hl7.fhir.dstu2016may.terminologies.ValueSetExpander; import org.hl7.fhir.dstu2016may.terminologies.ValueSetExpander.ValueSetExpansionOutcome; +import org.hl7.fhir.dstu2016may.terminologies.ValueSetExpanderFactory; +import org.hl7.fhir.dstu2016may.terminologies.ValueSetExpanderSimple; import org.hl7.fhir.dstu2016may.utils.IWorkerContext; import org.hl7.fhir.dstu2016may.validation.IResourceValidator; import ca.uhn.fhir.context.FhirContext; +import ca.uhn.fhir.rest.server.exceptions.InternalErrorException; +import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException; -public final class HapiWorkerContext implements IWorkerContext { +public final class HapiWorkerContext implements IWorkerContext, ValueSetExpanderFactory { private final FhirContext myCtx; private Map myFetchedResourceCache = new HashMap(); private IValidationSupport myValidationSupport; @@ -201,8 +206,8 @@ public final class HapiWorkerContext implements IWorkerContext { } } } - - + + boolean caseSensitive = true; if (isNotBlank(theSystem)) { CodeSystem system = fetchCodeSystem(theSystem); @@ -259,10 +264,27 @@ public final class HapiWorkerContext implements IWorkerContext { return new ValidationResult(IssueSeverity.ERROR, "Unknown code[" + theCode + "] in system[" + theSystem + "]"); } + @Override + public ValueSetExpander getExpander() { + ValueSetExpanderSimple retVal = new ValueSetExpanderSimple(this, this); + return retVal; + } @Override public ValueSetExpansionOutcome expandVS(ValueSet theSource, boolean theCacheOk) { - throw new UnsupportedOperationException(); + ValueSetExpansionOutcome vso; + try { + vso = getExpander().expand(theSource); + } catch (InvalidRequestException e) { + throw e; + } catch (Exception e) { + throw new InternalErrorException(e); + } + if (vso.getError() != null) { + throw new InvalidRequestException(vso.getError()); + } else { + return vso; + } } @Override diff --git a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/metamodel/ParserBase.java b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/metamodel/ParserBase.java index b190cafd4a3..a60470196c2 100644 --- a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/metamodel/ParserBase.java +++ b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/metamodel/ParserBase.java @@ -25,13 +25,13 @@ import org.hl7.fhir.utilities.Utilities; public abstract class ParserBase { interface IErrorNotifier { - + } public enum ValidationPolicy { NONE, QUICK, EVERYTHING } public static boolean isPrimitive(String code) { - return Utilities.existsInList(code, - "xhtml", "boolean", "integer", "string", "decimal", "uri", "base64Binary", "instant", "date", "dateTime", + return Utilities.existsInList(code, + "xhtml", "boolean", "integer", "string", "decimal", "uri", "base64Binary", "instant", "date", "dateTime", "time", "code", "oid", "id", "markdown", "unsignedInt", "positiveInt", "xhtml", "base64Binary"); } @@ -49,12 +49,12 @@ public abstract class ParserBase { this.policy = policy; this.errors = errors; } - + public abstract Element parse(InputStream stream) throws Exception; public abstract void compose(Element e, OutputStream destination, OutputStyle style, String base) throws Exception; - + public void logError(int line, int col, String path, IssueType type, String message, IssueSeverity level) throws FHIRFormatError { if (policy == ValidationPolicy.EVERYTHING) { ValidationMessage msg = new ValidationMessage(Source.InstanceValidator, type, line, col, path, message, level); @@ -62,8 +62,8 @@ public abstract class ParserBase { } else if (level == IssueSeverity.FATAL || (level == IssueSeverity.ERROR && policy == ValidationPolicy.QUICK)) throw new FHIRFormatError(message+String.format(" at line %d col %d", line, col)); } - - + + protected StructureDefinition getDefinition(int line, int col, String ns, String name) throws FHIRFormatError { if (ns == null) { logError(line, col, name, IssueType.STRUCTURE, "This cannot be parsed as a FHIR object (no namespace)", IssueSeverity.FATAL); @@ -74,7 +74,7 @@ public abstract class ParserBase { return null; } for (StructureDefinition sd : context.allStructures()) { - if (name.equals(sd.getId())) { + if (name.equals(sd.getIdElement().getIdPart())) { if((ns == null || ns.equals(FormatUtilities.FHIR_NS)) && !ToolingExtensions.hasExtension(sd, "http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace")) return sd; String sns = ToolingExtensions.readStringExtension(sd, "http://hl7.org/fhir/StructureDefinition/elementdefinition-namespace"); @@ -92,7 +92,7 @@ public abstract class ParserBase { return null; } for (StructureDefinition sd : context.allStructures()) { - if (name.equals(sd.getId())) { + if (name.equals(sd.getIdElement().getIdPart())) { return sd; } } @@ -100,7 +100,7 @@ public abstract class ParserBase { return null; } - + protected List getChildProperties(Property property, String elementName, String statedType) throws DefinitionException { ElementDefinition ed = property.getDefinition(); StructureDefinition sd = property.getStructure(); @@ -128,12 +128,12 @@ public abstract class ParserBase { if (t == null && ToolingExtensions.hasExtension(ed, "http://hl7.org/fhir/StructureDefinition/elementdefinition-defaultype")) t = ToolingExtensions.readStringExtension(ed, "http://hl7.org/fhir/StructureDefinition/elementdefinition-defaultype"); boolean ok = false; - for (TypeRefComponent tr : ed.getType()) - if (tr.getCode().equals(t)) + for (TypeRefComponent tr : ed.getType()) + if (tr.getCode().equals(t)) ok = true; if (!ok) throw new DefinitionException("Type '"+t+"' is not an acceptable type for '"+elementName+"' on property "+property.getDefinition().getPath()); - + } else { t = elementName.substring(tail(ed.getPath()).length() - 3); if (isPrimitive(lowFirst(t))) diff --git a/hapi-fhir-validation-resources-dstu2.1/src/main/resources/org/hl7/fhir/dstu2016may/profile/profiles-resources.xml b/hapi-fhir-validation-resources-dstu2.1/src/main/resources/org/hl7/fhir/dstu2016may/profile/profiles-resources.xml index 1fbd3b8c958..7b6c50eebb0 100644 --- a/hapi-fhir-validation-resources-dstu2.1/src/main/resources/org/hl7/fhir/dstu2016may/profile/profiles-resources.xml +++ b/hapi-fhir-validation-resources-dstu2.1/src/main/resources/org/hl7/fhir/dstu2016may/profile/profiles-resources.xml @@ -20460,7 +20460,7 @@ - + @@ -20649,7 +20649,7 @@ - + @@ -121071,7 +121071,7 @@ - + @@ -122307,7 +122307,7 @@ - + @@ -154515,7 +154515,7 @@ - + @@ -155580,7 +155580,7 @@ - + diff --git a/hapi-fhir-validation-resources-dstu2.1/src/main/resources/org/hl7/fhir/dstu2016may/profile/profiles-types.xml b/hapi-fhir-validation-resources-dstu2.1/src/main/resources/org/hl7/fhir/dstu2016may/profile/profiles-types.xml index 12452becea4..64d4561ddf0 100644 --- a/hapi-fhir-validation-resources-dstu2.1/src/main/resources/org/hl7/fhir/dstu2016may/profile/profiles-types.xml +++ b/hapi-fhir-validation-resources-dstu2.1/src/main/resources/org/hl7/fhir/dstu2016may/profile/profiles-types.xml @@ -4681,7 +4681,7 @@ - + @@ -4779,7 +4779,7 @@ - +