Fix bug not handling slicing/sparse differentials correctly (both snapshot and rendering)

This commit is contained in:
Grahame Grieve 2020-05-20 18:52:11 +10:00
parent f02c9f0e09
commit 4e6c8ba232
3 changed files with 80 additions and 10 deletions

View File

@ -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<ElementDefinition> 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(".");

View File

@ -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;
}
}

View File

@ -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)