From 5ef894572662f092ee1b0ba837a46d819f05bf86 Mon Sep 17 00:00:00 2001 From: Michael Lawley Date: Thu, 23 Feb 2017 21:25:35 +1000 Subject: [PATCH 1/3] Correct paths to profiles and valuesets/codesystems --- .../DefaultProfileValidationSupport.java | 22 +++++++++---------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/DefaultProfileValidationSupport.java b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/DefaultProfileValidationSupport.java index e390435ef68..39e9ae0e5f0 100644 --- a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/DefaultProfileValidationSupport.java +++ b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/DefaultProfileValidationSupport.java @@ -72,9 +72,9 @@ public class DefaultProfileValidationSupport implements IValidationSupport { codeSystems = new HashMap(); valueSets = new HashMap(); - loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/instance/model/dstu3/valueset/valuesets.xml"); - loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/instance/model/dstu3/valueset/v2-tables.xml"); - loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/instance/model/dstu3/valueset/v3-codesystems.xml"); + loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/instance/model/dstu2016may/valueset/valuesets.xml"); + loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/instance/model/dstu2016may/valueset/v2-tables.xml"); + loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/instance/model/dstu2016may/valueset/v3-codesystems.xml"); myCodeSystems = codeSystems; myValueSets = valueSets; @@ -91,7 +91,7 @@ public class DefaultProfileValidationSupport implements IValidationSupport { @Override public T fetchResource(FhirContext theContext, Class theClass, String theUri) { Validate.notBlank(theUri, "theUri must not be null or blank"); - + if (theUri.startsWith("http://hl7.org/fhir/StructureDefinition/")) { return (T) fetchStructureDefinition(theContext, theUri); } @@ -210,9 +210,9 @@ public class DefaultProfileValidationSupport implements IValidationSupport { if (structureDefinitions == null) { structureDefinitions = new HashMap(); - loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/instance/model/dstu3/profile/profiles-resources.xml"); - loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/instance/model/dstu3/profile/profiles-types.xml"); - loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/instance/model/dstu3/profile/profiles-others.xml"); + loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/instance/model/dstu2016may/profile/profiles-resources.xml"); + loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/instance/model/dstu2016may/profile/profiles-types.xml"); + loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/instance/model/dstu2016may/profile/profiles-others.xml"); myStructureDefinitions = structureDefinitions; } @@ -227,9 +227,9 @@ public class DefaultProfileValidationSupport implements IValidationSupport { if (cs.hasCaseSensitive()) { caseSensitive = cs.getCaseSensitive(); } - + CodeValidationResult retVal = testIfConceptIsInList(theCode, cs.getConcept(), caseSensitive); - + if (retVal != null) { return retVal; } @@ -243,7 +243,7 @@ public class DefaultProfileValidationSupport implements IValidationSupport { if (theCaseSensitive == false) { code = code.toUpperCase(); } - + return testIfConceptIsInListInner(conceptList, theCaseSensitive, code); } @@ -265,7 +265,7 @@ public class DefaultProfileValidationSupport implements IValidationSupport { break; } } - + return retVal; } From 3623bbca16eb1d3096ee5918cf46f9b03e5b6d30 Mon Sep 17 00:00:00 2001 From: Michael Lawley Date: Thu, 23 Feb 2017 22:16:43 +1000 Subject: [PATCH 2/3] fix rest of path to resources (remove v3-codesystems.xml) --- .../validation/DefaultProfileValidationSupport.java | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/DefaultProfileValidationSupport.java b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/DefaultProfileValidationSupport.java index 39e9ae0e5f0..649d1703d0c 100644 --- a/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/DefaultProfileValidationSupport.java +++ b/hapi-fhir-structures-dstu2.1/src/main/java/org/hl7/fhir/dstu2016may/hapi/validation/DefaultProfileValidationSupport.java @@ -72,9 +72,9 @@ public class DefaultProfileValidationSupport implements IValidationSupport { codeSystems = new HashMap(); valueSets = new HashMap(); - loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/instance/model/dstu2016may/valueset/valuesets.xml"); - loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/instance/model/dstu2016may/valueset/v2-tables.xml"); - loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/instance/model/dstu2016may/valueset/v3-codesystems.xml"); + loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/dstu2016may/valueset/valuesets.xml"); + loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/dstu2016may/valueset/v2-tables.xml"); + loadCodeSystems(theContext, codeSystems, valueSets, "/org/hl7/fhir/dstu2016may/valueset/v3-codesystems.xml"); myCodeSystems = codeSystems; myValueSets = valueSets; @@ -210,9 +210,9 @@ public class DefaultProfileValidationSupport implements IValidationSupport { if (structureDefinitions == null) { structureDefinitions = new HashMap(); - loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/instance/model/dstu2016may/profile/profiles-resources.xml"); - loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/instance/model/dstu2016may/profile/profiles-types.xml"); - loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/instance/model/dstu2016may/profile/profiles-others.xml"); + loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/dstu2016may/profile/profiles-resources.xml"); + loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/dstu2016may/profile/profiles-types.xml"); + loadStructureDefinitions(theContext, structureDefinitions, "/org/hl7/fhir/dstu2016may/profile/profiles-others.xml"); myStructureDefinitions = structureDefinitions; } From 884bfbeed5dfa04c26fe5100a60a4fa64d6bbe7f Mon Sep 17 00:00:00 2001 From: Michael Lawley Date: Mon, 13 Mar 2017 10:10:04 +1000 Subject: [PATCH 3/3] 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 @@ - +