diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java index 02e66bde2..044735405 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/conformance/ProfileUtilities.java @@ -871,15 +871,25 @@ public class ProfileUtilities extends TranslatingUtilities { if (outcome.getType().size() == 0) { throw new DefinitionException(context.formatMessage(I18nConstants._HAS_NO_CHILDREN__AND_NO_TYPES_IN_PROFILE_, diffMatches.get(0).getPath(), differential.getElement().get(diffCursor).getPath(), profileName)); } + boolean nonExtension = false; if (outcome.getType().size() > 1) { for (TypeRefComponent t : outcome.getType()) { - if (!t.getWorkingCode().equals("Reference")) - throw new DefinitionException(context.formatMessage(I18nConstants._HAS_CHILDREN__AND_MULTIPLE_TYPES__IN_PROFILE_, diffMatches.get(0).getPath(), differential.getElement().get(diffCursor).getPath(), typeCode(outcome.getType()), profileName)); + if (!t.getWorkingCode().equals("Reference")) { + for (ElementDefinition ed : diffMatches) { + if (ed != diffMatches.get(0) && !ed.getPath().endsWith(".extension")) { + nonExtension = true; + } + } + } } } - StructureDefinition dt = getProfileForDataType(outcome.getType().get(0)); - if (dt == null) + if (nonExtension) { + throw new DefinitionException(context.formatMessage(I18nConstants._HAS_CHILDREN__AND_MULTIPLE_TYPES__IN_PROFILE_, cpath, differential.getElement().get(diffCursor).getPath(), typeCode(outcome.getType()), profileName)); + } + StructureDefinition dt = outcome.getType().size() > 1 ? context.fetchTypeDefinition("Element") : getProfileForDataType(outcome.getType().get(0)); + if (dt == null) { throw new DefinitionException(context.formatMessage(I18nConstants.UNKNOWN_TYPE__AT_, outcome.getType().get(0), diffMatches.get(0).getPath())); + } contextName = dt.getUrl(); int start = diffCursor; while (differential.getElement().size() > diffCursor && pathStartsWith(differential.getElement().get(diffCursor).getPath(), cpath+".")) @@ -3229,8 +3239,9 @@ public class ProfileUtilities extends TranslatingUtilities { list.add(0, root); } } - if (diff) + if (diff) { insertMissingSparseElements(list); + } genElement(defFile == null ? null : defFile+"#", gen, model.getRows(), list.get(0), list, profiles, diff, profileBaseFileName, null, snapshot, corePath, imagePath, true, logicalModel, profile.getDerivation() == TypeDerivationRule.CONSTRAINT && usesMustSupport(list), allInvariants, null); try { return gen.generate(model, imagePath, 0, outputTracker); @@ -3251,16 +3262,31 @@ public class ProfileUtilities extends TranslatingUtilities { } if (!(isSibling(pathCurrent, pathLast, firstDiff) || isChild(pathCurrent, pathLast, firstDiff))) { // now work backwards down to lastMatch inserting missing path nodes - for (int index = pathCurrent.length-2; index >= firstDiff; index--) { - ElementDefinition root = new ElementDefinition().setPath(makePath(pathCurrent, index)); - root.setId(root.getPath()); - list.add(i, root); + ElementDefinition parent = findParent(list, i, list.get(i).getPath()); + int parentDepth = Utilities.charCount(parent.getPath(), '.')+1; + int childDepth = Utilities.charCount(list.get(i).getPath(), '.')+1; + if (childDepth > parentDepth + 1) { + String basePath = parent.getPath(); + String baseId = parent.getId(); + for (int index = parentDepth; index >= firstDiff; index--) { + String mtail = makeTail(pathCurrent, parentDepth, index); + ElementDefinition root = new ElementDefinition().setPath(basePath+"."+mtail); + root.setId(baseId+"."+mtail); + list.add(i, root); + } } } i++; } } + private ElementDefinition findParent(List list, int i, String path) { + while (i > 0 && !path.startsWith(list.get(i).getPath()+".")) { + i--; + } + return list.get(i); + } + private boolean isSibling(String[] pathCurrent, String[] pathLast, int firstDiff) { return pathCurrent.length == pathLast.length && firstDiff == pathCurrent.length-1; } @@ -3270,6 +3296,13 @@ public class ProfileUtilities extends TranslatingUtilities { return pathCurrent.length == pathLast.length+1 && firstDiff == pathLast.length; } + private String makeTail(String[] pathCurrent, int start, int index) { + CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder("."); + for (int i = start; i <= index; i++) { + b.append(pathCurrent[i]); + } + return b.toString(); + } private String makePath(String[] pathCurrent, int index) { CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder("."); diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java index ab8eda2f4..aff5485de 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/elementmodel/Element.java @@ -542,7 +542,7 @@ public class Element extends Base { return null; Element result = null; for (Element child : children) { - if (child.getName().equals(name)) { + if (child.getName().equals(name) || (child.getName().startsWith(name) && child.getProperty().getDefinition().isChoice())) { if (result == null) result = child; else @@ -883,5 +883,33 @@ public class Element extends Base { return null; } + public Base getExtensionValue(String url) { + if (children != null) { + for (Element child : children) { + if (Utilities.existsInList(child.getName(), "extension", "modifierExtension")) { + String u = child.getChildValue("url"); + if (url.equals(u)) { + return child.getNamedChild("value"); + } + } + } + } + return null; + } + + public boolean hasExtension(String url) { + if (children != null) { + for (Element child : children) { + if (Utilities.existsInList(child.getName(), "extension", "modifierExtension")) { + String u = child.getChildValue("url"); + if (url.equals(u)) { + return true; + } + } + } + } + return false; + } + } \ No newline at end of file diff --git a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ToolingExtensions.java b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ToolingExtensions.java index 171befe7e..dfabaa430 100644 --- a/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ToolingExtensions.java +++ b/org.hl7.fhir.r5/src/main/java/org/hl7/fhir/r5/utils/ToolingExtensions.java @@ -404,6 +404,15 @@ public class ToolingExtensions { return ((BooleanType) ex.getValue()).getValue(); } + public static boolean readBoolExtension(Element e, String uri) { + Extension ex = ExtensionHelper.getExtension(e, uri); + if (ex == null) + return false; + if (!(ex.getValue() instanceof BooleanType)) + return false; + return ((BooleanType) ex.getValue()).getValue(); + } + public static boolean findBooleanExtension(DomainResource c, String uri) { Extension ex = ExtensionHelper.getExtension(c, uri); if (ex == null)