Merge pull request #1024 from hapifhir/gg-202211-ref-pack

Gg 202211 ref pack
This commit is contained in:
Grahame Grieve 2022-12-01 11:22:55 +11:00 committed by GitHub
commit d6500cbb49
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 852 additions and 531 deletions

View File

@ -483,7 +483,7 @@ public class CapabilityStatementComparer extends CanonicalResourceComparer {
if (sdFocus.getUrl().equals(sdOther.getUrl()) && sdFocus.getVersion().equals(sdOther.getVersion())) { if (sdFocus.getUrl().equals(sdOther.getUrl()) && sdFocus.getVersion().equals(sdOther.getVersion())) {
return true; return true;
} }
sdFocus = ctxt.fetchResource(StructureDefinition.class, sdFocus.getBaseDefinition()); sdFocus = ctxt.fetchResource(StructureDefinition.class, sdFocus.getBaseDefinition(), sdFocus);
} }
return false; return false;
} }

View File

@ -60,12 +60,12 @@ public class ComparisonSession {
return title; return title;
} }
public ResourceComparison compare(String left, String right) throws DefinitionException, FHIRFormatError, IOException { public ResourceComparison compare(String left, Resource leftSource, String right, Resource rightSource) throws DefinitionException, FHIRFormatError, IOException {
CanonicalResource l = (CanonicalResource) contextLeft.fetchResource(Resource.class, left); CanonicalResource l = (CanonicalResource) contextLeft.fetchResource(Resource.class, left, leftSource);
if (l == null) { if (l == null) {
throw new DefinitionException("Unable to resolve "+left); throw new DefinitionException("Unable to resolve "+left);
} }
CanonicalResource r = (CanonicalResource) contextRight.fetchResource(Resource.class, right); CanonicalResource r = (CanonicalResource) contextRight.fetchResource(Resource.class, right, rightSource);
if (r == null) { if (r == null) {
throw new DefinitionException("Unable to resolve "+right); throw new DefinitionException("Unable to resolve "+right);
} }

View File

@ -29,6 +29,7 @@ import org.hl7.fhir.r5.model.Enumeration;
import org.hl7.fhir.r5.model.Enumerations.BindingStrength; import org.hl7.fhir.r5.model.Enumerations.BindingStrength;
import org.hl7.fhir.r5.model.IntegerType; import org.hl7.fhir.r5.model.IntegerType;
import org.hl7.fhir.r5.model.PrimitiveType; import org.hl7.fhir.r5.model.PrimitiveType;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StringType; import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule; import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule;
@ -226,7 +227,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
subset.setMin(intersectMin(leftMin, rightMin)); subset.setMin(intersectMin(leftMin, rightMin));
subset.setMax(intersectMax(leftMax, rightMax, left.current().getMax(), right.current().getMax())); subset.setMax(intersectMax(leftMax, rightMax, left.current().getMax(), right.current().getMax()));
superset.getType().addAll(unionTypes(comp, res, path, left.current().getType(), right.current().getType())); superset.getType().addAll(unionTypes(comp, res, path, left.current().getType(), right.current().getType(), left.getStructure(), right.getStructure()));
subset.getType().addAll(intersectTypes(comp, res, subset, path, left.current().getType(), right.current().getType())); subset.getType().addAll(intersectTypes(comp, res, subset, path, left.current().getType(), right.current().getType()));
rule(comp, res, !subset.getType().isEmpty() || (!left.current().hasType() && !right.current().hasType()), path, "Type Mismatch: "+typeCode(left)+" vs "+typeCode(right)); rule(comp, res, !subset.getType().isEmpty() || (!left.current().hasType() && !right.current().hasType()), path, "Type Mismatch: "+typeCode(left)+" vs "+typeCode(right));
// <fixed[x]><!-- ?? 0..1 * Value must be exactly this --></fixed[x]> // <fixed[x]><!-- ?? 0..1 * Value must be exactly this --></fixed[x]>
@ -234,7 +235,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
superset.setMaxLengthElement(unionMaxLength(left.current().getMaxLength(), right.current().getMaxLength())); superset.setMaxLengthElement(unionMaxLength(left.current().getMaxLength(), right.current().getMaxLength()));
subset.setMaxLengthElement(intersectMaxLength(left.current().getMaxLength(), right.current().getMaxLength())); subset.setMaxLengthElement(intersectMaxLength(left.current().getMaxLength(), right.current().getMaxLength()));
if (left.current().hasBinding() || right.current().hasBinding()) { if (left.current().hasBinding() || right.current().hasBinding()) {
compareBindings(comp, res, subset, superset, path, left.current(), right.current()); compareBindings(comp, res, subset, superset, path, left.current(), right.current(), left.getStructure(), right.getStructure());
} }
// note these are backwards // note these are backwards
superset.getConstraint().addAll(intersectConstraints(path, left.current().getConstraint(), right.current().getConstraint())); superset.getConstraint().addAll(intersectConstraints(path, left.current().getConstraint(), right.current().getConstraint()));
@ -312,10 +313,10 @@ public class ProfileComparer extends CanonicalResourceComparer {
// it's possible that one of these profiles walks into a data type and the other doesn't // it's possible that one of these profiles walks into a data type and the other doesn't
// if it does, we have to load the children for that data into the profile that doesn't // if it does, we have to load the children for that data into the profile that doesn't
// walk into it // walk into it
if (lc.isEmpty() && !rc.isEmpty() && right.current().getType().size() == 1 && left.hasTypeChildren(right.current().getType().get(0))) if (lc.isEmpty() && !rc.isEmpty() && right.current().getType().size() == 1 && left.hasTypeChildren(right.current().getType().get(0), left.getStructure()))
lc = left.childrenFromType(right.current().getType().get(0)); lc = left.childrenFromType(right.current().getType().get(0), right.getStructure());
if (rc.isEmpty() && !lc.isEmpty() && left.current().getType().size() == 1 && right.hasTypeChildren(left.current().getType().get(0))) if (rc.isEmpty() && !lc.isEmpty() && left.current().getType().size() == 1 && right.hasTypeChildren(left.current().getType().get(0), right.getStructure()))
rc = right.childrenFromType(left.current().getType().get(0)); rc = right.childrenFromType(left.current().getType().get(0), left.getStructure());
List<DefinitionNavigator> matchR = new ArrayList<>(); List<DefinitionNavigator> matchR = new ArrayList<>();
for (DefinitionNavigator l : lc) { for (DefinitionNavigator l : lc) {
@ -529,16 +530,16 @@ public class ProfileComparer extends CanonicalResourceComparer {
return Integer.toString(defn.current().getMin())+".."+defn.current().getMax(); return Integer.toString(defn.current().getMin())+".."+defn.current().getMax();
} }
private Collection<? extends TypeRefComponent> unionTypes(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, String path, List<TypeRefComponent> left, List<TypeRefComponent> right) throws DefinitionException, IOException, FHIRFormatError { private Collection<? extends TypeRefComponent> unionTypes(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, String path, List<TypeRefComponent> left, List<TypeRefComponent> right, Resource leftSrc, Resource rightSrc) throws DefinitionException, IOException, FHIRFormatError {
List<TypeRefComponent> result = new ArrayList<TypeRefComponent>(); List<TypeRefComponent> result = new ArrayList<TypeRefComponent>();
for (TypeRefComponent l : left) for (TypeRefComponent l : left)
checkAddTypeUnion(comp, res, path, result, l, session.getContextLeft()); checkAddTypeUnion(comp, res, path, result, l, session.getContextLeft(), leftSrc);
for (TypeRefComponent r : right) for (TypeRefComponent r : right)
checkAddTypeUnion(comp, res, path, result, r, session.getContextRight()); checkAddTypeUnion(comp, res, path, result, r, session.getContextRight(), rightSrc);
return result; return result;
} }
private void checkAddTypeUnion(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, String path, List<TypeRefComponent> results, TypeRefComponent nw, IWorkerContext ctxt) throws DefinitionException, IOException, FHIRFormatError { private void checkAddTypeUnion(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, String path, List<TypeRefComponent> results, TypeRefComponent nw, IWorkerContext ctxt, Resource nwSource) throws DefinitionException, IOException, FHIRFormatError {
boolean pfound = false; boolean pfound = false;
boolean tfound = false; boolean tfound = false;
nw = nw.copy(); nw = nw.copy();
@ -558,8 +559,8 @@ public class ProfileComparer extends CanonicalResourceComparer {
ex.setProfile(null); ex.setProfile(null);
} else { } else {
// both have profiles. Is one derived from the other? // both have profiles. Is one derived from the other?
StructureDefinition sdex = ((IWorkerContext) ex.getUserData("ctxt")).fetchResource(StructureDefinition.class, ex.getProfile().get(0).getValue()); StructureDefinition sdex = ((IWorkerContext) ex.getUserData("ctxt")).fetchResource(StructureDefinition.class, ex.getProfile().get(0).getValue(), nwSource);
StructureDefinition sdnw = ctxt.fetchResource(StructureDefinition.class, nw.getProfile().get(0).getValue()); StructureDefinition sdnw = ctxt.fetchResource(StructureDefinition.class, nw.getProfile().get(0).getValue(), nwSource);
if (sdex != null && sdnw != null) { if (sdex != null && sdnw != null) {
if (sdex.getUrl().equals(sdnw.getUrl())) { if (sdex.getUrl().equals(sdnw.getUrl())) {
pfound = true; pfound = true;
@ -586,8 +587,8 @@ public class ProfileComparer extends CanonicalResourceComparer {
ex.setTargetProfile(null); ex.setTargetProfile(null);
} else { } else {
// both have profiles. Is one derived from the other? // both have profiles. Is one derived from the other?
StructureDefinition sdex = ((IWorkerContext) ex.getUserData("ctxt")).fetchResource(StructureDefinition.class, ex.getTargetProfile().get(0).getValue()); StructureDefinition sdex = ((IWorkerContext) ex.getUserData("ctxt")).fetchResource(StructureDefinition.class, ex.getTargetProfile().get(0).getValue(), nwSource);
StructureDefinition sdnw = ctxt.fetchResource(StructureDefinition.class, nw.getTargetProfile().get(0).getValue()); StructureDefinition sdnw = ctxt.fetchResource(StructureDefinition.class, nw.getTargetProfile().get(0).getValue(), nwSource);
if (sdex != null && sdnw != null) { if (sdex != null && sdnw != null) {
if (matches(sdex, sdnw)) { if (matches(sdex, sdnw)) {
tfound = true; tfound = true;
@ -633,7 +634,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
if (right.getUrl().equals(sd.getBaseDefinition())) { if (right.getUrl().equals(sd.getBaseDefinition())) {
return true; return true;
} }
sd = sd.hasBaseDefinition() ? ctxt.fetchResource(StructureDefinition.class, sd.getBaseDefinition()) : null; sd = sd.hasBaseDefinition() ? ctxt.fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd) : null;
} }
return false; return false;
} }
@ -653,8 +654,8 @@ public class ProfileComparer extends CanonicalResourceComparer {
pfound = true; pfound = true;
c.setProfile(r.getProfile()); c.setProfile(r.getProfile());
} else { } else {
StructureDefinition sdl = resolveProfile(comp, res, path, l.getProfile().get(0).getValue(), comp.getLeft().getName(), session.getContextLeft()); StructureDefinition sdl = resolveProfile(comp, res, path, l.getProfile().get(0).getValue(), comp.getLeft().getName(), session.getContextLeft(), comp.getLeft());
StructureDefinition sdr = resolveProfile(comp, res, path, r.getProfile().get(0).getValue(), comp.getRight().getName(), session.getContextRight()); StructureDefinition sdr = resolveProfile(comp, res, path, r.getProfile().get(0).getValue(), comp.getRight().getName(), session.getContextRight(), comp.getRight());
if (sdl != null && sdr != null) { if (sdl != null && sdr != null) {
if (sdl == sdr) { if (sdl == sdr) {
pfound = true; pfound = true;
@ -680,8 +681,8 @@ public class ProfileComparer extends CanonicalResourceComparer {
tfound = true; tfound = true;
c.setTargetProfile(r.getTargetProfile()); c.setTargetProfile(r.getTargetProfile());
} else { } else {
StructureDefinition sdl = resolveProfile(comp, res, path, l.getTargetProfile().get(0).getValue(), comp.getLeft().getName(), session.getContextLeft()); StructureDefinition sdl = resolveProfile(comp, res, path, l.getTargetProfile().get(0).getValue(), comp.getLeft().getName(), session.getContextLeft(), comp.getLeft());
StructureDefinition sdr = resolveProfile(comp, res, path, r.getTargetProfile().get(0).getValue(), comp.getRight().getName(), session.getContextRight()); StructureDefinition sdr = resolveProfile(comp, res, path, r.getTargetProfile().get(0).getValue(), comp.getRight().getName(), session.getContextRight(), comp.getRight());
if (sdl != null && sdr != null) { if (sdl != null && sdr != null) {
if (matches(sdl, sdr)) { if (matches(sdl, sdr)) {
tfound = true; tfound = true;
@ -721,7 +722,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
return b.toString(); return b.toString();
} }
private boolean compareBindings(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, ElementDefinition subset, ElementDefinition superset, String path, ElementDefinition lDef, ElementDefinition rDef) throws FHIRFormatError, DefinitionException, IOException { private boolean compareBindings(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, ElementDefinition subset, ElementDefinition superset, String path, ElementDefinition lDef, ElementDefinition rDef, Resource leftSrc, Resource rightSrc) throws FHIRFormatError, DefinitionException, IOException {
assert(lDef.hasBinding() || rDef.hasBinding()); assert(lDef.hasBinding() || rDef.hasBinding());
if (!lDef.hasBinding()) { if (!lDef.hasBinding()) {
subset.setBinding(rDef.getBinding()); subset.setBinding(rDef.getBinding());
@ -750,25 +751,25 @@ public class ProfileComparer extends CanonicalResourceComparer {
if (right.getStrength() == BindingStrength.PREFERRED && left.getStrength() == BindingStrength.EXAMPLE && !Base.compareDeep(left.getValueSet(), right.getValueSet(), false)) { if (right.getStrength() == BindingStrength.PREFERRED && left.getStrength() == BindingStrength.EXAMPLE && !Base.compareDeep(left.getValueSet(), right.getValueSet(), false)) {
vm(IssueSeverity.INFORMATION, "Example/preferred bindings differ at "+path+" using binding from "+comp.getRight().getName(), path, comp.getMessages(), res.getMessages()); vm(IssueSeverity.INFORMATION, "Example/preferred bindings differ at "+path+" using binding from "+comp.getRight().getName(), path, comp.getMessages(), res.getMessages());
subset.setBinding(right); subset.setBinding(right);
superset.setBinding(unionBindings(comp, res, path, left, right)); superset.setBinding(unionBindings(comp, res, path, left, right, leftSrc, rightSrc));
} else { } else {
if ((right.getStrength() != BindingStrength.EXAMPLE || left.getStrength() != BindingStrength.EXAMPLE) && !Base.compareDeep(left.getValueSet(), right.getValueSet(), false) ) { if ((right.getStrength() != BindingStrength.EXAMPLE || left.getStrength() != BindingStrength.EXAMPLE) && !Base.compareDeep(left.getValueSet(), right.getValueSet(), false) ) {
vm(IssueSeverity.INFORMATION, "Example/preferred bindings differ at "+path+" using binding from "+comp.getLeft().getName(), path, comp.getMessages(), res.getMessages()); vm(IssueSeverity.INFORMATION, "Example/preferred bindings differ at "+path+" using binding from "+comp.getLeft().getName(), path, comp.getMessages(), res.getMessages());
} }
subset.setBinding(left); subset.setBinding(left);
superset.setBinding(unionBindings(comp, res, path, left, right)); superset.setBinding(unionBindings(comp, res, path, left, right, leftSrc, rightSrc));
} }
return true; return true;
} }
// if either of them are extensible/required, then it wins // if either of them are extensible/required, then it wins
if (isPreferredOrExample(left)) { if (isPreferredOrExample(left)) {
subset.setBinding(right); subset.setBinding(right);
superset.setBinding(unionBindings(comp, res, path, left, right)); superset.setBinding(unionBindings(comp, res, path, left, right, leftSrc, rightSrc));
return true; return true;
} }
if (isPreferredOrExample(right)) { if (isPreferredOrExample(right)) {
subset.setBinding(left); subset.setBinding(left);
superset.setBinding(unionBindings(comp, res, path, left, right)); superset.setBinding(unionBindings(comp, res, path, left, right, leftSrc, rightSrc));
return true; return true;
} }
@ -800,8 +801,8 @@ public class ProfileComparer extends CanonicalResourceComparer {
return true; return true;
} else { } else {
// ok, now we compare the value sets. This may be unresolvable. // ok, now we compare the value sets. This may be unresolvable.
ValueSet lvs = resolveVS(comp.getLeft(), left.getValueSet(), session.getContextLeft()); ValueSet lvs = resolveVS(comp.getLeft(), left.getValueSet(), leftSrc, session.getContextLeft());
ValueSet rvs = resolveVS(comp.getRight(), right.getValueSet(), session.getContextRight()); ValueSet rvs = resolveVS(comp.getRight(), right.getValueSet(), rightSrc, session.getContextRight());
if (lvs == null) { if (lvs == null) {
vm(IssueSeverity.ERROR, "Unable to resolve left value set "+left.getValueSet().toString()+" at "+path, path, comp.getMessages(), res.getMessages()); vm(IssueSeverity.ERROR, "Unable to resolve left value set "+left.getValueSet().toString()+" at "+path, path, comp.getMessages(), res.getMessages());
return true; return true;
@ -885,8 +886,8 @@ public class ProfileComparer extends CanonicalResourceComparer {
return result; return result;
} }
private StructureDefinition resolveProfile(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, String path, String url, String name, IWorkerContext ctxt) { private StructureDefinition resolveProfile(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, String path, String url, String name, IWorkerContext ctxt, Resource urlSource) {
StructureDefinition sd = ctxt.fetchResource(StructureDefinition.class, url); StructureDefinition sd = ctxt.fetchResource(StructureDefinition.class, url, urlSource);
if (sd == null) { if (sd == null) {
ValidationMessage vm = vmI(IssueSeverity.WARNING, "Unable to resolve profile "+url+" in profile "+name, path); ValidationMessage vm = vmI(IssueSeverity.WARNING, "Unable to resolve profile "+url+" in profile "+name, path);
} }
@ -897,7 +898,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
return binding.getStrength() == BindingStrength.EXAMPLE || binding.getStrength() == BindingStrength.PREFERRED; return binding.getStrength() == BindingStrength.EXAMPLE || binding.getStrength() == BindingStrength.PREFERRED;
} }
private ElementDefinitionBindingComponent unionBindings(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, String path, ElementDefinitionBindingComponent left, ElementDefinitionBindingComponent right) throws FHIRFormatError, DefinitionException, IOException { private ElementDefinitionBindingComponent unionBindings(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, String path, ElementDefinitionBindingComponent left, ElementDefinitionBindingComponent right, Resource leftSrc, Resource rightSrc) throws FHIRFormatError, DefinitionException, IOException {
ElementDefinitionBindingComponent union = new ElementDefinitionBindingComponent(); ElementDefinitionBindingComponent union = new ElementDefinitionBindingComponent();
if (left.getStrength().compareTo(right.getStrength()) < 0) if (left.getStrength().compareTo(right.getStrength()) < 0)
union.setStrength(left.getStrength()); union.setStrength(left.getStrength());
@ -907,8 +908,8 @@ public class ProfileComparer extends CanonicalResourceComparer {
if (Base.compareDeep(left.getValueSet(), right.getValueSet(), false)) if (Base.compareDeep(left.getValueSet(), right.getValueSet(), false))
union.setValueSet(left.getValueSet()); union.setValueSet(left.getValueSet());
else { else {
ValueSet lvs = resolveVS(comp.getLeft(), left.getValueSet(), session.getContextLeft()); ValueSet lvs = resolveVS(comp.getLeft(), left.getValueSet(), leftSrc, session.getContextLeft());
ValueSet rvs = resolveVS(comp.getRight(), right.getValueSet(), session.getContextRight()); ValueSet rvs = resolveVS(comp.getRight(), right.getValueSet(), rightSrc, session.getContextRight());
if (lvs != null && rvs != null) { if (lvs != null && rvs != null) {
ValueSetComparison compP = (ValueSetComparison) session.compare(lvs, rvs); ValueSetComparison compP = (ValueSetComparison) session.compare(lvs, rvs);
if (compP != null) { if (compP != null) {
@ -923,10 +924,10 @@ public class ProfileComparer extends CanonicalResourceComparer {
return union; return union;
} }
private ValueSet resolveVS(StructureDefinition ctxtLeft, String vsRef, IWorkerContext ctxt) { private ValueSet resolveVS(StructureDefinition ctxtLeft, String vsRef, Resource src, IWorkerContext ctxt) {
if (vsRef == null) if (vsRef == null)
return null; return null;
return ctxt.fetchResource(ValueSet.class, vsRef); return ctxt.fetchResource(ValueSet.class, vsRef, src);
} }
public XhtmlNode renderStructure(ProfileComparison comp, String id, String prefix, String corePath) throws FHIRException, IOException { public XhtmlNode renderStructure(ProfileComparison comp, String id, String prefix, String corePath) throws FHIRException, IOException {

View File

@ -58,7 +58,6 @@ import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.conformance.ProfileUtilities.SourcedChildDefinitions; import org.hl7.fhir.r5.conformance.ProfileUtilities.SourcedChildDefinitions;
import org.hl7.fhir.r5.conformance.ProfileUtilities.ProfileKnowledgeProvider.BindingResolution; import org.hl7.fhir.r5.conformance.ProfileUtilities.ProfileKnowledgeProvider.BindingResolution;
import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult; import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult;
import org.hl7.fhir.r5.elementmodel.ObjectConverter; import org.hl7.fhir.r5.elementmodel.ObjectConverter;
import org.hl7.fhir.r5.elementmodel.Property; import org.hl7.fhir.r5.elementmodel.Property;
@ -474,7 +473,7 @@ public class ProfileUtilities extends TranslatingUtilities {
} else if (element.getContentReference().contains("#")) { } else if (element.getContentReference().contains("#")) {
// external reference // external reference
String ref = element.getContentReference(); String ref = element.getContentReference();
StructureDefinition sd = context.fetchResource(StructureDefinition.class, ref.substring(0, ref.indexOf("#"))); StructureDefinition sd = context.fetchResource(StructureDefinition.class, ref.substring(0, ref.indexOf("#")), profile);
if (sd == null) { if (sd == null) {
throw new DefinitionException("unable to process contentReference '"+element.getContentReference()+"' on element '"+element.getId()+"'"); throw new DefinitionException("unable to process contentReference '"+element.getContentReference()+"' on element '"+element.getId()+"'");
} }
@ -578,7 +577,7 @@ public class ProfileUtilities extends TranslatingUtilities {
return getChildList(profile, e.getContentReference().substring(1), null, diff); return getChildList(profile, e.getContentReference().substring(1), null, diff);
} else if (e.getContentReference().contains("#")) { } else if (e.getContentReference().contains("#")) {
String url = e.getContentReference().substring(0, e.getContentReference().indexOf("#")); String url = e.getContentReference().substring(0, e.getContentReference().indexOf("#"));
StructureDefinition sd = context.fetchResource(StructureDefinition.class, url); StructureDefinition sd = context.fetchResource(StructureDefinition.class, url, profile);
if (sd == null) { if (sd == null) {
throw new DefinitionException("Unable to find Structure "+url); throw new DefinitionException("Unable to find Structure "+url);
} }
@ -722,7 +721,7 @@ public class ProfileUtilities extends TranslatingUtilities {
// debug = true; // debug = true;
// } // }
processPaths("", derived.getSnapshot(), baseSnapshot, diff, baseCursor, diffCursor, baseSnapshot.getElement().size()-1, processPaths("", derived.getSnapshot(), baseSnapshot, diff, baseCursor, diffCursor, baseSnapshot.getElement().size()-1,
derived.getDifferential().hasElement() ? derived.getDifferential().getElement().size()-1 : -1, url, webUrl, derived.present(), null, null, false, base.getUrl(), null, false, null, null, new ArrayList<ElementRedirection>(), base); derived.getDifferential().hasElement() ? derived.getDifferential().getElement().size()-1 : -1, url, webUrl, derived.present(), null, null, false, base.getUrl(), null, false, null, null, new ArrayList<ElementRedirection>(), base, derived);
checkGroupConstraints(derived); checkGroupConstraints(derived);
if (derived.getDerivation() == TypeDerivationRule.SPECIALIZATION) { if (derived.getDerivation() == TypeDerivationRule.SPECIALIZATION) {
for (ElementDefinition e : diff.getElement()) { for (ElementDefinition e : diff.getElement()) {
@ -824,7 +823,7 @@ public class ProfileUtilities extends TranslatingUtilities {
for (ElementDefinition ed : derived.getSnapshot().getElement()) { for (ElementDefinition ed : derived.getSnapshot().getElement()) {
for (TypeRefComponent t : ed.getType()) { for (TypeRefComponent t : ed.getType()) {
for (UriType u : t.getProfile()) { for (UriType u : t.getProfile()) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, u.getValue()); StructureDefinition sd = context.fetchResource(StructureDefinition.class, u.getValue(), derived);
if (sd == null) { if (sd == null) {
if (xver != null && xver.matchingUrl(u.getValue()) && xver.status(u.getValue()) == XVerExtensionStatus.Valid) { if (xver != null && xver.matchingUrl(u.getValue()) && xver.status(u.getValue()) == XVerExtensionStatus.Valid) {
sd = xver.makeDefinition(u.getValue()); sd = xver.makeDefinition(u.getValue());
@ -922,7 +921,7 @@ public class ProfileUtilities extends TranslatingUtilities {
public void checkDifferentialBaseType(StructureDefinition derived) throws Error { public void checkDifferentialBaseType(StructureDefinition derived) throws Error {
if (derived.hasDifferential() && !derived.getDifferential().getElementFirstRep().getPath().contains(".") && !derived.getDifferential().getElementFirstRep().getType().isEmpty()) { if (derived.hasDifferential() && !derived.getDifferential().getElementFirstRep().getPath().contains(".") && !derived.getDifferential().getElementFirstRep().getType().isEmpty()) {
if (wantFixDifferentialFirstElementType && typeMatchesAncestor(derived.getDifferential().getElementFirstRep().getType(), derived.getBaseDefinition())) { if (wantFixDifferentialFirstElementType && typeMatchesAncestor(derived.getDifferential().getElementFirstRep().getType(), derived.getBaseDefinition(), derived)) {
derived.getDifferential().getElementFirstRep().getType().clear(); derived.getDifferential().getElementFirstRep().getType().clear();
} else if (derived.getKind() != StructureDefinitionKind.LOGICAL) { } else if (derived.getKind() != StructureDefinitionKind.LOGICAL) {
throw new Error(context.formatMessage(I18nConstants.TYPE_ON_FIRST_DIFFERENTIAL_ELEMENT)); throw new Error(context.formatMessage(I18nConstants.TYPE_ON_FIRST_DIFFERENTIAL_ELEMENT));
@ -930,8 +929,8 @@ public class ProfileUtilities extends TranslatingUtilities {
} }
} }
private boolean typeMatchesAncestor(List<TypeRefComponent> type, String baseDefinition) { private boolean typeMatchesAncestor(List<TypeRefComponent> type, String baseDefinition, Resource src) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, baseDefinition); StructureDefinition sd = context.fetchResource(StructureDefinition.class, baseDefinition, src);
return sd != null && type.size() == 1 && sd.getType().equals(type.get(0).getCode()); return sd != null && type.size() == 1 && sd.getType().equals(type.get(0).getCode());
} }
@ -1072,7 +1071,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (sd.getUrl().equals(sdb.getUrl())) { if (sd.getUrl().equals(sdb.getUrl())) {
return true; return true;
} }
sd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition()); sd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
} }
return false; return false;
} }
@ -1179,11 +1178,12 @@ public class ProfileUtilities extends TranslatingUtilities {
/** /**
* @param trimDifferential * @param trimDifferential
* @param srcSD * @param srcSD
* @param derived
* @throws DefinitionException, FHIRException * @throws DefinitionException, FHIRException
* @throws Exception * @throws Exception
*/ */
private ElementDefinition processPaths(String indent, StructureDefinitionSnapshotComponent result, StructureDefinitionSnapshotComponent base, StructureDefinitionDifferentialComponent differential, int baseCursor, int diffCursor, int baseLimit, private ElementDefinition processPaths(String indent, StructureDefinitionSnapshotComponent result, StructureDefinitionSnapshotComponent base, StructureDefinitionDifferentialComponent differential, int baseCursor, int diffCursor, int baseLimit,
int diffLimit, String url, String webUrl, String profileName, String contextPathSrc, String contextPathDst, boolean trimDifferential, String contextName, String resultPathBase, boolean slicingDone, ElementDefinition slicer, String typeSlicingPath, List<ElementRedirection> redirector, StructureDefinition srcSD) throws DefinitionException, FHIRException { int diffLimit, String url, String webUrl, String profileName, String contextPathSrc, String contextPathDst, boolean trimDifferential, String contextName, String resultPathBase, boolean slicingDone, ElementDefinition slicer, String typeSlicingPath, List<ElementRedirection> redirector, StructureDefinition srcSD, StructureDefinition derived) throws DefinitionException, FHIRException {
if (debug) { if (debug) {
System.out.println(indent+"PP @ "+resultPathBase+" / "+contextPathSrc+" : base = "+baseCursor+" to "+baseLimit+", diff = "+diffCursor+" to "+diffLimit+" (slicing = "+slicingDone+", k "+(redirector == null ? "null" : redirector.toString())+")"); System.out.println(indent+"PP @ "+resultPathBase+" / "+contextPathSrc+" : base = "+baseCursor+" to "+baseLimit+", diff = "+diffCursor+" to "+diffLimit+" (slicing = "+slicingDone+", k "+(redirector == null ? "null" : redirector.toString())+")");
} }
@ -1218,7 +1218,7 @@ public class ProfileUtilities extends TranslatingUtilities {
// well, the profile walks into this, so we need to as well // well, the profile walks into this, so we need to as well
// did we implicitly step into a new type? // did we implicitly step into a new type?
if (baseHasChildren(base, currentBase)) { // not a new type here if (baseHasChildren(base, currentBase)) { // not a new type here
processPaths(indent+" ", result, base, differential, baseCursor+1, diffCursor, baseLimit, diffLimit, url, webUrl, profileName, contextPathSrc, contextPathDst, trimDifferential, contextName, resultPathBase, false, null, null, redirector, srcSD); processPaths(indent+" ", result, base, differential, baseCursor+1, diffCursor, baseLimit, diffLimit, url, webUrl, profileName, contextPathSrc, contextPathDst, trimDifferential, contextName, resultPathBase, false, null, null, redirector, srcSD, derived);
baseCursor = indexOfFirstNonChild(base, currentBase, baseCursor+1, baseLimit); baseCursor = indexOfFirstNonChild(base, currentBase, baseCursor+1, baseLimit);
} else { } else {
if (outcome.getType().size() == 0 && !outcome.hasContentReference()) { if (outcome.getType().size() == 0 && !outcome.hasContentReference()) {
@ -1253,27 +1253,27 @@ public class ProfileUtilities extends TranslatingUtilities {
int nbl = nbc; int nbl = nbc;
while (nbl < base.getElement().size() && base.getElement().get(nbl).getPath().startsWith(tgt.getElement().getPath()+".")) while (nbl < base.getElement().size() && base.getElement().get(nbl).getPath().startsWith(tgt.getElement().getPath()+"."))
nbl++; nbl++;
processPaths(indent+" ", result, base, differential, nbc, start - 1, nbl-1, diffCursor - 1, url, webUrl, profileName, tgt.getElement().getPath(), diffMatches.get(0).getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirectorStack(redirector, outcome, cpath), tgt.getSource()); processPaths(indent+" ", result, base, differential, nbc, start - 1, nbl-1, diffCursor - 1, url, webUrl, profileName, tgt.getElement().getPath(), diffMatches.get(0).getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirectorStack(redirector, outcome, cpath), tgt.getSource(), derived);
} else { } else {
int nbc = base.getElement().indexOf(tgt.getElement())+1; int nbc = base.getElement().indexOf(tgt.getElement())+1;
int nbl = nbc; int nbl = nbc;
while (nbl < base.getElement().size() && base.getElement().get(nbl).getPath().startsWith(tgt.getElement().getPath()+".")) while (nbl < base.getElement().size() && base.getElement().get(nbl).getPath().startsWith(tgt.getElement().getPath()+"."))
nbl++; nbl++;
System.out.println("Test!"); System.out.println("Test!");
processPaths(indent+" ", result, base, differential, nbc, start, nbl-1, diffCursor-1, url, webUrl, profileName, tgt.getElement().getPath(), outcome.getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirectorStack(redirector, outcome, cpath), srcSD); processPaths(indent+" ", result, base, differential, nbc, start, nbl-1, diffCursor-1, url, webUrl, profileName, tgt.getElement().getPath(), outcome.getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirectorStack(redirector, outcome, cpath), srcSD, derived);
} }
} else { } else {
StructureDefinition dt = outcome.getType().size() > 1 ? context.fetchTypeDefinition("Element") : getProfileForDataType(outcome.getType().get(0), webUrl); StructureDefinition dt = outcome.getType().size() > 1 ? context.fetchTypeDefinition("Element") : getProfileForDataType(outcome.getType().get(0), webUrl, srcSD);
if (dt == null) { if (dt == null) {
throw new DefinitionException(context.formatMessage(I18nConstants.UNKNOWN_TYPE__AT_, outcome.getType().get(0), cpath)); throw new DefinitionException(context.formatMessage(I18nConstants.UNKNOWN_TYPE__AT_, outcome.getType().get(0), cpath));
} }
contextName = dt.getUrl(); contextName = dt.getUrl();
if (redirector == null || redirector.isEmpty()) { if (redirector == null || redirector.isEmpty()) {
processPaths(indent+" ", result, dt.getSnapshot(), differential, 1 /* starting again on the data type, but skip the root */, start, dt.getSnapshot().getElement().size()-1, processPaths(indent+" ", result, dt.getSnapshot(), differential, 1 /* starting again on the data type, but skip the root */, start, dt.getSnapshot().getElement().size()-1,
diffCursor-1, url, getWebUrl(dt, webUrl, indent), profileName, cpath, outcome.getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirector, srcSD); diffCursor-1, url, getWebUrl(dt, webUrl, indent), profileName, cpath, outcome.getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirector, srcSD, derived);
} else { } else {
processPaths(indent+" ", result, dt.getSnapshot(), differential, 1 /* starting again on the data type, but skip the root */, start, dt.getSnapshot().getElement().size()-1, processPaths(indent+" ", result, dt.getSnapshot(), differential, 1 /* starting again on the data type, but skip the root */, start, dt.getSnapshot().getElement().size()-1,
diffCursor-1, url, getWebUrl(dt, webUrl, indent), profileName, cpath, outcome.getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirectorStack(redirector, currentBase, cpath), srcSD); diffCursor-1, url, getWebUrl(dt, webUrl, indent), profileName, cpath, outcome.getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirectorStack(redirector, currentBase, cpath), srcSD, derived);
} }
} }
} }
@ -1294,7 +1294,7 @@ public class ProfileUtilities extends TranslatingUtilities {
} else if (diffMatches.get(0).hasType() && diffMatches.get(0).getType().size() == 1 && diffMatches.get(0).getType().get(0).hasProfile() && !"Reference".equals(diffMatches.get(0).getType().get(0).getWorkingCode())) { } else if (diffMatches.get(0).hasType() && diffMatches.get(0).getType().size() == 1 && diffMatches.get(0).getType().get(0).hasProfile() && !"Reference".equals(diffMatches.get(0).getType().get(0).getWorkingCode())) {
CanonicalType p = diffMatches.get(0).getType().get(0).getProfile().get(0); CanonicalType p = diffMatches.get(0).getType().get(0).getProfile().get(0);
StructureDefinition sd = context.fetchResource(StructureDefinition.class, p.getValue()); StructureDefinition sd = context.fetchResource(StructureDefinition.class, p.getValue(), derived);
if (sd == null && xver != null && xver.matchingUrl(p.getValue())) { if (sd == null && xver != null && xver.matchingUrl(p.getValue())) {
switch (xver.status(p.getValue())) { switch (xver.status(p.getValue())) {
case BadVersion: throw new FHIRException("Reference to invalid version in extension url "+p.getValue()); case BadVersion: throw new FHIRException("Reference to invalid version in extension url "+p.getValue());
@ -1316,7 +1316,7 @@ public class ProfileUtilities extends TranslatingUtilities {
throw new FHIRException(context.formatMessage(I18nConstants.ATTEMPT_TO_USE_A_SNAPSHOT_ON_PROFILE__AS__BEFORE_IT_IS_GENERATED, sd.getUrl(), "Source for first element")); throw new FHIRException(context.formatMessage(I18nConstants.ATTEMPT_TO_USE_A_SNAPSHOT_ON_PROFILE__AS__BEFORE_IT_IS_GENERATED, sd.getUrl(), "Source for first element"));
} }
} else if (!sd.hasSnapshot()) { } else if (!sd.hasSnapshot()) {
StructureDefinition sdb = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition()); StructureDefinition sdb = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
if (sdb == null) if (sdb == null)
throw new DefinitionException(context.formatMessage(I18nConstants.UNABLE_TO_FIND_BASE__FOR_, sd.getBaseDefinition(), sd.getUrl())); throw new DefinitionException(context.formatMessage(I18nConstants.UNABLE_TO_FIND_BASE__FOR_, sd.getBaseDefinition(), sd.getUrl()));
checkNotGenerating(sdb, "an extension base"); checkNotGenerating(sdb, "an extension base");
@ -1362,7 +1362,7 @@ public class ProfileUtilities extends TranslatingUtilities {
} }
} }
} }
updateFromDefinition(outcome, diffMatches.get(0), profileName, trimDifferential, url, srcSD); updateFromDefinition(outcome, diffMatches.get(0), profileName, trimDifferential, url, srcSD, derived);
removeStatusExtensions(outcome); removeStatusExtensions(outcome);
// if (outcome.getPath().endsWith("[x]") && outcome.getType().size() == 1 && !outcome.getType().get(0).getCode().equals("*") && !diffMatches.get(0).hasSlicing()) // if the base profile allows multiple types, but the profile only allows one, rename it // if (outcome.getPath().endsWith("[x]") && outcome.getType().size() == 1 && !outcome.getType().get(0).getCode().equals("*") && !diffMatches.get(0).hasSlicing()) // if the base profile allows multiple types, but the profile only allows one, rename it
// outcome.setPath(outcome.getPath().substring(0, outcome.getPath().length()-3)+Utilities.capitalize(outcome.getType().get(0).getCode())); // outcome.setPath(outcome.getPath().substring(0, outcome.getPath().length()-3)+Utilities.capitalize(outcome.getType().get(0).getCode()));
@ -1415,21 +1415,21 @@ public class ProfileUtilities extends TranslatingUtilities {
int nbl = nbc; int nbl = nbc;
while (nbl < base.getElement().size() && base.getElement().get(nbl).getPath().startsWith(tgt.getElement().getPath()+".")) while (nbl < base.getElement().size() && base.getElement().get(nbl).getPath().startsWith(tgt.getElement().getPath()+"."))
nbl++; nbl++;
processPaths(indent+" ", result, base, differential, nbc, start - 1, nbl-1, diffCursor - 1, url, webUrl, profileName, tgt.getElement().getPath(), diffMatches.get(0).getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirectorStack(redirector, outcome, cpath), tgt.getSource()); processPaths(indent+" ", result, base, differential, nbc, start - 1, nbl-1, diffCursor - 1, url, webUrl, profileName, tgt.getElement().getPath(), diffMatches.get(0).getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirectorStack(redirector, outcome, cpath), tgt.getSource(), derived);
} else { } else {
int nbc = base.getElement().indexOf(tgt.getElement())+1; int nbc = base.getElement().indexOf(tgt.getElement())+1;
int nbl = nbc; int nbl = nbc;
while (nbl < base.getElement().size() && base.getElement().get(nbl).getPath().startsWith(tgt.getElement().getPath()+".")) while (nbl < base.getElement().size() && base.getElement().get(nbl).getPath().startsWith(tgt.getElement().getPath()+"."))
nbl++; nbl++;
processPaths(indent+" ", result, base, differential, nbc, start - 1, nbl-1, diffCursor - 1, url, webUrl, profileName, tgt.getElement().getPath(), diffMatches.get(0).getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirectorStack(redirector, outcome, cpath), srcSD); processPaths(indent+" ", result, base, differential, nbc, start - 1, nbl-1, diffCursor - 1, url, webUrl, profileName, tgt.getElement().getPath(), diffMatches.get(0).getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirectorStack(redirector, outcome, cpath), srcSD, derived);
} }
} else { } else {
StructureDefinition dt = outcome.getType().size() == 1 ? getProfileForDataType(outcome.getType().get(0), webUrl) : getProfileForDataType("Element"); StructureDefinition dt = outcome.getType().size() == 1 ? getProfileForDataType(outcome.getType().get(0), webUrl, derived) : getProfileForDataType("Element");
if (dt == null) if (dt == null)
throw new DefinitionException(context.formatMessage(I18nConstants._HAS_CHILDREN__FOR_TYPE__IN_PROFILE__BUT_CANT_FIND_TYPE, diffMatches.isEmpty() ? "??" : diffMatches.get(0).getPath(), differential.getElement().get(diffCursor).getPath(), typeCode(outcome.getType()), profileName)); throw new DefinitionException(context.formatMessage(I18nConstants._HAS_CHILDREN__FOR_TYPE__IN_PROFILE__BUT_CANT_FIND_TYPE, diffMatches.isEmpty() ? "??" : diffMatches.get(0).getPath(), differential.getElement().get(diffCursor).getPath(), typeCode(outcome.getType()), profileName));
contextName = dt.getUrl(); contextName = dt.getUrl();
processPaths(indent+" ", result, dt.getSnapshot(), differential, 1 /* starting again on the data type, but skip the root */, start, dt.getSnapshot().getElement().size()-1, processPaths(indent+" ", result, dt.getSnapshot(), differential, 1 /* starting again on the data type, but skip the root */, start, dt.getSnapshot().getElement().size()-1,
diffCursor - 1, url, getWebUrl(dt, webUrl, indent), profileName+pathTail(diffMatches, 0), diffMatches.get(0).getPath(), outcome.getPath(), trimDifferential, contextName, resultPathBase, false, null, null, new ArrayList<ElementRedirection>(), srcSD); diffCursor - 1, url, getWebUrl(dt, webUrl, indent), profileName+pathTail(diffMatches, 0), diffMatches.get(0).getPath(), outcome.getPath(), trimDifferential, contextName, resultPathBase, false, null, null, new ArrayList<ElementRedirection>(), srcSD, derived);
} }
} }
} }
@ -1515,7 +1515,7 @@ public class ProfileUtilities extends TranslatingUtilities {
// ok passed the checks. // ok passed the checks.
// copy the root diff, and then process any children it has // copy the root diff, and then process any children it has
ElementDefinition e = processPaths(indent+" ", result, base, differential, baseCursor, ndc, nbl, ndl, url, webUrl, profileName+pathTail(diffMatches, 0), contextPathSrc, contextPathDst, ElementDefinition e = processPaths(indent+" ", result, base, differential, baseCursor, ndc, nbl, ndl, url, webUrl, profileName+pathTail(diffMatches, 0), contextPathSrc, contextPathDst,
trimDifferential, contextName, resultPathBase, true, null, null, redirector, srcSD); trimDifferential, contextName, resultPathBase, true, null, null, redirector, srcSD, derived);
if (e==null) if (e==null)
throw new FHIRException(context.formatMessage(I18nConstants.DID_NOT_FIND_TYPE_ROOT_, diffMatches.get(0).getPath())); throw new FHIRException(context.formatMessage(I18nConstants.DID_NOT_FIND_TYPE_ROOT_, diffMatches.get(0).getPath()));
// now set up slicing on the e (cause it was wiped by what we called. // now set up slicing on the e (cause it was wiped by what we called.
@ -1541,7 +1541,7 @@ public class ProfileUtilities extends TranslatingUtilities {
} }
ndc = differential.getElement().indexOf(diffMatches.get(i)); ndc = differential.getElement().indexOf(diffMatches.get(i));
ndl = findEndOfElement(differential, ndc); ndl = findEndOfElement(differential, ndc);
ElementDefinition typeSliceElement = processPaths(indent+" ", result, base, differential, baseCursor, ndc, nbl, ndl, url, webUrl, profileName+pathTail(diffMatches, i), contextPathSrc, contextPathDst, trimDifferential, contextName, resultPathBase, true, e, null, redirector, srcSD); ElementDefinition typeSliceElement = processPaths(indent+" ", result, base, differential, baseCursor, ndc, nbl, ndl, url, webUrl, profileName+pathTail(diffMatches, i), contextPathSrc, contextPathDst, trimDifferential, contextName, resultPathBase, true, e, null, redirector, srcSD, derived);
if (typeList.size() > start+1) { if (typeList.size() > start+1) {
typeSliceElement.setMin(0); typeSliceElement.setMin(0);
} }
@ -1606,7 +1606,7 @@ public class ProfileUtilities extends TranslatingUtilities {
int ndc = differential.getElement().indexOf(diffMatches.get(0)); int ndc = differential.getElement().indexOf(diffMatches.get(0));
int ndl = findEndOfElement(differential, ndc); int ndl = findEndOfElement(differential, ndc);
ElementDefinition e = processPaths(indent+" ", result, base, differential, baseCursor, ndc, nbl, ndl, url, webUrl, profileName+pathTail(diffMatches, 0), contextPathSrc, contextPathDst, ElementDefinition e = processPaths(indent+" ", result, base, differential, baseCursor, ndc, nbl, ndl, url, webUrl, profileName+pathTail(diffMatches, 0), contextPathSrc, contextPathDst,
trimDifferential, contextName, resultPathBase, true, null, null, redirector, srcSD); trimDifferential, contextName, resultPathBase, true, null, null, redirector, srcSD, derived);
if (e==null) if (e==null)
throw new FHIRException(context.formatMessage(I18nConstants.DID_NOT_FIND_SINGLE_SLICE_, diffMatches.get(0).getPath())); throw new FHIRException(context.formatMessage(I18nConstants.DID_NOT_FIND_SINGLE_SLICE_, diffMatches.get(0).getPath()));
e.setSlicing(diffMatches.get(0).getSlicing()); e.setSlicing(diffMatches.get(0).getSlicing());
@ -1629,7 +1629,7 @@ public class ProfileUtilities extends TranslatingUtilities {
// differential - if the first one in the list has a name, we'll process it. Else we'll treat it as the base definition of the slice. // differential - if the first one in the list has a name, we'll process it. Else we'll treat it as the base definition of the slice.
if (!diffMatches.get(0).hasSliceName()) { if (!diffMatches.get(0).hasSliceName()) {
updateFromDefinition(outcome, diffMatches.get(0), profileName, trimDifferential, url, srcSD); updateFromDefinition(outcome, diffMatches.get(0), profileName, trimDifferential, url, srcSD, derived);
removeStatusExtensions(outcome); removeStatusExtensions(outcome);
if (!outcome.hasContentReference() && !outcome.hasType()) { if (!outcome.hasContentReference() && !outcome.hasType()) {
throw new DefinitionException(context.formatMessage(I18nConstants.NOT_DONE_YET)); throw new DefinitionException(context.formatMessage(I18nConstants.NOT_DONE_YET));
@ -1638,7 +1638,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (baseHasChildren(base, currentBase)) { // not a new type here if (baseHasChildren(base, currentBase)) { // not a new type here
throw new Error("This situation is not yet handled (constrain slicing to 1..1 and fix base slice for inline structure - please report issue to grahame@fhir.org along with a test case that reproduces this error (@ "+cpath+" | "+currentBase.getPath()+")"); throw new Error("This situation is not yet handled (constrain slicing to 1..1 and fix base slice for inline structure - please report issue to grahame@fhir.org along with a test case that reproduces this error (@ "+cpath+" | "+currentBase.getPath()+")");
} else { } else {
StructureDefinition dt = getTypeForElement(differential, diffCursor, profileName, diffMatches, outcome, webUrl); StructureDefinition dt = getTypeForElement(differential, diffCursor, profileName, diffMatches, outcome, webUrl, srcSD);
contextName = dt.getUrl(); contextName = dt.getUrl();
diffCursor++; diffCursor++;
start = diffCursor; start = diffCursor;
@ -1646,7 +1646,7 @@ public class ProfileUtilities extends TranslatingUtilities {
diffCursor++; diffCursor++;
diffCursor--; diffCursor--;
processPaths(indent+" ", result, dt.getSnapshot(), differential, 1 /* starting again on the data type, but skip the root */, start, dt.getSnapshot().getElement().size()-1, processPaths(indent+" ", result, dt.getSnapshot(), differential, 1 /* starting again on the data type, but skip the root */, start, dt.getSnapshot().getElement().size()-1,
diffCursor, url, getWebUrl(dt, webUrl, indent), profileName, cpath, outcome.getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirector, srcSD); diffCursor, url, getWebUrl(dt, webUrl, indent), profileName, cpath, outcome.getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirector, srcSD, derived);
} }
} }
start++; start++;
@ -1668,7 +1668,7 @@ public class ProfileUtilities extends TranslatingUtilities {
continue; continue;
}*/ }*/
// now we process the base scope repeatedly for each instance of the item in the differential list // now we process the base scope repeatedly for each instance of the item in the differential list
processPaths(indent+" ", result, base, differential, baseCursor, ndc, nbl, ndl, url, webUrl, profileName+pathTail(diffMatches, i), contextPathSrc, contextPathDst, trimDifferential, contextName, resultPathBase, true, slicerElement, null, redirector, srcSD); processPaths(indent+" ", result, base, differential, baseCursor, ndc, nbl, ndl, url, webUrl, profileName+pathTail(diffMatches, i), contextPathSrc, contextPathDst, trimDifferential, contextName, resultPathBase, true, slicerElement, null, redirector, srcSD, derived);
} }
// ok, done with that - next in the base list // ok, done with that - next in the base list
baseCursor = nbl+1; baseCursor = nbl+1;
@ -1701,10 +1701,10 @@ public class ProfileUtilities extends TranslatingUtilities {
// the profile walks into this, so we need to as well // the profile walks into this, so we need to as well
// did we implicitly step into a new type? // did we implicitly step into a new type?
if (baseHasChildren(base, currentBase)) { // not a new type here if (baseHasChildren(base, currentBase)) { // not a new type here
processPaths(indent+" ", result, base, differential, baseCursor+1, diffCursor, baseLimit, diffLimit, url, webUrl, profileName, contextPathSrc, contextPathDst, trimDifferential, contextName, resultPathBase, false, null, null, redirector, srcSD); processPaths(indent+" ", result, base, differential, baseCursor+1, diffCursor, baseLimit, diffLimit, url, webUrl, profileName, contextPathSrc, contextPathDst, trimDifferential, contextName, resultPathBase, false, null, null, redirector, srcSD, derived);
baseCursor = indexOfFirstNonChild(base, currentBase, baseCursor, baseLimit); baseCursor = indexOfFirstNonChild(base, currentBase, baseCursor, baseLimit);
} else { } else {
StructureDefinition dt = getTypeForElement(differential, diffCursor, profileName, diffMatches, outcome, webUrl); StructureDefinition dt = getTypeForElement(differential, diffCursor, profileName, diffMatches, outcome, webUrl, srcSD);
contextName = dt.getUrl(); contextName = dt.getUrl();
int start = diffCursor; int start = diffCursor;
if (differential.getElement().get(diffCursor).getPath().equals(cpath)) { if (differential.getElement().get(diffCursor).getPath().equals(cpath)) {
@ -1715,7 +1715,7 @@ public class ProfileUtilities extends TranslatingUtilities {
} }
if (diffCursor > start) { if (diffCursor > start) {
processPaths(indent+" ", result, dt.getSnapshot(), differential, 1 /* starting again on the data type, but skip the root */, start, dt.getSnapshot().getElement().size()-1, processPaths(indent+" ", result, dt.getSnapshot(), differential, 1 /* starting again on the data type, but skip the root */, start, dt.getSnapshot().getElement().size()-1,
diffCursor-1, url, getWebUrl(dt, webUrl, indent), profileName, cpath, outcome.getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirector, srcSD); diffCursor-1, url, getWebUrl(dt, webUrl, indent), profileName, cpath, outcome.getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirector, srcSD, derived);
} }
} }
baseCursor++; baseCursor++;
@ -1811,7 +1811,7 @@ public class ProfileUtilities extends TranslatingUtilities {
// ok passed the checks. // ok passed the checks.
// copy the root diff, and then process any children it has // copy the root diff, and then process any children it has
ElementDefinition e = processPaths(indent+" ", result, base, differential, baseCursor, ndc, nbl, ndl, url, webUrl, profileName+pathTail(diffMatches, 0), contextPathSrc, contextPathDst, ElementDefinition e = processPaths(indent+" ", result, base, differential, baseCursor, ndc, nbl, ndl, url, webUrl, profileName+pathTail(diffMatches, 0), contextPathSrc, contextPathDst,
trimDifferential, contextName, resultPathBase, true, null, cpath, redirector, srcSD); trimDifferential, contextName, resultPathBase, true, null, cpath, redirector, srcSD, derived);
if (e==null) if (e==null)
throw new FHIRException(context.formatMessage(I18nConstants.DID_NOT_FIND_TYPE_ROOT_, diffMatches.get(0).getPath())); throw new FHIRException(context.formatMessage(I18nConstants.DID_NOT_FIND_TYPE_ROOT_, diffMatches.get(0).getPath()));
// now set up slicing on the e (cause it was wiped by what we called. // now set up slicing on the e (cause it was wiped by what we called.
@ -1844,7 +1844,7 @@ public class ProfileUtilities extends TranslatingUtilities {
sEnd = bs.end; sEnd = bs.end;
bs.handled = true; bs.handled = true;
} }
processPaths(indent+" ", result, base, differential, sStart, ndc, sEnd, ndl, url, webUrl, profileName+pathTail(diffMatches, i), contextPathSrc, contextPathDst, trimDifferential, contextName, resultPathBase, true, e, cpath, redirector, srcSD); processPaths(indent+" ", result, base, differential, sStart, ndc, sEnd, ndl, url, webUrl, profileName+pathTail(diffMatches, i), contextPathSrc, contextPathDst, trimDifferential, contextName, resultPathBase, true, e, cpath, redirector, srcSD, derived);
} }
if (elementToRemove != null) { if (elementToRemove != null) {
differential.getElement().remove(elementToRemove); differential.getElement().remove(elementToRemove);
@ -1863,7 +1863,7 @@ public class ProfileUtilities extends TranslatingUtilities {
// ok we gimme up a fake differential that says nothing, and run that against the slice. // ok we gimme up a fake differential that says nothing, and run that against the slice.
StructureDefinitionDifferentialComponent fakeDiff = new StructureDefinitionDifferentialComponent(); StructureDefinitionDifferentialComponent fakeDiff = new StructureDefinitionDifferentialComponent();
fakeDiff.getElementFirstRep().setPath(bs.defn.getPath()); fakeDiff.getElementFirstRep().setPath(bs.defn.getPath());
processPaths(indent+" ", result, base, fakeDiff, bs.start, 0, bs.end, 0, url, webUrl, profileName+tail(bs.defn.getPath()), contextPathSrc, contextPathDst, trimDifferential, contextName, resultPathBase, true, e, cpath, redirector, srcSD); processPaths(indent+" ", result, base, fakeDiff, bs.start, 0, bs.end, 0, url, webUrl, profileName+tail(bs.defn.getPath()), contextPathSrc, contextPathDst, trimDifferential, contextName, resultPathBase, true, e, cpath, redirector, srcSD, derived);
} }
} }
@ -1893,7 +1893,7 @@ public class ProfileUtilities extends TranslatingUtilities {
updateFromBase(outcome, currentBase, srcSD.getUrl()); updateFromBase(outcome, currentBase, srcSD.getUrl());
if (diffMatches.get(0).hasSlicing() || !diffMatches.get(0).hasSliceName()) { if (diffMatches.get(0).hasSlicing() || !diffMatches.get(0).hasSliceName()) {
updateFromSlicing(outcome.getSlicing(), diffMatches.get(0).getSlicing()); updateFromSlicing(outcome.getSlicing(), diffMatches.get(0).getSlicing());
updateFromDefinition(outcome, diffMatches.get(0), profileName, closed, url, srcSD); // if there's no slice, we don't want to update the unsliced description updateFromDefinition(outcome, diffMatches.get(0), profileName, closed, url, srcSD, derived); // if there's no slice, we don't want to update the unsliced description
removeStatusExtensions(outcome); removeStatusExtensions(outcome);
} else if (!diffMatches.get(0).hasSliceName()) { } else if (!diffMatches.get(0).hasSliceName()) {
diffMatches.get(0).setUserData(GENERATED_IN_SNAPSHOT, outcome); // because of updateFromDefinition isn't called diffMatches.get(0).setUserData(GENERATED_IN_SNAPSHOT, outcome); // because of updateFromDefinition isn't called
@ -1913,7 +1913,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (base.getElement().get(baseCursor).getType().size() != 1) { if (base.getElement().get(baseCursor).getType().size() != 1) {
throw new Error(context.formatMessage(I18nConstants.DIFFERENTIAL_WALKS_INTO____BUT_THE_BASE_DOES_NOT_AND_THERE_IS_NOT_A_SINGLE_FIXED_TYPE_THE_TYPE_IS__THIS_IS_NOT_HANDLED_YET, cpath, diffMatches.get(0).toString(), base.getElement().get(baseCursor).typeSummary())); throw new Error(context.formatMessage(I18nConstants.DIFFERENTIAL_WALKS_INTO____BUT_THE_BASE_DOES_NOT_AND_THERE_IS_NOT_A_SINGLE_FIXED_TYPE_THE_TYPE_IS__THIS_IS_NOT_HANDLED_YET, cpath, diffMatches.get(0).toString(), base.getElement().get(baseCursor).typeSummary()));
} }
StructureDefinition dt = getProfileForDataType(base.getElement().get(baseCursor).getType().get(0), webUrl); StructureDefinition dt = getProfileForDataType(base.getElement().get(baseCursor).getType().get(0), webUrl, srcSD);
if (dt == null) { if (dt == null) {
throw new DefinitionException(context.formatMessage(I18nConstants.UNKNOWN_TYPE__AT_, outcome.getType().get(0), diffMatches.get(0).getPath())); throw new DefinitionException(context.formatMessage(I18nConstants.UNKNOWN_TYPE__AT_, outcome.getType().get(0), diffMatches.get(0).getPath()));
} }
@ -1921,10 +1921,10 @@ public class ProfileUtilities extends TranslatingUtilities {
while (differential.getElement().size() > diffCursor && pathStartsWith(differential.getElement().get(diffCursor).getPath(), cpath+".")) while (differential.getElement().size() > diffCursor && pathStartsWith(differential.getElement().get(diffCursor).getPath(), cpath+"."))
diffCursor++; diffCursor++;
processPaths(indent+" ", result, dt.getSnapshot(), differential, 1, ndc, dt.getSnapshot().getElement().size()-1, ndl, processPaths(indent+" ", result, dt.getSnapshot(), differential, 1, ndc, dt.getSnapshot().getElement().size()-1, ndl,
url, getWebUrl(dt, webUrl, indent), profileName, cpath, outcome.getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirector, srcSD); url, getWebUrl(dt, webUrl, indent), profileName, cpath, outcome.getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirector, srcSD, derived);
} else { } else {
processPaths(indent+" ", result, base, differential, baseCursor+1, ndc, nbl, ndl, processPaths(indent+" ", result, base, differential, baseCursor+1, ndc, nbl, ndl,
url, webUrl, profileName+pathTail(diffMatches, 0), contextPathSrc, contextPathDst, trimDifferential, contextName, resultPathBase, false, null, null, null, srcSD); url, webUrl, profileName+pathTail(diffMatches, 0), contextPathSrc, contextPathDst, trimDifferential, contextName, resultPathBase, false, null, null, null, srcSD, derived);
} }
// throw new Error("Not done yet"); // throw new Error("Not done yet");
// } else if (currentBase.getType().get(0).getCode().equals("BackboneElement") && diffMatches.size() > 0 && diffMatches.get(0).hasSliceName()) { // } else if (currentBase.getType().get(0).getCode().equals("BackboneElement") && diffMatches.size() > 0 && diffMatches.get(0).hasSliceName()) {
@ -1955,7 +1955,7 @@ public class ProfileUtilities extends TranslatingUtilities {
int ndc = differential.getElement().indexOf(diffMatches.get(diffpos)); int ndc = differential.getElement().indexOf(diffMatches.get(diffpos));
int ndl = findEndOfElement(differential, ndc); int ndl = findEndOfElement(differential, ndc);
// now we process the base scope repeatedly for each instance of the item in the differential list // now we process the base scope repeatedly for each instance of the item in the differential list
processPaths(indent+" ", result, base, differential, baseCursor, ndc, nbl, ndl, url, webUrl, profileName+pathTail(diffMatches, diffpos), contextPathSrc, contextPathDst, closed, contextName, resultPathBase, true, null, null, redirector, srcSD); processPaths(indent+" ", result, base, differential, baseCursor, ndc, nbl, ndl, url, webUrl, profileName+pathTail(diffMatches, diffpos), contextPathSrc, contextPathDst, closed, contextName, resultPathBase, true, null, null, redirector, srcSD, derived);
// ok, done with that - now set the cursors for if this is the end // ok, done with that - now set the cursors for if this is the end
baseCursor = nbl; baseCursor = nbl;
diffCursor = ndl+1; diffCursor = ndl+1;
@ -2006,7 +2006,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (!outcome.getPath().startsWith(resultPathBase)) if (!outcome.getPath().startsWith(resultPathBase))
throw new DefinitionException(context.formatMessage(I18nConstants.ADDING_WRONG_PATH)); throw new DefinitionException(context.formatMessage(I18nConstants.ADDING_WRONG_PATH));
result.getElement().add(outcome); result.getElement().add(outcome);
updateFromDefinition(outcome, diffItem, profileName, trimDifferential, url, srcSD); updateFromDefinition(outcome, diffItem, profileName, trimDifferential, url, srcSD, derived);
removeStatusExtensions(outcome); removeStatusExtensions(outcome);
// --- LM Added this // --- LM Added this
diffCursor = differential.getElement().indexOf(diffItem)+1; diffCursor = differential.getElement().indexOf(diffItem)+1;
@ -2028,10 +2028,10 @@ public class ProfileUtilities extends TranslatingUtilities {
while (differential.getElement().size() > diffCursor && pathStartsWith(differential.getElement().get(diffCursor).getPath(), diffMatches.get(0).getPath()+".")) while (differential.getElement().size() > diffCursor && pathStartsWith(differential.getElement().get(diffCursor).getPath(), diffMatches.get(0).getPath()+"."))
diffCursor++; diffCursor++;
processPaths(indent+" ", result, base, differential, baseStart, start-1, baseMax-1, processPaths(indent+" ", result, base, differential, baseStart, start-1, baseMax-1,
diffCursor - 1, url, webUrl, profileName+pathTail(diffMatches, 0), base.getElement().get(0).getPath(), base.getElement().get(0).getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirector, srcSD); diffCursor - 1, url, webUrl, profileName+pathTail(diffMatches, 0), base.getElement().get(0).getPath(), base.getElement().get(0).getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirector, srcSD, derived);
} else { } else {
StructureDefinition dt = getProfileForDataType(outcome.getType().get(0), webUrl); StructureDefinition dt = getProfileForDataType(outcome.getType().get(0), webUrl, derived);
// if (t.getCode().equals("Extension") && t.hasProfile() && !t.getProfile().contains(":")) { // if (t.getCode().equals("Extension") && t.hasProfile() && !t.getProfile().contains(":")) {
// lloydfix dt = // lloydfix dt =
// } // }
@ -2042,7 +2042,7 @@ public class ProfileUtilities extends TranslatingUtilities {
while (differential.getElement().size() > diffCursor && pathStartsWith(differential.getElement().get(diffCursor).getPath(), diffMatches.get(0).getPath()+".")) while (differential.getElement().size() > diffCursor && pathStartsWith(differential.getElement().get(diffCursor).getPath(), diffMatches.get(0).getPath()+"."))
diffCursor++; diffCursor++;
processPaths(indent+" ", result, dt.getSnapshot(), differential, 1 /* starting again on the data type, but skip the root */, start-1, dt.getSnapshot().getElement().size()-1, processPaths(indent+" ", result, dt.getSnapshot(), differential, 1 /* starting again on the data type, but skip the root */, start-1, dt.getSnapshot().getElement().size()-1,
diffCursor - 1, url, getWebUrl(dt, webUrl, indent), profileName+pathTail(diffMatches, 0), diffMatches.get(0).getPath(), outcome.getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirector, srcSD); diffCursor - 1, url, getWebUrl(dt, webUrl, indent), profileName+pathTail(diffMatches, 0), diffMatches.get(0).getPath(), outcome.getPath(), trimDifferential, contextName, resultPathBase, false, null, null, redirector, srcSD, derived);
} }
} }
} }
@ -2092,7 +2092,7 @@ public class ProfileUtilities extends TranslatingUtilities {
} }
public StructureDefinition getTypeForElement(StructureDefinitionDifferentialComponent differential, int diffCursor, String profileName, public StructureDefinition getTypeForElement(StructureDefinitionDifferentialComponent differential, int diffCursor, String profileName,
List<ElementDefinition> diffMatches, ElementDefinition outcome, String webUrl) { List<ElementDefinition> diffMatches, ElementDefinition outcome, String webUrl, Resource srcSD) {
if (outcome.getType().size() == 0) { if (outcome.getType().size() == 0) {
if (outcome.hasContentReference()) { if (outcome.hasContentReference()) {
throw new Error(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_CONTENT_REFERENCE_IN_THIS_CONTEXT, outcome.getContentReference(), outcome.getId(), outcome.getPath())); throw new Error(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_CONTENT_REFERENCE_IN_THIS_CONTEXT, outcome.getContentReference(), outcome.getId(), outcome.getPath()));
@ -2106,7 +2106,7 @@ public class ProfileUtilities extends TranslatingUtilities {
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)); 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));
} }
} }
StructureDefinition dt = getProfileForDataType(outcome.getType().get(0), webUrl); StructureDefinition dt = getProfileForDataType(outcome.getType().get(0), webUrl, srcSD);
if (dt == null) if (dt == null)
throw new DefinitionException(context.formatMessage(I18nConstants.UNKNOWN_TYPE__AT_, outcome.getType().get(0), diffMatches.get(0).getPath())); throw new DefinitionException(context.formatMessage(I18nConstants.UNKNOWN_TYPE__AT_, outcome.getType().get(0), diffMatches.get(0).getPath()));
return dt; return dt;
@ -2143,7 +2143,7 @@ public class ProfileUtilities extends TranslatingUtilities {
} }
} }
} }
sd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition()); sd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
} }
return false; return false;
} }
@ -2580,10 +2580,10 @@ public class ProfileUtilities extends TranslatingUtilities {
return s; return s;
} }
private StructureDefinition getProfileForDataType(TypeRefComponent type, String webUrl) { private StructureDefinition getProfileForDataType(TypeRefComponent type, String webUrl, Resource src) {
StructureDefinition sd = null; StructureDefinition sd = null;
if (type.hasProfile()) { if (type.hasProfile()) {
sd = context.fetchResource(StructureDefinition.class, type.getProfile().get(0).getValue()); sd = context.fetchResource(StructureDefinition.class, type.getProfile().get(0).getValue(), src);
if (sd == null) { if (sd == null) {
if (xver != null && xver.matchingUrl(type.getProfile().get(0).getValue()) && xver.status(type.getProfile().get(0).getValue()) == XVerExtensionStatus.Valid) { if (xver != null && xver.matchingUrl(type.getProfile().get(0).getValue()) && xver.status(type.getProfile().get(0).getValue()) == XVerExtensionStatus.Valid) {
sd = xver.makeDefinition(type.getProfile().get(0).getValue()); sd = xver.makeDefinition(type.getProfile().get(0).getValue());
@ -2974,7 +2974,7 @@ public class ProfileUtilities extends TranslatingUtilities {
return true; return true;
} }
private void updateFromDefinition(ElementDefinition dest, ElementDefinition source, String pn, boolean trimDifferential, String purl, StructureDefinition srcSD) throws DefinitionException, FHIRException { private void updateFromDefinition(ElementDefinition dest, ElementDefinition source, String pn, boolean trimDifferential, String purl, StructureDefinition srcSD, StructureDefinition derivedSrc) throws DefinitionException, FHIRException {
source.setUserData(GENERATED_IN_SNAPSHOT, dest); source.setUserData(GENERATED_IN_SNAPSHOT, dest);
// we start with a clone of the base profile ('dest') and we copy from the profile ('source') // we start with a clone of the base profile ('dest') and we copy from the profile ('source')
// over the top for anything the source has // over the top for anything the source has
@ -2992,9 +2992,9 @@ public class ProfileUtilities extends TranslatingUtilities {
// Before applying changes, apply them to what's in the profile // Before applying changes, apply them to what's in the profile
StructureDefinition profile = null; StructureDefinition profile = null;
if (base.hasSliceName()) if (base.hasSliceName())
profile = base.getType().size() == 1 && base.getTypeFirstRep().hasProfile() ? context.fetchResource(StructureDefinition.class, base.getTypeFirstRep().getProfile().get(0).getValue()) : null; profile = base.getType().size() == 1 && base.getTypeFirstRep().hasProfile() ? context.fetchResource(StructureDefinition.class, base.getTypeFirstRep().getProfile().get(0).getValue(), srcSD) : null;
if (profile==null) if (profile==null)
profile = source.getType().size() == 1 && source.getTypeFirstRep().hasProfile() ? context.fetchResource(StructureDefinition.class, source.getTypeFirstRep().getProfile().get(0).getValue()) : null; profile = source.getType().size() == 1 && source.getTypeFirstRep().hasProfile() ? context.fetchResource(StructureDefinition.class, source.getTypeFirstRep().getProfile().get(0).getValue(), derivedSrc) : null;
if (profile != null) { if (profile != null) {
ElementDefinition e = profile.getSnapshot().getElement().get(0); ElementDefinition e = profile.getSnapshot().getElement().get(0);
String webroot = profile.getUserString("webroot"); String webroot = profile.getUserString("webroot");
@ -3208,8 +3208,8 @@ public class ProfileUtilities extends TranslatingUtilities {
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "illegal attempt to change the binding on "+derived.getPath()+" from "+base.getBinding().getStrength().toCode()+" to "+derived.getBinding().getStrength().toCode(), ValidationMessage.IssueSeverity.ERROR)); messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+derived.getPath(), "illegal attempt to change the binding on "+derived.getPath()+" from "+base.getBinding().getStrength().toCode()+" to "+derived.getBinding().getStrength().toCode(), ValidationMessage.IssueSeverity.ERROR));
// throw new DefinitionException("StructureDefinition "+pn+" at "+derived.getPath()+": illegal attempt to change a binding from "+base.getBinding().getStrength().toCode()+" to "+derived.getBinding().getStrength().toCode()); // throw new DefinitionException("StructureDefinition "+pn+" at "+derived.getPath()+": illegal attempt to change a binding from "+base.getBinding().getStrength().toCode()+" to "+derived.getBinding().getStrength().toCode());
else if (base.hasBinding() && derived.hasBinding() && base.getBinding().getStrength() == BindingStrength.REQUIRED && base.getBinding().hasValueSet() && derived.getBinding().hasValueSet()) { else if (base.hasBinding() && derived.hasBinding() && base.getBinding().getStrength() == BindingStrength.REQUIRED && base.getBinding().hasValueSet() && derived.getBinding().hasValueSet()) {
ValueSet baseVs = context.fetchResource(ValueSet.class, base.getBinding().getValueSet()); ValueSet baseVs = context.fetchResource(ValueSet.class, base.getBinding().getValueSet(), srcSD);
ValueSet contextVs = context.fetchResource(ValueSet.class, derived.getBinding().getValueSet()); ValueSet contextVs = context.fetchResource(ValueSet.class, derived.getBinding().getValueSet(), derivedSrc);
if (baseVs == null) { if (baseVs == null) {
messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+base.getPath(), "Binding "+base.getBinding().getValueSet()+" could not be located", ValidationMessage.IssueSeverity.WARNING)); messages.add(new ValidationMessage(Source.ProfileValidator, ValidationMessage.IssueType.BUSINESSRULE, pn+"."+base.getPath(), "Binding "+base.getBinding().getValueSet()+" could not be located", ValidationMessage.IssueSeverity.WARNING));
} else if (contextVs == null) { } else if (contextVs == null) {
@ -3266,7 +3266,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()) {
checkTypeDerivation(purl, srcSD, base, derived, ts); checkTypeDerivation(purl, derivedSrc, base, derived, ts);
} }
} }
base.getType().clear(); base.getType().clear();
@ -3338,7 +3338,7 @@ public class ProfileUtilities extends TranslatingUtilities {
// finally, we copy any extensions from source to dest // finally, we copy any extensions from source to dest
for (Extension ex : derived.getExtension()) { for (Extension ex : derived.getExtension()) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, ex.getUrl()); StructureDefinition sd = context.fetchResource(StructureDefinition.class, ex.getUrl(), derivedSrc);
if (sd == null || sd.getSnapshot() == null || sd.getSnapshot().getElementFirstRep().getMax().equals("1")) { if (sd == null || sd.getSnapshot() == null || sd.getSnapshot().getElementFirstRep().getMax().equals("1")) {
ToolingExtensions.removeExtension(dest, ex.getUrl()); ToolingExtensions.removeExtension(dest, ex.getUrl());
} }
@ -3369,7 +3369,7 @@ public class ProfileUtilities extends TranslatingUtilities {
StructureDefinition sdb = context.fetchTypeDefinition(t); StructureDefinition sdb = context.fetchTypeDefinition(t);
while (sdb != null && !ok) { while (sdb != null && !ok) {
ok = sdb.getType().equals(sdt.getType()); ok = sdb.getType().equals(sdt.getType());
sdb = context.fetchResource(StructureDefinition.class, sdb.getBaseDefinition()); sdb = context.fetchResource(StructureDefinition.class, sdb.getBaseDefinition(), sdb);
} }
} }
} }
@ -3616,7 +3616,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (!child.getPath().endsWith(".id")) { if (!child.getPath().endsWith(".id")) {
List<StructureDefinition> sdl = new ArrayList<>(); List<StructureDefinition> sdl = new ArrayList<>();
sdl.add(ed); sdl.add(ed);
genElement(defFile == null ? "" : defFile+"-definitions.html#extension.", gen, r.getSubRows(), child, ed.getSnapshot().getElement(), sdl, true, defFile, true, full, corePath, imagePath, true, false, false, false, null, false, rc, ""); genElement(defFile == null ? "" : defFile+"-definitions.html#extension.", gen, r.getSubRows(), child, ed.getSnapshot().getElement(), sdl, true, defFile, true, full, corePath, imagePath, true, false, false, false, null, false, rc, "", ed);
} }
} else if (deep) { } else if (deep) {
List<ElementDefinition> children = new ArrayList<ElementDefinition>(); List<ElementDefinition> children = new ArrayList<ElementDefinition>();
@ -3729,7 +3729,7 @@ public class ProfileUtilities extends TranslatingUtilities {
List<TypeRefComponent> types = e.getType(); List<TypeRefComponent> types = e.getType();
if (!e.hasType()) { if (!e.hasType()) {
if (root) { // we'll use base instead of types then if (root) { // we'll use base instead of types then
StructureDefinition bsd = profile == null ? null : context.fetchResource(StructureDefinition.class, profile.getBaseDefinition()); StructureDefinition bsd = profile == null ? null : context.fetchResource(StructureDefinition.class, profile.getBaseDefinition(), profile);
if (bsd != null) { if (bsd != null) {
if (bsd.hasUserData("path")) { if (bsd.hasUserData("path")) {
c.getPieces().add(gen.new Piece(Utilities.isAbsoluteUrl(bsd.getUserString("path")) ? bsd.getUserString("path") : imagePath +bsd.getUserString("path"), bsd.getName(), null)); c.getPieces().add(gen.new Piece(Utilities.isAbsoluteUrl(bsd.getUserString("path")) ? bsd.getUserString("path") : imagePath +bsd.getUserString("path"), bsd.getName(), null));
@ -3780,7 +3780,7 @@ public class ProfileUtilities extends TranslatingUtilities {
tfirst = false; tfirst = false;
else else
c.addPiece(gen.new Piece(null, " | ", null)); c.addPiece(gen.new Piece(null, " | ", null));
genTargetLink(gen, profileBaseFileName, corePath, c, t, u.getValue()); genTargetLink(gen, profileBaseFileName, corePath, c, t, u.getValue(), null);
if (!mustSupportMode && isMustSupport(u) && e.getMustSupport()) { if (!mustSupportMode && isMustSupport(u) && e.getMustSupport()) {
c.addPiece(gen.new Piece(null, " ", null)); c.addPiece(gen.new Piece(null, " ", null));
c.addStyledText(translate("sd.table", "This target must be supported"), "S", "white", "red", null, false); c.addStyledText(translate("sd.table", "This target must be supported"), "S", "white", "red", null, false);
@ -3863,9 +3863,9 @@ public class ProfileUtilities extends TranslatingUtilities {
return Utilities.isAbsoluteUrl(url) ? url : prefix + url; return Utilities.isAbsoluteUrl(url) ? url : prefix + url;
} }
public void genTargetLink(HierarchicalTableGenerator gen, String profileBaseFileName, String corePath, Cell c, TypeRefComponent t, String u) { public void genTargetLink(HierarchicalTableGenerator gen, String profileBaseFileName, String corePath, Cell c, TypeRefComponent t, String u, Resource src) {
if (u.startsWith("http://hl7.org/fhir/StructureDefinition/")) { if (u.startsWith("http://hl7.org/fhir/StructureDefinition/")) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, u); StructureDefinition sd = context.fetchResource(StructureDefinition.class, u, src);
if (sd != null) { if (sd != null) {
String disp = sd.hasTitle() ? sd.getTitle() : sd.getName(); String disp = sd.hasTitle() ? sd.getTitle() : sd.getName();
c.addPiece(checkForNoChange(t, gen.new Piece(checkPrepend(corePath, sd.getUserString("path")), disp, null))); c.addPiece(checkForNoChange(t, gen.new Piece(checkPrepend(corePath, sd.getUserString("path")), disp, null)));
@ -3874,7 +3874,7 @@ public class ProfileUtilities extends TranslatingUtilities {
c.addPiece(checkForNoChange(t, gen.new Piece(pkp.getLinkFor(corePath, rn), rn, null))); c.addPiece(checkForNoChange(t, gen.new Piece(pkp.getLinkFor(corePath, rn), rn, null)));
} }
} else if (Utilities.isAbsoluteUrl(u)) { } else if (Utilities.isAbsoluteUrl(u)) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, u); StructureDefinition sd = context.fetchResource(StructureDefinition.class, u, src);
if (sd != null && pkp != null) { if (sd != null && pkp != null) {
String disp = sd.hasTitle() ? sd.getTitle() : sd.getName(); String disp = sd.hasTitle() ? sd.getTitle() : sd.getName();
String ref = pkp.getLinkForProfile(null, sd.getUrl()); String ref = pkp.getLinkForProfile(null, sd.getUrl());
@ -3949,7 +3949,7 @@ public class ProfileUtilities extends TranslatingUtilities {
url = source.getUrl(); url = source.getUrl();
} }
if (!url.equals(source.getUrl())) { if (!url.equals(source.getUrl())) {
source = context.fetchResource(StructureDefinition.class, url); source = context.fetchResource(StructureDefinition.class, url, source);
if (source == null) { if (source == null) {
throw new FHIRException("Unable to resolve StructureDefinition "+url+" resolving content reference "+contentReference); throw new FHIRException("Unable to resolve StructureDefinition "+url+" resolving content reference "+contentReference);
} }
@ -3973,7 +3973,7 @@ public class ProfileUtilities extends TranslatingUtilities {
String url = contentReference.substring(0, contentReference.indexOf("#")); String url = contentReference.substring(0, contentReference.indexOf("#"));
contentReference = contentReference.substring(contentReference.indexOf("#")); contentReference = contentReference.substring(contentReference.indexOf("#"));
if (!url.equals(source.getUrl())){ if (!url.equals(source.getUrl())){
source = context.fetchResource(StructureDefinition.class, url); source = context.fetchResource(StructureDefinition.class, url, source);
if (source == null) { if (source == null) {
return null; return null;
} }
@ -4148,7 +4148,7 @@ public class ProfileUtilities extends TranslatingUtilities {
profiles.add(profile); profiles.add(profile);
keyRows.clear(); keyRows.clear();
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, mustSupport, rc, anchorPrefix); 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, mustSupport, rc, anchorPrefix, profile);
try { try {
return gen.generate(model, imagePath, 0, outputTracker); return gen.generate(model, imagePath, 0, outputTracker);
} catch (org.hl7.fhir.exceptions.FHIRException e) { } catch (org.hl7.fhir.exceptions.FHIRException e) {
@ -4244,7 +4244,7 @@ public class ProfileUtilities extends TranslatingUtilities {
private Row genElement(String defPath, HierarchicalTableGenerator gen, List<Row> rows, ElementDefinition element, List<ElementDefinition> all, List<StructureDefinition> profiles, boolean showMissing, String profileBaseFileName, Boolean extensions, private Row genElement(String defPath, HierarchicalTableGenerator gen, List<Row> rows, ElementDefinition element, List<ElementDefinition> all, List<StructureDefinition> profiles, boolean showMissing, String profileBaseFileName, Boolean extensions,
boolean snapshot, String corePath, String imagePath, boolean root, boolean logicalModel, boolean isConstraintMode, boolean allInvariants, Row slicingRow, boolean mustSupport, RenderingContext rc, String anchorPrefix) throws IOException, FHIRException { boolean snapshot, String corePath, String imagePath, boolean root, boolean logicalModel, boolean isConstraintMode, boolean allInvariants, Row slicingRow, boolean mustSupport, RenderingContext rc, String anchorPrefix, Resource srcSD) throws IOException, FHIRException {
Row originalRow = slicingRow; Row originalRow = slicingRow;
StructureDefinition profile = profiles == null ? null : profiles.get(profiles.size()-1); StructureDefinition profile = profiles == null ? null : profiles.get(profiles.size()-1);
Row typesRow = null; Row typesRow = null;
@ -4393,7 +4393,7 @@ public class ProfileUtilities extends TranslatingUtilities {
Row childRow = chooseChildRowByGroup(gen, currRow, groups, child, element, isConstraintMode); Row childRow = chooseChildRowByGroup(gen, currRow, groups, child, element, isConstraintMode);
if (logicalModel || !child.getPath().endsWith(".id") || (child.getPath().endsWith(".id") && (profile != null) && (profile.getDerivation() == TypeDerivationRule.CONSTRAINT))) { if (logicalModel || !child.getPath().endsWith(".id") || (child.getPath().endsWith(".id") && (profile != null) && (profile.getDerivation() == TypeDerivationRule.CONSTRAINT))) {
currRow = genElement(defPath, gen, childRow.getSubRows(), child, all, profiles, showMissing, profileBaseFileName, isExtension, snapshot, corePath, imagePath, false, logicalModel, isConstraintMode, allInvariants, currRow, mustSupport, rc, anchorPrefix); currRow = genElement(defPath, gen, childRow.getSubRows(), child, all, profiles, showMissing, profileBaseFileName, isExtension, snapshot, corePath, imagePath, false, logicalModel, isConstraintMode, allInvariants, currRow, mustSupport, rc, anchorPrefix, srcSD);
} }
} }
} }
@ -4403,7 +4403,7 @@ public class ProfileUtilities extends TranslatingUtilities {
// genElement(defPath, gen, row.getSubRows(), child, all, profiles, showMissing, profileBaseFileName, true, false, corePath, imagePath, false, logicalModel, isConstraintMode, allInvariants); // genElement(defPath, gen, row.getSubRows(), child, all, profiles, showMissing, profileBaseFileName, true, false, corePath, imagePath, false, logicalModel, isConstraintMode, allInvariants);
} }
if (typesRow != null && !element.prohibited()) { if (typesRow != null && !element.prohibited()) {
makeChoiceRows(typesRow.getSubRows(), element, gen, corePath, profileBaseFileName, mustSupport); makeChoiceRows(typesRow.getSubRows(), element, gen, corePath, profileBaseFileName, mustSupport, srcSD);
} }
} }
return slicingRow; return slicingRow;
@ -4600,7 +4600,7 @@ public class ProfileUtilities extends TranslatingUtilities {
return key != null && key.startsWith("ele-") || key.startsWith("res-") || key.startsWith("ext-") || key.startsWith("dom-") || key.startsWith("dr-"); return key != null && key.startsWith("ele-") || key.startsWith("res-") || key.startsWith("ext-") || key.startsWith("dom-") || key.startsWith("dr-");
} }
private void makeChoiceRows(List<Row> subRows, ElementDefinition element, HierarchicalTableGenerator gen, String corePath, String profileBaseFileName, boolean mustSupportMode) { private void makeChoiceRows(List<Row> subRows, ElementDefinition element, HierarchicalTableGenerator gen, String corePath, String profileBaseFileName, boolean mustSupportMode, Resource src) {
// create a child for each choice // create a child for each choice
for (TypeRefComponent tr : element.getType()) { for (TypeRefComponent tr : element.getType()) {
if (!mustSupportMode || allTypesMustSupport(element) || isMustSupport(tr)) { if (!mustSupportMode || allTypesMustSupport(element) || isMustSupport(tr)) {
@ -4629,7 +4629,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (!mustSupportMode || allProfilesMustSupport(tr.getTargetProfile()) || isMustSupport(rt)) { if (!mustSupportMode || allProfilesMustSupport(tr.getTargetProfile()) || isMustSupport(rt)) {
if (!first) if (!first)
c.getPieces().add(gen.new Piece(null, " | ", null)); c.getPieces().add(gen.new Piece(null, " | ", null));
genTargetLink(gen, profileBaseFileName, corePath, c, tr, rt.getValue()); genTargetLink(gen, profileBaseFileName, corePath, c, tr, rt.getValue(), src);
if (!mustSupportMode && isMustSupport(rt) && element.getMustSupport()) { if (!mustSupportMode && isMustSupport(rt) && element.getMustSupport()) {
c.addPiece(gen.new Piece(null, " ", null)); c.addPiece(gen.new Piece(null, " ", null));
c.addStyledText(translate("sd.table", "This target must be supported"), "S", "white", "red", null, false); c.addStyledText(translate("sd.table", "This target must be supported"), "S", "white", "red", null, false);
@ -4680,7 +4680,7 @@ public class ProfileUtilities extends TranslatingUtilities {
for (CanonicalType pt : tr.getProfile()) { for (CanonicalType pt : tr.getProfile()) {
if (!mustSupportMode || allProfilesMustSupport(tr.getProfile()) || isMustSupport(pt)) { if (!mustSupportMode || allProfilesMustSupport(tr.getProfile()) || isMustSupport(pt)) {
if (first) first = false; else typeCell.addPiece(gen.new Piece(null, " | ", null)); if (first) first = false; else typeCell.addPiece(gen.new Piece(null, " | ", null));
StructureDefinition psd = context.fetchResource(StructureDefinition.class, pt.getValue()); StructureDefinition psd = context.fetchResource(StructureDefinition.class, pt.getValue(), src);
if (psd == null) if (psd == null)
typeCell.addPiece(gen.new Piece(null, "?gen-e2?", null)); typeCell.addPiece(gen.new Piece(null, "?gen-e2?", null));
else else
@ -4901,7 +4901,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (!c.getPieces().isEmpty()) if (!c.getPieces().isEmpty())
c.addPiece(gen.new Piece("br")); c.addPiece(gen.new Piece("br"));
String fullUrl = url.startsWith("#") ? baseURL+url : url; String fullUrl = url.startsWith("#") ? baseURL+url : url;
StructureDefinition ed = context.fetchResource(StructureDefinition.class, url); StructureDefinition ed = context.fetchResource(StructureDefinition.class, url, profile);
String ref = null; String ref = null;
String ref2 = null; String ref2 = null;
String fixedUrl = null; String fixedUrl = null;
@ -5417,7 +5417,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (!c.getPieces().isEmpty()) if (!c.getPieces().isEmpty())
c.addPiece(gen.new Piece("br")); c.addPiece(gen.new Piece("br"));
String fullUrl = url.startsWith("#") ? baseURL+url : url; String fullUrl = url.startsWith("#") ? baseURL+url : url;
StructureDefinition ed = context.fetchResource(StructureDefinition.class, url); StructureDefinition ed = context.fetchResource(StructureDefinition.class, url, profile);
String ref = null; String ref = null;
if (ed != null) { if (ed != null) {
String p = ed.getUserString("path"); String p = ed.getUserString("path");
@ -5661,7 +5661,7 @@ public class ProfileUtilities extends TranslatingUtilities {
code = url.substring(1); code = url.substring(1);
} else if (context != null) { } else if (context != null) {
String[] parts = url.split("\\#"); String[] parts = url.split("\\#");
profile = context.fetchResource(StructureDefinition.class, parts[0]); profile = context.fetchResource(StructureDefinition.class, parts[0], source);
code = parts.length == 1 ? null : parts[1]; code = parts.length == 1 ? null : parts[1];
} }
if (profile == null) if (profile == null)
@ -6075,7 +6075,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (!structure.hasSnapshot()) if (!structure.hasSnapshot())
throw new DefinitionException(context.formatMessage(I18nConstants.NEEDS_A_SNAPSHOT)); throw new DefinitionException(context.formatMessage(I18nConstants.NEEDS_A_SNAPSHOT));
StructureDefinition base = context.fetchResource(StructureDefinition.class, structure.getBaseDefinition()); StructureDefinition base = context.fetchResource(StructureDefinition.class, structure.getBaseDefinition(), structure);
if (base != null) { if (base != null) {
SchematronWriter sch = new SchematronWriter(dest, SchematronType.PROFILE, base.getName()); SchematronWriter sch = new SchematronWriter(dest, SchematronType.PROFILE, base.getName());
@ -6479,7 +6479,7 @@ public class ProfileUtilities extends TranslatingUtilities {
sd.getSnapshot().getElement().add(sd.getDifferential().getElementFirstRep().copy()); sd.getSnapshot().getElement().add(sd.getDifferential().getElementFirstRep().copy());
if (sd.hasBaseDefinition()) { if (sd.hasBaseDefinition()) {
StructureDefinition base = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition()); StructureDefinition base = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
if (base == null) if (base == null)
throw new FHIRException(context.formatMessage(I18nConstants.UNABLE_TO_FIND_BASE_DEFINITION_FOR_LOGICAL_MODEL__FROM_, sd.getBaseDefinition(), sd.getUrl())); throw new FHIRException(context.formatMessage(I18nConstants.UNABLE_TO_FIND_BASE_DEFINITION_FOR_LOGICAL_MODEL__FROM_, sd.getBaseDefinition(), sd.getUrl()));
copyElements(sd, base.getSnapshot().getElement()); copyElements(sd, base.getSnapshot().getElement());

View File

@ -13,7 +13,6 @@ import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.r5.conformance.R5ExtensionsLoader.Loadable; import org.hl7.fhir.r5.conformance.R5ExtensionsLoader.Loadable;
import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.context.ContextUtilities;
import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
import org.hl7.fhir.r5.formats.JsonParser; import org.hl7.fhir.r5.formats.JsonParser;
import org.hl7.fhir.r5.model.CanonicalResource; import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CanonicalType; import org.hl7.fhir.r5.model.CanonicalType;
@ -22,6 +21,7 @@ import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent; import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
import org.hl7.fhir.r5.model.PackageInformation;
import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule; import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule;
import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent; import org.hl7.fhir.r5.model.ValueSet.ConceptSetComponent;
import org.hl7.fhir.r5.utils.ResourceSorters; import org.hl7.fhir.r5.utils.ResourceSorters;
@ -64,7 +64,7 @@ public class R5ExtensionsLoader {
private Map<String, Loadable<CodeSystem>> codeSystems; private Map<String, Loadable<CodeSystem>> codeSystems;
private List<Loadable<StructureDefinition>> structures; private List<Loadable<StructureDefinition>> structures;
private IWorkerContext context; private IWorkerContext context;
private PackageVersion pd; private PackageInformation pd;
private JsonParser json; private JsonParser json;
public R5ExtensionsLoader(BasePackageCacheManager pcm, IWorkerContext context) { public R5ExtensionsLoader(BasePackageCacheManager pcm, IWorkerContext context) {
@ -79,7 +79,7 @@ public class R5ExtensionsLoader {
public void load() throws FHIRException, IOException { public void load() throws FHIRException, IOException {
pck = pcm.loadPackage("hl7.fhir.r5.core", "current"); pck = pcm.loadPackage("hl7.fhir.r5.core", "current");
pd = new PackageVersion(pck.name(), pck.version(), pck.dateAsDate()); pd = new PackageInformation(pck);
String[] types = new String[] { "StructureDefinition", "ValueSet", "CodeSystem" }; String[] types = new String[] { "StructureDefinition", "ValueSet", "CodeSystem" };
json = new JsonParser(); json = new JsonParser();
@ -140,7 +140,7 @@ public class R5ExtensionsLoader {
} }
} }
private void loadValueSet(String url, IWorkerContext context, Map<String, Loadable<ValueSet>> valueSets, Map<String, Loadable<CodeSystem>> codeSystems, PackageVersion pd) throws FHIRFormatError, FileNotFoundException, IOException { private void loadValueSet(String url, IWorkerContext context, Map<String, Loadable<ValueSet>> valueSets, Map<String, Loadable<CodeSystem>> codeSystems, PackageInformation pd) throws FHIRFormatError, FileNotFoundException, IOException {
if (valueSets.containsKey(url)) { if (valueSets.containsKey(url)) {
ValueSet vs = valueSets.get(url).getResource(); ValueSet vs = valueSets.get(url).getResource();
context.cacheResourceFromPackage(vs, pd); context.cacheResourceFromPackage(vs, pd);

View File

@ -84,6 +84,7 @@ import org.hl7.fhir.r5.model.NamingSystem.NamingSystemIdentifierType;
import org.hl7.fhir.r5.model.NamingSystem.NamingSystemUniqueIdComponent; import org.hl7.fhir.r5.model.NamingSystem.NamingSystemUniqueIdComponent;
import org.hl7.fhir.r5.model.OperationDefinition; import org.hl7.fhir.r5.model.OperationDefinition;
import org.hl7.fhir.r5.model.OperationOutcome; import org.hl7.fhir.r5.model.OperationOutcome;
import org.hl7.fhir.r5.model.PackageInformation;
import org.hl7.fhir.r5.model.Parameters; import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent; import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
import org.hl7.fhir.r5.model.PlanDefinition; import org.hl7.fhir.r5.model.PlanDefinition;
@ -116,6 +117,7 @@ import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorCla
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome; import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
import org.hl7.fhir.r5.terminologies.ValueSetExpanderSimple; import org.hl7.fhir.r5.terminologies.ValueSetExpanderSimple;
import org.hl7.fhir.r5.utils.PackageHackerR5; import org.hl7.fhir.r5.utils.PackageHackerR5;
import org.hl7.fhir.r5.utils.ResourceUtilities;
import org.hl7.fhir.r5.utils.ToolingExtensions; import org.hl7.fhir.r5.utils.ToolingExtensions;
import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier; import org.hl7.fhir.r5.utils.validation.ValidationContextCarrier;
import org.hl7.fhir.utilities.OIDUtils; import org.hl7.fhir.utilities.OIDUtils;
@ -138,6 +140,8 @@ import javax.annotation.Nonnull;
public abstract class BaseWorkerContext extends I18nBase implements IWorkerContext{ public abstract class BaseWorkerContext extends I18nBase implements IWorkerContext{
private static final boolean QA_CHECK_REFERENCE_SOURCE = true;
public class ResourceProxy { public class ResourceProxy {
private Resource resource; private Resource resource;
private CanonicalResourceProxy proxy; private CanonicalResourceProxy proxy;
@ -251,6 +255,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
protected ILoggingService logger = new SystemOutLoggingService(); protected ILoggingService logger = new SystemOutLoggingService();
protected Parameters expParameters; protected Parameters expParameters;
private TranslationServices translator = new NullTranslator(); private TranslationServices translator = new NullTranslator();
private Map<String, PackageInformation> packages = new HashMap<>();
@Getter @Getter
protected TerminologyCache txCache; protected TerminologyCache txCache;
@ -337,10 +342,13 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
} }
public void registerResourceFromPackage(CanonicalResourceProxy r, PackageVersion packageInfo) throws FHIRException { public void registerResourceFromPackage(CanonicalResourceProxy r, PackageInformation packageInfo) throws FHIRException {
PackageHackerR5.fixLoadedResource(r, packageInfo); PackageHackerR5.fixLoadedResource(r, packageInfo);
synchronized (lock) { synchronized (lock) {
if (packageInfo != null) {
packages.put(packageInfo.getVID(), packageInfo);
}
if (r.getId() != null) { if (r.getId() != null) {
Map<String, ResourceProxy> map = allResourcesById.get(r.getType()); Map<String, ResourceProxy> map = allResourcesById.get(r.getType());
if (map == null) { if (map == null) {
@ -419,9 +427,13 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
} }
} }
public void cacheResourceFromPackage(Resource r, PackageVersion packageInfo) throws FHIRException { public void cacheResourceFromPackage(Resource r, PackageInformation packageInfo) throws FHIRException {
synchronized (lock) { synchronized (lock) {
if (packageInfo != null) {
packages.put(packageInfo.getVID(), packageInfo);
}
if (r.getId() != null) { if (r.getId() != null) {
Map<String, ResourceProxy> map = allResourcesById.get(r.fhirType()); Map<String, ResourceProxy> map = allResourcesById.get(r.fhirType());
if (map == null) { if (map == null) {
@ -714,9 +726,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
} }
@Override @Override
public ValueSetExpansionOutcome expandVS(ElementDefinitionBindingComponent binding, boolean cacheOk, boolean heirarchical) throws FHIRException { public ValueSetExpansionOutcome expandVS(Resource src, ElementDefinitionBindingComponent binding, boolean cacheOk, boolean heirarchical) throws FHIRException {
ValueSet vs = null; ValueSet vs = null;
vs = fetchResource(ValueSet.class, binding.getValueSet()); vs = fetchResource(ValueSet.class, binding.getValueSet(), src);
if (vs == null) { if (vs == null) {
throw new FHIRException(formatMessage(I18nConstants.UNABLE_TO_RESOLVE_VALUE_SET_, binding.getValueSet())); throw new FHIRException(formatMessage(I18nConstants.UNABLE_TO_RESOLVE_VALUE_SET_, binding.getValueSet()));
} }
@ -1240,18 +1252,18 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
private boolean addDependentResources(Parameters pin, ValueSet vs) { private boolean addDependentResources(Parameters pin, ValueSet vs) {
boolean cache = false; boolean cache = false;
for (ConceptSetComponent inc : vs.getCompose().getInclude()) { for (ConceptSetComponent inc : vs.getCompose().getInclude()) {
cache = addDependentResources(pin, inc) || cache; cache = addDependentResources(pin, inc, vs) || cache;
} }
for (ConceptSetComponent inc : vs.getCompose().getExclude()) { for (ConceptSetComponent inc : vs.getCompose().getExclude()) {
cache = addDependentResources(pin, inc) || cache; cache = addDependentResources(pin, inc, vs) || cache;
} }
return cache; return cache;
} }
private boolean addDependentResources(Parameters pin, ConceptSetComponent inc) { private boolean addDependentResources(Parameters pin, ConceptSetComponent inc, Resource src) {
boolean cache = false; boolean cache = false;
for (CanonicalType c : inc.getValueSet()) { for (CanonicalType c : inc.getValueSet()) {
ValueSet vs = fetchResource(ValueSet.class, c.getValue()); ValueSet vs = fetchResource(ValueSet.class, c.getValue(), src);
if (vs != null) { if (vs != null) {
pin.addParameter().setName("tx-resource").setResource(vs); pin.addParameter().setName("tx-resource").setResource(vs);
if (isTxCaching && cacheId == null || !cached.contains(vs.getVUrl())) { if (isTxCaching && cacheId == null || !cached.contains(vs.getVUrl())) {
@ -1261,7 +1273,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
addDependentResources(pin, vs); addDependentResources(pin, vs);
} }
} }
CodeSystem cs = fetchResource(CodeSystem.class, inc.getSystem()); CodeSystem cs = fetchResource(CodeSystem.class, inc.getSystem(), src);
if (cs != null && (cs.getContent() == CodeSystemContentMode.COMPLETE || cs.getContent() == CodeSystemContentMode.FRAGMENT)) { if (cs != null && (cs.getContent() == CodeSystemContentMode.COMPLETE || cs.getContent() == CodeSystemContentMode.FRAGMENT)) {
pin.addParameter().setName("tx-resource").setResource(cs); pin.addParameter().setName("tx-resource").setResource(cs);
if (isTxCaching && cacheId == null || !cached.contains(cs.getVUrl())) { if (isTxCaching && cacheId == null || !cached.contains(cs.getVUrl())) {
@ -1285,9 +1297,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
if (p.getName().equals("result")) { if (p.getName().equals("result")) {
ok = ((BooleanType) p.getValue()).getValue().booleanValue(); ok = ((BooleanType) p.getValue()).getValue().booleanValue();
} else if (p.getName().equals("message")) { } else if (p.getName().equals("message")) {
message = ((StringType) p.getValue()).getValue(); message = p.getValue().primitiveValue();
} else if (p.getName().equals("display")) { } else if (p.getName().equals("display")) {
display = ((StringType) p.getValue()).getValue(); display = p.getValue().primitiveValue();
} else if (p.getName().equals("system")) { } else if (p.getName().equals("system")) {
system = ((PrimitiveType<?>) p.getValue()).asStringValue(); system = ((PrimitiveType<?>) p.getValue()).asStringValue();
} else if (p.getName().equals("code")) { } else if (p.getName().equals("code")) {
@ -1398,16 +1410,33 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
return fetchResourceWithExceptionByVersion(cls, uri, null, null); return fetchResourceWithExceptionByVersion(cls, uri, null, null);
} }
public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri, CanonicalResource source) throws FHIRException { public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri, Resource sourceForReference) throws FHIRException {
return fetchResourceWithExceptionByVersion(class_, uri, null, source); return fetchResourceWithExceptionByVersion(class_, uri, null, sourceForReference);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public <T extends Resource> T fetchResourceWithExceptionByVersion(Class<T> class_, String uri, String version, CanonicalResource source) throws FHIRException { public <T extends Resource> T fetchResourceWithExceptionByVersion(Class<T> class_, String uri, String version, Resource sourceForReference) throws FHIRException {
if (uri == null) { if (uri == null) {
return null; return null;
} }
if (QA_CHECK_REFERENCE_SOURCE) {
// it can be tricky to trace the source of a reference correctly. The code isn't water tight,
// particularly around snapshot generation. Enable this code to check that the references are
// correct (but it's slow)
if (sourceForReference != null && uri.contains("ValueSet")) {
if (!ResourceUtilities.hasURL(uri, sourceForReference)) {
System.out.print("Claimed source doesn't have url in it: "+sourceForReference.fhirType()+"/"+sourceForReference.getIdPart()+" -> "+uri);
System.out.println();
}
}
}
List<String> pvlist = new ArrayList<>();
if (sourceForReference != null && sourceForReference.getSourcePackage() != null) {
populatePVList(pvlist, sourceForReference.getSourcePackage());
}
if (class_ == StructureDefinition.class) { if (class_ == StructureDefinition.class) {
uri = ProfileUtilities.sdNs(uri, null); uri = ProfileUtilities.sdNs(uri, null);
} }
@ -1426,49 +1455,49 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
} }
if (class_ == Resource.class || class_ == null) { if (class_ == Resource.class || class_ == null) {
if (structures.has(uri)) { if (structures.has(uri)) {
return (T) structures.get(uri, version); return (T) structures.get(uri, version, pvlist);
} }
if (guides.has(uri)) { if (guides.has(uri)) {
return (T) guides.get(uri, version); return (T) guides.get(uri, version, pvlist);
} }
if (capstmts.has(uri)) { if (capstmts.has(uri)) {
return (T) capstmts.get(uri, version); return (T) capstmts.get(uri, version, pvlist);
} }
if (measures.has(uri)) { if (measures.has(uri)) {
return (T) measures.get(uri, version); return (T) measures.get(uri, version, pvlist);
} }
if (libraries.has(uri)) { if (libraries.has(uri)) {
return (T) libraries.get(uri, version); return (T) libraries.get(uri, version, pvlist);
} }
if (valueSets.has(uri)) { if (valueSets.has(uri)) {
return (T) valueSets.get(uri, version); return (T) valueSets.get(uri, version, pvlist);
} }
if (codeSystems.has(uri)) { if (codeSystems.has(uri)) {
return (T) codeSystems.get(uri, version); return (T) codeSystems.get(uri, version, pvlist);
} }
if (operations.has(uri)) { if (operations.has(uri)) {
return (T) operations.get(uri, version); return (T) operations.get(uri, version, pvlist);
} }
if (searchParameters.has(uri)) { if (searchParameters.has(uri)) {
return (T) searchParameters.get(uri, version); return (T) searchParameters.get(uri, version, pvlist);
} }
if (plans.has(uri)) { if (plans.has(uri)) {
return (T) plans.get(uri, version); return (T) plans.get(uri, version, pvlist);
} }
if (maps.has(uri)) { if (maps.has(uri)) {
return (T) maps.get(uri, version); return (T) maps.get(uri, version, pvlist);
} }
if (transforms.has(uri)) { if (transforms.has(uri)) {
return (T) transforms.get(uri, version); return (T) transforms.get(uri, version, pvlist);
} }
if (actors.has(uri)) { if (actors.has(uri)) {
return (T) transforms.get(uri, version); return (T) transforms.get(uri, version, pvlist);
} }
if (requirements.has(uri)) { if (requirements.has(uri)) {
return (T) transforms.get(uri, version); return (T) transforms.get(uri, version, pvlist);
} }
if (questionnaires.has(uri)) { if (questionnaires.has(uri)) {
return (T) questionnaires.get(uri, version); return (T) questionnaires.get(uri, version, pvlist);
} }
for (Map<String, ResourceProxy> rt : allResourcesById.values()) { for (Map<String, ResourceProxy> rt : allResourcesById.values()) {
@ -1493,47 +1522,47 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
// } // }
return null; return null;
} else if (class_ == ImplementationGuide.class) { } else if (class_ == ImplementationGuide.class) {
return (T) guides.get(uri, version); return (T) guides.get(uri, version, pvlist);
} else if (class_ == CapabilityStatement.class) { } else if (class_ == CapabilityStatement.class) {
return (T) capstmts.get(uri, version); return (T) capstmts.get(uri, version, pvlist);
} else if (class_ == Measure.class) { } else if (class_ == Measure.class) {
return (T) measures.get(uri, version); return (T) measures.get(uri, version, pvlist);
} else if (class_ == Library.class) { } else if (class_ == Library.class) {
return (T) libraries.get(uri, version); return (T) libraries.get(uri, version, pvlist);
} else if (class_ == StructureDefinition.class) { } else if (class_ == StructureDefinition.class) {
return (T) structures.get(uri, version); return (T) structures.get(uri, version, pvlist);
} else if (class_ == StructureMap.class) { } else if (class_ == StructureMap.class) {
return (T) transforms.get(uri, version); return (T) transforms.get(uri, version, pvlist);
} else if (class_ == ValueSet.class) { } else if (class_ == ValueSet.class) {
return (T) valueSets.get(uri, version); return (T) valueSets.get(uri, version, pvlist);
} else if (class_ == CodeSystem.class) { } else if (class_ == CodeSystem.class) {
return (T) codeSystems.get(uri, version); return (T) codeSystems.get(uri, version, pvlist);
} else if (class_ == ConceptMap.class) { } else if (class_ == ConceptMap.class) {
return (T) maps.get(uri, version); return (T) maps.get(uri, version, pvlist);
} else if (class_ == ActorDefinition.class) { } else if (class_ == ActorDefinition.class) {
return (T) actors.get(uri, version); return (T) actors.get(uri, version, pvlist);
} else if (class_ == Requirements.class) { } else if (class_ == Requirements.class) {
return (T) requirements.get(uri, version); return (T) requirements.get(uri, version, pvlist);
} else if (class_ == PlanDefinition.class) { } else if (class_ == PlanDefinition.class) {
return (T) plans.get(uri, version); return (T) plans.get(uri, version, pvlist);
} else if (class_ == OperationDefinition.class) { } else if (class_ == OperationDefinition.class) {
OperationDefinition od = operations.get(uri, version); OperationDefinition od = operations.get(uri, version);
return (T) od; return (T) od;
} else if (class_ == Questionnaire.class) { } else if (class_ == Questionnaire.class) {
return (T) questionnaires.get(uri, version); return (T) questionnaires.get(uri, version, pvlist);
} else if (class_ == SearchParameter.class) { } else if (class_ == SearchParameter.class) {
SearchParameter res = searchParameters.get(uri, version); SearchParameter res = searchParameters.get(uri, version, pvlist);
return (T) res; return (T) res;
} }
if (class_ == CodeSystem.class && codeSystems.has(uri)) { if (class_ == CodeSystem.class && codeSystems.has(uri)) {
return (T) codeSystems.get(uri, version); return (T) codeSystems.get(uri, version, pvlist);
} }
if (class_ == ValueSet.class && valueSets.has(uri)) { if (class_ == ValueSet.class && valueSets.has(uri)) {
return (T) valueSets.get(uri, version); return (T) valueSets.get(uri, version, pvlist);
} }
if (class_ == Questionnaire.class) { if (class_ == Questionnaire.class) {
return (T) questionnaires.get(uri, version); return (T) questionnaires.get(uri, version, pvlist);
} }
if (supportedCodeSystems.contains(uri)) { if (supportedCodeSystems.contains(uri)) {
return null; return null;
@ -1542,7 +1571,26 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
} }
} }
public PackageVersion getPackageForUrl(String uri) { private void populatePVList(List<String> pvlist, PackageInformation sourcePackage) {
pvlist.add(sourcePackage.getVID());
List<String> toadd = new ArrayList<>();
do {
toadd.clear();
for (String s : pvlist) {
PackageInformation pi = packages.get(s);
if (pi != null) {
for (String v : pi.getDependencies()) {
if (!pvlist.contains(v) && !toadd.contains(v)) {
toadd.add(v);
}
}
}
}
pvlist.addAll(toadd);
} while (toadd.size() > 0);
}
public PackageInformation getPackageForUrl(String uri) {
if (uri == null) { if (uri == null) {
return null; return null;
} }
@ -1836,9 +1884,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
} }
} }
public <T extends Resource> T fetchResource(Class<T> class_, String uri, CanonicalResource source) { public <T extends Resource> T fetchResource(Class<T> class_, String uri, Resource sourceForReference) {
try { try {
return fetchResourceWithException(class_, uri, source); return fetchResourceWithException(class_, uri, sourceForReference);
} catch (FHIRException e) { } catch (FHIRException e) {
throw new Error(e); throw new Error(e);
} }

View File

@ -3,9 +3,9 @@ package org.hl7.fhir.r5.context;
import java.util.*; import java.util.*;
import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
import org.hl7.fhir.r5.model.CanonicalResource; import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.PackageInformation;
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities; import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
import org.hl7.fhir.utilities.VersionUtilities; import org.hl7.fhir.utilities.VersionUtilities;
@ -110,15 +110,15 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
private class CachedCanonicalResource<T1 extends CanonicalResource> { private class CachedCanonicalResource<T1 extends CanonicalResource> {
private T1 resource; private T1 resource;
private CanonicalResourceProxy proxy; private CanonicalResourceProxy proxy;
private PackageVersion packageInfo; private PackageInformation packageInfo;
public CachedCanonicalResource(T1 resource, PackageVersion packageInfo) { public CachedCanonicalResource(T1 resource, PackageInformation packageInfo) {
super(); super();
this.resource = resource; this.resource = resource;
this.packageInfo = packageInfo; this.packageInfo = packageInfo;
} }
public CachedCanonicalResource(CanonicalResourceProxy proxy, PackageVersion packageInfo) { public CachedCanonicalResource(CanonicalResourceProxy proxy, PackageInformation packageInfo) {
super(); super();
this.proxy = proxy; this.proxy = proxy;
this.packageInfo = packageInfo; this.packageInfo = packageInfo;
@ -134,13 +134,13 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
synchronized (this) { synchronized (this) {
resource = res; resource = res;
} }
resource.setUserData("package", packageInfo); resource.setSourcePackage(packageInfo);
proxy = null; proxy = null;
} }
return resource; return resource;
} }
public PackageVersion getPackageInfo() { public PackageInformation getPackageInfo() {
return packageInfo; return packageInfo;
} }
public String getUrl() { public String getUrl() {
@ -158,7 +158,7 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
@Override @Override
public String toString() { public String toString() {
return resource != null ? resource.fhirType()+"/"+resource.getId()+": "+resource.getUrl()+"|"+resource.getVersion() : proxy.toString(); return resource != null ? resource.fhirType()+"/"+resource.getId()+"["+resource.getUrl()+"|"+resource.getVersion()+"]" : proxy.toString();
} }
} }
@ -188,6 +188,8 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
private boolean enforceUniqueId; private boolean enforceUniqueId;
private List<CachedCanonicalResource<T>> list = new ArrayList<>(); private List<CachedCanonicalResource<T>> list = new ArrayList<>();
private Map<String, List<CachedCanonicalResource<T>>> listForId = new HashMap<>();
private Map<String, List<CachedCanonicalResource<T>>> listForUrl = new HashMap<>();
private Map<String, CachedCanonicalResource<T>> map = new HashMap<>(); private Map<String, CachedCanonicalResource<T>> map = new HashMap<>();
private String version; // for debugging purposes private String version; // for debugging purposes
@ -215,7 +217,7 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
map.putAll(source.map); map.putAll(source.map);
} }
public void register(CanonicalResourceProxy r, PackageVersion packgeInfo) { public void register(CanonicalResourceProxy r, PackageInformation packgeInfo) {
if (!r.hasId()) { if (!r.hasId()) {
throw new FHIRException("An id is required for a deferred load resource"); throw new FHIRException("An id is required for a deferred load resource");
} }
@ -223,7 +225,7 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
see(cr); see(cr);
} }
public void see(T r, PackageVersion packgeInfo) { public void see(T r, PackageInformation packgeInfo) {
if (r != null) { if (r != null) {
if (!r.hasId()) { if (!r.hasId()) {
r.setId(UUID.randomUUID().toString()); r.setId(UUID.randomUUID().toString());
@ -234,21 +236,27 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
} }
public void see(CachedCanonicalResource<T> cr) { public void see(CachedCanonicalResource<T> cr) {
// -- 1. exit conditions -----------------------------------------------------------------------------
// ignore UTG NUCC erroneous code system // ignore UTG NUCC erroneous code system
if (cr.getPackageInfo() != null if (cr.getPackageInfo() != null
&& cr.getPackageInfo().getId() != null && cr.getPackageInfo().getId() != null
&& cr.getPackageInfo().getId().startsWith("hl7.terminology") && cr.getPackageInfo().getId().startsWith("hl7.terminology")
&& Arrays.stream(INVALID_TERMINOLOGY_URLS).anyMatch((it)->it.equals(cr.getUrl())) && Arrays.stream(INVALID_TERMINOLOGY_URLS).anyMatch((it)->it.equals(cr.getUrl()))) {
) { return;
}
if (map.get(cr.getUrl()) != null && (cr.getPackageInfo() != null && cr.getPackageInfo().isExamplesPackage())) {
return; return;
}
if (enforceUniqueId && map.containsKey(cr.getId())) {
drop(cr.getId());
} }
// -- 2. preparation -----------------------------------------------------------------------------
if (cr.resource != null) { if (cr.resource != null) {
cr.resource.setUserData("package", cr.getPackageInfo()); cr.resource.setSourcePackage(cr.getPackageInfo());
}
// -- 3. deleting existing content ---------------------------------------------------------------
if (enforceUniqueId && map.containsKey(cr.getId())) {
drop(cr.getId());
} }
// special case logic for UTG support prior to version 5 // special case logic for UTG support prior to version 5
@ -260,33 +268,104 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
} }
} }
for (CachedCanonicalResource<T> n : toDrop) { for (CachedCanonicalResource<T> n : toDrop) {
drop(n.getId()); drop(n);
} }
} }
CachedCanonicalResource<T> existing = cr.hasVersion() ? map.get(cr.getUrl()+"|"+cr.getVersion()) : map.get(cr.getUrl()+"|#0"); // CachedCanonicalResource<T> existing = cr.hasVersion() ? map.get(cr.getUrl()+"|"+cr.getVersion()) : map.get(cr.getUrl()+"|#0");
if (map.get(cr.getUrl()) != null && (cr.getPackageInfo() != null && cr.getPackageInfo().isExamplesPackage())) { // if (existing != null) {
return; // drop(existing); // was list.remove(existing)
} // }
if (existing != null) {
list.remove(existing);
}
// -- 4. ok we add it to the list ---------------------------------------------------------------
if (!enforceUniqueId) {
if (!listForId.containsKey(cr.getId())) {
listForId.put(cr.getId(), new ArrayList<>());
}
List<CachedCanonicalResource<T>> set = listForId.get(cr.getId());
set.add(cr);
}
list.add(cr); list.add(cr);
map.put(cr.getId(), cr); // we do this so we can drop by id if (!listForUrl.containsKey(cr.getUrl())) {
map.put(cr.getUrl(), cr); listForUrl.put(cr.getUrl(), new ArrayList<>());
}
List<CachedCanonicalResource<T>> set = listForUrl.get(cr.getUrl());
set.add(cr);
Collections.sort(set, new MetadataResourceVersionComparator<CachedCanonicalResource<T>>());
if (cr.getUrl() != null) { // -- 4. add to the map all the ways ---------------------------------------------------------------
// first, this is the correct reosurce for this version (if it has a version) String pv = cr.getPackageInfo() != null ? cr.getPackageInfo().getVID() : null;
if (cr.hasVersion()) { map.put(cr.getId(), cr); // we do this so we can drop by id - if not enforcing id, it's just the most recent resource with this id
map.put(cr.getUrl()+"|"+cr.getVersion(), cr); map.put(cr.hasVersion() ? cr.getUrl()+"|"+cr.getVersion() : cr.getUrl()+"|#0", cr);
} else { if (pv != null) {
map.put(cr.getUrl()+"|#0", cr); map.put(pv+":"+(cr.hasVersion() ? cr.getUrl()+"|"+cr.getVersion() : cr.getUrl()+"|#0"), cr);
}
int ndx = set.indexOf(cr);
if (ndx == set.size()-1) {
map.put(cr.getUrl(), cr);
if (pv != null) {
map.put(pv+":"+cr.getUrl(), cr);
}
}
String mm = VersionUtilities.getMajMin(cr.getVersion());
if (mm != null) {
if (pv != null) {
map.put(pv+":"+cr.getUrl()+"|"+mm, cr);
}
if (set.size() - 1 == ndx) {
map.put(cr.getUrl()+"|"+mm, cr);
} else {
for (int i = set.size() - 1; i > ndx; i--) {
if (mm.equals(VersionUtilities.getMajMin(set.get(i).getVersion()))) {
return;
}
map.put(cr.getUrl()+"|"+mm, cr);
}
} }
updateList(cr.getUrl(), cr.getVersion());
} }
} }
private boolean isBasePackage(PackageVersion packageInfo) { public void drop(CachedCanonicalResource<T> cr) {
while (map.values().remove(cr));
list.remove(cr);
List<CachedCanonicalResource<T>> set = listForUrl.get(cr.getUrl());
if (set != null) { // it really should be
boolean last = set.indexOf(cr) == set.size()-1;
set.remove(cr);
if (!set.isEmpty()) {
CachedCanonicalResource<T> crl = set.get(set.size()-1);
if (last) {
map.put(crl.getUrl(), crl);
}
String mm = VersionUtilities.getMajMin(cr.getVersion());
if (mm != null) {
for (int i = set.size()-1; i >= 0; i--) {
if (mm.equals(VersionUtilities.getMajMin(set.get(i).getVersion()))) {
map.put(cr.getUrl()+"|"+mm, set.get(i));
break;
}
}
}
}
}
}
public void drop(String id) {
if (enforceUniqueId) {
CachedCanonicalResource<T> cr = map.get(id);
if (cr != null) {
drop(cr);
}
} else {
List<CachedCanonicalResource<T>> set = listForId.get(id);
if (set != null) { // it really should be
for (CachedCanonicalResource<T> i : set) {
drop(i);
}
}
}
}
private boolean isBasePackage(PackageInformation packageInfo) {
return packageInfo == null ? false : VersionUtilities.isCorePackage(packageInfo.getId()); return packageInfo == null ? false : VersionUtilities.isCorePackage(packageInfo.getId());
} }
@ -299,7 +378,6 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
} }
if (rl.size() > 0) { if (rl.size() > 0) {
// sort by version as much as we are able // sort by version as much as we are able
Collections.sort(rl, new MetadataResourceVersionComparator<CachedCanonicalResource<T>>());
// the current is the latest // the current is the latest
map.put(url, rl.get(rl.size()-1)); map.put(url, rl.get(rl.size()-1));
// now, also, the latest for major/minor // now, also, the latest for major/minor
@ -320,27 +398,23 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
} }
public T get(String url) {
return map.containsKey(url) ? map.get(url).getResource() : null;
}
public PackageVersion getPackageInfo(String system, String version) {
if (version == null) {
return map.containsKey(system) ? map.get(system).getPackageInfo() : null;
} else {
if (map.containsKey(system+"|"+version))
return map.get(system+"|"+version).getPackageInfo();
String mm = VersionUtilities.getMajMin(version);
if (mm != null && map.containsKey(system+"|"+mm))
return map.get(system+"|"+mm).getPackageInfo();
else
return null;
}
}
public boolean has(String url) { public boolean has(String url) {
return map.containsKey(url); return map.containsKey(url);
} }
public boolean has(String system, String version) {
if (map.containsKey(system+"|"+version))
return true;
String mm = VersionUtilities.getMajMin(version);
if (mm != null)
return map.containsKey(system+"|"+mm);
else
return false;
}
public T get(String url) {
return map.containsKey(url) ? map.get(url).getResource() : null;
}
public T get(String system, String version) { public T get(String system, String version) {
if (version == null) { if (version == null) {
@ -356,45 +430,75 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
} }
} }
public boolean has(String system, String version) {
if (map.containsKey(system+"|"+version)) /**
return true; * This is asking for a packaged version aware resolution
String mm = VersionUtilities.getMajMin(version); *
if (mm != null) * if we can resolve the reference in the package dependencies, we will. if we can't
return map.containsKey(system+"|"+mm); * then we fall back to the non-package approach
else *
return false; * The context has to prepare the pvlist based on the original package
* @param url
* @param srcInfo
* @return
*/
public T get(String url, List<String> pvlist) {
for (String pv : pvlist) {
if (map.containsKey(pv+":"+url)) {
return map.get(pv+":"+url).getResource();
}
}
return map.containsKey(url) ? map.get(url).getResource() : null;
} }
public T get(String system, String version, List<String> pvlist) {
if (version == null) {
return get(system, pvlist);
} else {
for (String pv : pvlist) {
if (map.containsKey(pv+":"+system+"|"+version))
return map.get(pv+":"+system+"|"+version).getResource();
}
String mm = VersionUtilities.getMajMin(version);
if (mm != null && map.containsKey(system+"|"+mm))
for (String pv : pvlist) {
if (map.containsKey(pv+":"+system+"|"+mm))
return map.get(pv+":"+system+"|"+mm).getResource();
}
if (map.containsKey(system+"|"+version))
return map.get(system+"|"+version).getResource();
if (mm != null && map.containsKey(system+"|"+mm))
return map.get(system+"|"+mm).getResource();
else
return null;
}
}
public PackageInformation getPackageInfo(String system, String version) {
if (version == null) {
return map.containsKey(system) ? map.get(system).getPackageInfo() : null;
} else {
if (map.containsKey(system+"|"+version))
return map.get(system+"|"+version).getPackageInfo();
String mm = VersionUtilities.getMajMin(version);
if (mm != null && map.containsKey(system+"|"+mm))
return map.get(system+"|"+mm).getPackageInfo();
else
return null;
}
}
public int size() { public int size() {
return list.size(); return list.size();
} }
public void drop(String id) {
CachedCanonicalResource<T> res = null;
do {
res = null;
for (CachedCanonicalResource<T> t : list) {
if (t.getId().equals(id)) {
res = t;
}
}
if (res != null) {
list.remove(res);
map.remove(id);
map.remove(res.getUrl());
if (res.hasVersion()) {
map.remove(res.getUrl()+"|"+res.getVersion());
String mm = VersionUtilities.getMajMin(res.getVersion());
if (mm != null) {
map.remove(res.getUrl()+"|"+mm);
}
}
updateList(res.getUrl(), res.getVersion());
}
} while (res != null);
}
public void listAll(List<T> result) { public void listAll(List<T> result) {
for (CachedCanonicalResource<T> t : list) { for (CachedCanonicalResource<T> t : list) {
@ -437,5 +541,6 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
public boolean isEnforceUniqueId() { public boolean isEnforceUniqueId() {
return enforceUniqueId; return enforceUniqueId;
} }
} }

View File

@ -239,7 +239,7 @@ public class ContextUtilities implements ProfileKnowledgeProvider {
if ((!p.hasSnapshot() || isProfileNeedsRegenerate(p) ) && (ifLogical || p.getKind() != StructureDefinitionKind.LOGICAL)) { if ((!p.hasSnapshot() || isProfileNeedsRegenerate(p) ) && (ifLogical || p.getKind() != StructureDefinitionKind.LOGICAL)) {
if (!p.hasBaseDefinition()) if (!p.hasBaseDefinition())
throw new DefinitionException(context.formatMessage(I18nConstants.PROFILE___HAS_NO_BASE_AND_NO_SNAPSHOT, p.getName(), p.getUrl())); throw new DefinitionException(context.formatMessage(I18nConstants.PROFILE___HAS_NO_BASE_AND_NO_SNAPSHOT, p.getName(), p.getUrl()));
StructureDefinition sd = context.fetchResource(StructureDefinition.class, p.getBaseDefinition()); StructureDefinition sd = context.fetchResource(StructureDefinition.class, p.getBaseDefinition(), p);
if (sd == null && "http://hl7.org/fhir/StructureDefinition/Base".equals(p.getBaseDefinition())) { if (sd == null && "http://hl7.org/fhir/StructureDefinition/Base".equals(p.getBaseDefinition())) {
sd = ProfileUtilities.makeBaseDefinition(p.getFhirVersion()); sd = ProfileUtilities.makeBaseDefinition(p.getFhirVersion());
} }

View File

@ -8,19 +8,19 @@ import java.util.Date;
/* /*
Copyright (c) 2011+, HL7, Inc. Copyright (c) 2011+, HL7, Inc.
All rights reserved. All rights reserved.
Redistribution and use in source and binary forms, with or without modification, Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met: are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright notice, this * Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer. list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright notice, * Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution. and/or other materials provided with the distribution.
* Neither the name of HL7 nor the names of its contributors may be used to * Neither the name of HL7 nor the names of its contributors may be used to
endorse or promote products derived from this software without specific endorse or promote products derived from this software without specific
prior written permission. prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
@ -31,7 +31,7 @@ import java.util.Date;
WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE. POSSIBILITY OF SUCH DAMAGE.
*/ */
@ -58,6 +58,7 @@ import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.ConceptMap; import org.hl7.fhir.r5.model.ConceptMap;
import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent; import org.hl7.fhir.r5.model.ElementDefinition.ElementDefinitionBindingComponent;
import org.hl7.fhir.r5.model.NamingSystem; import org.hl7.fhir.r5.model.NamingSystem;
import org.hl7.fhir.r5.model.PackageInformation;
import org.hl7.fhir.r5.model.Parameters; import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
@ -102,7 +103,7 @@ import javax.annotation.Nonnull;
*/ */
public interface IWorkerContext { public interface IWorkerContext {
class ValidationResult { class ValidationResult {
private ConceptDefinitionComponent definition; private ConceptDefinitionComponent definition;
private String system; private String system;
@ -110,7 +111,7 @@ public interface IWorkerContext {
private String message; private String message;
private TerminologyServiceErrorClass errorClass; private TerminologyServiceErrorClass errorClass;
private String txLink; private String txLink;
@Override @Override
public String toString() { public String toString() {
return "ValidationResult [definition=" + definition + ", system=" + system + ", severity=" + severity + ", message=" + message + ", errorClass=" return "ValidationResult [definition=" + definition + ", system=" + system + ", severity=" + severity + ", message=" + message + ", errorClass="
@ -121,7 +122,7 @@ public interface IWorkerContext {
this.severity = severity; this.severity = severity;
this.message = message; this.message = message;
} }
public ValidationResult(String system, ConceptDefinitionComponent definition) { public ValidationResult(String system, ConceptDefinitionComponent definition) {
this.system = system; this.system = system;
this.definition = definition; this.definition = definition;
@ -133,7 +134,7 @@ public interface IWorkerContext {
this.system = system; this.system = system;
this.definition = definition; this.definition = definition;
} }
public ValidationResult(IssueSeverity severity, String message, TerminologyServiceErrorClass errorClass) { public ValidationResult(IssueSeverity severity, String message, TerminologyServiceErrorClass errorClass) {
this.severity = severity; this.severity = severity;
this.message = message; this.message = message;
@ -207,7 +208,7 @@ public interface IWorkerContext {
public boolean hasMessage() { public boolean hasMessage() {
return message != null; return message != null;
} }
public Coding asCoding() { public Coding asCoding() {
if (isOk() && definition != null && definition.getCode() != null) { if (isOk() && definition != null && definition.getCode() != null) {
return new Coding(system, definition.getCode(), definition.getDisplay()); return new Coding(system, definition.getCode(), definition.getDisplay());
@ -221,7 +222,7 @@ public interface IWorkerContext {
private Coding coding; private Coding coding;
private ValidationResult result; private ValidationResult result;
private CacheToken cacheToken; private CacheToken cacheToken;
public CodingValidationRequest(Coding coding) { public CodingValidationRequest(Coding coding) {
super(); super();
this.coding = coding; this.coding = coding;
@ -260,86 +261,17 @@ public interface IWorkerContext {
public void setCacheToken(CacheToken cacheToken) { public void setCacheToken(CacheToken cacheToken) {
this.cacheToken = cacheToken; this.cacheToken = cacheToken;
} }
} }
public class PackageVersion {
private String id;
private String version;
private Date date;
public PackageVersion(String source, Date date) {
if (source == null) {
throw new Error("Source cannot be null");
}
if (!source.contains("#")) {
throw new FHIRException("Source ");
}
id = source.substring(0, source.indexOf("#"));
version = source.substring(source.indexOf("#")+1);
this.date = date;
}
public PackageVersion(String id, String version, Date date) {
super();
this.id = id;
this.version = version;
this.date = date;
}
public String getId() {
return id;
}
public String getVersion() {
return version;
}
public boolean isExamplesPackage() {
boolean b = id.startsWith("hl7.fhir.") && id.endsWith(".examples");
return b;
}
@Override
public String toString() {
return id+"#"+version;
}
public Date getDate() {
return date;
}
public boolean isHTO() {
boolean b = id.startsWith("hl7.terminology.r");
return b;
}
}
public class PackageDetails extends PackageVersion {
private String name;
private String canonical;
private String web;
public PackageDetails(String id, String version, String name, String canonical, String web, Date date) {
super(id, version, date);
this.name = name;
this.canonical = canonical;
this.web = web;
}
public String getName() {
return name;
}
public String getCanonical() {
return canonical;
}
public String getWeb() {
return web;
}
}
public interface IContextResourceLoader { public interface IContextResourceLoader {
/** /**
* @return List of the resource types that should be loaded * @return List of the resource types that should be loaded
*/ */
String[] getTypes(); String[] getTypes();
/** /**
* Request to actually load the resources and do whatever is required * Request to actually load the resources and do whatever is required
* *
@ -350,7 +282,7 @@ public interface IWorkerContext {
* @throws IOException * @throws IOException
*/ */
Bundle loadBundle(InputStream stream, boolean isJson) throws FHIRException, IOException; Bundle loadBundle(InputStream stream, boolean isJson) throws FHIRException, IOException;
/** /**
* Load a single resources (lazy load) * Load a single resources (lazy load)
* *
@ -361,7 +293,7 @@ public interface IWorkerContext {
* @throws IOException * @throws IOException
*/ */
Resource loadResource(InputStream stream, boolean isJson) throws FHIRException, IOException; Resource loadResource(InputStream stream, boolean isJson) throws FHIRException, IOException;
/** /**
* get the path for references to this resource. * get the path for references to this resource.
* @param resource * @param resource
@ -388,7 +320,7 @@ public interface IWorkerContext {
* @return * @return
*/ */
public String getVersion(); public String getVersion();
/** /**
* Get the UCUM service that provides access to units of measure reasoning services * Get the UCUM service that provides access to units of measure reasoning services
* *
@ -438,6 +370,7 @@ public interface IWorkerContext {
*/ */
public <T extends Resource> T fetchResource(Class<T> class_, String uri); public <T extends Resource> T fetchResource(Class<T> class_, String uri);
public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri) throws FHIRException; public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri) throws FHIRException;
public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri, Resource sourceOfReference) throws FHIRException;
public <T extends Resource> T fetchResource(Class<T> class_, String uri, String version); public <T extends Resource> T fetchResource(Class<T> class_, String uri, String version);
/** has the same functionality as fetchResource, but passes in information about the source of the /** has the same functionality as fetchResource, but passes in information about the source of the
@ -449,7 +382,7 @@ public interface IWorkerContext {
* @param canonicalForSource * @param canonicalForSource
* @return * @return
*/ */
public <T extends Resource> T fetchResource(Class<T> class_, String uri, CanonicalResource canonicalForSource); public <T extends Resource> T fetchResource(Class<T> class_, String uri, Resource sourceOfReference);
/** /**
* Fetch all the resources of a particular type. if class == (null | Resource | DomainResource | CanonicalResource) return everything * Fetch all the resources of a particular type. if class == (null | Resource | DomainResource | CanonicalResource) return everything
@ -477,7 +410,7 @@ public interface IWorkerContext {
* @return * @return
*/ */
public Resource fetchResourceById(String type, String uri); public Resource fetchResourceById(String type, String uri);
/** /**
* find whether a resource is available. * find whether a resource is available.
* *
@ -501,7 +434,7 @@ public interface IWorkerContext {
* @throws FHIRException * @throws FHIRException
*/ */
public void cacheResource(Resource res) throws FHIRException; public void cacheResource(Resource res) throws FHIRException;
/** /**
* cache a resource for later retrieval using fetchResource. * cache a resource for later retrieval using fetchResource.
* *
@ -514,8 +447,8 @@ public interface IWorkerContext {
* @param res * @param res
* @throws FHIRException * @throws FHIRException
*/ */
public void cacheResourceFromPackage(Resource res, PackageVersion packageDetails) throws FHIRException; public void cacheResourceFromPackage(Resource res, PackageInformation packageInfo) throws FHIRException;
/** /**
* Inform the cache about package dependencies. This can be used to help resolve references * Inform the cache about package dependencies. This can be used to help resolve references
* *
@ -523,10 +456,10 @@ public interface IWorkerContext {
* *
* @param packageInfo * @param packageInfo
*/ */
public void cachePackage(PackageDetails packageDetails, List<PackageVersion> dependencies); public void cachePackage(PackageInformation packageInfo);
// -- profile services --------------------------------------------------------- // -- profile services ---------------------------------------------------------
/** /**
* @return a list of the resource names defined for this version * @return a list of the resource names defined for this version
*/ */
@ -590,7 +523,7 @@ public interface IWorkerContext {
* @return * @return
*/ */
public ValueSetExpansionOutcome expandVS(ValueSet source, boolean cacheOk, boolean heiarchical); public ValueSetExpansionOutcome expandVS(ValueSet source, boolean cacheOk, boolean heiarchical);
/** /**
* ValueSet Expansion - see $expand * ValueSet Expansion - see $expand
* *
@ -598,7 +531,7 @@ public interface IWorkerContext {
* @return * @return
*/ */
public ValueSetExpansionOutcome expandVS(ValueSet source, boolean cacheOk, boolean heiarchical, boolean incompleteOk); public ValueSetExpansionOutcome expandVS(ValueSet source, boolean cacheOk, boolean heiarchical, boolean incompleteOk);
/** /**
* ValueSet Expansion - see $expand, but resolves the binding first * ValueSet Expansion - see $expand, but resolves the binding first
* *
@ -606,8 +539,8 @@ public interface IWorkerContext {
* @return * @return
* @throws FHIRException * @throws FHIRException
*/ */
public ValueSetExpansionOutcome expandVS(ElementDefinitionBindingComponent binding, boolean cacheOk, boolean heiarchical) throws FHIRException; public ValueSetExpansionOutcome expandVS(Resource src, ElementDefinitionBindingComponent binding, boolean cacheOk, boolean heiarchical) throws FHIRException;
/** /**
* Value set expanion inside the internal expansion engine - used * Value set expanion inside the internal expansion engine - used
* for references to supported system (see "supportsSystem") for * for references to supported system (see "supportsSystem") for
@ -656,7 +589,7 @@ public interface IWorkerContext {
* @return * @return
*/ */
public ValidationResult validateCode(ValidationOptions options, String code, ValueSet vs); public ValidationResult validateCode(ValidationOptions options, String code, ValueSet vs);
/** /**
* Validation of a code - consult the terminology infrstructure and/or service * Validation of a code - consult the terminology infrstructure and/or service
* to see whether it is known. If known, return a description of it * to see whether it is known. If known, return a description of it
@ -672,7 +605,7 @@ public interface IWorkerContext {
* @return * @return
*/ */
public ValidationResult validateCode(ValidationOptions options, String system, String version, String code, String display); public ValidationResult validateCode(ValidationOptions options, String system, String version, String code, String display);
/** /**
* Validation of a code - consult the terminology infrstructure and/or service * Validation of a code - consult the terminology infrstructure and/or service
* to see whether it is known. If known, return a description of it * to see whether it is known. If known, return a description of it
@ -723,7 +656,7 @@ public interface IWorkerContext {
* @return * @return
*/ */
public ValidationResult validateCode(ValidationOptions options, Coding code, ValueSet vs); public ValidationResult validateCode(ValidationOptions options, Coding code, ValueSet vs);
/** /**
* See comments in ValidationContextCarrier. This is called when there might be additional value sets etc * See comments in ValidationContextCarrier. This is called when there might be additional value sets etc
* available in the context, but we don't want to pre-process them. * available in the context, but we don't want to pre-process them.
@ -745,10 +678,10 @@ public interface IWorkerContext {
* @param vs * @param vs
*/ */
public void validateCodeBatch(ValidationOptions options, List<? extends CodingValidationRequest> codes, ValueSet vs); public void validateCodeBatch(ValidationOptions options, List<? extends CodingValidationRequest> codes, ValueSet vs);
// todo: figure these out // todo: figure these out
public Map<String, NamingSystem> getNSUrlMap(); public Map<String, NamingSystem> getNSUrlMap();
public TranslationServices translator(); public TranslationServices translator();
public interface ILoggingService { public interface ILoggingService {
@ -770,7 +703,7 @@ public interface IWorkerContext {
public Set<String> getCodeSystemsUsed(); public Set<String> getCodeSystemsUsed();
public int getClientRetryCount(); public int getClientRetryCount();
public IWorkerContext setClientRetryCount(int value); public IWorkerContext setClientRetryCount(int value);
public TimeTracker clock(); public TimeTracker clock();
/** /**
@ -782,7 +715,7 @@ public interface IWorkerContext {
* @return * @return
*/ */
public StructureDefinition fetchTypeDefinition(String typeName); public StructureDefinition fetchTypeDefinition(String typeName);
/** /**
* Returns a set of keys that can be used to get binaries from this context. * Returns a set of keys that can be used to get binaries from this context.
@ -849,14 +782,14 @@ public interface IWorkerContext {
* @param pcm - used to find and load additional dependencies * @param pcm - used to find and load additional dependencies
* @return the number of resources loaded * @return the number of resources loaded
*/ */
int loadFromPackageAndDependencies(NpmPackage pi, IContextResourceLoader loader, BasePackageCacheManager pcm) throws FileNotFoundException, IOException, FHIRException; int loadFromPackageAndDependencies(NpmPackage pi, IContextResourceLoader loader, BasePackageCacheManager pcm) throws FileNotFoundException, IOException, FHIRException;
public boolean hasPackage(String id, String ver); public boolean hasPackage(String id, String ver);
public boolean hasPackage(PackageVersion pack); public boolean hasPackage(PackageInformation pack);
public PackageDetails getPackage(PackageVersion pack); public PackageInformation getPackage(String id, String ver);
public PackageInformation getPackageForUrl(String url);
public IWorkerContextManager.IPackageLoadingTracker getPackageTracker(); public IWorkerContextManager.IPackageLoadingTracker getPackageTracker();
public IWorkerContext setPackageTracker(IWorkerContextManager.IPackageLoadingTracker packageTracker); public IWorkerContext setPackageTracker(IWorkerContextManager.IPackageLoadingTracker packageTracker);
public PackageVersion getPackageForUrl(String url);
} }

View File

@ -294,7 +294,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
return build(context); return build(context);
} }
public SimpleWorkerContext fromDefinitions(Map<String, byte[]> source, IContextResourceLoader loader, PackageVersion pi) throws IOException, FHIRException { public SimpleWorkerContext fromDefinitions(Map<String, byte[]> source, IContextResourceLoader loader, PackageInformation pi) throws IOException, FHIRException {
SimpleWorkerContext context = getSimpleWorkerContextInstance(); SimpleWorkerContext context = getSimpleWorkerContextInstance();
for (String name : source.keySet()) { for (String name : source.keySet()) {
try { try {
@ -311,7 +311,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
} }
} }
private void loadDefinitionItem(String name, InputStream stream, IContextResourceLoader loader, ILoadFilter filter, PackageVersion pi) throws IOException, FHIRException { private void loadDefinitionItem(String name, InputStream stream, IContextResourceLoader loader, ILoadFilter filter, PackageInformation pi) throws IOException, FHIRException {
if (name.endsWith(".xml")) if (name.endsWith(".xml"))
loadFromFile(stream, name, loader, filter); loadFromFile(stream, name, loader, filter);
else if (name.endsWith(".json")) else if (name.endsWith(".json"))
@ -390,7 +390,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
} }
} }
private void loadFromFileJson(InputStream stream, String name, IContextResourceLoader loader, ILoadFilter filter, PackageVersion pi) throws IOException, FHIRException { private void loadFromFileJson(InputStream stream, String name, IContextResourceLoader loader, ILoadFilter filter, PackageInformation pi) throws IOException, FHIRException {
Bundle f = null; Bundle f = null;
try { try {
if (loader != null) if (loader != null)
@ -487,7 +487,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
} }
for (String s : pi.listResources(types)) { for (String s : pi.listResources(types)) {
try { try {
loadDefinitionItem(s, pi.load("package", s), loader, null, new PackageVersion(pi.id(), pi.version(), pi.dateAsDate())); loadDefinitionItem(s, pi.load("package", s), loader, null, new PackageInformation(pi));
t++; t++;
} catch (Exception e) { } catch (Exception e) {
throw new FHIRException(formatMessage(I18nConstants.ERROR_READING__FROM_PACKAGE__, s, pi.name(), pi.version(), e.getMessage()), e); throw new FHIRException(formatMessage(I18nConstants.ERROR_READING__FROM_PACKAGE__, s, pi.name(), pi.version(), e.getMessage()), e);
@ -500,7 +500,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
for (PackageResourceInformation pri : pi.listIndexedResources(types)) { for (PackageResourceInformation pri : pi.listIndexedResources(types)) {
if (!pri.getFilename().contains("ig-r4")) { if (!pri.getFilename().contains("ig-r4")) {
try { try {
registerResourceFromPackage(new PackageResourceLoader(pri, loader), new PackageVersion(pi.id(), pi.version(), pi.dateAsDate())); registerResourceFromPackage(new PackageResourceLoader(pri, loader), new PackageInformation(pi));
t++; t++;
} catch (FHIRException e) { } catch (FHIRException e) {
throw new FHIRException(formatMessage(I18nConstants.ERROR_READING__FROM_PACKAGE__, pri.getFilename(), pi.name(), pi.version(), e.getMessage()), e); throw new FHIRException(formatMessage(I18nConstants.ERROR_READING__FROM_PACKAGE__, pri.getFilename(), pi.name(), pi.version(), e.getMessage()), e);
@ -672,6 +672,21 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
return r; return r;
} }
@Override
public <T extends Resource> T fetchResource(Class<T> class_, String uri, Resource source) {
T r = super.fetchResource(class_, uri, source);
if (r instanceof StructureDefinition) {
StructureDefinition p = (StructureDefinition)r;
try {
new ContextUtilities(this).generateSnapshot(p);
} catch (Exception e) {
// not sure what to do in this case?
System.out.println("Unable to generate snapshot for "+uri+": "+e.getMessage());
}
}
return r;
}
@ -706,7 +721,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
return xverManager; return xverManager;
} }
public void cachePackage(PackageVersion packageDetails, List<PackageVersion> dependencies) { public void cachePackage(PackageInformation packageInfo) {
// nothing yet // nothing yet
} }
@ -720,17 +735,12 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
} }
@Override @Override
public void cachePackage(PackageDetails packageDetails, List<PackageVersion> dependencies) { public boolean hasPackage(PackageInformation pack) {
// TODO Auto-generated method stub
}
@Override
public boolean hasPackage(PackageVersion pack) {
return false; return false;
} }
@Override @Override
public PackageDetails getPackage(PackageVersion pack) { public PackageInformation getPackage(String id, String ver) {
return null; return null;
} }

View File

@ -942,7 +942,7 @@ public class Element extends Base {
return null; return null;
ICodingImpl c = new ICodingImpl(true, true, false, false); ICodingImpl c = new ICodingImpl(true, true, false, false);
c.code = primitiveValue(); c.code = primitiveValue();
ValueSetExpansionOutcome vse = property.getContext().expandVS(property.getDefinition().getBinding(), true, false); ValueSetExpansionOutcome vse = property.getContext().expandVS(property.getStructure(), property.getDefinition().getBinding(), true, false);
if (vse.getValueset() == null) if (vse.getValueset() == null)
return null; return null;
for (ValueSetExpansionContainsComponent cc : vse.getValueset().getExpansion().getContains()) { for (ValueSetExpansionContainsComponent cc : vse.getValueset().getExpansion().getContains()) {

View File

@ -587,7 +587,7 @@ public abstract class CanonicalResource extends DomainResource {
// Manual code (from Configuration.txt): // Manual code (from Configuration.txt):
@Override @Override
public String toString() { public String toString() {
return fhirType()+"["+getUrl()+"]"; return fhirType()+"["+getUrl()+(hasVersion() ? "|"+getVersion(): "")+"]";
} }
public String present() { public String present() {

View File

@ -0,0 +1,99 @@
package org.hl7.fhir.r5.model;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.hl7.fhir.utilities.npm.NpmPackage;
public class PackageInformation {
private String id;
private String version;
private Date date;
private String name;
private String canonical;
private String web;
private List<String> dependencies = new ArrayList<>();
public PackageInformation(String id, String version, Date date, String name, String canonical, String web) {
super();
this.id = id;
this.version = version;
this.date = date;
this.name = name;
this.canonical = canonical;
this.web = web;
}
public PackageInformation(String src, Date date) {
super();
this.id = src;
this.date = date;
}
public PackageInformation(NpmPackage pi) {
super();
this.id = pi.name();
this.version = pi.version();
this.date = pi.dateAsDate();
this.name = pi.title();
this.canonical = pi.canonical();
this.web = pi.getWebLocation();
dependencies.addAll(pi.dependencies());
}
public PackageInformation(String id, String version, Date date) {
super();
this.id = id;
this.version = version;
this.date = date;
}
public String getId() {
return id;
}
public String getVersion() {
return version;
}
public Date getDate() {
return date;
}
public String getName() {
return name;
}
public String getCanonical() {
return canonical;
}
public String getWeb() {
return web;
}
public List<String> getDependencies() {
return dependencies;
}
public boolean isExamplesPackage() {
boolean b = id.startsWith("hl7.fhir.") && id.endsWith(".examples");
return b;
}
public boolean isHTO() {
boolean b = id.startsWith("hl7.terminology.r");
return b;
}
public String getVID() {
return id+"#"+version;
}
public String toString() {
return getVID();
}
}

View File

@ -446,6 +446,24 @@ public abstract class Resource extends BaseResource implements IAnyResource {
public String getLanguage(String defValue) { public String getLanguage(String defValue) {
return hasLanguage() ? getLanguage() : defValue; return hasLanguage() ? getLanguage() : defValue;
} }
// when possible, the source package is considered when performing reference resolution.
private PackageInformation sourcePackage;
public boolean hasSourcePackage() {
return sourcePackage != null;
}
public PackageInformation getSourcePackage() {
return sourcePackage;
}
public void setSourcePackage(PackageInformation sourcePackage) {
this.sourcePackage = sourcePackage;
}
// end addition // end addition
} }

View File

@ -50,6 +50,7 @@ import org.hl7.fhir.r5.model.ContactPoint;
import org.hl7.fhir.r5.model.ContactPoint.ContactPointSystem; import org.hl7.fhir.r5.model.ContactPoint.ContactPointSystem;
import org.hl7.fhir.r5.model.CapabilityStatement.RestfulCapabilityMode; import org.hl7.fhir.r5.model.CapabilityStatement.RestfulCapabilityMode;
import org.hl7.fhir.r5.model.Enumerations.SearchParamType; import org.hl7.fhir.r5.model.Enumerations.SearchParamType;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.SearchParameter; import org.hl7.fhir.r5.model.SearchParameter;
import org.hl7.fhir.r5.openapi.ParameterWriter.ParameterLocation; import org.hl7.fhir.r5.openapi.ParameterWriter.ParameterLocation;
import org.hl7.fhir.r5.openapi.ParameterWriter.ParameterStyle; import org.hl7.fhir.r5.openapi.ParameterWriter.ParameterStyle;
@ -84,7 +85,7 @@ public class OpenApiGenerator {
for (CapabilityStatementRestComponent csr : source.getRest()) { for (CapabilityStatementRestComponent csr : source.getRest()) {
if (csr.getMode() == RestfulCapabilityMode.SERVER) { if (csr.getMode() == RestfulCapabilityMode.SERVER) {
generatePaths(csr); generatePaths(csr, source);
} }
} }
writeBaseParameters(dest.components()); writeBaseParameters(dest.components());
@ -115,21 +116,21 @@ public class OpenApiGenerator {
.schema().type(SchemaType.number); .schema().type(SchemaType.number);
} }
private void generatePaths(CapabilityStatementRestComponent csr) { private void generatePaths(CapabilityStatementRestComponent csr, Resource cs) {
generateMetadata(); generateMetadata();
for (CapabilityStatementRestResourceComponent r : csr.getResource()) for (CapabilityStatementRestResourceComponent r : csr.getResource())
generateResource(r); generateResource(r, cs);
if (hasOp(csr, SystemRestfulInteraction.HISTORYSYSTEM)) if (hasOp(csr, SystemRestfulInteraction.HISTORYSYSTEM))
generateHistorySystem(csr); generateHistorySystem(csr);
if (hasOp(csr, SystemRestfulInteraction.SEARCHSYSTEM)) if (hasOp(csr, SystemRestfulInteraction.SEARCHSYSTEM))
generateSearchSystem(csr); generateSearchSystem(csr, cs);
if (hasOp(csr, SystemRestfulInteraction.BATCH) || hasOp(csr, SystemRestfulInteraction.TRANSACTION) ) if (hasOp(csr, SystemRestfulInteraction.BATCH) || hasOp(csr, SystemRestfulInteraction.TRANSACTION) )
generateBatchTransaction(csr); generateBatchTransaction(csr);
} }
private void generateResource(CapabilityStatementRestResourceComponent r) { private void generateResource(CapabilityStatementRestResourceComponent r, Resource cs) {
if (hasOp(r, TypeRestfulInteraction.SEARCHTYPE)) if (hasOp(r, TypeRestfulInteraction.SEARCHTYPE))
generateSearch(r); generateSearch(r, cs);
if (hasOp(r, TypeRestfulInteraction.READ)) if (hasOp(r, TypeRestfulInteraction.READ))
generateRead(r); generateRead(r);
if (hasOp(r, TypeRestfulInteraction.CREATE)) if (hasOp(r, TypeRestfulInteraction.CREATE))
@ -189,7 +190,7 @@ public class OpenApiGenerator {
op.paramRef("#/components/parameters/elements"); op.paramRef("#/components/parameters/elements");
} }
private void generateSearch(CapabilityStatementRestResourceComponent r) { private void generateSearch(CapabilityStatementRestResourceComponent r, Resource cs) {
OperationWriter op = makePathResType(r).operation("get"); OperationWriter op = makePathResType(r).operation("get");
op.summary("Search all resources of type "+r.getType()+" based on a set of criteria"); op.summary("Search all resources of type "+r.getType()+" based on a set of criteria");
op.operationId("search"+r.getType()); op.operationId("search"+r.getType());
@ -213,7 +214,7 @@ public class OpenApiGenerator {
p.in(ParameterLocation.query).description(spc.getDocumentation()); p.in(ParameterLocation.query).description(spc.getDocumentation());
p.schema().type(getSchemaType(spc.getType())); p.schema().type(getSchemaType(spc.getType()));
if (spc.hasDefinition()) { if (spc.hasDefinition()) {
SearchParameter sp = context.fetchResource(SearchParameter.class, spc.getDefinition()); SearchParameter sp = context.fetchResource(SearchParameter.class, spc.getDefinition(), cs);
if (sp != null) { if (sp != null) {
p.description(sp.getDescription()); p.description(sp.getDescription());
} }
@ -222,7 +223,7 @@ public class OpenApiGenerator {
} }
} }
private void generateSearchSystem(CapabilityStatementRestComponent csr) { private void generateSearchSystem(CapabilityStatementRestComponent csr, Resource cs) {
OperationWriter op = makePathSystem().operation("get"); OperationWriter op = makePathSystem().operation("get");
op.summary("Search all resources of all types based on a set of criteria"); op.summary("Search all resources of all types based on a set of criteria");
op.operationId("searchAll"); op.operationId("searchAll");
@ -250,7 +251,7 @@ public class OpenApiGenerator {
p.in(ParameterLocation.query).description(spc.getDocumentation()); p.in(ParameterLocation.query).description(spc.getDocumentation());
p.schema().type(getSchemaType(spc.getType())); p.schema().type(getSchemaType(spc.getType()));
if (spc.hasDefinition()) { if (spc.hasDefinition()) {
SearchParameter sp = context.fetchResource(SearchParameter.class, spc.getDefinition()); SearchParameter sp = context.fetchResource(SearchParameter.class, spc.getDefinition(), cs);
if (sp != null) { if (sp != null) {
p.description(sp.getDescription()); p.description(sp.getDescription());
} }

View File

@ -50,7 +50,7 @@ public class ActorDefinitionRenderer extends ResourceRenderer {
if (acd.hasCapabilities()) { if (acd.hasCapabilities()) {
tbl.tr().td().tx("Capabilities:"); tbl.tr().td().tx("Capabilities:");
td = tr.td().colspan("2"); td = tr.td().colspan("2");
CapabilityStatement cs = context.getWorker().fetchResource(CapabilityStatement.class, acd.getCapabilities()); CapabilityStatement cs = context.getWorker().fetchResource(CapabilityStatement.class, acd.getCapabilities(), acd);
if (cs != null) { if (cs != null) {
td.ah(cs.getUserString("path")).tx(cs.present()); td.ah(cs.getUserString("path")).tx(cs.present());
} else { } else {
@ -63,7 +63,7 @@ public class ActorDefinitionRenderer extends ResourceRenderer {
boolean first = true; boolean first = true;
for (UrlType t : acd.getReference()) { for (UrlType t : acd.getReference()) {
if (first) first = false; else x.br(); if (first) first = false; else x.br();
ActorDefinition df = context.getWorker().fetchResource(ActorDefinition.class, t.getValue()); ActorDefinition df = context.getWorker().fetchResource(ActorDefinition.class, t.getValue(), acd);
if (df != null) { if (df != null) {
td.ah(df.getUserString("path")).tx(df.present()); td.ah(df.getUserString("path")).tx(df.present());
} else { } else {

View File

@ -44,12 +44,12 @@ public class ConceptMapRenderer extends TerminologyRenderer {
XhtmlNode p = x.para(); XhtmlNode p = x.para();
p.tx("Mapping from "); p.tx("Mapping from ");
if (cm.hasSourceScope()) if (cm.hasSourceScope())
AddVsRef(cm.getSourceScope().primitiveValue(), p); AddVsRef(cm.getSourceScope().primitiveValue(), p, cm);
else else
p.tx("(not specified)"); p.tx("(not specified)");
p.tx(" to "); p.tx(" to ");
if (cm.hasTargetScope()) if (cm.hasTargetScope())
AddVsRef(cm.getTargetScope().primitiveValue(), p); AddVsRef(cm.getTargetScope().primitiveValue(), p, cm);
else else
p.tx("(not specified)"); p.tx("(not specified)");

View File

@ -763,7 +763,7 @@ public class DataRenderer extends Renderer {
} }
} }
protected void renderUri(XhtmlNode x, UriType uri, String path, String id) { protected void renderUri(XhtmlNode x, UriType uri, String path, String id, Resource src) {
if (isCanonical(path)) { if (isCanonical(path)) {
x.code().tx(uri.getValue()); x.code().tx(uri.getValue());
} else { } else {
@ -773,7 +773,7 @@ public class DataRenderer extends Renderer {
} else if (uri.getValue().startsWith("mailto:")) { } else if (uri.getValue().startsWith("mailto:")) {
x.ah(uri.getValue()).addText(uri.getValue().substring(7)); x.ah(uri.getValue()).addText(uri.getValue().substring(7));
} else { } else {
Resource target = context.getContext().fetchResource(Resource.class, uri.getValue()); Resource target = context.getContext().fetchResource(Resource.class, uri.getValue(), src);
if (target != null && target.hasUserData("path")) { if (target != null && target.hasUserData("path")) {
String title = target instanceof CanonicalResource ? ((CanonicalResource) target).present() : uri.getValue(); String title = target instanceof CanonicalResource ? ((CanonicalResource) target).present() : uri.getValue();
x.ah(target.getUserString("path")).addText(title); x.ah(target.getUserString("path")).addText(title);

View File

@ -52,7 +52,7 @@ public class OperationDefinitionRenderer extends TerminologyRenderer {
if (opd.hasInputProfile()) { if (opd.hasInputProfile()) {
XhtmlNode p = x.para(); XhtmlNode p = x.para();
p.tx("Input parameters Profile: "); p.tx("Input parameters Profile: ");
StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, opd.getInputProfile()); StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, opd.getInputProfile(), opd);
if (sd == null) { if (sd == null) {
p.pre().tx(opd.getInputProfile()); p.pre().tx(opd.getInputProfile());
} else { } else {
@ -62,7 +62,7 @@ public class OperationDefinitionRenderer extends TerminologyRenderer {
if (opd.hasOutputProfile()) { if (opd.hasOutputProfile()) {
XhtmlNode p = x.para(); XhtmlNode p = x.para();
p.tx("Output parameters Profile: "); p.tx("Output parameters Profile: ");
StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, opd.getOutputProfile()); StructureDefinition sd = context.getContext().fetchResource(StructureDefinition.class, opd.getOutputProfile(), opd);
if (sd == null) { if (sd == null) {
p.pre().tx(opd.getOutputProfile()); p.pre().tx(opd.getOutputProfile());
} else { } else {
@ -79,7 +79,7 @@ public class OperationDefinitionRenderer extends TerminologyRenderer {
tr.td().b().tx("Binding"); tr.td().b().tx("Binding");
tr.td().b().tx("Documentation"); tr.td().b().tx("Documentation");
for (OperationDefinitionParameterComponent p : opd.getParameter()) { for (OperationDefinitionParameterComponent p : opd.getParameter()) {
genOpParam(tbl, "", p); genOpParam(tbl, "", p, opd);
} }
addMarkdown(x, opd.getComment()); addMarkdown(x, opd.getComment());
return true; return true;
@ -98,7 +98,7 @@ public class OperationDefinitionRenderer extends TerminologyRenderer {
return ((OperationDefinition) r).present(); return ((OperationDefinition) r).present();
} }
private void genOpParam(XhtmlNode tbl, String path, OperationDefinitionParameterComponent p) throws EOperationOutcome, FHIRException, IOException { private void genOpParam(XhtmlNode tbl, String path, OperationDefinitionParameterComponent p, Resource opd) throws EOperationOutcome, FHIRException, IOException {
XhtmlNode tr; XhtmlNode tr;
tr = tbl.tr(); tr = tbl.tr();
tr.td().addText(p.getUse().toString()); tr.td().addText(p.getUse().toString());
@ -129,13 +129,13 @@ public class OperationDefinitionRenderer extends TerminologyRenderer {
} }
td = tr.td(); td = tr.td();
if (p.hasBinding() && p.getBinding().hasValueSet()) { if (p.hasBinding() && p.getBinding().hasValueSet()) {
AddVsRef(p.getBinding().getValueSet(), td); AddVsRef(p.getBinding().getValueSet(), td, opd);
td.tx(" ("+p.getBinding().getStrength().getDisplay()+")"); td.tx(" ("+p.getBinding().getStrength().getDisplay()+")");
} }
addMarkdown(tr.td(), p.getDocumentation()); addMarkdown(tr.td(), p.getDocumentation());
if (!p.hasType()) { if (!p.hasType()) {
for (OperationDefinitionParameterComponent pp : p.getPart()) { for (OperationDefinitionParameterComponent pp : p.getPart()) {
genOpParam(tbl, path+p.getName()+".", pp); genOpParam(tbl, path+p.getName()+".", pp, opd);
} }
} }
} }

View File

@ -430,7 +430,7 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
renderContactPoint(x, c); renderContactPoint(x, c);
} }
} else if (e instanceof UriType) { } else if (e instanceof UriType) {
renderUri(x, (UriType) e, defn.getPath(), rcontext != null && rcontext.getResource() != null ? rcontext.getResource().getId() : null); renderUri(x, (UriType) e, defn.getPath(), rcontext != null && rcontext.getResource() != null ? rcontext.getResource().getId() : null, res.getResource());
} else if (e instanceof Timing) { } else if (e instanceof Timing) {
renderTiming(x, (Timing) e); renderTiming(x, (Timing) e);
} else if (e instanceof Range) { } else if (e instanceof Range) {
@ -795,7 +795,14 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
RenderingContext ctxt = context.copy(); RenderingContext ctxt = context.copy();
ctxt.setContained(true); ctxt.setContained(true);
ResourceRenderer rnd = RendererFactory.factory(v.fhirType(), ctxt); ResourceRenderer rnd = RendererFactory.factory(v.fhirType(), ctxt);
ResourceWrapper rw = new ElementWrappers.ResourceWrapperMetaElement(ctxt, (org.hl7.fhir.r5.elementmodel.Element) v.getBase()); ResourceWrapper rw = null;
if (v.getBase() instanceof org.hl7.fhir.r5.elementmodel.Element) {
rw = new ElementWrappers.ResourceWrapperMetaElement(ctxt, (org.hl7.fhir.r5.elementmodel.Element) v.getBase());
} else if (v.getBase() instanceof Resource){
rw = new DirectWrappers.ResourceWrapperDirect(ctxt, (Resource) v.getBase());
} else {
throw new FHIRException("Not handled: base = "+v.getBase().getClass().getName());
}
rnd.render(x.blockquote(), rw); rnd.render(x.blockquote(), rw);
} }
} }

View File

@ -289,7 +289,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
if (i.hasDefinition()) { if (i.hasDefinition()) {
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
defn.getPieces().add(gen.new Piece(null, "Definition: ", null)); defn.getPieces().add(gen.new Piece(null, "Definition: ", null));
genDefinitionLink(gen, i, defn); genDefinitionLink(gen, i, defn, q);
} }
if (i.hasEnableWhen()) { if (i.hasEnableWhen()) {
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
@ -318,7 +318,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
defn.getPieces().add(gen.new Piece(vs.getUserString("path"), vs.present(), null)); defn.getPieces().add(gen.new Piece(vs.getUserString("path"), vs.present(), null));
} }
} else { } else {
ValueSet vs = context.getWorker().fetchResource(ValueSet.class, i.getAnswerValueSet()); ValueSet vs = context.getWorker().fetchResource(ValueSet.class, i.getAnswerValueSet(), q);
if (vs == null || !vs.hasUserData("path")) { if (vs == null || !vs.hasUserData("path")) {
defn.getPieces().add(gen.new Piece(null, i.getAnswerValueSet(), null)); defn.getPieces().add(gen.new Piece(null, i.getAnswerValueSet(), null));
} else { } else {
@ -390,7 +390,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
return hasExt; return hasExt;
} }
public void genDefinitionLink(HierarchicalTableGenerator gen, QuestionnaireItemComponent i, Cell defn) { public void genDefinitionLink(HierarchicalTableGenerator gen, QuestionnaireItemComponent i, Cell defn, Questionnaire q) {
// can we resolve the definition? // can we resolve the definition?
String path = null; String path = null;
String d = i.getDefinition(); String d = i.getDefinition();
@ -398,7 +398,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
path = d.substring(d.indexOf("#")+1); path = d.substring(d.indexOf("#")+1);
d = d.substring(0, d.indexOf("#")); d = d.substring(0, d.indexOf("#"));
} }
StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, d); StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, d, q);
if (sd != null) { if (sd != null) {
String url = sd.getUserString("path"); String url = sd.getUserString("path");
if (url != null) { if (url != null) {
@ -411,7 +411,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
} }
} }
public void genDefinitionLink(XhtmlNode x, QuestionnaireItemComponent i) { public void genDefinitionLink(XhtmlNode x, QuestionnaireItemComponent i, Questionnaire q) {
// can we resolve the definition? // can we resolve the definition?
String path = null; String path = null;
String d = i.getDefinition(); String d = i.getDefinition();
@ -419,7 +419,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
path = d.substring(d.indexOf("#")+1); path = d.substring(d.indexOf("#")+1);
d = d.substring(0, d.indexOf("#")); d = d.substring(0, d.indexOf("#"));
} }
StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, d); StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, d, q);
if (sd != null) { if (sd != null) {
String url = sd.getUserString("path"); String url = sd.getUserString("path");
if (url != null) { if (url != null) {
@ -479,7 +479,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
if (i.hasDefinition()) { if (i.hasDefinition()) {
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
defn.getPieces().add(gen.new Piece(null, "Definition: ", null)); defn.getPieces().add(gen.new Piece(null, "Definition: ", null));
genDefinitionLink(gen, i, defn); genDefinitionLink(gen, i, defn, q);
} }
if (i.hasEnableWhen()) { if (i.hasEnableWhen()) {
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br")); if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
@ -497,7 +497,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
defn.getPieces().add(gen.new Piece(vs.getUserString("path"), vs.present(), null)); defn.getPieces().add(gen.new Piece(vs.getUserString("path"), vs.present(), null));
} }
} else { } else {
ValueSet vs = context.getWorker().fetchResource(ValueSet.class, i.getAnswerValueSet()); ValueSet vs = context.getWorker().fetchResource(ValueSet.class, i.getAnswerValueSet(), q);
if (vs == null || !vs.hasUserData("path")) { if (vs == null || !vs.hasUserData("path")) {
defn.getPieces().add(gen.new Piece(null, i.getAnswerValueSet(), null)); defn.getPieces().add(gen.new Piece(null, i.getAnswerValueSet(), null));
} else { } else {
@ -716,7 +716,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
item(ul, "Max Length", Integer.toString(i.getMaxLength())); item(ul, "Max Length", Integer.toString(i.getMaxLength()));
} }
if (i.hasDefinition()) { if (i.hasDefinition()) {
genDefinitionLink(item(ul, "Definition"), i); genDefinitionLink(item(ul, "Definition"), i, q);
} }
if (i.hasEnableWhen()) { if (i.hasEnableWhen()) {
item(ul, "Enable When", "todo"); item(ul, "Enable When", "todo");
@ -731,7 +731,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
ans.ah(vs.getUserString("path")).tx(vs.present()); ans.ah(vs.getUserString("path")).tx(vs.present());
} }
} else { } else {
ValueSet vs = context.getWorker().fetchResource(ValueSet.class, i.getAnswerValueSet()); ValueSet vs = context.getWorker().fetchResource(ValueSet.class, i.getAnswerValueSet(), q);
if (vs == null || !vs.hasUserData("path")) { if (vs == null || !vs.hasUserData("path")) {
ans.tx(i.getAnswerValueSet()); ans.tx(i.getAnswerValueSet());
} else { } else {
@ -819,7 +819,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
vs.setUrl(q.getUrl()+"--"+q.getContained(i.getAnswerValueSet().substring(1))); vs.setUrl(q.getUrl()+"--"+q.getContained(i.getAnswerValueSet().substring(1)));
} }
} else { } else {
vs = context.getContext().fetchResource(ValueSet.class, i.getAnswerValueSet()); vs = context.getContext().fetchResource(ValueSet.class, i.getAnswerValueSet(), q);
} }
if (vs != null) { if (vs != null) {
ValueSetExpansionOutcome exp = context.getContext().expandVS(vs, true, false); ValueSetExpansionOutcome exp = context.getContext().expandVS(vs, true, false);
@ -940,7 +940,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
// content control // content control
defn(tbl, "Max Length", qi.getMaxLength()); defn(tbl, "Max Length", qi.getMaxLength());
if (qi.hasAnswerValueSet()) { if (qi.hasAnswerValueSet()) {
defn(tbl, "Value Set", qi.getDefinition(), context.getWorker().fetchResource(ValueSet.class, qi.getAnswerValueSet())); defn(tbl, "Value Set", qi.getDefinition(), context.getWorker().fetchResource(ValueSet.class, qi.getAnswerValueSet(), q));
} }
if (qi.hasAnswerOption()) { if (qi.hasAnswerOption()) {
XhtmlNode tr = tbl.tr(); XhtmlNode tr = tbl.tr();
@ -983,7 +983,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
// formal definitions // formal definitions
if (qi.hasDefinition()) { if (qi.hasDefinition()) {
genDefinitionLink(defn(tbl, "Definition"), qi); genDefinitionLink(defn(tbl, "Definition"), qi, q);
} }
if (qi.hasCode()) { if (qi.hasCode()) {

View File

@ -225,7 +225,7 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
return hasExt; return hasExt;
} }
public void genDefinitionLink(HierarchicalTableGenerator gen, QuestionnaireResponseItemComponent i, Cell defn) { public void genDefinitionLink(HierarchicalTableGenerator gen, QuestionnaireResponseItemComponent i, Cell defn, Resource src) {
// can we resolve the definition? // can we resolve the definition?
String path = null; String path = null;
String d = i.getDefinition(); String d = i.getDefinition();
@ -233,7 +233,7 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
path = d.substring(d.indexOf("#")+1); path = d.substring(d.indexOf("#")+1);
d = d.substring(0, d.indexOf("#")); d = d.substring(0, d.indexOf("#"));
} }
StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, d); StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, d, src);
if (sd != null) { if (sd != null) {
String url = sd.getUserString("path"); String url = sd.getUserString("path");
if (url != null) { if (url != null) {
@ -246,7 +246,7 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
} }
} }
public void genDefinitionLink(XhtmlNode x, QuestionnaireResponseItemComponent i) { public void genDefinitionLink(XhtmlNode x, QuestionnaireResponseItemComponent i, Resource src) {
// can we resolve the definition? // can we resolve the definition?
String path = null; String path = null;
String d = i.getDefinition(); String d = i.getDefinition();
@ -254,7 +254,7 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
path = d.substring(d.indexOf("#")+1); path = d.substring(d.indexOf("#")+1);
d = d.substring(0, d.indexOf("#")); d = d.substring(0, d.indexOf("#"));
} }
StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, d); StructureDefinition sd = context.getWorker().fetchResource(StructureDefinition.class, d, src);
if (sd != null) { if (sd != null) {
String url = sd.getUserString("path"); String url = sd.getUserString("path");
if (url != null) { if (url != null) {

View File

@ -43,7 +43,7 @@ public class RequirementsRenderer extends ResourceRenderer {
public boolean render(XhtmlNode x, Requirements req) throws FHIRFormatError, DefinitionException, IOException { public boolean render(XhtmlNode x, Requirements req) throws FHIRFormatError, DefinitionException, IOException {
if (req.hasActor()) { if (req.hasActor()) {
if (req.getActor().size() == 1) { if (req.getActor().size() == 1) {
ActorDefinition acd = context.getWorker().fetchResource(ActorDefinition.class, req.getActor().get(0).getValue()); ActorDefinition acd = context.getWorker().fetchResource(ActorDefinition.class, req.getActor().get(0).getValue(), req);
XhtmlNode p = x.para(); XhtmlNode p = x.para();
p.tx("These requirements apply to the actor "); p.tx("These requirements apply to the actor ");
if (acd == null) { if (acd == null) {
@ -55,7 +55,7 @@ public class RequirementsRenderer extends ResourceRenderer {
x.para().tx("These requirements apply to the following actors:"); x.para().tx("These requirements apply to the following actors:");
XhtmlNode ul = x.ul(); XhtmlNode ul = x.ul();
for (CanonicalType a : req.getActor()) { for (CanonicalType a : req.getActor()) {
ActorDefinition acd = context.getWorker().fetchResource(ActorDefinition.class, a.getValue()); ActorDefinition acd = context.getWorker().fetchResource(ActorDefinition.class, a.getValue(), req);
if (acd == null) { if (acd == null) {
ul.li().code(a.getValue()); ul.li().code(a.getValue());
} else { } else {
@ -66,7 +66,7 @@ public class RequirementsRenderer extends ResourceRenderer {
} }
if (req.hasDerivedFrom()) { if (req.hasDerivedFrom()) {
if (req.getDerivedFrom().size() == 1) { if (req.getDerivedFrom().size() == 1) {
Requirements reqd = context.getWorker().fetchResource(Requirements.class, req.getDerivedFrom().get(0).getValue()); Requirements reqd = context.getWorker().fetchResource(Requirements.class, req.getDerivedFrom().get(0).getValue(), req);
XhtmlNode p = x.para(); XhtmlNode p = x.para();
p.tx("These requirements derive from "); p.tx("These requirements derive from ");
if (reqd == null) { if (reqd == null) {
@ -78,7 +78,7 @@ public class RequirementsRenderer extends ResourceRenderer {
x.para().tx("These requirements are derived from the following requirements:"); x.para().tx("These requirements are derived from the following requirements:");
XhtmlNode ul = x.ul(); XhtmlNode ul = x.ul();
for (CanonicalType a : req.getDerivedFrom()) { for (CanonicalType a : req.getDerivedFrom()) {
Requirements reqd = context.getWorker().fetchResource(Requirements.class, a.getValue()); Requirements reqd = context.getWorker().fetchResource(Requirements.class, a.getValue(), req);
if (reqd == null) { if (reqd == null) {
ul.li().code(a.getValue()); ul.li().code(a.getValue());
} else { } else {
@ -118,7 +118,7 @@ public class RequirementsRenderer extends ResourceRenderer {
String url = stmt.getDerivedFrom(); String url = stmt.getDerivedFrom();
String key = url.contains("#") ? url.substring(url.indexOf("#")+1) : ""; String key = url.contains("#") ? url.substring(url.indexOf("#")+1) : "";
if (url.contains("#")) { url = url.substring(0, url.indexOf("#")); }; if (url.contains("#")) { url = url.substring(0, url.indexOf("#")); };
Requirements reqr = context.getWorker().fetchResource(Requirements.class, url); Requirements reqr = context.getWorker().fetchResource(Requirements.class, url, req);
if (reqr != null) { if (reqr != null) {
RequirementsStatementComponent stmtr = reqr.findStatement(key); RequirementsStatementComponent stmtr = reqr.findStatement(key);
if (stmtr != null) { if (stmtr != null) {
@ -140,7 +140,7 @@ public class RequirementsRenderer extends ResourceRenderer {
if (url.contains("#")) { if (url.contains("#")) {
url = url.substring(0, url.indexOf("#")); url = url.substring(0, url.indexOf("#"));
} }
Resource r = context.getWorker().fetchResource(Resource.class, url); Resource r = context.getWorker().fetchResource(Resource.class, url, req);
if (r != null) { if (r != null) {
String desc = getResourceDescription(r, null); String desc = getResourceDescription(r, null);
li.ah(c.getValue()).tx(desc); li.ah(c.getValue()).tx(desc);
@ -174,7 +174,7 @@ public class RequirementsRenderer extends ResourceRenderer {
if (url.contains("#")) { if (url.contains("#")) {
url = url.substring(0, url.indexOf("#")); url = url.substring(0, url.indexOf("#"));
} }
Resource r = context.getWorker().fetchResource(Resource.class, url); Resource r = context.getWorker().fetchResource(Resource.class, url, req);
ResourceWithReference t = null; ResourceWithReference t = null;
if (r == null) { if (r == null) {
t = context.getResolver().resolve(context, url); t = context.getResolver().resolve(context, url);

View File

@ -142,14 +142,14 @@ public abstract class ResourceRenderer extends DataRenderer {
} }
public void renderCanonical(ResourceWrapper rw, XhtmlNode x, String url) throws UnsupportedEncodingException, IOException { public void renderCanonical(ResourceWrapper rw, XhtmlNode x, String url) throws UnsupportedEncodingException, IOException {
renderCanonical(rw, x, url, true); renderCanonical(rw, x, url, true, rw.getResource());
} }
public void renderCanonical(ResourceWrapper rw, XhtmlNode x, String url, boolean allowLinks) throws UnsupportedEncodingException, IOException { public void renderCanonical(ResourceWrapper rw, XhtmlNode x, String url, boolean allowLinks, Resource src) throws UnsupportedEncodingException, IOException {
if (url == null) { if (url == null) {
return; return;
} }
Resource target = context.getWorker().fetchResource(Resource.class, url); Resource target = context.getWorker().fetchResource(Resource.class, url, src);
if (target == null || !(target instanceof CanonicalResource)) { if (target == null || !(target instanceof CanonicalResource)) {
x.code().tx(url); x.code().tx(url);
} else { } else {

View File

@ -135,7 +135,7 @@ public class SearchParameterRenderer extends TerminologyRenderer {
tbl = x.table("grid"); tbl = x.table("grid");
for (SearchParameterComponentComponent t : spd.getComponent()) { for (SearchParameterComponentComponent t : spd.getComponent()) {
tr = tbl.tr(); tr = tbl.tr();
SearchParameter tsp = context.getWorker().fetchResource(SearchParameter.class, t.getDefinition()); SearchParameter tsp = context.getWorker().fetchResource(SearchParameter.class, t.getDefinition(), spd);
if (tsp != null && tsp.hasUserData("path")) { if (tsp != null && tsp.hasUserData("path")) {
tr.td().ah(tsp.getUserString("path")).tx(tsp.present()); tr.td().ah(tsp.getUserString("path")).tx(tsp.present());
} else { } else {

View File

@ -269,7 +269,7 @@ public abstract class TerminologyRenderer extends ResourceRenderer {
} }
protected void AddVsRef(String value, XhtmlNode li) { protected void AddVsRef(String value, XhtmlNode li, Resource source) {
Resource res = null; Resource res = null;
if (rcontext != null) { if (rcontext != null) {
BundleEntryComponent be = rcontext.resolve(value); BundleEntryComponent be = rcontext.resolve(value);
@ -283,13 +283,11 @@ public abstract class TerminologyRenderer extends ResourceRenderer {
} }
CanonicalResource vs = (CanonicalResource) res; CanonicalResource vs = (CanonicalResource) res;
if (vs == null) if (vs == null)
vs = getContext().getWorker().fetchResource(ValueSet.class, value); vs = getContext().getWorker().fetchResource(ValueSet.class, value, source);
if (vs == null) if (vs == null)
vs = getContext().getWorker().fetchResource(StructureDefinition.class, value); vs = getContext().getWorker().fetchResource(StructureDefinition.class, value, source);
// if (vs == null)
// vs = context.getWorker().fetchResource(DataElement.class, value);
if (vs == null) if (vs == null)
vs = getContext().getWorker().fetchResource(Questionnaire.class, value); vs = getContext().getWorker().fetchResource(Questionnaire.class, value, source);
if (vs != null) { if (vs != null) {
String ref = (String) vs.getUserData("path"); String ref = (String) vs.getUserData("path");

View File

@ -106,7 +106,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
re = new ConceptMapRenderInstructions(cm.present(), cm.getUrl(), false); re = new ConceptMapRenderInstructions(cm.present(), cm.getUrl(), false);
} }
if (re != null) { if (re != null) {
ValueSet vst = cm.hasTargetScope() ? getContext().getWorker().fetchResource(ValueSet.class, cm.hasTargetScopeCanonicalType() ? cm.getTargetScopeCanonicalType().getValue() : cm.getTargetScopeUriType().asStringValue()) : null; ValueSet vst = cm.hasTargetScope() ? getContext().getWorker().fetchResource(ValueSet.class, cm.hasTargetScopeCanonicalType() ? cm.getTargetScopeCanonicalType().getValue() : cm.getTargetScopeUriType().asStringValue(), cm) : null;
res.add(new UsedConceptMap(re, vst == null ? cm.getUserString("path") : vst.getUserString("path"), cm)); res.add(new UsedConceptMap(re, vst == null ? cm.getUserString("path") : vst.getUserString("path"), cm));
} }
} }
@ -194,8 +194,8 @@ public class ValueSetRenderer extends TerminologyRenderer {
x.para().tx("This value set contains "+count.toString()+" concepts"); x.para().tx("This value set contains "+count.toString()+" concepts");
} }
generateContentModeNotices(x, vs.getExpansion()); generateContentModeNotices(x, vs.getExpansion(), vs);
generateVersionNotice(x, vs.getExpansion()); generateVersionNotice(x, vs.getExpansion(), vs);
CodeSystem allCS = null; CodeSystem allCS = null;
boolean doLevel = false; boolean doLevel = false;
@ -304,12 +304,12 @@ public class ValueSetRenderer extends TerminologyRenderer {
return false; return false;
} }
private void generateContentModeNotices(XhtmlNode x, ValueSetExpansionComponent expansion) { private void generateContentModeNotices(XhtmlNode x, ValueSetExpansionComponent expansion, Resource vs) {
generateContentModeNotice(x, expansion, "example", "Expansion based on example code system"); generateContentModeNotice(x, expansion, "example", "Expansion based on example code system", vs);
generateContentModeNotice(x, expansion, "fragment", "Expansion based on code system fragment"); generateContentModeNotice(x, expansion, "fragment", "Expansion based on code system fragment", vs);
} }
private void generateContentModeNotice(XhtmlNode x, ValueSetExpansionComponent expansion, String mode, String text) { private void generateContentModeNotice(XhtmlNode x, ValueSetExpansionComponent expansion, String mode, String text, Resource vs) {
Multimap<String, String> versions = HashMultimap.create(); Multimap<String, String> versions = HashMultimap.create();
for (ValueSetExpansionParameterComponent p : expansion.getParameter()) { for (ValueSetExpansionParameterComponent p : expansion.getParameter()) {
if (p.getName().equals(mode)) { if (p.getName().equals(mode)) {
@ -327,7 +327,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
for (String v : versions.get(s)) { // though there'll only be one for (String v : versions.get(s)) { // though there'll only be one
XhtmlNode p = x.para().style("border: black 1px dotted; background-color: #ffcccc; padding: 8px; margin-bottom: 8px"); XhtmlNode p = x.para().style("border: black 1px dotted; background-color: #ffcccc; padding: 8px; margin-bottom: 8px");
p.tx(text+" "); p.tx(text+" ");
expRef(p, s, v); expRef(p, s, v, vs);
} }
} else { } else {
for (String v : versions.get(s)) { for (String v : versions.get(s)) {
@ -337,7 +337,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
ul = div.ul(); ul = div.ul();
first = false; first = false;
} }
expRef(ul.li(), s, v); expRef(ul.li(), s, v, vs);
} }
} }
} }
@ -435,7 +435,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
} }
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
private void generateVersionNotice(XhtmlNode x, ValueSetExpansionComponent expansion) { private void generateVersionNotice(XhtmlNode x, ValueSetExpansionComponent expansion, Resource vs) {
Multimap<String, String> versions = HashMultimap.create(); Multimap<String, String> versions = HashMultimap.create();
for (ValueSetExpansionParameterComponent p : expansion.getParameter()) { for (ValueSetExpansionParameterComponent p : expansion.getParameter()) {
if (p.getName().equals("version")) { if (p.getName().equals("version")) {
@ -453,7 +453,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
for (String v : versions.get(s)) { // though there'll only be one for (String v : versions.get(s)) { // though there'll only be one
XhtmlNode p = x.para().style("border: black 1px dotted; background-color: #EEEEEE; padding: 8px; margin-bottom: 8px"); XhtmlNode p = x.para().style("border: black 1px dotted; background-color: #EEEEEE; padding: 8px; margin-bottom: 8px");
p.tx("Expansion based on "); p.tx("Expansion based on ");
expRef(p, s, v); expRef(p, s, v, vs);
} }
} else { } else {
for (String v : versions.get(s)) { for (String v : versions.get(s)) {
@ -463,14 +463,14 @@ public class ValueSetRenderer extends TerminologyRenderer {
ul = div.ul(); ul = div.ul();
first = false; first = false;
} }
expRef(ul.li(), s, v); expRef(ul.li(), s, v, vs);
} }
} }
} }
} }
} }
private void expRef(XhtmlNode x, String u, String v) { private void expRef(XhtmlNode x, String u, String v, Resource source) {
// TODO Auto-generated method stub // TODO Auto-generated method stub
if (u.equals("http://snomed.info/sct")) { if (u.equals("http://snomed.info/sct")) {
String[] parts = v.split("\\/"); String[] parts = v.split("\\/");
@ -492,7 +492,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
x.tx("Loinc v"+v); x.tx("Loinc v"+v);
} }
} else { } else {
CanonicalResource cr = (CanonicalResource) getContext().getWorker().fetchResource(Resource.class, u+"|"+v); CanonicalResource cr = (CanonicalResource) getContext().getWorker().fetchResource(Resource.class, u+"|"+v, source);
if (cr != null) { if (cr != null) {
if (cr.hasUserData("path")) { if (cr.hasUserData("path")) {
x.ah(cr.getUserString("path")).tx(cr.present()+" v"+v+" ("+cr.fhirType()+")"); x.ah(cr.getUserString("path")).tx(cr.present()+" v"+v+" ("+cr.fhirType()+")");
@ -892,13 +892,13 @@ public class ValueSetRenderer extends TerminologyRenderer {
} }
int index = 0; int index = 0;
if (vs.getCompose().getInclude().size() == 1 && vs.getCompose().getExclude().size() == 0) { if (vs.getCompose().getInclude().size() == 1 && vs.getCompose().getExclude().size() == 0) {
hasExtensions = genInclude(x.ul(), vs.getCompose().getInclude().get(0), "Include", langs, doDesignations, maps, designations, index) || hasExtensions; hasExtensions = genInclude(x.ul(), vs.getCompose().getInclude().get(0), "Include", langs, doDesignations, maps, designations, index, vs) || hasExtensions;
} else { } else {
XhtmlNode p = x.para(); XhtmlNode p = x.para();
p.tx("This value set includes codes based on the following rules:"); p.tx("This value set includes codes based on the following rules:");
XhtmlNode ul = x.ul(); XhtmlNode ul = x.ul();
for (ConceptSetComponent inc : vs.getCompose().getInclude()) { for (ConceptSetComponent inc : vs.getCompose().getInclude()) {
hasExtensions = genInclude(ul, inc, "Include", langs, doDesignations, maps, designations, index) || hasExtensions; hasExtensions = genInclude(ul, inc, "Include", langs, doDesignations, maps, designations, index, vs) || hasExtensions;
index++; index++;
} }
if (vs.getCompose().hasExclude()) { if (vs.getCompose().hasExclude()) {
@ -906,7 +906,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
p.tx("This value set excludes codes based on the following rules:"); p.tx("This value set excludes codes based on the following rules:");
ul = x.ul(); ul = x.ul();
for (ConceptSetComponent exc : vs.getCompose().getExclude()) { for (ConceptSetComponent exc : vs.getCompose().getExclude()) {
hasExtensions = genInclude(ul, exc, "Exclude", langs, doDesignations, maps, designations, index) || hasExtensions; hasExtensions = genInclude(ul, exc, "Exclude", langs, doDesignations, maps, designations, index, vs) || hasExtensions;
index++; index++;
} }
} }
@ -1094,7 +1094,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
} }
} }
private boolean genInclude(XhtmlNode ul, ConceptSetComponent inc, String type, List<String> langs, boolean doDesignations, List<UsedConceptMap> maps, Map<String, String> designations, int index) throws FHIRException, IOException { private boolean genInclude(XhtmlNode ul, ConceptSetComponent inc, String type, List<String> langs, boolean doDesignations, List<UsedConceptMap> maps, Map<String, String> designations, int index, Resource vsRes) throws FHIRException, IOException {
boolean hasExtensions = false; boolean hasExtensions = false;
XhtmlNode li; XhtmlNode li;
li = ul.li(); li = ul.li();
@ -1228,7 +1228,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
first = false; first = false;
else else
li.tx(", "); li.tx(", ");
AddVsRef(vs.asStringValue(), li); AddVsRef(vs.asStringValue(), li, vsRes);
} }
} }
if (inc.hasExtension(ToolingExtensions.EXT_EXPAND_RULES) || inc.hasExtension(ToolingExtensions.EXT_EXPAND_GROUP)) { if (inc.hasExtension(ToolingExtensions.EXT_EXPAND_RULES) || inc.hasExtension(ToolingExtensions.EXT_EXPAND_GROUP)) {
@ -1244,12 +1244,12 @@ public class ValueSetRenderer extends TerminologyRenderer {
first = false; first = false;
else else
li.tx(", "); li.tx(", ");
AddVsRef(vs.asStringValue(), li); AddVsRef(vs.asStringValue(), li, vsRes);
} }
} else { } else {
XhtmlNode xul = li.ul(); XhtmlNode xul = li.ul();
for (UriType vs : inc.getValueSet()) { for (UriType vs : inc.getValueSet()) {
AddVsRef(vs.asStringValue(), xul.li()); AddVsRef(vs.asStringValue(), xul.li(), vsRes);
} }
} }

View File

@ -11,6 +11,7 @@ import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.Narrative.NarrativeStatus; import org.hl7.fhir.r5.model.Narrative.NarrativeStatus;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.renderers.ResourceRenderer; import org.hl7.fhir.r5.renderers.ResourceRenderer;
import org.hl7.fhir.utilities.xhtml.XhtmlNode; import org.hl7.fhir.utilities.xhtml.XhtmlNode;
@ -56,6 +57,7 @@ public class BaseWrappers {
public StructureDefinition getDefinition(); public StructureDefinition getDefinition();
public boolean hasNarrative(); public boolean hasNarrative();
public String getNameFromResource(); public String getNameFromResource();
public Resource getResource(); // if there is one
} }
public interface BaseWrapper extends WrapperBase { public interface BaseWrapper extends WrapperBase {

View File

@ -11,6 +11,7 @@ import org.hl7.fhir.r5.formats.FormatUtilities;
import org.hl7.fhir.r5.model.Base; import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.Property; import org.hl7.fhir.r5.model.Property;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.Narrative.NarrativeStatus; import org.hl7.fhir.r5.model.Narrative.NarrativeStatus;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind; import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
@ -386,7 +387,7 @@ public class DOMWrappers {
if ("DomainResource".equals(sd.getType())) { if ("DomainResource".equals(sd.getType())) {
return true; return true;
} }
sd = context.getWorker().fetchResource(StructureDefinition.class, sd.getBaseDefinition()); sd = context.getWorker().fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
} }
return false; return false;
} }
@ -404,6 +405,11 @@ public class DOMWrappers {
return null; return null;
} }
@Override
public Resource getResource() {
return null;
}
} }

View File

@ -295,7 +295,7 @@ public class DirectWrappers {
if ("DomainResource".equals(sd.getType())) { if ("DomainResource".equals(sd.getType())) {
return true; return true;
} }
sd = context.getWorker().fetchResource(StructureDefinition.class, sd.getBaseDefinition()); sd = context.getWorker().fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
} }
return false; return false;

View File

@ -17,6 +17,7 @@ import org.hl7.fhir.r5.formats.IParser.OutputStyle;
import org.hl7.fhir.r5.model.Base; import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.Property; import org.hl7.fhir.r5.model.Property;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.Narrative.NarrativeStatus; import org.hl7.fhir.r5.model.Narrative.NarrativeStatus;
import org.hl7.fhir.r5.model.StringType; import org.hl7.fhir.r5.model.StringType;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
@ -266,7 +267,7 @@ public class ElementWrappers {
if ("DomainResource".equals(sd.getType())) { if ("DomainResource".equals(sd.getType())) {
return true; return true;
} }
sd = context.getWorker().fetchResource(StructureDefinition.class, sd.getBaseDefinition()); sd = context.getWorker().fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
} }
return false; return false;
} }
@ -288,6 +289,11 @@ public class ElementWrappers {
return wrapped; return wrapped;
} }
@Override
public Resource getResource() {
return null;
}
} }
public static class PropertyWrapperMetaElement extends RendererWrapperImpl implements PropertyWrapper { public static class PropertyWrapperMetaElement extends RendererWrapperImpl implements PropertyWrapper {

View File

@ -43,7 +43,6 @@ import java.util.Set;
import org.hl7.fhir.exceptions.FHIRException; import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.exceptions.NoTerminologyServiceException; import org.hl7.fhir.exceptions.NoTerminologyServiceException;
import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult; import org.hl7.fhir.r5.context.IWorkerContext.ValidationResult;
import org.hl7.fhir.r5.model.CanonicalType; import org.hl7.fhir.r5.model.CanonicalType;
import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem;
@ -53,6 +52,7 @@ import org.hl7.fhir.r5.model.CodeSystem.ConceptDefinitionDesignationComponent;
import org.hl7.fhir.r5.model.CodeableConcept; import org.hl7.fhir.r5.model.CodeableConcept;
import org.hl7.fhir.r5.model.Coding; import org.hl7.fhir.r5.model.Coding;
import org.hl7.fhir.r5.model.Enumerations.PublicationStatus; import org.hl7.fhir.r5.model.Enumerations.PublicationStatus;
import org.hl7.fhir.r5.model.PackageInformation;
import org.hl7.fhir.r5.model.UriType; import org.hl7.fhir.r5.model.UriType;
import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.model.ValueSet;
import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent; import org.hl7.fhir.r5.model.ValueSet.ConceptReferenceComponent;
@ -751,7 +751,13 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
ValidationResult res = context.validateCode(options.noClient(), new Coding(system, code, null), vs); ValidationResult res = context.validateCode(options.noClient(), new Coding(system, code, null), vs);
if (res.getErrorClass() == TerminologyServiceErrorClass.UNKNOWN || res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED || res.getErrorClass() == TerminologyServiceErrorClass.VALUESET_UNSUPPORTED) { if (res.getErrorClass() == TerminologyServiceErrorClass.UNKNOWN || res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED || res.getErrorClass() == TerminologyServiceErrorClass.VALUESET_UNSUPPORTED) {
if (info != null && res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) { if (info != null && res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED) {
// server didn't know the code system either - we'll take it face value
info.getWarnings().add(context.formatMessage(I18nConstants.TERMINOLOGY_TX_SYSTEM_NOTKNOWN, system)); info.getWarnings().add(context.formatMessage(I18nConstants.TERMINOLOGY_TX_SYSTEM_NOTKNOWN, system));
for (ConceptReferenceComponent cc : vsi.getConcept()) {
if (cc.getCode().equals(code)) {
return true;
}
}
info.setErr(TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED); info.setErr(TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED);
} }
return null; return null;
@ -786,7 +792,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
} }
protected boolean isValueSetUnionImports() { protected boolean isValueSetUnionImports() {
PackageVersion p = (PackageVersion) valueset.getUserData("package"); PackageInformation p = (PackageInformation) valueset.getSourcePackage();
if (p != null) { if (p != null) {
return p.getDate().before(new GregorianCalendar(2022, Calendar.MARCH, 31).getTime()); return p.getDate().before(new GregorianCalendar(2022, Calendar.MARCH, 31).getTime());
} else { } else {
@ -853,7 +859,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
if (inner.containsKey(url)) { if (inner.containsKey(url)) {
return inner.get(url); return inner.get(url);
} }
ValueSet vs = context.fetchResource(ValueSet.class, url); ValueSet vs = context.fetchResource(ValueSet.class, url, valueset);
ValueSetCheckerSimple vsc = new ValueSetCheckerSimple(options, vs, context, localContext); ValueSetCheckerSimple vsc = new ValueSetCheckerSimple(options, vs, context, localContext);
inner.put(url, vsc); inner.put(url, vsc);
return vsc; return vsc;

View File

@ -81,7 +81,6 @@ import org.hl7.fhir.exceptions.FHIRFormatError;
import org.hl7.fhir.exceptions.NoTerminologyServiceException; import org.hl7.fhir.exceptions.NoTerminologyServiceException;
import org.hl7.fhir.exceptions.TerminologyServiceException; import org.hl7.fhir.exceptions.TerminologyServiceException;
import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
import org.hl7.fhir.r5.model.BooleanType; import org.hl7.fhir.r5.model.BooleanType;
import org.hl7.fhir.r5.model.CodeSystem; import org.hl7.fhir.r5.model.CodeSystem;
import org.hl7.fhir.r5.model.CodeSystem.CodeSystemContentMode; import org.hl7.fhir.r5.model.CodeSystem.CodeSystemContentMode;
@ -95,6 +94,7 @@ import org.hl7.fhir.r5.model.DateTimeType;
import org.hl7.fhir.r5.model.Enumerations.FilterOperator; import org.hl7.fhir.r5.model.Enumerations.FilterOperator;
import org.hl7.fhir.r5.model.Extension; import org.hl7.fhir.r5.model.Extension;
import org.hl7.fhir.r5.model.Factory; import org.hl7.fhir.r5.model.Factory;
import org.hl7.fhir.r5.model.PackageInformation;
import org.hl7.fhir.r5.model.Parameters; import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent; import org.hl7.fhir.r5.model.Parameters.ParametersParameterComponent;
import org.hl7.fhir.r5.model.PrimitiveType; import org.hl7.fhir.r5.model.PrimitiveType;
@ -508,9 +508,9 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
private ValueSet importValueSet(String value, ValueSetExpansionComponent exp, Parameters expParams, boolean noInactive, ValueSet valueSet) throws ETooCostly, TerminologyServiceException, FileNotFoundException, IOException, FHIRFormatError { private ValueSet importValueSet(String value, ValueSetExpansionComponent exp, Parameters expParams, boolean noInactive, ValueSet valueSet) throws ETooCostly, TerminologyServiceException, FileNotFoundException, IOException, FHIRFormatError {
if (value == null) if (value == null)
throw fail("unable to find value set with no identity"); throw fail("unable to find value set with no identity");
ValueSet vs = context.fetchResource(ValueSet.class, value); ValueSet vs = context.fetchResource(ValueSet.class, value, valueSet);
if (vs == null) { if (vs == null) {
if (context.fetchResource(CodeSystem.class, value) != null) { if (context.fetchResource(CodeSystem.class, value, valueSet) != null) {
throw fail("Cannot include value set "+value+" because it's actually a code system"); throw fail("Cannot include value set "+value+" because it's actually a code system");
} else { } else {
throw fail("Unable to find imported value set " + value); throw fail("Unable to find imported value set " + value);
@ -550,7 +550,7 @@ public class ValueSetExpanderSimple extends ValueSetWorker implements ValueSetEx
protected boolean isValueSetUnionImports(ValueSet valueSet) { protected boolean isValueSetUnionImports(ValueSet valueSet) {
PackageVersion p = (PackageVersion) valueSet.getUserData("package"); PackageInformation p = valueSet.getSourcePackage();
if (p != null) { if (p != null) {
return p.getDate().before(new GregorianCalendar(2022, Calendar.MARCH, 31).getTime()); return p.getDate().before(new GregorianCalendar(2022, Calendar.MARCH, 31).getTime());
} else { } else {

View File

@ -40,6 +40,7 @@ import org.hl7.fhir.exceptions.DefinitionException;
import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent; import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
public class DefinitionNavigator { public class DefinitionNavigator {
@ -164,19 +165,20 @@ public class DefinitionNavigator {
* *
* you have to provide a type if there's more than one type * you have to provide a type if there's more than one type
* for current() since this library doesn't know how to choose * for current() since this library doesn't know how to choose
* @param res
* @throws DefinitionException * @throws DefinitionException
* @ * @
*/ */
public boolean hasTypeChildren(TypeRefComponent type) throws DefinitionException { public boolean hasTypeChildren(TypeRefComponent type, Resource res) throws DefinitionException {
if (typeChildren == null || typeOfChildren != type) { if (typeChildren == null || typeOfChildren != type) {
loadTypedChildren(type); loadTypedChildren(type, res);
} }
return !typeChildren.isEmpty(); return !typeChildren.isEmpty();
} }
private void loadTypedChildren(TypeRefComponent type) throws DefinitionException { private void loadTypedChildren(TypeRefComponent type, Resource src) throws DefinitionException {
typeOfChildren = null; typeOfChildren = null;
StructureDefinition sd = context.fetchResource(StructureDefinition.class, /* GF#13465 : this somehow needs to be revisited type.hasProfile() ? type.getProfile() : */ type.getWorkingCode()); StructureDefinition sd = context.fetchResource(StructureDefinition.class, /* GF#13465 : this somehow needs to be revisited type.hasProfile() ? type.getProfile() : */ type.getWorkingCode(), src);
if (sd != null) { if (sd != null) {
DefinitionNavigator dn = new DefinitionNavigator(context, sd, 0, path, names, sd.getType()); DefinitionNavigator dn = new DefinitionNavigator(context, sd, 0, path, names, sd.getType());
typeChildren = dn.children(); typeChildren = dn.children();
@ -187,13 +189,14 @@ public class DefinitionNavigator {
/** /**
* *
* @param res
* @return * @return
* @throws DefinitionException * @throws DefinitionException
* @ * @
*/ */
public List<DefinitionNavigator> childrenFromType(TypeRefComponent type) throws DefinitionException { public List<DefinitionNavigator> childrenFromType(TypeRefComponent type, Resource res) throws DefinitionException {
if (typeChildren == null || typeOfChildren != type) { if (typeChildren == null || typeOfChildren != type) {
loadTypedChildren(type); loadTypedChildren(type, res);
} }
return typeChildren; return typeChildren;
} }

View File

@ -209,10 +209,12 @@ public class FHIRPathEngine {
public static class TypedElementDefinition { public static class TypedElementDefinition {
private ElementDefinition element; private ElementDefinition element;
private String type; private String type;
public TypedElementDefinition(ElementDefinition element, String type) { private StructureDefinition src;
public TypedElementDefinition(StructureDefinition src, ElementDefinition element, String type) {
super(); super();
this.element = element; this.element = element;
this.type = type; this.type = type;
this.src = src;
} }
public TypedElementDefinition(ElementDefinition element) { public TypedElementDefinition(ElementDefinition element) {
super(); super();
@ -245,6 +247,9 @@ public class FHIRPathEngine {
return false; return false;
} }
} }
public StructureDefinition getSrc() {
return src;
}
} }
private IWorkerContext worker; private IWorkerContext worker;
private IEvaluationContext hostServices; private IEvaluationContext hostServices;
@ -1812,7 +1817,7 @@ public class FHIRPathEngine {
if (tn.equals(sd.getType())) { if (tn.equals(sd.getType())) {
return makeBoolean(true); return makeBoolean(true);
} }
sd = worker.fetchResource(StructureDefinition.class, sd.getBaseDefinition()); sd = worker.fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
} }
return makeBoolean(false); return makeBoolean(false);
} }
@ -2992,7 +2997,7 @@ public class FHIRPathEngine {
result.add(item); result.add(item);
break; break;
} }
sd = worker.fetchResource(StructureDefinition.class, sd.getBaseDefinition()); sd = worker.fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
} }
} }
} else { } else {
@ -4528,7 +4533,7 @@ public class FHIRPathEngine {
if (n.equals(sd.getType())) { if (n.equals(sd.getType())) {
return makeBoolean(true); return makeBoolean(true);
} }
sd = worker.fetchResource(StructureDefinition.class, sd.getBaseDefinition()); sd = worker.fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
} }
return makeBoolean(false); return makeBoolean(false);
} }
@ -4565,7 +4570,7 @@ public class FHIRPathEngine {
result.add(b); result.add(b);
break; break;
} }
sd = worker.fetchResource(StructureDefinition.class, sd.getBaseDefinition()); sd = worker.fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
} }
} }
} }
@ -5534,7 +5539,7 @@ public class FHIRPathEngine {
m = getElementDefinition(sd, type.substring(type.indexOf("#")+1), false, expr); m = getElementDefinition(sd, type.substring(type.indexOf("#")+1), false, expr);
if (m != null && hasDataType(m.definition)) { if (m != null && hasDataType(m.definition)) {
if (m.fixedType != null) { if (m.fixedType != null) {
StructureDefinition dt = worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(m.fixedType, null)); StructureDefinition dt = worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(m.fixedType, null), sd);
if (dt == null) { if (dt == null) {
throw makeException(expr, I18nConstants.FHIRPATH_NO_TYPE, ProfileUtilities.sdNs(m.fixedType, null), "getChildTypesByName"); throw makeException(expr, I18nConstants.FHIRPATH_NO_TYPE, ProfileUtilities.sdNs(m.fixedType, null), "getChildTypesByName");
} }
@ -5693,7 +5698,7 @@ public class FHIRPathEngine {
if (ed.getType().size() > 1) { // if there's more than one type, the test above would fail this if (ed.getType().size() > 1) { // if there's more than one type, the test above would fail this
throw new Error("Internal typing issue...."); throw new Error("Internal typing issue....");
} }
StructureDefinition nsd = worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(ed.getType().get(0).getCode(), null)); StructureDefinition nsd = worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(ed.getType().get(0).getCode(), null), sd);
if (nsd == null) { if (nsd == null) {
throw makeException(expr, I18nConstants.FHIRPATH_NO_TYPE, ed.getType().get(0).getCode(), "getElementDefinition"); throw makeException(expr, I18nConstants.FHIRPATH_NO_TYPE, ed.getType().get(0).getCode(), "getElementDefinition");
} }
@ -5808,7 +5813,7 @@ public class FHIRPathEngine {
if (element.getTypes().get(0).getTargetProfile().size() > 1) { if (element.getTypes().get(0).getTargetProfile().size() > 1) {
throw makeExceptionPlural(element.getTypes().get(0).getTargetProfile().size(), expr, I18nConstants.FHIRPATH_RESOLVE_DISCRIMINATOR_NO_TARGET, element.getElement().getId()); throw makeExceptionPlural(element.getTypes().get(0).getTargetProfile().size(), expr, I18nConstants.FHIRPATH_RESOLVE_DISCRIMINATOR_NO_TARGET, element.getElement().getId());
} }
sd = worker.fetchResource(StructureDefinition.class, element.getTypes().get(0).getTargetProfile().get(0).getValue()); sd = worker.fetchResource(StructureDefinition.class, element.getTypes().get(0).getTargetProfile().get(0).getValue(), profile);
if (sd == null) { if (sd == null) {
throw makeException(expr, I18nConstants.FHIRPATH_RESOLVE_DISCRIMINATOR_CANT_FIND, element.getTypes().get(0).getTargetProfile(), element.getElement().getId()); throw makeException(expr, I18nConstants.FHIRPATH_RESOLVE_DISCRIMINATOR_CANT_FIND, element.getTypes().get(0).getTargetProfile(), element.getElement().getId());
} }
@ -5820,9 +5825,9 @@ public class FHIRPathEngine {
if (t.getPath().endsWith(".extension") && t.hasSliceName()) { if (t.getPath().endsWith(".extension") && t.hasSliceName()) {
System.out.println("t: "+t.getId()); System.out.println("t: "+t.getId());
StructureDefinition exsd = (t.getType() == null || t.getType().isEmpty() || t.getType().get(0).getProfile().isEmpty()) ? StructureDefinition exsd = (t.getType() == null || t.getType().isEmpty() || t.getType().get(0).getProfile().isEmpty()) ?
null : worker.fetchResource(StructureDefinition.class, t.getType().get(0).getProfile().get(0).getValue()); null : worker.fetchResource(StructureDefinition.class, t.getType().get(0).getProfile().get(0).getValue(), profile);
while (exsd != null && !exsd.getBaseDefinition().equals("http://hl7.org/fhir/StructureDefinition/Extension")) { while (exsd != null && !exsd.getBaseDefinition().equals("http://hl7.org/fhir/StructureDefinition/Extension")) {
exsd = worker.fetchResource(StructureDefinition.class, exsd.getBaseDefinition()); exsd = worker.fetchResource(StructureDefinition.class, exsd.getBaseDefinition(), exsd);
} }
if (exsd != null && exsd.getUrl().equals(targetUrl)) { if (exsd != null && exsd.getUrl().equals(targetUrl)) {
if (profileUtilities.getChildMap(sd, t).getList().isEmpty()) { if (profileUtilities.getChildMap(sd, t).getList().isEmpty()) {
@ -5851,7 +5856,7 @@ public class FHIRPathEngine {
okToNotResolve = true; okToNotResolve = true;
if ((atn.contains(stn))) { if ((atn.contains(stn))) {
if (element.getTypes().size() > 1) { if (element.getTypes().size() > 1) {
focus = new TypedElementDefinition(element.getElement(), stn); focus = new TypedElementDefinition( element.getSrc(), element.getElement(), stn);
} else { } else {
focus = element; focus = element;
} }
@ -5909,9 +5914,9 @@ public class FHIRPathEngine {
throw makeExceptionPlural(ed.getTypes().get(0).getProfile().size(), expr, I18nConstants.FHIRPATH_DISCRIMINATOR_MULTIPLE_PROFILES, ed.getElement().getId()); throw makeExceptionPlural(ed.getTypes().get(0).getProfile().size(), expr, I18nConstants.FHIRPATH_DISCRIMINATOR_MULTIPLE_PROFILES, ed.getElement().getId());
} }
if (ed.getTypes().get(0).hasProfile()) { if (ed.getTypes().get(0).hasProfile()) {
return worker.fetchResource(StructureDefinition.class, ed.getTypes().get(0).getProfile().get(0).getValue()); return worker.fetchResource(StructureDefinition.class, ed.getTypes().get(0).getProfile().get(0).getValue(), ed.getSrc());
} else { } else {
return worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(ed.getTypes().get(0).getCode(), null)); return worker.fetchResource(StructureDefinition.class, ProfileUtilities.sdNs(ed.getTypes().get(0).getCode(), null), ed.getSrc());
} }
} }

View File

@ -697,7 +697,7 @@ public class GraphQLEngine implements IGraphQLEngine {
Argument arg = new Argument(); Argument arg = new Argument();
params.add(arg); params.add(arg);
arg.setName(getSingleValue(parg)); arg.setName(getSingleValue(parg));
arg.addValue(new StringValue(source.fhirType()+"/"+source.getId())); arg.addValue(new StringValue(source.fhirType()+"/"+source.getIdPart()));
Bundle bnd = (Bundle) services.search(appInfo, field.getName().substring(0, field.getName().length()-10), params); Bundle bnd = (Bundle) services.search(appInfo, field.getName().substring(0, field.getName().length()-10), params);
Base bndWrapper = new SearchWrapper(field.getName(), bnd); Base bndWrapper = new SearchWrapper(field.getName(), bnd);
arg = target.addField(field.getAlias()+suffix, listStatus(field, false)); arg = target.addField(field.getAlias()+suffix, listStatus(field, false));

View File

@ -1,13 +1,13 @@
package org.hl7.fhir.r5.utils; package org.hl7.fhir.r5.utils;
import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalResourceProxy; import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalResourceProxy;
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
import org.hl7.fhir.r5.model.ElementDefinition; import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.PackageInformation;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
public class PackageHackerR5 { public class PackageHackerR5 {
public static void fixLoadedResource(CanonicalResourceProxy r, PackageVersion packageInfo) { public static void fixLoadedResource(CanonicalResourceProxy r, PackageInformation packageInfo) {
if ("http://terminology.hl7.org/CodeSystem/v2-0391|2.6".equals(r.getUrl())) { if ("http://terminology.hl7.org/CodeSystem/v2-0391|2.6".equals(r.getUrl())) {
r.hack("http://terminology.hl7.org/CodeSystem/v2-0391-2.6", "2.6"); r.hack("http://terminology.hl7.org/CodeSystem/v2-0391-2.6", "2.6");
} }

View File

@ -37,6 +37,7 @@ import java.util.Locale;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.Bundle; import org.hl7.fhir.r5.model.Bundle;
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent; import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
import org.hl7.fhir.r5.model.Bundle.BundleLinkComponent; import org.hl7.fhir.r5.model.Bundle.BundleLinkComponent;
@ -52,6 +53,7 @@ import org.hl7.fhir.r5.model.Meta;
import org.hl7.fhir.r5.model.OperationOutcome; import org.hl7.fhir.r5.model.OperationOutcome;
import org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity; import org.hl7.fhir.r5.model.OperationOutcome.IssueSeverity;
import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent; import org.hl7.fhir.r5.model.OperationOutcome.OperationOutcomeIssueComponent;
import org.hl7.fhir.r5.model.Property;
import org.hl7.fhir.r5.model.Reference; import org.hl7.fhir.r5.model.Reference;
import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.ResourceType; import org.hl7.fhir.r5.model.ResourceType;
@ -180,4 +182,28 @@ public class ResourceUtilities {
} }
return b.toString(); return b.toString();
} }
public static boolean hasURL(String uri, Resource src) {
for (Property p : src.children()) {
if (hasURL(uri, p)) {
return true;
}
}
return false;
}
private static boolean hasURL(String uri, Property p) {
for (Base b : p.getValues()) {
if (b.isPrimitive()) {
return uri.equals(b.primitiveValue());
} else {
for (Property c : b.children()) {
if (hasURL(uri, c)) {
return true;
}
}
}
}
return false;
}
} }

View File

@ -1,11 +1,13 @@
package org.hl7.fhir.r5.test; package org.hl7.fhir.r5.test;
import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List;
import org.hl7.fhir.r5.context.CanonicalResourceManager; import org.hl7.fhir.r5.context.CanonicalResourceManager;
import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalResourceProxy; import org.hl7.fhir.r5.context.CanonicalResourceManager.CanonicalResourceProxy;
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
import org.hl7.fhir.r5.model.CanonicalResource; import org.hl7.fhir.r5.model.CanonicalResource;
import org.hl7.fhir.r5.model.PackageInformation;
import org.hl7.fhir.r5.model.ValueSet; import org.hl7.fhir.r5.model.ValueSet;
import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test; import org.junit.jupiter.api.Test;
@ -428,12 +430,12 @@ public class CanonicalResourceManagerTests {
vs2.setVersion("2000.0.0"); vs2.setVersion("2000.0.0");
vs2.setName("2"); vs2.setName("2");
mrm.see(vs1, new PackageVersion("hl7.fhir.r4.core", "4.0.1", new Date())); mrm.see(vs1, new PackageInformation("hl7.fhir.r4.core", "4.0.1", new Date()));
Assertions.assertNotNull(mrm.get("http://terminology.hl7.org/ValueSet/234")); Assertions.assertNotNull(mrm.get("http://terminology.hl7.org/ValueSet/234"));
Assertions.assertNotNull(mrm.get("http://terminology.hl7.org/ValueSet/234", "2.0.0")); Assertions.assertNotNull(mrm.get("http://terminology.hl7.org/ValueSet/234", "2.0.0"));
Assertions.assertTrue(mrm.get("http://terminology.hl7.org/ValueSet/234").getName().equals("1")); Assertions.assertTrue(mrm.get("http://terminology.hl7.org/ValueSet/234").getName().equals("1"));
mrm.see(vs2, new PackageVersion("hl7.terminology.r4", "4.0.1", new Date())); mrm.see(vs2, new PackageInformation("hl7.terminology.r4", "4.0.1", new Date()));
Assertions.assertNotNull(mrm.get("http://terminology.hl7.org/ValueSet/234")); Assertions.assertNotNull(mrm.get("http://terminology.hl7.org/ValueSet/234"));
Assertions.assertTrue(mrm.get("http://terminology.hl7.org/ValueSet/234").getName().equals("2")); Assertions.assertTrue(mrm.get("http://terminology.hl7.org/ValueSet/234").getName().equals("2"));
Assertions.assertNull(mrm.get("http://terminology.hl7.org/ValueSet/234", "2.0.0")); // this will get dropped completely because of UTG rules Assertions.assertNull(mrm.get("http://terminology.hl7.org/ValueSet/234", "2.0.0")); // this will get dropped completely because of UTG rules
@ -809,5 +811,46 @@ public class CanonicalResourceManagerTests {
Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.1")); Assertions.assertNull(mrm.get("http://url/ValueSet/234", "4.1"));
} }
@Test
public void testPackageSpecificResolution1() {
// we add 2 canonicals to the cache with the same identification, but different package information
CanonicalResourceManager<ValueSet> mrm = new CanonicalResourceManager<>(false);
ValueSet vs1 = new ValueSet();
vs1.setId("2345");
vs1.setUrl("http://url/ValueSet/234");
vs1.setVersion("4.0.1");
vs1.setName("1");
DeferredLoadTestResource vs1d = new DeferredLoadTestResource(vs1);
mrm.see(vs1, new PackageInformation("pid.one", "1.0.0", new Date()));
ValueSet vs2 = new ValueSet();
vs2.setId("2346");
vs2.setUrl("http://url/ValueSet/234");
vs2.setVersion("4.0.1");
vs2.setName("2");
mrm.see(vs2, new PackageInformation("pid.two", "1.0.0", new Date()));
List<String> pvl1 = new ArrayList<>();
pvl1.add("pid.one#1.0.0");
List<String> pvl2 = new ArrayList<>();
pvl1.add("pid.two#1.0.0");
Assertions.assertEquals("2", mrm.get("http://url/ValueSet/234").getName());
Assertions.assertEquals("1", mrm.get("http://url/ValueSet/234", pvl1).getName());
Assertions.assertEquals("2", mrm.get("http://url/ValueSet/234", pvl2).getName());
Assertions.assertEquals("2", mrm.get("http://url/ValueSet/234", "4.0.1").getName());
Assertions.assertEquals("1", mrm.get("http://url/ValueSet/234", "4.0.1", pvl1).getName());
Assertions.assertEquals("2", mrm.get("http://url/ValueSet/234", "4.0.1", pvl2).getName());
Assertions.assertEquals("2", mrm.get("http://url/ValueSet/234", "4.0").getName());
Assertions.assertEquals("1", mrm.get("http://url/ValueSet/234", "4.0", pvl1).getName());
Assertions.assertEquals("2", mrm.get("http://url/ValueSet/234", "4.0", pvl2).getName());
Assertions.assertEquals("2", mrm.get("http://url/ValueSet/234", "4.0.2").getName());
Assertions.assertEquals("1", mrm.get("http://url/ValueSet/234", "4.0.2", pvl1).getName());
Assertions.assertEquals("2", mrm.get("http://url/ValueSet/234", "4.0.2", pvl2).getName());
}
} }

View File

@ -817,12 +817,13 @@ public class ValidationMessage implements Comparator<ValidationMessage>, Compara
return ruleDate; return ruleDate;
} }
public void setRuleDate(Date ruleDate) { public ValidationMessage setRuleDate(Date ruleDate) {
this.ruleDate = ruleDate; this.ruleDate = ruleDate;
return this;
} }
public void setRuleDate(String value) { public ValidationMessage setRuleDate(String value) {
if (value == null) { if (value == null) {
ruleDate = null; ruleDate = null;
} else { } else {
@ -834,5 +835,6 @@ public class ValidationMessage implements Comparator<ValidationMessage>, Compara
} }
ruleDate = d; ruleDate = d;
} }
return this;
} }
} }

View File

@ -2,6 +2,7 @@ package org.hl7.fhir.utilities;
import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertEquals;
import java.time.ZonedDateTime;
import java.util.Date; import java.util.Date;
import java.util.Locale; import java.util.Locale;
import java.util.TimeZone; import java.util.TimeZone;
@ -10,6 +11,7 @@ import java.util.stream.Stream;
import org.junit.jupiter.api.AfterAll; import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll; import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource; import org.junit.jupiter.params.provider.MethodSource;

View File

@ -801,7 +801,7 @@ public class BaseValidator implements IValidationContextResourceLoader {
} }
protected ValueSet resolveBindingReference(DomainResource ctxt, String reference, String uri) { protected ValueSet resolveBindingReference(DomainResource ctxt, String reference, String uri, Resource src) {
if (reference != null) { if (reference != null) {
if (reference.equals("http://www.rfc-editor.org/bcp/bcp13.txt")) { if (reference.equals("http://www.rfc-editor.org/bcp/bcp13.txt")) {
reference = "http://hl7.org/fhir/ValueSet/mimetypes"; reference = "http://hl7.org/fhir/ValueSet/mimetypes";
@ -814,11 +814,11 @@ public class BaseValidator implements IValidationContextResourceLoader {
return null; return null;
} else { } else {
long t = System.nanoTime(); long t = System.nanoTime();
ValueSet fr = context.fetchResource(ValueSet.class, reference); ValueSet fr = context.fetchResource(ValueSet.class, reference, src);
if (fr == null) { if (fr == null) {
if (!Utilities.isAbsoluteUrl(reference)) { if (!Utilities.isAbsoluteUrl(reference)) {
reference = resolve(uri, reference); reference = resolve(uri, reference);
fr = context.fetchResource(ValueSet.class, reference); fr = context.fetchResource(ValueSet.class, reference, src);
} }
} }
if (fr == null) { if (fr == null) {

View File

@ -29,7 +29,6 @@ import org.hl7.fhir.exceptions.FHIRException;
import org.hl7.fhir.r5.conformance.ProfileUtilities; import org.hl7.fhir.r5.conformance.ProfileUtilities;
import org.hl7.fhir.r5.context.ContextUtilities; import org.hl7.fhir.r5.context.ContextUtilities;
import org.hl7.fhir.r5.context.IWorkerContext; import org.hl7.fhir.r5.context.IWorkerContext;
import org.hl7.fhir.r5.context.IWorkerContext.PackageVersion;
import org.hl7.fhir.r5.context.IWorkerContextManager; import org.hl7.fhir.r5.context.IWorkerContextManager;
import org.hl7.fhir.r5.context.SimpleWorkerContext; import org.hl7.fhir.r5.context.SimpleWorkerContext;
import org.hl7.fhir.r5.context.SystemOutLoggingService; import org.hl7.fhir.r5.context.SystemOutLoggingService;
@ -52,6 +51,7 @@ import org.hl7.fhir.r5.model.ElementDefinition;
import org.hl7.fhir.r5.model.ExpressionNode; import org.hl7.fhir.r5.model.ExpressionNode;
import org.hl7.fhir.r5.model.ImplementationGuide; import org.hl7.fhir.r5.model.ImplementationGuide;
import org.hl7.fhir.r5.model.OperationOutcome; import org.hl7.fhir.r5.model.OperationOutcome;
import org.hl7.fhir.r5.model.PackageInformation;
import org.hl7.fhir.r5.model.Parameters; import org.hl7.fhir.r5.model.Parameters;
import org.hl7.fhir.r5.model.Resource; import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StructureDefinition; import org.hl7.fhir.r5.model.StructureDefinition;
@ -429,7 +429,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
if (userAgent != null) { if (userAgent != null) {
contextBuilder.withUserAgent(userAgent); contextBuilder.withUserAgent(userAgent);
} }
context = contextBuilder.fromDefinitions(source, ValidatorUtils.loaderForVersion(version), new PackageVersion(src, new Date())); context = contextBuilder.fromDefinitions(source, ValidatorUtils.loaderForVersion(version), new PackageInformation(src, new Date()));
ValidatorUtils.grabNatives(getBinaries(), source, "http://hl7.org/fhir"); ValidatorUtils.grabNatives(getBinaries(), source, "http://hl7.org/fhir");
} }
// ucum-essence.xml should be in the class path. if it's not, ask about how to sort this out // ucum-essence.xml should be in the class path. if it's not, ask about how to sort this out

View File

@ -864,7 +864,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
StructureDefinition sd = profiles.get(i); StructureDefinition sd = profiles.get(i);
if (sd.hasExtension(ToolingExtensions.EXT_SD_DEPENDENCY)) { if (sd.hasExtension(ToolingExtensions.EXT_SD_DEPENDENCY)) {
for (Extension ext : sd.getExtensionsByUrl(ToolingExtensions.EXT_SD_DEPENDENCY)) { for (Extension ext : sd.getExtensionsByUrl(ToolingExtensions.EXT_SD_DEPENDENCY)) {
StructureDefinition dep = context.fetchResource( StructureDefinition.class, ext.getValue().primitiveValue()); StructureDefinition dep = context.fetchResource( StructureDefinition.class, ext.getValue().primitiveValue(), sd);
if (dep == null) { if (dep == null) {
warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.VALIDATION_VAL_PROFILE_DEPENDS_NOT_RESOLVED, ext.getValue().primitiveValue(), sd.getVersionedUrl()); warning(errors, NO_RULE_DATE, IssueType.BUSINESSRULE, element.line(), element.col(), stack.getLiteralPath(), false, I18nConstants.VALIDATION_VAL_PROFILE_DEPENDS_NOT_RESOLVED, ext.getValue().primitiveValue(), sd.getVersionedUrl());
} else if (!profiles.contains(dep)) { } else if (!profiles.contains(dep)) {
@ -1025,7 +1025,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return false; return false;
} else { } else {
try { try {
if (context.fetchResourceWithException(ValueSet.class, system) != null) { if (context.fetchResourceWithException(ValueSet.class, system, element.getProperty().getStructure()) != null) {
rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_SYSTEM_VALUESET, system); rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, false, I18nConstants.TERMINOLOGY_TX_SYSTEM_VALUESET, system);
// Lloyd: This error used to prohibit checking for downstream issues, but there are some cases where that checking needs to occur. Please talk to me before changing the code back. // Lloyd: This error used to prohibit checking for downstream issues, but there are some cases where that checking needs to occur. Please talk to me before changing the code back.
} }
@ -1192,7 +1192,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
ElementDefinitionBindingComponent binding = theElementCntext.getBinding(); ElementDefinitionBindingComponent binding = theElementCntext.getBinding();
if (warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, binding != null, I18nConstants.TERMINOLOGY_TX_BINDING_MISSING, path)) { if (warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, binding != null, I18nConstants.TERMINOLOGY_TX_BINDING_MISSING, path)) {
if (binding.hasValueSet()) { if (binding.hasValueSet()) {
ValueSet valueset = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl()); ValueSet valueset = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl(), profile);
if (valueset == null) { if (valueset == null) {
CodeSystem cs = context.fetchCodeSystem(binding.getValueSet()); CodeSystem cs = context.fetchCodeSystem(binding.getValueSet());
if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(binding.getValueSet()))) { if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(binding.getValueSet()))) {
@ -1324,7 +1324,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
ElementDefinitionBindingComponent binding = theElementCntext.getBinding(); ElementDefinitionBindingComponent binding = theElementCntext.getBinding();
if (warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, binding != null, I18nConstants.TERMINOLOGY_TX_BINDING_MISSING, path)) { if (warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, binding != null, I18nConstants.TERMINOLOGY_TX_BINDING_MISSING, path)) {
if (binding.hasValueSet()) { if (binding.hasValueSet()) {
ValueSet valueset = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl()); ValueSet valueset = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl(), profile);
if (valueset == null) { if (valueset == null) {
CodeSystem cs = context.fetchCodeSystem(binding.getValueSet()); CodeSystem cs = context.fetchCodeSystem(binding.getValueSet());
if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(binding.getValueSet()))) { if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(binding.getValueSet()))) {
@ -1455,7 +1455,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
ElementDefinitionBindingComponent binding = theElementCntext.getBinding(); ElementDefinitionBindingComponent binding = theElementCntext.getBinding();
if (warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, binding != null, I18nConstants.TERMINOLOGY_TX_BINDING_MISSING2, path)) { if (warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, binding != null, I18nConstants.TERMINOLOGY_TX_BINDING_MISSING2, path)) {
if (binding.hasValueSet()) { if (binding.hasValueSet()) {
ValueSet valueset = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl()); ValueSet valueset = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl(), profile);
if (valueset == null) { if (valueset == null) {
CodeSystem cs = context.fetchCodeSystem(binding.getValueSet()); CodeSystem cs = context.fetchCodeSystem(binding.getValueSet());
if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(binding.getValueSet()))) { if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(binding.getValueSet()))) {
@ -1600,7 +1600,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} }
private void checkMaxValueSet(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, String maxVSUrl, CodeableConcept cc, NodeStack stack) { private void checkMaxValueSet(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, String maxVSUrl, CodeableConcept cc, NodeStack stack) {
ValueSet valueset = resolveBindingReference(profile, maxVSUrl, profile.getUrl()); ValueSet valueset = resolveBindingReference(profile, maxVSUrl, profile.getUrl(), profile);
if (valueset == null) { if (valueset == null) {
CodeSystem cs = context.fetchCodeSystem(maxVSUrl); CodeSystem cs = context.fetchCodeSystem(maxVSUrl);
if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(maxVSUrl))) { if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(maxVSUrl))) {
@ -1635,7 +1635,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
private boolean checkMaxValueSet(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, String maxVSUrl, Coding c, NodeStack stack) { private boolean checkMaxValueSet(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, String maxVSUrl, Coding c, NodeStack stack) {
boolean ok = true; boolean ok = true;
ValueSet valueset = resolveBindingReference(profile, maxVSUrl, profile.getUrl()); ValueSet valueset = resolveBindingReference(profile, maxVSUrl, profile.getUrl(), profile);
if (valueset == null) { if (valueset == null) {
CodeSystem cs = context.fetchCodeSystem(maxVSUrl); CodeSystem cs = context.fetchCodeSystem(maxVSUrl);
if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(maxVSUrl))) { if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(maxVSUrl))) {
@ -1664,7 +1664,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
private boolean checkMaxValueSet(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, String maxVSUrl, String value, NodeStack stack) { private boolean checkMaxValueSet(List<ValidationMessage> errors, String path, Element element, StructureDefinition profile, String maxVSUrl, String value, NodeStack stack) {
boolean ok = true; boolean ok = true;
ValueSet valueset = resolveBindingReference(profile, maxVSUrl, profile.getUrl()); ValueSet valueset = resolveBindingReference(profile, maxVSUrl, profile.getUrl(), profile);
if (valueset == null) { if (valueset == null) {
CodeSystem cs = context.fetchCodeSystem(maxVSUrl); CodeSystem cs = context.fetchCodeSystem(maxVSUrl);
if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(maxVSUrl))) { if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(maxVSUrl))) {
@ -1732,7 +1732,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
ElementDefinitionBindingComponent binding = theElementCntext.getBinding(); ElementDefinitionBindingComponent binding = theElementCntext.getBinding();
if (warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, binding != null, I18nConstants.TERMINOLOGY_TX_BINDING_MISSING2, path)) { if (warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, binding != null, I18nConstants.TERMINOLOGY_TX_BINDING_MISSING2, path)) {
if (binding.hasValueSet()) { if (binding.hasValueSet()) {
ValueSet valueset = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl()); ValueSet valueset = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl(), profile);
if (valueset == null) { if (valueset == null) {
CodeSystem cs = context.fetchCodeSystem(binding.getValueSet()); CodeSystem cs = context.fetchCodeSystem(binding.getValueSet());
if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(binding.getValueSet()))) { if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(binding.getValueSet()))) {
@ -1977,7 +1977,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
break; break;
} }
if (sd.getBaseDefinition() != null) { if (sd.getBaseDefinition() != null) {
sd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition()); sd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
} else { } else {
sd = null; sd = null;
} }
@ -2533,7 +2533,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} else { } else {
boolean tok = false; boolean tok = false;
for (StructureDefinition t : context.fetchResourcesByType(StructureDefinition.class)) { for (StructureDefinition t : context.fetchResourcesByType(StructureDefinition.class)) {
if (t.hasUserData("package") && t.getUserString("package").startsWith("hl7.fhir.r") && v.equals(t.getType())) { if (t.hasSourcePackage() && t.getSourcePackage().getId().startsWith("hl7.fhir.r") && v.equals(t.getType())) {
tok = true; tok = true;
} }
} }
@ -2921,7 +2921,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
// firstly, resolve the value set // firstly, resolve the value set
ElementDefinitionBindingComponent binding = elementContext.getBinding(); ElementDefinitionBindingComponent binding = elementContext.getBinding();
if (binding.hasValueSet()) { if (binding.hasValueSet()) {
ValueSet vs = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl()); ValueSet vs = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl(), profile);
if (vs == null) { if (vs == null) {
CodeSystem cs = context.fetchCodeSystem(binding.getValueSet()); CodeSystem cs = context.fetchCodeSystem(binding.getValueSet());
if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(binding.getValueSet()))) { if (rule(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, cs == null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND_CS, describeReference(binding.getValueSet()))) {
@ -3442,7 +3442,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
StructureDefinition sdFT = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/"+ft); StructureDefinition sdFT = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/"+ft);
boolean rok = false; boolean rok = false;
for (CanonicalType tp : type.getTargetProfile()) { for (CanonicalType tp : type.getTargetProfile()) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, tp.getValue()); StructureDefinition sd = context.fetchResource(StructureDefinition.class, tp.getValue(), profile);
if (sd != null) { if (sd != null) {
types.add(sd.getType()); types.add(sd.getType());
} }
@ -3452,7 +3452,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
rok = true; rok = true;
break; break;
} }
sdF = sdF.hasBaseDefinition() ? context.fetchResource(StructureDefinition.class, sdF.getBaseDefinition()) : null; sdF = sdF.hasBaseDefinition() ? context.fetchResource(StructureDefinition.class, sdF.getBaseDefinition(), sdF) : null;
} }
} }
ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, element.line(), element.col(), path, types.isEmpty() || rok, ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, element.line(), element.col(), path, types.isEmpty() || rok,
@ -3758,7 +3758,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
for (TypeRefComponent type : element.getType()) { for (TypeRefComponent type : element.getType()) {
for (CanonicalType p : type.getProfile()) { for (CanonicalType p : type.getProfile()) {
String id = p.hasExtension(ToolingExtensions.EXT_PROFILE_ELEMENT) ? p.getExtensionString(ToolingExtensions.EXT_PROFILE_ELEMENT) : null; String id = p.hasExtension(ToolingExtensions.EXT_PROFILE_ELEMENT) ? p.getExtensionString(ToolingExtensions.EXT_PROFILE_ELEMENT) : null;
StructureDefinition sd = context.fetchResource(StructureDefinition.class, p.getValue()); StructureDefinition sd = context.fetchResource(StructureDefinition.class, p.getValue(), profile);
if (sd == null) if (sd == null)
throw new DefinitionException(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_PROFILE_, p)); throw new DefinitionException(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_PROFILE_, p));
profile = sd; profile = sd;
@ -3801,13 +3801,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return igs; return igs;
} }
private StructureDefinition getProfileForType(String type, List<TypeRefComponent> list) { private StructureDefinition getProfileForType(String type, List<TypeRefComponent> list, Resource src) {
for (TypeRefComponent tr : list) { for (TypeRefComponent tr : list) {
String url = tr.getWorkingCode(); String url = tr.getWorkingCode();
if (!Utilities.isAbsoluteUrl(url)) if (!Utilities.isAbsoluteUrl(url))
url = "http://hl7.org/fhir/StructureDefinition/" + url; url = "http://hl7.org/fhir/StructureDefinition/" + url;
long t = System.nanoTime(); long t = System.nanoTime();
StructureDefinition sd = context.fetchResource(StructureDefinition.class, url); StructureDefinition sd = context.fetchResource(StructureDefinition.class, url, src);
timeTracker.sd(t); timeTracker.sd(t);
if (sd != null && (sd.getType().equals(type) || sd.getUrl().equals(type)) && sd.hasSnapshot()) { if (sd != null && (sd.getType().equals(type) || sd.getUrl().equals(type)) && sd.hasSnapshot()) {
return sd; return sd;
@ -4196,7 +4196,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return null; return null;
} else { } else {
long t = System.nanoTime(); long t = System.nanoTime();
StructureDefinition fr = context.fetchResource(StructureDefinition.class, pr); StructureDefinition fr = context.fetchResource(StructureDefinition.class, pr, profile);
timeTracker.sd(t); timeTracker.sd(t);
return fr; return fr;
} }
@ -4800,7 +4800,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
for (ImplementationGuide ig : igs) { for (ImplementationGuide ig : igs) {
for (ImplementationGuideGlobalComponent gl : ig.getGlobal()) { for (ImplementationGuideGlobalComponent gl : ig.getGlobal()) {
if (rt.equals(gl.getType())) { if (rt.equals(gl.getType())) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, gl.getProfile()); StructureDefinition sd = context.fetchResource(StructureDefinition.class, gl.getProfile(), ig);
if (warning(errors, NO_RULE_DATE, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), sd != null, I18nConstants.VALIDATION_VAL_GLOBAL_PROFILE_UNKNOWN, gl.getProfile())) { if (warning(errors, NO_RULE_DATE, IssueType.STRUCTURE, element.line(), element.col(), stack.getLiteralPath(), sd != null, I18nConstants.VALIDATION_VAL_GLOBAL_PROFILE_UNKNOWN, gl.getProfile())) {
if (crumbTrails) { if (crumbTrails) {
element.addMessage(signpost(errors, NO_RULE_DATE, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST_GLOBAL, sd.getVersionedUrl(), ig.getVersionedUrl())); element.addMessage(signpost(errors, NO_RULE_DATE, IssueType.INFORMATIONAL, element.line(), element.col(), stack.getLiteralPath(), I18nConstants.VALIDATION_VAL_PROFILE_SIGNPOST_GLOBAL, sd.getVersionedUrl(), ig.getVersionedUrl()));
@ -5132,7 +5132,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (typeForResource.getProfile().size() == 1) { if (typeForResource.getProfile().size() == 1) {
long t = System.nanoTime(); long t = System.nanoTime();
StructureDefinition profile = this.context.fetchResource(StructureDefinition.class, typeForResource.getProfile().get(0).asStringValue()); StructureDefinition profile = this.context.fetchResource(StructureDefinition.class, typeForResource.getProfile().get(0).asStringValue(), parentProfile);
timeTracker.sd(t); timeTracker.sd(t);
trackUsage(profile, hostContext, element); trackUsage(profile, hostContext, element);
if (rule(errors, NO_RULE_DATE, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(), if (rule(errors, NO_RULE_DATE, IssueType.INVALID, element.line(), element.col(), stack.getLiteralPath(),
@ -5165,7 +5165,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} else { } else {
List<String> types = new ArrayList<>(); List<String> types = new ArrayList<>();
for (UriType u : typeForResource.getProfile()) { for (UriType u : typeForResource.getProfile()) {
StructureDefinition sd = this.context.fetchResource(StructureDefinition.class, u.getValue()); StructureDefinition sd = this.context.fetchResource(StructureDefinition.class, u.getValue(), parentProfile);
if (sd != null && !types.contains(sd.getType())) { if (sd != null && !types.contains(sd.getType())) {
types.add(sd.getType()); types.add(sd.getType());
} }
@ -5210,7 +5210,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} }
} }
} }
sdt = context.fetchResource(StructureDefinition.class, sdt.getBaseDefinition()); sdt = context.fetchResource(StructureDefinition.class, sdt.getBaseDefinition(), sdt);
} }
return false; return false;
} }
@ -5533,7 +5533,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
String tail = null; String tail = null;
if (profiles.isEmpty()) { if (profiles.isEmpty()) {
if (type != null) { if (type != null) {
p = getProfileForType(type, checkDefn.getType()); p = getProfileForType(type, checkDefn.getType(), profile);
// If dealing with a primitive type, then we need to check the current child against // If dealing with a primitive type, then we need to check the current child against
// the invariants (constraints) on the current element, because otherwise it only gets // the invariants (constraints) on the current element, because otherwise it only gets
@ -5550,7 +5550,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
tail = url.substring(url.indexOf("#") + 1); tail = url.substring(url.indexOf("#") + 1);
url = url.substring(0, url.indexOf("#")); url = url.substring(0, url.indexOf("#"));
} }
p = this.context.fetchResource(StructureDefinition.class, url); p = this.context.fetchResource(StructureDefinition.class, url, profile);
ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, ei.line(), ei.col(), ei.getPath(), p != null, I18nConstants.VALIDATION_VAL_UNKNOWN_PROFILE, profiles.get(0)) && ok; ok = rule(errors, NO_RULE_DATE, IssueType.STRUCTURE, ei.line(), ei.col(), ei.getPath(), p != null, I18nConstants.VALIDATION_VAL_UNKNOWN_PROFILE, profiles.get(0)) && ok;
} else { } else {
elementValidated = true; elementValidated = true;
@ -6020,7 +6020,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return false; return false;
} }
while (profile != null) { while (profile != null) {
profile = context.fetchResource(StructureDefinition.class, profile.getBaseDefinition()); profile = context.fetchResource(StructureDefinition.class, profile.getBaseDefinition(), profile);
if (profile != null) { if (profile != null) {
if (source.equals(profile.getUrl())) { if (source.equals(profile.getUrl())) {
return true; return true;

View File

@ -546,7 +546,7 @@ public class QuestionnaireValidator extends BaseValidator {
if (ref.startsWith("#") && qSrc.container != null) { if (ref.startsWith("#") && qSrc.container != null) {
vs = (ValueSet) loadContainedResource(errors, qSrc.containerPath, qSrc.container, ref.substring(1), ValueSet.class); vs = (ValueSet) loadContainedResource(errors, qSrc.containerPath, qSrc.container, ref.substring(1), ValueSet.class);
} else { } else {
vs = resolveBindingReference(qSrc.q(), ref, qSrc.q().getUrl()); vs = resolveBindingReference(qSrc.q(), ref, qSrc.q().getUrl(), qSrc.q());
} }
if (warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), vs != null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND, describeReference(ref))) { if (warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, value.line(), value.col(), stack.getLiteralPath(), vs != null, I18nConstants.TERMINOLOGY_TX_VALUESET_NOTFOUND, describeReference(ref))) {
try { try {