Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bump org.hl7.fhir.core to 6.4.4 #6620

Open
wants to merge 34 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
34 commits
Select commit Hold shift + click to select a range
9e9f1e6
Breaking test
dotasek Nov 26, 2024
7a35d49
Additional testing to demonstrate mutations
dotasek Nov 26, 2024
349ee96
Merge remote-tracking branch 'origin/master' into do-20241126-json-pa…
dotasek Jan 13, 2025
4dd7760
Remove test - parser always produces valid FHIR contained resource ids
dotasek Jan 14, 2025
7826fae
Move all contained tests to nested test
dotasek Jan 14, 2025
35beac1
Assert that getResource and contained are same object when read
dotasek Jan 14, 2025
2447c8c
Add explicit base case for FHIRPath contained
dotasek Jan 14, 2025
0f99005
Test cleanup and some additional assertions
dotasek Jan 14, 2025
0cd295c
Bump core version + fix method signatures
dotasek Jan 14, 2025
67b5aae
FIXME to TODO
dotasek Jan 14, 2025
490476f
Merge remote-tracking branch 'origin/master' into do-20250114-core-bu…
dotasek Jan 15, 2025
2ee317e
Fix wg related validation changes
dotasek Jan 16, 2025
349348b
Fix format validation message
dotasek Jan 16, 2025
7eb1220
Fix format for validation message 2
dotasek Jan 16, 2025
a4f8ed6
Fix format for validation message 3
dotasek Jan 16, 2025
410ab53
Try fixing contained by tracking generated contained IDs
dotasek Jan 16, 2025
328deeb
Merge branch 'master' into do-20250114-core-bump-6-4-4
dotasek Jan 20, 2025
e3fabda
Use different logic to identify internal fragments
dotasek Jan 20, 2025
198854f
Remove dead code + spotless
dotasek Jan 20, 2025
4acbb2a
Naive solution for search param extraction
dotasek Jan 21, 2025
1a76c77
Better isInternalFragment, still naive
dotasek Jan 21, 2025
c089a44
Add hash to reference when modifying for search params
dotasek Jan 22, 2025
659980c
Fix double # when adding ref id for modifyResource=true
dotasek Jan 22, 2025
0dd8096
Merge branch 'master' into do-20250114-core-bump-6-4-4
dotasek Jan 23, 2025
55a36f7
Merge branch 'master' into do-20250114-core-bump-6-4-4
dotasek Jan 24, 2025
7740164
Fix hashless ref ID in test
dotasek Jan 24, 2025
4e7a5e5
Consistent hash use in getResourceToIdMap()
dotasek Jan 24, 2025
fdcbea2
Fix extra # in test
dotasek Jan 24, 2025
70297b2
Fix unneeded # in test
dotasek Jan 24, 2025
d5c1537
Add # when replacing an empty ref with a resource id
dotasek Jan 24, 2025
cf7e4e8
Fix more # based test failures
dotasek Jan 28, 2025
3d290c8
Merge branch 'master' into do-20250114-core-bump-6-4-4
dotasek Feb 11, 2025
7d00b1c
Apply spotless
dotasek Feb 11, 2025
7ad9929
Merge remote-tracking branch 'origin/master' into do-20250114-core-bu…
dotasek Feb 11, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 6 additions & 5 deletions hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ public void wereBack() {
myErrorHandler.containedResourceWithNoId(null);
} else {
if (!res.getId().isLocal()) {
res.setId(new IdDt('#' + res.getId().getIdPart()));
res.setId(new IdDt(res.getId().getIdPart()));
}
getPreResourceState().getContainedResources().put(res.getId().getValueAsString(), res);
}
Expand Down Expand Up @@ -439,7 +439,7 @@ public void wereBack() {
// need an ID to be referred to)
myErrorHandler.containedResourceWithNoId(null);
} else {
res.getIdElement().setValue('#' + res.getIdElement().getIdPart());
res.getIdElement().setValue(res.getIdElement().getIdPart());
getPreResourceState()
.getContainedResources()
.put(res.getIdElement().getValue(), res);
Expand Down Expand Up @@ -1238,12 +1238,13 @@ void weaveContainedResources() {
String ref = nextRef.getReferenceElement().getValue();
if (isNotBlank(ref)) {
if (ref.startsWith("#") && ref.length() > 1) {
IBaseResource target = myContainedResources.get(ref);
String hashLessId = ref.substring(1);
IBaseResource target = myContainedResources.get(hashLessId);
if (target != null) {
ourLog.debug("Resource contains local ref {}", ref);
ourLog.debug("Resource contains local ref {}", hashLessId);
nextRef.setResource(target);
} else {
myErrorHandler.unknownReference(null, ref);
myErrorHandler.unknownReference(null, hashLessId);
}
}
}
Expand Down
42 changes: 27 additions & 15 deletions hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
import ca.uhn.fhir.model.base.composite.BaseContainedDt;
import ca.uhn.fhir.model.base.composite.BaseResourceReferenceDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.parser.DataFormatException;
import com.google.common.collect.Lists;
Expand Down Expand Up @@ -1428,6 +1429,18 @@ public boolean acceptUndeclaredExtension(
});
}

private boolean isInternalFragment(IBaseReference theReference) {
assert theReference.getResource() != null;
if (theReference.getResource().getIdElement().isEmpty()) {
return true;
}
if (theReference.getResource().getIdElement().isAbsolute()
|| theReference.getResource().getIdElement().getValueAsString().startsWith("urn:")) {
return false;
}
return true;
}

private void containResourcesForEncoding(
ContainedResources theContained, IBaseResource theResource, boolean theModifyResource) {
List<IBaseReference> allReferences = getAllPopulatedChildElementsOfType(theResource, IBaseReference.class);
Expand Down Expand Up @@ -1456,17 +1469,17 @@ private void containResourcesForEncoding(
for (IBaseReference next : allReferences) {
IBaseResource resource = next.getResource();
if (resource != null) {
if (resource.getIdElement().isEmpty() || resource.getIdElement().isLocal()) {
if (resource.getIdElement().isEmpty() || isInternalFragment(next)) {

IIdType id = theContained.addContained(resource);
if (id == null) {
continue;
}
if (theModifyResource) {
getContainedResourceList(theResource).add(resource);
next.setReference(id.getValue());
next.setReference("#" + id.getValue());
}
if (resource.getIdElement().isLocal() && theContained.hasExistingIdToContainedResource()) {
if (isInternalFragment(next) && theContained.hasExistingIdToContainedResource()) {
theContained
.getExistingIdToContainedResource()
.remove(resource.getIdElement().getValue());
Expand Down Expand Up @@ -1508,13 +1521,6 @@ public ContainedResources containResources(IBaseResource theResource, OptionsEnu

List<? extends IBaseResource> containedResources = getContainedResourceList(theResource);
for (IBaseResource next : containedResources) {
String nextId = next.getIdElement().getValue();
if (StringUtils.isNotBlank(nextId)) {
if (!nextId.startsWith("#")) {
nextId = '#' + nextId;
}
next.getIdElement().setValue(nextId);
}
contained.addContained(next);
}

Expand Down Expand Up @@ -1810,14 +1816,20 @@ public IIdType addContained(IBaseResource theResource) {
return existing;
}

IIdType newId = theResource.getIdElement();
final IIdType newId = new IdDt(theResource.getIdElement());
if (isBlank(newId.getValue())) {
newId.setValue("#" + UUID.randomUUID());
UUID randomUUID = UUID.randomUUID();
theResource.getIdElement().setValue(randomUUID.toString());
newId.setValue("#" + randomUUID);
// TODO put newId in resourceToIdMap ?
getResourceToIdMap().put(theResource, newId);
} else {
// TODO put new IdDt with # in resourceToIdMap ?
getResourceToIdMap().put(theResource, new IdDt("#" + newId.getIdPart()));
}

getResourceToIdMap().put(theResource, newId);
// getResourceToIdMap().put(theResource, newId);
getOrCreateResourceList().add(theResource);
return newId;
return theResource.getIdElement();
}

public void addContained(IIdType theId, IBaseResource theResource) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -198,7 +198,7 @@ select foo()
IHfqlExecutionResult result = myHfqlExecutor.executeInitialSearch(statement, null, mySrd);
IHfqlExecutionResult.Row row = result.getNextRow();
assertEquals(IHfqlExecutionResult.ROW_OFFSET_ERROR, row.getRowOffset());
assertEquals("Failed to evaluate FHIRPath expression \"foo()\". Error: HAPI-2404: Error in ?? at 1, 1: The name foo is not a valid function name", row.getRowValues().get(0));
assertEquals("Failed to evaluate FHIRPath expression \"foo()\". Error: HAPI-2404: Error @1, 1: The name foo is not a valid function name", row.getRowValues().get(0));
assertFalse(result.hasNext());
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@
import ca.uhn.fhir.model.api.IQueryParameterType;
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
import ca.uhn.fhir.model.primitive.BoundCodeDt;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
import ca.uhn.fhir.rest.param.DateParam;
Expand Down Expand Up @@ -2237,7 +2238,7 @@ private void extractResourceLinkFromReference(
IBaseReference valueRef) {
IIdType nextId = valueRef.getReferenceElement();
if (nextId.isEmpty() && valueRef.getResource() != null) {
nextId = valueRef.getResource().getIdElement();
nextId = new IdDt("#" + valueRef.getResource().getIdElement());
}

if (nextId == null || nextId.isEmpty()) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,5 +208,10 @@ public boolean conformsToProfile(FHIRPathEngine engine, Object appContext, Base
public ValueSet resolveValueSet(FHIRPathEngine engine, Object appContext, String url) {
return null;
}

@Override
public boolean paramIsType(String name, int index) {
return false;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -462,7 +462,8 @@ private void extractSearchIndexParametersForTargetResources(

private IBaseResource findContainedResource(Collection<IBaseResource> resources, IBaseReference reference) {
for (IBaseResource resource : resources) {
if (resource.getIdElement().equals(reference.getReferenceElement())) return resource;
if (("#" + resource.getIdElement())
.equals(reference.getReferenceElement().toString())) return resource;
}
return null;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public void validation_Jpa_Bundle_MeasureReferencesLibraryAndLibrary() {

final ValidationResult validationResult = validator.validateWithResult(bundleWithBadLibrary);

assertEquals(12, validationResult.getMessages().stream().filter(errorMessagePredicate()).count());
assertEquals(10, validationResult.getMessages().stream().filter(errorMessagePredicate()).count());
}

@Test
Expand All @@ -94,7 +94,7 @@ public void validation_Jpa_Bundle_MeasureOnly() {

final ValidationResult validationResult = validator.validateWithResult(bundleWithMeasureOnly );

assertEquals(10, validationResult.getMessages().stream().filter(errorMessagePredicate()).count());
assertEquals(8, validationResult.getMessages().stream().filter(errorMessagePredicate()).count());
}

@Test
Expand All @@ -108,7 +108,7 @@ public void validation_Jpa_Bundle_MeasureOnly_NoLibraryReference() {

final ValidationResult validationResult = validator.validateWithResult(bundleWithMeasureOnlyNoLibraryReference);

assertEquals(9, validationResult.getMessages().stream().filter(errorMessagePredicate()).count());
assertEquals(7, validationResult.getMessages().stream().filter(errorMessagePredicate()).count());
}

@Test
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ public void testValidateInvalidExpression() {
myDao.validateResourceForStorage(nextSearchParameter, null);
fail();
} catch (UnprocessableEntityException e) {
assertEquals(Msg.code(1121) + "Invalid FHIRPath format for SearchParameter.expression \"Patient.ex[[[\": Error in ?? at 1, 1: Found [ expecting a token name", e.getMessage());
assertEquals(Msg.code(1121) + "Invalid FHIRPath format for SearchParameter.expression \"Patient.ex[[[\": Error @1, 1: Found [ expecting a token name", e.getMessage());
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -715,8 +715,8 @@ public void testShouldResolveAThreeLinkChainWithAContainedResourceAtTheEndOfTheC
obs.getCode().addCoding().setCode("obs2").setSystem("Some System").setDisplay("Body weight as measured by me");
obs.setStatus(Observation.ObservationStatus.FINAL);
obs.setValue(new Quantity(81));
obs.setSubject(new Reference(p.getId()));
obs.setEncounter(new Reference(encounter.getId()));
obs.setSubject(new Reference("#" +p.getId()));
obs.setEncounter(new Reference("#" + encounter.getId()));
oid1 = myObservationDao.create(obs, mySrd).getId().toUnqualifiedVersionless();

// Create a dummy record so that an unconstrained query doesn't pass the test due to returning the only record
Expand Down Expand Up @@ -1025,7 +1025,7 @@ public void testShouldResolveAThreeLinkChainWithQualifiersWithAContainedResource
Patient p = new Patient();
p.setId("pat");
p.addName().setFamily("Smith").addGiven("John");
p.getManagingOrganization().setReference(org.getId());
p.getManagingOrganization().setReference("#" + org.getId());

Observation obs = new Observation();
obs.getContained().add(p);
Expand All @@ -1036,7 +1036,7 @@ public void testShouldResolveAThreeLinkChainWithQualifiersWithAContainedResource

Device d = new Device();
d.setId("dev");
d.getOwner().setReference(org.getId());
d.getOwner().setReference("#" + org.getId());

Observation obs2 = new Observation();
obs2.getContained().add(d);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -168,7 +168,7 @@ public void testCreateLinkCreatesAppropriatePaths_ContainedResource() {
myPatientDao.update(p, mySrd);

Observation containedObs = new Observation();
containedObs.setId("#cont");
containedObs.setId("cont");
containedObs.setSubject(new Reference("Patient/A"));

Encounter enc = new Encounter();
Expand Down Expand Up @@ -285,7 +285,7 @@ public void testCreateLinkCreatesAppropriatePaths_ContainedResourceRecursive_ToO
p.setManagingOrganization(new Reference("Organization/ABC"));

Observation containedObs = new Observation();
containedObs.setId("#cont");
containedObs.setId("cont");
containedObs.setSubject(new Reference("#pat"));

Encounter enc = new Encounter();
Expand Down Expand Up @@ -754,7 +754,7 @@ public void testTagsInContainedResourcesPreserved() {
assertEquals(organizationUuid, organizationUuidParsed);

Organization org = (Organization) p.getManagingOrganization().getResource();
assertEquals("#" + organizationUuid, org.getId());
assertEquals(organizationUuid, org.getId());
assertThat(org.getMeta().getTag()).hasSize(1);

}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -852,7 +852,7 @@ public void testValidateProfileTargetType_PolicyCheckExistsAndType() throws IOEx
obs.setSubject(new Reference("Group/ABC"));
oo = validateAndReturnOutcome(obs);
ourLog.debug(myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(oo));
assertThat(oo.getIssueFirstRep().getDiagnostics()).as(encode(oo)).isEqualTo("Unable to find a match for profile Group/ABC (by type) among choices: ; [CanonicalType[http://hl7.org/fhir/StructureDefinition/Patient]]");
assertThat(oo.getIssueFirstRep().getDiagnostics()).as(encode(oo)).isEqualTo("Unable to find a match for profile Group/ABC (by type) among choices: ; [http://hl7.org/fhir/StructureDefinition/Patient]");

// Target of right type
obs.setSubject(new Reference("Patient/DEF"));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -195,6 +195,7 @@
import org.hl7.fhir.r5.utils.validation.constants.ContainedReferenceValidationPolicy;
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.validation.instance.advisor.BasePolicyAdvisorForFullValidation;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Order;
Expand Down Expand Up @@ -1073,6 +1074,16 @@ public boolean isSuppressMessageId(String path, String messageId) {
public ReferenceValidationPolicy getReferencePolicy() {
return ReferenceValidationPolicy.IGNORE;
}

@Override
public IValidationPolicyAdvisor getPolicyAdvisor() {
return new BasePolicyAdvisorForFullValidation(getReferencePolicy());
}

@Override
public IValidationPolicyAdvisor setPolicyAdvisor(IValidationPolicyAdvisor policyAdvisor) {
return null;
}
}


Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public void testMatcherBadFhirPath() throws IOException {
try {
setMdmRuleJson("bad-rules-bad-fhirpath.json");
fail(); } catch (ConfigurationException e) {
assertThat(e.getMessage()).startsWith(Msg.code(1518) + "MatchField [given-name] resourceType [Patient] has failed FHIRPath evaluation. Error in ?? at 1, 1: The name blurst is not a valid function name");
assertThat(e.getMessage()).startsWith(Msg.code(1518) + "MatchField [given-name] resourceType [Patient] has failed FHIRPath evaluation. Error @1, 1: The name blurst is not a valid function name");
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
import org.hl7.fhir.r5.utils.validation.constants.ContainedReferenceValidationPolicy;
import org.hl7.fhir.r5.utils.validation.constants.ReferenceValidationPolicy;
import org.hl7.fhir.utilities.validation.ValidationMessage;
import org.hl7.fhir.validation.instance.advisor.BasePolicyAdvisorForFullValidation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -127,4 +128,14 @@ public boolean isSuppressMessageId(String path, String messageId) {
public ReferenceValidationPolicy getReferencePolicy() {
return ReferenceValidationPolicy.IGNORE;
}

@Override
public IValidationPolicyAdvisor getPolicyAdvisor() {
return new BasePolicyAdvisorForFullValidation(getReferencePolicy());
}

@Override
public IValidationPolicyAdvisor setPolicyAdvisor(IValidationPolicyAdvisor policyAdvisor) {
return null;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r5.elementmodel.Element;
import org.hl7.fhir.r5.utils.XVerExtensionManager;
import org.hl7.fhir.r5.utils.validation.ValidatorSession;
import org.hl7.fhir.validation.instance.InstanceValidator;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
Expand Down Expand Up @@ -56,7 +57,8 @@ public void checkFetchByUrl() {
InstanceValidator v = new InstanceValidator(
wrappedWorkerContext,
new FhirInstanceValidator.NullEvaluationContext(),
new XVerExtensionManager(null));
new XVerExtensionManager(null),
new ValidatorSession());
RequestDetails r = new SystemRequestDetails();
// test
Element returnedResource = fetcher.fetch(v, r,"http://www.test-url-for-questionnaire.com/Questionnaire/test-id|1.0.0");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -403,7 +403,7 @@ public void testEncodeAndParseContained() {

assertNotNull(patient.getManagingOrganization().getResource());
org = (Organization) patient.getManagingOrganization().getResource();
assertEquals("#" + organizationUuid, org.getIdElement().getValue());
assertEquals( organizationUuid, org.getIdElement().getValue());
assertEquals("Contained Test Organization", org.getName());

// And re-encode a second time
Expand Down Expand Up @@ -817,7 +817,7 @@ public void testEncodeBinaryWithNoContentType() {
public void testEncodeBundleWithContained() {
DiagnosticReport rpt = new DiagnosticReport();
rpt.addResult().setResource(new Observation().setCode(new CodeableConcept().setText("Sharp1")).setId("#1"));
rpt.addResult().setResource(new Observation().setCode(new CodeableConcept().setText("Uuid1")).setId("urn:uuid:UUID1"));
rpt.addResult().setResource(new Observation().setCode(new CodeableConcept().setText("Uuid1")).setId("https//example.org/UUID1"));

Bundle b = new Bundle();
b.addEntry().setResource(rpt);
Expand Down
Loading
Loading