Issue 3530 terserutil contained failure (#3532)
* License headers * begin with failing test * fixed * changelog * add jira tag * review feedback
This commit is contained in:
parent
f361aa5998
commit
9d2a317446
|
@ -180,7 +180,7 @@ public final class TerserUtil {
|
|||
continue;
|
||||
}
|
||||
|
||||
IBase newFieldValue = newElement(childDefinition, theFromFieldValue, null);
|
||||
IBase newFieldValue = newElement(terser, childDefinition, theFromFieldValue, null);
|
||||
terser.cloneInto(theFromFieldValue, newFieldValue, true);
|
||||
|
||||
try {
|
||||
|
@ -316,6 +316,7 @@ public final class TerserUtil {
|
|||
|
||||
/**
|
||||
* Clears the specified field on the resource provided
|
||||
*
|
||||
* @param theFhirContext Context holding resource definition
|
||||
* @param theResource
|
||||
* @param theFieldName
|
||||
|
@ -529,19 +530,28 @@ public final class TerserUtil {
|
|||
* Creates a new element taking into consideration elements with choice that are not directly retrievable by element
|
||||
* name
|
||||
*
|
||||
*
|
||||
* @param theFhirTerser
|
||||
* @param theChildDefinition Child to create a new instance for
|
||||
* @param theFromFieldValue The base parent field
|
||||
* @param theConstructorParam Optional constructor param
|
||||
* @return Returns the new element with the given value if configured
|
||||
*/
|
||||
private static IBase newElement(BaseRuntimeChildDefinition theChildDefinition, IBase theFromFieldValue, Object theConstructorParam) {
|
||||
private static IBase newElement(FhirTerser theFhirTerser, BaseRuntimeChildDefinition theChildDefinition, IBase theFromFieldValue, Object theConstructorParam) {
|
||||
BaseRuntimeElementDefinition runtimeElementDefinition;
|
||||
if (theChildDefinition instanceof RuntimeChildChoiceDefinition) {
|
||||
runtimeElementDefinition = theChildDefinition.getChildElementDefinitionByDatatype(theFromFieldValue.getClass());
|
||||
} else {
|
||||
runtimeElementDefinition = theChildDefinition.getChildByName(theChildDefinition.getElementName());
|
||||
}
|
||||
return (theConstructorParam == null) ? runtimeElementDefinition.newInstance() : runtimeElementDefinition.newInstance(theConstructorParam);
|
||||
if ("contained".equals(runtimeElementDefinition.getName())) {
|
||||
IBaseResource sourceResource = (IBaseResource) theFromFieldValue;
|
||||
return theFhirTerser.clone(sourceResource);
|
||||
} else if (theConstructorParam == null) {
|
||||
return runtimeElementDefinition.newInstance();
|
||||
} else {
|
||||
return runtimeElementDefinition.newInstance(theConstructorParam);
|
||||
}
|
||||
}
|
||||
|
||||
private static void mergeFields(FhirTerser theTerser, IBaseResource theTo, BaseRuntimeChildDefinition childDefinition, List<IBase> theFromFieldValues, List<IBase> theToFieldValues) {
|
||||
|
@ -550,7 +560,7 @@ public final class TerserUtil {
|
|||
continue;
|
||||
}
|
||||
|
||||
IBase newFieldValue = newElement(childDefinition, theFromFieldValue, null);
|
||||
IBase newFieldValue = newElement(theTerser, childDefinition, theFromFieldValue, null);
|
||||
if (theFromFieldValue instanceof IPrimitiveType) {
|
||||
try {
|
||||
Method copyMethod = getMethod(theFromFieldValue, "copy");
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
type: fix
|
||||
issue: 3530
|
||||
jira: SMILE-4109
|
||||
title: "TerserUtil.mergeAllFields() threw an exception when cloning contained resources. This has been corrected."
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.jpa.mdm.util;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server - Master Data Management
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.mdm.util.MessageHelper;
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.batch2.impl;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server - Batch2 Task Processor
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.batch2.api.IJobDataSink;
|
||||
import ca.uhn.fhir.model.api.IModelJson;
|
||||
import org.slf4j.Logger;
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.batch2.impl;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server - Batch2 Task Processor
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.batch2.model.JobWorkNotification;
|
||||
import ca.uhn.fhir.batch2.model.JobWorkNotificationJsonMessage;
|
||||
import ca.uhn.fhir.jpa.subscription.channel.api.IChannelProducer;
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.batch2.impl;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server - Batch2 Task Processor
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.batch2.impl;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server - Batch2 Task Processor
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.batch2.api.JobExecutionFailedException;
|
||||
import ca.uhn.fhir.batch2.api.VoidModel;
|
||||
import ca.uhn.fhir.batch2.model.WorkChunkData;
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.batch2.impl;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server - Batch2 Task Processor
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.batch2.api.IJobPersistence;
|
||||
import ca.uhn.fhir.batch2.model.JobDefinitionStep;
|
||||
import ca.uhn.fhir.batch2.model.JobWorkNotification;
|
||||
|
|
|
@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.binstore;
|
|||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* HAPI FHIR Storage api
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
|
@ -20,10 +20,10 @@ package ca.uhn.fhir.jpa.binstore;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.context.ConfigurationException;
|
||||
import ca.uhn.fhir.jpa.binary.svc.BaseBinaryStorageSvcImpl;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.binary.api.StoredDetails;
|
||||
import ca.uhn.fhir.jpa.binary.svc.BaseBinaryStorageSvcImpl;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import com.fasterxml.jackson.annotation.JsonInclude;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
|
@ -41,7 +41,16 @@ import org.slf4j.LoggerFactory;
|
|||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import javax.annotation.PostConstruct;
|
||||
import java.io.*;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Reader;
|
||||
import java.util.Date;
|
||||
|
||||
public class FilesystemBinaryStorageSvcImpl extends BaseBinaryStorageSvcImpl {
|
||||
|
|
|
@ -2,7 +2,7 @@ package ca.uhn.fhir.jpa.binstore;
|
|||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* HAPI FHIR Storage api
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
|
@ -20,9 +20,9 @@ package ca.uhn.fhir.jpa.binstore;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.binary.svc.BaseBinaryStorageSvcImpl;
|
||||
import ca.uhn.fhir.jpa.binary.api.IBinaryStorageSvc;
|
||||
import ca.uhn.fhir.jpa.binary.api.StoredDetails;
|
||||
import ca.uhn.fhir.jpa.binary.svc.BaseBinaryStorageSvcImpl;
|
||||
import com.google.common.hash.HashingInputStream;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.commons.io.input.CountingInputStream;
|
||||
|
|
|
@ -9,6 +9,7 @@ import org.hl7.fhir.r4.model.Enumerations;
|
|||
import org.hl7.fhir.r4.model.Extension;
|
||||
import org.hl7.fhir.r4.model.HumanName;
|
||||
import org.hl7.fhir.r4.model.Identifier;
|
||||
import org.hl7.fhir.r4.model.Organization;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.hl7.fhir.r4.model.PrimitiveType;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -17,78 +18,99 @@ import java.util.Date;
|
|||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.hasSize;
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
class TerserUtilTest {
|
||||
|
||||
private FhirContext ourFhirContext = FhirContext.forR4();
|
||||
private static final String SAMPLE_PERSON = "{\n" +
|
||||
" \"resourceType\": \"Patient\",\n" +
|
||||
" \"extension\": [\n" +
|
||||
" {\n" +
|
||||
" \"url\": \"http://hl7.org/fhir/us/core/StructureDefinition/us-core-race\",\n" +
|
||||
" \"valueCoding\": {\n" +
|
||||
" \"system\": \"MyInternalRace\",\n" +
|
||||
" \"code\": \"X\",\n" +
|
||||
" \"display\": \"Eks\"\n" +
|
||||
" }\n" +
|
||||
" },\n" +
|
||||
" {\n" +
|
||||
" \"url\": \"http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity'\",\n" +
|
||||
" \"valueCoding\": {\n" +
|
||||
" \"system\": \"MyInternalEthnicity\",\n" +
|
||||
" \"display\": \"NNN\"\n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"identifier\": [\n" +
|
||||
" {\n" +
|
||||
" \"system\": \"http://example.org/member_id\",\n" +
|
||||
" \"value\": \"123123\"\n" +
|
||||
" },\n" +
|
||||
" {\n" +
|
||||
" \"system\": \"http://example.org/medicaid_id\",\n" +
|
||||
" \"value\": \"12312323123Z\"\n" +
|
||||
" },\n" +
|
||||
" {\n" +
|
||||
" \"system\": \"http://example.org/CDNS_id\",\n" +
|
||||
" \"value\": \"123123123E\"\n" +
|
||||
" },\n" +
|
||||
" {\n" +
|
||||
" \"system\": \"http://example.org/SSN\"\n" +
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"active\": true,\n" +
|
||||
" \"name\": [\n" +
|
||||
" {\n" +
|
||||
" \"family\": \"TestFamily\",\n" +
|
||||
" \"given\": [\n" +
|
||||
" \"Given\"\n" +
|
||||
" ]\n" +
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"telecom\": [\n" +
|
||||
" {\n" +
|
||||
" \"system\": \"email\",\n" +
|
||||
" \"value\": \"email@email.io\"\n" +
|
||||
" },\n" +
|
||||
" {\n" +
|
||||
" \"system\": \"phone\",\n" +
|
||||
" \"value\": \"123123231\"\n" +
|
||||
" },\n" +
|
||||
" {\n" +
|
||||
" \"system\": \"phone\",\n" +
|
||||
" \"value\": \"1231232312\"\n" +
|
||||
" },\n" +
|
||||
" {\n" +
|
||||
" \"system\": \"phone\",\n" +
|
||||
" \"value\": \"1231232314\"\n" +
|
||||
" }\n" +
|
||||
" ],\n" +
|
||||
" \"gender\": \"male\",\n" +
|
||||
" \"birthDate\": \"1900-01-01\",\n" +
|
||||
" \"deceasedBoolean\": true\n" +
|
||||
" }";
|
||||
private static final String SAMPLE_PERSON =
|
||||
"""
|
||||
{
|
||||
"resourceType": "Patient",
|
||||
"extension": [
|
||||
{
|
||||
"url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-race",
|
||||
"valueCoding": {
|
||||
"system": "MyInternalRace",
|
||||
"code": "X",
|
||||
"display": "Eks"
|
||||
}
|
||||
},
|
||||
{
|
||||
"url": "http://hl7.org/fhir/us/core/StructureDefinition/us-core-ethnicity'",
|
||||
"valueCoding": {
|
||||
"system": "MyInternalEthnicity",
|
||||
"display": "NNN"
|
||||
}
|
||||
}
|
||||
],
|
||||
"identifier": [
|
||||
{
|
||||
"system": "http://example.org/member_id",
|
||||
"value": "123123"
|
||||
},
|
||||
{
|
||||
"system": "http://example.org/medicaid_id",
|
||||
"value": "12312323123Z"
|
||||
},
|
||||
{
|
||||
"system": "http://example.org/CDNS_id",
|
||||
"value": "123123123E"
|
||||
},
|
||||
{
|
||||
"system": "http://example.org/SSN"
|
||||
}
|
||||
],
|
||||
"active": true,
|
||||
"name": [
|
||||
{
|
||||
"family": "TestFamily",
|
||||
"given": [
|
||||
"Given"
|
||||
]
|
||||
}
|
||||
],
|
||||
"telecom": [
|
||||
{
|
||||
"system": "email",
|
||||
"value": "email@email.io"
|
||||
},
|
||||
{
|
||||
"system": "phone",
|
||||
"value": "123123231"
|
||||
},
|
||||
{
|
||||
"system": "phone",
|
||||
"value": "1231232312"
|
||||
},
|
||||
{
|
||||
"system": "phone",
|
||||
"value": "1231232314"
|
||||
}
|
||||
],
|
||||
"gender": "male",
|
||||
"birthDate": "1900-01-01",
|
||||
"deceasedBoolean": true,
|
||||
"contained": [
|
||||
{
|
||||
"id": "1",
|
||||
"identifier": [
|
||||
{
|
||||
"system": "urn:hssc:srhs:contact:organizationId",
|
||||
"value": "1000"
|
||||
}
|
||||
],
|
||||
"name": "BUILDERS FIRST SOURCE",
|
||||
"resourceType": "Organization"
|
||||
}
|
||||
]
|
||||
}
|
||||
""";
|
||||
|
||||
@Test
|
||||
void testCloneEidIntoResource() {
|
||||
|
@ -130,6 +152,20 @@ class TerserUtilTest {
|
|||
assertEquals(2, p2.getExtension().size());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCloneContainedResource() {
|
||||
Patient p1 = ourFhirContext.newJsonParser().parseResource(Patient.class, SAMPLE_PERSON);
|
||||
|
||||
Patient p2 = new Patient();
|
||||
TerserUtil.mergeAllFields(ourFhirContext, p1, p2);
|
||||
|
||||
Organization org1 = (Organization) p1.getContained().get(0);
|
||||
Organization org2 = (Organization) p2.getContained().get(0);
|
||||
assertNotEquals(org1, org2);
|
||||
assertEquals("BUILDERS FIRST SOURCE", org1.getName());
|
||||
assertEquals("BUILDERS FIRST SOURCE", org2.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
void testCloneEidIntoResourceViaHelper() {
|
||||
TerserUtilHelper p1Helper = TerserUtilHelper.newHelper(ourFhirContext, "Patient");
|
||||
|
|
|
@ -1,5 +1,25 @@
|
|||
package ca.uhn.fhir.test.utilities;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR Test Utilities
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2022 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ch.qos.logback.classic.Level;
|
||||
import ch.qos.logback.classic.Logger;
|
||||
import org.junit.jupiter.api.extension.AfterEachCallback;
|
||||
|
|
Loading…
Reference in New Issue