diff --git a/.editorconfig b/.editorconfig
index 479bb985c23..31b0bd4a6a7 100644
--- a/.editorconfig
+++ b/.editorconfig
@@ -3,35 +3,30 @@ root = true
[*]
end_of_line = lf
insert_final_newline = true
-tab_width = 3
-indent_size = 3
+indent_style = space
+tab_width = 4
+indent_size = 4
charset = utf-8
[*.xml]
-charset = utf-8
indent_style = tab
tab_width = 3
indent_size = 3
[*.json]
-charset = utf-8
indent_style = tab
tab_width = 3
indent_size = 3
[*.vm]
-charset = utf-8
indent_style = tab
tab_width = 3
indent_size = 3
[*.java]
-charset = utf-8
indent_style = tab
-tab_width = 3
-indent_size = 3
-continuation_indent_size=3
+ij_continuation_indent_size = 4
ij_java_align_consecutive_assignments = false
ij_java_align_consecutive_variable_declarations = false
ij_java_align_group_field_declarations = false
diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml
index ce13833a0d2..7874bf40a3b 100644
--- a/.github/workflows/codeql-analysis.yml
+++ b/.github/workflows/codeql-analysis.yml
@@ -13,7 +13,7 @@ jobs:
steps:
- name: Checkout repository
- uses: actions/checkout@v2
+ uses: actions/checkout@v3
with:
# We must fetch at least the immediate parents so that if this is
# a pull request then we can checkout the head.
@@ -32,7 +32,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
- uses: github/codeql-action/init@v1
+ uses: github/codeql-action/init@v2
# Override language selection by uncommenting this and choosing your languages
# with:
# languages: go, javascript, csharp, python, cpp, java
@@ -40,7 +40,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
- uses: github/codeql-action/autobuild@v1
+ uses: github/codeql-action/autobuild@v2
# âšī¸ Command-line programs to run using the OS shell.
# đ https://git.io/JvXDl
@@ -54,4 +54,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
- uses: github/codeql-action/analyze@v1
+ uses: github/codeql-action/analyze@v2
diff --git a/hapi-deployable-pom/pom.xml b/hapi-deployable-pom/pom.xml
index 269981d81db..d0dee2ba288 100644
--- a/hapi-deployable-pom/pom.xml
+++ b/hapi-deployable-pom/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhirhapi-fhir
- 6.9.2-SNAPSHOT
+ 6.9.10-SNAPSHOT../pom.xml
diff --git a/hapi-fhir-android/pom.xml b/hapi-fhir-android/pom.xml
index 380ff208a8f..8fca23316db 100644
--- a/hapi-fhir-android/pom.xml
+++ b/hapi-fhir-android/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhirhapi-deployable-pom
- 6.9.2-SNAPSHOT
+ 6.9.10-SNAPSHOT../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-base/pom.xml b/hapi-fhir-base/pom.xml
index 6b7053b7588..74170e83cf3 100644
--- a/hapi-fhir-base/pom.xml
+++ b/hapi-fhir-base/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhirhapi-deployable-pom
- 6.9.2-SNAPSHOT
+ 6.9.10-SNAPSHOT../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java
index c402268dea6..f62b3fdfc49 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/FhirContext.java
@@ -1001,9 +1001,9 @@ public class FhirContext {
*/
public void registerCustomType(final Class extends IBase> theType) {
Validate.notNull(theType, "theType must not be null");
-
ensureCustomTypeList();
myCustomTypes.add(theType);
+ myResourceNames = null;
}
/**
@@ -1025,6 +1025,7 @@ public class FhirContext {
ensureCustomTypeList();
myCustomTypes.addAll(theTypes);
+ myResourceNames = null;
}
private BaseRuntimeElementDefinition> scanDatatype(final Class extends IElement> theResourceType) {
@@ -1177,7 +1178,14 @@ public class FhirContext {
synchronized (this) {
if (!myInitialized && !myInitializing) {
myInitializing = true;
- scanResourceTypes(toElementList(myResourceTypesToScan));
+ try {
+ scanResourceTypes(toElementList(myResourceTypesToScan));
+ } catch (Exception e) {
+ ourLog.error("Failed to initialize FhirContext", e);
+ throw e;
+ } finally {
+ myInitializing = false;
+ }
}
}
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/IValidationSupport.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/IValidationSupport.java
index 4f3ff3825ab..b08d10cadc5 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/IValidationSupport.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/context/support/IValidationSupport.java
@@ -553,11 +553,29 @@ public interface IValidationSupport {
private String myCodeSystemVersion;
private List myProperties;
private String myDisplay;
+ private String mySourceDetails;
public CodeValidationResult() {
super();
}
+ /**
+ * This field may contain information about what the source of the
+ * validation information was.
+ */
+ public String getSourceDetails() {
+ return mySourceDetails;
+ }
+
+ /**
+ * This field may contain information about what the source of the
+ * validation information was.
+ */
+ public CodeValidationResult setSourceDetails(String theSourceDetails) {
+ mySourceDetails = theSourceDetails;
+ return this;
+ }
+
public String getDisplay() {
return myDisplay;
}
@@ -691,8 +709,9 @@ public interface IValidationSupport {
private boolean myFound;
private String mySearchedForCode;
private String mySearchedForSystem;
- private List myProperties;
+ private List myProperties;
private List myDesignations;
+ private String myErrorMessage;
/**
* Constructor
@@ -708,7 +727,7 @@ public interface IValidationSupport {
return myProperties;
}
- public void setProperties(List theProperties) {
+ public void setProperties(List theProperties) {
myProperties = theProperties;
}
@@ -808,7 +827,7 @@ public interface IValidationSupport {
.collect(Collectors.toSet());
}
- for (IValidationSupport.BaseConceptProperty next : myProperties) {
+ for (BaseConceptProperty next : myProperties) {
if (!properties.isEmpty()) {
if (!properties.contains(next.getPropertyName())) {
@@ -819,11 +838,11 @@ public interface IValidationSupport {
IBase property = ParametersUtil.addParameterToParameters(theContext, retVal, "property");
ParametersUtil.addPartCode(theContext, property, "code", next.getPropertyName());
- if (next instanceof IValidationSupport.StringConceptProperty) {
- IValidationSupport.StringConceptProperty prop = (IValidationSupport.StringConceptProperty) next;
+ if (next instanceof StringConceptProperty) {
+ StringConceptProperty prop = (StringConceptProperty) next;
ParametersUtil.addPartString(theContext, property, "value", prop.getValue());
- } else if (next instanceof IValidationSupport.CodingConceptProperty) {
- IValidationSupport.CodingConceptProperty prop = (IValidationSupport.CodingConceptProperty) next;
+ } else if (next instanceof CodingConceptProperty) {
+ CodingConceptProperty prop = (CodingConceptProperty) next;
ParametersUtil.addPartCoding(
theContext, property, "value", prop.getCodeSystem(), prop.getCode(), prop.getDisplay());
} else {
@@ -846,6 +865,14 @@ public interface IValidationSupport {
return retVal;
}
+ public void setErrorMessage(String theErrorMessage) {
+ myErrorMessage = theErrorMessage;
+ }
+
+ public String getErrorMessage() {
+ return myErrorMessage;
+ }
+
public static LookupCodeResult notFound(String theSearchedForSystem, String theSearchedForCode) {
return new LookupCodeResult()
.setFound(false)
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java
index e481f4cc2bb..994ea9cd1cf 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/interceptor/api/Pointcut.java
@@ -1484,6 +1484,15 @@ public enum Pointcut implements IPointcut {
* to the new contents of the resource. These changes will be reflected in
* permanent storage.
*
+ *
+ * NO-OPS: If the client has submitted an update that does not actually make any changes
+ * (i.e. the resource they include in the PUT body is identical to the content that
+ * was already stored) the server may choose to ignore the update and perform
+ * a "NO-OP". In this case, this pointcut is still invoked, but {@link #STORAGE_PRECOMMIT_RESOURCE_UPDATED}
+ * will not be. Hook methods for this pointcut may make changes to the new contents of the
+ * resource being updated, and in this case the NO-OP will be cancelled and
+ * {@link #STORAGE_PRECOMMIT_RESOURCE_UPDATED} will also be invoked.
+ *
* Hooks may accept the following parameters:
*
*
org.hl7.fhir.instance.model.api.IBaseResource - The previous contents of the resource being updated
@@ -1617,6 +1626,10 @@ public enum Pointcut implements IPointcut {
* changes as storage has already occurred. Changes will not be reflected
* in storage, but may be reflected in the HTTP response.
*
+ *
+ * NO-OP note: See {@link #STORAGE_PRESTORAGE_RESOURCE_UPDATED} for a note on
+ * no-op updates when no changes are detected.
+ *
* Hooks may accept the following parameters:
*
*
org.hl7.fhir.instance.model.api.IBaseResource - The previous contents of the resource
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/base/composite/BaseCodingDt.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/base/composite/BaseCodingDt.java
index a2f335130e9..3b2e929ce6f 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/base/composite/BaseCodingDt.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/model/base/composite/BaseCodingDt.java
@@ -24,6 +24,7 @@ import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.model.api.BaseIdentifiableElement;
import ca.uhn.fhir.model.api.ICompositeDatatype;
import ca.uhn.fhir.model.api.IQueryParameterType;
+import ca.uhn.fhir.model.primitive.BooleanDt;
import ca.uhn.fhir.model.primitive.CodeDt;
import ca.uhn.fhir.model.primitive.StringDt;
import ca.uhn.fhir.model.primitive.UriDt;
@@ -58,6 +59,10 @@ public abstract class BaseCodingDt extends BaseIdentifiableElement implements IC
*/
public abstract UriDt getSystemElement();
+ public abstract StringDt getVersionElement();
+
+ public abstract BooleanDt getUserSelectedElement();
+
/**
* Gets the value(s) for display (Representation defined by the system).
* creating it if it does
@@ -72,13 +77,6 @@ public abstract class BaseCodingDt extends BaseIdentifiableElement implements IC
public abstract BaseCodingDt setDisplay(String theString);
- /*
- todo: handle version
- public abstract StringDt getVersion();
-
- public abstract BaseCodingDt setVersion ( String theString);
- */
-
/**
* {@inheritDoc}
*/
@@ -181,7 +179,7 @@ public abstract class BaseCodingDt extends BaseIdentifiableElement implements IC
* @deprecated get/setMissing is not supported in StringDt. Use {@link TokenParam} instead if you
* need this functionality
*/
- @Deprecated
+ @Deprecated(since = "6.0.0")
@Override
public Boolean getMissing() {
return null;
@@ -193,7 +191,7 @@ public abstract class BaseCodingDt extends BaseIdentifiableElement implements IC
* @deprecated get/setMissing is not supported in StringDt. Use {@link TokenParam} instead if you
* need this functionality
*/
- @Deprecated
+ @Deprecated(since = "6.0.0")
@Override
public IQueryParameterType setMissing(Boolean theMissing) {
throw new UnsupportedOperationException(
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java
index 6f51c24e136..846d5dab271 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java
@@ -1033,7 +1033,8 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
writeOptionalTagWithTextNode(theEventWriter, "system", tag.getScheme());
writeOptionalTagWithTextNode(theEventWriter, "code", tag.getTerm());
writeOptionalTagWithTextNode(theEventWriter, "display", tag.getLabel());
- // wipmb should we be writing the new properties here? There must be another path.
+ writeOptionalTagWithTextNode(theEventWriter, "version", tag.getVersion());
+ write(theEventWriter, "userSelected", tag.getUserSelectedBoolean());
theEventWriter.endObject();
}
theEventWriter.endArray();
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java
index 4ebe4b3ea62..c25a3d11984 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/ParserState.java
@@ -636,7 +636,7 @@ class ParserState {
BaseRuntimeElementDefinition> target = child.getChildByName(theChildName);
if (target == null) {
- // This is a bug with the structures and shouldn't happen..
+ // This is a bug with the structures and shouldn't happen.
throw new DataFormatException(
Msg.code(1809) + "Found unexpected element '" + theChildName + "' in parent element '"
+ myDefinition.getName() + "'. Valid names are: " + child.getValidChildNames());
@@ -1584,16 +1584,20 @@ class ParserState {
private class TagState extends BaseState {
- private static final int LABEL = 2;
private static final int NONE = 0;
+ private static final int TERM = 1;
+ private static final int LABEL = 2;
private static final int SCHEME = 3;
- private static final int TERM = 1;
+ private static final int VERSION = 4;
+ private static final int USER_SELECTED = 5;
private String myLabel;
private String myScheme;
private int mySubState = 0;
private TagList myTagList;
private String myTerm;
+ private String myVersion;
+ private Boolean myUserSelected;
public TagState(TagList theTagList) {
super(null);
@@ -1614,6 +1618,12 @@ class ParserState {
case SCHEME:
myScheme = (value);
break;
+ case VERSION:
+ myVersion = (value);
+ break;
+ case USER_SELECTED:
+ myUserSelected = Boolean.valueOf(value);
+ break;
case NONE:
// This handles JSON encoding, which is a bit weird
enteringNewElement(null, theName);
@@ -1629,7 +1639,9 @@ class ParserState {
mySubState = NONE;
} else {
if (isNotEmpty(myScheme) || isNotBlank(myTerm) || isNotBlank(myLabel)) {
- myTagList.addTag(myScheme, myTerm, myLabel);
+ Tag tag = myTagList.addTag(myScheme, myTerm, myLabel);
+ tag.setUserSelectedBoolean(myUserSelected);
+ tag.setVersion(myVersion);
}
pop();
}
@@ -1646,6 +1658,10 @@ class ParserState {
mySubState = SCHEME;
} else if (Tag.ATTR_LABEL.equals(theLocalPart) || "display".equals(theLocalPart)) {
mySubState = LABEL;
+ } else if ("userSelected".equals(theLocalPart)) {
+ mySubState = USER_SELECTED;
+ } else if ("version".equals(theLocalPart)) {
+ mySubState = VERSION;
} else {
throw new DataFormatException(Msg.code(1818) + "Unexpected element: " + theLocalPart);
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java
index fba60711839..94f330c9416 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java
@@ -187,7 +187,8 @@ public class XmlParser extends BaseParser {
String namespaceURI = elem.getName().getNamespaceURI();
- if ("extension".equals(elem.getName().getLocalPart())) {
+ String localPart = elem.getName().getLocalPart();
+ if ("extension".equals(localPart)) {
Attribute urlAttr = elem.getAttributeByName(new QName("url"));
String url;
if (urlAttr == null || isBlank(urlAttr.getValue())) {
@@ -199,7 +200,7 @@ public class XmlParser extends BaseParser {
url = urlAttr.getValue();
}
parserState.enteringNewElementExtension(elem, url, false, getServerBaseUrl());
- } else if ("modifierExtension".equals(elem.getName().getLocalPart())) {
+ } else if ("modifierExtension".equals(localPart)) {
Attribute urlAttr = elem.getAttributeByName(new QName("url"));
String url;
if (urlAttr == null || isBlank(urlAttr.getValue())) {
@@ -213,8 +214,7 @@ public class XmlParser extends BaseParser {
}
parserState.enteringNewElementExtension(elem, url, true, getServerBaseUrl());
} else {
- String elementName = elem.getName().getLocalPart();
- parserState.enteringNewElement(namespaceURI, elementName);
+ parserState.enteringNewElement(namespaceURI, localPart);
}
if (!heldComments.isEmpty()) {
@@ -768,6 +768,11 @@ public class XmlParser extends BaseParser {
writeOptionalTagWithValue(theEventWriter, "system", tag.getScheme());
writeOptionalTagWithValue(theEventWriter, "code", tag.getTerm());
writeOptionalTagWithValue(theEventWriter, "display", tag.getLabel());
+ writeOptionalTagWithValue(theEventWriter, "version", tag.getVersion());
+ Boolean userSelected = tag.getUserSelectedBoolean();
+ if (userSelected != null) {
+ writeOptionalTagWithValue(theEventWriter, "userSelected", userSelected.toString());
+ }
theEventWriter.writeEndElement();
}
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/json/jackson/JacksonStructure.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/json/jackson/JacksonStructure.java
index 5c3636a6582..27d93057d0c 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/json/jackson/JacksonStructure.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/json/jackson/JacksonStructure.java
@@ -28,6 +28,7 @@ import ca.uhn.fhir.parser.json.BaseJsonLikeWriter;
import ca.uhn.fhir.parser.json.JsonLikeStructure;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.core.StreamReadConstraints;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
@@ -388,6 +389,15 @@ public class JacksonStructure implements JsonLikeStructure {
retVal = retVal.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
retVal = retVal.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE);
retVal = retVal.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
+
+ retVal.getFactory().setStreamReadConstraints(createStreamReadConstraints());
+
return retVal;
}
+
+ private static StreamReadConstraints createStreamReadConstraints() {
+ return StreamReadConstraints.builder()
+ .maxStringLength(Integer.MAX_VALUE)
+ .build();
+ }
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/Constants.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/Constants.java
index 1eacae7780e..780e528759e 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/Constants.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/Constants.java
@@ -182,6 +182,11 @@ public class Constants {
public static final String PARAM_HAS = "_has";
public static final String PARAM_HISTORY = "_history";
public static final String PARAM_INCLUDE = "_include";
+ /**
+ * @since 7.0.0
+ */
+ public static final String PARAM_LANGUAGE = "_language";
+
public static final String PARAM_INCLUDE_QUALIFIER_RECURSE = ":recurse";
public static final String PARAM_INCLUDE_RECURSE = "_include" + PARAM_INCLUDE_QUALIFIER_RECURSE;
public static final String PARAM_INCLUDE_QUALIFIER_ITERATE = ":iterate";
@@ -326,6 +331,9 @@ public class Constants {
*/
public static final int UUID_LENGTH = 36;
+ public static final String BULK_DATA_ACCESS_IG_URL =
+ "http://hl7.org/fhir/uv/bulkdata/CapabilityStatement/bulk-data";
+
/**
* Application configuration key used to enable or disable Hibernate Envers.
*/
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/MethodOutcome.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/MethodOutcome.java
index c9bfa5aa2c9..909a9ad8dc8 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/MethodOutcome.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/api/MethodOutcome.java
@@ -40,7 +40,7 @@ public class MethodOutcome {
private IBaseResource myResource;
private Map> myResponseHeaders;
private Collection myResourceViewCallbacks;
- private int myResponseStatusCode;
+ private Integer myResponseStatusCode;
/**
* Constructor
@@ -258,6 +258,10 @@ public class MethodOutcome {
}
public int getResponseStatusCode() {
- return myResponseStatusCode;
+ return isResponseStatusCodeSet() ? myResponseStatusCode : 0;
+ }
+
+ public boolean isResponseStatusCodeSet() {
+ return myResponseStatusCode != null;
}
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/InternalCodingDt.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/InternalCodingDt.java
index 49be6fd8040..393e5cb8562 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/InternalCodingDt.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/InternalCodingDt.java
@@ -151,13 +151,27 @@ public class InternalCodingDt extends BaseCodingDt implements ICompositeDatatype
* is consistent across versions. However this cannot consistently be assured. and When the meaning is not guaranteed to be consistent, the version SHOULD be exchanged
*
*/
- public StringDt getVersion() {
+ @Override
+ public StringDt getVersionElement() {
if (myVersion == null) {
myVersion = new StringDt();
}
return myVersion;
}
+ @Override
+ public BooleanDt getUserSelectedElement() {
+ return new BooleanDt();
+ }
+
+ /**
+ * Legacy name for {@link #getVersionElement()}
+ */
+ @Deprecated(since = "7.0.0")
+ public StringDt getVersion() {
+ return getVersionElement();
+ }
+
/**
* Sets the value(s) for version (Version of the system - if relevant)
*
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/UriParamQualifierEnum.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/UriParamQualifierEnum.java
index e697f53f2a6..5dcd56221e1 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/UriParamQualifierEnum.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/UriParamQualifierEnum.java
@@ -48,7 +48,16 @@ public enum UriParamQualifierEnum {
* Value :below
*
*/
- BELOW(":below");
+ BELOW(":below"),
+
+ /**
+ * The contains modifier allows clients to indicate that a supplied URI input should be matched
+ * as a case-insensitive and combining-character insensitive match anywhere in the target URI.
+ *
+ * Value :contains
+ *
+ */
+ CONTAINS(":contains");
private static final Map KEY_TO_VALUE;
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/system/HapiSystemProperties.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/system/HapiSystemProperties.java
index 4f3711bb0cf..8423bd031eb 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/system/HapiSystemProperties.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/system/HapiSystemProperties.java
@@ -36,6 +36,8 @@ public final class HapiSystemProperties {
static final String TEST_MODE = "test";
static final String UNIT_TEST_MODE = "unit_test_mode";
static final long DEFAULT_TEST_SYSTEM_PROP_VALIDATION_RESOURCE_CACHES_MS = 10 * DateUtils.MILLIS_PER_SECOND;
+ static final String PREVENT_INVALIDATING_CONDITIONAL_MATCH_CRITERIA =
+ "hapi.storage.prevent_invalidating_conditional_match_criteria";
private HapiSystemProperties() {}
@@ -158,4 +160,9 @@ public final class HapiSystemProperties {
public static boolean isSuppressHapiFhirVersionLogEnabled() {
return Boolean.parseBoolean(System.getProperty(SUPPRESS_HAPI_FHIR_VERSION_LOG));
}
+
+ public static boolean isPreventInvalidatingConditionalMatchCriteria() {
+ return Boolean.parseBoolean(System.getProperty(
+ HapiSystemProperties.PREVENT_INVALIDATING_CONDITIONAL_MATCH_CRITERIA, Boolean.FALSE.toString()));
+ }
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java
index 4e4319076c3..294761ae174 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/FhirTerser.java
@@ -287,9 +287,33 @@ public class FhirTerser {
return retVal;
}
+ /**
+ * Extracts all outbound references from a resource
+ *
+ * @param theResource the resource to be analyzed
+ * @return a list of references to other resources
+ */
public List getAllResourceReferences(final IBaseResource theResource) {
+ return getAllResourceReferencesExcluding(theResource, Lists.newArrayList());
+ }
+
+ /**
+ * Extracts all outbound references from a resource, excluding any that are located on black-listed parts of the
+ * resource
+ *
+ * @param theResource the resource to be analyzed
+ * @param thePathsToExclude a list of dot-delimited paths not to include in the result
+ * @return a list of references to other resources
+ */
+ public List getAllResourceReferencesExcluding(
+ final IBaseResource theResource, List thePathsToExclude) {
final ArrayList retVal = new ArrayList<>();
BaseRuntimeElementCompositeDefinition> def = myContext.getResourceDefinition(theResource);
+ List> tokenizedPathsToExclude = thePathsToExclude.stream()
+ .map(path -> StringUtils.split(path, "."))
+ .map(Lists::newArrayList)
+ .collect(Collectors.toList());
+
visit(newMap(), theResource, theResource, null, null, def, new IModelVisitor() {
@Override
public void acceptElement(
@@ -301,6 +325,10 @@ public class FhirTerser {
if (theElement == null || theElement.isEmpty()) {
return;
}
+
+ if (thePathToElement != null && pathShouldBeExcluded(tokenizedPathsToExclude, thePathToElement)) {
+ return;
+ }
if (IBaseReference.class.isAssignableFrom(theElement.getClass())) {
retVal.add(new ResourceReferenceInfo(
myContext, theOuterResource, thePathToElement, (IBaseReference) theElement));
@@ -310,6 +338,19 @@ public class FhirTerser {
return retVal;
}
+ private boolean pathShouldBeExcluded(List> theTokenizedPathsToExclude, List thePathToElement) {
+ return theTokenizedPathsToExclude.stream().anyMatch(p -> {
+ // Check whether the path to the element starts with the path to be excluded
+ if (p.size() > thePathToElement.size()) {
+ return false;
+ }
+
+ List prefix = thePathToElement.subList(0, p.size());
+
+ return Objects.equals(p, prefix);
+ });
+ }
+
private BaseRuntimeChildDefinition getDefinition(
BaseRuntimeElementCompositeDefinition> theCurrentDef, List theSubList) {
BaseRuntimeChildDefinition nextDef = theCurrentDef.getChildByNameOrThrowDataFormatException(theSubList.get(0));
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/OperationOutcomeUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/OperationOutcomeUtil.java
index ccb2b588169..eadf61d44f2 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/OperationOutcomeUtil.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/OperationOutcomeUtil.java
@@ -23,6 +23,7 @@ import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementCompositeDefinition;
import ca.uhn.fhir.context.BaseRuntimeElementDefinition;
import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.i18n.Msg;
import ca.uhn.fhir.rest.api.Constants;
@@ -250,34 +251,77 @@ public class OperationOutcomeUtil {
public static IBase addIssueWithMessageId(
FhirContext myCtx,
IBaseOperationOutcome theOperationOutcome,
- String severity,
- String message,
- String messageId,
- String location,
+ String theSeverity,
+ String theMessage,
+ String theMessageId,
+ String theLocation,
String theCode) {
- IBase issue = addIssue(myCtx, theOperationOutcome, severity, message, location, theCode);
- BaseRuntimeElementCompositeDefinition> issueElement =
- (BaseRuntimeElementCompositeDefinition>) myCtx.getElementDefinition(issue.getClass());
- BaseRuntimeChildDefinition detailsChildDef = issueElement.getChildByName("details");
+ IBase issue = addIssue(myCtx, theOperationOutcome, theSeverity, theMessage, theLocation, theCode);
+ if (isNotBlank(theMessageId)) {
+ addDetailsToIssue(myCtx, issue, Constants.JAVA_VALIDATOR_DETAILS_SYSTEM, theMessageId);
+ }
- IPrimitiveType> system =
- (IPrimitiveType>) myCtx.getElementDefinition("uri").newInstance();
- system.setValueAsString(Constants.JAVA_VALIDATOR_DETAILS_SYSTEM);
- IPrimitiveType> code =
- (IPrimitiveType>) myCtx.getElementDefinition("code").newInstance();
- code.setValueAsString(messageId);
-
- BaseRuntimeElementCompositeDefinition> codingDef =
- (BaseRuntimeElementCompositeDefinition>) myCtx.getElementDefinition("Coding");
- ICompositeType coding = (ICompositeType) codingDef.newInstance();
- codingDef.getChildByName("system").getMutator().addValue(coding, system);
- codingDef.getChildByName("code").getMutator().addValue(coding, code);
- BaseRuntimeElementCompositeDefinition> ccDef =
- (BaseRuntimeElementCompositeDefinition>) myCtx.getElementDefinition("CodeableConcept");
- ICompositeType codeableConcept = (ICompositeType) ccDef.newInstance();
- ccDef.getChildByName("coding").getMutator().addValue(codeableConcept, coding);
-
- detailsChildDef.getMutator().addValue(issue, codeableConcept);
return issue;
}
+
+ public static void addDetailsToIssue(FhirContext theFhirContext, IBase theIssue, String theSystem, String theCode) {
+ BaseRuntimeElementCompositeDefinition> issueElement =
+ (BaseRuntimeElementCompositeDefinition>) theFhirContext.getElementDefinition(theIssue.getClass());
+ BaseRuntimeChildDefinition detailsChildDef = issueElement.getChildByName("details");
+
+ BaseRuntimeElementCompositeDefinition> codingDef =
+ (BaseRuntimeElementCompositeDefinition>) theFhirContext.getElementDefinition("Coding");
+ ICompositeType coding = (ICompositeType) codingDef.newInstance();
+
+ // System
+ IPrimitiveType> system =
+ (IPrimitiveType>) theFhirContext.getElementDefinition("uri").newInstance();
+ system.setValueAsString(theSystem);
+ codingDef.getChildByName("system").getMutator().addValue(coding, system);
+
+ // Code
+ IPrimitiveType> code =
+ (IPrimitiveType>) theFhirContext.getElementDefinition("code").newInstance();
+ code.setValueAsString(theCode);
+ codingDef.getChildByName("code").getMutator().addValue(coding, code);
+ BaseRuntimeElementCompositeDefinition> ccDef =
+ (BaseRuntimeElementCompositeDefinition>) theFhirContext.getElementDefinition("CodeableConcept");
+
+ ICompositeType codeableConcept = (ICompositeType) ccDef.newInstance();
+ ccDef.getChildByName("coding").getMutator().addValue(codeableConcept, coding);
+ detailsChildDef.getMutator().addValue(theIssue, codeableConcept);
+ }
+
+ public static void addIssueLineExtensionToIssue(FhirContext theCtx, IBase theIssue, String theLine) {
+ if (theCtx.getVersion().getVersion() != FhirVersionEnum.DSTU2) {
+ ExtensionUtil.setExtension(
+ theCtx,
+ theIssue,
+ "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-line",
+ "integer",
+ theLine);
+ }
+ }
+
+ public static void addIssueColExtensionToIssue(FhirContext theCtx, IBase theIssue, String theColumn) {
+ if (theCtx.getVersion().getVersion() != FhirVersionEnum.DSTU2) {
+ ExtensionUtil.setExtension(
+ theCtx,
+ theIssue,
+ "http://hl7.org/fhir/StructureDefinition/operationoutcome-issue-col",
+ "integer",
+ theColumn);
+ }
+ }
+
+ public static void addMessageIdExtensionToIssue(FhirContext theCtx, IBase theIssue, String theMessageId) {
+ if (theCtx.getVersion().getVersion() != FhirVersionEnum.DSTU2) {
+ ExtensionUtil.setExtension(
+ theCtx,
+ theIssue,
+ "http://hl7.org/fhir/StructureDefinition/operationoutcome-message-id",
+ "string",
+ theMessageId);
+ }
+ }
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ParametersUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ParametersUtil.java
index 3b091f9ff08..44d26280759 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ParametersUtil.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/ParametersUtil.java
@@ -403,7 +403,7 @@ public class ParametersUtil {
public static void addPartDecimal(FhirContext theContext, IBase theParameter, String theName, Double theValue) {
IPrimitiveType value = (IPrimitiveType)
theContext.getElementDefinition("decimal").newInstance();
- value.setValue(theValue == null ? null : new BigDecimal(theValue));
+ value.setValue(theValue == null ? null : BigDecimal.valueOf(theValue));
addPart(theContext, theParameter, theName, value);
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/UrlUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/UrlUtil.java
index 19c54ebd899..bca08865ebc 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/UrlUtil.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/UrlUtil.java
@@ -40,6 +40,8 @@ import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.net.URLDecoder;
+import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
@@ -602,6 +604,39 @@ public class UrlUtil {
return parameters;
}
+ /**
+ * Creates list of sub URIs candidates for search with :above modifier
+ * Example input: http://[host]/[pathPart1]/[pathPart2]
+ * Example output: http://[host], http://[host]/[pathPart1], http://[host]/[pathPart1]/[pathPart2]
+ *
+ * @param theUri String URI parameter
+ * @return List of URI candidates
+ */
+ public static List getAboveUriCandidates(String theUri) {
+ try {
+ URI uri = new URI(theUri);
+ if (uri.getScheme() == null || uri.getHost() == null) {
+ throwInvalidRequestExceptionForNotValidUri(theUri, null);
+ }
+ } catch (URISyntaxException theCause) {
+ throwInvalidRequestExceptionForNotValidUri(theUri, theCause);
+ }
+
+ List candidates = new ArrayList<>();
+ Path path = Paths.get(theUri);
+ candidates.add(path.toString().replace(":/", "://"));
+ while (path.getParent() != null && path.getParent().toString().contains("/")) {
+ candidates.add(path.getParent().toString().replace(":/", "://"));
+ path = path.getParent();
+ }
+ return candidates;
+ }
+
+ private static void throwInvalidRequestExceptionForNotValidUri(String theUri, Exception theCause) {
+ throw new InvalidRequestException(
+ Msg.code(2419) + String.format("Provided URI is not valid: %s", theUri), theCause);
+ }
+
public static class UrlParts {
private String myParams;
private String myResourceId;
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionEnum.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionEnum.java
index 2516ef314c2..70f2a2bd4c7 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionEnum.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionEnum.java
@@ -117,11 +117,18 @@ public enum VersionEnum {
V6_4_2,
V6_5_0,
V6_6_0,
+ V6_6_1,
+ V6_6_2,
V6_7_0,
V6_8_0,
-
+ V6_8_1,
+ V6_8_2,
V6_9_0,
+ V6_10_0,
+
+ V6_11_0,
+
V7_0_0;
public static VersionEnum latestVersion() {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SingleValidationMessage.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SingleValidationMessage.java
index 7d9e827d493..569a2f5e9d1 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SingleValidationMessage.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/SingleValidationMessage.java
@@ -24,6 +24,8 @@ import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.builder.ToStringBuilder;
import org.apache.commons.lang3.builder.ToStringStyle;
+import java.util.List;
+
public class SingleValidationMessage {
private Integer myLocationCol;
@@ -32,6 +34,7 @@ public class SingleValidationMessage {
private String myMessage;
private String myMessageId;
private ResultSeverityEnum mySeverity;
+ private List mySliceMessages;
/**
* Constructor
@@ -58,6 +61,7 @@ public class SingleValidationMessage {
b.append(myLocationString, other.myLocationString);
b.append(myMessage, other.myMessage);
b.append(mySeverity, other.mySeverity);
+ b.append(mySliceMessages, other.mySliceMessages);
return b.isEquals();
}
@@ -93,6 +97,7 @@ public class SingleValidationMessage {
b.append(myLocationString);
b.append(myMessage);
b.append(mySeverity);
+ b.append(mySliceMessages);
return b.toHashCode();
}
@@ -137,6 +142,17 @@ public class SingleValidationMessage {
if (mySeverity != null) {
b.append("severity", mySeverity.getCode());
}
+ if (mySliceMessages != null) {
+ b.append("sliceMessages", mySliceMessages);
+ }
return b.toString();
}
+
+ public void setSliceMessages(List theSliceMessages) {
+ mySliceMessages = theSliceMessages;
+ }
+
+ public List getSliceMessages() {
+ return mySliceMessages;
+ }
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/ValidationResult.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/ValidationResult.java
index 0eca0cc8a61..f95f993637e 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/ValidationResult.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/validation/ValidationResult.java
@@ -28,6 +28,7 @@ import org.hl7.fhir.instance.model.api.IBaseOperationOutcome;
import java.util.Collections;
import java.util.List;
+import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
/**
@@ -38,11 +39,11 @@ import static org.apache.commons.lang3.StringUtils.isNotBlank;
*/
public class ValidationResult {
public static final int ERROR_DISPLAY_LIMIT_DEFAULT = 1;
-
+ public static final String UNKNOWN = "(unknown)";
+ private static final String ourNewLine = System.getProperty("line.separator");
private final FhirContext myCtx;
private final boolean myIsSuccessful;
private final List myMessages;
-
private int myErrorDisplayLimit = ERROR_DISPLAY_LIMIT_DEFAULT;
public ValidationResult(FhirContext theCtx, List theMessages) {
@@ -108,8 +109,8 @@ public class ValidationResult {
/**
* @deprecated Use {@link #toOperationOutcome()} instead since this method returns a view.
- * {@link #toOperationOutcome()} is identical to this method, but has a more suitable name so this method
- * will be removed at some point.
+ * {@link #toOperationOutcome()} is identical to this method, but has a more suitable name so this method
+ * will be removed at some point.
*/
@Deprecated
public IBaseOperationOutcome getOperationOutcome() {
@@ -131,39 +132,36 @@ public class ValidationResult {
*/
public void populateOperationOutcome(IBaseOperationOutcome theOperationOutcome) {
for (SingleValidationMessage next : myMessages) {
- String location;
- if (isNotBlank(next.getLocationString())) {
- location = next.getLocationString();
- } else if (next.getLocationLine() != null || next.getLocationCol() != null) {
- location = "Line[" + next.getLocationLine() + "] Col[" + next.getLocationCol() + "]";
- } else {
- location = null;
- }
- String severity = next.getSeverity() != null ? next.getSeverity().getCode() : null;
- IBase issue = OperationOutcomeUtil.addIssueWithMessageId(
- myCtx,
- theOperationOutcome,
- severity,
- next.getMessage(),
- next.getMessageId(),
- location,
- Constants.OO_INFOSTATUS_PROCESSING);
+ Integer locationLine = next.getLocationLine();
+ Integer locationCol = next.getLocationCol();
+ String location = next.getLocationString();
+ ResultSeverityEnum issueSeverity = next.getSeverity();
+ String message = next.getMessage();
+ String messageId = next.getMessageId();
- if (next.getLocationLine() != null || next.getLocationCol() != null) {
- String unknown = "(unknown)";
- String line = unknown;
- if (next.getLocationLine() != null && next.getLocationLine() != -1) {
- line = next.getLocationLine().toString();
- }
- String col = unknown;
- if (next.getLocationCol() != null && next.getLocationCol() != -1) {
- col = next.getLocationCol().toString();
- }
- if (!unknown.equals(line) || !unknown.equals(col)) {
- OperationOutcomeUtil.addLocationToIssue(myCtx, issue, "Line " + line + ", Col " + col);
- }
+ if (next.getSliceMessages() == null) {
+ addIssueToOperationOutcome(
+ theOperationOutcome, location, locationLine, locationCol, issueSeverity, message, messageId);
+ continue;
}
- }
+
+ /*
+ * Occasionally the validator will return these lists of "slice messages"
+ * which happen when validating rules associated with a specific slice in
+ * a profile.
+ */
+ for (String nextSliceMessage : next.getSliceMessages()) {
+ String combinedMessage = message + " - " + nextSliceMessage;
+ addIssueToOperationOutcome(
+ theOperationOutcome,
+ location,
+ locationLine,
+ locationCol,
+ issueSeverity,
+ combinedMessage,
+ messageId);
+ }
+ } // for
if (myMessages.isEmpty()) {
String message = myCtx.getLocalizer().getMessage(ValidationResult.class, "noIssuesDetected");
@@ -171,6 +169,44 @@ public class ValidationResult {
}
}
+ private void addIssueToOperationOutcome(
+ IBaseOperationOutcome theOperationOutcome,
+ String location,
+ Integer locationLine,
+ Integer locationCol,
+ ResultSeverityEnum issueSeverity,
+ String message,
+ String messageId) {
+ if (isBlank(location) && locationLine != null && locationCol != null) {
+ location = "Line[" + locationLine + "] Col[" + locationCol + "]";
+ }
+ String severity = issueSeverity != null ? issueSeverity.getCode() : null;
+ IBase issue = OperationOutcomeUtil.addIssueWithMessageId(
+ myCtx, theOperationOutcome, severity, message, messageId, location, Constants.OO_INFOSTATUS_PROCESSING);
+
+ if (locationLine != null || locationCol != null) {
+ String unknown = UNKNOWN;
+ String line = unknown;
+ if (locationLine != null && locationLine != -1) {
+ line = locationLine.toString();
+ }
+ String col = unknown;
+ if (locationCol != null && locationCol != -1) {
+ col = locationCol.toString();
+ }
+ if (!unknown.equals(line) || !unknown.equals(col)) {
+ OperationOutcomeUtil.addIssueLineExtensionToIssue(myCtx, issue, line);
+ OperationOutcomeUtil.addIssueColExtensionToIssue(myCtx, issue, col);
+ String locationString = "Line[" + line + "] Col[" + col + "]";
+ OperationOutcomeUtil.addLocationToIssue(myCtx, issue, locationString);
+ }
+ }
+
+ if (isNotBlank(messageId)) {
+ OperationOutcomeUtil.addMessageIdExtensionToIssue(myCtx, issue, messageId);
+ }
+ }
+
@Override
public String toString() {
return "ValidationResult{" + "messageCount=" + myMessages.size() + ", isSuccessful=" + myIsSuccessful
@@ -191,6 +227,4 @@ public class ValidationResult {
public void setErrorDisplayLimit(int theErrorDisplayLimit) {
myErrorDisplayLimit = theErrorDisplayLimit;
}
-
- private static final String ourNewLine = System.getProperty("line.separator");
}
diff --git a/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties b/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties
index 5cbae62faa5..f0375733e44 100644
--- a/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties
+++ b/hapi-fhir-base/src/main/resources/ca/uhn/fhir/i18n/hapi-messages.properties
@@ -1,4 +1,7 @@
+org.hl7.fhir.common.hapi.validation.support.InMemoryTerminologyServerValidationSupport.displayMismatch=Concept Display "{0}" does not match expected "{1}"
+
+
ca.uhn.fhir.jpa.term.TermReadSvcImpl.expansionRefersToUnknownCs=Unknown CodeSystem URI "{0}" referenced from ValueSet
ca.uhn.fhir.jpa.term.TermReadSvcImpl.valueSetNotYetExpanded=ValueSet "{0}" has not yet been pre-expanded. Performing in-memory expansion without parameters. Current status: {1} | {2}
ca.uhn.fhir.jpa.term.TermReadSvcImpl.valueSetNotYetExpanded_OffsetNotAllowed=ValueSet expansion can not combine "offset" with "ValueSet.compose.exclude" unless the ValueSet has been pre-expanded. ValueSet "{0}" must be pre-expanded for this operation to work.
@@ -6,8 +9,9 @@ ca.uhn.fhir.jpa.term.TermReadSvcImpl.valueSetExpandedUsingPreExpansion=ValueSet
ca.uhn.fhir.jpa.term.TermReadSvcImpl.valueSetExpandedUsingInMemoryExpansion=ValueSet with URL "{0}" was expanded using an in-memory expansion
ca.uhn.fhir.jpa.term.TermReadSvcImpl.validationPerformedAgainstPreExpansion=Code validation occurred using a ValueSet expansion that was pre-calculated at {0}
ca.uhn.fhir.jpa.term.TermReadSvcImpl.valueSetNotFoundInTerminologyDatabase=ValueSet can not be found in terminology database: {0}
-ca.uhn.fhir.jpa.term.TermReadSvcImpl.valueSetPreExpansionInvalidated=ValueSet with URL "{0}" precaluclated expansion with {1} concept(s) has been invalidated
-ca.uhn.fhir.jpa.term.TermReadSvcImpl.valueSetCantInvalidateNotYetPrecalculated=ValueSet with URL "{0}" already has status: {1}
+ca.uhn.fhir.jpa.term.TermReadSvcImpl.valueSetPreExpansionInvalidated=ValueSet with URL "{0}" precaluclated expansion with {1} concept(s) has been invalidated
+ca.uhn.fhir.jpa.term.TermReadSvcImpl.valueSetCantInvalidateNotYetPrecalculated=ValueSet with URL "{0}" already has status: {1}
+ca.uhn.fhir.jpa.term.TermReadSvcImpl.unknownCodeInSystem=Unknown code "{0}#{1}"
# Core Library Messages
diff --git a/hapi-fhir-bom/pom.xml b/hapi-fhir-bom/pom.xml
index fd740343205..a3a762e6942 100644
--- a/hapi-fhir-bom/pom.xml
+++ b/hapi-fhir-bom/pom.xml
@@ -4,7 +4,7 @@
4.0.0ca.uhn.hapi.fhirhapi-fhir-bom
- 6.9.2-SNAPSHOT
+ 6.9.10-SNAPSHOTpomHAPI FHIR BOM
@@ -12,7 +12,7 @@
ca.uhn.hapi.fhirhapi-deployable-pom
- 6.9.2-SNAPSHOT
+ 6.9.10-SNAPSHOT../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-checkstyle/pom.xml b/hapi-fhir-checkstyle/pom.xml
index a06d5a1b05e..1c5f54d6dae 100644
--- a/hapi-fhir-checkstyle/pom.xml
+++ b/hapi-fhir-checkstyle/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhirhapi-fhir
- 6.9.2-SNAPSHOT
+ 6.9.10-SNAPSHOT../pom.xml
diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml
index eba0d255131..cdf8bfd4252 100644
--- a/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml
+++ b/hapi-fhir-cli/hapi-fhir-cli-api/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhirhapi-deployable-pom
- 6.9.2-SNAPSHOT
+ 6.9.10-SNAPSHOT../../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/BaseApp.java b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/BaseApp.java
index 9adf11b102a..b073900702d 100644
--- a/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/BaseApp.java
+++ b/hapi-fhir-cli/hapi-fhir-cli-api/src/main/java/ca/uhn/fhir/cli/BaseApp.java
@@ -270,14 +270,6 @@ public abstract class BaseApp {
// Actually execute the command
command.run(parsedOptions);
-
- myShutdownHookHasNotRun = true;
- runCleanupHookAndUnregister();
-
- if (!HapiSystemProperties.isTestModeEnabled()) {
- System.exit(0);
- }
-
} catch (ParseException e) {
if (!HapiSystemProperties.isTestModeEnabled()) {
LogbackUtil.loggingConfigOff();
@@ -296,6 +288,13 @@ public abstract class BaseApp {
ourLog.error("Error during execution: ", t);
runCleanupHookAndUnregister();
exitDueToException(new CommandFailureException("Error: " + t, t));
+ } finally {
+ myShutdownHookHasNotRun = true;
+ runCleanupHookAndUnregister();
+
+ if (!HapiSystemProperties.isTestModeEnabled()) {
+ System.exit(0);
+ }
}
}
diff --git a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml
index e85bb0a1f5f..4a2718254e6 100644
--- a/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml
+++ b/hapi-fhir-cli/hapi-fhir-cli-app/pom.xml
@@ -6,7 +6,7 @@
ca.uhn.hapi.fhirhapi-fhir-cli
- 6.9.2-SNAPSHOT
+ 6.9.10-SNAPSHOT../pom.xml
diff --git a/hapi-fhir-cli/pom.xml b/hapi-fhir-cli/pom.xml
index 0b0e1d8f7c7..e90ff04faef 100644
--- a/hapi-fhir-cli/pom.xml
+++ b/hapi-fhir-cli/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhirhapi-fhir
- 6.9.2-SNAPSHOT
+ 6.9.10-SNAPSHOT../pom.xml
diff --git a/hapi-fhir-client-okhttp/pom.xml b/hapi-fhir-client-okhttp/pom.xml
index 5d55c9e04ad..54405842ff1 100644
--- a/hapi-fhir-client-okhttp/pom.xml
+++ b/hapi-fhir-client-okhttp/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhirhapi-deployable-pom
- 6.9.2-SNAPSHOT
+ 6.9.10-SNAPSHOT../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-client/pom.xml b/hapi-fhir-client/pom.xml
index 1f7929cacb4..7ccf7bcadc3 100644
--- a/hapi-fhir-client/pom.xml
+++ b/hapi-fhir-client/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhirhapi-deployable-pom
- 6.9.2-SNAPSHOT
+ 6.9.10-SNAPSHOT../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/impl/RestfulClientFactory.java b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/impl/RestfulClientFactory.java
index 3369dff8911..1b288195eb3 100644
--- a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/impl/RestfulClientFactory.java
+++ b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/impl/RestfulClientFactory.java
@@ -75,8 +75,7 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
/**
* Constructor
*
- * @param theFhirContext
- * The context
+ * @param theFhirContext The context
*/
public RestfulClientFactory(FhirContext theFhirContext) {
myContext = theFhirContext;
@@ -142,13 +141,10 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
/**
* Instantiates a new client instance
*
- * @param theClientType
- * The client type, which is an interface type to be instantiated
- * @param theServerBase
- * The URL of the base for the restful FHIR server to connect to
+ * @param theClientType The client type, which is an interface type to be instantiated
+ * @param theServerBase The URL of the base for the restful FHIR server to connect to
* @return A newly created client
- * @throws ConfigurationException
- * If the interface type is not an interface
+ * @throws ConfigurationException If the interface type is not an interface
*/
@Override
public synchronized T newClient(Class theClientType, String theServerBase) {
@@ -281,13 +277,8 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
break;
case ONCE:
- if (myValidatedServerBaseUrls.contains(serverBase)) {
- break;
- }
-
synchronized (myValidatedServerBaseUrls) {
- if (!myValidatedServerBaseUrls.contains(serverBase)) {
- myValidatedServerBaseUrls.add(serverBase);
+ if (myValidatedServerBaseUrls.add(serverBase)) {
validateServerBase(serverBase, theHttpClient, theClient);
}
}
@@ -396,20 +387,13 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
}
String serverBase = normalizeBaseUrlForMap(theServerBase);
- if (myValidatedServerBaseUrls.contains(serverBase)) {
- return;
- }
-
- synchronized (myValidatedServerBaseUrls) {
- myValidatedServerBaseUrls.add(serverBase);
- }
+ myValidatedServerBaseUrls.add(serverBase);
}
/**
* Get the http client for the given server base
*
- * @param theServerBase
- * the server base
+ * @param theServerBase the server base
* @return the http client
*/
protected abstract IHttpClient getHttpClient(String theServerBase);
diff --git a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/MethodUtil.java b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/MethodUtil.java
index 5021374f9b6..f5b7b991e22 100644
--- a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/MethodUtil.java
+++ b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/MethodUtil.java
@@ -544,6 +544,7 @@ public class MethodUtil {
}
MethodOutcome retVal = new MethodOutcome();
+ retVal.setResponseStatusCode(theResponseStatusCode);
if (locationHeaders.size() > 0) {
String locationHeader = locationHeaders.get(0);
BaseOutcomeReturningMethodBinding.parseContentLocation(theContext, retVal, locationHeader);
diff --git a/hapi-fhir-converter/pom.xml b/hapi-fhir-converter/pom.xml
index 83d3a31e15d..cfdfed5e12d 100644
--- a/hapi-fhir-converter/pom.xml
+++ b/hapi-fhir-converter/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhirhapi-deployable-pom
- 6.9.2-SNAPSHOT
+ 6.9.10-SNAPSHOT../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-dist/pom.xml b/hapi-fhir-dist/pom.xml
index 2d5ac77b138..e6503bfc300 100644
--- a/hapi-fhir-dist/pom.xml
+++ b/hapi-fhir-dist/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhirhapi-fhir
- 6.9.2-SNAPSHOT
+ 6.9.10-SNAPSHOT../pom.xml
diff --git a/hapi-fhir-docs/pom.xml b/hapi-fhir-docs/pom.xml
index 8abe16e9fa2..5e69ddf10f4 100644
--- a/hapi-fhir-docs/pom.xml
+++ b/hapi-fhir-docs/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhirhapi-deployable-pom
- 6.9.2-SNAPSHOT
+ 6.9.10-SNAPSHOT../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-docs/src/main/java/ca/uhn/hapi/fhir/docs/PagingPatientProvider.java b/hapi-fhir-docs/src/main/java/ca/uhn/hapi/fhir/docs/PagingPatientProvider.java
index 2622ad526d1..7712ad307d2 100644
--- a/hapi-fhir-docs/src/main/java/ca/uhn/hapi/fhir/docs/PagingPatientProvider.java
+++ b/hapi-fhir-docs/src/main/java/ca/uhn/hapi/fhir/docs/PagingPatientProvider.java
@@ -24,6 +24,7 @@ import ca.uhn.fhir.rest.annotation.Search;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.StringParam;
import ca.uhn.fhir.rest.server.IResourceProvider;
+import ca.uhn.fhir.rest.server.method.ResponsePage;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.r4.model.InstantType;
import org.hl7.fhir.r4.model.Patient;
@@ -63,7 +64,10 @@ public class PagingPatientProvider implements IResourceProvider {
@Nonnull
@Override
- public List getResources(int theFromIndex, int theToIndex) {
+ public List getResources(
+ int theFromIndex,
+ int theToIndex,
+ @Nonnull ResponsePage.ResponsePageBuilder theResponsePageBuilder) {
int end = Math.max(theToIndex, matchingResourceIds.size() - 1);
List idsToReturn = matchingResourceIds.subList(theFromIndex, end);
return loadResourcesByIds(idsToReturn);
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/3786-mdm-npe.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/3786-mdm-npe.yaml
new file mode 100644
index 00000000000..12b71f42361
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/3786-mdm-npe.yaml
@@ -0,0 +1,4 @@
+---
+type: fix
+issue: 3786
+title: "Previously, when executing an update on a resource that had to undergo MDM, a nullpointer could occur. This has been fixed."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_0_0/4834-ips-dont-include-empty-section.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/4834-ips-dont-include-empty-section.yaml
similarity index 100%
rename from hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_0_0/4834-ips-dont-include-empty-section.yaml
rename to hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/4834-ips-dont-include-empty-section.yaml
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5089-clinical-reasoning-measurerefactor.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5089-clinical-reasoning-measurerefactor.yaml
new file mode 100644
index 00000000000..319e7177959
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5089-clinical-reasoning-measurerefactor.yaml
@@ -0,0 +1,6 @@
+---
+type: add
+issue: 5089
+title: "Updating storage-cr module to latest CQL 3.0.0, latest cql engine improvements, and Clinical Reasoning operations
+to leverage repository api pattern. This will remove several dependencies from within hapi-fhir to make future maintenance
+simpler and performance more robust."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_0_0/5090-adding-mdm-operation-pointcuts.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5090-adding-mdm-operation-pointcuts.yaml
similarity index 100%
rename from hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_0_0/5090-adding-mdm-operation-pointcuts.yaml
rename to hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5090-adding-mdm-operation-pointcuts.yaml
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5129-add-total-results-to-mdm-possible-duplicate-operation.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5129-add-total-results-to-mdm-possible-duplicate-operation.yaml
new file mode 100644
index 00000000000..5c4e726a6b8
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5129-add-total-results-to-mdm-possible-duplicate-operation.yaml
@@ -0,0 +1,4 @@
+---
+type: add
+issue: 5129
+title: "Added a field that shows the total number of `POSSIBLE_DUPLICATE` links has been added to the `$mdm-duplicate-golden-resources` operation response."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_0_0/5141-updating-resources-will-link-to-existing-resources.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5141-updating-resources-will-link-to-existing-resources.yaml
similarity index 100%
rename from hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_0_0/5141-updating-resources-will-link-to-existing-resources.yaml
rename to hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5141-updating-resources-will-link-to-existing-resources.yaml
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5192-include-in-search-paging-fix.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5192-include-in-search-paging-fix.yaml
new file mode 100644
index 00000000000..7a7acb851a1
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5192-include-in-search-paging-fix.yaml
@@ -0,0 +1,9 @@
+---
+type: fix
+issue: 5192
+title: "Fixed a bug where search Bundles with `include` entries from an _include query parameter might
+ trigger a 'next' link to blank pages.
+ Specifically, if _include'd resources + requested resources were greater than (or equal to)
+ requested page size, a 'next' link would be generated, even though no additional
+ resources are available.
+"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5196-type-level-expunge-operation-is-accepted-even-when-expunge_operation_enabled-is-set-to-false.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5196-type-level-expunge-operation-is-accepted-even-when-expunge_operation_enabled-is-set-to-false.yaml
new file mode 100644
index 00000000000..9d146d88d51
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5196-type-level-expunge-operation-is-accepted-even-when-expunge_operation_enabled-is-set-to-false.yaml
@@ -0,0 +1,4 @@
+---
+type: fix
+issue: 5196
+title: "Previously, type-level expunge was allowed even if expunge operation was turned off. This is now fixed."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5198-fixing-everything-search-paging-issues.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5198-fixing-everything-search-paging-issues.yaml
new file mode 100644
index 00000000000..7379d14ff29
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5198-fixing-everything-search-paging-issues.yaml
@@ -0,0 +1,7 @@
+---
+type: fix
+issue: 5198
+title: "Resolved an issue with type-everything search operations (eg, /Patient/$everything),
+ where not all page results were being returned if _count was specified to be
+ the same value as the maximum page size to fetch.
+"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5212-cds-hooks-request-throwing-500-internal-server-when-context-is-missing.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5212-cds-hooks-request-throwing-500-internal-server-when-context-is-missing.yaml
new file mode 100644
index 00000000000..33be2cc18dd
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5212-cds-hooks-request-throwing-500-internal-server-when-context-is-missing.yaml
@@ -0,0 +1,4 @@
+---
+type: fix
+issue: 5212
+title: "Previously, when a CDS hook was registered and called with a empty context, the server returned a 500. This behaviour has been fixed."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5215-improve-hfql-id-filtering.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5215-improve-hfql-id-filtering.yaml
new file mode 100644
index 00000000000..00153b26474
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5215-improve-hfql-id-filtering.yaml
@@ -0,0 +1,5 @@
+---
+type: perf
+issue: 5215
+title: "When executing an HFQL search with a FHIRPath filter on the `id` element, this will now
+ be automatically converted into an `_id` search parameter match for better performance."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5219-batch-npe.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5219-batch-npe.yaml
new file mode 100644
index 00000000000..c67be3b55b6
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5219-batch-npe.yaml
@@ -0,0 +1,4 @@
+---
+type: fix
+issue: 5219
+title: "Reindex batch job threw an exception when no results matched the reindex request. This has been corrected."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5220-race-conditions.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5220-race-conditions.yaml
new file mode 100644
index 00000000000..85bf9798c41
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5220-race-conditions.yaml
@@ -0,0 +1,7 @@
+---
+type: fix
+issue: 5220
+title: "Fixed a race condition in RestfulClientFactory that could cause validateInitialized() to deadlock.
+Fixed a race condition in FhirContext initialization that could produce a 'this.myNameToResourceType is null' NPE.
+Fixed a shutdown hook memory leak in BaseApp that happened when the command threw an exception;
+this memory leak only affects code that calls App.main repeatedly which is probably only in test code."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5230-batch2-job-cannot-transition-to-failed-status-on-mssql.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5230-batch2-job-cannot-transition-to-failed-status-on-mssql.yaml
new file mode 100644
index 00000000000..2994ffbe2d9
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5230-batch2-job-cannot-transition-to-failed-status-on-mssql.yaml
@@ -0,0 +1,6 @@
+---
+type: fix
+issue: 5230
+title: "batch2 jobs on MS SQL Server were failing to transition to FAILED state after max retrials
+ for the job are exhausted. This is now fixed."
+
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5231-fix-mdm-link-history-gives-404-after-mdm-clear.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5231-fix-mdm-link-history-gives-404-after-mdm-clear.yaml
new file mode 100644
index 00000000000..152828337b0
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5231-fix-mdm-link-history-gives-404-after-mdm-clear.yaml
@@ -0,0 +1,5 @@
+---
+type: fix
+issue: 5231
+title: "Previously, the `$mdm-link-history` operation would result in a 404 response when it was executed after a
+`$mdm-clear`. This has now been fixed by removing link history on `$mdm-clear`."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5235-allow-search-on-multiple-patient-ids-in-partitioned-environment.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5235-allow-search-on-multiple-patient-ids-in-partitioned-environment.yaml
new file mode 100644
index 00000000000..d74e0220be0
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5235-allow-search-on-multiple-patient-ids-in-partitioned-environment.yaml
@@ -0,0 +1,6 @@
+---
+type: add
+issue: 5235
+title: "Changes have been made to allow searching on multiple patient _ids
+ when in a patient_id partitioned environment.
+ "
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5236-rebuild-golden-resource-after-changing-mdm-link.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5236-rebuild-golden-resource-after-changing-mdm-link.yaml
new file mode 100644
index 00000000000..227f9b8a39b
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5236-rebuild-golden-resource-after-changing-mdm-link.yaml
@@ -0,0 +1,13 @@
+---
+type: add
+issue: 5236
+title: "Previously, when updating an MDM link to NO_MATCH,
+ the golden resource involved would maintain its previous
+ values, as defined by survivorship service.
+ This would result in out-of-date golden resources with
+ data that might not be accurate anymore.
+ Now, when a link is changed to NO_MATCH, golden resources
+ will be rebuilt from the ground up using the MDM survivorship
+ service, and the set of links/source resources available at the
+ time of update.
+"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5238-add-cds-on-fhir.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5238-add-cds-on-fhir.yaml
new file mode 100644
index 00000000000..38bddd5b239
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5238-add-cds-on-fhir.yaml
@@ -0,0 +1,6 @@
+---
+type: add
+issue: 5238
+title: "Added an implementation of Clinical Reasoning CDS on FHIR to the CDS Hooks module that allows PlanDefinition
+worfklows to be processed as CDS Services using the $apply operation.
+"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5242-mdm-clear-should-expunge-redirected-golden-resources.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5242-mdm-clear-should-expunge-redirected-golden-resources.yaml
new file mode 100644
index 00000000000..4b7972fd8b2
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5242-mdm-clear-should-expunge-redirected-golden-resources.yaml
@@ -0,0 +1,5 @@
+---
+type: fix
+issue: 5242
+title: "Previously, `$mdm-clear` failed to expunge `REDIRECTED` golden resources which left them as orphans. This is now fixed."
+
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5246-bulk-export-merge-steps.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5246-bulk-export-merge-steps.yaml
new file mode 100644
index 00000000000..64081e83088
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5246-bulk-export-merge-steps.yaml
@@ -0,0 +1,4 @@
+---
+type: add
+issue: 5246
+title: "Combined the ExpandResources step and WriteBinary step in the new WriteBinary step v2 for bulk exports."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5254-bulk-export-enabled-disrupts-custom-resource-addition.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5254-bulk-export-enabled-disrupts-custom-resource-addition.yaml
new file mode 100644
index 00000000000..53237cad66f
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5254-bulk-export-enabled-disrupts-custom-resource-addition.yaml
@@ -0,0 +1,7 @@
+---
+type: fix
+issue: 5254
+title: "Previously, when bulk export is enabled the resource list would be generated and would
+not be able to add a custom resource to that list. Now once a custom resource is added the list is
+rebuilt.
+"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5256-made-requestdetails-part-of-the-parameter-when-doing-cleanuppossiblematches.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5256-made-requestdetails-part-of-the-parameter-when-doing-cleanuppossiblematches.yaml
new file mode 100644
index 00000000000..2aeb7ceb619
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5256-made-requestdetails-part-of-the-parameter-when-doing-cleanuppossiblematches.yaml
@@ -0,0 +1,5 @@
+---
+type: fix
+issue: 5256
+title: "Added RequestDetails as part of the parameters when cleaning up possible matches to enable interceptors to
+access it."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5259-sort-meta-collection-properties.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5259-sort-meta-collection-properties.yaml
new file mode 100644
index 00000000000..9a470ab4187
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5259-sort-meta-collection-properties.yaml
@@ -0,0 +1,7 @@
+---
+type: change
+issue: 5229
+title: "Previously, when using INLINE tag storage mode, a superfluous version of a resource would be created as a result
+ of an update request which didn't have a real logical change to the resource but only changed the order of existing
+ items in tag, security label or profile collections. This change prevents this behaviour. Also on resource retrieval,
+ these meta collections are sorted alphabetically, based on (security, code) pair for tags and security labels."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5262-adding-new-parameter-strictmatch-to-the-mdm-history-link-operation.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5262-adding-new-parameter-strictmatch-to-the-mdm-history-link-operation.yaml
new file mode 100644
index 00000000000..e727ec08d83
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5262-adding-new-parameter-strictmatch-to-the-mdm-history-link-operation.yaml
@@ -0,0 +1,5 @@
+---
+type: change
+issue: 5262
+title: "Previously, when both resourceId and goldenResourceId are provided to the mdm link history operation, they will
+be treated as an OR. This is now changed to AND in order to comply with REST conventions."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5265-group-bulk-export-forward-refs.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5265-group-bulk-export-forward-refs.yaml
new file mode 100644
index 00000000000..c18ae9b1b45
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5265-group-bulk-export-forward-refs.yaml
@@ -0,0 +1,4 @@
+---
+type: fix
+jira: SMILE-7307
+title: "Previously, executing a Group Bulk Export without defining the `_type` parameter would accidentally omit `Patient` and `Organization` types. This has been corrected."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5268-respect-response-status-code-of-method-outcome-from-resource-provider.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5268-respect-response-status-code-of-method-outcome-from-resource-provider.yaml
new file mode 100644
index 00000000000..25e68ebabdb
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5268-respect-response-status-code-of-method-outcome-from-resource-provider.yaml
@@ -0,0 +1,5 @@
+---
+type: fix
+issue: 5268
+title: "Previously, the response status code set in a `MethodOutcome` of a Resource provider was not respected.
+This has been fixed."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5271-improve-code-validation-error-messages.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5271-improve-code-validation-error-messages.yaml
new file mode 100644
index 00000000000..9d194939a3c
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5271-improve-code-validation-error-messages.yaml
@@ -0,0 +1,8 @@
+---
+type: add
+issue: 5271
+title: "The error messages returned in an OperationOutcome when validating terminology codes
+ as a part of resource profile validation have been improved. Machine processable location
+ (line/col) information is now available through a pair of dedicated extensions, and
+ error messages such as UCUM parsing issues are now returned to the client (previously
+ they were swallowed and a generic error message was returned)."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5274-adding-metric-svc-to-mdm.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5274-adding-metric-svc-to-mdm.yaml
new file mode 100644
index 00000000000..6d9b3be278f
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5274-adding-metric-svc-to-mdm.yaml
@@ -0,0 +1,6 @@
+---
+type: add
+issue: 5274
+title: "Added a service for generating metrics on mdm links and resources.
+ This includes JPA queries and updated indices.
+ "
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5275-allow-to-configure-permission-rules-for-operation-with-access-to-all-resources.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5275-allow-to-configure-permission-rules-for-operation-with-access-to-all-resources.yaml
new file mode 100644
index 00000000000..7ddd86bec5e
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5275-allow-to-configure-permission-rules-for-operation-with-access-to-all-resources.yaml
@@ -0,0 +1,6 @@
+---
+type: add
+issue: 5275
+title: "Added an API that allows to configure permission rules for operations with access to all resources.
+This permission is needed to allow a search across the entire patient's record in the scope of the $everything operation to access all
+resources that references input Patient, including resources outside of the patient's compartment."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5275-searchbuilder-should-not-allow-everything-operation-to-follow-links-to-group-or-list-resources.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5275-searchbuilder-should-not-allow-everything-operation-to-follow-links-to-group-or-list-resources.yaml
new file mode 100644
index 00000000000..7d6f01929b0
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5275-searchbuilder-should-not-allow-everything-operation-to-follow-links-to-group-or-list-resources.yaml
@@ -0,0 +1,6 @@
+---
+type: fix
+issue: 5275
+title: "Previously, when calling `$everything` operation on a Patient instance, it was possible to retrieve data related
+to another patient via a List or Group resources. This has been fixed."
+
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5276-the-graphql-request-results-in-an-http-400-error.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5276-the-graphql-request-results-in-an-http-400-error.yaml
new file mode 100644
index 00000000000..389409cd931
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5276-the-graphql-request-results-in-an-http-400-error.yaml
@@ -0,0 +1,5 @@
+---
+type: fix
+issue: 5276
+title: "Previously, GraphQL queries will error when using base resource search parameters such as '_id' after search parameter rebuild.
+This has been fixed."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5290-allow-preventing-conditional-updates-to-invalidate-match.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5290-allow-preventing-conditional-updates-to-invalidate-match.yaml
new file mode 100644
index 00000000000..f6b83e8b80d
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5290-allow-preventing-conditional-updates-to-invalidate-match.yaml
@@ -0,0 +1,4 @@
+---
+type: add
+issue: 5290
+title: "Added storage property to prevent conditional updates from invalidating match criteria."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5295-fix-absolute-refs-with-identifier.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5295-fix-absolute-refs-with-identifier.yaml
new file mode 100644
index 00000000000..80b40e9c0fb
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5295-fix-absolute-refs-with-identifier.yaml
@@ -0,0 +1,6 @@
+---
+type: fix
+issue: 5295
+title: "A regression in the HAPI FHIR 6.6.0 JPA server meant that absolute resource
+ references which also contained an identifier were rejected even if the server
+ was configured to allow absolute references. This has been corrected."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5297-ips-fixes.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5297-ips-fixes.yaml
new file mode 100644
index 00000000000..f3bf54177c4
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5297-ips-fixes.yaml
@@ -0,0 +1,13 @@
+---
+type: fix
+issue: 5297
+title: "Several fixes have been made to the IPS generator:
+
+
The display names associated with several sections have been corrected to exactly match the LOINC definitions for their codes
+
Immunizations will now be ordered from most recent to least recent
+
IPS documents containing Consent resources for Advanced Directives could result in a crash
+
IPS documents containing Procedure resources for History of Procedures with a performed date could result in a crash
+
IPS documents containing AllergyIntolerance resources containing an occurrence but not a reaction date could result in a crash
+
IPS documents containing AllergyIntolerance resources containing an onset value in string format could result in a crash
+
IPS documents containing MedicationRequest resources with no associated Medication could result in a crash
+
"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5298-fix-everything-timeout.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5298-fix-everything-timeout.yaml
new file mode 100644
index 00000000000..a20577d008d
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5298-fix-everything-timeout.yaml
@@ -0,0 +1,4 @@
+---
+type: fix
+issue: 5298
+title: "Under some circumstances, a large `$everything` operation could enter an infinite loop and eventually timeout with a failure. This has been corrected."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5300-remove-duplicates-from-r5-defaultprofilevalidationsupport.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5300-remove-duplicates-from-r5-defaultprofilevalidationsupport.yaml
new file mode 100644
index 00000000000..5ffee261d22
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5300-remove-duplicates-from-r5-defaultprofilevalidationsupport.yaml
@@ -0,0 +1,6 @@
+---
+type: fix
+issue: 5300
+title: "A bug in DefaultProfileValidationSupport in R5 mode caused it to return duplicates
+ in the lists returned by `fetchAllStructureDefinitions()`, `fetchAllSearchParameters()`, etc.
+ This has been corrected."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5300-support-language-sp.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5300-support-language-sp.yaml
new file mode 100644
index 00000000000..ed819e5fe7e
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5300-support-language-sp.yaml
@@ -0,0 +1,5 @@
+---
+type: add
+issue: 5300
+title: "A new configuration option has been added to `StorageSettings` which enables
+ support in the JPA server for the `_language` SearchParameter."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5306-add-no-history-mode.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5306-add-no-history-mode.yaml
new file mode 100644
index 00000000000..f5509948193
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5306-add-no-history-mode.yaml
@@ -0,0 +1,6 @@
+---
+type: add
+issue: 5306
+title: "A new option has been added to the JPA server JpaStorageOptions which prevents the
+ server from maintaining a version history. In this mode, when a new version of a resource
+ is added, the previous version is automatically expunged."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5307-search-for-medicationrequests-with-medication-contained-does-not-return-correct-results.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5307-search-for-medicationrequests-with-medication-contained-does-not-return-correct-results.yaml
new file mode 100644
index 00000000000..61ac6be82ac
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5307-search-for-medicationrequests-with-medication-contained-does-not-return-correct-results.yaml
@@ -0,0 +1,6 @@
+---
+type: fix
+issue: 5307
+title: "Some search parameters include parenthetical expressions (e.g. `(MedicationRequest.medication as Reference)`).
+The leading `(` was causing searches using parenthetical expressions to fail where the reference target was a contained resource.
+This has been corrected."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5310-broken-tag-parse.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5310-broken-tag-parse.yaml
new file mode 100644
index 00000000000..1b647288093
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5310-broken-tag-parse.yaml
@@ -0,0 +1,5 @@
+---
+type: fix
+issue: 5310
+title: "Update DSTU2 tags and security labels with support for `userSelected` and `version` elements.
+ Also fix them on security labels in JPA storage."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5312-reindexstep-failing-when-executing-on-partition.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5312-reindexstep-failing-when-executing-on-partition.yaml
new file mode 100644
index 00000000000..bd186c81feb
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5312-reindexstep-failing-when-executing-on-partition.yaml
@@ -0,0 +1,5 @@
+---
+type: fix
+issue: 5312
+jira: SMILE-7323
+title: "Previously, issuing a reindex operation for resources on a specific partition would fail. This problem has been fixed."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5316-transaction-bundle-with-conditional-delete-and-update-on-same-resource-should-not-fail.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5316-transaction-bundle-with-conditional-delete-and-update-on-same-resource-should-not-fail.yaml
new file mode 100644
index 00000000000..0be0832994e
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5316-transaction-bundle-with-conditional-delete-and-update-on-same-resource-should-not-fail.yaml
@@ -0,0 +1,6 @@
+---
+type: fix
+issue: 5316
+jira: SMILE-7168
+title: "Previously, performing a FHIR transaction containing both a conditional delete and a conditional update
+on the same resource would fail. This has been fixed."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5321-code-display-validation-now-configurable.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5321-code-display-validation-now-configurable.yaml
new file mode 100644
index 00000000000..1e5b06ad12e
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5321-code-display-validation-now-configurable.yaml
@@ -0,0 +1,8 @@
+---
+type: add
+issue: 5321
+title: "It is now possible to configure the strictness of concept display name validation
+ using a new flag on the InMemoryTerminologyServerValidationSupport (for non-JPA validation)
+ and JpaStorageSettings (for JPA validation). In addition, the error messages emitted by
+ the validator when a concept display doesn't match have been improved to be much
+ more useful."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5322-dstu3-validation-resources-are-out-of-date.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5322-dstu3-validation-resources-are-out-of-date.yaml
new file mode 100644
index 00000000000..eb452d7d298
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5322-dstu3-validation-resources-are-out-of-date.yaml
@@ -0,0 +1,4 @@
+---
+type: fix
+issue: 5322
+title: "Update DSTU3 validation resources to FHIR 3.0.2 instead of 3.0.1"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5330-capability-statement-needs-to-declare-conformance-to-ig.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5330-capability-statement-needs-to-declare-conformance-to-ig.yaml
new file mode 100644
index 00000000000..7cdc6abc6ed
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5330-capability-statement-needs-to-declare-conformance-to-ig.yaml
@@ -0,0 +1,6 @@
+---
+type: fix
+issue: 5330
+jira: SMILE-7372
+title: "Previously, the capability statement returned by the server would not declare conformance to IG when a bulk data
+export provider is registered with the server. This issue has been fixed."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5331-mdm-query-links-operation-score-field-imprecise-value.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5331-mdm-query-links-operation-score-field-imprecise-value.yaml
new file mode 100644
index 00000000000..136783fbe82
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5331-mdm-query-links-operation-score-field-imprecise-value.yaml
@@ -0,0 +1,5 @@
+---
+type: fix
+issue: 5331
+title: "Previously, the score field returned by $mdm-query-links operation would contain imprecise decimal values. This
+is now fixed and rounded to 4 decimal places."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5333-prefix-regression-export.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5333-prefix-regression-export.yaml
new file mode 100644
index 00000000000..ccd72cf2982
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5333-prefix-regression-export.yaml
@@ -0,0 +1,5 @@
+---
+type: fix
+issue: 5333
+jira: SMILE-7403
+title: "A regression was introduced in 2023.08.R01 which caused binary storage prefixes to not be applied to exported binary blobs. This has been fixed."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5336-mdm-link-history-would-fail-if-provided-with-unknown-ids-on-postgres.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5336-mdm-link-history-would-fail-if-provided-with-unknown-ids-on-postgres.yaml
new file mode 100644
index 00000000000..17aefdceb19
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5336-mdm-link-history-would-fail-if-provided-with-unknown-ids-on-postgres.yaml
@@ -0,0 +1,6 @@
+---
+type: fix
+issue: 5336
+jira: SMILE-7406
+title: "Previously, on PostgreSQL, the $mdm-link-history operation would fail if all ids provided to a parameter are
+unknown, and the error will persist for all subsequent requests. This is now fixed."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5339-bulk-export-errors-when-patient-compartment-searchparameter-of-the-resource-is-not-present.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5339-bulk-export-errors-when-patient-compartment-searchparameter-of-the-resource-is-not-present.yaml
new file mode 100644
index 00000000000..d0e0461aeb4
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5339-bulk-export-errors-when-patient-compartment-searchparameter-of-the-resource-is-not-present.yaml
@@ -0,0 +1,6 @@
+---
+type: fix
+issue: 5339
+jira: SMILE-7236
+title: "Previously, Bulk Export will error when processing a resource if the patient compartment SearchParameter of that resource is not present.
+This has been fixed, the new behaviour is to ignore such resources."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5341-add-cds-cr-registries.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5341-add-cds-cr-registries.yaml
new file mode 100644
index 00000000000..bda264324e3
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5341-add-cds-cr-registries.yaml
@@ -0,0 +1,4 @@
+---
+type: add
+issue: 5341
+title: "Added registries for CdsCrServices and CrDiscoveryServices in CDS Hooks to allow registration of custom services."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5344-expunge-failing-when-executing-on-partition.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5344-expunge-failing-when-executing-on-partition.yaml
new file mode 100644
index 00000000000..61ffdfbdaf6
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5344-expunge-failing-when-executing-on-partition.yaml
@@ -0,0 +1,5 @@
+---
+type: fix
+issue: 5344
+jira: SMILE-7324
+title: "Previously, issuing an expunge operation for resources on a specific partition would fail. This problem has been fixed."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5349-jpa-config-bean-override-exception.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5349-jpa-config-bean-override-exception.yaml
new file mode 100644
index 00000000000..1f2504c4602
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5349-jpa-config-bean-override-exception.yaml
@@ -0,0 +1,4 @@
+---
+type: fix
+issue: 5349
+title: "Removed duplicate helperSvc bean in JpaConfig (also defined in imported MdmJpaConfig) to resolve BeanDefinitionOverrideException"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5353-iterate-on-revincludes-and-includes-does-not-return-correct-resources-when-used-with-non-iterate-revincludes.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5353-iterate-on-revincludes-and-includes-does-not-return-correct-resources-when-used-with-non-iterate-revincludes.yaml
new file mode 100644
index 00000000000..fe14f3cd2b8
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5353-iterate-on-revincludes-and-includes-does-not-return-correct-resources-when-used-with-non-iterate-revincludes.yaml
@@ -0,0 +1,6 @@
+---
+type: fix
+issue: 5353
+jira: SMILE-7451
+title: "Previously, when using revincludes and includes with iterate, while also using revincludes without iterate,
+the result omitted some resources that should have been included. This issue has now been fixed."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5355-add-openapi-resource-details.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5355-add-openapi-resource-details.yaml
new file mode 100644
index 00000000000..3e784c3b80f
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5355-add-openapi-resource-details.yaml
@@ -0,0 +1,8 @@
+---
+type: add
+issue: 5355
+title: "The generated OpenAPI documentation produced by OpenApiInterceptor will now include
+ additional details in the individual resource type documentation, including the values of
+ *CapabilityStatement.rest.resource.documentation*,
+ *CapabilityStatement.rest.resource.profile*, and
+ *CapabilityStatement.rest.resource.supportedProfile*."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5356-cr-codecache-invalidation-bug.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5356-cr-codecache-invalidation-bug.yaml
new file mode 100644
index 00000000000..b3a9c984458
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/5356-cr-codecache-invalidation-bug.yaml
@@ -0,0 +1,4 @@
+---
+type: fix
+issue: 5356
+title: "Clinical reasoning bug that did not invalidate resources in repository api global caches for terminology and libraries when updates/deletes were made."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_0_0/changes.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/changes.yaml
similarity index 62%
rename from hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_0_0/changes.yaml
rename to hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/changes.yaml
index a307d8ac4df..86eb2ac6c22 100644
--- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_0_0/changes.yaml
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/changes.yaml
@@ -8,4 +8,8 @@
"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/upgrade.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/upgrade.md
new file mode 100644
index 00000000000..258d2440c2f
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/upgrade.md
@@ -0,0 +1,26 @@
+This release introduces significant a change to the mechanism performing submission of resource modification events
+to the message broker. Previously, an event would be submitted as part of the synchronous transaction
+modifying a resource. Synchronous submission yielded responsive publishing with the caveat that events would be dropped
+upon submission failure.
+
+We have replaced the synchronous mechanism with a two stage process. Events are initially stored in
+database upon completion of the transaction and subsequently submitted to the broker by a scheduled task.
+This new asynchronous submission mechanism will introduce a slight delay in event publishing. It is our view that such
+delay is largely compensated by the capability to retry submission upon failure which will eliminate event losses.
+
+
+There are some potentially breaking changes:
+* On resource retrieval and before storage, tags, security label and profile collections in resource meta will be
+sorted in lexicographical order. The order of the elements for Coding types (i.e. tags and security labels) is defined
+by the (security, code) pair of each element. This normally should not break any clients because these properties are
+sets according to the FHIR specification, and hence the order of the elements in these collections should not matter.
+Also with this change the following side effects can be observed:
+ - If using INLINE tag storage mode, the first update request to a resource which has tags, security
+ labels or profiles could create a superfluous resource version if the update request does not really introduce any
+ change to the resource. This is because the persisted tags, security labels, and profile may not be sorted in
+ lexicographical order, and this would be interpreted as a new resource version since the tags would be sorted
+ before storage after this change. If the update request actually changes the resource, there is no concern here.
+ Also, subsequent updates will not create an additional version because of ordering of the meta properties anymore.
+ - These meta collections are sorted in place by the storage layer before persisting the resource, so any piece of
+ code that is calling storage layer directly should not be passing in unmodifiable collections, as it would
+ result in an error.
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_0_0/version.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/version.yaml
similarity index 100%
rename from hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_0_0/version.yaml
rename to hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_10_0/version.yaml
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_4_0/version.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_4_0/version.yaml
index 65e91d915a7..4be86bbbac8 100644
--- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_4_0/version.yaml
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_4_0/version.yaml
@@ -1,3 +1,3 @@
---
release-date: "2022-02-18"
-codename: "TBD"
+codename: "Vishwa"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_0_0/upgrade.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_4_3/upgrade.md
similarity index 100%
rename from hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/7_0_0/upgrade.md
rename to hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_4_3/upgrade.md
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_4_3/version.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_4_3/version.yaml
new file mode 100644
index 00000000000..37c96634729
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_4_3/version.yaml
@@ -0,0 +1,3 @@
+---
+release-date: "2023-03-15"
+codename: "Vishwa"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_0/version.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_0/version.yaml
index 2de22c443a8..864fb0d514c 100644
--- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_0/version.yaml
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_0/version.yaml
@@ -1,3 +1,3 @@
---
release-date: "2023-05-18"
-codename: "TBD"
+codename: "Xenon"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_1/upgrade.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_1/upgrade.md
new file mode 100644
index 00000000000..04fe4dc9295
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_1/upgrade.md
@@ -0,0 +1 @@
+This release resolves several CVEs.
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_1/version.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_1/version.yaml
new file mode 100644
index 00000000000..59b79c3607a
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_1/version.yaml
@@ -0,0 +1,3 @@
+---
+release-date: "2023-05-28"
+codename: "Xenon"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_2/upgrade.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_2/upgrade.md
new file mode 100644
index 00000000000..04fe4dc9295
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_2/upgrade.md
@@ -0,0 +1 @@
+This release resolves several CVEs.
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_2/version.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_2/version.yaml
new file mode 100644
index 00000000000..53408677d81
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_6_2/version.yaml
@@ -0,0 +1,3 @@
+---
+release-date: "2023-07-04"
+codename: "Xenon"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5023-fix-usage-of-awssdk-string-utils.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5023-fix-usage-of-awssdk-string-utils.yaml
new file mode 100644
index 00000000000..c9eac0e178a
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5023-fix-usage-of-awssdk-string-utils.yaml
@@ -0,0 +1,5 @@
+---
+type: fix
+issue: 5023
+backport: 6.6.2
+title: "Jpa migration task used awssdk StringUtils rather than apache commons string utils. Thanks to @Thopap for the contribution"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5037-fix-golden-resource-remains-when-last-source-resource-deleted.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5037-fix-golden-resource-remains-when-last-source-resource-deleted.yaml
new file mode 100644
index 00000000000..a57ca7a32e5
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5037-fix-golden-resource-remains-when-last-source-resource-deleted.yaml
@@ -0,0 +1,7 @@
+---
+type: fix
+issue: 5037
+jira: SMILE-6370
+title: "Previously, when the last source resource with a `MATCH` link was deleted, the golden resource
+remained in the database, leaving it orphaned. This has now been fixed such that when there are no more
+`MATCH` links left associated with a golden resource, the golden resource will automatically be deleted."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5095-add-support-for-source-search-parameter-modifiers.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5095-add-support-for-source-search-parameter-modifiers.yaml
new file mode 100644
index 00000000000..29181a0ace6
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5095-add-support-for-source-search-parameter-modifiers.yaml
@@ -0,0 +1,4 @@
+---
+type: add
+issue: 5095
+title: "Added support for :above, :below, :contains and :missing _source search parameter modifiers."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5150--delete-expunge-over-10k-resources-deletes-only-10k.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5150--delete-expunge-over-10k-resources-deletes-only-10k.yaml
new file mode 100644
index 00000000000..64666cbcf69
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5150--delete-expunge-over-10k-resources-deletes-only-10k.yaml
@@ -0,0 +1,5 @@
+---
+type: fix
+issue: 5150
+title: "When running a $delete-expunge with over 10,000 resources, only the first 10,000 resources were deleted.
+ This is now fixed."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5155-expunge-operation-on-codesystem-may-return-500.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5155-expunge-operation-on-codesystem-may-return-500.yaml
new file mode 100644
index 00000000000..06afea286b3
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5155-expunge-operation-on-codesystem-may-return-500.yaml
@@ -0,0 +1,5 @@
+---
+type: fix
+issue: 5155
+title: "Previously, requesting an $expunge operation on CodeSystem resources while CS batch deletion is underway would return HTTP 500.
+ This has been fixed to return HTTP 412 (precondition failed)."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5157-bulkexport-reuse-with-POSTandGET.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5157-bulkexport-reuse-with-POSTandGET.yaml
new file mode 100644
index 00000000000..12e12d03097
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5157-bulkexport-reuse-with-POSTandGET.yaml
@@ -0,0 +1,4 @@
+---
+type: fix
+issue: 5157
+title: "Previously, the reuse functionality did not operate correctly when dealing with POST and GET requests. This fix ensures that similar POST and GET export requests will be reused."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5158-add-support-for-subscription-matching-of-source-search-parameter-modifiers.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5158-add-support-for-subscription-matching-of-source-search-parameter-modifiers.yaml
new file mode 100644
index 00000000000..390c1c42110
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5158-add-support-for-subscription-matching-of-source-search-parameter-modifiers.yaml
@@ -0,0 +1,4 @@
+---
+type: add
+issue: 5158
+title: "Added support for Subscription matching of ':above', ':below', ':contains' and ':missing' '_source' search parameter modifiers."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5167-fix-jdbc-deps.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5167-fix-jdbc-deps.yaml
new file mode 100644
index 00000000000..2a688854a4b
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5167-fix-jdbc-deps.yaml
@@ -0,0 +1,4 @@
+---
+type: fix
+issue: 5167
+title: "Fixed a dependency in the HSQL JDBC driver referencing a non-bundled class (javax.ServletOutputStream)"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5173-gateway-everything-doesnt-return-all-patients.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5173-gateway-everything-doesnt-return-all-patients.yaml
new file mode 100644
index 00000000000..6d051d71575
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5173-gateway-everything-doesnt-return-all-patients.yaml
@@ -0,0 +1,4 @@
+---
+type: fix
+issue: 5173
+title: "Fix gateway `$everything` operation to respect server configured default and maximum page sizes."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5179-cr-cachebig-providerloader.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5179-cr-cachebig-providerloader.yaml
new file mode 100644
index 00000000000..f3f3461b834
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5179-cr-cachebig-providerloader.yaml
@@ -0,0 +1,3 @@
+type: fix
+issue: 5179
+title: "Added evaluation setting for hapi-fhir storage-cr module operations from outside. Updated provider loading from hapi-fhir instead of external server for caregaps and submitdata providers. Updated testing suite to depend on restful server for new provider loader"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5182-fix-removing-tags-does-not-trigger-subscription.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5182-fix-removing-tags-does-not-trigger-subscription.yaml
new file mode 100644
index 00000000000..cfa564c6356
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5182-fix-removing-tags-does-not-trigger-subscription.yaml
@@ -0,0 +1,6 @@
+---
+type: fix
+issue: 5182
+jira: SMILE-6857
+title: "Previously, removing tags in a resource update with proper headers and versioning flag would not trigger a
+new subscription. This has been fixed."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5183-us-core-ig-ingestion-fails-value-set-version-id-conflict.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5183-us-core-ig-ingestion-fails-value-set-version-id-conflict.yaml
new file mode 100644
index 00000000000..6c143123bc6
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5183-us-core-ig-ingestion-fails-value-set-version-id-conflict.yaml
@@ -0,0 +1,4 @@
+---
+type: fix
+issue: 5183
+title: "The latest US Core IG includes two ValueSets with different contents, but the same FHIR Id and OID via two different included IGs (i.e. `2.16.840.1.113762.1.4.1010.9` via us.cdc.phinvads and us.nlm.vsac). Ingesting these duplicates in US Core failed with a 500 error. This has been resolved by logging the error and allowing the rest of the ingestion to proceed."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5195-subscription-max-results.yml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5195-subscription-max-results.yml
new file mode 100644
index 00000000000..222e54373cd
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5195-subscription-max-results.yml
@@ -0,0 +1,4 @@
+---
+type: fix
+issue: 5195
+title: "MAX_SUBSCRIPTION_RESULTS was set to an arbitrarily high 50000. This resulted in a failures in hapi-fhir-jpaserver-starter. Other constants, such as SearchParamRegistryImpl.MAX_MANAGED_PARAM_COUNT have a limit of 10000 as well. This aligns the MAX_SUBSCRIPTION results with that value."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5205-uploading-large-vocabulary-file-returns-error.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5205-uploading-large-vocabulary-file-returns-error.yaml
new file mode 100644
index 00000000000..6346b9ff78d
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/5205-uploading-large-vocabulary-file-returns-error.yaml
@@ -0,0 +1,5 @@
+---
+type: fix
+issue: 5205
+title: "Previously, uploading a large vocabulary file (like Loinc) through the upload-external-code-system command would
+return an error. The issue has been fixed."
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/version.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/version.yaml
index 390061b1ec6..f08e2d4312f 100644
--- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/version.yaml
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_0/version.yaml
@@ -1,3 +1,3 @@
---
release-date: "2023-08-18"
-codename: "TBD"
+codename: "YucatÃĄn"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_1/upgrade.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_1/upgrade.md
new file mode 100644
index 00000000000..ec0f458f5ab
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_1/upgrade.md
@@ -0,0 +1 @@
+Note: this release has been decommissioned, and you should not be using it. Please upgrade to a newer version.
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_1/version.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_1/version.yaml
new file mode 100644
index 00000000000..f8d2aa34372
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_1/version.yaml
@@ -0,0 +1,3 @@
+---
+release-date: "2023-08-31"
+codename: "YucatÃĄn"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_2/upgrade.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_2/upgrade.md
new file mode 100644
index 00000000000..ec0f458f5ab
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_2/upgrade.md
@@ -0,0 +1 @@
+Note: this release has been decommissioned, and you should not be using it. Please upgrade to a newer version.
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_2/version.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_2/version.yaml
new file mode 100644
index 00000000000..97d5210f1d1
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/6_8_2/version.yaml
@@ -0,0 +1,3 @@
+---
+release-date: "2023-09-05"
+codename: "YucatÃĄn"
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/files.properties b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/files.properties
index 41de46a1a1e..fa474411fe3 100644
--- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/files.properties
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/files.properties
@@ -1,7 +1,8 @@
section.introduction.title=Welcome to HAPI FHIR
page.introduction.table_of_contents=Table of Contents
-page.introduction.changelog=Changelog: 2022
+page.introduction.changelog=Changelog: 2023
+page.introduction.changelog_2022=Changelog: 2022
page.introduction.changelog_2021=Changelog: 2021
page.introduction.changelog_2020=Changelog: 2020
page.introduction.changelog_2019=Changelog: 2019
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/hfql/hfql.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/hfql/hfql.md
index 3a9e006d259..c2b698f0426 100644
--- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/hfql/hfql.md
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/hfql/hfql.md
@@ -1,4 +1,4 @@
-# FQL Driver: SQL For FHIR Repositories
+# HFQL Driver: SQL For FHIR Repositories
This is an experimental module. Use with caution. This API is likely to change.
@@ -14,8 +14,8 @@ A simple example query is shown below:
```sql
SELECT
- name.family as family,
- name.given as given,
+ name[0].family as family,
+ name[0].given[0] as given,
birthDate,
identifier.where(system='http://hl7.org/fhir/sid/us-ssn').value as SSN
FROM
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/introduction/changelog.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/introduction/changelog.md
index bab69254101..01cee0f6861 100644
--- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/introduction/changelog.md
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/introduction/changelog.md
@@ -1,4 +1,4 @@
-# Changelog: 2022
+# Changelog: 2023
-
+
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/introduction/changelog_2022.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/introduction/changelog_2022.md
new file mode 100644
index 00000000000..d6a43753fcd
--- /dev/null
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/introduction/changelog_2022.md
@@ -0,0 +1,5 @@
+
+# Changelog: 2022
+
+
+
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa/configuration.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa/configuration.md
index 7a789c5276d..dbc4157ba7b 100644
--- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa/configuration.md
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa/configuration.md
@@ -179,3 +179,10 @@ Clients may want to disable this setting for performance reasons as it populates
Setting this property explicitly to false disables the feature: [Non Resource DB History](/apidocs/hapi-fhir-storage/ca/uhn/fhir/jpa/api/config/JpaStorageSettings.html#isNonResourceDbHistoryEnabled())
+# Prevent Conditional Updates to Invalidate Match Criteria
+
+JPA Server prevents conditional updated to invalidate match criteria for first version of resources.
+This setting, disabled by default, allows to configure the same behaviour for later versions.
+
+Setting this property explicitly to true enables the feature: [Prevent Conditional Updates Invalidating Match Criteria](/apidocs/hapi-fhir-storage/ca/uhn/fhir/jpa/api/config/JpaStorageSettings.html#isPreventInvalidatingConditionalMatchCriteria())
+
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_details.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_details.md
index 033dc0b7081..93515243748 100644
--- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_details.md
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_details.md
@@ -22,10 +22,7 @@ Below are some simplifying principles HAPI MDM follows to reduce complexity and
1. The only source resources in the system that do not have a MATCH link are those that have the 'NO-MDM' tag or those that have POSSIBLE_MATCH links pending review.
-1. The HAPI MDM rules define a single identifier system that holds the external enterprise id ("EID"). If a source resource has an external EID, then the Golden Resource it links to always has the same EID. If a source resource has no EID when it arrives, a unique UUID will be assigned as that source resource's EID.
-
-1. A Golden Resource can have both an internal EID (auto-created by HAPI), and an external EID (provided by an
-external system).
+1. The HAPI MDM rules define a single identifier system that holds the external enterprise id ("EID"). If a source resource has an external EID, then the Golden Resource it links to always has the same EID.
1. Two different Golden Resources cannot have the same EID.
@@ -85,7 +82,7 @@ possible that hundreds of John Doe's could be linked to the same Golden Resource
When a new source resource is compared with all other resources of the same type in the repository, there are four possible outcomes:
-* CASE 1: No MATCH and no POSSIBLE_MATCH outcomes -> a new Golden Resource is created and linked to that source resource as MATCH. If the incoming resource has an EID, it is copied to the Golden Resource. Otherwise a new UUID is generated and used as the internal EID.
+* CASE 1: No MATCH and no POSSIBLE_MATCH outcomes -> a new Golden Resource is created and linked to that source resource as MATCH. If the incoming resource has an EID, it is copied to the Golden Resource.
* CASE 2: All of the MATCH source resources are already linked to the same Golden Resource -> a new Link is created between the new source resource and that Golden Resource and is set to MATCH.
@@ -93,6 +90,17 @@ When a new source resource is compared with all other resources of the same type
* CASE 4: Only POSSIBLE_MATCH outcomes -> In this case, new POSSIBLE_MATCH links are created and await manual reassignment to either NO_MATCH or MATCH.
+### MDM and Resource Deletion
+By default, when the last source resource in a `MATCH` relationship with a golden resource is deleted, the associated golden resource is permanently (hard) deleted. This prevents orphaned golden resources that remain in the database. Note that this will also delete the respective MDM link history. Here are several scenarios and their associated behaviour, we will define SR as a source resource and GR as a golden resource:
+
+* There is a 1 to 1 `MATCH` relationship between SR/1 and GR/1 -> when SR/1 is deleted, GR/1 is also deleted.
+
+* GR/1 has a `MATCH` link with SR/1, and a `POSSIBLE_MATCH` link with SR/2 -> when SR/1 is deleted, all links are deleted and GR/1 is deleted. Additionally, SR/2 is re-submitted for matching, meaning a new GR could be created or it could match with another GR.
+
+* GR/1 has a `MATCH` link with SR/1, a `POSSIBLE_MATCH` link with SR/2, and a `POSSIBLE_DUPLICATE` with GR/2. Additionally, GR/2 has a `MATCH` with SR/3, a `POSSIBLE_MACH` with SR/2 -> when SR/1 is deleted, all links associated with GR/1, including the `POSSIBLE_DUPLICATE` link, are deleted. SR/2 maintains its `POSSIBLE_MATCH` relation with GR/2. Finally, GR/1 is deleted.
+
+This behaviour can be changed from the default of hard deleting to soft deleting by setting [setAutoExpungeGoldenResources(boolean)](/hapi-fhir/apidocs/hapi-fhir-server-mdm/ca/uhn/fhir/mdm/rules/config/MdmSettings.html#setAutoExpungeGoldenResources(boolean)) to false. Soft deleting the golden resource means the golden resource will continue to persist in the database, but the MDM link history for the affected link(s) will still be accessible, which may be useful for auditing.
+
# HAPI MDM Technical Details
When MDM is enabled, the HAPI FHIR JPA Server does the following things on startup:
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_eid.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_eid.md
index d86d3a68ecc..fcae048b3eb 100644
--- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_eid.md
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_eid.md
@@ -1,8 +1,9 @@
# MDM Enterprise Identifiers
-An Enterprise Identifier (EID) is a unique identifier that can be attached to source resources. Each implementation is expected to use exactly one EID system for incoming resources, defined in the MDM Rules file. If a source resource with a valid EID is submitted, that EID will be copied over to the Golden Resource that was matched. In the case that the incoming source resource had no EID assigned, an internal EID will be created for it. There are thus two classes of EID:
- * Internal EIDs, created by HAPI-MDM, and
- * External EIDs, provided by the submitted resources.
+An Enterprise Identifier (EID) is a unique identifier that can be attached to source resources.
+Each implementation is expected to use exactly one EID system for incoming resources,
+defined in the MDM Rules file.
+If a source resource with a valid EID is submitted, that EID will be copied over to the Golden Resource that was matched.
## MDM EID Settings
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_operations.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_operations.md
index 8e9e154e787..eec3d90a613 100644
--- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_operations.md
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_operations.md
@@ -816,13 +816,13 @@ Content-Type: application/fhir+json; charset=UTF-8
{
"name":"resource",
"resource": {
- "resourceType":"Orgaization",
+ "resourceType":"Organization",
"name": "McMaster Family Practice"
}
},
{
"name":"resourceType",
- "valueString": "Orgaization"
+ "valueString": "Organization"
}
]
}
@@ -839,7 +839,8 @@ your ruleset. It permits the user to reset the state of their MDM system without
and Golden Resources.
After the operation is complete, all targeted MDM links are removed from the system, and their related Golden Resources
-are deleted and expunged from the server.
+are deleted and expunged from the server. Additionally, the link history for targeted links and their related golden
+resources will also be expunged.
This operation takes two optional Parameters.
diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_rules.md b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_rules.md
index 0a56dea7a22..35fb636255d 100644
--- a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_rules.md
+++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/docs/server_jpa_mdm/mdm_rules.md
@@ -111,9 +111,27 @@ Here is a description of how each section of this document is configured.
### candidateSearchParams
-These define fields which must have at least one exact match before two resources are considered for matching. This is like a list of "pre-searches" that find potential candidates for matches, to avoid the expensive operation of running a match score calculation on all resources in the system. E.g. you may only wish to consider matching two Patients if they either share at least one identifier in common or have the same birthday or the same phone number. The HAPI FHIR server executes each of these searches separately and then takes the union of the results, so you can think of these as `OR` criteria that cast a wide net for potential candidates. In some MDM systems, these "pre-searches" are called "blocking" searches (since they identify "blocks" of candidates that will be searched for matches).
+These define one or more fields which must have a match before two resources are considered for matching.
+This is like a list of "pre-searches" that find potential candidates for matches,
+to avoid the expensive operation of running a match score calculation on all resources in the system.
+`candidateSearchParams` are capable of making searches using any SearchParameter defined in the system.
+For example, [phonetic SearchParameters](https://smilecdr.com/docs/fhir_repository/search_parameter_phonetic.html)
+can be useful here when matchFields include phonetic matchers.
+E.g. you may only wish to consider matching two Patients if they either share at least one identifier in
+common or have the same birthday or the same phone number. The HAPI FHIR server executes each of these searches
+separately and then takes the union of the results, so you can think of these as `OR` criteria that
+cast a wide net for potential candidates. In some MDM systems, these "pre-searches" are called "blocking"
+searches (since they identify "blocks" of candidates that will be searched for matches).
-If a list of searchParams is specified in a given candidateSearchParams item, then these search parameters are treated as `AND` parameters. In the following candidateSearchParams definition, hapi-fhir will extract given name, family name and identifiers from the incoming Patient and perform two separate searches, first for all Patient resources that have the same given `AND` the same family name as the incoming Patient, and second for all Patient resources that share at least one identifier as the incoming Patient. Note that if the incoming Patient was missing any of these searchParam values, then that search would be skipped. E.g. if the incoming Patient had a given name but no family name, then only a search for matching identifiers would be performed.
+If a list of searchParams is specified in a given `candidateSearchParams` item,
+then these search parameters are treated as `AND` parameters.
+In the following `candidateSearchParams` definition, hapi-fhir will extract given name,
+family name and identifiers from the incoming Patient and perform two separate searches,
+first for all Patient resources that have the same given `AND` the same family name as
+the incoming Patient, and second for all Patient resources that share at least one
+identifier as the incoming Patient. Note that if the incoming Patient was missing any of these searchParam values,
+then that search would be skipped. E.g. if the incoming Patient had a given name but no family name,
+then only a search for matching identifiers would be performed.
```json
{
diff --git a/hapi-fhir-jacoco/pom.xml b/hapi-fhir-jacoco/pom.xml
index 71336446bae..1a91d9252e9 100644
--- a/hapi-fhir-jacoco/pom.xml
+++ b/hapi-fhir-jacoco/pom.xml
@@ -11,7 +11,7 @@
ca.uhn.hapi.fhirhapi-deployable-pom
- 6.9.2-SNAPSHOT
+ 6.9.10-SNAPSHOT../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jaxrsserver-base/pom.xml b/hapi-fhir-jaxrsserver-base/pom.xml
index 876d65a0949..115ce1185e2 100644
--- a/hapi-fhir-jaxrsserver-base/pom.xml
+++ b/hapi-fhir-jaxrsserver-base/pom.xml
@@ -4,7 +4,7 @@
ca.uhn.hapi.fhirhapi-deployable-pom
- 6.9.2-SNAPSHOT
+ 6.9.10-SNAPSHOT../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpa/pom.xml b/hapi-fhir-jpa/pom.xml
index f9eba6c26e0..9323628d70b 100644
--- a/hapi-fhir-jpa/pom.xml
+++ b/hapi-fhir-jpa/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhirhapi-deployable-pom
- 6.9.2-SNAPSHOT
+ 6.9.10-SNAPSHOT../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-base/pom.xml b/hapi-fhir-jpaserver-base/pom.xml
index 976434018bd..8b5b0bb7239 100644
--- a/hapi-fhir-jpaserver-base/pom.xml
+++ b/hapi-fhir-jpaserver-base/pom.xml
@@ -5,7 +5,7 @@
ca.uhn.hapi.fhirhapi-deployable-pom
- 6.9.2-SNAPSHOT
+ 6.9.10-SNAPSHOT../hapi-deployable-pom/pom.xml
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImpl.java
index 19a060a915a..01fe091dbbe 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImpl.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/batch2/JpaJobPersistenceImpl.java
@@ -36,7 +36,12 @@ import ca.uhn.fhir.jpa.dao.tx.IHapiTransactionService;
import ca.uhn.fhir.jpa.entity.Batch2JobInstanceEntity;
import ca.uhn.fhir.jpa.entity.Batch2WorkChunkEntity;
import ca.uhn.fhir.model.api.PagingIterator;
+import ca.uhn.fhir.util.Batch2JobDefinitionConstants;
import ca.uhn.fhir.util.Logs;
+import com.fasterxml.jackson.core.JsonParser;
+import com.fasterxml.jackson.databind.JsonNode;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ObjectNode;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.Validate;
import org.slf4j.Logger;
@@ -220,6 +225,11 @@ public class JpaJobPersistenceImpl implements IJobPersistence {
List instanceEntities;
if (statuses != null && !statuses.isEmpty()) {
+ if (definitionId.equals(Batch2JobDefinitionConstants.BULK_EXPORT)) {
+ if (originalRequestUrlTruncation(params) != null) {
+ params = originalRequestUrlTruncation(params);
+ }
+ }
instanceEntities = myJobInstanceRepository.findInstancesByJobIdParamsAndStatus(
definitionId, params, statuses, pageable);
} else {
@@ -228,6 +238,31 @@ public class JpaJobPersistenceImpl implements IJobPersistence {
return toInstanceList(instanceEntities);
}
+ private String originalRequestUrlTruncation(String theParams) {
+ try {
+ ObjectMapper mapper = new ObjectMapper();
+ mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
+ mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
+ JsonNode rootNode = mapper.readTree(theParams);
+ String originalUrl = "originalRequestUrl";
+
+ if (rootNode instanceof ObjectNode) {
+ ObjectNode objectNode = (ObjectNode) rootNode;
+
+ if (objectNode.has(originalUrl)) {
+ String url = objectNode.get(originalUrl).asText();
+ if (url.contains("?")) {
+ objectNode.put(originalUrl, url.split("\\?")[0]);
+ }
+ }
+ return mapper.writeValueAsString(objectNode);
+ }
+ } catch (Exception e) {
+ ourLog.info("Error Truncating Original Request Url", e);
+ }
+ return null;
+ }
+
@Override
@Transactional(propagation = Propagation.REQUIRES_NEW)
public List fetchInstances(int thePageSize, int thePageIndex) {
@@ -265,7 +300,7 @@ public class JpaJobPersistenceImpl implements IJobPersistence {
Validate.isTrue(changeCount > 0, "changed chunk matching %s", chunkId);
Query query = myEntityManager.createQuery("update Batch2WorkChunkEntity " + "set myStatus = :failed "
- + ",myErrorMessage = CONCAT('Too many errors: ', myErrorCount, '. Last error msg was ', myErrorMessage) "
+ + ",myErrorMessage = CONCAT('Too many errors: ', CAST(myErrorCount as string), '. Last error msg was ', myErrorMessage) "
+ "where myId = :chunkId and myErrorCount > :maxCount");
query.setParameter("chunkId", chunkId);
query.setParameter("failed", WorkChunkStatusEnum.FAILED);
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessor.java
index ae0fb1115f1..8245fdaf066 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessor.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/bulk/export/svc/JpaBulkExportProcessor.java
@@ -53,6 +53,7 @@ import ca.uhn.fhir.rest.param.HasOrListParam;
import ca.uhn.fhir.rest.param.HasParam;
import ca.uhn.fhir.rest.param.ReferenceOrListParam;
import ca.uhn.fhir.rest.param.ReferenceParam;
+import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
import ca.uhn.fhir.util.ExtensionUtil;
import ca.uhn.fhir.util.HapiExtensions;
import ca.uhn.fhir.util.Logs;
@@ -121,6 +122,9 @@ public class JpaBulkExportProcessor implements IBulkExportProcessor {
@Autowired
private IHapiTransactionService myHapiTransactionService;
+ @Autowired
+ private ISearchParamRegistry mySearchParamRegistry;
+
private IFhirPath myFhirPath;
@Override
@@ -298,28 +302,36 @@ public class JpaBulkExportProcessor implements IBulkExportProcessor {
private LinkedHashSet getRelatedResourceTypePids(
ExportPIDIteratorParameters theParams, RuntimeResourceDefinition theDef) throws IOException {
LinkedHashSet pids = new LinkedHashSet<>();
- // expand the group pid -> list of patients in that group (list of patient pids)
- Set expandedMemberResourceIds = expandAllPatientPidsFromGroup(theParams);
- assert !expandedMemberResourceIds.isEmpty();
- Logs.getBatchTroubleshootingLog()
- .debug("{} has been expanded to members:[{}]", theParams.getGroupId(), expandedMemberResourceIds);
+ // Check if the patient compartment search parameter is active to enable export of this resource
+ RuntimeSearchParam activeSearchParam =
+ getActivePatientSearchParamForCurrentResourceType(theParams.getResourceType());
+ if (activeSearchParam != null) {
+ // expand the group pid -> list of patients in that group (list of patient pids)
+ Set expandedMemberResourceIds = expandAllPatientPidsFromGroup(theParams);
+ assert !expandedMemberResourceIds.isEmpty();
+ Logs.getBatchTroubleshootingLog()
+ .debug("{} has been expanded to members:[{}]", theParams.getGroupId(), expandedMemberResourceIds);
- // for each patient pid ->
- // search for the target resources, with their correct patient references, chunked.
- // The results will be jammed into myReadPids
- QueryChunker queryChunker = new QueryChunker<>();
- queryChunker.chunk(expandedMemberResourceIds, QUERY_CHUNK_SIZE, (idChunk) -> {
- try {
- queryResourceTypeWithReferencesToPatients(pids, idChunk, theParams, theDef);
- } catch (IOException ex) {
- // we will never see this;
- // SearchBuilder#QueryIterator does not (nor can ever) throw
- // an IOException... but Java requires the check,
- // so we'll put a log here (just in the off chance)
- ourLog.error("Couldn't close query iterator ", ex);
- throw new RuntimeException(Msg.code(2346) + "Couldn't close query iterator", ex);
- }
- });
+ // for each patient pid ->
+ // search for the target resources, with their correct patient references, chunked.
+ // The results will be jammed into myReadPids
+ QueryChunker queryChunker = new QueryChunker<>();
+ queryChunker.chunk(expandedMemberResourceIds, QUERY_CHUNK_SIZE, (idChunk) -> {
+ try {
+ queryResourceTypeWithReferencesToPatients(pids, idChunk, theParams, theDef);
+ } catch (IOException ex) {
+ // we will never see this;
+ // SearchBuilder#QueryIterator does not (nor can ever) throw
+ // an IOException... but Java requires the check,
+ // so we'll put a log here (just in the off chance)
+ ourLog.error("Couldn't close query iterator ", ex);
+ throw new RuntimeException(Msg.code(2346) + "Couldn't close query iterator", ex);
+ }
+ });
+ } else {
+ ourLog.warn("No active patient compartment search parameter(s) for resource type "
+ + theParams.getResourceType());
+ }
return pids;
}
@@ -600,6 +612,22 @@ public class JpaBulkExportProcessor implements IBulkExportProcessor {
}
}
+ private RuntimeSearchParam getActivePatientSearchParamForCurrentResourceType(String theResourceType) {
+ String activeSearchParamName = "";
+ String resourceToCheck = theResourceType;
+ if (!PATIENT_BULK_EXPORT_FORWARD_REFERENCE_RESOURCE_TYPES.contains(theResourceType)) {
+ activeSearchParamName =
+ getPatientSearchParamForCurrentResourceType(theResourceType).getName();
+ } else if ("Practitioner".equalsIgnoreCase(theResourceType)) {
+ resourceToCheck = "Patient";
+ activeSearchParamName = "general-practitioner";
+ } else if ("Organization".equalsIgnoreCase(theResourceType)) {
+ resourceToCheck = "Patient";
+ activeSearchParamName = "organization";
+ }
+ return mySearchParamRegistry.getActiveSearchParam(resourceToCheck, activeSearchParamName);
+ }
+
/**
* Must not be called for resources types listed in PATIENT_BULK_EXPORT_FORWARD_REFERENCE_RESOURCE_TYPES
*
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/Batch2SupportConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/Batch2SupportConfig.java
index 7fbf1209703..0ea5cae5175 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/Batch2SupportConfig.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/Batch2SupportConfig.java
@@ -19,16 +19,21 @@
*/
package ca.uhn.fhir.jpa.config;
+import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
+import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.api.svc.IBatch2DaoSvc;
import ca.uhn.fhir.jpa.api.svc.IDeleteExpungeSvc;
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
import ca.uhn.fhir.jpa.dao.data.IResourceLinkDao;
+import ca.uhn.fhir.jpa.dao.data.IResourceTableDao;
import ca.uhn.fhir.jpa.dao.expunge.ResourceTableFKProvider;
+import ca.uhn.fhir.jpa.dao.tx.IHapiTransactionService;
import ca.uhn.fhir.jpa.delete.batch2.DeleteExpungeSqlBuilder;
import ca.uhn.fhir.jpa.delete.batch2.DeleteExpungeSvcImpl;
import ca.uhn.fhir.jpa.reindex.Batch2DaoSvcImpl;
+import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
@@ -37,8 +42,20 @@ import javax.persistence.EntityManager;
public class Batch2SupportConfig {
@Bean
- public IBatch2DaoSvc batch2DaoSvc() {
- return new Batch2DaoSvcImpl();
+ public IBatch2DaoSvc batch2DaoSvc(
+ IResourceTableDao theResourceTableDao,
+ MatchUrlService theMatchUrlService,
+ DaoRegistry theDaoRegistry,
+ FhirContext theFhirContext,
+ IHapiTransactionService theTransactionService,
+ JpaStorageSettings theJpaStorageSettings) {
+ return new Batch2DaoSvcImpl(
+ theResourceTableDao,
+ theMatchUrlService,
+ theDaoRegistry,
+ theFhirContext,
+ theTransactionService,
+ theJpaStorageSettings);
}
@Bean
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/HapiFhirHibernateJpaDialect.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/HapiFhirHibernateJpaDialect.java
index 4e2b5d1f5c3..a926dc35c85 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/HapiFhirHibernateJpaDialect.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/HapiFhirHibernateJpaDialect.java
@@ -26,6 +26,7 @@ import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
import ca.uhn.fhir.jpa.model.entity.ResourceSearchUrlEntity;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
+import ca.uhn.fhir.system.HapiSystemProperties;
import org.hibernate.HibernateException;
import org.hibernate.PessimisticLockException;
import org.hibernate.exception.ConstraintViolationException;
@@ -71,6 +72,10 @@ public class HapiFhirHibernateJpaDialect extends HibernateJpaDialect {
messageToPrepend = theMessageToPrepend + " - ";
}
+ if (HapiSystemProperties.isUnitTestModeEnabled()) {
+ ourLog.error("Hibernate exception", theException);
+ }
+
if (theException instanceof ConstraintViolationException) {
String constraintName = ((ConstraintViolationException) theException).getConstraintName();
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/JpaConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/JpaConfig.java
index 941f2273b7c..3a44a5f8ed2 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/JpaConfig.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/JpaConfig.java
@@ -32,9 +32,7 @@ import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.api.model.ExpungeOptions;
-import ca.uhn.fhir.jpa.api.svc.IDeleteExpungeSvc;
import ca.uhn.fhir.jpa.api.svc.IIdHelperService;
-import ca.uhn.fhir.jpa.api.svc.IMdmClearHelperSvc;
import ca.uhn.fhir.jpa.api.svc.ISearchUrlJobMaintenanceSvc;
import ca.uhn.fhir.jpa.binary.interceptor.BinaryStorageInterceptor;
import ca.uhn.fhir.jpa.binary.provider.BinaryAccessProvider;
@@ -43,7 +41,6 @@ import ca.uhn.fhir.jpa.bulk.export.svc.BulkDataExportJobSchedulingHelperImpl;
import ca.uhn.fhir.jpa.bulk.export.svc.BulkExportHelperService;
import ca.uhn.fhir.jpa.bulk.imprt.api.IBulkDataImportSvc;
import ca.uhn.fhir.jpa.bulk.imprt.svc.BulkDataImportSvcImpl;
-import ca.uhn.fhir.jpa.bulk.mdm.MdmClearHelperSvcImpl;
import ca.uhn.fhir.jpa.cache.IResourceVersionSvc;
import ca.uhn.fhir.jpa.cache.ResourceVersionSvcDaoImpl;
import ca.uhn.fhir.jpa.dao.DaoSearchParamProvider;
@@ -57,6 +54,7 @@ import ca.uhn.fhir.jpa.dao.MatchResourceUrlService;
import ca.uhn.fhir.jpa.dao.ObservationLastNIndexPersistSvc;
import ca.uhn.fhir.jpa.dao.SearchBuilderFactory;
import ca.uhn.fhir.jpa.dao.TransactionProcessor;
+import ca.uhn.fhir.jpa.dao.data.IResourceModifiedDao;
import ca.uhn.fhir.jpa.dao.data.IResourceSearchUrlDao;
import ca.uhn.fhir.jpa.dao.expunge.ExpungeEverythingService;
import ca.uhn.fhir.jpa.dao.expunge.ExpungeOperation;
@@ -69,14 +67,11 @@ import ca.uhn.fhir.jpa.dao.index.DaoResourceLinkResolver;
import ca.uhn.fhir.jpa.dao.index.DaoSearchParamSynchronizer;
import ca.uhn.fhir.jpa.dao.index.IdHelperService;
import ca.uhn.fhir.jpa.dao.index.SearchParamWithInlineReferencesExtractor;
-import ca.uhn.fhir.jpa.dao.mdm.JpaMdmLinkImplFactory;
-import ca.uhn.fhir.jpa.dao.mdm.MdmLinkDaoJpaImpl;
import ca.uhn.fhir.jpa.dao.tx.HapiTransactionService;
import ca.uhn.fhir.jpa.dao.validation.SearchParameterDaoValidator;
import ca.uhn.fhir.jpa.delete.DeleteConflictFinderService;
import ca.uhn.fhir.jpa.delete.DeleteConflictService;
import ca.uhn.fhir.jpa.delete.ThreadSafeResourceDeleterSvc;
-import ca.uhn.fhir.jpa.entity.MdmLink;
import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.esr.ExternallyStoredResourceServiceRegistry;
import ca.uhn.fhir.jpa.graphql.DaoRegistryGraphQLStorageServices;
@@ -155,6 +150,7 @@ import ca.uhn.fhir.jpa.searchparam.extractor.IResourceLinkResolver;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamProvider;
import ca.uhn.fhir.jpa.sp.ISearchParamPresenceSvc;
import ca.uhn.fhir.jpa.sp.SearchParamPresenceSvcImpl;
+import ca.uhn.fhir.jpa.subscription.ResourceModifiedMessagePersistenceSvcImpl;
import ca.uhn.fhir.jpa.term.TermCodeSystemStorageSvcImpl;
import ca.uhn.fhir.jpa.term.TermConceptMappingSvcImpl;
import ca.uhn.fhir.jpa.term.TermReadSvcImpl;
@@ -169,9 +165,6 @@ import ca.uhn.fhir.jpa.util.MemoryCacheService;
import ca.uhn.fhir.jpa.util.PersistenceContextProvider;
import ca.uhn.fhir.jpa.validation.ResourceLoaderImpl;
import ca.uhn.fhir.jpa.validation.ValidationSettings;
-import ca.uhn.fhir.mdm.dao.IMdmLinkDao;
-import ca.uhn.fhir.mdm.dao.IMdmLinkImplFactory;
-import ca.uhn.fhir.mdm.svc.MdmLinkExpandSvc;
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.api.server.storage.IDeleteExpungeJobSubmitter;
@@ -181,6 +174,9 @@ import ca.uhn.fhir.rest.server.interceptor.ResponseTerminologyTranslationSvc;
import ca.uhn.fhir.rest.server.interceptor.consent.IConsentContextServices;
import ca.uhn.fhir.rest.server.interceptor.partition.RequestTenantPartitionInterceptor;
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
+import ca.uhn.fhir.subscription.api.IResourceModifiedMessagePersistenceSvc;
+import ca.uhn.fhir.util.IMetaTagSorter;
+import ca.uhn.fhir.util.MetaTagSorterAlphabetical;
import ca.uhn.hapi.converters.canonical.VersionCanonicalizer;
import org.hl7.fhir.common.hapi.validation.support.UnknownCodeSystemWarningValidationSupport;
import org.hl7.fhir.utilities.graphql.IGraphQLStorageServices;
@@ -216,7 +212,8 @@ import javax.annotation.Nullable;
JpaBulkExportConfig.class,
SearchConfig.class,
PackageLoaderConfig.class,
- EnversAuditConfig.class
+ EnversAuditConfig.class,
+ MdmJpaConfig.class
})
public class JpaConfig {
public static final String JPA_VALIDATION_SUPPORT_CHAIN = "myJpaValidationSupportChain";
@@ -475,11 +472,6 @@ public class JpaConfig {
return new RequestTenantPartitionInterceptor();
}
- @Bean
- public MdmLinkExpandSvc mdmLinkExpandSvc() {
- return new MdmLinkExpandSvc();
- }
-
@Bean
@Lazy
public TerminologyUploaderProvider terminologyUploaderProvider() {
@@ -853,16 +845,6 @@ public class JpaConfig {
return new ObservationLastNIndexPersistSvc();
}
- @Bean
- public IMdmLinkDao mdmLinkDao() {
- return new MdmLinkDaoJpaImpl();
- }
-
- @Bean
- IMdmLinkImplFactory mdmLinkImplFactory() {
- return new JpaMdmLinkImplFactory();
- }
-
@Bean
@Scope("prototype")
public PersistenceContextProvider persistenceContextProvider() {
@@ -888,7 +870,17 @@ public class JpaConfig {
}
@Bean
- public IMdmClearHelperSvc helperSvc(IDeleteExpungeSvc theDeleteExpungeSvc) {
- return new MdmClearHelperSvcImpl(theDeleteExpungeSvc);
+ public IResourceModifiedMessagePersistenceSvc subscriptionMessagePersistence(
+ FhirContext theFhirContext,
+ IResourceModifiedDao theIResourceModifiedDao,
+ DaoRegistry theDaoRegistry,
+ HapiTransactionService theHapiTransactionService) {
+ return new ResourceModifiedMessagePersistenceSvcImpl(
+ theFhirContext, theIResourceModifiedDao, theDaoRegistry, theHapiTransactionService);
+ }
+
+ @Bean
+ public IMetaTagSorter metaTagSorter() {
+ return new MetaTagSorterAlphabetical();
}
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/MdmJpaConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/MdmJpaConfig.java
new file mode 100644
index 00000000000..c9727845114
--- /dev/null
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/MdmJpaConfig.java
@@ -0,0 +1,57 @@
+/*-
+ * #%L
+ * HAPI FHIR JPA Server
+ * %%
+ * Copyright (C) 2014 - 2023 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%
+ */
+package ca.uhn.fhir.jpa.config;
+
+import ca.uhn.fhir.jpa.api.svc.IDeleteExpungeSvc;
+import ca.uhn.fhir.jpa.api.svc.IMdmClearHelperSvc;
+import ca.uhn.fhir.jpa.bulk.mdm.MdmClearHelperSvcImpl;
+import ca.uhn.fhir.jpa.dao.mdm.JpaMdmLinkImplFactory;
+import ca.uhn.fhir.jpa.dao.mdm.MdmLinkDaoJpaImpl;
+import ca.uhn.fhir.jpa.entity.MdmLink;
+import ca.uhn.fhir.jpa.model.dao.JpaPid;
+import ca.uhn.fhir.mdm.dao.IMdmLinkDao;
+import ca.uhn.fhir.mdm.dao.IMdmLinkImplFactory;
+import ca.uhn.fhir.mdm.svc.MdmLinkExpandSvc;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class MdmJpaConfig {
+
+ @Bean
+ public MdmLinkExpandSvc mdmLinkExpandSvc() {
+ return new MdmLinkExpandSvc();
+ }
+
+ @Bean
+ public IMdmLinkDao mdmLinkDao() {
+ return new MdmLinkDaoJpaImpl();
+ }
+
+ @Bean
+ public IMdmLinkImplFactory mdmLinkImplFactory() {
+ return new JpaMdmLinkImplFactory();
+ }
+
+ @Bean
+ public IMdmClearHelperSvc helperSvc(IDeleteExpungeSvc theDeleteExpungeSvc) {
+ return new MdmClearHelperSvcImpl(theDeleteExpungeSvc);
+ }
+}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/ValidationSupportConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/ValidationSupportConfig.java
index 3cbd8bc5ddf..5fffa5d73c6 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/ValidationSupportConfig.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/ValidationSupportConfig.java
@@ -23,6 +23,7 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.FhirVersionEnum;
import ca.uhn.fhir.context.support.DefaultProfileValidationSupport;
import ca.uhn.fhir.context.support.IValidationSupport;
+import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.dao.JpaPersistedResourceValidationSupport;
import ca.uhn.fhir.jpa.validation.JpaValidationSupportChain;
@@ -30,6 +31,7 @@ import ca.uhn.fhir.jpa.validation.ValidatorPolicyAdvisor;
import ca.uhn.fhir.jpa.validation.ValidatorResourceFetcher;
import ca.uhn.fhir.validation.IInstanceValidatorModule;
import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport;
+import org.hl7.fhir.common.hapi.validation.support.InMemoryTerminologyServerValidationSupport;
import org.hl7.fhir.common.hapi.validation.support.ValidationSupportChain;
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
import org.hl7.fhir.common.hapi.validation.validator.HapiToHl7OrgDstu2ValidatingSupportWrapper;
@@ -45,6 +47,15 @@ public class ValidationSupportConfig {
return new DefaultProfileValidationSupport(theFhirContext);
}
+ @Bean
+ public InMemoryTerminologyServerValidationSupport inMemoryTerminologyServerValidationSupport(
+ FhirContext theFhirContext, JpaStorageSettings theStorageSettings) {
+ InMemoryTerminologyServerValidationSupport retVal =
+ new InMemoryTerminologyServerValidationSupport(theFhirContext);
+ retVal.setIssueSeverityForCodeDisplayMismatch(theStorageSettings.getIssueSeverityForCodeDisplayMismatch());
+ return retVal;
+ }
+
@Bean(name = JpaConfig.JPA_VALIDATION_SUPPORT_CHAIN)
public JpaValidationSupportChain jpaValidationSupportChain(FhirContext theFhirContext) {
return new JpaValidationSupportChain(theFhirContext);
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java
index 4e0691dd8a4..13dfc7b25f0 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java
@@ -32,7 +32,6 @@ import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
import ca.uhn.fhir.interceptor.api.Pointcut;
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
import ca.uhn.fhir.jpa.api.config.JpaStorageSettings;
-import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
import ca.uhn.fhir.jpa.api.dao.IDao;
import ca.uhn.fhir.jpa.api.dao.IJpaDao;
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
@@ -137,6 +136,7 @@ import org.springframework.transaction.support.TransactionSynchronization;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate;
+import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
@@ -166,6 +166,7 @@ import javax.xml.stream.events.XMLEvent;
import static java.util.Objects.isNull;
import static java.util.Objects.nonNull;
+import static org.apache.commons.collections4.CollectionUtils.isEqualCollection;
import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.left;
@@ -226,9 +227,6 @@ public abstract class BaseHapiFhirDao extends BaseStora
@Autowired
protected IInterceptorBroadcaster myInterceptorBroadcaster;
- @Autowired
- protected DaoRegistry myDaoRegistry;
-
@Autowired
protected InMemoryResourceMatcher myInMemoryResourceMatcher;
@@ -302,7 +300,7 @@ public abstract class BaseHapiFhirDao extends BaseStora
}
}
- private void extractTagsHapi(
+ private void extractHapiTags(
TransactionDetails theTransactionDetails,
IResource theResource,
ResourceTable theEntity,
@@ -335,8 +333,8 @@ public abstract class BaseHapiFhirDao extends BaseStora
next.getSystemElement().getValue(),
next.getCodeElement().getValue(),
next.getDisplayElement().getValue(),
- null,
- null);
+ next.getVersionElement().getValue(),
+ next.getUserSelectedElement().getValue());
if (def != null) {
ResourceTag tag = theEntity.addTag(def);
allDefs.add(tag);
@@ -359,7 +357,7 @@ public abstract class BaseHapiFhirDao extends BaseStora
}
}
- private void extractTagsRi(
+ private void extractRiTags(
TransactionDetails theTransactionDetails,
IAnyResource theResource,
ResourceTable theEntity,
@@ -416,6 +414,25 @@ public abstract class BaseHapiFhirDao extends BaseStora
}
}
+ private void extractProfileTags(
+ TransactionDetails theTransactionDetails,
+ IBaseResource theResource,
+ ResourceTable theEntity,
+ Set theAllTags) {
+ RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
+ if (!def.isStandardType()) {
+ String profile = def.getResourceProfile("");
+ if (isNotBlank(profile)) {
+ TagDefinition profileDef = getTagOrNull(
+ theTransactionDetails, TagTypeEnum.PROFILE, NS_JPA_PROFILE, profile, null, null, null);
+
+ ResourceTag tag = theEntity.addTag(profileDef);
+ theAllTags.add(tag);
+ theEntity.setHasTags(true);
+ }
+ }
+ }
+
private Set getAllTagDefinitions(ResourceTable theEntity) {
HashSet retVal = Sets.newHashSet();
if (theEntity.isHasTags()) {
@@ -546,11 +563,9 @@ public abstract class BaseHapiFhirDao extends BaseStora
}
});
} catch (Exception ex) {
- // transaction template can fail if connections to db are exhausted
- // and/or timeout
- ourLog.warn("Transaction failed with: "
- + ex.getMessage() + ". "
- + "Transaction will rollback and be reattempted.");
+ // transaction template can fail if connections to db are exhausted and/or timeout
+ ourLog.warn(
+ "Transaction failed with: {}. Transaction will rollback and be reattempted.", ex.getMessage());
retVal = null;
}
count++;
@@ -680,7 +695,7 @@ public abstract class BaseHapiFhirDao extends BaseStora
}
String hashSha256 = hashCode.toString();
- if (hashSha256.equals(theEntity.getHashSha256()) == false) {
+ if (!hashSha256.equals(theEntity.getHashSha256())) {
changed = true;
}
theEntity.setHashSha256(hashSha256);
@@ -764,7 +779,7 @@ public abstract class BaseHapiFhirDao extends BaseStora
byte[] resourceBinary;
switch (encoding) {
case JSON:
- resourceBinary = encodedResource.getBytes(Charsets.UTF_8);
+ resourceBinary = encodedResource.getBytes(StandardCharsets.UTF_8);
break;
case JSONC:
resourceBinary = GZipUtil.compress(encodedResource);
@@ -845,39 +860,36 @@ public abstract class BaseHapiFhirDao extends BaseStora
RequestDetails theRequest,
IBaseResource theResource,
ResourceTable theEntity) {
- Set allDefs = new HashSet<>();
- Set allTagsOld = getAllTagDefinitions(theEntity);
+ Set allResourceTagsFromTheResource = new HashSet<>();
+ Set allOriginalResourceTagsFromTheEntity = getAllTagDefinitions(theEntity);
if (theResource instanceof IResource) {
- extractTagsHapi(theTransactionDetails, (IResource) theResource, theEntity, allDefs);
+ extractHapiTags(theTransactionDetails, (IResource) theResource, theEntity, allResourceTagsFromTheResource);
} else {
- extractTagsRi(theTransactionDetails, (IAnyResource) theResource, theEntity, allDefs);
+ extractRiTags(theTransactionDetails, (IAnyResource) theResource, theEntity, allResourceTagsFromTheResource);
}
- RuntimeResourceDefinition def = myContext.getResourceDefinition(theResource);
- if (!def.isStandardType()) {
- String profile = def.getResourceProfile("");
- if (isNotBlank(profile)) {
- TagDefinition profileDef = getTagOrNull(
- theTransactionDetails, TagTypeEnum.PROFILE, NS_JPA_PROFILE, profile, null, null, null);
+ extractProfileTags(theTransactionDetails, theResource, theEntity, allResourceTagsFromTheResource);
- ResourceTag tag = theEntity.addTag(profileDef);
- allDefs.add(tag);
- theEntity.setHasTags(true);
- }
- }
+ // the extract[Hapi|Ri|Profile]Tags methods above will have populated the allResourceTagsFromTheResource Set
+ // AND
+ // added all tags from theResource.meta.tags to theEntity.meta.tags. the next steps are to:
+ // 1- remove duplicates;
+ // 2- remove tags from theEntity that are not present in theResource if header HEADER_META_SNAPSHOT_MODE
+ // is present in the request;
+ //
+ Set allResourceTagsNewAndOldFromTheEntity = getAllTagDefinitions(theEntity);
+ Set allTagDefinitionsPresent = new HashSet<>();
- Set allTagsNew = getAllTagDefinitions(theEntity);
- Set allDefsPresent = new HashSet<>();
- allTagsNew.forEach(tag -> {
+ allResourceTagsNewAndOldFromTheEntity.forEach(tag -> {
// Don't keep duplicate tags
- if (!allDefsPresent.add(tag.getTag())) {
+ if (!allTagDefinitionsPresent.add(tag.getTag())) {
theEntity.getTags().remove(tag);
}
// Drop any tags that have been removed
- if (!allDefs.contains(tag)) {
+ if (!allResourceTagsFromTheResource.contains(tag)) {
if (shouldDroppedTagBeRemovedOnUpdate(theRequest, tag)) {
theEntity.getTags().remove(tag);
} else if (HapiExtensions.EXT_SUBSCRIPTION_MATCHING_STRATEGY.equals(
@@ -887,21 +899,33 @@ public abstract class BaseHapiFhirDao extends BaseStora
}
});
- // Update the resource to contain the old tags
- allTagsOld.forEach(tag -> {
- IBaseCoding iBaseCoding = theResource
- .getMeta()
- .addTag()
- .setCode(tag.getTag().getCode())
- .setSystem(tag.getTag().getSystem())
- .setVersion(tag.getTag().getVersion());
- if (tag.getTag().getUserSelected() != null) {
- iBaseCoding.setUserSelected(tag.getTag().getUserSelected());
+ // at this point, theEntity.meta.tags will be up to date:
+ // 1- it was stripped from tags that needed removing;
+ // 2- it has new tags from a resource update through theResource;
+ // 3- it has tags from the previous version;
+ //
+ // Since tags are merged on updates, we add tags from theEntity that theResource does not have
+ Set allUpdatedResourceTagsNewAndOldMinusRemovalsFromTheEntity = getAllTagDefinitions(theEntity);
+
+ allUpdatedResourceTagsNewAndOldMinusRemovalsFromTheEntity.forEach(aResourcetag -> {
+ if (!allResourceTagsFromTheResource.contains(aResourcetag)) {
+ IBaseCoding iBaseCoding = theResource
+ .getMeta()
+ .addTag()
+ .setCode(aResourcetag.getTag().getCode())
+ .setSystem(aResourcetag.getTag().getSystem())
+ .setVersion(aResourcetag.getTag().getVersion());
+
+ allResourceTagsFromTheResource.add(aResourcetag);
+
+ if (aResourcetag.getTag().getUserSelected() != null) {
+ iBaseCoding.setUserSelected(aResourcetag.getTag().getUserSelected());
+ }
}
});
- theEntity.setHasTags(!allTagsNew.isEmpty());
- return !allTagsOld.equals(allTagsNew);
+ theEntity.setHasTags(!allUpdatedResourceTagsNewAndOldMinusRemovalsFromTheEntity.isEmpty());
+ return !isEqualCollection(allOriginalResourceTagsFromTheEntity, allResourceTagsFromTheResource);
}
/**
@@ -947,7 +971,7 @@ public abstract class BaseHapiFhirDao extends BaseStora
* The default implementation removes any profile declarations, but leaves tags and security labels in place. Subclasses may choose to override and change this behaviour.
*
*