Fix changelog syntax. Merge current master.
This commit is contained in:
commit
ad6f7a204c
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
package ca.uhn.fhir.context;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2021 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%
|
||||
*/
|
||||
|
||||
public enum ComboSearchParamType {
|
||||
|
||||
UNIQUE,
|
||||
NON_UNIQUE
|
||||
|
||||
}
|
|
@ -416,7 +416,7 @@ class ModelScanner {
|
|||
if (theResourceDef.isStandardType()) {
|
||||
url = "http://hl7.org/fhir/SearchParameter/" + theResourceDef.getName().toLowerCase() + "-" + searchParam.name();
|
||||
}
|
||||
RuntimeSearchParam param = new RuntimeSearchParam(null, url, searchParam.name(), searchParam.description(), searchParam.path(), paramType, providesMembershipInCompartments, toTargetList(searchParam.target()), RuntimeSearchParamStatusEnum.ACTIVE, false, components, base);
|
||||
RuntimeSearchParam param = new RuntimeSearchParam(null, url, searchParam.name(), searchParam.description(), searchParam.path(), paramType, providesMembershipInCompartments, toTargetList(searchParam.target()), RuntimeSearchParamStatusEnum.ACTIVE, null, components, base);
|
||||
theResourceDef.addSearchParam(param);
|
||||
nameToParam.put(param.getName(), param);
|
||||
}
|
||||
|
|
|
@ -10,6 +10,7 @@ import org.hl7.fhir.instance.model.api.IBaseExtension;
|
|||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
|
@ -55,7 +56,7 @@ public class RuntimeSearchParam {
|
|||
private final RuntimeSearchParamStatusEnum myStatus;
|
||||
private final String myUri;
|
||||
private final Map<String, List<IBaseExtension<?, ?>>> myExtensions = new HashMap<>();
|
||||
private final boolean myUnique;
|
||||
private final ComboSearchParamType myComboSearchParamType;
|
||||
private final List<Component> myComponents;
|
||||
private IPhoneticEncoder myPhoneticEncoder;
|
||||
|
||||
|
@ -64,20 +65,20 @@ public class RuntimeSearchParam {
|
|||
*/
|
||||
public RuntimeSearchParam(IIdType theId, String theUri, String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType,
|
||||
Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus, Collection<String> theBase) {
|
||||
this(theId, theUri, theName, theDescription, thePath, theParamType, theProvidesMembershipInCompartments, theTargets, theStatus, false, Collections.emptyList(), theBase);
|
||||
this(theId, theUri, theName, theDescription, thePath, theParamType, theProvidesMembershipInCompartments, theTargets, theStatus, null, Collections.emptyList(), theBase);
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy constructor
|
||||
*/
|
||||
public RuntimeSearchParam(RuntimeSearchParam theSp) {
|
||||
this(theSp.getId(), theSp.getUri(), theSp.getName(), theSp.getDescription(), theSp.getPath(), theSp.getParamType(), theSp.getProvidesMembershipInCompartments(), theSp.getTargets(), theSp.getStatus(), theSp.isUnique(), theSp.getComponents(), theSp.getBase());
|
||||
this(theSp.getId(), theSp.getUri(), theSp.getName(), theSp.getDescription(), theSp.getPath(), theSp.getParamType(), theSp.getProvidesMembershipInCompartments(), theSp.getTargets(), theSp.getStatus(), theSp.getComboSearchParamType(), theSp.getComponents(), theSp.getBase());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public RuntimeSearchParam(IIdType theId, String theUri, String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus, boolean theUnique, List<Component> theComponents, Collection<String> theBase) {
|
||||
public RuntimeSearchParam(IIdType theId, String theUri, String theName, String theDescription, String thePath, RestSearchParameterTypeEnum theParamType, Set<String> theProvidesMembershipInCompartments, Set<String> theTargets, RuntimeSearchParamStatusEnum theStatus, ComboSearchParamType theComboSearchParamType, List<Component> theComponents, Collection<String> theBase) {
|
||||
super();
|
||||
|
||||
myId = theId;
|
||||
|
@ -110,7 +111,7 @@ public class RuntimeSearchParam {
|
|||
} else {
|
||||
myBase = Collections.unmodifiableSet(new HashSet<>(theBase));
|
||||
}
|
||||
myUnique = theUnique;
|
||||
myComboSearchParamType = theComboSearchParamType;
|
||||
if (theComponents != null) {
|
||||
myComponents = Collections.unmodifiableList(theComponents);
|
||||
} else {
|
||||
|
@ -122,8 +123,12 @@ public class RuntimeSearchParam {
|
|||
return myComponents;
|
||||
}
|
||||
|
||||
public boolean isUnique() {
|
||||
return myUnique;
|
||||
/**
|
||||
* Returns <code>null</code> if this is not a combo search param type
|
||||
*/
|
||||
@Nullable
|
||||
public ComboSearchParamType getComboSearchParamType() {
|
||||
return myComboSearchParamType;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -3,14 +3,14 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-bom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>HAPI FHIR BOM</name>
|
||||
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-cli</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../../hapi-deployable-pom</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -381,6 +381,17 @@
|
|||
"lat": 49.234000,
|
||||
"lon": -123.065890,
|
||||
"added": "2021-06-29"
|
||||
},
|
||||
{
|
||||
"title": "Innovattic",
|
||||
"description": "Creating remote monitoring solutions for several hospitals in the Netherlands.",
|
||||
"contactName": "Lauwerens Metz",
|
||||
"contactEmail": "info@innovattic.com",
|
||||
"link": "https://innovattic.com/",
|
||||
"city": "Delft, The Netherlands",
|
||||
"lat": 52.01804,
|
||||
"lon": 4.354307,
|
||||
"added": "2021-07-15"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
type: change
|
||||
issue: 2791
|
||||
title: "Identifier maximum length increased from 200 to 500. This specifically applies to table HFJ_IDX_CMP_STRING_UNIQ."
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 2794
|
||||
title: "When providing links for placeholder creation, DaoResourceLinkResolver expects just a single 'identifier=value' param, but it can be additional data, s.a. tags, extra identifiers, etc."
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 2797
|
||||
title: "When initiating a FHIR bulk export, if more than one `_typeFilter` parameter was supplied
|
||||
only the first one was respected. This has been corrected."
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
type: add
|
||||
issue: 2800
|
||||
title: "Allowed the optional inclusion of the LOINC Consumer Names archive in addition to
|
||||
the main LOINC distribution. If it is supplied, the consumer names CSV file will be scanned,
|
||||
and all consumer names will be added to uploaded Concepts as additional designations"
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
type: add
|
||||
issue: 2803
|
||||
title: "Allowed the optional inclusion of the LOINC Linguistic Variants archive in addition to
|
||||
the main LOINC distribution. If it is supplied, all linguistic variants files will be scanned,
|
||||
and all translations will be added to uploaded Concepts as additional designations"
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
type: change
|
||||
issue: 2805
|
||||
title: "When the contents of a package are corrupt, the error messages now identify the corrupt element"
|
|
@ -0,0 +1,4 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 2808
|
||||
title: "Loading packages would fail when partitioning was enabled with unnamed partitions. This has been fixed."
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 2810
|
||||
title: "An issue in the FHIRPath evaluator prevented Encounters from being stored when using the new
|
||||
PatientIdPartitionInterceptor. This has been corrected."
|
|
@ -165,7 +165,7 @@ then the above `candidateSearchParams` and `candidateFilterSearchParams` would r
|
|||
|
||||
### matchFields
|
||||
|
||||
Once the match candidates have been found, they are then each compared to the incoming Patient resource. This comparison is made across a list of `matchField`s. Each matchField returns `true` or `false` indicating whether the candidate and the incoming Patient match on that field. There are two types of matchFields: `matcher` and `similarity`. `matcher` matchFields return a `true` or `false` directly, whereas `similarity` matchFields return a score between 0.0 (no match) and 1.0 (exact match) and this score is translated to a `true/false` via a `matchThreshold`. E.g. if a `JARO_WINKLER` matchField is configured with a `matchThreshold` of 0.8 then that matchField will only return `true` if the `JARO_WINKLER` similarity evaluates to a score >= 8.0.
|
||||
Once the match candidates have been found, they are then each compared to the incoming Patient resource. This comparison is made across a list of `matchField`s. Each matchField returns `true` or `false` indicating whether the candidate and the incoming Patient match on that field. There are two types of matchFields: `matcher` and `similarity`. `matcher` matchFields return a `true` or `false` directly, whereas `similarity` matchFields return a score between 0.0 (no match) and 1.0 (exact match) and this score is translated to a `true/false` via a `matchThreshold`. E.g. if a `JARO_WINKLER` matchField is configured with a `matchThreshold` of 0.8 then that matchField will only return `true` if the `JARO_WINKLER` similarity evaluates to a score >= 0.8.
|
||||
|
||||
By default, all matchFields have `exact=false` which means that they will have all diacritical marks removed and all letters will be converted to upper case before matching. `exact=true` can be added to any matchField to compare the strings as they are originally capitalized and accented.
|
||||
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -85,7 +85,7 @@ public class BulkDataExportProvider {
|
|||
@OperationParam(name = JpaConstants.PARAM_EXPORT_OUTPUT_FORMAT, min = 0, max = 1, typeName = "string") IPrimitiveType<String> theOutputFormat,
|
||||
@OperationParam(name = JpaConstants.PARAM_EXPORT_TYPE, min = 0, max = 1, typeName = "string") IPrimitiveType<String> theType,
|
||||
@OperationParam(name = JpaConstants.PARAM_EXPORT_SINCE, min = 0, max = 1, typeName = "instant") IPrimitiveType<Date> theSince,
|
||||
@OperationParam(name = JpaConstants.PARAM_EXPORT_TYPE_FILTER, min = 0, max = 1, typeName = "string") IPrimitiveType<String> theTypeFilter,
|
||||
@OperationParam(name = JpaConstants.PARAM_EXPORT_TYPE_FILTER, min = 0, max = OperationParam.MAX_UNLIMITED, typeName = "string") List<IPrimitiveType<String>> theTypeFilter,
|
||||
ServletRequestDetails theRequestDetails
|
||||
) {
|
||||
validatePreferAsyncHeader(theRequestDetails);
|
||||
|
@ -113,7 +113,7 @@ public class BulkDataExportProvider {
|
|||
@OperationParam(name = JpaConstants.PARAM_EXPORT_OUTPUT_FORMAT, min = 0, max = 1, typeName = "string") IPrimitiveType<String> theOutputFormat,
|
||||
@OperationParam(name = JpaConstants.PARAM_EXPORT_TYPE, min = 0, max = 1, typeName = "string") IPrimitiveType<String> theType,
|
||||
@OperationParam(name = JpaConstants.PARAM_EXPORT_SINCE, min = 0, max = 1, typeName = "instant") IPrimitiveType<Date> theSince,
|
||||
@OperationParam(name = JpaConstants.PARAM_EXPORT_TYPE_FILTER, min = 0, max = 1, typeName = "string") IPrimitiveType<String> theTypeFilter,
|
||||
@OperationParam(name = JpaConstants.PARAM_EXPORT_TYPE_FILTER, min = 0, max = OperationParam.MAX_UNLIMITED, typeName = "string") List<IPrimitiveType<String>> theTypeFilter,
|
||||
@OperationParam(name = JpaConstants.PARAM_EXPORT_MDM, min = 0, max = 1, typeName = "boolean") IPrimitiveType<Boolean> theMdm,
|
||||
ServletRequestDetails theRequestDetails
|
||||
) {
|
||||
|
@ -151,7 +151,7 @@ public class BulkDataExportProvider {
|
|||
@OperationParam(name = JpaConstants.PARAM_EXPORT_OUTPUT_FORMAT, min = 0, max = 1, typeName = "string") IPrimitiveType<String> theOutputFormat,
|
||||
@OperationParam(name = JpaConstants.PARAM_EXPORT_TYPE, min = 0, max = 1, typeName = "string") IPrimitiveType<String> theType,
|
||||
@OperationParam(name = JpaConstants.PARAM_EXPORT_SINCE, min = 0, max = 1, typeName = "instant") IPrimitiveType<Date> theSince,
|
||||
@OperationParam(name = JpaConstants.PARAM_EXPORT_TYPE_FILTER, min = 0, max = 1, typeName = "string") IPrimitiveType<String> theTypeFilter,
|
||||
@OperationParam(name = JpaConstants.PARAM_EXPORT_TYPE_FILTER, min = 0, max = OperationParam.MAX_UNLIMITED, typeName = "string") List<IPrimitiveType<String>> theTypeFilter,
|
||||
ServletRequestDetails theRequestDetails
|
||||
) {
|
||||
validatePreferAsyncHeader(theRequestDetails);
|
||||
|
@ -218,11 +218,11 @@ public class BulkDataExportProvider {
|
|||
}
|
||||
}
|
||||
|
||||
private BulkDataExportOptions buildSystemBulkExportOptions(IPrimitiveType<String> theOutputFormat, IPrimitiveType<String> theType, IPrimitiveType<Date> theSince, IPrimitiveType<String> theTypeFilter) {
|
||||
private BulkDataExportOptions buildSystemBulkExportOptions(IPrimitiveType<String> theOutputFormat, IPrimitiveType<String> theType, IPrimitiveType<Date> theSince, List<IPrimitiveType<String>> theTypeFilter) {
|
||||
return buildBulkDataExportOptions(theOutputFormat, theType, theSince, theTypeFilter, BulkDataExportOptions.ExportStyle.SYSTEM);
|
||||
}
|
||||
|
||||
private BulkDataExportOptions buildGroupBulkExportOptions(IPrimitiveType<String> theOutputFormat, IPrimitiveType<String> theType, IPrimitiveType<Date> theSince, IPrimitiveType<String> theTypeFilter, IIdType theGroupId, IPrimitiveType<Boolean> theExpandMdm) {
|
||||
private BulkDataExportOptions buildGroupBulkExportOptions(IPrimitiveType<String> theOutputFormat, IPrimitiveType<String> theType, IPrimitiveType<Date> theSince, List<IPrimitiveType<String>> theTypeFilter, IIdType theGroupId, IPrimitiveType<Boolean> theExpandMdm) {
|
||||
BulkDataExportOptions bulkDataExportOptions = buildBulkDataExportOptions(theOutputFormat, theType, theSince, theTypeFilter, BulkDataExportOptions.ExportStyle.GROUP);
|
||||
bulkDataExportOptions.setGroupId(theGroupId);
|
||||
|
||||
|
@ -235,11 +235,11 @@ public class BulkDataExportProvider {
|
|||
return bulkDataExportOptions;
|
||||
}
|
||||
|
||||
private BulkDataExportOptions buildPatientBulkExportOptions(IPrimitiveType<String> theOutputFormat, IPrimitiveType<String> theType, IPrimitiveType<Date> theSince, IPrimitiveType<String> theTypeFilter) {
|
||||
private BulkDataExportOptions buildPatientBulkExportOptions(IPrimitiveType<String> theOutputFormat, IPrimitiveType<String> theType, IPrimitiveType<Date> theSince, List<IPrimitiveType<String>> theTypeFilter) {
|
||||
return buildBulkDataExportOptions(theOutputFormat, theType, theSince, theTypeFilter, BulkDataExportOptions.ExportStyle.PATIENT);
|
||||
}
|
||||
|
||||
private BulkDataExportOptions buildBulkDataExportOptions(IPrimitiveType<String> theOutputFormat, IPrimitiveType<String> theType, IPrimitiveType<Date> theSince, IPrimitiveType<String> theTypeFilter, BulkDataExportOptions.ExportStyle theExportStyle) {
|
||||
private BulkDataExportOptions buildBulkDataExportOptions(IPrimitiveType<String> theOutputFormat, IPrimitiveType<String> theType, IPrimitiveType<Date> theSince, List<IPrimitiveType<String>> theTypeFilter, BulkDataExportOptions.ExportStyle theExportStyle) {
|
||||
String outputFormat = theOutputFormat != null ? theOutputFormat.getValueAsString() : null;
|
||||
|
||||
Set<String> resourceTypes = null;
|
||||
|
@ -285,17 +285,22 @@ public class BulkDataExportProvider {
|
|||
}
|
||||
}
|
||||
|
||||
private Set<String> splitTypeFilters(IPrimitiveType<String> theTypeFilter) {
|
||||
private Set<String> splitTypeFilters(List<IPrimitiveType<String>> theTypeFilter) {
|
||||
if (theTypeFilter== null) {
|
||||
return null;
|
||||
}
|
||||
String typeFilterSring = theTypeFilter.getValueAsString();
|
||||
String[] typeFilters = typeFilterSring.split(FARM_TO_TABLE_TYPE_FILTER_REGEX);
|
||||
if (typeFilters == null || typeFilters.length == 0) {
|
||||
return null;
|
||||
|
||||
Set<String> retVal = new HashSet<>();
|
||||
|
||||
for (IPrimitiveType<String> next : theTypeFilter) {
|
||||
String typeFilterString = next.getValueAsString();
|
||||
Arrays
|
||||
.stream(typeFilterString.split(FARM_TO_TABLE_TYPE_FILTER_REGEX))
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.forEach(t->retVal.add(t));
|
||||
}
|
||||
|
||||
return new HashSet<>(Arrays.asList(typeFilters));
|
||||
return retVal;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -94,7 +94,8 @@ import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
|
|||
import ca.uhn.fhir.jpa.search.StaleSearchDeletingSvcImpl;
|
||||
import ca.uhn.fhir.jpa.search.builder.QueryStack;
|
||||
import ca.uhn.fhir.jpa.search.builder.SearchBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.CompositeUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ComboNonUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ComboUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.CoordsPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.DatePredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ForcedIdPredicateBuilder;
|
||||
|
@ -609,8 +610,14 @@ public abstract class BaseConfig {
|
|||
|
||||
@Bean
|
||||
@Scope("prototype")
|
||||
public CompositeUniqueSearchParameterPredicateBuilder newCompositeUniqueSearchParameterPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
return new CompositeUniqueSearchParameterPredicateBuilder(theSearchSqlBuilder);
|
||||
public ComboUniqueSearchParameterPredicateBuilder newComboUniqueSearchParameterPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
return new ComboUniqueSearchParameterPredicateBuilder(theSearchSqlBuilder);
|
||||
}
|
||||
|
||||
@Bean
|
||||
@Scope("prototype")
|
||||
public ComboNonUniqueSearchParameterPredicateBuilder newComboNonUniqueSearchParameterPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
return new ComboNonUniqueSearchParameterPredicateBuilder(theSearchSqlBuilder);
|
||||
}
|
||||
|
||||
@Bean
|
||||
|
|
|
@ -23,7 +23,7 @@ package ca.uhn.fhir.jpa.config;
|
|||
import ca.uhn.fhir.i18n.HapiLocalizer;
|
||||
import ca.uhn.fhir.jpa.model.entity.ForcedId;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
||||
import org.hibernate.HibernateException;
|
||||
import org.hibernate.PessimisticLockException;
|
||||
|
@ -81,7 +81,7 @@ public class HapiFhirHibernateJpaDialect extends HibernateJpaDialect {
|
|||
if (constraintName.contains(ResourceHistoryTable.IDX_RESVER_ID_VER)) {
|
||||
throw new ResourceVersionConflictException(messageToPrepend + myLocalizer.getMessage(HapiFhirHibernateJpaDialect.class, "resourceVersionConstraintFailure"));
|
||||
}
|
||||
if (constraintName.contains(ResourceIndexedCompositeStringUnique.IDX_IDXCMPSTRUNIQ_STRING)) {
|
||||
if (constraintName.contains(ResourceIndexedComboStringUnique.IDX_IDXCMPSTRUNIQ_STRING)) {
|
||||
throw new ResourceVersionConflictException(messageToPrepend + myLocalizer.getMessage(HapiFhirHibernateJpaDialect.class, "resourceIndexedCompositeStringUniqueConstraintFailure"));
|
||||
}
|
||||
if (constraintName.contains(ForcedId.IDX_FORCEDID_TYPE_FID)) {
|
||||
|
|
|
@ -129,7 +129,6 @@ import javax.persistence.TypedQuery;
|
|||
import javax.persistence.criteria.CriteriaBuilder;
|
||||
import javax.persistence.criteria.CriteriaQuery;
|
||||
import javax.persistence.criteria.Root;
|
||||
import javax.validation.constraints.Null;
|
||||
import javax.xml.stream.events.Characters;
|
||||
import javax.xml.stream.events.XMLEvent;
|
||||
import java.util.ArrayList;
|
||||
|
@ -1404,7 +1403,7 @@ public abstract class BaseHapiFhirDao<T extends IBaseResource> extends BaseStora
|
|||
}
|
||||
|
||||
// Synchronize composite params
|
||||
mySearchParamWithInlineReferencesExtractor.storeCompositeStringUniques(newParams, entity, existingParams);
|
||||
mySearchParamWithInlineReferencesExtractor.storeUniqueComboParameters(newParams, entity, existingParams);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.dao;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.ComboSearchParamType;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
|
@ -42,7 +43,7 @@ import ca.uhn.fhir.jpa.entity.ResourceSearchView;
|
|||
import ca.uhn.fhir.jpa.interceptor.JpaPreResourceAccessDetails;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTag;
|
||||
|
@ -868,9 +869,11 @@ public class LegacySearchBuilder implements ISearchBuilder {
|
|||
// Since we're going to remove elements below
|
||||
theParams.values().forEach(nextAndList -> ensureSubListsAreWritable(nextAndList));
|
||||
|
||||
List<RuntimeSearchParam> activeUniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(myResourceName, theParams.keySet());
|
||||
List<RuntimeSearchParam> activeUniqueSearchParams = mySearchParamRegistry.getActiveComboSearchParams(myResourceName, theParams.keySet());
|
||||
if (activeUniqueSearchParams.size() > 0) {
|
||||
|
||||
Validate.isTrue(activeUniqueSearchParams.get(0).getComboSearchParamType()== ComboSearchParamType.UNIQUE, "Non unique combo parameters are not supported with the legacy search builder");
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(myResourceName);
|
||||
sb.append("?");
|
||||
|
@ -943,7 +946,7 @@ public class LegacySearchBuilder implements ISearchBuilder {
|
|||
}
|
||||
|
||||
private void addPredicateCompositeStringUnique(@Nonnull SearchParameterMap theParams, String theIndexedString, RequestPartitionId theRequestPartitionId) {
|
||||
From<?, ResourceIndexedCompositeStringUnique> join = myQueryStack.createJoin(SearchBuilderJoinEnum.COMPOSITE_UNIQUE, null);
|
||||
From<?, ResourceIndexedComboStringUnique> join = myQueryStack.createJoin(SearchBuilderJoinEnum.COMPOSITE_UNIQUE, null);
|
||||
|
||||
if (!theRequestPartitionId.isAllPartitions()) {
|
||||
Integer partitionId = theRequestPartitionId.getFirstPartitionIdOrNull();
|
||||
|
|
|
@ -20,7 +20,7 @@ package ca.uhn.fhir.jpa.dao.data;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
|
@ -28,15 +28,15 @@ import org.springframework.data.repository.query.Param;
|
|||
|
||||
import java.util.List;
|
||||
|
||||
public interface IResourceIndexedCompositeStringUniqueDao extends JpaRepository<ResourceIndexedCompositeStringUnique, Long> {
|
||||
public interface IResourceIndexedComboStringUniqueDao extends JpaRepository<ResourceIndexedComboStringUnique, Long> {
|
||||
|
||||
@Query("SELECT r FROM ResourceIndexedCompositeStringUnique r WHERE r.myIndexString = :str")
|
||||
ResourceIndexedCompositeStringUnique findByQueryString(@Param("str") String theQueryString);
|
||||
@Query("SELECT r FROM ResourceIndexedComboStringUnique r WHERE r.myIndexString = :str")
|
||||
ResourceIndexedComboStringUnique findByQueryString(@Param("str") String theQueryString);
|
||||
|
||||
@Query("SELECT r FROM ResourceIndexedCompositeStringUnique r WHERE r.myResourceId = :resId")
|
||||
List<ResourceIndexedCompositeStringUnique> findAllForResourceIdForUnitTest(@Param("resId") Long theResourceId);
|
||||
@Query("SELECT r FROM ResourceIndexedComboStringUnique r WHERE r.myResourceId = :resId")
|
||||
List<ResourceIndexedComboStringUnique> findAllForResourceIdForUnitTest(@Param("resId") Long theResourceId);
|
||||
|
||||
@Modifying
|
||||
@Query("delete from ResourceIndexedCompositeStringUnique t WHERE t.myResourceId = :resid")
|
||||
@Query("delete from ResourceIndexedComboStringUnique t WHERE t.myResourceId = :resid")
|
||||
void deleteByResourceId(@Param("resid") Long theResourcePid);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
package ca.uhn.fhir.jpa.dao.data;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboTokenNonUnique;
|
||||
import org.springframework.data.jpa.repository.JpaRepository;
|
||||
import org.springframework.data.jpa.repository.Modifying;
|
||||
import org.springframework.data.jpa.repository.Query;
|
||||
import org.springframework.data.repository.query.Param;
|
||||
|
||||
public interface IResourceIndexedComboTokensNonUniqueDao extends JpaRepository<ResourceIndexedComboTokenNonUnique, Long> {
|
||||
|
||||
@Modifying
|
||||
@Query("DELETE FROM ResourceIndexedComboTokenNonUnique t WHERE t.myResourceId = :res_id")
|
||||
void deleteByResourceId(@Param("res_id") Long theResourcePid);
|
||||
}
|
|
@ -50,7 +50,8 @@ import ca.uhn.fhir.jpa.model.entity.NpmPackageVersionResourceEntity;
|
|||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryProvenanceEntity;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTag;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboTokenNonUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamCoords;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamNumber;
|
||||
|
@ -136,7 +137,8 @@ public class ExpungeEverythingService {
|
|||
counter.addAndGet(expungeEverythingByType(ResourceIndexedSearchParamToken.class));
|
||||
counter.addAndGet(expungeEverythingByType(ResourceIndexedSearchParamUri.class));
|
||||
counter.addAndGet(expungeEverythingByType(ResourceIndexedSearchParamCoords.class));
|
||||
counter.addAndGet(expungeEverythingByType(ResourceIndexedCompositeStringUnique.class));
|
||||
counter.addAndGet(expungeEverythingByType(ResourceIndexedComboStringUnique.class));
|
||||
counter.addAndGet(expungeEverythingByType(ResourceIndexedComboTokenNonUnique.class));
|
||||
counter.addAndGet(expungeEverythingByType(ResourceLink.class));
|
||||
counter.addAndGet(expungeEverythingByType(SearchResult.class));
|
||||
counter.addAndGet(expungeEverythingByType(SearchInclude.class));
|
||||
|
|
|
@ -28,7 +28,8 @@ import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
|||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTableDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTagDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedCompositeStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedComboStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedComboTokensNonUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamCoordsDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamDateDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamNumberDao;
|
||||
|
@ -95,7 +96,9 @@ public class ResourceExpungeService implements IResourceExpungeService {
|
|||
@Autowired
|
||||
private IResourceIndexedSearchParamNumberDao myResourceIndexedSearchParamNumberDao;
|
||||
@Autowired
|
||||
private IResourceIndexedCompositeStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
private IResourceIndexedComboStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
@Autowired
|
||||
private IResourceIndexedComboTokensNonUniqueDao myResourceIndexedComboTokensNonUniqueDao;
|
||||
@Autowired
|
||||
private IResourceLinkDao myResourceLinkDao;
|
||||
@Autowired
|
||||
|
@ -289,9 +292,12 @@ public class ResourceExpungeService implements IResourceExpungeService {
|
|||
if (resource == null || resource.isParamsTokenPopulated()) {
|
||||
myResourceIndexedSearchParamTokenDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
if (resource == null || resource.isParamsCompositeStringUniquePresent()) {
|
||||
if (resource == null || resource.isParamsComboStringUniquePresent()) {
|
||||
myResourceIndexedCompositeStringUniqueDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
if (resource == null || resource.isParamsComboTokensNonUniquePresent()) {
|
||||
myResourceIndexedComboTokensNonUniqueDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
if (myDaoConfig.getIndexMissingFields() == DaoConfig.IndexEnabledEnum.ENABLED) {
|
||||
mySearchParamPresentDao.deleteByResourceId(theResourceId);
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ public class ResourceTableFKProvider {
|
|||
// SELECT FKTABLE_NAME, FKCOLUMN_NAME FROM CROSS_REFERENCES WHERE PKTABLE_NAME = 'HFJ_RESOURCE'
|
||||
retval.add(new ResourceForeignKey("HFJ_FORCED_ID", "RESOURCE_PID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_IDX_CMP_STRING_UNIQ", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_IDX_CMB_TOK_NU", "RES_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_LINK", "SRC_RESOURCE_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_LINK", "TARGET_RESOURCE_ID"));
|
||||
retval.add(new ResourceForeignKey("HFJ_RES_PARAM_PRESENT", "RES_ID"));
|
||||
|
|
|
@ -40,6 +40,8 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
|||
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
|
||||
import ca.uhn.fhir.util.HapiExtensions;
|
||||
import ca.uhn.fhir.util.TerserUtil;
|
||||
import org.apache.http.NameValuePair;
|
||||
import org.apache.http.client.utils.URLEncodedUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseExtension;
|
||||
import org.hl7.fhir.instance.model.api.IBaseHasExtensions;
|
||||
|
@ -54,6 +56,8 @@ import javax.annotation.Nullable;
|
|||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.PersistenceContextType;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
public class DaoResourceLinkResolver implements IResourceLinkResolver {
|
||||
|
@ -160,7 +164,7 @@ public class DaoResourceLinkResolver implements IResourceLinkResolver {
|
|||
|
||||
if (referenceIdentifier == null && referenceMatchUrlIdentifier != null) {
|
||||
addMatchUrlIdentifierToTargetResource(theTargetResourceDef, theTargetResource, referenceMatchUrlIdentifier);
|
||||
} else if (referenceIdentifier!= null && referenceMatchUrlIdentifier == null) {
|
||||
} else if (referenceIdentifier != null && referenceMatchUrlIdentifier == null) {
|
||||
addSubjectIdentifierToTargetResource(theSourceReference, theTargetResourceDef, theTargetResource);
|
||||
} else if (referenceIdentifier != null && referenceMatchUrlIdentifier != null) {
|
||||
if (referenceIdentifier.equals(referenceMatchUrlIdentifier)) {
|
||||
|
@ -222,16 +226,33 @@ public class DaoResourceLinkResolver implements IResourceLinkResolver {
|
|||
}
|
||||
}
|
||||
|
||||
private CanonicalIdentifier extractIdentifierFromUrl(String theValue) {
|
||||
if (!theValue.contains("identifier=")) {
|
||||
/**
|
||||
* Extracts the first available identifier from the URL part
|
||||
*
|
||||
* @param theValue Part of the URL to extract identifiers from
|
||||
* @return Returns the first available identifier in the canonical form or null if URL contains no identifier param
|
||||
* @throws IllegalArgumentException IllegalArgumentException is thrown in case identifier parameter can not be split using <code>system|value</code> pattern.
|
||||
*/
|
||||
protected CanonicalIdentifier extractIdentifierFromUrl(String theValue) {
|
||||
int identifierIndex = theValue.indexOf("identifier=");
|
||||
if (identifierIndex == -1) {
|
||||
return null;
|
||||
}
|
||||
CanonicalIdentifier identifier = new CanonicalIdentifier();
|
||||
String identifierString = theValue.substring(theValue.indexOf("=") + 1);
|
||||
|
||||
List<NameValuePair> params = URLEncodedUtils.parse(theValue.substring(identifierIndex), StandardCharsets.UTF_8, '&', ';');
|
||||
Optional<NameValuePair> idOptional = params.stream().filter(p -> p.getName().equals("identifier")).findFirst();
|
||||
if (!idOptional.isPresent()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
NameValuePair id = idOptional.get();
|
||||
String identifierString = id.getValue();
|
||||
String[] split = identifierString.split("\\|");
|
||||
if (split.length != 2) {
|
||||
throw new IllegalArgumentException("Can't create a placeholder reference with identifier " + theValue + ". It is not a valid identifier");
|
||||
}
|
||||
|
||||
CanonicalIdentifier identifier = new CanonicalIdentifier();
|
||||
identifier.setSystem(split[0]);
|
||||
identifier.setValue(split[1]);
|
||||
return identifier;
|
||||
|
|
|
@ -20,17 +20,11 @@ package ca.uhn.fhir.jpa.dao.index;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndex;
|
||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams;
|
||||
import ca.uhn.fhir.jpa.util.AddRemoveCount;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.persistence.EntityManager;
|
||||
|
@ -43,15 +37,8 @@ import java.util.List;
|
|||
|
||||
@Service
|
||||
public class DaoSearchParamSynchronizer {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(DaoSearchParamSynchronizer.class);
|
||||
@PersistenceContext(type = PersistenceContextType.TRANSACTION)
|
||||
protected EntityManager myEntityManager;
|
||||
@Autowired
|
||||
private DaoConfig myDaoConfig;
|
||||
@Autowired
|
||||
private PartitionSettings myPartitionSettings;
|
||||
@Autowired
|
||||
private ModelConfig myModelConfig;
|
||||
|
||||
public AddRemoveCount synchronizeSearchParamsToDatabase(ResourceIndexedSearchParams theParams, ResourceTable theEntity, ResourceIndexedSearchParams existingParams) {
|
||||
AddRemoveCount retVal = new AddRemoveCount();
|
||||
|
@ -65,6 +52,7 @@ public class DaoSearchParamSynchronizer {
|
|||
synchronize(theEntity, retVal, theParams.myUriParams, existingParams.myUriParams);
|
||||
synchronize(theEntity, retVal, theParams.myCoordsParams, existingParams.myCoordsParams);
|
||||
synchronize(theEntity, retVal, theParams.myLinks, existingParams.myLinks);
|
||||
synchronize(theEntity, retVal, theParams.myComboTokenNonUnique, existingParams.myComboTokenNonUnique);
|
||||
|
||||
// make sure links are indexed
|
||||
theEntity.setResourceLinks(theParams.myLinks);
|
||||
|
|
|
@ -36,6 +36,7 @@ import ca.uhn.fhir.model.primitive.IdDt;
|
|||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.ListMultimap;
|
||||
import com.google.common.collect.MultimapBuilder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
@ -389,9 +390,9 @@ public class IdHelperService {
|
|||
return retVal;
|
||||
}
|
||||
|
||||
private RequestPartitionId replaceDefault(RequestPartitionId theRequestPartitionId) {
|
||||
RequestPartitionId replaceDefault(RequestPartitionId theRequestPartitionId) {
|
||||
if (myPartitionSettings.getDefaultPartitionId() != null) {
|
||||
if (theRequestPartitionId.hasDefaultPartitionId()) {
|
||||
if (!theRequestPartitionId.isAllPartitions() && theRequestPartitionId.hasDefaultPartitionId()) {
|
||||
List<Integer> partitionIds = theRequestPartitionId
|
||||
.getPartitionIds()
|
||||
.stream()
|
||||
|
@ -577,6 +578,11 @@ public class IdHelperService {
|
|||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
void setPartitionSettingsForUnitTest(PartitionSettings thePartitionSettings) {
|
||||
myPartitionSettings = thePartitionSettings;
|
||||
}
|
||||
|
||||
public static boolean isValidPid(IIdType theId) {
|
||||
if (theId == null) {
|
||||
return false;
|
||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.dao.index;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.ComboSearchParamType;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
|
@ -27,17 +28,19 @@ import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
|||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
|
||||
import ca.uhn.fhir.jpa.dao.MatchResourceUrlService;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedCompositeStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedComboStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam;
|
||||
import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboTokenNonUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.searchparam.extractor.ResourceIndexedSearchParams;
|
||||
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorService;
|
||||
import ca.uhn.fhir.jpa.searchparam.util.JpaParamUtil;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.storage.ResourcePersistentId;
|
||||
import ca.uhn.fhir.rest.api.server.storage.TransactionDetails;
|
||||
|
@ -46,15 +49,18 @@ import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
|
|||
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
|
||||
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
||||
import ca.uhn.fhir.util.FhirTerser;
|
||||
import ca.uhn.fhir.util.StringUtil;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import org.hl7.fhir.instance.model.api.IBaseReference;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import javax.persistence.EntityManager;
|
||||
import javax.persistence.PersistenceContext;
|
||||
import javax.persistence.PersistenceContextType;
|
||||
|
@ -64,8 +70,10 @@ import java.util.HashSet;
|
|||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
|
@ -92,7 +100,7 @@ public class SearchParamWithInlineReferencesExtractor {
|
|||
@Autowired
|
||||
private DaoSearchParamSynchronizer myDaoSearchParamSynchronizer;
|
||||
@Autowired
|
||||
private IResourceIndexedCompositeStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
private IResourceIndexedComboStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
@Autowired
|
||||
private PartitionSettings myPartitionSettings;
|
||||
|
||||
|
@ -140,7 +148,7 @@ public class SearchParamWithInlineReferencesExtractor {
|
|||
}
|
||||
|
||||
/*
|
||||
* Handle composites
|
||||
* Handle combo parameters
|
||||
*/
|
||||
extractCompositeStringUniques(theEntity, theParams);
|
||||
}
|
||||
|
@ -148,86 +156,152 @@ public class SearchParamWithInlineReferencesExtractor {
|
|||
private void extractCompositeStringUniques(ResourceTable theEntity, ResourceIndexedSearchParams theParams) {
|
||||
|
||||
final String resourceType = theEntity.getResourceType();
|
||||
List<RuntimeSearchParam> uniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(resourceType);
|
||||
List<RuntimeSearchParam> comboSearchParams = mySearchParamRegistry.getActiveComboSearchParams(resourceType);
|
||||
|
||||
for (RuntimeSearchParam next : uniqueSearchParams) {
|
||||
for (RuntimeSearchParam next : comboSearchParams) {
|
||||
switch (Objects.requireNonNull(next.getComboSearchParamType())) {
|
||||
case UNIQUE:
|
||||
extractComboUniqueParam(theEntity, theParams, resourceType, next);
|
||||
break;
|
||||
case NON_UNIQUE:
|
||||
extractComboNonUniqueParam(theEntity, theParams, resourceType, next);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<List<String>> partsChoices = new ArrayList<>();
|
||||
private void extractComboNonUniqueParam(ResourceTable theEntity, ResourceIndexedSearchParams theParams, String theResourceType, RuntimeSearchParam theParam) {
|
||||
Set<String> queryStringsToPopulate = extractParameterCombinationsForComboParam(theParams, theResourceType, theParam);
|
||||
|
||||
List<RuntimeSearchParam> compositeComponents = JpaParamUtil.resolveComponentParameters(mySearchParamRegistry, next);
|
||||
for (RuntimeSearchParam nextCompositeOf : compositeComponents) {
|
||||
Collection<? extends BaseResourceIndexedSearchParam> paramsListForCompositePart = null;
|
||||
Collection<ResourceLink> linksForCompositePart = null;
|
||||
Collection<String> linksForCompositePartWantPaths = null;
|
||||
switch (nextCompositeOf.getParamType()) {
|
||||
case NUMBER:
|
||||
paramsListForCompositePart = theParams.myNumberParams;
|
||||
break;
|
||||
case DATE:
|
||||
paramsListForCompositePart = theParams.myDateParams;
|
||||
break;
|
||||
case STRING:
|
||||
paramsListForCompositePart = theParams.myStringParams;
|
||||
break;
|
||||
case TOKEN:
|
||||
paramsListForCompositePart = theParams.myTokenParams;
|
||||
break;
|
||||
case REFERENCE:
|
||||
linksForCompositePart = theParams.myLinks;
|
||||
linksForCompositePartWantPaths = new HashSet<>(nextCompositeOf.getPathsSplit());
|
||||
break;
|
||||
case QUANTITY:
|
||||
paramsListForCompositePart = theParams.myQuantityParams;
|
||||
break;
|
||||
case URI:
|
||||
paramsListForCompositePart = theParams.myUriParams;
|
||||
break;
|
||||
case SPECIAL:
|
||||
case COMPOSITE:
|
||||
case HAS:
|
||||
break;
|
||||
}
|
||||
for (String nextQueryString : queryStringsToPopulate) {
|
||||
ourLog.trace("Adding composite unique SP: {}", nextQueryString);
|
||||
theParams.myComboTokenNonUnique.add(new ResourceIndexedComboTokenNonUnique(myPartitionSettings, theEntity, nextQueryString));
|
||||
}
|
||||
}
|
||||
|
||||
ArrayList<String> nextChoicesList = new ArrayList<>();
|
||||
partsChoices.add(nextChoicesList);
|
||||
private void extractComboUniqueParam(ResourceTable theEntity, ResourceIndexedSearchParams theParams, String theResourceType, RuntimeSearchParam theParam) {
|
||||
Set<String> queryStringsToPopulate = extractParameterCombinationsForComboParam(theParams, theResourceType, theParam);
|
||||
|
||||
String key = UrlUtil.escapeUrlParam(nextCompositeOf.getName());
|
||||
if (paramsListForCompositePart != null) {
|
||||
for (BaseResourceIndexedSearchParam nextParam : paramsListForCompositePart) {
|
||||
if (nextParam.getParamName().equals(nextCompositeOf.getName())) {
|
||||
IQueryParameterType nextParamAsClientParam = nextParam.toQueryParameterType();
|
||||
String value = nextParamAsClientParam.getValueAsQueryToken(myContext);
|
||||
if (isNotBlank(value)) {
|
||||
value = UrlUtil.escapeUrlParam(value);
|
||||
nextChoicesList.add(key + "=" + value);
|
||||
}
|
||||
}
|
||||
for (String nextQueryString : queryStringsToPopulate) {
|
||||
ourLog.trace("Adding composite unique SP: {}", nextQueryString);
|
||||
theParams.myComboStringUniques.add(new ResourceIndexedComboStringUnique(theEntity, nextQueryString, theParam.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Set<String> extractParameterCombinationsForComboParam(ResourceIndexedSearchParams theParams, String theResourceType, RuntimeSearchParam theParam) {
|
||||
List<List<String>> partsChoices = new ArrayList<>();
|
||||
|
||||
List<RuntimeSearchParam> compositeComponents = JpaParamUtil.resolveComponentParameters(mySearchParamRegistry, theParam);
|
||||
for (RuntimeSearchParam nextCompositeOf : compositeComponents) {
|
||||
Collection<? extends BaseResourceIndexedSearchParam> paramsListForCompositePart = findParameterIndexes(theParams, nextCompositeOf);
|
||||
|
||||
Collection<ResourceLink> linksForCompositePart = null;
|
||||
switch (nextCompositeOf.getParamType()) {
|
||||
case REFERENCE:
|
||||
linksForCompositePart = theParams.myLinks;
|
||||
break;
|
||||
case NUMBER:
|
||||
case DATE:
|
||||
case STRING:
|
||||
case TOKEN:
|
||||
case QUANTITY:
|
||||
case URI:
|
||||
case SPECIAL:
|
||||
case COMPOSITE:
|
||||
case HAS:
|
||||
break;
|
||||
}
|
||||
|
||||
Collection<String> linksForCompositePartWantPaths = null;
|
||||
switch (nextCompositeOf.getParamType()) {
|
||||
case REFERENCE:
|
||||
linksForCompositePartWantPaths = new HashSet<>(nextCompositeOf.getPathsSplit());
|
||||
break;
|
||||
case NUMBER:
|
||||
case DATE:
|
||||
case STRING:
|
||||
case TOKEN:
|
||||
case QUANTITY:
|
||||
case URI:
|
||||
case SPECIAL:
|
||||
case COMPOSITE:
|
||||
case HAS:
|
||||
break;
|
||||
}
|
||||
|
||||
ArrayList<String> nextChoicesList = new ArrayList<>();
|
||||
partsChoices.add(nextChoicesList);
|
||||
|
||||
String key = UrlUtil.escapeUrlParam(nextCompositeOf.getName());
|
||||
if (paramsListForCompositePart != null) {
|
||||
for (BaseResourceIndexedSearchParam nextParam : paramsListForCompositePart) {
|
||||
IQueryParameterType nextParamAsClientParam = nextParam.toQueryParameterType();
|
||||
String value = nextParamAsClientParam.getValueAsQueryToken(myContext);
|
||||
|
||||
RuntimeSearchParam param = mySearchParamRegistry.getActiveSearchParam(theResourceType, key);
|
||||
if (theParam.getComboSearchParamType() == ComboSearchParamType.NON_UNIQUE && param != null && param.getParamType() == RestSearchParameterTypeEnum.STRING) {
|
||||
value = StringUtil.normalizeStringForSearchIndexing(value);
|
||||
}
|
||||
}
|
||||
if (linksForCompositePart != null) {
|
||||
for (ResourceLink nextLink : linksForCompositePart) {
|
||||
if (linksForCompositePartWantPaths.contains(nextLink.getSourcePath())) {
|
||||
assert isNotBlank(nextLink.getTargetResourceType());
|
||||
assert isNotBlank(nextLink.getTargetResourceId());
|
||||
String value = nextLink.getTargetResourceType() + "/" + nextLink.getTargetResourceId();
|
||||
if (isNotBlank(value)) {
|
||||
value = UrlUtil.escapeUrlParam(value);
|
||||
nextChoicesList.add(key + "=" + value);
|
||||
}
|
||||
}
|
||||
|
||||
if (isNotBlank(value)) {
|
||||
value = UrlUtil.escapeUrlParam(value);
|
||||
nextChoicesList.add(key + "=" + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Set<String> queryStringsToPopulate = ResourceIndexedSearchParams.extractCompositeStringUniquesValueChains(resourceType, partsChoices);
|
||||
|
||||
for (String nextQueryString : queryStringsToPopulate) {
|
||||
if (isNotBlank(nextQueryString)) {
|
||||
ourLog.trace("Adding composite unique SP: {}", nextQueryString);
|
||||
theParams.myCompositeStringUniques.add(new ResourceIndexedCompositeStringUnique(theEntity, nextQueryString, next.getId()));
|
||||
if (linksForCompositePart != null) {
|
||||
for (ResourceLink nextLink : linksForCompositePart) {
|
||||
if (linksForCompositePartWantPaths.contains(nextLink.getSourcePath())) {
|
||||
assert isNotBlank(nextLink.getTargetResourceType());
|
||||
assert isNotBlank(nextLink.getTargetResourceId());
|
||||
String value = nextLink.getTargetResourceType() + "/" + nextLink.getTargetResourceId();
|
||||
if (isNotBlank(value)) {
|
||||
value = UrlUtil.escapeUrlParam(value);
|
||||
nextChoicesList.add(key + "=" + value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ResourceIndexedSearchParams.extractCompositeStringUniquesValueChains(theResourceType, partsChoices);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private Collection<? extends BaseResourceIndexedSearchParam> findParameterIndexes(ResourceIndexedSearchParams theParams, RuntimeSearchParam nextCompositeOf) {
|
||||
Collection<? extends BaseResourceIndexedSearchParam> paramsListForCompositePart = null;
|
||||
switch (nextCompositeOf.getParamType()) {
|
||||
case NUMBER:
|
||||
paramsListForCompositePart = theParams.myNumberParams;
|
||||
break;
|
||||
case DATE:
|
||||
paramsListForCompositePart = theParams.myDateParams;
|
||||
break;
|
||||
case STRING:
|
||||
paramsListForCompositePart = theParams.myStringParams;
|
||||
break;
|
||||
case TOKEN:
|
||||
paramsListForCompositePart = theParams.myTokenParams;
|
||||
break;
|
||||
case QUANTITY:
|
||||
paramsListForCompositePart = theParams.myQuantityParams;
|
||||
break;
|
||||
case URI:
|
||||
paramsListForCompositePart = theParams.myUriParams;
|
||||
break;
|
||||
case REFERENCE:
|
||||
case SPECIAL:
|
||||
case COMPOSITE:
|
||||
case HAS:
|
||||
break;
|
||||
}
|
||||
if (paramsListForCompositePart != null) {
|
||||
paramsListForCompositePart = paramsListForCompositePart
|
||||
.stream()
|
||||
.filter(t->t.getParamName().equals(nextCompositeOf.getName()))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
return paramsListForCompositePart;
|
||||
}
|
||||
|
||||
|
||||
|
@ -309,19 +383,21 @@ public class SearchParamWithInlineReferencesExtractor {
|
|||
myDaoSearchParamSynchronizer = theDaoSearchParamSynchronizer;
|
||||
}
|
||||
|
||||
public void storeCompositeStringUniques(ResourceIndexedSearchParams theParams, ResourceTable theEntity, ResourceIndexedSearchParams existingParams) {
|
||||
public void storeUniqueComboParameters(ResourceIndexedSearchParams theParams, ResourceTable theEntity, ResourceIndexedSearchParams theExistingParams) {
|
||||
|
||||
// Store composite string uniques
|
||||
/*
|
||||
* String Uniques
|
||||
*/
|
||||
if (myDaoConfig.isUniqueIndexesEnabled()) {
|
||||
for (ResourceIndexedCompositeStringUnique next : myDaoSearchParamSynchronizer.subtract(existingParams.myCompositeStringUniques, theParams.myCompositeStringUniques)) {
|
||||
for (ResourceIndexedComboStringUnique next : myDaoSearchParamSynchronizer.subtract(theExistingParams.myComboStringUniques, theParams.myComboStringUniques)) {
|
||||
ourLog.debug("Removing unique index: {}", next);
|
||||
myEntityManager.remove(next);
|
||||
theEntity.getParamsCompositeStringUnique().remove(next);
|
||||
theEntity.getParamsComboStringUnique().remove(next);
|
||||
}
|
||||
boolean haveNewParams = false;
|
||||
for (ResourceIndexedCompositeStringUnique next : myDaoSearchParamSynchronizer.subtract(theParams.myCompositeStringUniques, existingParams.myCompositeStringUniques)) {
|
||||
boolean haveNewStringUniqueParams = false;
|
||||
for (ResourceIndexedComboStringUnique next : myDaoSearchParamSynchronizer.subtract(theParams.myComboStringUniques, theExistingParams.myComboStringUniques)) {
|
||||
if (myDaoConfig.isUniqueIndexesCheckedBeforeSave()) {
|
||||
ResourceIndexedCompositeStringUnique existing = myResourceIndexedCompositeStringUniqueDao.findByQueryString(next.getIndexString());
|
||||
ResourceIndexedComboStringUnique existing = myResourceIndexedCompositeStringUniqueDao.findByQueryString(next.getIndexString());
|
||||
if (existing != null) {
|
||||
|
||||
String searchParameterId = "(unknown)";
|
||||
|
@ -335,12 +411,12 @@ public class SearchParamWithInlineReferencesExtractor {
|
|||
}
|
||||
ourLog.debug("Persisting unique index: {}", next);
|
||||
myEntityManager.persist(next);
|
||||
haveNewParams = true;
|
||||
haveNewStringUniqueParams = true;
|
||||
}
|
||||
if (theParams.myCompositeStringUniques.size() > 0 || haveNewParams) {
|
||||
theEntity.setParamsCompositeStringUniquePresent(true);
|
||||
if (theParams.myComboStringUniques.size() > 0 || haveNewStringUniqueParams) {
|
||||
theEntity.setParamsComboStringUniquePresent(true);
|
||||
} else {
|
||||
theEntity.setParamsCompositeStringUniquePresent(false);
|
||||
theEntity.setParamsComboStringUniquePresent(false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -170,7 +170,7 @@ class QueryRootEntryResourceTable extends QueryRootEntry {
|
|||
join = myResourceTableRoot.join("mySearchParamPresents", JoinType.LEFT);
|
||||
break;
|
||||
case COMPOSITE_UNIQUE:
|
||||
join = myResourceTableRoot.join("myParamsCompositeStringUnique", JoinType.LEFT);
|
||||
join = myResourceTableRoot.join("myParamsComboStringUnique", JoinType.LEFT);
|
||||
break;
|
||||
case RESOURCE_TAGS:
|
||||
join = myResourceTableRoot.join("myTags", JoinType.LEFT);
|
||||
|
|
|
@ -23,7 +23,6 @@ package ca.uhn.fhir.jpa.interceptor;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.fhirpath.IFhirPath;
|
||||
import ca.uhn.fhir.interceptor.api.Hook;
|
||||
import ca.uhn.fhir.interceptor.api.Interceptor;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
|
@ -31,6 +30,7 @@ import ca.uhn.fhir.interceptor.model.ReadPartitionIdRequestDetails;
|
|||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.searchparam.extractor.BaseSearchParamExtractor;
|
||||
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
|
||||
import ca.uhn.fhir.model.api.IQueryParameterType;
|
||||
import ca.uhn.fhir.rest.api.RestSearchParameterTypeEnum;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
|
@ -45,7 +45,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import javax.annotation.Nonnull;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
@ -62,6 +61,9 @@ public class PatientIdPartitionInterceptor {
|
|||
@Autowired
|
||||
private FhirContext myFhirContext;
|
||||
|
||||
@Autowired
|
||||
private ISearchParamExtractor mySearchParamExtractor;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
|
@ -72,9 +74,10 @@ public class PatientIdPartitionInterceptor {
|
|||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public PatientIdPartitionInterceptor(FhirContext theFhirContext) {
|
||||
public PatientIdPartitionInterceptor(FhirContext theFhirContext, ISearchParamExtractor theSearchParamExtractor) {
|
||||
this();
|
||||
myFhirContext = theFhirContext;
|
||||
mySearchParamExtractor = theSearchParamExtractor;
|
||||
}
|
||||
|
||||
@Hook(Pointcut.STORAGE_PARTITION_IDENTIFY_CREATE)
|
||||
|
@ -92,14 +95,15 @@ public class PatientIdPartitionInterceptor {
|
|||
throw new MethodNotAllowedException("Patient resource IDs must be client-assigned in patient compartment mode");
|
||||
}
|
||||
} else {
|
||||
IFhirPath fhirPath = myFhirContext.newFhirPath();
|
||||
compartmentIdentity = compartmentSps
|
||||
.stream()
|
||||
.flatMap(param -> Arrays.stream(BaseSearchParamExtractor.splitPathsR4(param.getPath())))
|
||||
.filter(StringUtils::isNotBlank)
|
||||
.map(path -> fhirPath.evaluateFirst(theResource, path, IBaseReference.class))
|
||||
.filter(Optional::isPresent)
|
||||
.map(Optional::get)
|
||||
.map(path -> mySearchParamExtractor.getPathValueExtractor(theResource, path).get())
|
||||
.filter(t -> !t.isEmpty())
|
||||
.map(t -> t.get(0))
|
||||
.filter(t -> t instanceof IBaseReference)
|
||||
.map(t -> (IBaseReference) t)
|
||||
.map(t -> t.getReferenceElement().getValue())
|
||||
.map(t -> new IdType(t).getIdPart())
|
||||
.filter(StringUtils::isNotBlank)
|
||||
|
|
|
@ -23,6 +23,7 @@ package ca.uhn.fhir.jpa.packages;
|
|||
import ca.uhn.fhir.context.BaseRuntimeChildDefinition;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
import ca.uhn.fhir.jpa.api.model.ExpungeOptions;
|
||||
|
@ -331,7 +332,11 @@ public class JpaPackageCache extends BasePackageCacheManager implements IHapiPac
|
|||
|
||||
if (myPartitionSettings.isPartitioningEnabled()) {
|
||||
SystemRequestDetails requestDetails = new SystemRequestDetails();
|
||||
requestDetails.setTenantId(JpaConstants.DEFAULT_PARTITION_NAME);
|
||||
if (myPartitionSettings.isUnnamedPartitionMode() && myPartitionSettings.getDefaultPartitionId() != null) {
|
||||
requestDetails.setRequestPartitionId(RequestPartitionId.fromPartitionId(myPartitionSettings.getDefaultPartitionId()));
|
||||
} else {
|
||||
requestDetails.setTenantId(JpaConstants.DEFAULT_PARTITION_NAME);
|
||||
}
|
||||
return (ResourceTable) getBinaryDao().create(theResourceBinary, requestDetails).getEntity();
|
||||
} else {
|
||||
return (ResourceTable) getBinaryDao().create(theResourceBinary).getEntity();
|
||||
|
@ -472,6 +477,8 @@ public class JpaPackageCache extends BasePackageCacheManager implements IHapiPac
|
|||
}
|
||||
|
||||
private IBaseResource loadPackageEntity(NpmPackageVersionResourceEntity contents) {
|
||||
try {
|
||||
|
||||
ResourcePersistentId binaryPid = new ResourcePersistentId(contents.getResourceBinary().getId());
|
||||
IBaseBinary binary = getBinaryDao().readByPid(binaryPid);
|
||||
byte[] resourceContentsBytes = BinaryUtil.getOrCreateData(myCtx, binary).getValue();
|
||||
|
@ -479,6 +486,9 @@ public class JpaPackageCache extends BasePackageCacheManager implements IHapiPac
|
|||
|
||||
FhirContext packageContext = getFhirContext(contents.getFhirVersion());
|
||||
return EncodingEnum.detectEncoding(resourceContents).newParser(packageContext).parseResource(resourceContents);
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException("Failed to load package resource " + contents, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -359,7 +359,6 @@ public class PackageInstallerSvcImpl implements IPackageInstallerSvc {
|
|||
private IBundleProvider searchResource(IFhirResourceDao theDao, SearchParameterMap theMap) {
|
||||
if (myPartitionSettings.isPartitioningEnabled()) {
|
||||
SystemRequestDetails requestDetails = new SystemRequestDetails();
|
||||
// requestDetails.setTenantId(JpaConstants.DEFAULT_PARTITION_NAME);
|
||||
return theDao.search(theMap, requestDetails);
|
||||
} else {
|
||||
return theDao.search(theMap);
|
||||
|
@ -369,7 +368,6 @@ public class PackageInstallerSvcImpl implements IPackageInstallerSvc {
|
|||
private void createResource(IFhirResourceDao theDao, IBaseResource theResource) {
|
||||
if (myPartitionSettings.isPartitioningEnabled()) {
|
||||
SystemRequestDetails requestDetails = new SystemRequestDetails();
|
||||
requestDetails.setTenantId(JpaConstants.DEFAULT_PARTITION_NAME);
|
||||
theDao.create(theResource, requestDetails);
|
||||
} else {
|
||||
theDao.create(theResource);
|
||||
|
@ -379,7 +377,6 @@ public class PackageInstallerSvcImpl implements IPackageInstallerSvc {
|
|||
private DaoMethodOutcome updateResource(IFhirResourceDao theDao, IBaseResource theResource) {
|
||||
if (myPartitionSettings.isPartitioningEnabled()) {
|
||||
SystemRequestDetails requestDetails = new SystemRequestDetails();
|
||||
requestDetails.setTenantId(JpaConstants.DEFAULT_PARTITION_NAME);
|
||||
return theDao.update(theResource, requestDetails);
|
||||
} else {
|
||||
return theDao.update(theResource);
|
||||
|
|
|
@ -34,7 +34,8 @@ import ca.uhn.fhir.jpa.model.entity.NormalizedQuantitySearchLevel;
|
|||
import ca.uhn.fhir.jpa.model.entity.TagTypeEnum;
|
||||
import ca.uhn.fhir.jpa.model.util.UcumServiceUtil;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.BaseJoiningPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.CompositeUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ComboNonUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ComboUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.CoordsPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.DatePredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ForcedIdPredicateBuilder;
|
||||
|
@ -1214,11 +1215,18 @@ public class QueryStack {
|
|||
}
|
||||
|
||||
public void addPredicateCompositeUnique(String theIndexString, RequestPartitionId theRequestPartitionId) {
|
||||
CompositeUniqueSearchParameterPredicateBuilder predicateBuilder = mySqlBuilder.addCompositeUniquePredicateBuilder();
|
||||
ComboUniqueSearchParameterPredicateBuilder predicateBuilder = mySqlBuilder.addComboUniquePredicateBuilder();
|
||||
Condition predicate = predicateBuilder.createPredicateIndexString(theRequestPartitionId, theIndexString);
|
||||
mySqlBuilder.addPredicate(predicate);
|
||||
}
|
||||
|
||||
public void addPredicateCompositeNonUnique(String theIndexString, RequestPartitionId theRequestPartitionId) {
|
||||
ComboNonUniqueSearchParameterPredicateBuilder predicateBuilder = mySqlBuilder.addComboNonUniquePredicateBuilder();
|
||||
Condition predicate = predicateBuilder.createPredicateHashComplete(theRequestPartitionId, theIndexString);
|
||||
mySqlBuilder.addPredicate(predicate);
|
||||
}
|
||||
|
||||
|
||||
public void addPredicateEverythingOperation(String theResourceName, Long theTargetPid) {
|
||||
ResourceLinkPredicateBuilder table = mySqlBuilder.addReferencePredicateBuilder(this, null);
|
||||
Condition predicate = table.createEverythingPredicate(theResourceName, theTargetPid);
|
||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.search.builder;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.context.ComboSearchParamType;
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
|
@ -85,6 +86,7 @@ import ca.uhn.fhir.rest.param.StringParam;
|
|||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
import ca.uhn.fhir.util.StopWatch;
|
||||
import ca.uhn.fhir.util.StringUtil;
|
||||
import ca.uhn.fhir.util.UrlUtil;
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.collect.Lists;
|
||||
|
@ -119,6 +121,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
|
@ -213,7 +216,7 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
|
||||
// Attempt to lookup via composite unique key.
|
||||
if (isCompositeUniqueSpCandidate()) {
|
||||
attemptCompositeUniqueSpProcessing(theQueryStack, theParams, theRequest);
|
||||
attemptComboUniqueSpProcessing(theQueryStack, theParams, theRequest);
|
||||
}
|
||||
|
||||
SearchContainedModeEnum searchContainedMode = theParams.getSearchContainedMode();
|
||||
|
@ -366,7 +369,10 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
QueryStack queryStack3 = new QueryStack(theParams, myDaoConfig, myDaoConfig.getModelConfig(), myContext, sqlBuilder, mySearchParamRegistry, myPartitionSettings);
|
||||
|
||||
if (theParams.keySet().size() > 1 || theParams.getSort() != null || theParams.keySet().contains(Constants.PARAM_HAS)) {
|
||||
sqlBuilder.setNeedResourceTableRoot(true);
|
||||
List<RuntimeSearchParam> activeComboParams = mySearchParamRegistry.getActiveComboSearchParams(myResourceName, theParams.keySet());
|
||||
if (activeComboParams.isEmpty()) {
|
||||
sqlBuilder.setNeedResourceTableRoot(true);
|
||||
}
|
||||
}
|
||||
|
||||
JdbcTemplate jdbcTemplate = new JdbcTemplate(myEntityManagerFactory.getDataSource());
|
||||
|
@ -1009,12 +1015,34 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
}
|
||||
}
|
||||
|
||||
private void attemptCompositeUniqueSpProcessing(QueryStack theQueryStack3, @Nonnull SearchParameterMap theParams, RequestDetails theRequest) {
|
||||
// Since we're going to remove elements below
|
||||
theParams.values().forEach(nextAndList -> ensureSubListsAreWritable(nextAndList));
|
||||
private void attemptComboUniqueSpProcessing(QueryStack theQueryStack3, @Nonnull SearchParameterMap theParams, RequestDetails theRequest) {
|
||||
RuntimeSearchParam comboParam = null;
|
||||
List<String> comboParamNames = null;
|
||||
List<RuntimeSearchParam> exactMatchParams = mySearchParamRegistry.getActiveComboSearchParams(myResourceName, theParams.keySet());
|
||||
if (exactMatchParams.size() > 0) {
|
||||
comboParam = exactMatchParams.get(0);
|
||||
comboParamNames = new ArrayList<>(theParams.keySet());
|
||||
}
|
||||
|
||||
List<RuntimeSearchParam> activeUniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams(myResourceName, theParams.keySet());
|
||||
if (activeUniqueSearchParams.size() > 0) {
|
||||
if (comboParam == null) {
|
||||
List<RuntimeSearchParam> candidateComboParams = mySearchParamRegistry.getActiveComboSearchParams(myResourceName);
|
||||
for (RuntimeSearchParam nextCandidate : candidateComboParams) {
|
||||
List<String> nextCandidateParamNames = JpaParamUtil
|
||||
.resolveComponentParameters(mySearchParamRegistry, nextCandidate)
|
||||
.stream()
|
||||
.map(t -> t.getName())
|
||||
.collect(Collectors.toList());
|
||||
if (theParams.keySet().containsAll(nextCandidateParamNames)) {
|
||||
comboParam = nextCandidate;
|
||||
comboParamNames = nextCandidateParamNames;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (comboParam != null) {
|
||||
// Since we're going to remove elements below
|
||||
theParams.values().forEach(nextAndList -> ensureSubListsAreWritable(nextAndList));
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(myResourceName);
|
||||
|
@ -1022,9 +1050,8 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
|
||||
boolean first = true;
|
||||
|
||||
ArrayList<String> keys = new ArrayList<>(theParams.keySet());
|
||||
Collections.sort(keys);
|
||||
for (String nextParamName : keys) {
|
||||
Collections.sort(comboParamNames);
|
||||
for (String nextParamName : comboParamNames) {
|
||||
List<List<IQueryParameterType>> nextValues = theParams.get(nextParamName);
|
||||
|
||||
nextParamName = UrlUtil.escapeUrlParam(nextParamName);
|
||||
|
@ -1047,6 +1074,13 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
List<? extends IQueryParameterType> nextAnd = nextValues.remove(0);
|
||||
IQueryParameterType nextOr = nextAnd.remove(0);
|
||||
String nextOrValue = nextOr.getValueAsQueryToken(myContext);
|
||||
|
||||
if (comboParam.getComboSearchParamType() == ComboSearchParamType.NON_UNIQUE) {
|
||||
if (nextParamDef.getParamType() == RestSearchParameterTypeEnum.STRING) {
|
||||
nextOrValue = StringUtil.normalizeStringForSearchIndexing(nextOrValue);
|
||||
}
|
||||
}
|
||||
|
||||
nextOrValue = UrlUtil.escapeUrlParam(nextOrValue);
|
||||
|
||||
if (first) {
|
||||
|
@ -1061,18 +1095,25 @@ public class SearchBuilder implements ISearchBuilder {
|
|||
|
||||
if (sb != null) {
|
||||
String indexString = sb.toString();
|
||||
ourLog.debug("Checking for unique index for query: {}", indexString);
|
||||
ourLog.debug("Checking for {} combo index for query: {}", comboParam.getComboSearchParamType(), indexString);
|
||||
|
||||
// Interceptor broadcast: JPA_PERFTRACE_INFO
|
||||
StorageProcessingMessage msg = new StorageProcessingMessage()
|
||||
.setMessage("Using unique index for query for search: " + indexString);
|
||||
.setMessage("Using " + comboParam.getComboSearchParamType() + " index for query for search: " + indexString);
|
||||
HookParams params = new HookParams()
|
||||
.add(RequestDetails.class, theRequest)
|
||||
.addIfMatchesType(ServletRequestDetails.class, theRequest)
|
||||
.add(StorageProcessingMessage.class, msg);
|
||||
CompositeInterceptorBroadcaster.doCallHooks(myInterceptorBroadcaster, theRequest, Pointcut.JPA_PERFTRACE_INFO, params);
|
||||
|
||||
theQueryStack3.addPredicateCompositeUnique(indexString, myRequestPartitionId);
|
||||
switch (comboParam.getComboSearchParamType()) {
|
||||
case UNIQUE:
|
||||
theQueryStack3.addPredicateCompositeUnique(indexString, myRequestPartitionId);
|
||||
break;
|
||||
case NON_UNIQUE:
|
||||
theQueryStack3.addPredicateCompositeNonUnique(indexString, myRequestPartitionId);
|
||||
break;
|
||||
}
|
||||
|
||||
// Remove any empty parameters remaining after this
|
||||
theParams.clean();
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
package ca.uhn.fhir.jpa.search.builder.predicate;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.search.builder.sql.SearchQueryBuilder;
|
||||
import com.healthmarketscience.sqlbuilder.BinaryCondition;
|
||||
import com.healthmarketscience.sqlbuilder.Condition;
|
||||
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbColumn;
|
||||
|
||||
public class ComboNonUniqueSearchParameterPredicateBuilder extends BaseSearchParamPredicateBuilder {
|
||||
|
||||
private final DbColumn myColumnIndexString;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ComboNonUniqueSearchParameterPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
super(theSearchSqlBuilder, theSearchSqlBuilder.addTable("HFJ_IDX_CMB_TOK_NU"));
|
||||
|
||||
myColumnIndexString = getTable().addColumn("IDX_STRING");
|
||||
}
|
||||
|
||||
|
||||
public Condition createPredicateHashComplete(RequestPartitionId theRequestPartitionId, String theIndexString) {
|
||||
BinaryCondition predicate = BinaryCondition.equalTo(myColumnIndexString, generatePlaceholder(theIndexString));
|
||||
return combineWithRequestPartitionIdPredicate(theRequestPartitionId, predicate);
|
||||
}
|
||||
}
|
|
@ -26,14 +26,14 @@ import com.healthmarketscience.sqlbuilder.BinaryCondition;
|
|||
import com.healthmarketscience.sqlbuilder.Condition;
|
||||
import com.healthmarketscience.sqlbuilder.dbspec.basic.DbColumn;
|
||||
|
||||
public class CompositeUniqueSearchParameterPredicateBuilder extends BaseSearchParamPredicateBuilder {
|
||||
public class ComboUniqueSearchParameterPredicateBuilder extends BaseSearchParamPredicateBuilder {
|
||||
|
||||
private final DbColumn myColumnString;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public CompositeUniqueSearchParameterPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
public ComboUniqueSearchParameterPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
super(theSearchSqlBuilder, theSearchSqlBuilder.addTable("HFJ_IDX_CMP_STRING_UNIQ"));
|
||||
|
||||
myColumnString = getTable().addColumn("IDX_STRING");
|
|
@ -27,7 +27,8 @@ import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
|||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||
import ca.uhn.fhir.jpa.search.builder.QueryStack;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.BaseJoiningPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.CompositeUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ComboNonUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ComboUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.CoordsPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.DatePredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ForcedIdPredicateBuilder;
|
||||
|
@ -145,12 +146,20 @@ public class SearchQueryBuilder {
|
|||
/**
|
||||
* Add and return a predicate builder (or a root query if no root query exists yet) for selecting on a Composite Unique search parameter
|
||||
*/
|
||||
public CompositeUniqueSearchParameterPredicateBuilder addCompositeUniquePredicateBuilder() {
|
||||
CompositeUniqueSearchParameterPredicateBuilder retVal = mySqlBuilderFactory.newCompositeUniqueSearchParameterPredicateBuilder(this);
|
||||
public ComboUniqueSearchParameterPredicateBuilder addComboUniquePredicateBuilder() {
|
||||
ComboUniqueSearchParameterPredicateBuilder retVal = mySqlBuilderFactory.newComboUniqueSearchParameterPredicateBuilder(this);
|
||||
addTable(retVal, null);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add and return a predicate builder (or a root query if no root query exists yet) for selecting on a Composite Unique search parameter
|
||||
*/
|
||||
public ComboNonUniqueSearchParameterPredicateBuilder addComboNonUniquePredicateBuilder() {
|
||||
ComboNonUniqueSearchParameterPredicateBuilder retVal = mySqlBuilderFactory.newComboNonUniqueSearchParameterPredicateBuilder(this);
|
||||
addTable(retVal, null);
|
||||
return retVal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add and return a predicate builder (or a root query if no root query exists yet) for selecting on a COORDS search parameter
|
||||
|
|
|
@ -21,7 +21,8 @@ package ca.uhn.fhir.jpa.search.builder.sql;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.search.builder.QueryStack;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.CompositeUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ComboNonUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ComboUniqueSearchParameterPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.CoordsPredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.DatePredicateBuilder;
|
||||
import ca.uhn.fhir.jpa.search.builder.predicate.ForcedIdPredicateBuilder;
|
||||
|
@ -45,10 +46,15 @@ public class SqlObjectFactory {
|
|||
@Autowired
|
||||
private ApplicationContext myApplicationContext;
|
||||
|
||||
public CompositeUniqueSearchParameterPredicateBuilder newCompositeUniqueSearchParameterPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
return myApplicationContext.getBean(CompositeUniqueSearchParameterPredicateBuilder.class, theSearchSqlBuilder);
|
||||
public ComboUniqueSearchParameterPredicateBuilder newComboUniqueSearchParameterPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
return myApplicationContext.getBean(ComboUniqueSearchParameterPredicateBuilder.class, theSearchSqlBuilder);
|
||||
}
|
||||
|
||||
public ComboNonUniqueSearchParameterPredicateBuilder newComboNonUniqueSearchParameterPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
return myApplicationContext.getBean(ComboNonUniqueSearchParameterPredicateBuilder.class, theSearchSqlBuilder);
|
||||
}
|
||||
|
||||
|
||||
public CoordsPredicateBuilder coordsPredicateBuilder(SearchQueryBuilder theSearchSqlBuilder) {
|
||||
return myApplicationContext.getBean(CoordsPredicateBuilder.class, theSearchSqlBuilder);
|
||||
}
|
||||
|
@ -112,4 +118,5 @@ public class SqlObjectFactory {
|
|||
public SearchQueryExecutor newSearchQueryExecutor(GeneratedSql theGeneratedSql, Integer theMaxResultsToFetch) {
|
||||
return myApplicationContext.getBean(SearchQueryExecutor.class, theGeneratedSql, theMaxResultsToFetch);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -12,6 +12,7 @@ import ca.uhn.fhir.jpa.term.custom.CustomTerminologySet;
|
|||
import ca.uhn.fhir.jpa.term.icd10cm.Icd10CmLoader;
|
||||
import ca.uhn.fhir.jpa.term.loinc.LoincAnswerListHandler;
|
||||
import ca.uhn.fhir.jpa.term.loinc.LoincAnswerListLinkHandler;
|
||||
import ca.uhn.fhir.jpa.term.loinc.LoincConsumerNameHandler;
|
||||
import ca.uhn.fhir.jpa.term.loinc.LoincDocumentOntologyHandler;
|
||||
import ca.uhn.fhir.jpa.term.loinc.LoincGroupFileHandler;
|
||||
import ca.uhn.fhir.jpa.term.loinc.LoincGroupTermsFileHandler;
|
||||
|
@ -19,6 +20,8 @@ import ca.uhn.fhir.jpa.term.loinc.LoincHandler;
|
|||
import ca.uhn.fhir.jpa.term.loinc.LoincHierarchyHandler;
|
||||
import ca.uhn.fhir.jpa.term.loinc.LoincIeeeMedicalDeviceCodeHandler;
|
||||
import ca.uhn.fhir.jpa.term.loinc.LoincImagingDocumentCodeHandler;
|
||||
import ca.uhn.fhir.jpa.term.loinc.LoincLinguisticVariantHandler;
|
||||
import ca.uhn.fhir.jpa.term.loinc.LoincLinguisticVariantsHandler;
|
||||
import ca.uhn.fhir.jpa.term.loinc.LoincParentGroupFileHandler;
|
||||
import ca.uhn.fhir.jpa.term.loinc.LoincPartHandler;
|
||||
import ca.uhn.fhir.jpa.term.loinc.LoincPartLinkHandler;
|
||||
|
@ -90,6 +93,8 @@ import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_ANSWERL
|
|||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_ANSWERLIST_LINK_FILE;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_ANSWERLIST_LINK_FILE_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_CODESYSTEM_VERSION;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_CONSUMER_NAME_FILE;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_CONSUMER_NAME_FILE_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_DOCUMENT_ONTOLOGY_FILE;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_DOCUMENT_ONTOLOGY_FILE_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_FILE;
|
||||
|
@ -104,6 +109,10 @@ import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_IEEE_ME
|
|||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_IEEE_MEDICAL_DEVICE_CODE_MAPPING_TABLE_FILE_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_IMAGING_DOCUMENT_CODES_FILE;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_IMAGING_DOCUMENT_CODES_FILE_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_LINGUISTIC_VARIANTS_FILE;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_LINGUISTIC_VARIANTS_FILE_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_LINGUISTIC_VARIANTS_PATH;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_LINGUISTIC_VARIANTS_PATH_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_PARENT_GROUP_FILE;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_PARENT_GROUP_FILE_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_PART_FILE;
|
||||
|
@ -249,7 +258,12 @@ public class TermLoaderSvcImpl implements ITermLoaderSvc {
|
|||
uploadProperties.getProperty(LOINC_GROUP_TERMS_FILE.getCode(), LOINC_GROUP_TERMS_FILE_DEFAULT.getCode()),
|
||||
uploadProperties.getProperty(LOINC_PARENT_GROUP_FILE.getCode(), LOINC_PARENT_GROUP_FILE_DEFAULT.getCode()),
|
||||
uploadProperties.getProperty(LOINC_TOP2000_COMMON_LAB_RESULTS_SI_FILE.getCode(), LOINC_TOP2000_COMMON_LAB_RESULTS_SI_FILE_DEFAULT.getCode()),
|
||||
uploadProperties.getProperty(LOINC_TOP2000_COMMON_LAB_RESULTS_US_FILE.getCode(), LOINC_TOP2000_COMMON_LAB_RESULTS_US_FILE_DEFAULT.getCode())
|
||||
uploadProperties.getProperty(LOINC_TOP2000_COMMON_LAB_RESULTS_US_FILE.getCode(), LOINC_TOP2000_COMMON_LAB_RESULTS_US_FILE_DEFAULT.getCode()),
|
||||
|
||||
//-- optional consumer name
|
||||
uploadProperties.getProperty(LOINC_CONSUMER_NAME_FILE.getCode(), LOINC_CONSUMER_NAME_FILE_DEFAULT.getCode()),
|
||||
uploadProperties.getProperty(LOINC_LINGUISTIC_VARIANTS_FILE.getCode(), LOINC_LINGUISTIC_VARIANTS_FILE_DEFAULT.getCode())
|
||||
|
||||
);
|
||||
descriptors.verifyOptionalFilesExist(optionalFilenameFragments);
|
||||
|
||||
|
@ -567,6 +581,8 @@ public class TermLoaderSvcImpl implements ITermLoaderSvc {
|
|||
final List<ValueSet> valueSets = new ArrayList<>();
|
||||
final List<ConceptMap> conceptMaps = new ArrayList<>();
|
||||
|
||||
final List<LoincLinguisticVariantsHandler.LinguisticVariant> linguisticVariants = new ArrayList<>();
|
||||
|
||||
LoincXmlFileZipContentsHandler loincXmlHandler = new LoincXmlFileZipContentsHandler();
|
||||
iterateOverZipFile(theDescriptors, "loinc.xml", false, false, loincXmlHandler);
|
||||
String loincCsString = loincXmlHandler.getContents();
|
||||
|
@ -674,6 +690,21 @@ public class TermLoaderSvcImpl implements ITermLoaderSvc {
|
|||
iterateOverZipFileCsvOptional(theDescriptors, theUploadProperties.getProperty(LOINC_PART_LINK_FILE_PRIMARY.getCode(), LOINC_PART_LINK_FILE_PRIMARY_DEFAULT.getCode()), handler, ',', QuoteMode.NON_NUMERIC, false);
|
||||
iterateOverZipFileCsvOptional(theDescriptors, theUploadProperties.getProperty(LOINC_PART_LINK_FILE_SUPPLEMENTARY.getCode(), LOINC_PART_LINK_FILE_SUPPLEMENTARY_DEFAULT.getCode()), handler, ',', QuoteMode.NON_NUMERIC, false);
|
||||
|
||||
// Consumer Name
|
||||
handler = new LoincConsumerNameHandler(code2concept);
|
||||
iterateOverZipFileCsvOptional(theDescriptors, theUploadProperties.getProperty(LOINC_CONSUMER_NAME_FILE.getCode(), LOINC_CONSUMER_NAME_FILE_DEFAULT.getCode()), handler, ',', QuoteMode.NON_NUMERIC, false);
|
||||
|
||||
// Linguistic Variants
|
||||
handler = new LoincLinguisticVariantsHandler(linguisticVariants);
|
||||
iterateOverZipFileCsvOptional(theDescriptors, theUploadProperties.getProperty(LOINC_LINGUISTIC_VARIANTS_FILE.getCode(), LOINC_LINGUISTIC_VARIANTS_FILE_DEFAULT.getCode()), handler, ',', QuoteMode.NON_NUMERIC, false);
|
||||
|
||||
String langFileName = null;
|
||||
for (LoincLinguisticVariantsHandler.LinguisticVariant linguisticVariant : linguisticVariants) {
|
||||
handler = new LoincLinguisticVariantHandler(code2concept, linguisticVariant.getLanguageCode());
|
||||
langFileName = linguisticVariant.getLinguisticVariantFileName();
|
||||
iterateOverZipFileCsvOptional(theDescriptors, theUploadProperties.getProperty(LOINC_LINGUISTIC_VARIANTS_PATH.getCode() + langFileName, LOINC_LINGUISTIC_VARIANTS_PATH_DEFAULT.getCode() + langFileName), handler, ',', QuoteMode.NON_NUMERIC, false);
|
||||
}
|
||||
|
||||
if (theCloseFiles) {
|
||||
IOUtils.closeQuietly(theDescriptors);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
package ca.uhn.fhir.jpa.term.loinc;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||
import ca.uhn.fhir.jpa.term.IZipContentsHandlerCsv;
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.trim;
|
||||
|
||||
public class LoincConsumerNameHandler implements IZipContentsHandlerCsv {
|
||||
|
||||
private final Map<String, TermConcept> myCode2Concept;
|
||||
|
||||
public LoincConsumerNameHandler(Map<String, TermConcept> theCode2concept) {
|
||||
myCode2Concept = theCode2concept;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(CSVRecord theRecord) {
|
||||
|
||||
String loincNumber = trim(theRecord.get("LoincNumber"));
|
||||
if (isBlank(loincNumber)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String consumerName = trim(theRecord.get("ConsumerName"));
|
||||
if (isBlank(consumerName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TermConcept loincCode = myCode2Concept.get(loincNumber);
|
||||
if (loincCode == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
loincCode.addDesignation()
|
||||
.setUseDisplay("ConsumerName")
|
||||
.setValue(consumerName);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
package ca.uhn.fhir.jpa.term.loinc;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.trim;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
|
||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||
import ca.uhn.fhir.jpa.term.IZipContentsHandlerCsv;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermLoaderSvc;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2021 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%
|
||||
*/
|
||||
|
||||
public class LoincLinguisticVariantHandler implements IZipContentsHandlerCsv {
|
||||
|
||||
private final Map<String, TermConcept> myCode2Concept;
|
||||
private final String myLanguageCode;
|
||||
|
||||
public LoincLinguisticVariantHandler(Map<String, TermConcept> theCode2Concept, String theLanguageCode) {
|
||||
myCode2Concept = theCode2Concept;
|
||||
myLanguageCode = theLanguageCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(CSVRecord theRecord) {
|
||||
|
||||
String loincNumber = trim(theRecord.get("LOINC_NUM"));
|
||||
if (isBlank(loincNumber)) {
|
||||
return;
|
||||
}
|
||||
|
||||
TermConcept concept = myCode2Concept.get(loincNumber);
|
||||
if (concept == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
addDesignation(theRecord, concept, "COMPONENT");
|
||||
addDesignation(theRecord, concept, "PROPERTY");
|
||||
addDesignation(theRecord, concept, "TIME_ASPCT");
|
||||
addDesignation(theRecord, concept, "SYSTEM");
|
||||
addDesignation(theRecord, concept, "SCALE_TYP");
|
||||
|
||||
addDesignation(theRecord, concept, "METHOD_TYP");
|
||||
addDesignation(theRecord, concept, "CLASS");
|
||||
addDesignation(theRecord, concept, "SHORTNAME");
|
||||
addDesignation(theRecord, concept, "LONG_COMMON_NAME");
|
||||
addDesignation(theRecord, concept, "RELATEDNAMES2");
|
||||
|
||||
addDesignation(theRecord, concept, "LinguisticVariantDisplayName");
|
||||
|
||||
}
|
||||
|
||||
private void addDesignation(CSVRecord theRecord, TermConcept concept, String fieldName) {
|
||||
|
||||
String field = trim(theRecord.get(fieldName));
|
||||
if (isBlank(field)) {
|
||||
return;
|
||||
}
|
||||
|
||||
concept.addDesignation()
|
||||
.setLanguage(myLanguageCode)
|
||||
.setUseSystem(ITermLoaderSvc.LOINC_URI)
|
||||
.setUseCode(fieldName)
|
||||
.setUseDisplay(fieldName)
|
||||
.setValue(field);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package ca.uhn.fhir.jpa.term.loinc;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.trim;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
import org.apache.commons.csv.CSVRecord;
|
||||
|
||||
import ca.uhn.fhir.jpa.term.IZipContentsHandlerCsv;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Server
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2021 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%
|
||||
*/
|
||||
|
||||
public class LoincLinguisticVariantsHandler implements IZipContentsHandlerCsv {
|
||||
|
||||
private final List<LinguisticVariant> myLinguisticVariants;
|
||||
|
||||
public LoincLinguisticVariantsHandler(List<LinguisticVariant> thelinguisticVariants) {
|
||||
myLinguisticVariants = thelinguisticVariants;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(CSVRecord theRecord) {
|
||||
|
||||
String id = trim(theRecord.get("ID"));
|
||||
if (isBlank(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String isoLanguage = trim(theRecord.get("ISO_LANGUAGE"));
|
||||
if (isBlank(isoLanguage)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String isoCountry = trim(theRecord.get("ISO_COUNTRY"));
|
||||
if (isBlank(isoCountry)) {
|
||||
return;
|
||||
}
|
||||
|
||||
String languageName = trim(theRecord.get("LANGUAGE_NAME"));
|
||||
if (isBlank(languageName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
LinguisticVariant linguisticVariant = new LinguisticVariant(id, isoLanguage, isoCountry, languageName);
|
||||
myLinguisticVariants.add(linguisticVariant);
|
||||
}
|
||||
|
||||
public static class LinguisticVariant {
|
||||
|
||||
private String myId;
|
||||
private String myIsoLanguage;
|
||||
private String myIsoCountry;
|
||||
private String myLanguageName;
|
||||
|
||||
public LinguisticVariant(@NotNull String theId, @NotNull String theIsoLanguage, @NotNull String theIsoCountry, @NotNull String theLanguageName) {
|
||||
this.myId = theId;
|
||||
this.myIsoLanguage = theIsoLanguage;
|
||||
this.myIsoCountry = theIsoCountry;
|
||||
this.myLanguageName = theLanguageName;
|
||||
}
|
||||
|
||||
public String getLinguisticVariantFileName() {
|
||||
return myIsoLanguage + myIsoCountry + myId + "LinguisticVariant.csv";
|
||||
}
|
||||
|
||||
public String getLanguageName() {
|
||||
return myLanguageName;
|
||||
}
|
||||
|
||||
public String getLanguageCode() {
|
||||
return myIsoLanguage + "-" + myIsoCountry;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -117,6 +117,18 @@ public enum LoincUploadPropertiesEnum {
|
|||
LOINC_PARENT_GROUP_FILE("loinc.parent.group.file"),
|
||||
LOINC_PARENT_GROUP_FILE_DEFAULT("AccessoryFiles/GroupFile/ParentGroup.csv"),
|
||||
|
||||
// Consumer Name
|
||||
LOINC_CONSUMER_NAME_FILE("loinc.consumer.name.file"),
|
||||
LOINC_CONSUMER_NAME_FILE_DEFAULT("AccessoryFiles/ConsumerName/ConsumerName.csv"),
|
||||
|
||||
// Linguistic Variants
|
||||
LOINC_LINGUISTIC_VARIANTS_FILE("loinc.linguistic.variants.file"),
|
||||
LOINC_LINGUISTIC_VARIANTS_FILE_DEFAULT("AccessoryFiles/LinguisticVariants/LinguisticVariants.csv"),
|
||||
|
||||
// Linguistic Variants Folder Path which contains variants for different languages
|
||||
LOINC_LINGUISTIC_VARIANTS_PATH("loinc.linguistic.variants.path"),
|
||||
LOINC_LINGUISTIC_VARIANTS_PATH_DEFAULT("AccessoryFiles/LinguisticVariants/"),
|
||||
|
||||
/*
|
||||
* DUPLICATES
|
||||
*/
|
||||
|
|
|
@ -91,3 +91,13 @@ loinc.group.terms.file=AccessoryFiles/GroupFile/GroupLoincTerms.csv
|
|||
## Default value if key not provided: AccessoryFiles/GroupFile/ParentGroup.csv
|
||||
## File may be omitted
|
||||
loinc.parent.group.file=AccessoryFiles/GroupFile/ParentGroup.csv
|
||||
|
||||
# Consumer Names
|
||||
## Default value if key not provided: AccessoryFiles/ConsumerName/ConsumerName.csv
|
||||
## File may be omitted
|
||||
loinc.consumer.name.file=AccessoryFiles/ConsumerName/ConsumerName.csv
|
||||
|
||||
# Linguistic Variants
|
||||
## Default value if key not provided: AccessoryFiles/LinguisticVariants/LinguisticVariants.csv
|
||||
## File may be omitted
|
||||
loinc.linguistic.variants.file=AccessoryFiles/LinguisticVariants/LinguisticVariants.csv
|
|
@ -188,6 +188,39 @@ public class BulkDataExportProviderTest {
|
|||
assertThat(options.getFilters(), containsInAnyOrder("Patient?identifier=foo"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSuccessfulInitiateBulkRequest_Get_MultipleTypeFilters() throws IOException {
|
||||
|
||||
IBulkDataExportSvc.JobInfo jobInfo = new IBulkDataExportSvc.JobInfo()
|
||||
.setJobId(A_JOB_ID);
|
||||
when(myBulkDataExportSvc.submitJob(any(),any(), nullable(RequestDetails.class))).thenReturn(jobInfo);
|
||||
|
||||
String url = "http://localhost:" + myPort + "/" + JpaConstants.OPERATION_EXPORT
|
||||
+ "?" + JpaConstants.PARAM_EXPORT_OUTPUT_FORMAT + "=" + UrlUtil.escapeUrlParam(Constants.CT_FHIR_NDJSON)
|
||||
+ "&" + JpaConstants.PARAM_EXPORT_TYPE + "=" + UrlUtil.escapeUrlParam("Patient,EpisodeOfCare")
|
||||
+ "&" + JpaConstants.PARAM_EXPORT_TYPE_FILTER + "=" + UrlUtil.escapeUrlParam("Patient?_id=P999999990")
|
||||
+ "&" + JpaConstants.PARAM_EXPORT_TYPE_FILTER + "=" + UrlUtil.escapeUrlParam("EpisodeOfCare?patient=P999999990");
|
||||
|
||||
HttpGet get = new HttpGet(url);
|
||||
get.addHeader(Constants.HEADER_PREFER, Constants.HEADER_PREFER_RESPOND_ASYNC);
|
||||
ourLog.info("Request: {}", url);
|
||||
try (CloseableHttpResponse response = myClient.execute(get)) {
|
||||
ourLog.info("Response: {}", response.toString());
|
||||
|
||||
assertEquals(202, response.getStatusLine().getStatusCode());
|
||||
assertEquals("Accepted", response.getStatusLine().getReasonPhrase());
|
||||
assertEquals("http://localhost:" + myPort + "/$export-poll-status?_jobId=" + A_JOB_ID, response.getFirstHeader(Constants.HEADER_CONTENT_LOCATION).getValue());
|
||||
}
|
||||
|
||||
verify(myBulkDataExportSvc, times(1)).submitJob(myBulkDataExportOptionsCaptor.capture(), any(), nullable(RequestDetails.class));
|
||||
BulkDataExportOptions options = myBulkDataExportOptionsCaptor.getValue();
|
||||
assertEquals(Constants.CT_FHIR_NDJSON, options.getOutputFormat());
|
||||
assertThat(options.getResourceTypes(), containsInAnyOrder("Patient", "EpisodeOfCare"));
|
||||
assertThat(options.getSince(), nullValue());
|
||||
assertThat(options.getFilters(), containsInAnyOrder("Patient?_id=P999999990", "EpisodeOfCare?patient=P999999990"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPollForStatus_BUILDING() throws IOException {
|
||||
|
||||
|
|
|
@ -7,7 +7,6 @@ import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
|||
import ca.uhn.fhir.jpa.api.model.DaoMethodOutcome;
|
||||
import ca.uhn.fhir.jpa.batch.BatchJobsConfig;
|
||||
import ca.uhn.fhir.jpa.batch.api.IBatchJobSubmitter;
|
||||
import ca.uhn.fhir.rest.api.server.bulk.BulkDataExportOptions;
|
||||
import ca.uhn.fhir.jpa.bulk.export.api.IBulkDataExportSvc;
|
||||
import ca.uhn.fhir.jpa.bulk.export.job.BulkExportJobParametersBuilder;
|
||||
import ca.uhn.fhir.jpa.bulk.export.job.GroupBulkExportJobParametersBuilder;
|
||||
|
@ -26,6 +25,7 @@ import ca.uhn.fhir.mdm.api.MdmMatchResultEnum;
|
|||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.bulk.BulkDataExportOptions;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.test.utilities.BatchJobHelper;
|
||||
import ca.uhn.fhir.util.HapiExtensions;
|
||||
|
@ -40,6 +40,7 @@ import org.hl7.fhir.r4.model.Binary;
|
|||
import org.hl7.fhir.r4.model.CareTeam;
|
||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||
import org.hl7.fhir.r4.model.Enumerations;
|
||||
import org.hl7.fhir.r4.model.EpisodeOfCare;
|
||||
import org.hl7.fhir.r4.model.Extension;
|
||||
import org.hl7.fhir.r4.model.Group;
|
||||
import org.hl7.fhir.r4.model.Immunization;
|
||||
|
@ -518,6 +519,63 @@ public class BulkDataExportSvcImplR4Test extends BaseJpaR4Test {
|
|||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateBulkExport_WithMultipleTypeFilters() {
|
||||
// Create some resources to load
|
||||
Patient p = new Patient();
|
||||
p.setId("P999999990");
|
||||
p.setActive(true);
|
||||
myPatientDao.update(p);
|
||||
|
||||
EpisodeOfCare eoc = new EpisodeOfCare();
|
||||
eoc.setId("E0");
|
||||
eoc.getPatient().setReference("Patient/P999999990");
|
||||
myEpisodeOfCareDao.update(eoc);
|
||||
|
||||
// Create a bulk job
|
||||
HashSet<String> types = Sets.newHashSet("Patient", "EpisodeOfCare");
|
||||
Set<String> typeFilters = Sets.newHashSet("Patient?_id=P999999990", "EpisodeOfCare?patient=P999999990");
|
||||
BulkDataExportOptions options = new BulkDataExportOptions();
|
||||
options.setExportStyle(BulkDataExportOptions.ExportStyle.SYSTEM);
|
||||
options.setResourceTypes(types);
|
||||
options.setFilters(typeFilters);
|
||||
IBulkDataExportSvc.JobInfo jobDetails = myBulkDataExportSvc.submitJob(options);
|
||||
assertNotNull(jobDetails.getJobId());
|
||||
|
||||
// Check the status
|
||||
IBulkDataExportSvc.JobInfo status = myBulkDataExportSvc.getJobInfoOrThrowResourceNotFound(jobDetails.getJobId());
|
||||
assertEquals(BulkExportJobStatusEnum.SUBMITTED, status.getStatus());
|
||||
assertEquals("/$export?_outputFormat=application%2Ffhir%2Bndjson&_type=EpisodeOfCare,Patient&_typeFilter=Patient%3F_id%3DP999999990&_typeFilter=EpisodeOfCare%3Fpatient%3DP999999990", status.getRequest());
|
||||
|
||||
// Run a scheduled pass to build the export
|
||||
myBulkDataExportSvc.buildExportFiles();
|
||||
|
||||
awaitAllBulkJobCompletions();
|
||||
|
||||
// Fetch the job again
|
||||
status = myBulkDataExportSvc.getJobInfoOrThrowResourceNotFound(jobDetails.getJobId());
|
||||
assertEquals(BulkExportJobStatusEnum.COMPLETE, status.getStatus());
|
||||
assertEquals(2, status.getFiles().size());
|
||||
|
||||
// Iterate over the files
|
||||
for (IBulkDataExportSvc.FileEntry next : status.getFiles()) {
|
||||
Binary nextBinary = myBinaryDao.read(next.getResourceId());
|
||||
assertEquals(Constants.CT_FHIR_NDJSON, nextBinary.getContentType());
|
||||
String nextContents = new String(nextBinary.getContent(), Constants.CHARSET_UTF8);
|
||||
ourLog.info("Next contents for type {}:\n{}", next.getResourceType(), nextContents);
|
||||
|
||||
if ("Patient".equals(next.getResourceType())) {
|
||||
assertThat(nextContents, containsString("\"id\":\"P999999990\""));
|
||||
assertEquals(1, nextContents.split("\n").length);
|
||||
} else if ("EpisodeOfCare".equals(next.getResourceType())) {
|
||||
assertThat(nextContents, containsString("\"id\":\"E0\""));
|
||||
assertEquals(1, nextContents.split("\n").length);
|
||||
} else {
|
||||
fail(next.getResourceType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateBulkExport_WithSince() {
|
||||
|
||||
|
|
|
@ -13,6 +13,7 @@ import ca.uhn.fhir.jpa.bulk.export.api.IBulkDataExportSvc;
|
|||
import ca.uhn.fhir.jpa.config.BaseConfig;
|
||||
import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTableDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedComboTokensNonUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamDateDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamTokenDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceLinkDao;
|
||||
|
@ -161,6 +162,8 @@ public abstract class BaseJpaTest extends BaseTest {
|
|||
@Autowired
|
||||
protected IResourceIndexedSearchParamDateDao myResourceIndexedSearchParamDateDao;
|
||||
@Autowired
|
||||
protected IResourceIndexedComboTokensNonUniqueDao myResourceIndexedComboTokensNonUniqueDao;
|
||||
@Autowired
|
||||
private IdHelperService myIdHelperService;
|
||||
@Autowired
|
||||
private MemoryCacheService myMemoryCacheService;
|
||||
|
@ -306,6 +309,12 @@ public abstract class BaseJpaTest extends BaseTest {
|
|||
});
|
||||
}
|
||||
|
||||
protected void logAllNonUniqueIndexes() {
|
||||
runInTransaction(() -> {
|
||||
ourLog.info("Non unique indexes:\n * {}", myResourceIndexedComboTokensNonUniqueDao.findAll().stream().map(t -> t.toString()).collect(Collectors.joining("\n * ")));
|
||||
});
|
||||
}
|
||||
|
||||
protected void logAllTokenIndexes() {
|
||||
runInTransaction(() -> {
|
||||
ourLog.info("Token indexes:\n * {}", myResourceIndexedSearchParamTokenDao.findAll().stream().map(t -> t.toString()).collect(Collectors.joining("\n * ")));
|
||||
|
|
|
@ -17,7 +17,7 @@ import ca.uhn.fhir.jpa.bulk.export.api.IBulkDataExportSvc;
|
|||
import ca.uhn.fhir.jpa.config.TestDstu3Config;
|
||||
import ca.uhn.fhir.jpa.dao.BaseJpaTest;
|
||||
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedCompositeStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedComboStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamStringDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamTokenDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceReindexJobDao;
|
||||
|
@ -150,7 +150,7 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest {
|
|||
@Qualifier("myCoverageDaoDstu3")
|
||||
protected IFhirResourceDao<Coverage> myCoverageDao;
|
||||
@Autowired
|
||||
protected IResourceIndexedCompositeStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
protected IResourceIndexedComboStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
@Autowired
|
||||
@Qualifier("myAllergyIntoleranceDaoDstu3")
|
||||
protected IFhirResourceDao<AllergyIntolerance> myAllergyIntoleranceDao;
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
package ca.uhn.fhir.jpa.dao.index;
|
||||
|
||||
import ca.uhn.fhir.mdm.util.CanonicalIdentifier;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
class DaoResourceLinkResolverTest {
|
||||
|
||||
@Test
|
||||
public void testLinkResolution() {
|
||||
DaoResourceLinkResolver resolver = new DaoResourceLinkResolver();
|
||||
CanonicalIdentifier canonicalIdentifier = resolver.extractIdentifierFromUrl("Patient?_patient?" +
|
||||
"identifier=http://hapifhir.io/fhir/namingsystem/my_id|123456");
|
||||
assertEquals("http://hapifhir.io/fhir/namingsystem/my_id", canonicalIdentifier.getSystemElement().getValueAsString());
|
||||
assertEquals("123456", canonicalIdentifier.getValueElement().getValueAsString());
|
||||
|
||||
canonicalIdentifier = resolver.extractIdentifierFromUrl("Patient?_patient?" +
|
||||
"identifier=http://hapifhir.io/fhir/namingsystem/my_id|123456&identifier=https://www.id.org/identifiers/member|1101331");
|
||||
assertEquals("http://hapifhir.io/fhir/namingsystem/my_id", canonicalIdentifier.getSystemElement().getValueAsString());
|
||||
assertEquals("123456", canonicalIdentifier.getValueElement().getValueAsString());
|
||||
|
||||
canonicalIdentifier = resolver.extractIdentifierFromUrl("Patient?_tag:not=http://hapifhir.io/fhir/namingsystem/mdm-record-status|GOLDEn_rEcorD" +
|
||||
"&identifier=https://www.my.org/identifiers/memBER|123456");
|
||||
assertEquals("https://www.my.org/identifiers/memBER", canonicalIdentifier.getSystemElement().getValueAsString());
|
||||
assertEquals("123456", canonicalIdentifier.getValueElement().getValueAsString());
|
||||
|
||||
canonicalIdentifier = resolver.extractIdentifierFromUrl("Patient?_tag:not=http://hapifhir.io/fhir/namingsystem/mdm-record-status|GOLDEn_rEcorD");
|
||||
assertNull(canonicalIdentifier);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,35 @@
|
|||
package ca.uhn.fhir.jpa.dao.index;
|
||||
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.*;
|
||||
|
||||
public class IdHelperServiceTest {
|
||||
|
||||
@Test
|
||||
public void testReplaceDefault_AllPartitions() {
|
||||
|
||||
IdHelperService svc = new IdHelperService();
|
||||
PartitionSettings partitionSettings = new PartitionSettings();
|
||||
partitionSettings.setDefaultPartitionId(1);
|
||||
svc.setPartitionSettingsForUnitTest(partitionSettings);
|
||||
|
||||
RequestPartitionId outcome = svc.replaceDefault(RequestPartitionId.allPartitions());
|
||||
assertSame(RequestPartitionId.allPartitions(), outcome);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testReplaceDefault_DefaultPartition() {
|
||||
|
||||
IdHelperService svc = new IdHelperService();
|
||||
PartitionSettings partitionSettings = new PartitionSettings();
|
||||
partitionSettings.setDefaultPartitionId(1);
|
||||
svc.setPartitionSettingsForUnitTest(partitionSettings);
|
||||
|
||||
RequestPartitionId outcome = svc.replaceDefault(RequestPartitionId.defaultPartition());
|
||||
assertEquals(1, outcome.getPartitionIds().get(0));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4;
|
||||
|
||||
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
|
||||
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
|
||||
import ca.uhn.fhir.jpa.search.reindex.ResourceReindexingSvcImpl;
|
||||
import ca.uhn.fhir.jpa.util.SpringObjectCaster;
|
||||
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public abstract class BaseComboParamsR4Test extends BaseJpaR4Test {
|
||||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(BaseComboParamsR4Test.class);
|
||||
@Autowired
|
||||
protected ISearchParamRegistry mySearchParamRegistry;
|
||||
protected List<String> myMessages = new ArrayList<>();
|
||||
private IInterceptorBroadcaster myInterceptorBroadcaster;
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
myModelConfig.setDefaultSearchParamsCanBeOverridden(true);
|
||||
myDaoConfig.setSchedulingDisabled(true);
|
||||
myDaoConfig.setUniqueIndexesEnabled(true);
|
||||
|
||||
myInterceptorBroadcaster = mock(IInterceptorBroadcaster.class);
|
||||
when(mySrd.getInterceptorBroadcaster()).thenReturn(myInterceptorBroadcaster);
|
||||
when(mySrd.getServer().getPagingProvider()).thenReturn(new DatabaseBackedPagingProvider());
|
||||
|
||||
when(myInterceptorBroadcaster.hasHooks(eq(Pointcut.JPA_PERFTRACE_WARNING))).thenReturn(true);
|
||||
when(myInterceptorBroadcaster.hasHooks(eq(Pointcut.JPA_PERFTRACE_INFO))).thenReturn(true);
|
||||
when(myInterceptorBroadcaster.callHooks(eq(Pointcut.JPA_PERFTRACE_INFO), ArgumentMatchers.any(HookParams.class))).thenAnswer(t -> {
|
||||
HookParams params = t.getArgument(1, HookParams.class);
|
||||
myMessages.add("INFO " + params.get(StorageProcessingMessage.class).getMessage());
|
||||
return null;
|
||||
});
|
||||
when(myInterceptorBroadcaster.callHooks(eq(Pointcut.JPA_PERFTRACE_WARNING), ArgumentMatchers.any(HookParams.class))).thenAnswer(t -> {
|
||||
HookParams params = t.getArgument(1, HookParams.class);
|
||||
myMessages.add("WARN " + params.get(StorageProcessingMessage.class).getMessage());
|
||||
return null;
|
||||
});
|
||||
when(myInterceptorBroadcaster.callHooks(eq(Pointcut.JPA_PERFTRACE_SEARCH_REUSING_CACHED), ArgumentMatchers.any(HookParams.class))).thenAnswer(t -> {
|
||||
HookParams params = t.getArgument(1, HookParams.class);
|
||||
myMessages.add("REUSING CACHED SEARCH");
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void after() throws Exception {
|
||||
myModelConfig.setDefaultSearchParamsCanBeOverridden(new ModelConfig().isDefaultSearchParamsCanBeOverridden());
|
||||
myDaoConfig.setUniqueIndexesCheckedBeforeSave(new DaoConfig().isUniqueIndexesCheckedBeforeSave());
|
||||
myDaoConfig.setSchedulingDisabled(new DaoConfig().isSchedulingDisabled());
|
||||
myDaoConfig.setUniqueIndexesEnabled(new DaoConfig().isUniqueIndexesEnabled());
|
||||
myDaoConfig.setReindexThreadCount(new DaoConfig().getReindexThreadCount());
|
||||
|
||||
ResourceReindexingSvcImpl svc = SpringObjectCaster.getTargetObject(myResourceReindexingSvc, ResourceReindexingSvcImpl.class);
|
||||
svc.initExecutor();
|
||||
}
|
||||
|
||||
protected void logCapturedMessages() {
|
||||
ourLog.info("Messages:\n {}", String.join("\n ", myMessages));
|
||||
}
|
||||
|
||||
}
|
|
@ -26,7 +26,8 @@ import ca.uhn.fhir.jpa.dao.data.IMdmLinkDao;
|
|||
import ca.uhn.fhir.jpa.dao.data.IPartitionDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTableDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTagDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedCompositeStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedComboStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedComboTokensNonUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamCoordsDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamDateDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamQuantityDao;
|
||||
|
@ -228,7 +229,9 @@ public abstract class BaseJpaR4Test extends BaseJpaTest implements ITestDataBuil
|
|||
@Autowired
|
||||
protected IResourceIndexedSearchParamDateDao myResourceIndexedSearchParamDateDao;
|
||||
@Autowired
|
||||
protected IResourceIndexedCompositeStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
protected IResourceIndexedComboStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
@Autowired
|
||||
protected IResourceIndexedComboTokensNonUniqueDao myResourceIndexedComboTokensNonUniqueDao;
|
||||
@Autowired
|
||||
@Qualifier("myAllergyIntoleranceDaoR4")
|
||||
protected IFhirResourceDao<AllergyIntolerance> myAllergyIntoleranceDao;
|
||||
|
|
|
@ -0,0 +1,194 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboTokenNonUnique;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.param.DateParam;
|
||||
import ca.uhn.fhir.rest.param.StringParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.util.HapiExtensions;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.BooleanType;
|
||||
import org.hl7.fhir.r4.model.DateType;
|
||||
import org.hl7.fhir.r4.model.Enumerations;
|
||||
import org.hl7.fhir.r4.model.Enumerations.PublicationStatus;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.hl7.fhir.r4.model.SearchParameter;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsInAnyOrder;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
|
||||
public class FhirResourceDaoR4ComboNonUniqueParamTest extends BaseComboParamsR4Test {
|
||||
|
||||
private void createNamesAndGenderSp() {
|
||||
SearchParameter sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/patient-family");
|
||||
sp.setType(Enumerations.SearchParamType.STRING);
|
||||
sp.setCode("family");
|
||||
sp.setExpression("Patient.name.family + '|'");
|
||||
sp.setStatus(PublicationStatus.ACTIVE);
|
||||
sp.addBase("Patient");
|
||||
mySearchParameterDao.update(sp);
|
||||
|
||||
sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/patient-given");
|
||||
sp.setType(Enumerations.SearchParamType.STRING);
|
||||
sp.setCode("given");
|
||||
sp.setExpression("Patient.name.given");
|
||||
sp.setStatus(PublicationStatus.ACTIVE);
|
||||
sp.addBase("Patient");
|
||||
mySearchParameterDao.update(sp);
|
||||
|
||||
sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/patient-gender");
|
||||
sp.setType(Enumerations.SearchParamType.TOKEN);
|
||||
sp.setCode("gender");
|
||||
sp.setExpression("Patient.gender");
|
||||
sp.setStatus(PublicationStatus.ACTIVE);
|
||||
sp.addBase("Patient");
|
||||
mySearchParameterDao.update(sp);
|
||||
|
||||
sp = new SearchParameter();
|
||||
sp.setId("SearchParameter/patient-names-and-gender");
|
||||
sp.setType(Enumerations.SearchParamType.COMPOSITE);
|
||||
sp.setStatus(PublicationStatus.ACTIVE);
|
||||
sp.addBase("Patient");
|
||||
sp.addComponent()
|
||||
.setExpression("Patient")
|
||||
.setDefinition("SearchParameter/patient-family");
|
||||
sp.addComponent()
|
||||
.setExpression("Patient")
|
||||
.setDefinition("SearchParameter/patient-given");
|
||||
sp.addComponent()
|
||||
.setExpression("Patient")
|
||||
.setDefinition("SearchParameter/patient-gender");
|
||||
sp.addExtension()
|
||||
.setUrl(HapiExtensions.EXT_SP_UNIQUE)
|
||||
.setValue(new BooleanType(false));
|
||||
mySearchParameterDao.update(sp);
|
||||
|
||||
mySearchParamRegistry.forceRefresh();
|
||||
|
||||
myMessages.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCreateAndUse() {
|
||||
createNamesAndGenderSp();
|
||||
|
||||
IIdType id1 = createPatient1();
|
||||
assertNotNull(id1);
|
||||
|
||||
IIdType id2 = createPatient2();
|
||||
assertNotNull(id2);
|
||||
|
||||
logAllNonUniqueIndexes();
|
||||
runInTransaction(() -> {
|
||||
List<ResourceIndexedComboTokenNonUnique> indexedTokens = myResourceIndexedComboTokensNonUniqueDao.findAll();
|
||||
indexedTokens.sort(Comparator.comparing(t -> t.getId()));
|
||||
assertEquals(2, indexedTokens.size());
|
||||
assertEquals(-7504889232313729794L, indexedTokens.get(0).getHashComplete().longValue());
|
||||
});
|
||||
|
||||
myMessages.clear();
|
||||
SearchParameterMap params = SearchParameterMap.newSynchronous();
|
||||
params.add("family", new StringParam("fAmIlY1|")); // weird casing to test normalization
|
||||
params.add("given", new StringParam("gIVEn1"));
|
||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
||||
myCaptureQueriesListener.clear();
|
||||
IBundleProvider results = myPatientDao.search(params, mySrd);
|
||||
List<String> actual = toUnqualifiedVersionlessIdValues(results);
|
||||
myCaptureQueriesListener.logSelectQueries();
|
||||
assertThat(actual, containsInAnyOrder(id1.toUnqualifiedVersionless().getValue()));
|
||||
|
||||
String sql = myCaptureQueriesListener.getSelectQueries().get(0).getSql(true, false);
|
||||
assertEquals("SELECT t0.RES_ID FROM HFJ_IDX_CMB_TOK_NU t0 WHERE (t0.IDX_STRING = 'Patient?family=FAMILY1%5C%7C&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale&given=GIVEN1')", sql);
|
||||
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString(), containsString("[INFO Using NON_UNIQUE index for query for search: Patient?family=FAMILY1%5C%7C&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale&given=GIVEN1]"));
|
||||
myMessages.clear();
|
||||
|
||||
// Remove 1, add another
|
||||
|
||||
myPatientDao.delete(id1);
|
||||
|
||||
IIdType id3 = createPatient1();
|
||||
assertNotNull(id3);
|
||||
|
||||
params = SearchParameterMap.newSynchronous();
|
||||
params.add("family", new StringParam("fAmIlY1|")); // weird casing to test normalization
|
||||
params.add("given", new StringParam("gIVEn1"));
|
||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
||||
results = myPatientDao.search(params, mySrd);
|
||||
actual = toUnqualifiedVersionlessIdValues(results);
|
||||
myCaptureQueriesListener.logSelectQueries();
|
||||
assertThat(actual, containsInAnyOrder(id3.toUnqualifiedVersionless().getValue()));
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSearchWithExtraParameters() {
|
||||
createNamesAndGenderSp();
|
||||
|
||||
IIdType id1 = createPatient1();
|
||||
assertNotNull(id1);
|
||||
|
||||
IIdType id2 = createPatient2();
|
||||
assertNotNull(id2);
|
||||
|
||||
logAllNonUniqueIndexes();
|
||||
runInTransaction(() -> {
|
||||
List<ResourceIndexedComboTokenNonUnique> indexedTokens = myResourceIndexedComboTokensNonUniqueDao.findAll();
|
||||
indexedTokens.sort(Comparator.comparing(t -> t.getId()));
|
||||
assertEquals(2, indexedTokens.size());
|
||||
assertEquals(-7504889232313729794L, indexedTokens.get(0).getHashComplete().longValue());
|
||||
});
|
||||
|
||||
myMessages.clear();
|
||||
SearchParameterMap params = SearchParameterMap.newSynchronous();
|
||||
params.add("family", new StringParam("fAmIlY1|")); // weird casing to test normalization
|
||||
params.add("given", new StringParam("gIVEn1"));
|
||||
params.add("gender", new TokenParam("http://hl7.org/fhir/administrative-gender", "male"));
|
||||
params.add("birthdate", new DateParam("2021-02-02"));
|
||||
myCaptureQueriesListener.clear();
|
||||
IBundleProvider results = myPatientDao.search(params, mySrd);
|
||||
List<String> actual = toUnqualifiedVersionlessIdValues(results);
|
||||
myCaptureQueriesListener.logSelectQueries();
|
||||
assertThat(actual, containsInAnyOrder(id1.toUnqualifiedVersionless().getValue()));
|
||||
|
||||
String sql = myCaptureQueriesListener.getSelectQueries().get(0).getSql(true, false);
|
||||
assertEquals("SELECT t1.RES_ID FROM HFJ_RESOURCE t1 LEFT OUTER JOIN HFJ_IDX_CMB_TOK_NU t0 ON (t1.RES_ID = t0.RES_ID) LEFT OUTER JOIN HFJ_SPIDX_DATE t2 ON (t1.RES_ID = t2.RES_ID) WHERE ((t0.IDX_STRING = 'Patient?family=FAMILY1%5C%7C&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale&given=GIVEN1') AND ((t2.HASH_IDENTITY = '5247847184787287691') AND ((t2.SP_VALUE_LOW_DATE_ORDINAL >= '20210202') AND (t2.SP_VALUE_HIGH_DATE_ORDINAL <= '20210202'))))", sql);
|
||||
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString(), containsString("[INFO Using NON_UNIQUE index for query for search: Patient?family=FAMILY1%5C%7C&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale&given=GIVEN1]"));
|
||||
myMessages.clear();
|
||||
|
||||
}
|
||||
|
||||
|
||||
private IIdType createPatient2() {
|
||||
Patient pt2 = new Patient();
|
||||
pt2.getNameFirstRep().setFamily("Family2").addGiven("Given2");
|
||||
pt2.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
pt2.setBirthDateElement(new DateType("2021-02-02"));
|
||||
IIdType id2 = myPatientDao.create(pt2).getId().toUnqualified();
|
||||
return id2;
|
||||
}
|
||||
|
||||
private IIdType createPatient1() {
|
||||
Patient pt1 = new Patient();
|
||||
pt1.getNameFirstRep().setFamily("Family1").addGiven("Given1");
|
||||
pt1.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
pt1.setBirthDateElement(new DateType("2021-02-02"));
|
||||
return myPatientDao.create(pt1).getId().toUnqualified();
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -1,19 +1,12 @@
|
|||
package ca.uhn.fhir.jpa.dao.r4;
|
||||
|
||||
import ca.uhn.fhir.context.ComboSearchParamType;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.interceptor.api.HookParams;
|
||||
import ca.uhn.fhir.interceptor.api.IInterceptorBroadcaster;
|
||||
import ca.uhn.fhir.interceptor.api.Pointcut;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.model.search.StorageProcessingMessage;
|
||||
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
|
||||
import ca.uhn.fhir.jpa.search.reindex.ResourceReindexingSvcImpl;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.searchparam.util.JpaParamUtil;
|
||||
import ca.uhn.fhir.rest.server.util.ISearchParamRegistry;
|
||||
import ca.uhn.fhir.jpa.util.SpringObjectCaster;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.param.DateParam;
|
||||
|
@ -27,17 +20,12 @@ import ca.uhn.fhir.util.HapiExtensions;
|
|||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.*;
|
||||
import org.hl7.fhir.r4.model.Enumerations.PublicationStatus;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.mockito.ArgumentMatchers;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.support.TransactionCallbackWithoutResult;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
@ -57,56 +45,10 @@ import static org.junit.jupiter.api.Assertions.assertNotNull;
|
|||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
import static org.mockito.ArgumentMatchers.eq;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
||||
public class FhirResourceDaoR4ComboUniqueParamTest extends BaseComboParamsR4Test {
|
||||
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4UniqueSearchParamTest.class);
|
||||
@Autowired
|
||||
private ISearchParamRegistry mySearchParamRegistry;
|
||||
private IInterceptorBroadcaster myInterceptorBroadcaster;
|
||||
private List<String> myMessages = new ArrayList<>();
|
||||
|
||||
@AfterEach
|
||||
public void after() throws Exception {
|
||||
myModelConfig.setDefaultSearchParamsCanBeOverridden(new ModelConfig().isDefaultSearchParamsCanBeOverridden());
|
||||
myDaoConfig.setUniqueIndexesCheckedBeforeSave(new DaoConfig().isUniqueIndexesCheckedBeforeSave());
|
||||
myDaoConfig.setSchedulingDisabled(new DaoConfig().isSchedulingDisabled());
|
||||
myDaoConfig.setUniqueIndexesEnabled(new DaoConfig().isUniqueIndexesEnabled());
|
||||
myDaoConfig.setReindexThreadCount(new DaoConfig().getReindexThreadCount());
|
||||
|
||||
ResourceReindexingSvcImpl svc = SpringObjectCaster.getTargetObject(myResourceReindexingSvc, ResourceReindexingSvcImpl.class);
|
||||
svc.initExecutor();
|
||||
}
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
myModelConfig.setDefaultSearchParamsCanBeOverridden(true);
|
||||
myDaoConfig.setSchedulingDisabled(true);
|
||||
myDaoConfig.setUniqueIndexesEnabled(true);
|
||||
|
||||
myInterceptorBroadcaster = mock(IInterceptorBroadcaster.class);
|
||||
when(mySrd.getInterceptorBroadcaster()).thenReturn(myInterceptorBroadcaster);
|
||||
when(mySrd.getServer().getPagingProvider()).thenReturn(new DatabaseBackedPagingProvider());
|
||||
|
||||
when(myInterceptorBroadcaster.hasHooks(eq(Pointcut.JPA_PERFTRACE_WARNING))).thenReturn(true);
|
||||
when(myInterceptorBroadcaster.hasHooks(eq(Pointcut.JPA_PERFTRACE_INFO))).thenReturn(true);
|
||||
when(myInterceptorBroadcaster.callHooks(eq(Pointcut.JPA_PERFTRACE_INFO), ArgumentMatchers.any(HookParams.class))).thenAnswer(t -> {
|
||||
HookParams params = t.getArgument(1, HookParams.class);
|
||||
myMessages.add("INFO " + params.get(StorageProcessingMessage.class).getMessage());
|
||||
return null;
|
||||
});
|
||||
when(myInterceptorBroadcaster.callHooks(eq(Pointcut.JPA_PERFTRACE_WARNING), ArgumentMatchers.any(HookParams.class))).thenAnswer(t -> {
|
||||
HookParams params = t.getArgument(1, HookParams.class);
|
||||
myMessages.add("WARN " + params.get(StorageProcessingMessage.class).getMessage());
|
||||
return null;
|
||||
});
|
||||
when(myInterceptorBroadcaster.callHooks(eq(Pointcut.JPA_PERFTRACE_SEARCH_REUSING_CACHED), ArgumentMatchers.any(HookParams.class))).thenAnswer(t -> {
|
||||
HookParams params = t.getArgument(1, HookParams.class);
|
||||
myMessages.add("REUSING CACHED SEARCH");
|
||||
return null;
|
||||
});
|
||||
}
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoR4ComboUniqueParamTest.class);
|
||||
|
||||
|
||||
private void createUniqueBirthdateAndGenderSps() {
|
||||
|
@ -647,7 +589,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
|
||||
// Make sure entries are saved
|
||||
runInTransaction(() -> {
|
||||
List<ResourceIndexedCompositeStringUnique> all = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> all = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
assertEquals(2, all.size());
|
||||
});
|
||||
|
||||
|
@ -691,7 +633,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(@Nonnull TransactionStatus status) {
|
||||
List<ResourceIndexedCompositeStringUnique> all = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> all = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
assertEquals(2, all.size());
|
||||
}
|
||||
});
|
||||
|
@ -706,7 +648,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
ResourceReindexingSvcImpl svc = SpringObjectCaster.getTargetObject(myResourceReindexingSvc, ResourceReindexingSvcImpl.class);
|
||||
svc.initExecutor();
|
||||
|
||||
List<RuntimeSearchParam> uniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams("Observation");
|
||||
List<RuntimeSearchParam> uniqueSearchParams = mySearchParamRegistry.getActiveComboSearchParams("Observation");
|
||||
assertEquals(0, uniqueSearchParams.size());
|
||||
|
||||
Patient pt1 = new Patient();
|
||||
|
@ -735,7 +677,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
|
||||
createUniqueObservationSubjectDateCode();
|
||||
|
||||
uniqueSearchParams = mySearchParamRegistry.getActiveUniqueSearchParams("Observation");
|
||||
uniqueSearchParams = mySearchParamRegistry.getActiveComboSearchParams("Observation");
|
||||
assertEquals(1, uniqueSearchParams.size());
|
||||
assertEquals(3, uniqueSearchParams.get(0).getComponents().size());
|
||||
|
||||
|
@ -745,7 +687,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
assertEquals(0, myResourceReindexingSvc.forceReindexingPass());
|
||||
|
||||
runInTransaction(() -> {
|
||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
assertEquals(1, uniques.size(), uniques.toString());
|
||||
assertThat(uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue(), either(equalTo("Observation/" + id2.getIdPart())).or(equalTo("Observation/" + id3.getIdPart())));
|
||||
assertEquals("Observation?code=foo%7Cbar&date=2011-01-01&subject=Patient%2F" + id1.getIdPart(), uniques.get(0).getIndexString());
|
||||
|
@ -753,7 +695,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
myResourceIndexedCompositeStringUniqueDao.deleteAll();
|
||||
});
|
||||
|
||||
assertEquals(1, mySearchParamRegistry.getActiveUniqueSearchParams("Observation").size());
|
||||
assertEquals(1, mySearchParamRegistry.getActiveComboSearchParams("Observation").size());
|
||||
|
||||
myResourceReindexingSvc.markAllResourcesForReindexing("Observation");
|
||||
assertEquals(1, myResourceReindexingSvc.forceReindexingPass());
|
||||
|
@ -762,7 +704,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
assertEquals(0, myResourceReindexingSvc.forceReindexingPass());
|
||||
|
||||
runInTransaction(() -> {
|
||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
assertEquals(1, uniques.size(), uniques.toString());
|
||||
assertThat(uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue(), either(equalTo("Observation/" + id2.getIdPart())).or(equalTo("Observation/" + id3.getIdPart())));
|
||||
assertEquals("Observation?code=foo%7Cbar&date=2011-01-01&subject=Patient%2F" + id1.getIdPart(), uniques.get(0).getIndexString());
|
||||
|
@ -833,7 +775,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(@Nonnull TransactionStatus status) {
|
||||
List<ResourceIndexedCompositeStringUnique> all = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> all = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
assertEquals(2, all.size());
|
||||
}
|
||||
});
|
||||
|
@ -873,7 +815,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
});
|
||||
|
||||
runInTransaction(() -> {
|
||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
ourLog.info("** Uniques: {}", uniques);
|
||||
assertEquals(1, uniques.size(), uniques.toString());
|
||||
assertEquals("Coverage/" + id3.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue());
|
||||
|
@ -1042,7 +984,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
|
||||
@Override
|
||||
protected void doInTransactionWithoutResult(@Nonnull TransactionStatus status) {
|
||||
List<ResourceIndexedCompositeStringUnique> all = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> all = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
assertEquals(1, all.size(), all.toString());
|
||||
}
|
||||
});
|
||||
|
@ -1074,7 +1016,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
assertThat(toUnqualifiedVersionlessIdValues(results), containsInAnyOrder(id1.getValue()));
|
||||
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString(), containsString("Using unique index for query for search: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||
assertThat(myMessages.toString(), containsString("Using UNIQUE index for query for search: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||
myMessages.clear();
|
||||
|
||||
}
|
||||
|
@ -1102,7 +1044,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
String searchId = results.getUuid();
|
||||
assertThat(toUnqualifiedVersionlessIdValues(results), containsInAnyOrder(id1));
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString(), containsString("Using unique index for query for search: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||
assertThat(myMessages.toString(), containsString("Using UNIQUE index for query for search: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||
myMessages.clear();
|
||||
|
||||
// Other order
|
||||
|
@ -1126,7 +1068,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
results = myPatientDao.search(params, mySrd);
|
||||
assertThat(toUnqualifiedVersionlessIdValues(results), empty());
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString(), containsString("Using unique index for query for search: Patient?birthdate=2011-01-03&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||
assertThat(myMessages.toString(), containsString("Using UNIQUE index for query for search: Patient?birthdate=2011-01-03&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||
myMessages.clear();
|
||||
|
||||
myMessages.clear();
|
||||
|
@ -1151,7 +1093,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
pt1.setBirthDateElement(new DateType("2011-01-01"));
|
||||
IIdType id1 = myPatientDao.create(pt1).getId().toUnqualifiedVersionless();
|
||||
|
||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
assertEquals(1, uniques.size(), uniques.toString());
|
||||
assertEquals("Patient/" + id1.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue());
|
||||
assertEquals("Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale", uniques.get(0).getIndexString());
|
||||
|
@ -1161,7 +1103,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
public void testUniqueValuesAreIndexed_RefAndDateAndToken() {
|
||||
createUniqueObservationSubjectDateCode();
|
||||
|
||||
List<ResourceIndexedCompositeStringUnique> uniques;
|
||||
List<ResourceIndexedComboStringUnique> uniques;
|
||||
uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
assertEquals(0, uniques.size(), uniques.toString());
|
||||
|
||||
|
@ -1190,7 +1132,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
@Test
|
||||
public void testUniqueValuesAreIndexed_Reference_UsingModifierSyntax() {
|
||||
createUniqueNameAndManagingOrganizationSps();
|
||||
List<ResourceIndexedCompositeStringUnique> uniques;
|
||||
List<ResourceIndexedComboStringUnique> uniques;
|
||||
|
||||
Organization org = new Organization();
|
||||
org.setId("Organization/ORG");
|
||||
|
@ -1204,7 +1146,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
IIdType id1 = myPatientDao.update(pt1, "Patient?name=FAMILY1&organization:Organization=ORG", mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString(), containsString("Using unique index for query for search: Patient?name=FAMILY1&organization=Organization%2FORG"));
|
||||
assertThat(myMessages.toString(), containsString("Using UNIQUE index for query for search: Patient?name=FAMILY1&organization=Organization%2FORG"));
|
||||
myMessages.clear();
|
||||
|
||||
uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
|
@ -1221,7 +1163,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
id1 = myPatientDao.update(pt1, "Patient?name=FAMILY1&organization:Organization=ORG", mySrd).getId().toUnqualifiedVersionless();
|
||||
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString(), containsString("Using unique index for query for search: Patient?name=FAMILY1&organization=Organization%2FORG"));
|
||||
assertThat(myMessages.toString(), containsString("Using UNIQUE index for query for search: Patient?name=FAMILY1&organization=Organization%2FORG"));
|
||||
myMessages.clear();
|
||||
|
||||
uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
|
@ -1231,10 +1173,6 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
|
||||
}
|
||||
|
||||
private void logCapturedMessages() {
|
||||
ourLog.info("Messages:\n {}", String.join("\n ", myMessages));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUniqueValuesAreIndexed_StringAndReference() {
|
||||
createUniqueNameAndManagingOrganizationSps();
|
||||
|
@ -1253,7 +1191,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
pt1.setManagingOrganization(new Reference("Organization/ORG"));
|
||||
IIdType id1 = myPatientDao.create(pt1).getId().toUnqualifiedVersionless();
|
||||
|
||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
Collections.sort(uniques);
|
||||
|
||||
assertEquals(3, uniques.size());
|
||||
|
@ -1270,7 +1208,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
@Test
|
||||
public void testUniqueValuesAreIndexed_StringAndReference_UsingConditional() {
|
||||
createUniqueNameAndManagingOrganizationSps();
|
||||
List<ResourceIndexedCompositeStringUnique> uniques;
|
||||
List<ResourceIndexedComboStringUnique> uniques;
|
||||
|
||||
Organization org = new Organization();
|
||||
org.setId("Organization/ORG");
|
||||
|
@ -1303,7 +1241,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
@Test
|
||||
public void testUniqueValuesAreIndexed_StringAndReference_UsingConditionalInTransaction() {
|
||||
createUniqueNameAndManagingOrganizationSps();
|
||||
List<ResourceIndexedCompositeStringUnique> uniques;
|
||||
List<ResourceIndexedComboStringUnique> uniques;
|
||||
|
||||
Organization org = new Organization();
|
||||
org.setId("Organization/ORG");
|
||||
|
@ -1385,7 +1323,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
createUniqueBirthdateAndGenderSps();
|
||||
|
||||
Patient pt;
|
||||
List<ResourceIndexedCompositeStringUnique> uniques;
|
||||
List<ResourceIndexedComboStringUnique> uniques;
|
||||
|
||||
pt = new Patient();
|
||||
pt.setGender(Enumerations.AdministrativeGender.MALE);
|
||||
|
@ -1416,7 +1354,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
org.setName("ORG");
|
||||
myOrganizationDao.update(org);
|
||||
|
||||
List<ResourceIndexedCompositeStringUnique> uniques;
|
||||
List<ResourceIndexedComboStringUnique> uniques;
|
||||
Patient pt;
|
||||
|
||||
pt = new Patient();
|
||||
|
@ -1464,7 +1402,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
myResourceReindexingSvc.forceReindexingPass();
|
||||
myResourceReindexingSvc.forceReindexingPass();
|
||||
|
||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
List<ResourceIndexedComboStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAll();
|
||||
assertEquals(1, uniques.size(), uniques.toString());
|
||||
assertEquals("Observation/" + id2.getIdPart(), uniques.get(0).getResource().getIdDt().toUnqualifiedVersionless().getValue());
|
||||
assertEquals("Observation?code=foo%7Cbar&date=2011-01-01&subject=Patient%2F" + id1.getIdPart(), uniques.get(0).getIndexString());
|
||||
|
@ -1486,10 +1424,10 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
@Test
|
||||
public void testDetectUniqueSearchParams() {
|
||||
createUniqueBirthdateAndGenderSps();
|
||||
List<RuntimeSearchParam> params = mySearchParamRegistry.getActiveUniqueSearchParams("Patient");
|
||||
List<RuntimeSearchParam> params = mySearchParamRegistry.getActiveComboSearchParams("Patient");
|
||||
|
||||
assertEquals(1, params.size());
|
||||
assertEquals(params.get(0).isUnique(), true);
|
||||
assertEquals(ComboSearchParamType.UNIQUE, params.get(0).getComboSearchParamType());
|
||||
assertEquals(2, params.get(0).getComponents().size());
|
||||
|
||||
// Should be alphabetical order
|
||||
|
@ -1565,7 +1503,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
|
|||
assertThat(toUnqualifiedVersionlessIdValues(results), containsInAnyOrder(id2.getValue()));
|
||||
|
||||
logCapturedMessages();
|
||||
assertThat(myMessages.toString(), containsString("Using unique index for query for search: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||
assertThat(myMessages.toString(), containsString("Using UNIQUE index for query for search: Patient?birthdate=2011-01-01&gender=http%3A%2F%2Fhl7.org%2Ffhir%2Fadministrative-gender%7Cmale"));
|
||||
myMessages.clear();
|
||||
|
||||
}
|
|
@ -12,7 +12,7 @@ import ca.uhn.fhir.jpa.model.entity.ForcedId;
|
|||
import ca.uhn.fhir.jpa.model.entity.PartitionablePartitionId;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTable;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceHistoryTag;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedComboStringUnique;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamDate;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceLink;
|
||||
|
@ -435,7 +435,7 @@ public class PartitioningSqlR4Test extends BasePartitioningR4Test {
|
|||
assertEquals(myPartitionDate, presents.get(0).getPartitionId().getPartitionDate());
|
||||
|
||||
// HFJ_IDX_CMP_STRING_UNIQ
|
||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAllForResourceIdForUnitTest(patientId);
|
||||
List<ResourceIndexedComboStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAllForResourceIdForUnitTest(patientId);
|
||||
assertEquals(1, uniques.size());
|
||||
assertEquals(myPartitionId, uniques.get(0).getPartitionId().getPartitionId().intValue());
|
||||
assertEquals(myPartitionDate, uniques.get(0).getPartitionId().getPartitionDate());
|
||||
|
@ -519,7 +519,7 @@ public class PartitioningSqlR4Test extends BasePartitioningR4Test {
|
|||
assertEquals(myPartitionDate, presents.get(0).getPartitionId().getPartitionDate());
|
||||
|
||||
// HFJ_IDX_CMP_STRING_UNIQ
|
||||
List<ResourceIndexedCompositeStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAllForResourceIdForUnitTest(patientId);
|
||||
List<ResourceIndexedComboStringUnique> uniques = myResourceIndexedCompositeStringUniqueDao.findAllForResourceIdForUnitTest(patientId);
|
||||
assertEquals(1, uniques.size());
|
||||
assertEquals(null, uniques.get(0).getPartitionId().getPartitionId());
|
||||
assertEquals(myPartitionDate, uniques.get(0).getPartitionId().getPartitionDate());
|
||||
|
|
|
@ -327,7 +327,7 @@ public class SearchParamExtractorR4Test {
|
|||
public void testExtensionContainingReference() {
|
||||
String path = "Patient.extension('http://patext').value.as(Reference)";
|
||||
|
||||
RuntimeSearchParam sp = new RuntimeSearchParam(null, null, "extpat", "Patient SP", path, RestSearchParameterTypeEnum.REFERENCE, new HashSet<>(), Sets.newHashSet("Patient"), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, false, null, null);
|
||||
RuntimeSearchParam sp = new RuntimeSearchParam(null, null, "extpat", "Patient SP", path, RestSearchParameterTypeEnum.REFERENCE, new HashSet<>(), Sets.newHashSet("Patient"), RuntimeSearchParam.RuntimeSearchParamStatusEnum.ACTIVE, null, null, null);
|
||||
mySearchParamRegistry.addSearchParam(sp);
|
||||
|
||||
Patient patient = new Patient();
|
||||
|
@ -440,7 +440,7 @@ public class SearchParamExtractorR4Test {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName, Set<String> theParamNames) {
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName, Set<String> theParamNames) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
@ -451,7 +451,7 @@ public class SearchParamExtractorR4Test {
|
|||
}
|
||||
|
||||
@Override
|
||||
public List<RuntimeSearchParam> getActiveUniqueSearchParams(String theResourceName) {
|
||||
public List<RuntimeSearchParam> getActiveComboSearchParams(String theResourceName) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
|
|
|
@ -22,7 +22,7 @@ import ca.uhn.fhir.jpa.dao.BaseJpaTest;
|
|||
import ca.uhn.fhir.jpa.dao.IFulltextSearchSvc;
|
||||
import ca.uhn.fhir.jpa.dao.data.IForcedIdDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceHistoryTableDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedCompositeStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedComboStringUniqueDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamDateDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamQuantityDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.IResourceIndexedSearchParamStringDao;
|
||||
|
@ -185,7 +185,7 @@ public abstract class BaseJpaR5Test extends BaseJpaTest implements ITestDataBuil
|
|||
@Autowired
|
||||
protected IResourceIndexedSearchParamDateDao myResourceIndexedSearchParamDateDao;
|
||||
@Autowired
|
||||
protected IResourceIndexedCompositeStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
protected IResourceIndexedComboStringUniqueDao myResourceIndexedCompositeStringUniqueDao;
|
||||
@Autowired
|
||||
@Qualifier("myAllergyIntoleranceDaoR5")
|
||||
protected IFhirResourceDao<AllergyIntolerance> myAllergyIntoleranceDao;
|
||||
|
|
|
@ -5,11 +5,13 @@ import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4SystemTest;
|
|||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.jpa.searchparam.extractor.ISearchParamExtractor;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
import ca.uhn.fhir.rest.param.TokenOrListParam;
|
||||
import ca.uhn.fhir.rest.param.TokenParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
|
||||
import org.hl7.fhir.r4.model.Encounter;
|
||||
import org.hl7.fhir.r4.model.Enumerations;
|
||||
import org.hl7.fhir.r4.model.IdType;
|
||||
import org.hl7.fhir.r4.model.Observation;
|
||||
|
@ -18,6 +20,7 @@ import org.hl7.fhir.r4.model.Patient;
|
|||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
@ -31,9 +34,12 @@ public class PatientIdPartitionInterceptorTest extends BaseJpaR4SystemTest {
|
|||
private PatientIdPartitionInterceptor mySvc;
|
||||
private ForceOffsetSearchModeInterceptor myForceOffsetSearchModeInterceptor;
|
||||
|
||||
@Autowired
|
||||
private ISearchParamExtractor mySearchParamExtractor;
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
mySvc = new PatientIdPartitionInterceptor(myFhirCtx);
|
||||
mySvc = new PatientIdPartitionInterceptor(myFhirCtx, mySearchParamExtractor);
|
||||
myForceOffsetSearchModeInterceptor = new ForceOffsetSearchModeInterceptor();
|
||||
|
||||
myInterceptorRegistry.registerInterceptor(mySvc);
|
||||
|
@ -95,6 +101,24 @@ public class PatientIdPartitionInterceptorTest extends BaseJpaR4SystemTest {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Encounter.subject has a FHIRPath expression with a resolve() on it
|
||||
*/
|
||||
@Test
|
||||
public void testCreateEncounter_ValidMembershipInCompartment() {
|
||||
createPatientA();
|
||||
|
||||
Encounter encounter = new Encounter();
|
||||
encounter.getSubject().setReference("Patient/A");
|
||||
Long id = myEncounterDao.create(encounter).getId().getIdPartAsLong();
|
||||
|
||||
runInTransaction(() -> {
|
||||
ResourceTable observation = myResourceTableDao.findById(id).orElseThrow(() -> new IllegalArgumentException());
|
||||
assertEquals("Encounter", observation.getResourceType());
|
||||
assertEquals(65, observation.getPartitionId().getPartitionId());
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Type is not in the patient compartment
|
||||
*/
|
||||
|
|
|
@ -45,6 +45,7 @@ public class JpaPackageCacheTest extends BaseJpaR4Test {
|
|||
public void disablePartitioning() {
|
||||
myPartitionSettings.setPartitioningEnabled(false);
|
||||
myPartitionSettings.setDefaultPartitionId(new PartitionSettings().getDefaultPartitionId());
|
||||
myPartitionSettings.setUnnamedPartitionMode(false);
|
||||
myInterceptorService.unregisterInterceptor(myRequestTenantPartitionInterceptor);
|
||||
}
|
||||
|
||||
|
@ -103,6 +104,38 @@ public class JpaPackageCacheTest extends BaseJpaR4Test {
|
|||
assertEquals("Deleting package basisprofil.de#0.2.40", deleteOutcomeMsgs.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSaveAndDeletePackageUnnamedPartitionsEnabled() throws IOException {
|
||||
myPartitionSettings.setPartitioningEnabled(true);
|
||||
myPartitionSettings.setDefaultPartitionId(0);
|
||||
myPartitionSettings.setUnnamedPartitionMode(true);
|
||||
myInterceptorService.registerInterceptor(new PatientIdPartitionInterceptor());
|
||||
myInterceptorService.registerInterceptor(myRequestTenantPartitionInterceptor);
|
||||
|
||||
try (InputStream stream = ClasspathUtil.loadResourceAsStream("/packages/hl7.fhir.uv.shorthand-0.12.0.tgz")) {
|
||||
myPackageCacheManager.addPackageToCache("hl7.fhir.uv.shorthand", "0.12.0", stream, "hl7.fhir.uv.shorthand");
|
||||
}
|
||||
|
||||
NpmPackage pkg;
|
||||
|
||||
pkg = myPackageCacheManager.loadPackage("hl7.fhir.uv.shorthand", null);
|
||||
assertEquals("0.12.0", pkg.version());
|
||||
|
||||
pkg = myPackageCacheManager.loadPackage("hl7.fhir.uv.shorthand", "0.12.0");
|
||||
assertEquals("0.12.0", pkg.version());
|
||||
|
||||
try {
|
||||
myPackageCacheManager.loadPackage("hl7.fhir.uv.shorthand", "99");
|
||||
fail();
|
||||
} catch (ResourceNotFoundException e) {
|
||||
assertEquals("Unable to locate package hl7.fhir.uv.shorthand#99", e.getMessage());
|
||||
}
|
||||
|
||||
PackageDeleteOutcomeJson deleteOutcomeJson = myPackageCacheManager.uninstallPackage("hl7.fhir.uv.shorthand", "0.12.0");
|
||||
List<String> deleteOutcomeMsgs = deleteOutcomeJson.getMessage();
|
||||
assertEquals("Deleting package hl7.fhir.uv.shorthand#0.12.0", deleteOutcomeMsgs.get(0));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSavePackageWithLongDescription() throws IOException {
|
||||
try (InputStream stream = ClasspathUtil.loadResourceAsStream("/packages/package-davinci-cdex-0.2.0.tgz")) {
|
||||
|
|
|
@ -10,6 +10,7 @@ import ca.uhn.fhir.jpa.dao.data.INpmPackageDao;
|
|||
import ca.uhn.fhir.jpa.dao.data.INpmPackageVersionDao;
|
||||
import ca.uhn.fhir.jpa.dao.data.INpmPackageVersionResourceDao;
|
||||
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.model.entity.NpmPackageEntity;
|
||||
import ca.uhn.fhir.jpa.model.entity.NpmPackageVersionEntity;
|
||||
import ca.uhn.fhir.jpa.model.entity.NpmPackageVersionResourceEntity;
|
||||
|
@ -127,6 +128,8 @@ public class NpmR4Test extends BaseJpaR4Test {
|
|||
myDaoConfig.setAllowExternalReferences(new DaoConfig().isAllowExternalReferences());
|
||||
myDaoConfig.setAutoCreatePlaceholderReferenceTargets(new DaoConfig().isAutoCreatePlaceholderReferenceTargets());
|
||||
myPartitionSettings.setPartitioningEnabled(false);
|
||||
myPartitionSettings.setUnnamedPartitionMode(false);
|
||||
myPartitionSettings.setDefaultPartitionId(new PartitionSettings().getDefaultPartitionId());
|
||||
myInterceptorService.unregisterInterceptor(myRequestTenantPartitionInterceptor);
|
||||
}
|
||||
|
||||
|
@ -451,6 +454,31 @@ public class NpmR4Test extends BaseJpaR4Test {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInstallR4Package_Twice_partitioningEnabled() throws Exception {
|
||||
myDaoConfig.setAllowExternalReferences(true);
|
||||
myPartitionSettings.setPartitioningEnabled(true);
|
||||
myInterceptorService.registerInterceptor(myRequestTenantPartitionInterceptor);
|
||||
|
||||
byte[] bytes = loadClasspathBytes("/packages/hl7.fhir.uv.shorthand-0.12.0.tgz");
|
||||
myFakeNpmServlet.myResponses.put("/hl7.fhir.uv.shorthand/0.12.0", bytes);
|
||||
|
||||
PackageInstallOutcomeJson outcome;
|
||||
|
||||
PackageInstallationSpec spec = new PackageInstallationSpec().setName("hl7.fhir.uv.shorthand").setVersion("0.12.0").setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL);
|
||||
outcome = myPackageInstallerSvc.install(spec);
|
||||
assertEquals(1, outcome.getResourcesInstalled().get("CodeSystem"));
|
||||
|
||||
myPackageInstallerSvc.install(spec);
|
||||
outcome = myPackageInstallerSvc.install(spec);
|
||||
assertEquals(null, outcome.getResourcesInstalled().get("CodeSystem"));
|
||||
|
||||
// Ensure that we loaded the contents
|
||||
IBundleProvider searchResult = myCodeSystemDao.search(SearchParameterMap.newSynchronous("url", new UriParam("http://hl7.org/fhir/uv/shorthand/CodeSystem/shorthand-code-system")));
|
||||
assertEquals(1, searchResult.sizeOrThrowNpe());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testInstallR4PackageWithNoDescription() throws Exception {
|
||||
|
@ -801,6 +829,43 @@ public class NpmR4Test extends BaseJpaR4Test {
|
|||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInstallPkgContainingNonPartitionedResourcesPartitionsEnabled() throws Exception {
|
||||
myDaoConfig.setAllowExternalReferences(true);
|
||||
myPartitionSettings.setPartitioningEnabled(true);
|
||||
myInterceptorService.registerInterceptor(myRequestTenantPartitionInterceptor);
|
||||
|
||||
byte[] bytes = loadClasspathBytes("/packages/test-logical-structuredefinition.tgz");
|
||||
myFakeNpmServlet.myResponses.put("/test-logical-structuredefinition/1.0.0", bytes);
|
||||
|
||||
PackageInstallationSpec spec = new PackageInstallationSpec().setName("test-logical-structuredefinition").setVersion("1.0.0").setInstallMode(PackageInstallationSpec.InstallModeEnum.STORE_AND_INSTALL);
|
||||
PackageInstallOutcomeJson outcome = myPackageInstallerSvc.install(spec);
|
||||
assertEquals(2, outcome.getResourcesInstalled().get("StructureDefinition"));
|
||||
|
||||
// Be sure no further communication with the server
|
||||
JettyUtil.closeServer(myServer);
|
||||
|
||||
// Search for the installed resource
|
||||
runInTransaction(() -> {
|
||||
// Confirm that Laborbefund (a logical StructureDefinition) was created without a snapshot.
|
||||
SearchParameterMap map = SearchParameterMap.newSynchronous();
|
||||
map.add(StructureDefinition.SP_URL, new UriParam("https://www.medizininformatik-initiative.de/fhir/core/modul-labor/StructureDefinition/LogicalModel/Laborbefund"));
|
||||
IBundleProvider result = myStructureDefinitionDao.search(map);
|
||||
assertEquals(1, result.sizeOrThrowNpe());
|
||||
List<IBaseResource> resources = result.getResources(0,1);
|
||||
assertFalse(((StructureDefinition)resources.get(0)).hasSnapshot());
|
||||
|
||||
// Confirm that DiagnosticLab (a resource StructureDefinition with differential but no snapshot) was created with a generated snapshot.
|
||||
map = SearchParameterMap.newSynchronous();
|
||||
map.add(StructureDefinition.SP_URL, new UriParam("https://www.medizininformatik-initiative.de/fhir/core/modul-labor/StructureDefinition/DiagnosticReportLab"));
|
||||
result = myStructureDefinitionDao.search(map);
|
||||
assertEquals(1, result.sizeOrThrowNpe());
|
||||
resources = result.getResources(0,1);
|
||||
assertTrue(((StructureDefinition)resources.get(0)).hasSnapshot());
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
static class FakeNpmServlet extends HttpServlet {
|
||||
|
||||
private final Map<String, byte[]> myResponses = new HashMap<>();
|
||||
|
|
|
@ -7,6 +7,7 @@ import static org.junit.jupiter.api.Assertions.assertTrue;
|
|||
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.r4.model.BooleanType;
|
||||
import org.hl7.fhir.r4.model.Bundle;
|
||||
import org.hl7.fhir.r4.model.CodeType;
|
||||
import org.hl7.fhir.r4.model.CodeableConcept;
|
||||
import org.hl7.fhir.r4.model.Coding;
|
||||
|
@ -27,6 +28,8 @@ import org.springframework.transaction.annotation.Transactional;
|
|||
|
||||
import ca.uhn.fhir.rest.api.MethodOutcome;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class ResourceProviderR4ConceptMapTest extends BaseResourceProviderR4Test {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(ResourceProviderR4ConceptMapTest.class);
|
||||
|
||||
|
@ -171,6 +174,101 @@ public class ResourceProviderR4ConceptMapTest extends BaseResourceProviderR4Test
|
|||
assertEquals(CM_URL, ((UriType) part.getValue()).getValueAsString());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testTranslateByCodeSystemsAndSourceCodeOneToOne_InBatchOperation() {
|
||||
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
|
||||
|
||||
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.setType(Bundle.BundleType.BATCH);
|
||||
bundle
|
||||
.addEntry()
|
||||
.getRequest()
|
||||
.setMethod(Bundle.HTTPVerb.GET)
|
||||
.setUrl("ConceptMap/$translate?system=" + CS_URL + "&code=12345" + "&targetsystem=" + CS_URL_2);
|
||||
|
||||
ourLog.info("Request:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle));
|
||||
|
||||
Bundle respBundle = myClient
|
||||
.transaction()
|
||||
.withBundle(bundle)
|
||||
.execute();
|
||||
|
||||
ourLog.info("Response:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respBundle));
|
||||
|
||||
assertEquals(1, respBundle.getEntry().size());
|
||||
Parameters respParams = (Parameters) respBundle.getEntry().get(0).getResource();
|
||||
|
||||
ParametersParameterComponent param = getParameterByName(respParams, "result");
|
||||
assertTrue(((BooleanType) param.getValue()).booleanValue());
|
||||
|
||||
param = getParameterByName(respParams, "message");
|
||||
assertEquals("Matches found", ((StringType) param.getValue()).getValueAsString());
|
||||
|
||||
assertEquals(1, getNumberOfParametersByName(respParams, "match"));
|
||||
|
||||
param = getParameterByName(respParams, "match");
|
||||
assertEquals(3, param.getPart().size());
|
||||
ParametersParameterComponent part = getPartByName(param, "equivalence");
|
||||
assertEquals("equal", ((CodeType) part.getValue()).getCode());
|
||||
part = getPartByName(param, "concept");
|
||||
Coding coding = (Coding) part.getValue();
|
||||
assertEquals("34567", coding.getCode());
|
||||
assertEquals("Target Code 34567", coding.getDisplay());
|
||||
assertFalse(coding.getUserSelected());
|
||||
assertEquals(CS_URL_2, coding.getSystem());
|
||||
assertEquals("Version 2", coding.getVersion());
|
||||
part = getPartByName(param, "source");
|
||||
assertEquals(CM_URL, ((UriType) part.getValue()).getValueAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTranslateByCodeSystemsAndSourceCodeOneToOne_InBatchOperation2() throws IOException {
|
||||
ConceptMap cm = loadResourceFromClasspath(ConceptMap.class, "/r4/conceptmap.json");
|
||||
myConceptMapDao.update(cm);
|
||||
|
||||
Bundle bundle = new Bundle();
|
||||
bundle.setType(Bundle.BundleType.BATCH);
|
||||
bundle
|
||||
.addEntry()
|
||||
.getRequest()
|
||||
.setMethod(Bundle.HTTPVerb.GET)
|
||||
.setUrl("ConceptMap/$translate?url=http://hl7.org/fhir/ConceptMap/CMapHie&system=http://fkcfhir.org/fhir/cs/FMCECCOrderAbbreviation&code=IMed_Janssen&targetsystem=http://fkcfhir.org/fhir/cs/FMCHIEOrderAbbreviation");
|
||||
|
||||
ourLog.info("Request:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(bundle));
|
||||
|
||||
Bundle respBundle = myClient
|
||||
.transaction()
|
||||
.withBundle(bundle)
|
||||
.execute();
|
||||
|
||||
ourLog.info("Response:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(respBundle));
|
||||
|
||||
assertEquals(1, respBundle.getEntry().size());
|
||||
Parameters respParams = (Parameters) respBundle.getEntry().get(0).getResource();
|
||||
|
||||
ParametersParameterComponent param = getParameterByName(respParams, "result");
|
||||
assertTrue(((BooleanType) param.getValue()).booleanValue());
|
||||
|
||||
param = getParameterByName(respParams, "message");
|
||||
assertEquals("Matches found", ((StringType) param.getValue()).getValueAsString());
|
||||
|
||||
assertEquals(1, getNumberOfParametersByName(respParams, "match"));
|
||||
|
||||
param = getParameterByName(respParams, "match");
|
||||
assertEquals(3, param.getPart().size());
|
||||
ParametersParameterComponent part = getPartByName(param, "equivalence");
|
||||
assertEquals("equivalent", ((CodeType) part.getValue()).getCode());
|
||||
part = getPartByName(param, "concept");
|
||||
Coding coding = (Coding) part.getValue();
|
||||
assertEquals("212", coding.getCode());
|
||||
assertEquals("COVID-19 Vaccine,vecton-nr,rS-Ad26,PF,0.5mL", coding.getDisplay());
|
||||
assertFalse(coding.getUserSelected());
|
||||
assertEquals("http://fkcfhir.org/fhir/cs/FMCHIEOrderAbbreviation", coding.getSystem());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTranslateByCodeSystemsAndSourceCodeUnmapped() {
|
||||
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
|
||||
|
|
|
@ -3,6 +3,7 @@ package ca.uhn.fhir.jpa.term;
|
|||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import ca.uhn.fhir.jpa.entity.TermConcept;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptDesignation;
|
||||
import ca.uhn.fhir.jpa.entity.TermConceptProperty;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermCodeSystemStorageSvc;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
|
||||
|
@ -35,6 +36,7 @@ import org.mockito.Mockito;
|
|||
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
@ -45,6 +47,7 @@ import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_ANSWERL
|
|||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_ANSWERLIST_LINK_DUPLICATE_FILE_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_ANSWERLIST_LINK_FILE_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_CODESYSTEM_VERSION;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_CONSUMER_NAME_FILE_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_DOCUMENT_ONTOLOGY_FILE_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_DUPLICATE_FILE_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_FILE_DEFAULT;
|
||||
|
@ -53,6 +56,8 @@ import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_GROUP_T
|
|||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_HIERARCHY_FILE_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_IEEE_MEDICAL_DEVICE_CODE_MAPPING_TABLE_FILE_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_IMAGING_DOCUMENT_CODES_FILE_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_LINGUISTIC_VARIANTS_FILE_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_LINGUISTIC_VARIANTS_PATH_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_PARENT_GROUP_FILE_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_PART_FILE_DEFAULT;
|
||||
import static ca.uhn.fhir.jpa.term.loinc.LoincUploadPropertiesEnum.LOINC_PART_LINK_FILE_DEFAULT;
|
||||
|
@ -111,8 +116,7 @@ public class TerminologyLoaderSvcLoincTest extends BaseLoaderTest {
|
|||
@Mock
|
||||
private ITermDeferredStorageSvc myTermDeferredStorageSvc;
|
||||
|
||||
private Parameters parameters = new Parameters();
|
||||
|
||||
private Parameters myParameters = new Parameters();
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
|
@ -120,15 +124,13 @@ public class TerminologyLoaderSvcLoincTest extends BaseLoaderTest {
|
|||
myFiles = new ZipCollectionBuilder();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Nested
|
||||
public class TestsUsingDefaultMakeCurrentVerionParameter {
|
||||
|
||||
@BeforeEach
|
||||
public void before() {
|
||||
parameters.addParameter().setName(MAKE_CURRENT_VERSION).setValue(new StringType("true"));
|
||||
when(mySrd.getResource()).thenReturn(parameters);
|
||||
myParameters.addParameter().setName(MAKE_CURRENT_VERSION).setValue(new StringType("true"));
|
||||
when(mySrd.getResource()).thenReturn(myParameters);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -146,7 +148,7 @@ public class TerminologyLoaderSvcLoincTest extends BaseLoaderTest {
|
|||
@Test
|
||||
public void testLoadLoincWithMandatoryFilesOnly() throws Exception {
|
||||
addLoincMandatoryFilesWithoutTop2000ToZip(myFiles);
|
||||
verifyLoadLoinc(false);
|
||||
verifyLoadLoinc(false, false);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -184,18 +186,24 @@ public class TerminologyLoaderSvcLoincTest extends BaseLoaderTest {
|
|||
|
||||
}
|
||||
|
||||
|
||||
private void verifyLoadLoinc() {
|
||||
verifyLoadLoinc(true);
|
||||
@Test
|
||||
public void testLoadLoincWithConsumerNameAndLinguisticVariants() throws Exception {
|
||||
addLoincMandatoryFilesAndConsumerNameAndLinguisticVariants(myFiles);
|
||||
verifyLoadLoinc(false, true);
|
||||
}
|
||||
|
||||
private void verifyLoadLoinc(boolean theIncludeTop2000) {
|
||||
|
||||
private void verifyLoadLoinc() {
|
||||
verifyLoadLoinc(true, false);
|
||||
}
|
||||
|
||||
private void verifyLoadLoinc(boolean theIncludeTop2000, boolean theIncludeConsumerNameAndLinguisticVariants) {
|
||||
// Actually do the load
|
||||
mySvc.loadLoinc(myFiles.getFiles(), mySrd);
|
||||
|
||||
verify(myTermCodeSystemStorageSvc, times(1)).storeNewCodeSystemVersion(
|
||||
mySystemCaptor.capture(), myCsvCaptor.capture(), any(RequestDetails.class), myValueSetsCaptor.capture(),
|
||||
myConceptMapCaptor.capture(), eq(true));
|
||||
mySystemCaptor.capture(), myCsvCaptor.capture(), any(RequestDetails.class),
|
||||
myValueSetsCaptor.capture(), myConceptMapCaptor.capture(), eq(true));
|
||||
Map<String, TermConcept> concepts = extractConcepts();
|
||||
Map<String, ValueSet> valueSets = extractValueSets();
|
||||
Map<String, ConceptMap> conceptMaps = extractConceptMaps();
|
||||
|
@ -475,6 +483,22 @@ public class TerminologyLoaderSvcLoincTest extends BaseLoaderTest {
|
|||
assertEquals(2, vs.getCompose().getInclude().get(0).getConcept().size());
|
||||
assertEquals("17424-3", vs.getCompose().getInclude().get(0).getConcept().get(0).getCode());
|
||||
assertEquals("13006-2", vs.getCompose().getInclude().get(0).getConcept().get(1).getCode());
|
||||
|
||||
// Consumer Name
|
||||
if (theIncludeConsumerNameAndLinguisticVariants) {
|
||||
code = concepts.get("61438-8");
|
||||
assertEquals(28, code.getDesignations().size());
|
||||
verifyConsumerName(code.getDesignations(), "Consumer Name 61438-8");
|
||||
verifyLinguisticVariant(code.getDesignations(), "de-AT", "Entlassungsbrief Ärztlich","Ergebnis","Zeitpunkt","{Setting}","Dokument","Dermatologie","DOC.ONTOLOGY","de shortname","de long common name","de related names 2","de linguistic variant display name");
|
||||
verifyLinguisticVariant(code.getDesignations(), "fr-CA", "Cellules de Purkinje cytoplasmique type 2 , IgG","Titre","Temps ponctuel","Sérum","Quantitatif","Immunofluorescence","Sérologie","","","","");
|
||||
verifyLinguisticVariant(code.getDesignations(), "zh-CN", "血流速度.收缩期.最大值","速度","时间点","大脑中动脉","定量型","超声.多普勒","产科学检查与测量指标.超声","","", "Cereb 动态 可用数量表示的;定量性;数值型;数量型;连续数值型标尺 大脑(Cerebral) 时刻;随机;随意;瞬间 术语\"cerebral\"指的是主要由中枢半球(大脑皮质和基底神经节)组成的那部分脑结构 流 流量;流速;流体 血;全血 血流量;血液流量 速度(距离/时间);速率;速率(距离/时间)","");
|
||||
code = concepts.get("17787-3");
|
||||
assertEquals(19, code.getDesignations().size());
|
||||
verifyConsumerName(code.getDesignations(), "Consumer Name 17787-3");
|
||||
verifyLinguisticVariant(code.getDesignations(), "de-AT", "","","","","","","","","","CoV OC43 RNA ql/SM P","Coronavirus OC43 RNA ql. /Sondermaterial PCR");
|
||||
verifyLinguisticVariant(code.getDesignations(), "fr-CA", "Virus respiratoire syncytial bovin","Présence-Seuil","Temps ponctuel","XXX","Ordinal","Culture spécifique à un microorganisme","Microbiologie","","","","");
|
||||
verifyLinguisticVariant(code.getDesignations(), "zh-CN", "血流速度.收缩期.最大值","速度","时间点","二尖瓣^胎儿","定量型","超声.多普勒","产科学检查与测量指标.超声","","","僧帽瓣 动态 可用数量表示的;定量性;数值型;数量型;连续数值型标尺 时刻;随机;随意;瞬间 流 流量;流速;流体 胎;超系统 - 胎儿 血;全血 血流量;血液流量 速度(距离/时间);速率;速率(距离/时间)","");
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -661,7 +685,6 @@ public class TerminologyLoaderSvcLoincTest extends BaseLoaderTest {
|
|||
}
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testLoadLoincMultiaxialHierarchySupport() throws Exception {
|
||||
addLoincMandatoryFilesToZip(myFiles);
|
||||
|
@ -670,8 +693,8 @@ public class TerminologyLoaderSvcLoincTest extends BaseLoaderTest {
|
|||
mySvc.loadLoinc(myFiles.getFiles(), mySrd);
|
||||
|
||||
verify(myTermCodeSystemStorageSvc, times(1)).storeNewCodeSystemVersion(
|
||||
mySystemCaptor.capture(), myCsvCaptor.capture(), any(RequestDetails.class), myValueSetsCaptor.capture(),
|
||||
myConceptMapCaptor.capture(), eq(true));
|
||||
mySystemCaptor.capture(), myCsvCaptor.capture(), any(RequestDetails.class),
|
||||
myValueSetsCaptor.capture(), myConceptMapCaptor.capture(), eq(true));
|
||||
Map<String, TermConcept> concepts = extractConcepts();
|
||||
|
||||
TermConcept code;
|
||||
|
@ -769,6 +792,7 @@ public class TerminologyLoaderSvcLoincTest extends BaseLoaderTest {
|
|||
|
||||
|
||||
|
||||
|
||||
@Nested
|
||||
public class CurrentVersionParameter {
|
||||
private TermLoaderSvcImpl testedSvc;
|
||||
|
@ -778,12 +802,11 @@ public class TerminologyLoaderSvcLoincTest extends BaseLoaderTest {
|
|||
@SuppressWarnings("unchecked")
|
||||
@Mock private final List<ITermLoaderSvc.FileDescriptor> mockFileDescriptorList = mock(List.class);
|
||||
|
||||
private final Parameters myParameters = new Parameters();
|
||||
|
||||
@BeforeEach
|
||||
void beforeEachCurrentVersionParameterTest() {
|
||||
testedSvc = spy(mySvc);
|
||||
doReturn(mockFileDescriptors).when(testedSvc).getLoadedFileDescriptors(any());
|
||||
doReturn(mockFileDescriptors).when(testedSvc).getLoadedFileDescriptors(mockFileDescriptorList);
|
||||
doReturn(testProps).when(testedSvc).getProperties(any(), eq(LOINC_UPLOAD_PROPERTIES_FILE.getCode()));
|
||||
}
|
||||
|
||||
|
@ -865,12 +888,27 @@ public class TerminologyLoaderSvcLoincTest extends BaseLoaderTest {
|
|||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static void addLoincMandatoryFilesAndSinglePartLinkToZip(ZipCollectionBuilder theFiles) throws IOException {
|
||||
addBaseLoincMandatoryFilesToZip(theFiles, true);
|
||||
theFiles.addFileZip("/loinc/", "loincupload_singlepartlink.properties");
|
||||
theFiles.addFileZip("/loinc/", LOINC_PART_LINK_FILE_DEFAULT.getCode());
|
||||
}
|
||||
|
||||
public static void addLoincMandatoryFilesAndConsumerNameAndLinguisticVariants(ZipCollectionBuilder theFiles) throws IOException {
|
||||
addBaseLoincMandatoryFilesToZip(theFiles, true);
|
||||
theFiles.addFileZip("/loinc/", "loincupload_singlepartlink.properties");
|
||||
theFiles.addFileZip("/loinc/", LOINC_PART_LINK_FILE_DEFAULT.getCode());
|
||||
theFiles.addFileZip("/loinc/", LOINC_CONSUMER_NAME_FILE_DEFAULT.getCode());
|
||||
theFiles.addFileZip("/loinc/", LOINC_LINGUISTIC_VARIANTS_FILE_DEFAULT.getCode());
|
||||
theFiles.addFileZip("/loinc/", LOINC_LINGUISTIC_VARIANTS_PATH_DEFAULT.getCode() + "zhCN5LinguisticVariant.csv");
|
||||
theFiles.addFileZip("/loinc/", LOINC_LINGUISTIC_VARIANTS_PATH_DEFAULT.getCode() + "deAT24LinguisticVariant.csv");
|
||||
theFiles.addFileZip("/loinc/", LOINC_LINGUISTIC_VARIANTS_PATH_DEFAULT.getCode() + "frCA8LinguisticVariant.csv");
|
||||
}
|
||||
|
||||
|
||||
public static void addLoincMandatoryFilesToZip(ZipCollectionBuilder theFiles) throws IOException {
|
||||
addBaseLoincMandatoryFilesToZip(theFiles, true);
|
||||
theFiles.addFileZip("/loinc/", LOINC_UPLOAD_PROPERTIES_FILE.getCode());
|
||||
|
@ -916,6 +954,88 @@ public class TerminologyLoaderSvcLoincTest extends BaseLoaderTest {
|
|||
theFiles.addFileZip("/loinc/", LOINC_TOP2000_COMMON_LAB_RESULTS_SI_FILE_DEFAULT.getCode());
|
||||
theFiles.addFileZip("/loinc/", LOINC_TOP2000_COMMON_LAB_RESULTS_US_FILE_DEFAULT.getCode());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void verifyConsumerName(Collection<TermConceptDesignation> designationList, String theConsumerName) {
|
||||
|
||||
TermConceptDesignation consumerNameDesignation = null;
|
||||
for (TermConceptDesignation designation : designationList) {
|
||||
if ("ConsumerName".equals(designation.getUseDisplay() )) {
|
||||
consumerNameDesignation = designation;
|
||||
}
|
||||
}
|
||||
assertEquals(theConsumerName, consumerNameDesignation.getValue());
|
||||
}
|
||||
|
||||
private static void verifyLinguisticVariant(Collection<TermConceptDesignation> designationList, String theLanguage,
|
||||
String theComponent, String theProperty, String theTimeAspct, String theSystem, String theScaleTyp,
|
||||
String methodType, String theClass, String theShortName, String theLongCommonName, String theRelatedName2,
|
||||
String theLinguisticVariantDisplayName) {
|
||||
|
||||
TermConceptDesignation componentDes = null;
|
||||
TermConceptDesignation propertyDes = null;
|
||||
TermConceptDesignation timeAspctDes = null;
|
||||
TermConceptDesignation systemDes = null;
|
||||
TermConceptDesignation scaleTypDes = null;
|
||||
|
||||
TermConceptDesignation methodTypDes = null;
|
||||
TermConceptDesignation classDes = null;
|
||||
TermConceptDesignation shortNameDes = null;
|
||||
TermConceptDesignation longCommonNameDes = null;
|
||||
TermConceptDesignation relatedNames2Des = null;
|
||||
|
||||
TermConceptDesignation linguisticVariantDisplayNameDes = null;
|
||||
|
||||
for (TermConceptDesignation designation : designationList) {
|
||||
if (theLanguage.equals(designation.getLanguage())) {
|
||||
|
||||
if ("COMPONENT".equals(designation.getUseDisplay()))
|
||||
componentDes = designation;
|
||||
if ("PROPERTY".equals(designation.getUseDisplay()))
|
||||
propertyDes = designation;
|
||||
if ("TIME_ASPCT".equals(designation.getUseDisplay()))
|
||||
timeAspctDes = designation;
|
||||
if ("SYSTEM".equals(designation.getUseDisplay()))
|
||||
systemDes = designation;
|
||||
if ("SCALE_TYP".equals(designation.getUseDisplay()))
|
||||
scaleTypDes = designation;
|
||||
|
||||
if ("METHOD_TYP".equals(designation.getUseDisplay()))
|
||||
methodTypDes = designation;
|
||||
if ("CLASS".equals(designation.getUseDisplay()))
|
||||
classDes = designation;
|
||||
if ("SHORTNAME".equals(designation.getUseDisplay()))
|
||||
shortNameDes = designation;
|
||||
if ("LONG_COMMON_NAME".equals(designation.getUseDisplay()))
|
||||
longCommonNameDes = designation;
|
||||
if ("RELATEDNAMES2".equals(designation.getUseDisplay()))
|
||||
relatedNames2Des = designation;
|
||||
|
||||
if ("LinguisticVariantDisplayName".equals(designation.getUseDisplay()))
|
||||
linguisticVariantDisplayNameDes = designation;
|
||||
}
|
||||
}
|
||||
verifyDesignation(componentDes, ITermLoaderSvc.LOINC_URI, "COMPONENT", theComponent);
|
||||
verifyDesignation(propertyDes, ITermLoaderSvc.LOINC_URI, "PROPERTY", theProperty);
|
||||
verifyDesignation(timeAspctDes, ITermLoaderSvc.LOINC_URI, "TIME_ASPCT", theTimeAspct);
|
||||
verifyDesignation(systemDes, ITermLoaderSvc.LOINC_URI, "SYSTEM", theSystem);
|
||||
verifyDesignation(scaleTypDes, ITermLoaderSvc.LOINC_URI, "SCALE_TYP", theScaleTyp);
|
||||
|
||||
verifyDesignation(methodTypDes, ITermLoaderSvc.LOINC_URI, "METHOD_TYP", methodType);
|
||||
verifyDesignation(classDes, ITermLoaderSvc.LOINC_URI, "CLASS", theClass);
|
||||
verifyDesignation(shortNameDes, ITermLoaderSvc.LOINC_URI, "SHORTNAME", theShortName);
|
||||
verifyDesignation(longCommonNameDes, ITermLoaderSvc.LOINC_URI, "LONG_COMMON_NAME", theLongCommonName);
|
||||
verifyDesignation(relatedNames2Des, ITermLoaderSvc.LOINC_URI, "RELATEDNAMES2", theRelatedName2);
|
||||
|
||||
verifyDesignation(linguisticVariantDisplayNameDes, ITermLoaderSvc.LOINC_URI, "LinguisticVariantDisplayName", theLinguisticVariantDisplayName);
|
||||
}
|
||||
|
||||
private static void verifyDesignation(TermConceptDesignation theDesignation, String theUseSystem, String theUseCode, String theValue) {
|
||||
if (theDesignation == null)
|
||||
return;
|
||||
assertEquals(theUseSystem, theDesignation.getUseSystem());
|
||||
assertEquals(theUseCode, theDesignation.getUseCode());
|
||||
assertEquals(theValue, theDesignation.getValue());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
"LoincNumber","ConsumerName"
|
||||
"61438-8","Consumer Name 61438-8"
|
||||
,"Consumer Name X"
|
||||
47239-9",""
|
||||
"17787-3","Consumer Name 17787-3"
|
||||
"38699-5","1,1-Dichloroethane, Air"
|
Can't render this file because it contains an unexpected character in line 4 and column 8.
|
|
@ -0,0 +1,9 @@
|
|||
"ID","ISO_LANGUAGE","ISO_COUNTRY","LANGUAGE_NAME","PRODUCER"
|
||||
"5","zh","CN","Chinese (CHINA)","Lin Zhang, A LOINC volunteer from China"
|
||||
"7","es","AR","Spanish (ARGENTINA)","Conceptum Medical Terminology Center"
|
||||
"8","fr","CA","French (CANADA)","Canada Health Infoway Inc."
|
||||
,"de","AT","German (AUSTRIA)","ELGA, Austria"
|
||||
"88",,"AT","German (AUSTRIA)","ELGA, Austria"
|
||||
"89","de",,"German (AUSTRIA)","ELGA, Austria"
|
||||
"90","de","AT",,"ELGA, Austria"
|
||||
"24","de","AT","German (AUSTRIA)","ELGA, Austria"
|
|
|
@ -0,0 +1,4 @@
|
|||
"LOINC_NUM","COMPONENT","PROPERTY","TIME_ASPCT","SYSTEM","SCALE_TYP","METHOD_TYP","CLASS","SHORTNAME","LONG_COMMON_NAME","RELATEDNAMES2","LinguisticVariantDisplayName"
|
||||
"61438-8","Entlassungsbrief Ärztlich","Ergebnis","Zeitpunkt","{Setting}","Dokument","Dermatologie","DOC.ONTOLOGY","de shortname","de long common name","de related names 2","de linguistic variant display name"
|
||||
"43730-1","","","","","","","","","","EBV-DNA qn. PCR","EBV-DNA quantitativ PCR"
|
||||
"17787-3","","","","","","","","","","CoV OC43 RNA ql/SM P","Coronavirus OC43 RNA ql. /Sondermaterial PCR"
|
|
|
@ -0,0 +1,6 @@
|
|||
"LOINC_NUM","COMPONENT","PROPERTY","TIME_ASPCT","SYSTEM","SCALE_TYP","METHOD_TYP","CLASS","SHORTNAME","LONG_COMMON_NAME","RELATEDNAMES2","LinguisticVariantDisplayName"
|
||||
"61438-8","Cellules de Purkinje cytoplasmique type 2 , IgG","Titre","Temps ponctuel","Sérum","Quantitatif","Immunofluorescence","Sérologie","","","",""
|
||||
"11704-4","Gliale nucléaire de type 1 , IgG","Titre","Temps ponctuel","LCR","Quantitatif","Immunofluorescence","Sérologie","","","",""
|
||||
,"Cellules de Purkinje cytoplasmique type 2 , IgG","Titre","Temps ponctuel","Sérum","Quantitatif",,,"","","",""
|
||||
"17787-3","Virus respiratoire syncytial bovin","Présence-Seuil","Temps ponctuel","XXX","Ordinal","Culture spécifique à un microorganisme","Microbiologie","","","",""
|
||||
"17788-1","Cellules de Purkinje cytoplasmique type 2 , IgG","Titre","Temps ponctuel","Sérum","Quantitatif",,,"","","",""
|
|
|
@ -0,0 +1,9 @@
|
|||
"LOINC_NUM","COMPONENT","PROPERTY","TIME_ASPCT","SYSTEM","SCALE_TYP","METHOD_TYP","CLASS","SHORTNAME","LONG_COMMON_NAME","RELATEDNAMES2","LinguisticVariantDisplayName"
|
||||
"61438-8","血流速度.收缩期.最大值","速度","时间点","大脑中动脉","定量型","超声.多普勒","产科学检查与测量指标.超声","","","Cereb 动态 可用数量表示的;定量性;数值型;数量型;连续数值型标尺 大脑(Cerebral) 时刻;随机;随意;瞬间 术语""cerebral""指的是主要由中枢半球(大脑皮质和基底神经节)组成的那部分脑结构 流 流量;流速;流体 血;全血 血流量;血液流量 速度(距离/时间);速率;速率(距离/时间)",""
|
||||
"11704-4","血流速度.收缩期.最大值","速度","时间点","动脉导管","定量型","超声.多普勒","产科学检查与测量指标.超声","","","动态 动脉管 可用数量表示的;定量性;数值型;数量型;连续数值型标尺 时刻;随机;随意;瞬间 流 流量;流速;流体 血;全血 血流量;血液流量 速度(距离/时间);速率;速率(距离/时间)",""
|
||||
"17787-3","血流速度.收缩期.最大值","速度","时间点","二尖瓣^胎儿","定量型","超声.多普勒","产科学检查与测量指标.超声","","","僧帽瓣 动态 可用数量表示的;定量性;数值型;数量型;连续数值型标尺 时刻;随机;随意;瞬间 流 流量;流速;流体 胎;超系统 - 胎儿 血;全血 血流量;血液流量 速度(距离/时间);速率;速率(距离/时间)",""
|
||||
"61438-6",,"速度","时间点","二尖瓣^胎儿","定量型","超声.多普勒","产科学检查与测量指标.超声","","","僧帽瓣 动态 可用数量表示的;定量性;数值型;数量型;连续数值型标尺 时刻;随机;随意;瞬间 流 流量;流速;流体 胎;超系统 - 胎儿 血;全血 血流量;血液流量 速度(距离/时间);速率;速率(距离/时间)",""
|
||||
"10000-8","血流速度.收缩期.最大值",,"时间点","二尖瓣^胎儿","定量型","超声.多普勒","产科学检查与测量指标.超声","","","僧帽瓣 动态 可用数量表示的;定量性;数值型;数量型;连续数值型标尺 时刻;随机;随意;瞬间 流 流量;流速;流体 胎;超系统 - 胎儿 血;全血 血流量;血液流量 速度(距离/时间);速率;速率(距离/时间)",""
|
||||
"17788-1","血流速度.收缩期.最大值","速度",,"大脑中动脉","定量型","超声.多普勒","产科学检查与测量指标.超声","","","Cereb 动态 可用数量表示的;定量性;数值型;数量型;连续数值型标尺 大脑(Cerebral) 时刻;随机;随意;瞬间 术语""cerebral""指的是主要由中枢半球(大脑皮质和基底神经节)组成的那部分脑结构 流 流量;流速;流体 血;全血 血流量;血液流量 速度(距离/时间);速率;速率(距离/时间)",""
|
||||
"11488-4","血流速度.收缩期.最大值","速度","时间点",,"定量型","超声.多普勒","产科学检查与测量指标.超声","","","Cereb 动态 可用数量表示的;定量性;数值型;数量型;连续数值型标尺 大脑(Cerebral) 时刻;随机;随意;瞬间 术语""cerebral""指的是主要由中枢半球(大脑皮质和基底神经节)组成的那部分脑结构 流 流量;流速;流体 血;全血 血流量;血液流量 速度(距离/时间);速率;速率(距离/时间)",""
|
||||
"47239-9","血流速度.收缩期.最大值","速度","时间点","大脑中动脉",,"超声.多普勒","产科学检查与测量指标.超声","","","Cereb 动态 可用数量表示的;定量性;数值型;数量型;连续数值型标尺 大脑(Cerebral) 时刻;随机;随意;瞬间 术语""cerebral""指的是主要由中枢半球(大脑皮质和基底神经节)组成的那部分脑结构 流 流量;流速;流体 血;全血 血流量;血液流量 速度(距离/时间);速率;速率(距离/时间)",""
|
|
|
@ -81,3 +81,13 @@ loinc.group.terms.file=AccessoryFiles/GroupFile/GroupLoincTerms.csv
|
|||
## Default value if key not provided: AccessoryFiles/GroupFile/ParentGroup.csv
|
||||
## File may be omitted
|
||||
loinc.parent.group.file=AccessoryFiles/GroupFile/ParentGroup.csv
|
||||
|
||||
# Consumer Names
|
||||
## Default value if key not provided: AccessoryFiles/ConsumerName/ConsumerName.csv
|
||||
## File may be omitted
|
||||
loinc.consumer.name.file=AccessoryFiles/ConsumerName/ConsumerName.csv
|
||||
|
||||
# Linguistic Variants
|
||||
## Default value if key not provided: AccessoryFiles/LinguisticVariants/LinguisticVariants.csv
|
||||
## File may be omitted
|
||||
loinc.linguistic.variants.file=AccessoryFiles/LinguisticVariants/LinguisticVariants.csv
|
|
@ -85,3 +85,13 @@ loinc.group.terms.file=AccessoryFiles/GroupFile/GroupLoincTerms.csv
|
|||
## Default value if key not provided: AccessoryFiles/GroupFile/ParentGroup.csv
|
||||
## File may be omitted
|
||||
loinc.parent.group.file=AccessoryFiles/GroupFile/ParentGroup.csv
|
||||
|
||||
# Consumer Names
|
||||
## Default value if key not provided: AccessoryFiles/ConsumerName/ConsumerName.csv
|
||||
## File may be omitted
|
||||
loinc.consumer.name.file=AccessoryFiles/ConsumerName/ConsumerName.csv
|
||||
|
||||
# Linguistic Variants
|
||||
## Default value if key not provided: AccessoryFiles/LinguisticVariants/LinguisticVariants.csv
|
||||
## File may be omitted
|
||||
loinc.linguistic.variants.file=AccessoryFiles/LinguisticVariants/LinguisticVariants.csv
|
|
@ -85,3 +85,13 @@ loinc.group.terms.file=AccessoryFiles/GroupFile/GroupLoincTerms.csv
|
|||
## Default value if key not provided: AccessoryFiles/GroupFile/ParentGroup.csv
|
||||
## File may be omitted
|
||||
loinc.parent.group.file=AccessoryFiles/GroupFile/ParentGroup.csv
|
||||
|
||||
# Consumer Names
|
||||
## Default value if key not provided: AccessoryFiles/ConsumerName/ConsumerName.csv
|
||||
## File may be omitted
|
||||
loinc.consumer.name.file=AccessoryFiles/ConsumerName/ConsumerName.csv
|
||||
|
||||
# Linguistic Variants
|
||||
## Default value if key not provided: AccessoryFiles/LinguisticVariants/LinguisticVariants.csv
|
||||
## File may be omitted
|
||||
loinc.linguistic.variants.file=AccessoryFiles/LinguisticVariants/LinguisticVariants.csv
|
|
@ -0,0 +1,98 @@
|
|||
{
|
||||
"resourceType": "ConceptMap",
|
||||
"id": "CMapHie",
|
||||
"meta": {
|
||||
"extension": [
|
||||
{
|
||||
"url": "http://hapifhir.io/fhir/StructureDefinition/resource-meta-source",
|
||||
"valueUri": "#VAL8lnninHkvaEWc"
|
||||
}
|
||||
],
|
||||
"versionId": "1",
|
||||
"lastUpdated": "2021-07-08T14:19:11.748-04:00"
|
||||
},
|
||||
"url": "http://hl7.org/fhir/ConceptMap/CMapHie",
|
||||
"identifier": {
|
||||
"system": "urn:ietf:rfc:3986",
|
||||
"value": "urn:uuid:53cd62ee-033e-414c-9f58-3ca97b5ffc3b"
|
||||
},
|
||||
"version": "4.0.1",
|
||||
"name": "FHIR-v3-Address-Use",
|
||||
"title": "FHIR/v3 Address Use Mapping",
|
||||
"status": "draft",
|
||||
"experimental": true,
|
||||
"date": "2012-06-13",
|
||||
"publisher": "HL7, Inc",
|
||||
"contact": [
|
||||
{
|
||||
"name": "FHIR project team (example)",
|
||||
"telecom": [
|
||||
{
|
||||
"system": "url",
|
||||
"value": "http://hl7.org/fhir"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"description": "A mapping between the ECC and HIE Code systems",
|
||||
"useContext": [
|
||||
{
|
||||
"code": {
|
||||
"system": "http://terminology.hl7.org/CodeSystem/usage-context-type",
|
||||
"code": "venue"
|
||||
},
|
||||
"valueCodeableConcept": {
|
||||
"text": "for CCDA Usage"
|
||||
}
|
||||
}
|
||||
],
|
||||
"jurisdiction": [
|
||||
{
|
||||
"coding": [
|
||||
{
|
||||
"system": "urn:iso:std:iso:3166",
|
||||
"code": "US"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"purpose": "To help implementers map from HL7 v3/CDA to FHIR",
|
||||
"copyright": "Creative Commons 0",
|
||||
"sourceUri": "http://fkcfhir.org/fhir/vs/FMCOrderAbbreviation",
|
||||
"targetUri": "http://fkcfhir.org/fhir/vs/FMCHIEAbbreviation",
|
||||
"group": [
|
||||
{
|
||||
"source": "http://fkcfhir.org/fhir/cs/FMCECCOrderAbbreviation",
|
||||
"target": "http://fkcfhir.org/fhir/cs/FMCHIEOrderAbbreviation",
|
||||
"element": [
|
||||
{
|
||||
"code": "IMed_Janssen",
|
||||
"display": "COVID-19 Vaccine-Janssen",
|
||||
"target": [
|
||||
{
|
||||
"code": "212",
|
||||
"display": "COVID-19 Vaccine,vecton-nr,rS-Ad26,PF,0.5mL",
|
||||
"equivalence": "equivalent"
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"code": "IMed_Moderna1",
|
||||
"display": "COVID-19 Vaccine-Moderna (Dose 1 of 2)",
|
||||
"target": [
|
||||
{
|
||||
"code": "207",
|
||||
"display": "COVID-19, mRNA,LNP-S,PF,100 mcg/0.5 mL dose",
|
||||
"equivalence": "equivalent"
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
"unmapped": {
|
||||
"mode": "fixed",
|
||||
"code": "unknown",
|
||||
"display": "unknown"
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -99,6 +99,24 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
|
||||
version.onTable("HFJ_BLK_EXPORT_JOB")
|
||||
.modifyColumn("20210624.1","REQUEST").nonNullable().withType(ColumnTypeEnum.STRING, 1024);
|
||||
|
||||
version.onTable("HFJ_IDX_CMP_STRING_UNIQ")
|
||||
.modifyColumn("20210713.1","IDX_STRING").nonNullable().withType(ColumnTypeEnum.STRING, 500);
|
||||
|
||||
version.onTable("HFJ_RESOURCE")
|
||||
.addColumn("20210720.1", "SP_CMPTOKS_PRESENT").nullable().type(ColumnTypeEnum.BOOLEAN);
|
||||
|
||||
version.addIdGenerator("20210720.2", "SEQ_IDXCMBTOKNU_ID");
|
||||
|
||||
Builder.BuilderAddTableByColumns cmpToks = version
|
||||
.addTableByColumns("20210720.3", "HFJ_IDX_CMB_TOK_NU", "PID");
|
||||
cmpToks.addColumn("PID").nonNullable().type(ColumnTypeEnum.LONG);
|
||||
cmpToks.addColumn("RES_ID").nonNullable().type(ColumnTypeEnum.LONG);
|
||||
cmpToks.addColumn("HASH_COMPLETE").nonNullable().type(ColumnTypeEnum.LONG);
|
||||
cmpToks.addColumn("IDX_STRING").nonNullable().type(ColumnTypeEnum.STRING, 500);
|
||||
cmpToks.addForeignKey("20210720.4", "FK_IDXCMBTOKNU_RES_ID").toColumn("RES_ID").references("HFJ_RESOURCE", "RES_ID");
|
||||
cmpToks.addIndex("20210720.5", "IDX_IDXCMBTOKNU_STR").unique(false).withColumns("IDX_STRING");
|
||||
cmpToks.addIndex("20210720.6", "IDX_IDXCMBTOKNU_RES").unique(false).withColumns("RES_ID");
|
||||
}
|
||||
|
||||
private void init540() {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -43,6 +43,7 @@ import javax.persistence.Temporal;
|
|||
import javax.persistence.TemporalType;
|
||||
import javax.persistence.Transient;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
@MappedSuperclass
|
||||
public abstract class BaseResourceIndexedSearchParam extends BaseResourceIndex {
|
||||
|
@ -182,6 +183,17 @@ public abstract class BaseResourceIndexedSearchParam extends BaseResourceIndex {
|
|||
return hash(thePartitionSettings, theRequestPartitionId, theResourceType, theParamName);
|
||||
}
|
||||
|
||||
public static long calculateHashIdentity(PartitionSettings thePartitionSettings, RequestPartitionId theRequestPartitionId, String theResourceType, String theParamName, List<String> theAdditionalValues) {
|
||||
String[] values = new String[theAdditionalValues.size() + 2];
|
||||
values[0] = theResourceType;
|
||||
values[1] = theParamName;
|
||||
for (int i = 0; i < theAdditionalValues.size(); i++) {
|
||||
values[i + 2] = theAdditionalValues.get(i);
|
||||
}
|
||||
|
||||
return hash(thePartitionSettings, theRequestPartitionId, values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a fast and consistent hashing algorithm to a set of strings
|
||||
*/
|
||||
|
|
|
@ -21,6 +21,8 @@ package ca.uhn.fhir.jpa.model.entity;
|
|||
*/
|
||||
|
||||
import ca.uhn.fhir.context.FhirVersionEnum;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringStyle;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
|
@ -157,4 +159,20 @@ public class NpmPackageVersionResourceEntity {
|
|||
myCanonicalUrl = theCanonicalUrl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
|
||||
return new ToStringBuilder(this, ToStringStyle.SHORT_PREFIX_STYLE)
|
||||
.append("myId", myId)
|
||||
.append("myCanonicalUrl", myCanonicalUrl)
|
||||
.append("myCanonicalVersion", myCanonicalVersion)
|
||||
.append("myResourceType", myResourceType)
|
||||
.append("myDirectory", myDirectory)
|
||||
.append("myFilename", myFilename)
|
||||
.append("myPackageVersion", myPackageVersion)
|
||||
.append("myResSizeBytes", myResSizeBytes)
|
||||
.append("myVersion", myVersion)
|
||||
.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -32,12 +32,12 @@ import javax.persistence.*;
|
|||
|
||||
@Entity()
|
||||
@Table(name = "HFJ_IDX_CMP_STRING_UNIQ", indexes = {
|
||||
@Index(name = ResourceIndexedCompositeStringUnique.IDX_IDXCMPSTRUNIQ_STRING, columnList = "IDX_STRING", unique = true),
|
||||
@Index(name = ResourceIndexedCompositeStringUnique.IDX_IDXCMPSTRUNIQ_RESOURCE, columnList = "RES_ID", unique = false)
|
||||
@Index(name = ResourceIndexedComboStringUnique.IDX_IDXCMPSTRUNIQ_STRING, columnList = "IDX_STRING", unique = true),
|
||||
@Index(name = ResourceIndexedComboStringUnique.IDX_IDXCMPSTRUNIQ_RESOURCE, columnList = "RES_ID", unique = false)
|
||||
})
|
||||
public class ResourceIndexedCompositeStringUnique extends BasePartitionable implements Comparable<ResourceIndexedCompositeStringUnique> {
|
||||
public class ResourceIndexedComboStringUnique extends BasePartitionable implements Comparable<ResourceIndexedComboStringUnique> {
|
||||
|
||||
public static final int MAX_STRING_LENGTH = 200;
|
||||
public static final int MAX_STRING_LENGTH = 500;
|
||||
public static final String IDX_IDXCMPSTRUNIQ_STRING = "IDX_IDXCMPSTRUNIQ_STRING";
|
||||
public static final String IDX_IDXCMPSTRUNIQ_RESOURCE = "IDX_IDXCMPSTRUNIQ_RESOURCE";
|
||||
|
||||
|
@ -66,14 +66,14 @@ public class ResourceIndexedCompositeStringUnique extends BasePartitionable impl
|
|||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ResourceIndexedCompositeStringUnique() {
|
||||
public ResourceIndexedComboStringUnique() {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ResourceIndexedCompositeStringUnique(ResourceTable theResource, String theIndexString, IIdType theSearchParameterId) {
|
||||
public ResourceIndexedComboStringUnique(ResourceTable theResource, String theIndexString, IIdType theSearchParameterId) {
|
||||
setResource(theResource);
|
||||
setIndexString(theIndexString);
|
||||
setPartitionId(theResource.getPartitionId());
|
||||
|
@ -81,7 +81,7 @@ public class ResourceIndexedCompositeStringUnique extends BasePartitionable impl
|
|||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ResourceIndexedCompositeStringUnique theO) {
|
||||
public int compareTo(ResourceIndexedComboStringUnique theO) {
|
||||
CompareToBuilder b = new CompareToBuilder();
|
||||
b.append(myIndexString, theO.getIndexString());
|
||||
return b.toComparison();
|
||||
|
@ -91,11 +91,11 @@ public class ResourceIndexedCompositeStringUnique extends BasePartitionable impl
|
|||
public boolean equals(Object theO) {
|
||||
if (this == theO) return true;
|
||||
|
||||
if (!(theO instanceof ResourceIndexedCompositeStringUnique)) {
|
||||
if (!(theO instanceof ResourceIndexedComboStringUnique)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ResourceIndexedCompositeStringUnique that = (ResourceIndexedCompositeStringUnique) theO;
|
||||
ResourceIndexedComboStringUnique that = (ResourceIndexedComboStringUnique) theO;
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(myIndexString, that.myIndexString)
|
|
@ -0,0 +1,190 @@
|
|||
package ca.uhn.fhir.jpa.model.entity;
|
||||
|
||||
/*-
|
||||
* #%L
|
||||
* HAPI FHIR JPA Model
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2021 Smile CDR, Inc.
|
||||
* %%
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.interceptor.model.RequestPartitionId;
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import org.apache.commons.lang3.builder.CompareToBuilder;
|
||||
import org.apache.commons.lang3.builder.EqualsBuilder;
|
||||
import org.apache.commons.lang3.builder.HashCodeBuilder;
|
||||
import org.apache.commons.lang3.builder.ToStringBuilder;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
import javax.persistence.ForeignKey;
|
||||
import javax.persistence.GeneratedValue;
|
||||
import javax.persistence.GenerationType;
|
||||
import javax.persistence.Id;
|
||||
import javax.persistence.Index;
|
||||
import javax.persistence.JoinColumn;
|
||||
import javax.persistence.ManyToOne;
|
||||
import javax.persistence.SequenceGenerator;
|
||||
import javax.persistence.Table;
|
||||
import javax.persistence.Transient;
|
||||
|
||||
import static ca.uhn.fhir.jpa.model.entity.BaseResourceIndexedSearchParam.hash;
|
||||
|
||||
@Entity
|
||||
@Table(name = "HFJ_IDX_CMB_TOK_NU", indexes = {
|
||||
@Index(name = "IDX_IDXCMBTOKNU_STR", columnList = "IDX_STRING", unique = false),
|
||||
@Index(name = "IDX_IDXCMBTOKNU_RES", columnList = "RES_ID", unique = false)
|
||||
})
|
||||
public class ResourceIndexedComboTokenNonUnique extends BaseResourceIndex implements Comparable<ResourceIndexedComboTokenNonUnique> {
|
||||
|
||||
@SequenceGenerator(name = "SEQ_IDXCMBTOKNU_ID", sequenceName = "SEQ_IDXCMBTOKNU_ID")
|
||||
@GeneratedValue(strategy = GenerationType.AUTO, generator = "SEQ_IDXCMBTOKNU_ID")
|
||||
@Id
|
||||
@Column(name = "PID")
|
||||
private Long myId;
|
||||
|
||||
@ManyToOne
|
||||
@JoinColumn(name = "RES_ID", referencedColumnName = "RES_ID", foreignKey = @ForeignKey(name = "FK_IDXCMBTOKNU_RES_ID"))
|
||||
private ResourceTable myResource;
|
||||
|
||||
@Column(name = "RES_ID", insertable = false, updatable = false)
|
||||
private Long myResourceId;
|
||||
|
||||
@Column(name = "HASH_COMPLETE", nullable = false)
|
||||
private Long myHashComplete;
|
||||
|
||||
@Column(name = "IDX_STRING", nullable = false, length = ResourceIndexedComboStringUnique.MAX_STRING_LENGTH)
|
||||
private String myIndexString;
|
||||
|
||||
@Transient
|
||||
private transient PartitionSettings myPartitionSettings;
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
public ResourceIndexedComboTokenNonUnique() {
|
||||
super();
|
||||
}
|
||||
|
||||
public ResourceIndexedComboTokenNonUnique(PartitionSettings thePartitionSettings, ResourceTable theEntity, String theQueryString) {
|
||||
myPartitionSettings = thePartitionSettings;
|
||||
myResource = theEntity;
|
||||
myIndexString = theQueryString;
|
||||
}
|
||||
|
||||
public String getIndexString() {
|
||||
return myIndexString;
|
||||
}
|
||||
|
||||
public void setIndexString(String theIndexString) {
|
||||
myIndexString = theIndexString;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object theO) {
|
||||
if (this == theO) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (theO == null || getClass() != theO.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
ResourceIndexedComboTokenNonUnique that = (ResourceIndexedComboTokenNonUnique) theO;
|
||||
|
||||
return new EqualsBuilder()
|
||||
.append(myResource, that.myResource)
|
||||
.append(myHashComplete, that.myHashComplete)
|
||||
.isEquals();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends BaseResourceIndex> void copyMutableValuesFrom(T theSource) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long getId() {
|
||||
return myId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setId(Long theId) {
|
||||
myId = theId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void calculateHashes() {
|
||||
PartitionSettings partitionSettings = getPartitionSettings();
|
||||
PartitionablePartitionId partitionId = getPartitionId();
|
||||
String queryString = myIndexString;
|
||||
setHashComplete(calculateHashComplete(partitionSettings, partitionId, queryString));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new HashCodeBuilder(17, 37)
|
||||
.append(myResource)
|
||||
.append(myHashComplete)
|
||||
.toHashCode();
|
||||
}
|
||||
|
||||
public PartitionSettings getPartitionSettings() {
|
||||
return myPartitionSettings;
|
||||
}
|
||||
|
||||
public ResourceTable getResource() {
|
||||
return myResource;
|
||||
}
|
||||
|
||||
public void setResource(ResourceTable theResource) {
|
||||
myResource = theResource;
|
||||
}
|
||||
|
||||
public Long getHashComplete() {
|
||||
return myHashComplete;
|
||||
}
|
||||
|
||||
public void setHashComplete(Long theHashComplete) {
|
||||
myHashComplete = theHashComplete;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(ResourceIndexedComboTokenNonUnique theO) {
|
||||
CompareToBuilder b = new CompareToBuilder();
|
||||
b.append(myHashComplete, theO.getHashComplete());
|
||||
return b.toComparison();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new ToStringBuilder(this)
|
||||
.append("id", myId)
|
||||
.append("resourceId", myResourceId)
|
||||
.append("hashComplete", myHashComplete)
|
||||
.append("indexString", myIndexString)
|
||||
.toString();
|
||||
}
|
||||
|
||||
public static long calculateHashComplete(PartitionSettings partitionSettings, PartitionablePartitionId thePartitionId, String queryString) {
|
||||
RequestPartitionId requestPartitionId = PartitionablePartitionId.toRequestPartitionId(thePartitionId);
|
||||
return hash(partitionSettings, requestPartitionId, queryString);
|
||||
}
|
||||
|
||||
public static long calculateHashComplete(PartitionSettings partitionSettings, RequestPartitionId partitionId, String queryString) {
|
||||
return hash(partitionSettings, partitionId, queryString);
|
||||
}
|
||||
|
||||
}
|
|
@ -192,11 +192,20 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
// Added in 3.0.0 - Should make this a primitive Boolean at some point
|
||||
@OptimisticLock(excluded = true)
|
||||
@Column(name = "SP_CMPSTR_UNIQ_PRESENT")
|
||||
private Boolean myParamsCompositeStringUniquePresent = false;
|
||||
private Boolean myParamsComboStringUniquePresent = false;
|
||||
|
||||
@OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
|
||||
@OptimisticLock(excluded = true)
|
||||
private Collection<ResourceIndexedCompositeStringUnique> myParamsCompositeStringUnique;
|
||||
private Collection<ResourceIndexedComboStringUnique> myParamsComboStringUnique;
|
||||
|
||||
// Added in 5.5.0 - Should make this a primitive Boolean at some point
|
||||
@OptimisticLock(excluded = true)
|
||||
@Column(name = "SP_CMPTOKS_PRESENT")
|
||||
private Boolean myParamsComboTokensNonUniquePresent = false;
|
||||
|
||||
@OneToMany(mappedBy = "myResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
|
||||
@OptimisticLock(excluded = true)
|
||||
private Collection<ResourceIndexedComboTokenNonUnique> myParamsComboTokensNonUnique;
|
||||
|
||||
@OneToMany(mappedBy = "mySourceResource", cascade = {}, fetch = FetchType.LAZY, orphanRemoval = false)
|
||||
@OptimisticLock(excluded = true)
|
||||
|
@ -312,11 +321,18 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
myLanguage = theLanguage;
|
||||
}
|
||||
|
||||
public Collection<ResourceIndexedCompositeStringUnique> getParamsCompositeStringUnique() {
|
||||
if (myParamsCompositeStringUnique == null) {
|
||||
myParamsCompositeStringUnique = new ArrayList<>();
|
||||
public Collection<ResourceIndexedComboStringUnique> getParamsComboStringUnique() {
|
||||
if (myParamsComboStringUnique == null) {
|
||||
myParamsComboStringUnique = new ArrayList<>();
|
||||
}
|
||||
return myParamsCompositeStringUnique;
|
||||
return myParamsComboStringUnique;
|
||||
}
|
||||
|
||||
public Collection<ResourceIndexedComboTokenNonUnique> getmyParamsComboTokensNonUnique() {
|
||||
if (myParamsComboTokensNonUnique == null) {
|
||||
myParamsComboTokensNonUnique = new ArrayList<>();
|
||||
}
|
||||
return myParamsComboTokensNonUnique;
|
||||
}
|
||||
|
||||
public Collection<ResourceIndexedSearchParamCoords> getParamsCoords() {
|
||||
|
@ -494,15 +510,26 @@ public class ResourceTable extends BaseHasResource implements Serializable, IBas
|
|||
myHasLinks = theHasLinks;
|
||||
}
|
||||
|
||||
public boolean isParamsCompositeStringUniquePresent() {
|
||||
if (myParamsCompositeStringUniquePresent == null) {
|
||||
public boolean isParamsComboStringUniquePresent() {
|
||||
if (myParamsComboStringUniquePresent == null) {
|
||||
return false;
|
||||
}
|
||||
return myParamsCompositeStringUniquePresent;
|
||||
return myParamsComboStringUniquePresent;
|
||||
}
|
||||
|
||||
public void setParamsCompositeStringUniquePresent(boolean theParamsCompositeStringUniquePresent) {
|
||||
myParamsCompositeStringUniquePresent = theParamsCompositeStringUniquePresent;
|
||||
public void setParamsComboStringUniquePresent(boolean theParamsComboStringUniquePresent) {
|
||||
myParamsComboStringUniquePresent = theParamsComboStringUniquePresent;
|
||||
}
|
||||
|
||||
public boolean isParamsComboTokensNonUniquePresent() {
|
||||
if (myParamsComboTokensNonUniquePresent == null) {
|
||||
return false;
|
||||
}
|
||||
return myParamsComboTokensNonUniquePresent;
|
||||
}
|
||||
|
||||
public void setParamsComboTokensNonUniquePresent(boolean theParamsComboTokensNonUniquePresent) {
|
||||
myParamsComboStringUniquePresent = theParamsComboTokensNonUniquePresent;
|
||||
}
|
||||
|
||||
public boolean isParamsCoordsPopulated() {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>5.5.0-PRE6-SNAPSHOT</version>
|
||||
<version>5.5.0-PRE7-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue