Snapshot generation: handle profiles on Bundle.entry.resource properly
This commit is contained in:
parent
2732ef3dd5
commit
139cd561df
|
@ -905,7 +905,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
result.getElement().add(outcome);
|
result.getElement().add(outcome);
|
||||||
baseCursor++;
|
baseCursor++;
|
||||||
diffCursor = differential.getElement().indexOf(diffMatches.get(0))+1;
|
diffCursor = differential.getElement().indexOf(diffMatches.get(0))+1;
|
||||||
if (diffLimit >= diffCursor && outcome.getPath().contains(".") && (isDataType(outcome.getType()) || outcome.hasContentReference())) { // don't want to do this for the root, since that's base, and we're already processing it
|
if (diffLimit >= diffCursor && outcome.getPath().contains(".") && (isDataType(outcome.getType()) || isBaseResource(outcome.getType()) || outcome.hasContentReference())) { // don't want to do this for the root, since that's base, and we're already processing it
|
||||||
if (pathStartsWith(differential.getElement().get(diffCursor).getPath(), diffMatches.get(0).getPath()+".") && !baseWalksInto(base.getElement(), baseCursor)) {
|
if (pathStartsWith(differential.getElement().get(diffCursor).getPath(), diffMatches.get(0).getPath()+".") && !baseWalksInto(base.getElement(), baseCursor)) {
|
||||||
if (outcome.getType().size() > 1) {
|
if (outcome.getType().size() > 1) {
|
||||||
if (outcome.getPath().endsWith("[x]") && !diffMatches.get(0).getPath().endsWith("[x]")) {
|
if (outcome.getPath().endsWith("[x]") && !diffMatches.get(0).getPath().endsWith("[x]")) {
|
||||||
|
@ -1540,6 +1540,18 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private boolean isBaseResource(List<TypeRefComponent> types) {
|
||||||
|
if (types.isEmpty())
|
||||||
|
return false;
|
||||||
|
for (TypeRefComponent type : types) {
|
||||||
|
String t = type.getWorkingCode();
|
||||||
|
if ("Resource".equals(t))
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
public String determineFixedType(List<ElementDefinition> diffMatches, String fixedType, int i) {
|
public String determineFixedType(List<ElementDefinition> diffMatches, String fixedType, int i) {
|
||||||
if (diffMatches.get(i).getType().size() == 0 && diffMatches.get(i).hasSliceName()) {
|
if (diffMatches.get(i).getType().size() == 0 && diffMatches.get(i).hasSliceName()) {
|
||||||
String n = tail(diffMatches.get(i).getPath()).replace("[x]", "");
|
String n = tail(diffMatches.get(i).getPath()).replace("[x]", "");
|
||||||
|
@ -2441,62 +2453,7 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
if (!Base.compareDeep(derived.getType(), base.getType(), false)) {
|
if (!Base.compareDeep(derived.getType(), base.getType(), false)) {
|
||||||
if (base.hasType()) {
|
if (base.hasType()) {
|
||||||
for (TypeRefComponent ts : derived.getType()) {
|
for (TypeRefComponent ts : derived.getType()) {
|
||||||
boolean ok = false;
|
checkTypeDerivation(purl, srcSD, base, derived, ts);
|
||||||
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
|
||||||
String t = ts.getWorkingCode();
|
|
||||||
for (TypeRefComponent td : base.getType()) {;
|
|
||||||
String tt = td.getWorkingCode();
|
|
||||||
b.append(tt);
|
|
||||||
if (td.hasCode() && (tt.equals(t))) {
|
|
||||||
ok = true;
|
|
||||||
}
|
|
||||||
if (!ok) {
|
|
||||||
StructureDefinition sdt = context.fetchTypeDefinition(tt);
|
|
||||||
if (sdt != null && sdt.getAbstract()) {
|
|
||||||
StructureDefinition sdb = context.fetchTypeDefinition(t);
|
|
||||||
while (sdb != null && !ok) {
|
|
||||||
ok = sdb.getType().equals(sdt.getUrl());
|
|
||||||
sdb = context.fetchResource(StructureDefinition.class, sdb.getBaseDefinition());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// work around for old badly generated SDs
|
|
||||||
if (DONT_DO_THIS && Utilities.existsInList(tt, "Extension", "uri", "string", "Element")) {
|
|
||||||
ok = true;
|
|
||||||
}
|
|
||||||
if (DONT_DO_THIS && Utilities.existsInList(tt, "Resource","DomainResource") && pkp.isResource(t)) {
|
|
||||||
ok = true;
|
|
||||||
}
|
|
||||||
if (ok && ts.hasTargetProfile()) {
|
|
||||||
// check that any derived target has a reference chain back to one of the base target profiles
|
|
||||||
for (UriType u : ts.getTargetProfile()) {
|
|
||||||
String url = u.getValue();
|
|
||||||
boolean tgtOk = !td.hasTargetProfile() || td.hasTargetProfile(url);
|
|
||||||
while (url != null && !tgtOk) {
|
|
||||||
StructureDefinition sd = context.fetchResource(StructureDefinition.class, url);
|
|
||||||
if (sd == null) {
|
|
||||||
if (messages != null) {
|
|
||||||
messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, purl+"#"+derived.getPath(), "Connect check whether the target profile "+url+" is valid constraint on the base because it is not known", IssueSeverity.WARNING));
|
|
||||||
}
|
|
||||||
url = null;
|
|
||||||
tgtOk = true; // suppress error message
|
|
||||||
} else {
|
|
||||||
url = sd.getBaseDefinition();
|
|
||||||
tgtOk = td.hasTargetProfile(url);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!tgtOk) {
|
|
||||||
if (messages == null) {
|
|
||||||
throw new FHIRException("Error at "+purl+"#"+derived.getPath()+": The target profile "+url+" is not valid constraint on the base ("+td.getTargetProfile()+")");
|
|
||||||
} else {
|
|
||||||
messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, derived.getPath(), "The target profile "+u.getValue()+" is not a valid constraint on the base ("+td.getTargetProfile()+") at "+derived.getPath(), IssueSeverity.ERROR));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!ok)
|
|
||||||
throw new DefinitionException("StructureDefinition "+purl+" at "+derived.getPath()+": illegal constrained type "+t+" from "+b.toString()+" in "+srcSD.getUrl());
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
base.getType().clear();
|
base.getType().clear();
|
||||||
|
@ -2576,6 +2533,66 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void checkTypeDerivation(String purl, StructureDefinition srcSD, ElementDefinition base, ElementDefinition derived, TypeRefComponent ts) {
|
||||||
|
boolean ok = false;
|
||||||
|
CommaSeparatedStringBuilder b = new CommaSeparatedStringBuilder();
|
||||||
|
String t = ts.getWorkingCode();
|
||||||
|
for (TypeRefComponent td : base.getType()) {;
|
||||||
|
String tt = td.getWorkingCode();
|
||||||
|
b.append(tt);
|
||||||
|
if (td.hasCode() && (tt.equals(t))) {
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
if (!ok) {
|
||||||
|
StructureDefinition sdt = context.fetchTypeDefinition(tt);
|
||||||
|
if (sdt != null && sdt.getAbstract()) {
|
||||||
|
StructureDefinition sdb = context.fetchTypeDefinition(t);
|
||||||
|
while (sdb != null && !ok) {
|
||||||
|
ok = sdb.getType().equals(sdt.getType());
|
||||||
|
sdb = context.fetchResource(StructureDefinition.class, sdb.getBaseDefinition());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// work around for old badly generated SDs
|
||||||
|
if (DONT_DO_THIS && Utilities.existsInList(tt, "Extension", "uri", "string", "Element")) {
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
if (DONT_DO_THIS && Utilities.existsInList(tt, "Resource","DomainResource") && pkp.isResource(t)) {
|
||||||
|
ok = true;
|
||||||
|
}
|
||||||
|
if (ok && ts.hasTargetProfile()) {
|
||||||
|
// check that any derived target has a reference chain back to one of the base target profiles
|
||||||
|
for (UriType u : ts.getTargetProfile()) {
|
||||||
|
String url = u.getValue();
|
||||||
|
boolean tgtOk = !td.hasTargetProfile() || td.hasTargetProfile(url);
|
||||||
|
while (url != null && !tgtOk) {
|
||||||
|
StructureDefinition sd = context.fetchResource(StructureDefinition.class, url);
|
||||||
|
if (sd == null) {
|
||||||
|
if (messages != null) {
|
||||||
|
messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, purl+"#"+derived.getPath(), "Connect check whether the target profile "+url+" is valid constraint on the base because it is not known", IssueSeverity.WARNING));
|
||||||
|
}
|
||||||
|
url = null;
|
||||||
|
tgtOk = true; // suppress error message
|
||||||
|
} else {
|
||||||
|
url = sd.getBaseDefinition();
|
||||||
|
tgtOk = td.hasTargetProfile(url);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!tgtOk) {
|
||||||
|
if (messages == null) {
|
||||||
|
throw new FHIRException("Error at "+purl+"#"+derived.getPath()+": The target profile "+url+" is not valid constraint on the base ("+td.getTargetProfile()+")");
|
||||||
|
} else {
|
||||||
|
messages.add(new ValidationMessage(Source.InstanceValidator, IssueType.BUSINESSRULE, derived.getPath(), "The target profile "+u.getValue()+" is not a valid constraint on the base ("+td.getTargetProfile()+") at "+derived.getPath(), IssueSeverity.ERROR));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!ok) {
|
||||||
|
throw new DefinitionException("StructureDefinition "+purl+" at "+derived.getPath()+": illegal constrained type "+t+" from "+b.toString()+" in "+srcSD.getUrl());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
public void checkTypeOk(ElementDefinition dest, String ft) {
|
public void checkTypeOk(ElementDefinition dest, String ft) {
|
||||||
boolean ok = false;
|
boolean ok = false;
|
||||||
|
@ -4518,8 +4535,9 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
for (ElementDefinitionHolder child : edh.getChildren()) {
|
for (ElementDefinitionHolder child : edh.getChildren()) {
|
||||||
if (child.getChildren().size() > 0) {
|
if (child.getChildren().size() > 0) {
|
||||||
ElementDefinitionComparer ccmp = getComparer(cmp, child);
|
ElementDefinitionComparer ccmp = getComparer(cmp, child);
|
||||||
if (ccmp != null)
|
if (ccmp != null) {
|
||||||
sortElements(child, ccmp, errors);
|
sortElements(child, ccmp, errors);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4530,7 +4548,22 @@ public class ProfileUtilities extends TranslatingUtilities {
|
||||||
ElementDefinition ed = cmp.snapshot.get(child.getBaseIndex());
|
ElementDefinition ed = cmp.snapshot.get(child.getBaseIndex());
|
||||||
ElementDefinitionComparer ccmp;
|
ElementDefinitionComparer ccmp;
|
||||||
if (ed.getType().isEmpty() || isAbstract(ed.getType().get(0).getWorkingCode()) || ed.getType().get(0).getWorkingCode().equals(ed.getPath())) {
|
if (ed.getType().isEmpty() || isAbstract(ed.getType().get(0).getWorkingCode()) || ed.getType().get(0).getWorkingCode().equals(ed.getPath())) {
|
||||||
ccmp = new ElementDefinitionComparer(true, cmp.snapshot, cmp.base, cmp.prefixLength, cmp.name);
|
if (ed.hasType() && "Resource".equals(ed.getType().get(0).getWorkingCode()) && child.getSelf().getType().get(0).hasProfile()) {
|
||||||
|
if (child.getSelf().getType().get(0).getProfile().size() > 1) {
|
||||||
|
throw new FHIRException("Unhandled situation: resource is profiled to more than one option - cannot sort profile");
|
||||||
|
}
|
||||||
|
StructureDefinition profile = context.fetchResource(StructureDefinition.class, child.getSelf().getType().get(0).getProfile().get(0).getValue());
|
||||||
|
while (profile != null && profile.getDerivation() == TypeDerivationRule.CONSTRAINT) {
|
||||||
|
profile = context.fetchResource(StructureDefinition.class, profile.getBaseDefinition());
|
||||||
|
}
|
||||||
|
if (profile==null) {
|
||||||
|
ccmp = null; // this might happen before everything is loaded. And we don't so much care about sot order in this case
|
||||||
|
} else {
|
||||||
|
ccmp = new ElementDefinitionComparer(true, profile.getSnapshot().getElement(), profile.getType(), child.getSelf().getPath().length(), cmp.name);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ccmp = new ElementDefinitionComparer(true, cmp.snapshot, cmp.base, cmp.prefixLength, cmp.name);
|
||||||
|
}
|
||||||
} else if (ed.getType().get(0).getWorkingCode().equals("Extension") && child.getSelf().getType().size() == 1 && child.getSelf().getType().get(0).hasProfile()) {
|
} else if (ed.getType().get(0).getWorkingCode().equals("Extension") && child.getSelf().getType().size() == 1 && child.getSelf().getType().get(0).hasProfile()) {
|
||||||
StructureDefinition profile = context.fetchResource(StructureDefinition.class, child.getSelf().getType().get(0).getProfile().get(0).getValue());
|
StructureDefinition profile = context.fetchResource(StructureDefinition.class, child.getSelf().getType().get(0).getProfile().get(0).getValue());
|
||||||
if (profile==null)
|
if (profile==null)
|
||||||
|
|
Loading…
Reference in New Issue