refactor resource reference resolution to use package dependencies whereever possible

This commit is contained in:
Grahame Grieve 2022-12-01 08:16:00 +11:00
parent d79ac9ba66
commit fedfa88ffb
44 changed files with 849 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())) {
return true;
}
sdFocus = ctxt.fetchResource(StructureDefinition.class, sdFocus.getBaseDefinition());
sdFocus = ctxt.fetchResource(StructureDefinition.class, sdFocus.getBaseDefinition(), sdFocus);
}
return false;
}

View File

@ -60,12 +60,12 @@ public class ComparisonSession {
return title;
}
public ResourceComparison compare(String left, String right) throws DefinitionException, FHIRFormatError, IOException {
CanonicalResource l = (CanonicalResource) contextLeft.fetchResource(Resource.class, left);
public ResourceComparison compare(String left, Resource leftSource, String right, Resource rightSource) throws DefinitionException, FHIRFormatError, IOException {
CanonicalResource l = (CanonicalResource) contextLeft.fetchResource(Resource.class, left, leftSource);
if (l == null) {
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) {
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.IntegerType;
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.StructureDefinition;
import org.hl7.fhir.r5.model.StructureDefinition.TypeDerivationRule;
@ -226,7 +227,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
subset.setMin(intersectMin(leftMin, rightMin));
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()));
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]>
@ -234,7 +235,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
superset.setMaxLengthElement(unionMaxLength(left.current().getMaxLength(), right.current().getMaxLength()));
subset.setMaxLengthElement(intersectMaxLength(left.current().getMaxLength(), right.current().getMaxLength()));
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
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
// if it does, we have to load the children for that data into the profile that doesn't
// walk into it
if (lc.isEmpty() && !rc.isEmpty() && right.current().getType().size() == 1 && left.hasTypeChildren(right.current().getType().get(0)))
lc = left.childrenFromType(right.current().getType().get(0));
if (rc.isEmpty() && !lc.isEmpty() && left.current().getType().size() == 1 && right.hasTypeChildren(left.current().getType().get(0)))
rc = right.childrenFromType(left.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), right.getStructure());
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), left.getStructure());
List<DefinitionNavigator> matchR = new ArrayList<>();
for (DefinitionNavigator l : lc) {
@ -529,16 +530,16 @@ public class ProfileComparer extends CanonicalResourceComparer {
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>();
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)
checkAddTypeUnion(comp, res, path, result, r, session.getContextRight());
checkAddTypeUnion(comp, res, path, result, r, session.getContextRight(), rightSrc);
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 tfound = false;
nw = nw.copy();
@ -558,8 +559,8 @@ public class ProfileComparer extends CanonicalResourceComparer {
ex.setProfile(null);
} else {
// both have profiles. Is one derived from the other?
StructureDefinition sdex = ((IWorkerContext) ex.getUserData("ctxt")).fetchResource(StructureDefinition.class, ex.getProfile().get(0).getValue());
StructureDefinition sdnw = ctxt.fetchResource(StructureDefinition.class, nw.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(), nwSource);
if (sdex != null && sdnw != null) {
if (sdex.getUrl().equals(sdnw.getUrl())) {
pfound = true;
@ -586,8 +587,8 @@ public class ProfileComparer extends CanonicalResourceComparer {
ex.setTargetProfile(null);
} else {
// both have profiles. Is one derived from the other?
StructureDefinition sdex = ((IWorkerContext) ex.getUserData("ctxt")).fetchResource(StructureDefinition.class, ex.getTargetProfile().get(0).getValue());
StructureDefinition sdnw = ctxt.fetchResource(StructureDefinition.class, nw.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(), nwSource);
if (sdex != null && sdnw != null) {
if (matches(sdex, sdnw)) {
tfound = true;
@ -633,7 +634,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
if (right.getUrl().equals(sd.getBaseDefinition())) {
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;
}
@ -653,8 +654,8 @@ public class ProfileComparer extends CanonicalResourceComparer {
pfound = true;
c.setProfile(r.getProfile());
} else {
StructureDefinition sdl = resolveProfile(comp, res, path, l.getProfile().get(0).getValue(), comp.getLeft().getName(), session.getContextLeft());
StructureDefinition sdr = resolveProfile(comp, res, path, r.getProfile().get(0).getValue(), comp.getRight().getName(), session.getContextRight());
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(), comp.getRight());
if (sdl != null && sdr != null) {
if (sdl == sdr) {
pfound = true;
@ -680,8 +681,8 @@ public class ProfileComparer extends CanonicalResourceComparer {
tfound = true;
c.setTargetProfile(r.getTargetProfile());
} else {
StructureDefinition sdl = resolveProfile(comp, res, path, l.getTargetProfile().get(0).getValue(), comp.getLeft().getName(), session.getContextLeft());
StructureDefinition sdr = resolveProfile(comp, res, path, r.getTargetProfile().get(0).getValue(), comp.getRight().getName(), session.getContextRight());
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(), comp.getRight());
if (sdl != null && sdr != null) {
if (matches(sdl, sdr)) {
tfound = true;
@ -721,7 +722,7 @@ public class ProfileComparer extends CanonicalResourceComparer {
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());
if (!lDef.hasBinding()) {
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)) {
vm(IssueSeverity.INFORMATION, "Example/preferred bindings differ at "+path+" using binding from "+comp.getRight().getName(), path, comp.getMessages(), res.getMessages());
subset.setBinding(right);
superset.setBinding(unionBindings(comp, res, path, left, right));
superset.setBinding(unionBindings(comp, res, path, left, right, leftSrc, rightSrc));
} else {
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());
}
subset.setBinding(left);
superset.setBinding(unionBindings(comp, res, path, left, right));
superset.setBinding(unionBindings(comp, res, path, left, right, leftSrc, rightSrc));
}
return true;
}
// if either of them are extensible/required, then it wins
if (isPreferredOrExample(left)) {
subset.setBinding(right);
superset.setBinding(unionBindings(comp, res, path, left, right));
superset.setBinding(unionBindings(comp, res, path, left, right, leftSrc, rightSrc));
return true;
}
if (isPreferredOrExample(right)) {
subset.setBinding(left);
superset.setBinding(unionBindings(comp, res, path, left, right));
superset.setBinding(unionBindings(comp, res, path, left, right, leftSrc, rightSrc));
return true;
}
@ -800,8 +801,8 @@ public class ProfileComparer extends CanonicalResourceComparer {
return true;
} else {
// ok, now we compare the value sets. This may be unresolvable.
ValueSet lvs = resolveVS(comp.getLeft(), left.getValueSet(), session.getContextLeft());
ValueSet rvs = resolveVS(comp.getRight(), right.getValueSet(), session.getContextRight());
ValueSet lvs = resolveVS(comp.getLeft(), left.getValueSet(), leftSrc, session.getContextLeft());
ValueSet rvs = resolveVS(comp.getRight(), right.getValueSet(), rightSrc, session.getContextRight());
if (lvs == null) {
vm(IssueSeverity.ERROR, "Unable to resolve left value set "+left.getValueSet().toString()+" at "+path, path, comp.getMessages(), res.getMessages());
return true;
@ -885,8 +886,8 @@ public class ProfileComparer extends CanonicalResourceComparer {
return result;
}
private StructureDefinition resolveProfile(ProfileComparison comp, StructuralMatch<ElementDefinitionNode> res, String path, String url, String name, IWorkerContext ctxt) {
StructureDefinition sd = ctxt.fetchResource(StructureDefinition.class, url);
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, urlSource);
if (sd == null) {
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;
}
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();
if (left.getStrength().compareTo(right.getStrength()) < 0)
union.setStrength(left.getStrength());
@ -907,8 +908,8 @@ public class ProfileComparer extends CanonicalResourceComparer {
if (Base.compareDeep(left.getValueSet(), right.getValueSet(), false))
union.setValueSet(left.getValueSet());
else {
ValueSet lvs = resolveVS(comp.getLeft(), left.getValueSet(), session.getContextLeft());
ValueSet rvs = resolveVS(comp.getRight(), right.getValueSet(), session.getContextRight());
ValueSet lvs = resolveVS(comp.getLeft(), left.getValueSet(), leftSrc, session.getContextLeft());
ValueSet rvs = resolveVS(comp.getRight(), right.getValueSet(), rightSrc, session.getContextRight());
if (lvs != null && rvs != null) {
ValueSetComparison compP = (ValueSetComparison) session.compare(lvs, rvs);
if (compP != null) {
@ -923,10 +924,10 @@ public class ProfileComparer extends CanonicalResourceComparer {
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)
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 {

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.ProfileKnowledgeProvider.BindingResolution;
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.elementmodel.ObjectConverter;
import org.hl7.fhir.r5.elementmodel.Property;
@ -474,7 +473,7 @@ public class ProfileUtilities extends TranslatingUtilities {
} else if (element.getContentReference().contains("#")) {
// external reference
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) {
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);
} else if (e.getContentReference().contains("#")) {
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) {
throw new DefinitionException("Unable to find Structure "+url);
}
@ -722,7 +721,7 @@ public class ProfileUtilities extends TranslatingUtilities {
// debug = true;
// }
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);
if (derived.getDerivation() == TypeDerivationRule.SPECIALIZATION) {
for (ElementDefinition e : diff.getElement()) {
@ -824,7 +823,7 @@ public class ProfileUtilities extends TranslatingUtilities {
for (ElementDefinition ed : derived.getSnapshot().getElement()) {
for (TypeRefComponent t : ed.getType()) {
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 (xver != null && xver.matchingUrl(u.getValue()) && xver.status(u.getValue()) == XVerExtensionStatus.Valid) {
sd = xver.makeDefinition(u.getValue());
@ -922,7 +921,7 @@ public class ProfileUtilities extends TranslatingUtilities {
public void checkDifferentialBaseType(StructureDefinition derived) throws Error {
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();
} else if (derived.getKind() != StructureDefinitionKind.LOGICAL) {
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) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, baseDefinition);
private boolean typeMatchesAncestor(List<TypeRefComponent> type, String baseDefinition, Resource src) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, baseDefinition, src);
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())) {
return true;
}
sd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
sd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
}
return false;
}
@ -1179,11 +1178,12 @@ public class ProfileUtilities extends TranslatingUtilities {
/**
* @param trimDifferential
* @param srcSD
* @param derived
* @throws DefinitionException, FHIRException
* @throws Exception
*/
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) {
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
// did we implicitly step into a new type?
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);
} else {
if (outcome.getType().size() == 0 && !outcome.hasContentReference()) {
@ -1253,27 +1253,27 @@ public class ProfileUtilities extends TranslatingUtilities {
int nbl = nbc;
while (nbl < base.getElement().size() && base.getElement().get(nbl).getPath().startsWith(tgt.getElement().getPath()+"."))
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 {
int nbc = base.getElement().indexOf(tgt.getElement())+1;
int nbl = nbc;
while (nbl < base.getElement().size() && base.getElement().get(nbl).getPath().startsWith(tgt.getElement().getPath()+"."))
nbl++;
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 {
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) {
throw new DefinitionException(context.formatMessage(I18nConstants.UNKNOWN_TYPE__AT_, outcome.getType().get(0), cpath));
}
contextName = dt.getUrl();
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,
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 {
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())) {
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())) {
switch (xver.status(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"));
}
} else if (!sd.hasSnapshot()) {
StructureDefinition sdb = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
StructureDefinition sdb = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
if (sdb == null)
throw new DefinitionException(context.formatMessage(I18nConstants.UNABLE_TO_FIND_BASE__FOR_, sd.getBaseDefinition(), sd.getUrl()));
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);
// 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()));
@ -1415,21 +1415,21 @@ public class ProfileUtilities extends TranslatingUtilities {
int nbl = nbc;
while (nbl < base.getElement().size() && base.getElement().get(nbl).getPath().startsWith(tgt.getElement().getPath()+"."))
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 {
int nbc = base.getElement().indexOf(tgt.getElement())+1;
int nbl = nbc;
while (nbl < base.getElement().size() && base.getElement().get(nbl).getPath().startsWith(tgt.getElement().getPath()+"."))
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 {
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)
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();
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.
// 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,
trimDifferential, contextName, resultPathBase, true, null, null, redirector, srcSD);
trimDifferential, contextName, resultPathBase, true, null, null, redirector, srcSD, derived);
if (e==null)
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.
@ -1541,7 +1541,7 @@ public class ProfileUtilities extends TranslatingUtilities {
}
ndc = differential.getElement().indexOf(diffMatches.get(i));
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) {
typeSliceElement.setMin(0);
}
@ -1606,7 +1606,7 @@ public class ProfileUtilities extends TranslatingUtilities {
int ndc = differential.getElement().indexOf(diffMatches.get(0));
int ndl = findEndOfElement(differential, ndc);
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)
throw new FHIRException(context.formatMessage(I18nConstants.DID_NOT_FIND_SINGLE_SLICE_, diffMatches.get(0).getPath()));
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.
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);
if (!outcome.hasContentReference() && !outcome.hasType()) {
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
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 {
StructureDefinition dt = getTypeForElement(differential, diffCursor, profileName, diffMatches, outcome, webUrl);
StructureDefinition dt = getTypeForElement(differential, diffCursor, profileName, diffMatches, outcome, webUrl, srcSD);
contextName = dt.getUrl();
diffCursor++;
start = diffCursor;
@ -1646,7 +1646,7 @@ public class ProfileUtilities extends TranslatingUtilities {
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,
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++;
@ -1668,7 +1668,7 @@ public class ProfileUtilities extends TranslatingUtilities {
continue;
}*/
// 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
baseCursor = nbl+1;
@ -1701,10 +1701,10 @@ public class ProfileUtilities extends TranslatingUtilities {
// the profile walks into this, so we need to as well
// did we implicitly step into a new type?
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);
} else {
StructureDefinition dt = getTypeForElement(differential, diffCursor, profileName, diffMatches, outcome, webUrl);
StructureDefinition dt = getTypeForElement(differential, diffCursor, profileName, diffMatches, outcome, webUrl, srcSD);
contextName = dt.getUrl();
int start = diffCursor;
if (differential.getElement().get(diffCursor).getPath().equals(cpath)) {
@ -1715,7 +1715,7 @@ public class ProfileUtilities extends TranslatingUtilities {
}
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,
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++;
@ -1811,7 +1811,7 @@ public class ProfileUtilities extends TranslatingUtilities {
// ok passed the checks.
// 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,
trimDifferential, contextName, resultPathBase, true, null, cpath, redirector, srcSD);
trimDifferential, contextName, resultPathBase, true, null, cpath, redirector, srcSD, derived);
if (e==null)
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.
@ -1844,7 +1844,7 @@ public class ProfileUtilities extends TranslatingUtilities {
sEnd = bs.end;
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) {
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.
StructureDefinitionDifferentialComponent fakeDiff = new StructureDefinitionDifferentialComponent();
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());
if (diffMatches.get(0).hasSlicing() || !diffMatches.get(0).hasSliceName()) {
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);
} else if (!diffMatches.get(0).hasSliceName()) {
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) {
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) {
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+"."))
diffCursor++;
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 {
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");
// } 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 ndl = findEndOfElement(differential, ndc);
// 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
baseCursor = nbl;
diffCursor = ndl+1;
@ -2006,7 +2006,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (!outcome.getPath().startsWith(resultPathBase))
throw new DefinitionException(context.formatMessage(I18nConstants.ADDING_WRONG_PATH));
result.getElement().add(outcome);
updateFromDefinition(outcome, diffItem, profileName, trimDifferential, url, srcSD);
updateFromDefinition(outcome, diffItem, profileName, trimDifferential, url, srcSD, derived);
removeStatusExtensions(outcome);
// --- LM Added this
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()+"."))
diffCursor++;
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 {
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(":")) {
// 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()+"."))
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,
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,
List<ElementDefinition> diffMatches, ElementDefinition outcome, String webUrl) {
List<ElementDefinition> diffMatches, ElementDefinition outcome, String webUrl, Resource srcSD) {
if (outcome.getType().size() == 0) {
if (outcome.hasContentReference()) {
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));
}
}
StructureDefinition dt = getProfileForDataType(outcome.getType().get(0), webUrl);
StructureDefinition dt = getProfileForDataType(outcome.getType().get(0), webUrl, srcSD);
if (dt == null)
throw new DefinitionException(context.formatMessage(I18nConstants.UNKNOWN_TYPE__AT_, outcome.getType().get(0), diffMatches.get(0).getPath()));
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;
}
@ -2580,10 +2580,10 @@ public class ProfileUtilities extends TranslatingUtilities {
return s;
}
private StructureDefinition getProfileForDataType(TypeRefComponent type, String webUrl) {
private StructureDefinition getProfileForDataType(TypeRefComponent type, String webUrl, Resource src) {
StructureDefinition sd = null;
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 (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());
@ -2974,7 +2974,7 @@ public class ProfileUtilities extends TranslatingUtilities {
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);
// 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
@ -2992,9 +2992,9 @@ public class ProfileUtilities extends TranslatingUtilities {
// Before applying changes, apply them to what's in the profile
StructureDefinition profile = null;
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)
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) {
ElementDefinition e = profile.getSnapshot().getElement().get(0);
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));
// 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()) {
ValueSet baseVs = context.fetchResource(ValueSet.class, base.getBinding().getValueSet());
ValueSet contextVs = context.fetchResource(ValueSet.class, derived.getBinding().getValueSet());
ValueSet baseVs = context.fetchResource(ValueSet.class, base.getBinding().getValueSet(), srcSD);
ValueSet contextVs = context.fetchResource(ValueSet.class, derived.getBinding().getValueSet(), derivedSrc);
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));
} else if (contextVs == null) {
@ -3266,7 +3266,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (!Base.compareDeep(derived.getType(), base.getType(), false)) {
if (base.hasType()) {
for (TypeRefComponent ts : derived.getType()) {
checkTypeDerivation(purl, srcSD, base, derived, ts);
checkTypeDerivation(purl, derivedSrc, base, derived, ts);
}
}
base.getType().clear();
@ -3338,7 +3338,7 @@ public class ProfileUtilities extends TranslatingUtilities {
// finally, we copy any extensions from source to dest
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")) {
ToolingExtensions.removeExtension(dest, ex.getUrl());
}
@ -3369,7 +3369,7 @@ public class ProfileUtilities extends TranslatingUtilities {
StructureDefinition sdb = context.fetchTypeDefinition(t);
while (sdb != null && !ok) {
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")) {
List<StructureDefinition> sdl = new ArrayList<>();
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) {
List<ElementDefinition> children = new ArrayList<ElementDefinition>();
@ -3729,7 +3729,7 @@ public class ProfileUtilities extends TranslatingUtilities {
List<TypeRefComponent> types = e.getType();
if (!e.hasType()) {
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.hasUserData("path")) {
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;
else
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()) {
c.addPiece(gen.new Piece(null, " ", null));
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;
}
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/")) {
StructureDefinition sd = context.fetchResource(StructureDefinition.class, u);
StructureDefinition sd = context.fetchResource(StructureDefinition.class, u, src);
if (sd != null) {
String disp = sd.hasTitle() ? sd.getTitle() : sd.getName();
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)));
}
} 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) {
String disp = sd.hasTitle() ? sd.getTitle() : sd.getName();
String ref = pkp.getLinkForProfile(null, sd.getUrl());
@ -3949,7 +3949,7 @@ public class ProfileUtilities extends TranslatingUtilities {
url = source.getUrl();
}
if (!url.equals(source.getUrl())) {
source = context.fetchResource(StructureDefinition.class, url);
source = context.fetchResource(StructureDefinition.class, url, source);
if (source == null) {
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("#"));
contentReference = contentReference.substring(contentReference.indexOf("#"));
if (!url.equals(source.getUrl())){
source = context.fetchResource(StructureDefinition.class, url);
source = context.fetchResource(StructureDefinition.class, url, source);
if (source == null) {
return null;
}
@ -4148,7 +4148,7 @@ public class ProfileUtilities extends TranslatingUtilities {
profiles.add(profile);
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 {
return gen.generate(model, imagePath, 0, outputTracker);
} 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,
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;
StructureDefinition profile = profiles == null ? null : profiles.get(profiles.size()-1);
Row typesRow = null;
@ -4393,7 +4393,7 @@ public class ProfileUtilities extends TranslatingUtilities {
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))) {
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);
}
if (typesRow != null && !element.prohibited()) {
makeChoiceRows(typesRow.getSubRows(), element, gen, corePath, profileBaseFileName, mustSupport);
makeChoiceRows(typesRow.getSubRows(), element, gen, corePath, profileBaseFileName, mustSupport, srcSD);
}
}
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-");
}
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
for (TypeRefComponent tr : element.getType()) {
if (!mustSupportMode || allTypesMustSupport(element) || isMustSupport(tr)) {
@ -4629,7 +4629,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (!mustSupportMode || allProfilesMustSupport(tr.getTargetProfile()) || isMustSupport(rt)) {
if (!first)
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()) {
c.addPiece(gen.new Piece(null, " ", null));
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()) {
if (!mustSupportMode || allProfilesMustSupport(tr.getProfile()) || isMustSupport(pt)) {
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)
typeCell.addPiece(gen.new Piece(null, "?gen-e2?", null));
else
@ -4901,7 +4901,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (!c.getPieces().isEmpty())
c.addPiece(gen.new Piece("br"));
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 ref2 = null;
String fixedUrl = null;
@ -5417,7 +5417,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (!c.getPieces().isEmpty())
c.addPiece(gen.new Piece("br"));
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;
if (ed != null) {
String p = ed.getUserString("path");
@ -5661,7 +5661,7 @@ public class ProfileUtilities extends TranslatingUtilities {
code = url.substring(1);
} else if (context != null) {
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];
}
if (profile == null)
@ -6075,7 +6075,7 @@ public class ProfileUtilities extends TranslatingUtilities {
if (!structure.hasSnapshot())
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) {
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());
if (sd.hasBaseDefinition()) {
StructureDefinition base = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
StructureDefinition base = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
if (base == null)
throw new FHIRException(context.formatMessage(I18nConstants.UNABLE_TO_FIND_BASE_DEFINITION_FOR_LOGICAL_MODEL__FROM_, sd.getBaseDefinition(), sd.getUrl()));
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.context.ContextUtilities;
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.model.CanonicalResource;
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.ValueSet;
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.ValueSet.ConceptSetComponent;
import org.hl7.fhir.r5.utils.ResourceSorters;
@ -64,7 +64,7 @@ public class R5ExtensionsLoader {
private Map<String, Loadable<CodeSystem>> codeSystems;
private List<Loadable<StructureDefinition>> structures;
private IWorkerContext context;
private PackageVersion pd;
private PackageInformation pd;
private JsonParser json;
public R5ExtensionsLoader(BasePackageCacheManager pcm, IWorkerContext context) {
@ -79,7 +79,7 @@ public class R5ExtensionsLoader {
public void load() throws FHIRException, IOException {
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" };
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)) {
ValueSet vs = valueSets.get(url).getResource();
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.OperationDefinition;
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.ParametersParameterComponent;
import org.hl7.fhir.r5.model.PlanDefinition;
@ -115,6 +116,7 @@ import org.hl7.fhir.r5.terminologies.ValueSetExpander.TerminologyServiceErrorCla
import org.hl7.fhir.r5.terminologies.ValueSetExpander.ValueSetExpansionOutcome;
import org.hl7.fhir.r5.terminologies.ValueSetExpanderSimple;
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.validation.ValidationContextCarrier;
import org.hl7.fhir.utilities.OIDUtils;
@ -137,6 +139,8 @@ import javax.annotation.Nonnull;
public abstract class BaseWorkerContext extends I18nBase implements IWorkerContext{
private static final boolean QA_CHECK_REFERENCE_SOURCE = true;
public class ResourceProxy {
private Resource resource;
private CanonicalResourceProxy proxy;
@ -250,6 +254,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
protected ILoggingService logger = new SystemOutLoggingService();
protected Parameters expParameters;
private TranslationServices translator = new NullTranslator();
private Map<String, PackageInformation> packages = new HashMap<>();
@Getter
protected TerminologyCache txCache;
@ -336,10 +341,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);
synchronized (lock) {
if (packageInfo != null) {
packages.put(packageInfo.getVID(), packageInfo);
}
if (r.getId() != null) {
Map<String, ResourceProxy> map = allResourcesById.get(r.getType());
if (map == null) {
@ -418,9 +426,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) {
if (packageInfo != null) {
packages.put(packageInfo.getVID(), packageInfo);
}
if (r.getId() != null) {
Map<String, ResourceProxy> map = allResourcesById.get(r.fhirType());
if (map == null) {
@ -713,9 +725,9 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
}
@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;
vs = fetchResource(ValueSet.class, binding.getValueSet());
vs = fetchResource(ValueSet.class, binding.getValueSet(), src);
if (vs == null) {
throw new FHIRException(formatMessage(I18nConstants.UNABLE_TO_RESOLVE_VALUE_SET_, binding.getValueSet()));
}
@ -1239,18 +1251,18 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
private boolean addDependentResources(Parameters pin, ValueSet vs) {
boolean cache = false;
for (ConceptSetComponent inc : vs.getCompose().getInclude()) {
cache = addDependentResources(pin, inc) || cache;
cache = addDependentResources(pin, inc, vs) || cache;
}
for (ConceptSetComponent inc : vs.getCompose().getExclude()) {
cache = addDependentResources(pin, inc) || cache;
cache = addDependentResources(pin, inc, vs) || cache;
}
return cache;
}
private boolean addDependentResources(Parameters pin, ConceptSetComponent inc) {
private boolean addDependentResources(Parameters pin, ConceptSetComponent inc, Resource src) {
boolean cache = false;
for (CanonicalType c : inc.getValueSet()) {
ValueSet vs = fetchResource(ValueSet.class, c.getValue());
ValueSet vs = fetchResource(ValueSet.class, c.getValue(), src);
if (vs != null) {
pin.addParameter().setName("tx-resource").setResource(vs);
if (isTxCaching && cacheId == null || !cached.contains(vs.getVUrl())) {
@ -1260,7 +1272,7 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
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)) {
pin.addParameter().setName("tx-resource").setResource(cs);
if (isTxCaching && cacheId == null || !cached.contains(cs.getVUrl())) {
@ -1397,16 +1409,33 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
return fetchResourceWithExceptionByVersion(cls, uri, null, null);
}
public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri, CanonicalResource source) throws FHIRException {
return fetchResourceWithExceptionByVersion(class_, uri, null, source);
public <T extends Resource> T fetchResourceWithException(Class<T> class_, String uri, Resource sourceForReference) throws FHIRException {
return fetchResourceWithExceptionByVersion(class_, uri, null, sourceForReference);
}
@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) {
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) {
uri = ProfileUtilities.sdNs(uri, null);
}
@ -1425,49 +1454,49 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
}
if (class_ == Resource.class || class_ == null) {
if (structures.has(uri)) {
return (T) structures.get(uri, version);
return (T) structures.get(uri, version, pvlist);
}
if (guides.has(uri)) {
return (T) guides.get(uri, version);
return (T) guides.get(uri, version, pvlist);
}
if (capstmts.has(uri)) {
return (T) capstmts.get(uri, version);
return (T) capstmts.get(uri, version, pvlist);
}
if (measures.has(uri)) {
return (T) measures.get(uri, version);
return (T) measures.get(uri, version, pvlist);
}
if (libraries.has(uri)) {
return (T) libraries.get(uri, version);
return (T) libraries.get(uri, version, pvlist);
}
if (valueSets.has(uri)) {
return (T) valueSets.get(uri, version);
return (T) valueSets.get(uri, version, pvlist);
}
if (codeSystems.has(uri)) {
return (T) codeSystems.get(uri, version);
return (T) codeSystems.get(uri, version, pvlist);
}
if (operations.has(uri)) {
return (T) operations.get(uri, version);
return (T) operations.get(uri, version, pvlist);
}
if (searchParameters.has(uri)) {
return (T) searchParameters.get(uri, version);
return (T) searchParameters.get(uri, version, pvlist);
}
if (plans.has(uri)) {
return (T) plans.get(uri, version);
return (T) plans.get(uri, version, pvlist);
}
if (maps.has(uri)) {
return (T) maps.get(uri, version);
return (T) maps.get(uri, version, pvlist);
}
if (transforms.has(uri)) {
return (T) transforms.get(uri, version);
return (T) transforms.get(uri, version, pvlist);
}
if (actors.has(uri)) {
return (T) transforms.get(uri, version);
return (T) transforms.get(uri, version, pvlist);
}
if (requirements.has(uri)) {
return (T) transforms.get(uri, version);
return (T) transforms.get(uri, version, pvlist);
}
if (questionnaires.has(uri)) {
return (T) questionnaires.get(uri, version);
return (T) questionnaires.get(uri, version, pvlist);
}
for (Map<String, ResourceProxy> rt : allResourcesById.values()) {
@ -1492,47 +1521,47 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
// }
return null;
} else if (class_ == ImplementationGuide.class) {
return (T) guides.get(uri, version);
return (T) guides.get(uri, version, pvlist);
} else if (class_ == CapabilityStatement.class) {
return (T) capstmts.get(uri, version);
return (T) capstmts.get(uri, version, pvlist);
} else if (class_ == Measure.class) {
return (T) measures.get(uri, version);
return (T) measures.get(uri, version, pvlist);
} else if (class_ == Library.class) {
return (T) libraries.get(uri, version);
return (T) libraries.get(uri, version, pvlist);
} else if (class_ == StructureDefinition.class) {
return (T) structures.get(uri, version);
return (T) structures.get(uri, version, pvlist);
} else if (class_ == StructureMap.class) {
return (T) transforms.get(uri, version);
return (T) transforms.get(uri, version, pvlist);
} else if (class_ == ValueSet.class) {
return (T) valueSets.get(uri, version);
return (T) valueSets.get(uri, version, pvlist);
} else if (class_ == CodeSystem.class) {
return (T) codeSystems.get(uri, version);
return (T) codeSystems.get(uri, version, pvlist);
} else if (class_ == ConceptMap.class) {
return (T) maps.get(uri, version);
return (T) maps.get(uri, version, pvlist);
} else if (class_ == ActorDefinition.class) {
return (T) actors.get(uri, version);
return (T) actors.get(uri, version, pvlist);
} else if (class_ == Requirements.class) {
return (T) requirements.get(uri, version);
return (T) requirements.get(uri, version, pvlist);
} else if (class_ == PlanDefinition.class) {
return (T) plans.get(uri, version);
return (T) plans.get(uri, version, pvlist);
} else if (class_ == OperationDefinition.class) {
OperationDefinition od = operations.get(uri, version);
return (T) od;
} else if (class_ == Questionnaire.class) {
return (T) questionnaires.get(uri, version);
return (T) questionnaires.get(uri, version, pvlist);
} else if (class_ == SearchParameter.class) {
SearchParameter res = searchParameters.get(uri, version);
SearchParameter res = searchParameters.get(uri, version, pvlist);
return (T) res;
}
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)) {
return (T) valueSets.get(uri, version);
return (T) valueSets.get(uri, version, pvlist);
}
if (class_ == Questionnaire.class) {
return (T) questionnaires.get(uri, version);
return (T) questionnaires.get(uri, version, pvlist);
}
if (supportedCodeSystems.contains(uri)) {
return null;
@ -1541,7 +1570,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) {
return null;
}
@ -1835,9 +1883,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 {
return fetchResourceWithException(class_, uri, source);
return fetchResourceWithException(class_, uri, sourceForReference);
} catch (FHIRException e) {
throw new Error(e);
}
@ -2345,7 +2393,4 @@ public abstract class BaseWorkerContext extends I18nBase implements IWorkerConte
return this;
}
public void registerVSACRule(boolean byVersion) {
valueSets.registerSpecialRule(valueSets.new VSACRule(byVersion));
}
}

View File

@ -3,9 +3,9 @@ package org.hl7.fhir.r5.context;
import java.util.*;
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.CodeSystem;
import org.hl7.fhir.r5.model.PackageInformation;
import org.hl7.fhir.r5.terminologies.CodeSystemUtilities;
import org.hl7.fhir.utilities.VersionUtilities;
@ -110,15 +110,15 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
private class CachedCanonicalResource<T1 extends CanonicalResource> {
private T1 resource;
private CanonicalResourceProxy proxy;
private PackageVersion packageInfo;
private PackageInformation packageInfo;
public CachedCanonicalResource(T1 resource, PackageVersion packageInfo) {
public CachedCanonicalResource(T1 resource, PackageInformation packageInfo) {
super();
this.resource = resource;
this.packageInfo = packageInfo;
}
public CachedCanonicalResource(CanonicalResourceProxy proxy, PackageVersion packageInfo) {
public CachedCanonicalResource(CanonicalResourceProxy proxy, PackageInformation packageInfo) {
super();
this.proxy = proxy;
this.packageInfo = packageInfo;
@ -134,13 +134,13 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
synchronized (this) {
resource = res;
}
resource.setUserData("package", packageInfo);
resource.setSourcePackage(packageInfo);
proxy = null;
}
return resource;
}
public PackageVersion getPackageInfo() {
public PackageInformation getPackageInfo() {
return packageInfo;
}
public String getUrl() {
@ -158,7 +158,7 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
@Override
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 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 String version; // for debugging purposes
@ -215,7 +217,7 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
map.putAll(source.map);
}
public void register(CanonicalResourceProxy r, PackageVersion packgeInfo) {
public void register(CanonicalResourceProxy r, PackageInformation packgeInfo) {
if (!r.hasId()) {
throw new FHIRException("An id is required for a deferred load resource");
}
@ -223,7 +225,7 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
see(cr);
}
public void see(T r, PackageVersion packgeInfo) {
public void see(T r, PackageInformation packgeInfo) {
if (r != null) {
if (!r.hasId()) {
r.setId(UUID.randomUUID().toString());
@ -234,21 +236,27 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
}
public void see(CachedCanonicalResource<T> cr) {
// -- 1. exit conditions -----------------------------------------------------------------------------
// ignore UTG NUCC erroneous code system
if (cr.getPackageInfo() != null
&& cr.getPackageInfo().getId() != null
&& 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;
}
if (enforceUniqueId && map.containsKey(cr.getId())) {
drop(cr.getId());
}
// -- 2. preparation -----------------------------------------------------------------------------
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
@ -260,33 +268,104 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
}
}
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");
if (map.get(cr.getUrl()) != null && (cr.getPackageInfo() != null && cr.getPackageInfo().isExamplesPackage())) {
return;
}
if (existing != null) {
list.remove(existing);
}
// CachedCanonicalResource<T> existing = cr.hasVersion() ? map.get(cr.getUrl()+"|"+cr.getVersion()) : map.get(cr.getUrl()+"|#0");
// if (existing != null) {
// drop(existing); // was 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);
map.put(cr.getId(), cr); // we do this so we can drop by id
map.put(cr.getUrl(), cr);
if (!listForUrl.containsKey(cr.getUrl())) {
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) {
// first, this is the correct reosurce for this version (if it has a version)
if (cr.hasVersion()) {
map.put(cr.getUrl()+"|"+cr.getVersion(), cr);
} else {
map.put(cr.getUrl()+"|#0", cr);
// -- 4. add to the map all the ways ---------------------------------------------------------------
String pv = cr.getPackageInfo() != null ? cr.getPackageInfo().getVID() : null;
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.hasVersion() ? cr.getUrl()+"|"+cr.getVersion() : cr.getUrl()+"|#0", cr);
if (pv != null) {
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());
}
@ -299,7 +378,6 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
}
if (rl.size() > 0) {
// sort by version as much as we are able
Collections.sort(rl, new MetadataResourceVersionComparator<CachedCanonicalResource<T>>());
// the current is the latest
map.put(url, rl.get(rl.size()-1));
// 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) {
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) {
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;
String mm = VersionUtilities.getMajMin(version);
if (mm != null)
return map.containsKey(system+"|"+mm);
else
return false;
/**
* This is asking for a packaged version aware resolution
*
* if we can resolve the reference in the package dependencies, we will. if we can't
* then we fall back to the non-package approach
*
* 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() {
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) {
for (CachedCanonicalResource<T> t : list) {
@ -437,5 +541,6 @@ public class CanonicalResourceManager<T extends CanonicalResource> {
public boolean isEnforceUniqueId() {
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.hasBaseDefinition())
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())) {
sd = ProfileUtilities.makeBaseDefinition(p.getFhirVersion());
}

View File

@ -8,19 +8,19 @@ import java.util.Date;
/*
Copyright (c) 2011+, HL7, Inc.
All rights reserved.
Redistribution and use in source and binary forms, with or without modification,
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.
* 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
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
prior written permission.
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
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)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
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.ElementDefinition.ElementDefinitionBindingComponent;
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.Resource;
import org.hl7.fhir.r5.model.StructureDefinition;
@ -102,7 +103,7 @@ import javax.annotation.Nonnull;
*/
public interface IWorkerContext {
class ValidationResult {
private ConceptDefinitionComponent definition;
private String system;
@ -110,7 +111,7 @@ public interface IWorkerContext {
private String message;
private TerminologyServiceErrorClass errorClass;
private String txLink;
@Override
public String toString() {
return "ValidationResult [definition=" + definition + ", system=" + system + ", severity=" + severity + ", message=" + message + ", errorClass="
@ -121,7 +122,7 @@ public interface IWorkerContext {
this.severity = severity;
this.message = message;
}
public ValidationResult(String system, ConceptDefinitionComponent definition) {
this.system = system;
this.definition = definition;
@ -133,7 +134,7 @@ public interface IWorkerContext {
this.system = system;
this.definition = definition;
}
public ValidationResult(IssueSeverity severity, String message, TerminologyServiceErrorClass errorClass) {
this.severity = severity;
this.message = message;
@ -207,7 +208,7 @@ public interface IWorkerContext {
public boolean hasMessage() {
return message != null;
}
public Coding asCoding() {
if (isOk() && definition != null && definition.getCode() != null) {
return new Coding(system, definition.getCode(), definition.getDisplay());
@ -221,7 +222,7 @@ public interface IWorkerContext {
private Coding coding;
private ValidationResult result;
private CacheToken cacheToken;
public CodingValidationRequest(Coding coding) {
super();
this.coding = coding;
@ -260,86 +261,17 @@ public interface IWorkerContext {
public void setCacheToken(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 {
/**
* @return List of the resource types that should be loaded
*/
String[] getTypes();
/**
* Request to actually load the resources and do whatever is required
*
@ -350,7 +282,7 @@ public interface IWorkerContext {
* @throws IOException
*/
Bundle loadBundle(InputStream stream, boolean isJson) throws FHIRException, IOException;
/**
* Load a single resources (lazy load)
*
@ -361,7 +293,7 @@ public interface IWorkerContext {
* @throws IOException
*/
Resource loadResource(InputStream stream, boolean isJson) throws FHIRException, IOException;
/**
* get the path for references to this resource.
* @param resource
@ -388,7 +320,7 @@ public interface IWorkerContext {
* @return
*/
public String getVersion();
/**
* 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 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);
/** has the same functionality as fetchResource, but passes in information about the source of the
@ -449,7 +382,7 @@ public interface IWorkerContext {
* @param canonicalForSource
* @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
@ -477,7 +410,7 @@ public interface IWorkerContext {
* @return
*/
public Resource fetchResourceById(String type, String uri);
/**
* find whether a resource is available.
*
@ -501,7 +434,7 @@ public interface IWorkerContext {
* @throws FHIRException
*/
public void cacheResource(Resource res) throws FHIRException;
/**
* cache a resource for later retrieval using fetchResource.
*
@ -514,8 +447,8 @@ public interface IWorkerContext {
* @param res
* @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
*
@ -523,10 +456,10 @@ public interface IWorkerContext {
*
* @param packageInfo
*/
public void cachePackage(PackageDetails packageDetails, List<PackageVersion> dependencies);
public void cachePackage(PackageInformation packageInfo);
// -- profile services ---------------------------------------------------------
/**
* @return a list of the resource names defined for this version
*/
@ -590,7 +523,7 @@ public interface IWorkerContext {
* @return
*/
public ValueSetExpansionOutcome expandVS(ValueSet source, boolean cacheOk, boolean heiarchical);
/**
* ValueSet Expansion - see $expand
*
@ -598,7 +531,7 @@ public interface IWorkerContext {
* @return
*/
public ValueSetExpansionOutcome expandVS(ValueSet source, boolean cacheOk, boolean heiarchical, boolean incompleteOk);
/**
* ValueSet Expansion - see $expand, but resolves the binding first
*
@ -606,8 +539,8 @@ public interface IWorkerContext {
* @return
* @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
* for references to supported system (see "supportsSystem") for
@ -656,7 +589,7 @@ public interface IWorkerContext {
* @return
*/
public ValidationResult validateCode(ValidationOptions options, String code, ValueSet vs);
/**
* Validation of a code - consult the terminology infrstructure and/or service
* to see whether it is known. If known, return a description of it
@ -672,7 +605,7 @@ public interface IWorkerContext {
* @return
*/
public ValidationResult validateCode(ValidationOptions options, String system, String version, String code, String display);
/**
* Validation of a code - consult the terminology infrstructure and/or service
* to see whether it is known. If known, return a description of it
@ -723,7 +656,7 @@ public interface IWorkerContext {
* @return
*/
public ValidationResult validateCode(ValidationOptions options, Coding code, ValueSet vs);
/**
* 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.
@ -745,10 +678,10 @@ public interface IWorkerContext {
* @param vs
*/
public void validateCodeBatch(ValidationOptions options, List<? extends CodingValidationRequest> codes, ValueSet vs);
// todo: figure these out
public Map<String, NamingSystem> getNSUrlMap();
public Map<String, NamingSystem> getNSUrlMap();
public TranslationServices translator();
public interface ILoggingService {
@ -770,7 +703,7 @@ public interface IWorkerContext {
public Set<String> getCodeSystemsUsed();
public int getClientRetryCount();
public IWorkerContext setClientRetryCount(int value);
public TimeTracker clock();
/**
@ -782,7 +715,7 @@ public interface IWorkerContext {
* @return
*/
public StructureDefinition fetchTypeDefinition(String typeName);
/**
* 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
* @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(PackageVersion pack);
public PackageDetails getPackage(PackageVersion pack);
public boolean hasPackage(String id, String ver);
public boolean hasPackage(PackageInformation pack);
public PackageInformation getPackage(String id, String ver);
public PackageInformation getPackageForUrl(String url);
public IWorkerContextManager.IPackageLoadingTracker getPackageTracker();
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);
}
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();
for (String name : source.keySet()) {
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"))
loadFromFile(stream, name, loader, filter);
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;
try {
if (loader != null)
@ -487,7 +487,7 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
}
for (String s : pi.listResources(types)) {
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++;
} catch (Exception 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)) {
if (!pri.getFilename().contains("ig-r4")) {
try {
registerResourceFromPackage(new PackageResourceLoader(pri, loader), new PackageVersion(pi.id(), pi.version(), pi.dateAsDate()));
registerResourceFromPackage(new PackageResourceLoader(pri, loader), new PackageInformation(pi));
t++;
} catch (FHIRException 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;
}
@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;
}
public void cachePackage(PackageVersion packageDetails, List<PackageVersion> dependencies) {
public void cachePackage(PackageInformation packageInfo) {
// nothing yet
}
@ -720,17 +735,12 @@ public class SimpleWorkerContext extends BaseWorkerContext implements IWorkerCon
}
@Override
public void cachePackage(PackageDetails packageDetails, List<PackageVersion> dependencies) {
// TODO Auto-generated method stub
}
@Override
public boolean hasPackage(PackageVersion pack) {
public boolean hasPackage(PackageInformation pack) {
return false;
}
@Override
public PackageDetails getPackage(PackageVersion pack) {
public PackageInformation getPackage(String id, String ver) {
return null;
}

View File

@ -942,7 +942,7 @@ public class Element extends Base {
return null;
ICodingImpl c = new ICodingImpl(true, true, false, false);
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)
return null;
for (ValueSetExpansionContainsComponent cc : vse.getValueset().getExpansion().getContains()) {

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) {
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
}

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

View File

@ -50,7 +50,7 @@ public class ActorDefinitionRenderer extends ResourceRenderer {
if (acd.hasCapabilities()) {
tbl.tr().td().tx("Capabilities:");
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) {
td.ah(cs.getUserString("path")).tx(cs.present());
} else {
@ -63,7 +63,7 @@ public class ActorDefinitionRenderer extends ResourceRenderer {
boolean first = true;
for (UrlType t : acd.getReference()) {
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) {
td.ah(df.getUserString("path")).tx(df.present());
} else {

View File

@ -44,12 +44,12 @@ public class ConceptMapRenderer extends TerminologyRenderer {
XhtmlNode p = x.para();
p.tx("Mapping from ");
if (cm.hasSourceScope())
AddVsRef(cm.getSourceScope().primitiveValue(), p);
AddVsRef(cm.getSourceScope().primitiveValue(), p, cm);
else
p.tx("(not specified)");
p.tx(" to ");
if (cm.hasTargetScope())
AddVsRef(cm.getTargetScope().primitiveValue(), p);
AddVsRef(cm.getTargetScope().primitiveValue(), p, cm);
else
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)) {
x.code().tx(uri.getValue());
} else {
@ -773,7 +773,7 @@ public class DataRenderer extends Renderer {
} else if (uri.getValue().startsWith("mailto:")) {
x.ah(uri.getValue()).addText(uri.getValue().substring(7));
} 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")) {
String title = target instanceof CanonicalResource ? ((CanonicalResource) target).present() : uri.getValue();
x.ah(target.getUserString("path")).addText(title);

View File

@ -52,7 +52,7 @@ public class OperationDefinitionRenderer extends TerminologyRenderer {
if (opd.hasInputProfile()) {
XhtmlNode p = x.para();
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) {
p.pre().tx(opd.getInputProfile());
} else {
@ -62,7 +62,7 @@ public class OperationDefinitionRenderer extends TerminologyRenderer {
if (opd.hasOutputProfile()) {
XhtmlNode p = x.para();
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) {
p.pre().tx(opd.getOutputProfile());
} else {
@ -79,7 +79,7 @@ public class OperationDefinitionRenderer extends TerminologyRenderer {
tr.td().b().tx("Binding");
tr.td().b().tx("Documentation");
for (OperationDefinitionParameterComponent p : opd.getParameter()) {
genOpParam(tbl, "", p);
genOpParam(tbl, "", p, opd);
}
addMarkdown(x, opd.getComment());
return true;
@ -98,7 +98,7 @@ public class OperationDefinitionRenderer extends TerminologyRenderer {
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;
tr = tbl.tr();
tr.td().addText(p.getUse().toString());
@ -129,13 +129,13 @@ public class OperationDefinitionRenderer extends TerminologyRenderer {
}
td = tr.td();
if (p.hasBinding() && p.getBinding().hasValueSet()) {
AddVsRef(p.getBinding().getValueSet(), td);
AddVsRef(p.getBinding().getValueSet(), td, opd);
td.tx(" ("+p.getBinding().getStrength().getDisplay()+")");
}
addMarkdown(tr.td(), p.getDocumentation());
if (!p.hasType()) {
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);
}
} 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) {
renderTiming(x, (Timing) e);
} else if (e instanceof Range) {
@ -795,7 +795,14 @@ public class ProfileDrivenRenderer extends ResourceRenderer {
RenderingContext ctxt = context.copy();
ctxt.setContained(true);
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);
}
}

View File

@ -289,7 +289,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
if (i.hasDefinition()) {
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
defn.getPieces().add(gen.new Piece(null, "Definition: ", null));
genDefinitionLink(gen, i, defn);
genDefinitionLink(gen, i, defn, q);
}
if (i.hasEnableWhen()) {
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));
}
} 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")) {
defn.getPieces().add(gen.new Piece(null, i.getAnswerValueSet(), null));
} else {
@ -390,7 +390,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
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?
String path = null;
String d = i.getDefinition();
@ -398,7 +398,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
path = d.substring(d.indexOf("#")+1);
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) {
String url = sd.getUserString("path");
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?
String path = null;
String d = i.getDefinition();
@ -419,7 +419,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
path = d.substring(d.indexOf("#")+1);
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) {
String url = sd.getUserString("path");
if (url != null) {
@ -479,7 +479,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
if (i.hasDefinition()) {
if (!defn.getPieces().isEmpty()) defn.addPiece(gen.new Piece("br"));
defn.getPieces().add(gen.new Piece(null, "Definition: ", null));
genDefinitionLink(gen, i, defn);
genDefinitionLink(gen, i, defn, q);
}
if (i.hasEnableWhen()) {
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));
}
} 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")) {
defn.getPieces().add(gen.new Piece(null, i.getAnswerValueSet(), null));
} else {
@ -716,7 +716,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
item(ul, "Max Length", Integer.toString(i.getMaxLength()));
}
if (i.hasDefinition()) {
genDefinitionLink(item(ul, "Definition"), i);
genDefinitionLink(item(ul, "Definition"), i, q);
}
if (i.hasEnableWhen()) {
item(ul, "Enable When", "todo");
@ -731,7 +731,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
ans.ah(vs.getUserString("path")).tx(vs.present());
}
} 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")) {
ans.tx(i.getAnswerValueSet());
} else {
@ -819,7 +819,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
vs.setUrl(q.getUrl()+"--"+q.getContained(i.getAnswerValueSet().substring(1)));
}
} else {
vs = context.getContext().fetchResource(ValueSet.class, i.getAnswerValueSet());
vs = context.getContext().fetchResource(ValueSet.class, i.getAnswerValueSet(), q);
}
if (vs != null) {
ValueSetExpansionOutcome exp = context.getContext().expandVS(vs, true, false);
@ -940,7 +940,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
// content control
defn(tbl, "Max Length", qi.getMaxLength());
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()) {
XhtmlNode tr = tbl.tr();
@ -983,7 +983,7 @@ public class QuestionnaireRenderer extends TerminologyRenderer {
// formal definitions
if (qi.hasDefinition()) {
genDefinitionLink(defn(tbl, "Definition"), qi);
genDefinitionLink(defn(tbl, "Definition"), qi, q);
}
if (qi.hasCode()) {

View File

@ -225,7 +225,7 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
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?
String path = null;
String d = i.getDefinition();
@ -233,7 +233,7 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
path = d.substring(d.indexOf("#")+1);
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) {
String url = sd.getUserString("path");
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?
String path = null;
String d = i.getDefinition();
@ -254,7 +254,7 @@ public class QuestionnaireResponseRenderer extends ResourceRenderer {
path = d.substring(d.indexOf("#")+1);
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) {
String url = sd.getUserString("path");
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 {
if (req.hasActor()) {
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();
p.tx("These requirements apply to the actor ");
if (acd == null) {
@ -55,7 +55,7 @@ public class RequirementsRenderer extends ResourceRenderer {
x.para().tx("These requirements apply to the following actors:");
XhtmlNode ul = x.ul();
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) {
ul.li().code(a.getValue());
} else {
@ -66,7 +66,7 @@ public class RequirementsRenderer extends ResourceRenderer {
}
if (req.hasDerivedFrom()) {
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();
p.tx("These requirements derive from ");
if (reqd == null) {
@ -78,7 +78,7 @@ public class RequirementsRenderer extends ResourceRenderer {
x.para().tx("These requirements are derived from the following requirements:");
XhtmlNode ul = x.ul();
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) {
ul.li().code(a.getValue());
} else {
@ -118,7 +118,7 @@ public class RequirementsRenderer extends ResourceRenderer {
String url = stmt.getDerivedFrom();
String key = url.contains("#") ? url.substring(url.indexOf("#")+1) : "";
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) {
RequirementsStatementComponent stmtr = reqr.findStatement(key);
if (stmtr != null) {
@ -140,7 +140,7 @@ public class RequirementsRenderer extends ResourceRenderer {
if (url.contains("#")) {
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) {
String desc = getResourceDescription(r, null);
li.ah(c.getValue()).tx(desc);
@ -174,7 +174,7 @@ public class RequirementsRenderer extends ResourceRenderer {
if (url.contains("#")) {
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;
if (r == null) {
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 {
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) {
return;
}
Resource target = context.getWorker().fetchResource(Resource.class, url);
Resource target = context.getWorker().fetchResource(Resource.class, url, src);
if (target == null || !(target instanceof CanonicalResource)) {
x.code().tx(url);
} else {

View File

@ -135,7 +135,7 @@ public class SearchParameterRenderer extends TerminologyRenderer {
tbl = x.table("grid");
for (SearchParameterComponentComponent t : spd.getComponent()) {
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")) {
tr.td().ah(tsp.getUserString("path")).tx(tsp.present());
} 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;
if (rcontext != null) {
BundleEntryComponent be = rcontext.resolve(value);
@ -283,13 +283,11 @@ public abstract class TerminologyRenderer extends ResourceRenderer {
}
CanonicalResource vs = (CanonicalResource) res;
if (vs == null)
vs = getContext().getWorker().fetchResource(ValueSet.class, value);
vs = getContext().getWorker().fetchResource(ValueSet.class, value, source);
if (vs == null)
vs = getContext().getWorker().fetchResource(StructureDefinition.class, value);
// if (vs == null)
// vs = context.getWorker().fetchResource(DataElement.class, value);
vs = getContext().getWorker().fetchResource(StructureDefinition.class, value, source);
if (vs == null)
vs = getContext().getWorker().fetchResource(Questionnaire.class, value);
vs = getContext().getWorker().fetchResource(Questionnaire.class, value, source);
if (vs != null) {
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);
}
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));
}
}
@ -194,8 +194,8 @@ public class ValueSetRenderer extends TerminologyRenderer {
x.para().tx("This value set contains "+count.toString()+" concepts");
}
generateContentModeNotices(x, vs.getExpansion());
generateVersionNotice(x, vs.getExpansion());
generateContentModeNotices(x, vs.getExpansion(), vs);
generateVersionNotice(x, vs.getExpansion(), vs);
CodeSystem allCS = null;
boolean doLevel = false;
@ -304,12 +304,12 @@ public class ValueSetRenderer extends TerminologyRenderer {
return false;
}
private void generateContentModeNotices(XhtmlNode x, ValueSetExpansionComponent expansion) {
generateContentModeNotice(x, expansion, "example", "Expansion based on example code system");
generateContentModeNotice(x, expansion, "fragment", "Expansion based on code system fragment");
private void generateContentModeNotices(XhtmlNode x, ValueSetExpansionComponent expansion, Resource vs) {
generateContentModeNotice(x, expansion, "example", "Expansion based on example code system", vs);
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();
for (ValueSetExpansionParameterComponent p : expansion.getParameter()) {
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
XhtmlNode p = x.para().style("border: black 1px dotted; background-color: #ffcccc; padding: 8px; margin-bottom: 8px");
p.tx(text+" ");
expRef(p, s, v);
expRef(p, s, v, vs);
}
} else {
for (String v : versions.get(s)) {
@ -337,7 +337,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
ul = div.ul();
first = false;
}
expRef(ul.li(), s, v);
expRef(ul.li(), s, v, vs);
}
}
}
@ -435,7 +435,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
}
@SuppressWarnings("rawtypes")
private void generateVersionNotice(XhtmlNode x, ValueSetExpansionComponent expansion) {
private void generateVersionNotice(XhtmlNode x, ValueSetExpansionComponent expansion, Resource vs) {
Multimap<String, String> versions = HashMultimap.create();
for (ValueSetExpansionParameterComponent p : expansion.getParameter()) {
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
XhtmlNode p = x.para().style("border: black 1px dotted; background-color: #EEEEEE; padding: 8px; margin-bottom: 8px");
p.tx("Expansion based on ");
expRef(p, s, v);
expRef(p, s, v, vs);
}
} else {
for (String v : versions.get(s)) {
@ -463,14 +463,14 @@ public class ValueSetRenderer extends TerminologyRenderer {
ul = div.ul();
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
if (u.equals("http://snomed.info/sct")) {
String[] parts = v.split("\\/");
@ -492,7 +492,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
x.tx("Loinc v"+v);
}
} 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.hasUserData("path")) {
x.ah(cr.getUserString("path")).tx(cr.present()+" v"+v+" ("+cr.fhirType()+")");
@ -892,13 +892,13 @@ public class ValueSetRenderer extends TerminologyRenderer {
}
int index = 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 {
XhtmlNode p = x.para();
p.tx("This value set includes codes based on the following rules:");
XhtmlNode ul = x.ul();
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++;
}
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:");
ul = x.ul();
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++;
}
}
@ -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;
XhtmlNode li;
li = ul.li();
@ -1228,7 +1228,7 @@ public class ValueSetRenderer extends TerminologyRenderer {
first = false;
else
li.tx(", ");
AddVsRef(vs.asStringValue(), li);
AddVsRef(vs.asStringValue(), li, vsRes);
}
}
if (inc.hasExtension(ToolingExtensions.EXT_EXPAND_RULES) || inc.hasExtension(ToolingExtensions.EXT_EXPAND_GROUP)) {
@ -1244,12 +1244,12 @@ public class ValueSetRenderer extends TerminologyRenderer {
first = false;
else
li.tx(", ");
AddVsRef(vs.asStringValue(), li);
AddVsRef(vs.asStringValue(), li, vsRes);
}
} else {
XhtmlNode xul = li.ul();
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.StructureDefinition;
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.utilities.xhtml.XhtmlNode;
@ -56,6 +57,7 @@ public class BaseWrappers {
public StructureDefinition getDefinition();
public boolean hasNarrative();
public String getNameFromResource();
public Resource getResource(); // if there is one
}
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.ElementDefinition;
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.StructureDefinition;
import org.hl7.fhir.r5.model.StructureDefinition.StructureDefinitionKind;
@ -386,7 +387,7 @@ public class DOMWrappers {
if ("DomainResource".equals(sd.getType())) {
return true;
}
sd = context.getWorker().fetchResource(StructureDefinition.class, sd.getBaseDefinition());
sd = context.getWorker().fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
}
return false;
}
@ -404,6 +405,11 @@ public class DOMWrappers {
return null;
}
@Override
public Resource getResource() {
return null;
}
}

View File

@ -295,7 +295,7 @@ public class DirectWrappers {
if ("DomainResource".equals(sd.getType())) {
return true;
}
sd = context.getWorker().fetchResource(StructureDefinition.class, sd.getBaseDefinition());
sd = context.getWorker().fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
}
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.ElementDefinition;
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.StringType;
import org.hl7.fhir.r5.model.StructureDefinition;
@ -266,7 +267,7 @@ public class ElementWrappers {
if ("DomainResource".equals(sd.getType())) {
return true;
}
sd = context.getWorker().fetchResource(StructureDefinition.class, sd.getBaseDefinition());
sd = context.getWorker().fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
}
return false;
}
@ -288,6 +289,11 @@ public class ElementWrappers {
return wrapped;
}
@Override
public Resource getResource() {
return null;
}
}
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.NoTerminologyServiceException;
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.model.CanonicalType;
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.Coding;
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.ValueSet;
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);
if (res.getErrorClass() == TerminologyServiceErrorClass.UNKNOWN || res.getErrorClass() == TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED || res.getErrorClass() == TerminologyServiceErrorClass.VALUESET_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));
for (ConceptReferenceComponent cc : vsi.getConcept()) {
if (cc.getCode().equals(code)) {
return true;
}
}
info.setErr(TerminologyServiceErrorClass.CODESYSTEM_UNSUPPORTED);
}
return null;
@ -786,7 +792,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
}
protected boolean isValueSetUnionImports() {
PackageVersion p = (PackageVersion) valueset.getUserData("package");
PackageInformation p = (PackageInformation) valueset.getSourcePackage();
if (p != null) {
return p.getDate().before(new GregorianCalendar(2022, Calendar.MARCH, 31).getTime());
} else {
@ -853,7 +859,7 @@ public class ValueSetCheckerSimple extends ValueSetWorker implements ValueSetChe
if (inner.containsKey(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);
inner.put(url, 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.TerminologyServiceException;
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.CodeSystem;
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.Extension;
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.ParametersParameterComponent;
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 {
if (value == null)
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 (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");
} else {
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) {
PackageVersion p = (PackageVersion) valueSet.getUserData("package");
PackageInformation p = valueSet.getSourcePackage();
if (p != null) {
return p.getDate().before(new GregorianCalendar(2022, Calendar.MARCH, 31).getTime());
} 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.model.ElementDefinition;
import org.hl7.fhir.r5.model.ElementDefinition.TypeRefComponent;
import org.hl7.fhir.r5.model.Resource;
import org.hl7.fhir.r5.model.StructureDefinition;
public class DefinitionNavigator {
@ -164,19 +165,20 @@ public class DefinitionNavigator {
*
* you have to provide a type if there's more than one type
* for current() since this library doesn't know how to choose
* @param res
* @throws DefinitionException
* @
*/
public boolean hasTypeChildren(TypeRefComponent type) throws DefinitionException {
public boolean hasTypeChildren(TypeRefComponent type, Resource res) throws DefinitionException {
if (typeChildren == null || typeOfChildren != type) {
loadTypedChildren(type);
loadTypedChildren(type, res);
}
return !typeChildren.isEmpty();
}
private void loadTypedChildren(TypeRefComponent type) throws DefinitionException {
private void loadTypedChildren(TypeRefComponent type, Resource src) throws DefinitionException {
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) {
DefinitionNavigator dn = new DefinitionNavigator(context, sd, 0, path, names, sd.getType());
typeChildren = dn.children();
@ -187,13 +189,14 @@ public class DefinitionNavigator {
/**
*
* @param res
* @return
* @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) {
loadTypedChildren(type);
loadTypedChildren(type, res);
}
return typeChildren;
}

View File

@ -209,10 +209,12 @@ public class FHIRPathEngine {
public static class TypedElementDefinition {
private ElementDefinition element;
private String type;
public TypedElementDefinition(ElementDefinition element, String type) {
private StructureDefinition src;
public TypedElementDefinition(StructureDefinition src, ElementDefinition element, String type) {
super();
this.element = element;
this.type = type;
this.src = src;
}
public TypedElementDefinition(ElementDefinition element) {
super();
@ -245,6 +247,9 @@ public class FHIRPathEngine {
return false;
}
}
public StructureDefinition getSrc() {
return src;
}
}
private IWorkerContext worker;
private IEvaluationContext hostServices;
@ -1812,7 +1817,7 @@ public class FHIRPathEngine {
if (tn.equals(sd.getType())) {
return makeBoolean(true);
}
sd = worker.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
sd = worker.fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
}
return makeBoolean(false);
}
@ -2992,7 +2997,7 @@ public class FHIRPathEngine {
result.add(item);
break;
}
sd = worker.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
sd = worker.fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
}
}
} else {
@ -4528,7 +4533,7 @@ public class FHIRPathEngine {
if (n.equals(sd.getType())) {
return makeBoolean(true);
}
sd = worker.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
sd = worker.fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
}
return makeBoolean(false);
}
@ -4565,7 +4570,7 @@ public class FHIRPathEngine {
result.add(b);
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);
if (m != null && hasDataType(m.definition)) {
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) {
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
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) {
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) {
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) {
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()) {
System.out.println("t: "+t.getId());
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")) {
exsd = worker.fetchResource(StructureDefinition.class, exsd.getBaseDefinition());
exsd = worker.fetchResource(StructureDefinition.class, exsd.getBaseDefinition(), exsd);
}
if (exsd != null && exsd.getUrl().equals(targetUrl)) {
if (profileUtilities.getChildMap(sd, t).getList().isEmpty()) {
@ -5851,7 +5856,7 @@ public class FHIRPathEngine {
okToNotResolve = true;
if ((atn.contains(stn))) {
if (element.getTypes().size() > 1) {
focus = new TypedElementDefinition(element.getElement(), stn);
focus = new TypedElementDefinition( element.getSrc(), element.getElement(), stn);
} else {
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());
}
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 {
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

@ -1,13 +1,13 @@
package org.hl7.fhir.r5.utils;
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.PackageInformation;
import org.hl7.fhir.r5.model.StructureDefinition;
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())) {
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.Set;
import org.hl7.fhir.r5.model.Base;
import org.hl7.fhir.r5.model.Bundle;
import org.hl7.fhir.r5.model.Bundle.BundleEntryComponent;
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.IssueSeverity;
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.Resource;
import org.hl7.fhir.r5.model.ResourceType;
@ -180,4 +182,28 @@ public class ResourceUtilities {
}
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;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import org.hl7.fhir.r5.context.CanonicalResourceManager;
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.PackageInformation;
import org.hl7.fhir.r5.model.ValueSet;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@ -428,12 +430,12 @@ public class CanonicalResourceManagerTests {
vs2.setVersion("2000.0.0");
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", "2.0.0"));
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.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
@ -809,5 +811,46 @@ public class CanonicalResourceManagerTests {
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;
}
public void setRuleDate(Date ruleDate) {
public ValidationMessage setRuleDate(Date ruleDate) {
this.ruleDate = ruleDate;
return this;
}
public void setRuleDate(String value) {
public ValidationMessage setRuleDate(String value) {
if (value == null) {
ruleDate = null;
} else {
@ -834,5 +835,6 @@ public class ValidationMessage implements Comparator<ValidationMessage>, Compara
}
ruleDate = d;
}
return this;
}
}

View File

@ -2,6 +2,7 @@ package org.hl7.fhir.utilities;
import static org.junit.jupiter.api.Assertions.assertEquals;
import java.time.ZonedDateTime;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
@ -10,6 +11,7 @@ import java.util.stream.Stream;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
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.equals("http://www.rfc-editor.org/bcp/bcp13.txt")) {
reference = "http://hl7.org/fhir/ValueSet/mimetypes";
@ -814,11 +814,11 @@ public class BaseValidator implements IValidationContextResourceLoader {
return null;
} else {
long t = System.nanoTime();
ValueSet fr = context.fetchResource(ValueSet.class, reference);
ValueSet fr = context.fetchResource(ValueSet.class, reference, src);
if (fr == null) {
if (!Utilities.isAbsoluteUrl(reference)) {
reference = resolve(uri, reference);
fr = context.fetchResource(ValueSet.class, reference);
fr = context.fetchResource(ValueSet.class, reference, src);
}
}
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.context.ContextUtilities;
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.SimpleWorkerContext;
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.ImplementationGuide;
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.Resource;
import org.hl7.fhir.r5.model.StructureDefinition;
@ -429,7 +429,7 @@ public class ValidationEngine implements IValidatorResourceFetcher, IValidationP
if (userAgent != null) {
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");
}
// 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);
if (sd.hasExtension(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) {
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)) {
@ -1025,7 +1025,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return false;
} else {
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);
// 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();
if (warning(errors, NO_RULE_DATE, IssueType.CODEINVALID, element.line(), element.col(), path, binding != null, I18nConstants.TERMINOLOGY_TX_BINDING_MISSING, path)) {
if (binding.hasValueSet()) {
ValueSet valueset = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl());
ValueSet valueset = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl(), profile);
if (valueset == null) {
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()))) {
@ -1324,7 +1324,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
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 (binding.hasValueSet()) {
ValueSet valueset = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl());
ValueSet valueset = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl(), profile);
if (valueset == null) {
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()))) {
@ -1455,7 +1455,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
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 (binding.hasValueSet()) {
ValueSet valueset = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl());
ValueSet valueset = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl(), profile);
if (valueset == null) {
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()))) {
@ -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) {
ValueSet valueset = resolveBindingReference(profile, maxVSUrl, profile.getUrl());
ValueSet valueset = resolveBindingReference(profile, maxVSUrl, profile.getUrl(), profile);
if (valueset == null) {
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))) {
@ -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) {
boolean ok = true;
ValueSet valueset = resolveBindingReference(profile, maxVSUrl, profile.getUrl());
ValueSet valueset = resolveBindingReference(profile, maxVSUrl, profile.getUrl(), profile);
if (valueset == null) {
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))) {
@ -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) {
boolean ok = true;
ValueSet valueset = resolveBindingReference(profile, maxVSUrl, profile.getUrl());
ValueSet valueset = resolveBindingReference(profile, maxVSUrl, profile.getUrl(), profile);
if (valueset == null) {
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))) {
@ -1732,7 +1732,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
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 (binding.hasValueSet()) {
ValueSet valueset = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl());
ValueSet valueset = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl(), profile);
if (valueset == null) {
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()))) {
@ -1977,7 +1977,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
break;
}
if (sd.getBaseDefinition() != null) {
sd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition());
sd = context.fetchResource(StructureDefinition.class, sd.getBaseDefinition(), sd);
} else {
sd = null;
}
@ -2533,7 +2533,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
} else {
boolean tok = false;
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;
}
}
@ -2921,7 +2921,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
// firstly, resolve the value set
ElementDefinitionBindingComponent binding = elementContext.getBinding();
if (binding.hasValueSet()) {
ValueSet vs = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl());
ValueSet vs = resolveBindingReference(profile, binding.getValueSet(), profile.getUrl(), profile);
if (vs == null) {
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()))) {
@ -3442,7 +3442,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
StructureDefinition sdFT = context.fetchResource(StructureDefinition.class, "http://hl7.org/fhir/StructureDefinition/"+ft);
boolean rok = false;
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) {
types.add(sd.getType());
}
@ -3452,7 +3452,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
rok = true;
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,
@ -3758,7 +3758,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
for (TypeRefComponent type : element.getType()) {
for (CanonicalType p : type.getProfile()) {
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)
throw new DefinitionException(context.formatMessage(I18nConstants.UNABLE_TO_RESOLVE_PROFILE_, p));
profile = sd;
@ -3801,13 +3801,13 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return igs;
}
private StructureDefinition getProfileForType(String type, List<TypeRefComponent> list) {
private StructureDefinition getProfileForType(String type, List<TypeRefComponent> list, Resource src) {
for (TypeRefComponent tr : list) {
String url = tr.getWorkingCode();
if (!Utilities.isAbsoluteUrl(url))
url = "http://hl7.org/fhir/StructureDefinition/" + url;
long t = System.nanoTime();
StructureDefinition sd = context.fetchResource(StructureDefinition.class, url);
StructureDefinition sd = context.fetchResource(StructureDefinition.class, url, src);
timeTracker.sd(t);
if (sd != null && (sd.getType().equals(type) || sd.getUrl().equals(type)) && sd.hasSnapshot()) {
return sd;
@ -4196,7 +4196,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return null;
} else {
long t = System.nanoTime();
StructureDefinition fr = context.fetchResource(StructureDefinition.class, pr);
StructureDefinition fr = context.fetchResource(StructureDefinition.class, pr, profile);
timeTracker.sd(t);
return fr;
}
@ -4800,7 +4800,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
for (ImplementationGuide ig : igs) {
for (ImplementationGuideGlobalComponent gl : ig.getGlobal()) {
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 (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()));
@ -5132,7 +5132,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
if (typeForResource.getProfile().size() == 1) {
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);
trackUsage(profile, hostContext, element);
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 {
List<String> types = new ArrayList<>();
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())) {
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;
}
@ -5533,7 +5533,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
String tail = null;
if (profiles.isEmpty()) {
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
// 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);
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;
} else {
elementValidated = true;
@ -6020,7 +6020,7 @@ public class InstanceValidator extends BaseValidator implements IResourceValidat
return false;
}
while (profile != null) {
profile = context.fetchResource(StructureDefinition.class, profile.getBaseDefinition());
profile = context.fetchResource(StructureDefinition.class, profile.getBaseDefinition(), profile);
if (profile != null) {
if (source.equals(profile.getUrl())) {
return true;

View File

@ -546,7 +546,7 @@ public class QuestionnaireValidator extends BaseValidator {
if (ref.startsWith("#") && qSrc.container != null) {
vs = (ValueSet) loadContainedResource(errors, qSrc.containerPath, qSrc.container, ref.substring(1), ValueSet.class);
} 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))) {
try {

View File

@ -19,7 +19,7 @@
<properties>
<hapi_fhir_version>5.4.0</hapi_fhir_version>
<validator_test_case_version>1.1.127</validator_test_case_version>
<validator_test_case_version>1.1.128-SNAPSHOT</validator_test_case_version>
<junit_jupiter_version>5.7.1</junit_jupiter_version>
<junit_platform_launcher_version>1.8.2</junit_platform_launcher_version>
<maven_surefire_version>3.0.0-M5</maven_surefire_version>