Skip to content

Commit b0daf66

Browse files
Merge pull request #1140 from hapifhir/gg-202302-map-validation-3
structuremap validation and invariant fixes for forthcoming R5 release
2 parents a62c868 + 4c30621 commit b0daf66

File tree

9 files changed

+446
-115
lines changed

9 files changed

+446
-115
lines changed

org.hl7.fhir.convertors/src/main/java/org/hl7/fhir/convertors/loaders/loaderR5/BaseLoaderR5.java

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.hl7.fhir.r5.model.ValueSet;
1919
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
2020
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
21+
import org.hl7.fhir.utilities.Utilities;
2122
import org.hl7.fhir.utilities.VersionUtilities;
2223
import org.hl7.fhir.utilities.npm.NpmPackage;
2324

@@ -115,6 +116,7 @@ protected void doPatchUrls(Resource resource) {
115116
cr.setUrl(patchUrl(cr.getUrl(), cr.fhirType()));
116117
if (cr instanceof StructureDefinition) {
117118
StructureDefinition sd = (StructureDefinition) cr;
119+
sd.setBaseDefinition(patchUrl(sd.getBaseDefinition(), sd.fhirType()));
118120
new ProfileUtilities(null, null, null, null).setIds(sd, false);
119121
sd.addExtension().setUrl(URL_ELEMENT_DEF_NAMESPACE).setValue(new UriType(URL_BASE));
120122
for (ElementDefinition ed : sd.getSnapshot().getElement())
@@ -152,6 +154,9 @@ private void patchUrls(OperationDefinitionParameterComponent param) {
152154

153155
private void patchUrl(ElementDefinition ed) {
154156
for (TypeRefComponent tr : ed.getType()) {
157+
if (!Utilities.isAbsoluteUrl(tr.getCode())) {
158+
tr.setCode(URL_BASE+versionString()+"/StructureDefinition/"+tr.getCode());
159+
}
155160
for (CanonicalType s : tr.getTargetProfile()) {
156161
s.setValue(patchUrl(s.getValue(), "StructureDefinitino"));
157162
}

org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -292,9 +292,21 @@ public String getChildValue(String name) {
292292
if (name.equals(child.getName()))
293293
return child.getValue();
294294
}
295+
for (Element child : children) {
296+
if (name.equals(child.getNameBase()))
297+
return child.getValue();
298+
}
295299
return null;
296300
}
297301

302+
private String getNameBase() {
303+
if (property.isChoice()) {
304+
return property.getName().replace("[x]", "");
305+
} else {
306+
return getName();
307+
}
308+
}
309+
298310
public void setChildValue(String name, String value) {
299311
if (children == null)
300312
children = new ArrayList<Element>();
@@ -543,6 +555,16 @@ public Element makeElement(String name) throws FHIRException {
543555
Element ne = new Element(name, p);
544556
children.add(ne);
545557
return ne;
558+
} else if (p.getDefinition().isChoice() && name.startsWith(p.getName().replace("[x]", ""))) {
559+
String type = name.substring(p.getName().length()-3);
560+
if (new ContextUtilities(property.getContext()).isPrimitiveDatatype(Utilities.uncapitalize(type))) {
561+
type = Utilities.uncapitalize(type);
562+
}
563+
Element ne = new Element(name, p);
564+
ne.setType(type);
565+
children.add(ne);
566+
return ne;
567+
546568
}
547569
}
548570

org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/FmlParser.java

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -354,6 +354,10 @@ private void parseRule(Element map, Element context, FHIRLexer lexer, boolean ne
354354
rule.forceElement("source").makeElement("variable").setValue(StructureMapUtilities.AUTO_VAR_NAME);
355355
rule.forceElement("target").makeElement("variable").setValue(StructureMapUtilities.AUTO_VAR_NAME);
356356
rule.forceElement("target").makeElement("transform").setValue(StructureMapTransform.CREATE.toCode());
357+
Element dep = rule.forceElement("dependent");
358+
dep.makeElement("name").setValue(StructureMapUtilities.DEF_GROUP_NAME);
359+
dep.makeElement("parameter").makeElement("valueId").setValue(StructureMapUtilities.AUTO_VAR_NAME);
360+
dep.makeElement("parameter").makeElement("valueId").setValue(StructureMapUtilities.AUTO_VAR_NAME);
357361
// no dependencies - imply what is to be done based on types
358362
}
359363
if (newFmt) {
@@ -480,7 +484,7 @@ private void parseTarget(Element rule, FHIRLexer lexer) throws FHIRException {
480484
loc = lexer.getCurrentLocation();
481485
ExpressionNode node = fpe.parse(lexer);
482486
target.setUserData(StructureMapUtilities.MAP_EXPRESSION, node);
483-
target.addElement("parameter").markLocation(loc).setValue(node.toString());
487+
target.addElement("parameter").markLocation(loc).makeElement("valueString").setValue(node.toString());
484488
lexer.token(")");
485489
} else if (lexer.hasToken("(")) {
486490
target.makeElement("transform").markLocation(loc).setValue(name);
@@ -529,11 +533,11 @@ private void parseTarget(Element rule, FHIRLexer lexer) throws FHIRException {
529533

530534
private void parseParameter(Element ref, FHIRLexer lexer) throws FHIRLexerException, FHIRFormatError {
531535
if (!lexer.isConstant()) {
532-
ref.addElement("parameter").markLocation(lexer.getCurrentLocation()).setType("string").setValue(lexer.take());
536+
ref.addElement("parameter").markLocation(lexer.getCurrentLocation()).makeElement("valueId").setValue(lexer.take());
533537
} else if (lexer.isStringConstant())
534-
ref.addElement("parameter").markLocation(lexer.getCurrentLocation()).setType("string").setValue(lexer.readConstant("??"));
538+
ref.addElement("parameter").markLocation(lexer.getCurrentLocation()).makeElement("valueString").setValue(lexer.readConstant("??"));
535539
else {
536-
ref.addElement("parameter").markLocation(lexer.getCurrentLocation()).setType("string").setValue(readConstant(lexer.take(), lexer));
540+
ref.addElement("parameter").markLocation(lexer.getCurrentLocation()).makeElement("valueString").setValue(readConstant(lexer.take(), lexer));
537541
}
538542
}
539543

org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/structuremap/StructureMapUtilities.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,6 +104,7 @@ public class StructureMapUtilities {
104104
public static final String MAP_EXPRESSION = "map.transform.expression";
105105
private static final boolean RENDER_MULTIPLE_TARGETS_ONELINE = true;
106106
public static final String AUTO_VAR_NAME = "vvv";
107+
public static final String DEF_GROUP_NAME = "DefaultMappingGroupAnonymousAlias";
107108

108109
private final IWorkerContext worker;
109110
private final FHIRPathEngine fpe;

org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -782,7 +782,8 @@ public class I18nConstants {
782782
public static final String SM_GROUP_INPUT_NO_TYPE = "SM_GROUP_INPUT_NO_TYPE";
783783
public static final String SM_GROUP_INPUT_TYPE_NOT_DECLARED = "SM_GROUP_INPUT_TYPE_NOT_DECLARED";
784784
public static final String SM_GROUP_INPUT_MODE_MISMATCH = "SM_GROUP_INPUT_MODE_MISMATCH";
785-
public static final String SM_GROUP_INPUT_TYPE_UNKNOWN = "SM_GROUP_INPUT_TYPE_UNKNOWN";
785+
public static final String SM_GROUP_INPUT_TYPE_UNKNOWN_STRUCTURE = "SM_GROUP_INPUT_TYPE_UNKNOWN_STRUCTURE";
786+
public static final String SM_GROUP_INPUT_TYPE_UNKNOWN_TYPE = "SM_GROUP_INPUT_TYPE_UNKNOWN_TYPE";
786787
public static final String SM_SOURCE_CONTEXT_UNKNOWN = "SM_SOURCE_CONTEXT_UNKNOWN";
787788
public static final String SM_SOURCE_PATH_INVALID = "SM_SOURCE_PATH_INVALID";
788789
public static final String SM_RULE_SOURCE_MIN_REDUNDANT = "SM_RULE_SOURCE_MIN_REDUNDANT";
@@ -804,6 +805,13 @@ public class I18nConstants {
804805
public static final String SM_TARGET_TRANSFORM_PARAM_UNPROCESSIBLE = "SM_TARGET_TRANSFORM_PARAM_UNPROCESSIBLE";
805806
public static final String SM_TARGET_TRANSFORM_EXPRESSION_ERROR = "SM_TARGET_TRANSFORM_EXPRESSION_ERROR";
806807
public static final String SM_IMPORT_NOT_FOUND = "SM_IMPORT_NOT_FOUND";
808+
public static final String SM_TARGET_TYPE_MULTIPLE_POSSIBLE = "SM_TARGET_TYPE_MULTIPLE_POSSIBLE";
809+
public static final String SM_DEPENDENT_PARAM_MODE_MISMATCH = "SM_DEPENDENT_PARAM_MODE_MISMATCH";
810+
public static final String SM_DEPENDENT_PARAM_TYPE_MISMATCH = "SM_DEPENDENT_PARAM_TYPE_MISMATCH";
811+
public static final String SM_ORPHAN_GROUP = "SM_ORPHAN_GROUP";
812+
public static final String SM_SOURCE_TYPE_NOT_FOUND = "SM_SOURCE_TYPE_NOT_FOUND";
813+
public static final String SM_TARGET_TYPE_NOT_FOUND = "SM_TARGET_TYPE_NOT_FOUND";
814+
public static final String SM_MATCHING_RULEGROUP_NOT_FOUND = "SM_MATCHING_RULEGROUP_NOT_FOUND";
807815
}
808816

809817

org.hl7.fhir.utilities/src/main/resources/Messages.properties

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -830,9 +830,10 @@ SM_NAME_INVALID = The name {0} is not valid
830830
SM_GROUP_INPUT_DUPLICATE = The name {0} is already used
831831
SM_GROUP_INPUT_MODE_INVALID = The group parameter {0} mode {1} isn''t valid
832832
SM_GROUP_INPUT_NO_TYPE = The group parameter {0} has no type, so the paths cannot be validated
833-
SM_GROUP_INPUT_TYPE_NOT_DECLARED = The type {0} was not declared and is unknown
833+
SM_GROUP_INPUT_TYPE_NOT_DECLARED = The type {0} is not declared and is unknown
834834
SM_GROUP_INPUT_MODE_MISMATCH = The type {0} has mode {1} which doesn''t match the structure definition {2}
835-
SM_GROUP_INPUT_TYPE_UNKNOWN = The type {0} which maps to the canonical URL {1} is not known, so the paths cannot be validated
835+
SM_GROUP_INPUT_TYPE_UNKNOWN_STRUCTURE = The type {0} which maps to the canonical URL {1} is not known, so the paths cannot be validated
836+
SM_GROUP_INPUT_TYPE_UNKNOWN_TYPE = The type {0} is not known, so the paths cannot be validated
836837
SM_SOURCE_CONTEXT_UNKNOWN = The source context {0} is not known at this point
837838
SM_SOURCE_PATH_INVALID = The source path {0}.{1} refers to the path {2} which is unknown
838839
SM_RULE_SOURCE_MIN_REDUNDANT = The min value of {0} is redundant since the valid min is {0}
@@ -853,6 +854,15 @@ SM_TARGET_NO_TRANSFORM_NO_CHECKED = When there is no transform, parameters can''
853854
SM_TARGET_TRANSFORM_TYPE_UNPROCESSIBLE = The value of the type parameter could not be processed
854855
SM_TARGET_TRANSFORM_PARAM_UNPROCESSIBLE = The parameter at index {0} could not be processed (type = {1})
855856
SM_TARGET_TRANSFORM_EXPRESSION_ERROR = The FHIRPath expression passed as the evaluate parameter is invalid: {0}
856-
SM_IMPORT_NOT_FOUND = No maps were found to match {0} - validation may be wrong
857+
SM_IMPORT_NOT_FOUND = No maps were found to match {0} - validation may be wrong
858+
SM_TARGET_TYPE_MULTIPLE_POSSIBLE = Multiple types are possible here ({0}) so further type checking is not possible
859+
SM_DEPENDENT_PARAM_MODE_MISMATCH = The parameter {0} refers to the variable {1} but it''s mode is {2} which is not the same as the mode required for the group {3}
860+
SM_DEPENDENT_PARAM_TYPE_MISMATCH = The parameter {0} refers to the variable {1} but it''s type is {2} which is not compatible with the type required for the group {3}
861+
SM_ORPHAN_GROUP = This group is not called from within this mapping script, and does not have types on it's inputs, so type verification is not possible
862+
SM_SOURCE_TYPE_NOT_FOUND = No source type was found, so the default group for this implied dependent rule could not be determined
863+
SM_TARGET_TYPE_NOT_FOUND = No target type was found, so the default group for this implied dependent rule could not be determined
864+
SM_MATCHING_RULEGROUP_NOT_FOUND = Unable to find a default rule for the type pair source={0} and target={1}
865+
866+
857867

858868

org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/InstanceValidator.java

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3774,7 +3774,7 @@ private List<ElementDefinition> getCriteriaForDiscriminator(String path, Element
37743774
}
37753775

37763776
TypedElementDefinition ted = null;
3777-
String fp = FHIRPathExpressionFixer.fixExpr(discriminator, null);
3777+
String fp = FHIRPathExpressionFixer.fixExpr(discriminator, null, context.getVersion());
37783778
ExpressionNode expr = null;
37793779
try {
37803780
expr = fpe.parse(fp);
@@ -4392,7 +4392,7 @@ private boolean sliceMatches(ValidatorHostContext hostContext, Element element,
43924392
}
43934393

43944394
try {
4395-
n = fpe.parse(FHIRPathExpressionFixer.fixExpr(expression.toString(), null));
4395+
n = fpe.parse(FHIRPathExpressionFixer.fixExpr(expression.toString(), null, context.getVersion()));
43964396
} catch (FHIRLexerException e) {
43974397
if (STACK_TRACE) e.printStackTrace();
43984398
throw new FHIRException(context.formatMessage(I18nConstants.PROBLEM_PROCESSING_EXPRESSION__IN_PROFILE__PATH__, expression, profile.getVersionedUrl(), path, e.getMessage()));
@@ -6020,7 +6020,7 @@ private boolean checkInvariants(ValidatorHostContext hostContext, List<Validatio
60206020
}
60216021
List<ValidationMessage> invErrors = null;
60226022
// We key based on inv.expression rather than inv.key because expressions can change in derived profiles and aren't guaranteed to be consistent across profiles.
6023-
String key = FHIRPathExpressionFixer.fixExpr(inv.getExpression(), inv.getKey());
6023+
String key = FHIRPathExpressionFixer.fixExpr(inv.getExpression(), inv.getKey(), context.getVersion());
60246024
if (!invMap.keySet().contains(key)) {
60256025
invErrors = new ArrayList<ValidationMessage>();
60266026
invMap.put(key, invErrors);
@@ -6074,7 +6074,7 @@ public boolean checkInvariant(ValidatorHostContext hostContext, List<ValidationM
60746074
if (n == null) {
60756075
long t = System.nanoTime();
60766076
try {
6077-
String expr = FHIRPathExpressionFixer.fixExpr(inv.getExpression(), inv.getKey());
6077+
String expr = FHIRPathExpressionFixer.fixExpr(inv.getExpression(), inv.getKey(), context.getVersion());
60786078
n = fpe.parse(expr);
60796079
} catch (FHIRException e) {
60806080
rule(errors, NO_RULE_DATE, IssueType.INVARIANT, element.line(), element.col(), path, false, I18nConstants.PROBLEM_PROCESSING_EXPRESSION__IN_PROFILE__PATH__, inv.getExpression(), profile.getVersionedUrl(), path, e.getMessage());
@@ -6285,7 +6285,7 @@ public void checkAllInvariants() {
62856285
try {
62866286
ExpressionNode n = (ExpressionNode) inv.getUserData("validator.expression.cache");
62876287
if (n == null) {
6288-
n = fpe.parse(FHIRPathExpressionFixer.fixExpr(inv.getExpression(), inv.getKey()));
6288+
n = fpe.parse(FHIRPathExpressionFixer.fixExpr(inv.getExpression(), inv.getKey(), context.getVersion()));
62896289
inv.setUserData("validator.expression.cache", n);
62906290
}
62916291
fpe.check(null, sd.getKind() == StructureDefinitionKind.RESOURCE ? sd.getType() : "DomainResource", ed.getPath(), n);

0 commit comments

Comments
 (0)