Skip to content

Commit

Permalink
5401 add terserutil clear by fhirpath (hapifhir#5402)
Browse files Browse the repository at this point in the history
* begin with failing test

* test passes

* test passes

* changelog

* moar testor
  • Loading branch information
fil512 authored Oct 26, 2023
1 parent 84e3bec commit a7a4469
Show file tree
Hide file tree
Showing 5 changed files with 210 additions and 122 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
package ca.uhn.fhir.context;

import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.model.api.annotation.Child;
import org.hl7.fhir.instance.model.api.IBase;
import org.hl7.fhir.instance.model.api.IBaseReference;

Expand Down Expand Up @@ -78,6 +79,10 @@ public void setReplacedParentDefinition(BaseRuntimeChildDefinition myReplacedPar
this.myReplacedParentDefinition = myReplacedParentDefinition;
}

public boolean isMultipleCardinality() {
return this.getMax() > 1 || this.getMax() == Child.MAX_UNLIMITED;
}

public interface IAccessor {
List<IBase> getValues(IBase theTarget);

Expand Down
21 changes: 6 additions & 15 deletions hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.api.Tag;
import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.api.annotation.Child;
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.base.composite.BaseContainedDt;
import ca.uhn.fhir.model.primitive.IdDt;
Expand Down Expand Up @@ -659,9 +658,8 @@ private void encodeCompositeElementChildrenToStreamWriter(
theEventWriter.endArray();
}
BaseRuntimeChildDefinition replacedParentDefinition = nextChild.getReplacedParentDefinition();
if (isMultipleCardinality(nextChild.getMax())
|| (replacedParentDefinition != null
&& isMultipleCardinality(replacedParentDefinition.getMax()))) {
if (nextChild.isMultipleCardinality()
|| (replacedParentDefinition != null && replacedParentDefinition.isMultipleCardinality())) {
beginArray(theEventWriter, nextChildSpecificName);
inArray = true;
encodeChildElementToStreamWriter(
Expand Down Expand Up @@ -728,14 +726,14 @@ && isMultipleCardinality(replacedParentDefinition.getMax()))) {
List<HeldExtension> heldModExts = Collections.emptyList();
if (extensions.size() > i
&& extensions.get(i) != null
&& extensions.get(i).isEmpty() == false) {
&& !extensions.get(i).isEmpty()) {
haveContent = true;
heldExts = extensions.get(i);
}

if (modifierExtensions.size() > i
&& modifierExtensions.get(i) != null
&& modifierExtensions.get(i).isEmpty() == false) {
&& !modifierExtensions.get(i).isEmpty()) {
haveContent = true;
heldModExts = modifierExtensions.get(i);
}
Expand All @@ -746,7 +744,7 @@ && isMultipleCardinality(replacedParentDefinition.getMax()))) {
} else {
nextComments = null;
}
if (nextComments != null && nextComments.isEmpty() == false) {
if (nextComments != null && !nextComments.isEmpty()) {
haveContent = true;
}

Expand Down Expand Up @@ -804,10 +802,6 @@ private boolean isSupportsFhirComment() {
return myIsSupportsFhirComment;
}

private boolean isMultipleCardinality(int maxCardinality) {
return maxCardinality > 1 || maxCardinality == Child.MAX_UNLIMITED;
}

private void encodeCompositeElementToStreamWriter(
RuntimeResourceDefinition theResDef,
IBaseResource theResource,
Expand Down Expand Up @@ -917,10 +911,7 @@ private void encodeResourceToJsonStreamWriter(
// Undeclared extensions
extractUndeclaredExtensions(
theResourceId, extensions, modifierExtensions, null, null, theEncodeContext, theContainedResource);
boolean haveExtension = false;
if (!extensions.isEmpty()) {
haveExtension = true;
}
boolean haveExtension = !extensions.isEmpty();

if (theResourceId.hasFormatComment() || haveExtension) {
beginObject(theEventWriter, "_id");
Expand Down
34 changes: 33 additions & 1 deletion hapi-fhir-base/src/main/java/ca/uhn/fhir/util/TerserUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -351,6 +351,29 @@ public static void clearField(FhirContext theFhirContext, IBaseResource theResou
clear(childDefinition.getAccessor().getValues(theResource));
}

/**
* Clears the specified field on the resource provided by the FHIRPath. If more than one value matches
* the FHIRPath, all values will be cleared.
*
* @param theFhirContext
* @param theResource
* @param theFhirPath
*/
public static void clearFieldByFhirPath(FhirContext theFhirContext, IBaseResource theResource, String theFhirPath) {

if (theFhirPath.contains(".")) {
String parentPath = theFhirPath.substring(0, theFhirPath.lastIndexOf("."));
String fieldName = theFhirPath.substring(theFhirPath.lastIndexOf(".") + 1);
FhirTerser terser = theFhirContext.newTerser();
List<IBase> parents = terser.getValues(theResource, parentPath);
for (IBase parent : parents) {
clearField(theFhirContext, fieldName, parent);
}
} else {
clearField(theFhirContext, theResource, theFhirPath);
}
}

/**
* Clears the specified field on the element provided
*
Expand All @@ -362,7 +385,16 @@ public static void clearField(FhirContext theFhirContext, String theFieldName, I
BaseRuntimeElementDefinition definition = theFhirContext.getElementDefinition(theBase.getClass());
BaseRuntimeChildDefinition childDefinition = definition.getChildByName(theFieldName);
Validate.notNull(childDefinition);
clear(childDefinition.getAccessor().getValues(theBase));
BaseRuntimeChildDefinition.IAccessor accessor = childDefinition.getAccessor();
clear(accessor.getValues(theBase));
List<IBase> newValue = accessor.getValues(theBase);

if (newValue != null && !newValue.isEmpty()) {
// Our clear failed, probably because it was an immutable SingletonList returned by a FieldPlainAccessor
// that cannot be cleared.
// Let's just null it out instead.
childDefinition.getMutator().setValue(theBase, null);
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
type: add
issue: 5401
title: "Previously, it was only possible to clear a top-level field on a resource using TerserUtil. A new method has been added
to TerserUtil to support clearing a value by FhirPath."
Loading

0 comments on commit a7a4469

Please sign in to comment.