diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java index 4459a2525..f151d042a 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/Utilities.java @@ -1912,6 +1912,16 @@ public class Utilities { '\u2028', '\u2029', '\u202F', '\u205F', '\u3000'); } + public static boolean stringsEqual(String s1, String s2) { + if (s1 == null && s2 == null) { + return true; + } else if (s1 == null) { + return false; + } else { + return s1.equals(s2); + } + } + //public static boolean !isWhitespace(String s) { //boolean ok = true; //for (int i = 0; i < s.length(); i++) diff --git a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java index f5288f393..699bade3a 100644 --- a/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java +++ b/org.hl7.fhir.utilities/src/main/java/org/hl7/fhir/utilities/i18n/I18nConstants.java @@ -832,6 +832,7 @@ public class I18nConstants { public static final String SM_TARGET_TRANSLATE_BINDING_VS_TARGET = "SM_TARGET_TRANSLATE_BINDING_VS_TARGET"; public static final String SM_TARGET_TRANSLATE_BINDING_VSE_TARGET = "SM_TARGET_TRANSLATE_BINDING_VSE_TARGET"; public static final String SM_TARGET_TRANSLATE_BINDING_TARGET_WRONG = "SM_TARGET_TRANSLATE_BINDING_TARGET_WRONG"; + public static final String SM_DEPENDENT_PARAM_TYPE_MISMATCH_DUPLICATE = "SM_DEPENDENT_PARAM_TYPE_MISMATCH_DUPLICATE"; public static final String CONCEPTMAP_GROUP_SOURCE_MISSING = "CONCEPTMAP_GROUP_SOURCE_MISSING"; public static final String CONCEPTMAP_GROUP_SOURCE_UNKNOWN = "CONCEPTMAP_GROUP_SOURCE_UNKNOWN"; public static final String CONCEPTMAP_GROUP_TARGET_MISSING = "CONCEPTMAP_GROUP_TARGET_MISSING"; diff --git a/org.hl7.fhir.utilities/src/main/resources/Messages.properties b/org.hl7.fhir.utilities/src/main/resources/Messages.properties index a540fe323..901be98f7 100644 --- a/org.hl7.fhir.utilities/src/main/resources/Messages.properties +++ b/org.hl7.fhir.utilities/src/main/resources/Messages.properties @@ -895,5 +895,5 @@ CONCEPTMAP_GROUP_TARGET_PROPERTY_TYPE_MISMATCH = The type of this property shoul CONCEPTMAP_GROUP_TARGET_PROPERTY_TYPE_NO_SYSTEM = Since no system has been provided, a plain code cannot be used CONCEPTMAP_GROUP_TARGET_PROPERTY_CODE_INVALID = The code {0} is invalid in the system {1} CONCEPTMAP_GROUP_TARGET_PROPERTY_TYPE_UNKNOWN_SYSTEM = The system {0} is unknown, so code values can''t be checked - +SM_DEPENDENT_PARAM_TYPE_MISMATCH_DUPLICATE = The group {0} has already been used with different parameters, so the type checking may be incorrect (other = [{1}]; this = [{2}]) \ No newline at end of file diff --git a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureMapValidator.java b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureMapValidator.java index 1a296f910..b31915f38 100644 --- a/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureMapValidator.java +++ b/org.hl7.fhir.validation/src/main/java/org/hl7/fhir/validation/instance/type/StructureMapValidator.java @@ -176,6 +176,22 @@ public class StructureMapValidator extends BaseValidator { return null; } + public String summary() { + return mode+" "+getWorkingType()+" "+name; + } + + public boolean matches(VariableDefn other) { + if (!(name.equals(other.name) && mode.equals(other.mode))) { + return false; + } + if (sd == null && other.sd == null) { + return true; + } else if (sd == null || other.sd == null) { + return false; + } + return sd.getUrl().equals(other.sd.getUrl()) && ed.getPath().equals(other.ed.getPath()) && Utilities.stringsEqual(type, other.type); + } + } public class VariableSet { @@ -234,6 +250,26 @@ public class StructureMapValidator extends BaseValidator { vn.name = pname; list.add(vn); } + + public String summary() { + CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder(); + for (VariableDefn v : list) { + b.append(v.summary()); + } + return b.toString(); + } + + public boolean matches(VariableSet other) { + if (list.size() != other.list.size()) { + return false; + } + for (int i = 0; i < list.size(); i++) { + if (!list.get(i).matches(other.list.get(i))) { + return false; + } + } + return true; + } } private static final boolean SOURCE = true; @@ -485,7 +521,7 @@ public class StructureMapValidator extends BaseValidator { cc++; } - // process the targets + // process the nested rules List rules = rule.getChildrenByName("rule"); cc = 0; for (Element child : rules) { @@ -901,7 +937,23 @@ public class StructureMapValidator extends BaseValidator { } else { for (ElementDefinition t : children) { if (t.getNameBase().equals(element)) { - result.add(new ElementDefinitionSource(sd, t)); + if (t.hasContentReference()) { + String url = t.getContentReference().substring(0, t.getContentReference().indexOf("#")); + String path = t.getContentReference().substring(t.getContentReference().indexOf("#")+1); + StructureDefinition sdt = "".equals(url) || url.equals(sd.getUrl()) ? sd : context.fetchResource(StructureDefinition.class, url); + if (sdt == null) { + throw new Error("Unable to resolve "+url); + } else { + ElementDefinition t2 = sdt.getSnapshot().getElementByPath(path); + if (t2 == null) { + throw new Error("Unable to resolve "+path+" in "+url); + } else { + result.add(new ElementDefinitionSource(sdt, t2)); + } + } + } else { + result.add(new ElementDefinitionSource(sd, t)); + } } } } @@ -987,7 +1039,8 @@ public class StructureMapValidator extends BaseValidator { if (ok && grp.hasUserData("element.source")) { Element g = (Element) grp.getUserData("element.source"); if (g.hasUserData("structuremap.parameters")) { - throw new Error("bang! - this situation is not handled"); + VariableSet pvars = (VariableSet) g.getUserData("structuremap.parameters"); + rule(errors, "2023-03-01", IssueType.INVALID, dependent.line(), dependent.col(), stack.getLiteralPath(), pvars.matches(lvars), I18nConstants.SM_DEPENDENT_PARAM_TYPE_MISMATCH_DUPLICATE, grp.getName(), pvars.summary(), lvars.summary()); } else { g.setUserData("structuremap.parameters", lvars); }