diff --git a/.mvn/wrapper/MavenWrapperDownloader.java b/.mvn/wrapper/MavenWrapperDownloader.java
new file mode 100755
index 00000000000..fa4f7b499fd
--- /dev/null
+++ b/.mvn/wrapper/MavenWrapperDownloader.java
@@ -0,0 +1,110 @@
+/*
+Licensed to the Apache Software Foundation (ASF) under one
+or more contributor license agreements. See the NOTICE file
+distributed with this work for additional information
+regarding copyright ownership. The ASF licenses this file
+to you 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.
+*/
+
+import java.net.*;
+import java.io.*;
+import java.nio.channels.*;
+import java.util.Properties;
+
+public class MavenWrapperDownloader {
+
+ /**
+ * Default URL to download the maven-wrapper.jar from, if no 'downloadUrl' is provided.
+ */
+ private static final String DEFAULT_DOWNLOAD_URL =
+ "https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.4.2/maven-wrapper-0.4.2.jar";
+
+ /**
+ * Path to the maven-wrapper.properties file, which might contain a downloadUrl property to
+ * use instead of the default one.
+ */
+ private static final String MAVEN_WRAPPER_PROPERTIES_PATH =
+ ".mvn/wrapper/maven-wrapper.properties";
+
+ /**
+ * Path where the maven-wrapper.jar will be saved to.
+ */
+ private static final String MAVEN_WRAPPER_JAR_PATH =
+ ".mvn/wrapper/maven-wrapper.jar";
+
+ /**
+ * Name of the property which should be used to override the default download url for the wrapper.
+ */
+ private static final String PROPERTY_NAME_WRAPPER_URL = "wrapperUrl";
+
+ public static void main(String args[]) {
+ System.out.println("- Downloader started");
+ File baseDirectory = new File(args[0]);
+ System.out.println("- Using base directory: " + baseDirectory.getAbsolutePath());
+
+ // If the maven-wrapper.properties exists, read it and check if it contains a custom
+ // wrapperUrl parameter.
+ File mavenWrapperPropertyFile = new File(baseDirectory, MAVEN_WRAPPER_PROPERTIES_PATH);
+ String url = DEFAULT_DOWNLOAD_URL;
+ if(mavenWrapperPropertyFile.exists()) {
+ FileInputStream mavenWrapperPropertyFileInputStream = null;
+ try {
+ mavenWrapperPropertyFileInputStream = new FileInputStream(mavenWrapperPropertyFile);
+ Properties mavenWrapperProperties = new Properties();
+ mavenWrapperProperties.load(mavenWrapperPropertyFileInputStream);
+ url = mavenWrapperProperties.getProperty(PROPERTY_NAME_WRAPPER_URL, url);
+ } catch (IOException e) {
+ System.out.println("- ERROR loading '" + MAVEN_WRAPPER_PROPERTIES_PATH + "'");
+ } finally {
+ try {
+ if(mavenWrapperPropertyFileInputStream != null) {
+ mavenWrapperPropertyFileInputStream.close();
+ }
+ } catch (IOException e) {
+ // Ignore ...
+ }
+ }
+ }
+ System.out.println("- Downloading from: : " + url);
+
+ File outputFile = new File(baseDirectory.getAbsolutePath(), MAVEN_WRAPPER_JAR_PATH);
+ if(!outputFile.getParentFile().exists()) {
+ if(!outputFile.getParentFile().mkdirs()) {
+ System.out.println(
+ "- ERROR creating output direcrory '" + outputFile.getParentFile().getAbsolutePath() + "'");
+ }
+ }
+ System.out.println("- Downloading to: " + outputFile.getAbsolutePath());
+ try {
+ downloadFileFromURL(url, outputFile);
+ System.out.println("Done");
+ System.exit(0);
+ } catch (Throwable e) {
+ System.out.println("- Error downloading");
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ private static void downloadFileFromURL(String urlString, File destination) throws Exception {
+ URL website = new URL(urlString);
+ ReadableByteChannel rbc;
+ rbc = Channels.newChannel(website.openStream());
+ FileOutputStream fos = new FileOutputStream(destination);
+ fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE);
+ fos.close();
+ rbc.close();
+ }
+
+}
diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties
new file mode 100755
index 00000000000..00d32aab1d4
--- /dev/null
+++ b/.mvn/wrapper/maven-wrapper.properties
@@ -0,0 +1 @@
+distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.4/apache-maven-3.5.4-bin.zip
\ No newline at end of file
diff --git a/examples/pom.xml b/examples/pom.xml
index 15adf39931e..98034c83f21 100644
--- a/examples/pom.xml
+++ b/examples/pom.xml
@@ -92,6 +92,11 @@
org.springframework
spring-web
+
+ ca.uhn.hapi.fhir
+ hapi-fhir-jpaserver-base
+ ${project.version}
+
org.slf4j
diff --git a/examples/src/main/java/example/AuthorizationInterceptors.java b/examples/src/main/java/example/AuthorizationInterceptors.java
index 3ef5822b6d1..28d508a5b38 100644
--- a/examples/src/main/java/example/AuthorizationInterceptors.java
+++ b/examples/src/main/java/example/AuthorizationInterceptors.java
@@ -1,15 +1,11 @@
package example;
-import static org.apache.commons.lang3.StringUtils.isNotBlank;
-
-import java.util.List;
-
-import org.hl7.fhir.dstu3.model.IdType;
-import org.hl7.fhir.instance.model.api.IBaseResource;
-
import ca.uhn.fhir.model.dstu2.resource.Patient;
import ca.uhn.fhir.model.primitive.IdDt;
-import ca.uhn.fhir.rest.annotation.*;
+import ca.uhn.fhir.rest.annotation.ConditionalUrlParam;
+import ca.uhn.fhir.rest.annotation.IdParam;
+import ca.uhn.fhir.rest.annotation.ResourceParam;
+import ca.uhn.fhir.rest.annotation.Update;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
import ca.uhn.fhir.rest.api.server.RequestDetails;
@@ -17,6 +13,12 @@ import ca.uhn.fhir.rest.server.IResourceProvider;
import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
import ca.uhn.fhir.rest.server.interceptor.auth.*;
+import org.hl7.fhir.dstu3.model.IdType;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+
+import java.util.List;
+
+import static org.apache.commons.lang3.StringUtils.isNotBlank;
@SuppressWarnings("unused")
public class AuthorizationInterceptors {
@@ -158,4 +160,47 @@ public class AuthorizationInterceptors {
//END SNIPPET: patchAll
}
+
+
+ //START SNIPPET: narrowing
+ public class MyPatientSearchNarrowingInterceptor extends SearchNarrowingInterceptor {
+
+ /**
+ * This method must be overridden to provide the list of compartments
+ * and/or resources that the current user should have access to
+ */
+ @Override
+ protected AuthorizedList buildAuthorizedList(RequestDetails theRequestDetails) {
+ // Process authorization header - The following is a fake
+ // implementation. Obviously we'd want something more real
+ // for a production scenario.
+ //
+ // In this basic example we have two hardcoded bearer tokens,
+ // one which is for a user that has access to one patient, and
+ // another that has full access.
+ String authHeader = theRequestDetails.getHeader("Authorization");
+ if ("Bearer dfw98h38r".equals(authHeader)) {
+
+ // This user will have access to two compartments
+ return new AuthorizedList()
+ .addCompartment("Patient/123")
+ .addCompartment("Patient/456");
+
+ } else if ("Bearer 39ff939jgg".equals(authHeader)) {
+
+ // This user has access to everything
+ return new AuthorizedList();
+
+ } else {
+
+ throw new AuthenticationException("Unknown bearer token");
+
+ }
+
+ }
+
+ }
+ //END SNIPPET: narrowing
+
+
}
diff --git a/examples/src/main/java/example/interceptor/MyTestInterceptor.java b/examples/src/main/java/example/interceptor/MyTestInterceptor.java
new file mode 100644
index 00000000000..ba4b92f4aaf
--- /dev/null
+++ b/examples/src/main/java/example/interceptor/MyTestInterceptor.java
@@ -0,0 +1,25 @@
+package example.interceptor;
+
+import ca.uhn.fhir.jpa.model.interceptor.api.Hook;
+import ca.uhn.fhir.jpa.model.interceptor.api.Interceptor;
+import ca.uhn.fhir.jpa.model.interceptor.api.Pointcut;
+import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
+import ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage;
+
+/**
+ * Interceptor class
+ */
+@Interceptor
+public class MyTestInterceptor {
+
+ @Hook(Pointcut.SUBSCRIPTION_BEFORE_REST_HOOK_DELIVERY)
+ public boolean beforeRestHookDelivery(ResourceDeliveryMessage theDeliveryMessage, CanonicalSubscription theSubscription) {
+
+ String header = "Authorization: Bearer 1234567";
+
+ theSubscription.addHeader(header);
+
+ return true;
+ }
+
+}
diff --git a/hapi-fhir-base/pom.xml b/hapi-fhir-base/pom.xml
index 4056f44e884..ef32c50de30 100644
--- a/hapi-fhir-base/pom.xml
+++ b/hapi-fhir-base/pom.xml
@@ -162,12 +162,45 @@
+
+ org.codehaus.mojo
+ buildnumber-maven-plugin
+ true
+
+
+ standard
+ validate
+
+ create
+
+
+
+ downstream
+ validate
+
+ create-metadata
+
+
+ ${project.build.directory}/generated-sources/properties
+ ca/uhn/fhir/hapi-fhir-base-build.properties
+ hapifhir.buildnumber
+ hapifhir.timestamp
+ yyyy-MM-dd'T'HH:mm:ss.SXXX
+ hapifhir.version
+
+
+
+
src/main/resources
true
+
+ ${project.build.directory}/generated-sources/properties
+ false
+
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/ReferenceClientParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/ReferenceClientParam.java
index 9a8cdcda269..7b2aba70b6b 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/ReferenceClientParam.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/gclient/ReferenceClientParam.java
@@ -1,8 +1,10 @@
package ca.uhn.fhir.rest.gclient;
import ca.uhn.fhir.context.FhirContext;
+import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IIdType;
+import java.util.Arrays;
import java.util.Collection;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
@@ -97,7 +99,19 @@ public class ReferenceClientParam extends BaseClientParam implements IParam {
public ICriterion hasAnyOfIds(Collection theIds) {
return new StringCriterion<>(getParamName(), theIds);
}
-
+
+ /**
+ * Match the referenced resource if the resource has ANY of the given IDs
+ * (this is an OR search, not an AND search), (this can be the logical ID or
+ * the absolute URL of the resource). Note that to specify an AND search,
+ * simply add a subsequent {@link IQuery#where(ICriterion) where} criteria
+ * with the same parameter.
+ */
+ public ICriterion hasAnyOfIds(String... theIds) {
+ Validate.notNull(theIds, "theIds must not be null");
+ return hasAnyOfIds(Arrays.asList(theIds));
+ }
+
private static class ReferenceChainCriterion implements ICriterion, ICriterionInternal {
private final String myResourceTypeQualifier;
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseAndListParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseAndListParam.java
index b6533e892dc..39e23a5bd68 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseAndListParam.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/BaseAndListParam.java
@@ -62,5 +62,10 @@ public abstract class BaseAndListParam> implement
return myValues.toString();
}
-
+ /**
+ * Returns the number of AND parameters
+ */
+ public int size() {
+ return myValues.size();
+ }
}
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/DateParam.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/DateParam.java
index d6c3ec9e9da..246d3b8d099 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/DateParam.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/DateParam.java
@@ -255,7 +255,15 @@ public class DateParam extends BaseParamWithPrefix implements /*IQuer
return b.build();
}
- public class DateParamDateTimeHolder extends BaseDateTimeDt {
+ public static class DateParamDateTimeHolder extends BaseDateTimeDt {
+
+ /**
+ * Constructor
+ */
+ public DateParamDateTimeHolder() {
+ super();
+ }
+
@Override
protected TemporalPrecisionEnum getDefaultPrecisionForDatatype() {
return TemporalPrecisionEnum.SECOND;
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ParameterUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ParameterUtil.java
index 7c74ece0228..c33bc9ed6b2 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ParameterUtil.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/rest/param/ParameterUtil.java
@@ -20,8 +20,10 @@ import org.hl7.fhir.instance.model.api.IPrimitiveType;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.stream.Collectors;
/*
* #%L
@@ -208,6 +210,13 @@ public class ParameterUtil {
|| IPrimitiveType.class.isAssignableFrom(theClass);
}
+ public static String escapeAndJoinOrList(Collection theValues) {
+ return theValues
+ .stream()
+ .map(ParameterUtil::escape)
+ .collect(Collectors.joining(","));
+ }
+
public static int nonEscapedIndexOf(String theString, char theCharacter) {
for (int i = 0; i < theString.length(); i++) {
if (theString.charAt(i) == theCharacter) {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/UrlUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/UrlUtil.java
index 10be04f97b3..d9bd5cec28c 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/UrlUtil.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/UrlUtil.java
@@ -1,6 +1,9 @@
package ca.uhn.fhir.util;
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.model.primitive.IdDt;
+import ca.uhn.fhir.parser.DataFormatException;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import com.google.common.escape.Escaper;
@@ -172,8 +175,13 @@ public class UrlUtil {
return true;
}
- public static void main(String[] args) {
- System.out.println(escapeUrlParam("http://snomed.info/sct?fhir_vs=isa/126851005"));
+ public static RuntimeResourceDefinition parseUrlResourceType(FhirContext theCtx, String theUrl) throws DataFormatException {
+ int paramIndex = theUrl.indexOf('?');
+ String resourceName = theUrl.substring(0, paramIndex);
+ if (resourceName.contains("/")) {
+ resourceName = resourceName.substring(resourceName.lastIndexOf('/') + 1);
+ }
+ return theCtx.getResourceDefinition(resourceName);
}
public static Map parseQueryString(String theQueryString) {
diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionUtil.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionUtil.java
index f0852a252df..c2208fd3c60 100644
--- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionUtil.java
+++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/util/VersionUtil.java
@@ -20,9 +20,13 @@ package ca.uhn.fhir.util;
* #L%
*/
+import org.apache.commons.lang3.StringUtils;
+
import java.io.InputStream;
import java.util.Properties;
+import static org.apache.commons.lang3.StringUtils.defaultIfBlank;
+
/**
* Used internally by HAPI to log the version of the HAPI FHIR framework
* once, when the framework is first loaded by the classloader.
@@ -31,24 +35,46 @@ public class VersionUtil {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(VersionUtil.class);
private static String ourVersion;
+ private static String ourBuildNumber;
+ private static String ourBuildTime;
static {
initialize();
}
+ public static String getBuildNumber() {
+ return ourBuildNumber;
+ }
+
+ public static String getBuildTime() {
+ return ourBuildTime;
+ }
+
public static String getVersion() {
return ourVersion;
}
private static void initialize() {
- try (InputStream is = VersionUtil.class.getResourceAsStream("/ca/uhn/fhir/hapi-version.properties")) {
+ try (InputStream is = VersionUtil.class.getResourceAsStream("/ca/uhn/fhir/hapi-fhir-base-build.properties")) {
+
Properties p = new Properties();
- p.load(is);
- ourVersion = p.getProperty("version");
- ourLog.info("HAPI FHIR version is: " + ourVersion);
+ if (is != null) {
+ p.load(is);
+ }
+
+ ourVersion = p.getProperty("hapifhir.version");
+ ourVersion = defaultIfBlank(ourVersion, "(unknown)");
+
+ ourBuildNumber = p.getProperty("hapifhir.buildnumber");
+ ourBuildTime = p.getProperty("hapifhir.timestamp");
+
+ if (System.getProperty("suppress_hapi_fhir_version_log") == null) {
+ ourLog.info("HAPI FHIR version {} - Rev {}", ourVersion, StringUtils.right(ourBuildNumber, 10));
+ }
+
} catch (Exception e) {
ourLog.warn("Unable to determine HAPI version information", e);
}
}
-
+
}
diff --git a/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IAnyResource.java b/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IAnyResource.java
index 7dd655693b4..13ce67e35f5 100644
--- a/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IAnyResource.java
+++ b/hapi-fhir-base/src/main/java/org/hl7/fhir/instance/model/api/IAnyResource.java
@@ -29,14 +29,14 @@ public interface IAnyResource extends IBaseResource {
* Search parameter constant for _language
*/
@SearchParamDefinition(name="_language", path="", description="The language of the resource", type="string" )
- public static final String SP_RES_LANGUAGE = "_language";
+ String SP_RES_LANGUAGE = "_language";
/**
* Search parameter constant for _id
*/
@SearchParamDefinition(name="_id", path="", description="The ID of the resource", type="token" )
- public static final String SP_RES_ID = "_id";
+ String SP_RES_ID = "_id";
/**
* Fluent Client search parameter constant for _id
@@ -46,7 +46,7 @@ public interface IAnyResource extends IBaseResource {
* Path: Resource._id
*
*/
- public static final TokenClientParam RES_ID = new TokenClientParam(IAnyResource.SP_RES_ID);
+ TokenClientParam RES_ID = new TokenClientParam(IAnyResource.SP_RES_ID);
String getId();
@@ -55,11 +55,11 @@ public interface IAnyResource extends IBaseResource {
IPrimitiveType getLanguageElement();
- public Object getUserData(String name);
+ Object getUserData(String name);
@Override
IAnyResource setId(String theId);
- public void setUserData(String name, Object value);
+ void setUserData(String name, Object value);
}
diff --git a/hapi-fhir-base/src/main/resources/ca/uhn/fhir/hapi-version.properties b/hapi-fhir-base/src/main/resources/ca/uhn/fhir/hapi-version.properties
deleted file mode 100644
index e5683df88cb..00000000000
--- a/hapi-fhir-base/src/main/resources/ca/uhn/fhir/hapi-version.properties
+++ /dev/null
@@ -1 +0,0 @@
-version=${project.version}
\ No newline at end of file
diff --git a/hapi-fhir-base/src/test/java/ca/uhn/fhir/util/VersionUtilTest.java b/hapi-fhir-base/src/test/java/ca/uhn/fhir/util/VersionUtilTest.java
new file mode 100644
index 00000000000..c66151b6d3e
--- /dev/null
+++ b/hapi-fhir-base/src/test/java/ca/uhn/fhir/util/VersionUtilTest.java
@@ -0,0 +1,19 @@
+package ca.uhn.fhir.util;
+
+import org.junit.Test;
+
+import static org.hamcrest.CoreMatchers.not;
+import static org.hamcrest.Matchers.blankOrNullString;
+import static org.junit.Assert.*;
+
+public class VersionUtilTest {
+
+ @Test
+ public void testProperties() {
+ assertThat(VersionUtil.getVersion(), not(blankOrNullString()));
+ assertThat(VersionUtil.getBuildNumber(), not(blankOrNullString()));
+ assertThat(VersionUtil.getBuildTime(), not(blankOrNullString()));
+ }
+
+
+}
diff --git a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/impl/RestfulClientFactory.java b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/impl/RestfulClientFactory.java
index c6100a4fa31..d6afdfc59e8 100644
--- a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/impl/RestfulClientFactory.java
+++ b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/impl/RestfulClientFactory.java
@@ -301,7 +301,7 @@ public abstract class RestfulClientFactory implements IRestfulClientFactory {
conformance = (IBaseResource) client.fetchConformance().ofType(implementingClass).execute();
} catch (FhirClientConnectionException e) {
if (!myContext.getVersion().getVersion().isOlderThan(FhirVersionEnum.DSTU3) && e.getCause() instanceof DataFormatException) {
- capabilityStatementResourceName = "Conformance";
+ capabilityStatementResourceName = "CapabilityStatement";
implementingClass = myContext.getResourceDefinition(capabilityStatementResourceName).getImplementingClass();
conformance = (IBaseResource) client.fetchConformance().ofType(implementingClass).execute();
} else {
diff --git a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/BaseQueryParameter.java b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/BaseQueryParameter.java
index 2f056184b13..9e260e56755 100644
--- a/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/BaseQueryParameter.java
+++ b/hapi-fhir-client/src/main/java/ca/uhn/fhir/rest/client/method/BaseQueryParameter.java
@@ -81,7 +81,7 @@ public abstract class BaseQueryParameter implements IParameter {
String paramName = isNotBlank(qualifier) ? getName() + qualifier : getName();
List paramValues = theTargetQueryArguments.get(paramName);
if (paramValues == null) {
- paramValues = new ArrayList(value.size());
+ paramValues = new ArrayList<>(value.size());
theTargetQueryArguments.put(paramName, paramValues);
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseConfig.java
index 5e6377848cb..4880c08c8c9 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseConfig.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/config/BaseConfig.java
@@ -57,10 +57,12 @@ import javax.annotation.Nonnull;
@Configuration
@EnableScheduling
@EnableJpaRepositories(basePackages = "ca.uhn.fhir.jpa.dao.data")
-@ComponentScan(basePackages = "ca.uhn.fhir.jpa", excludeFilters={
- @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=BaseConfig.class),
- @ComponentScan.Filter(type=FilterType.ASSIGNABLE_TYPE, value=WebSocketConfigurer.class),
- @ComponentScan.Filter(type=FilterType.REGEX, pattern="ca.uhn.fhir.jpa.subscription.module.standalone.*")})
+@ComponentScan(basePackages = "ca.uhn.fhir.jpa", excludeFilters = {
+ @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = BaseConfig.class),
+ @ComponentScan.Filter(type = FilterType.ASSIGNABLE_TYPE, value = WebSocketConfigurer.class),
+ @ComponentScan.Filter(type = FilterType.REGEX, pattern = ".*\\.test\\..*"),
+ @ComponentScan.Filter(type = FilterType.REGEX, pattern = ".*Test.*"),
+ @ComponentScan.Filter(type = FilterType.REGEX, pattern = "ca.uhn.fhir.jpa.subscription.module.standalone.*")})
public abstract class BaseConfig implements SchedulingConfigurer {
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java
index 9ad47a9730b..b9bd91e2eb6 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirDao.java
@@ -7,6 +7,9 @@ import ca.uhn.fhir.jpa.dao.index.IdHelperService;
import ca.uhn.fhir.jpa.dao.index.SearchParamWithInlineReferencesExtractor;
import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.model.entity.*;
+import ca.uhn.fhir.jpa.model.interceptor.api.HookParams;
+import ca.uhn.fhir.jpa.model.interceptor.api.IInterceptorBroadcaster;
+import ca.uhn.fhir.jpa.model.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc;
import ca.uhn.fhir.jpa.search.PersistedJpaBundleProvider;
import ca.uhn.fhir.jpa.searchparam.ResourceMetaParams;
@@ -58,7 +61,6 @@ import org.hibernate.Session;
import org.hibernate.internal.SessionImpl;
import org.hl7.fhir.instance.model.api.*;
import org.hl7.fhir.r4.model.Bundle.HTTPVerb;
-import org.hl7.fhir.r4.model.InstantType;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
@@ -70,6 +72,8 @@ import org.springframework.data.domain.SliceImpl;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
+import org.springframework.transaction.support.TransactionSynchronizationAdapter;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate;
import javax.persistence.*;
@@ -116,7 +120,7 @@ public abstract class BaseHapiFhirDao implements IDao,
public static final String OO_SEVERITY_INFO = "information";
public static final String OO_SEVERITY_WARN = "warning";
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(BaseHapiFhirDao.class);
- private static final Map ourRetrievalContexts = new HashMap();
+ private static final Map ourRetrievalContexts = new HashMap<>();
private static final String PROCESSING_SUB_REQUEST = "BaseHapiFhirDao.processingSubRequest";
private static boolean ourValidationDisabledForUnitTest;
private static boolean ourDisableIncrementOnUpdateForUnitTest = false;
@@ -126,6 +130,8 @@ public abstract class BaseHapiFhirDao implements IDao,
@Autowired
protected IdHelperService myIdHelperService;
@Autowired
+ protected IInterceptorBroadcaster myInterceptorBroadcaster;
+ @Autowired
protected IForcedIdDao myForcedIdDao;
@Autowired
protected ISearchResultDao mySearchResultDao;
@@ -1421,9 +1427,8 @@ public abstract class BaseHapiFhirDao implements IDao,
return updateEntity(theRequest, theResource, entity, theDeletedTimestampOrNull, true, true, theUpdateTime, false, true);
}
- public ResourceTable updateInternal(RequestDetails theRequest, T theResource, boolean thePerformIndexing,
- boolean theForceUpdateVersion, RequestDetails theRequestDetails, ResourceTable theEntity, IIdType
- theResourceId, IBaseResource theOldResource) {
+ public ResourceTable updateInternal(RequestDetails theRequestDetails, T theResource, boolean thePerformIndexing, boolean theForceUpdateVersion,
+ ResourceTable theEntity, IIdType theResourceId, IBaseResource theOldResource) {
// Notify interceptors
ActionRequestDetails requestDetails;
if (theRequestDetails != null) {
@@ -1440,9 +1445,13 @@ public abstract class BaseHapiFhirDao implements IDao,
((IServerOperationInterceptor) next).resourcePreUpdate(theRequestDetails, theOldResource, theResource);
}
}
+ HookParams hookParams = new HookParams()
+ .add(IBaseResource.class, theOldResource)
+ .add(IBaseResource.class, theResource);
+ myInterceptorBroadcaster.callHooks(Pointcut.OP_PRESTORAGE_RESOURCE_UPDATED, hookParams);
// Perform update
- ResourceTable savedEntity = updateEntity(theRequest, theResource, theEntity, null, thePerformIndexing, thePerformIndexing, new Date(), theForceUpdateVersion, thePerformIndexing);
+ ResourceTable savedEntity = updateEntity(theRequestDetails, theResource, theEntity, null, thePerformIndexing, thePerformIndexing, new Date(), theForceUpdateVersion, thePerformIndexing);
/*
* If we aren't indexing (meaning we're probably executing a sub-operation within a transaction),
@@ -1471,7 +1480,17 @@ public abstract class BaseHapiFhirDao implements IDao,
((IServerOperationInterceptor) next).resourceUpdated(theRequestDetails, theOldResource, theResource);
}
}
+ TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
+ @Override
+ public void beforeCommit(boolean readOnly) {
+ HookParams hookParams = new HookParams()
+ .add(IBaseResource.class, theOldResource)
+ .add(IBaseResource.class, theResource);
+ myInterceptorBroadcaster.callHooks(Pointcut.OP_PRECOMMIT_RESOURCE_UPDATED, hookParams);
+ }
+ });
}
+
return savedEntity;
}
@@ -1481,6 +1500,10 @@ public abstract class BaseHapiFhirDao implements IDao,
id = getContext().getVersion().newIdType().setValue(id.getValue());
}
+ if (id.hasResourceType() == false) {
+ id = id.withResourceType(theEntity.getResourceType());
+ }
+
theResource.setId(id);
if (theResource instanceof IResource) {
ResourceMetadataKeyEnum.VERSION.put((IResource) theResource, id.getVersionIdPart());
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java
index fbe42a91c8c..d55055aaa91 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/BaseHapiFhirResourceDao.java
@@ -26,6 +26,8 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.context.RuntimeSearchParam;
import ca.uhn.fhir.jpa.dao.r4.MatchResourceUrlService;
import ca.uhn.fhir.jpa.model.entity.*;
+import ca.uhn.fhir.jpa.model.interceptor.api.HookParams;
+import ca.uhn.fhir.jpa.model.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.PersistedJpaBundleProvider;
import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
@@ -35,7 +37,9 @@ import ca.uhn.fhir.jpa.util.ExpungeOptions;
import ca.uhn.fhir.jpa.util.ExpungeOutcome;
import ca.uhn.fhir.jpa.util.jsonpatch.JsonPatchUtils;
import ca.uhn.fhir.jpa.util.xmlpatch.XmlPatchUtils;
-import ca.uhn.fhir.model.api.*;
+import ca.uhn.fhir.model.api.IQueryParameterAnd;
+import ca.uhn.fhir.model.api.IQueryParameterType;
+import ca.uhn.fhir.model.api.TagList;
import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.api.*;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
@@ -57,10 +61,11 @@ import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
+import org.springframework.transaction.support.TransactionSynchronizationAdapter;
+import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.transaction.support.TransactionTemplate;
import javax.annotation.Nonnull;
-import javax.annotation.Nullable;
import javax.annotation.PostConstruct;
import javax.persistence.NoResultException;
import javax.persistence.TypedQuery;
@@ -172,7 +177,7 @@ public abstract class BaseHapiFhirResourceDao extends B
}
@Override
- public DaoMethodOutcome delete(IIdType theId, List theDeleteConflicts, RequestDetails theReques) {
+ public DaoMethodOutcome delete(IIdType theId, List theDeleteConflicts, RequestDetails theRequest) {
if (theId == null || !theId.hasIdPart()) {
throw new InvalidRequestException("Can not perform delete, no ID provided");
}
@@ -205,12 +210,12 @@ public abstract class BaseHapiFhirResourceDao extends B
T resourceToDelete = toResource(myResourceType, entity, null, false);
// Notify IServerOperationInterceptors about pre-action call
- if (theReques != null) {
- theReques.getRequestOperationCallback().resourcePreDelete(resourceToDelete);
+ if (theRequest != null) {
+ theRequest.getRequestOperationCallback().resourcePreDelete(resourceToDelete);
}
for (IServerInterceptor next : getConfig().getInterceptors()) {
if (next instanceof IServerOperationInterceptor) {
- ((IServerOperationInterceptor) next).resourcePreDelete(theReques, resourceToDelete);
+ ((IServerOperationInterceptor) next).resourcePreDelete(theRequest, resourceToDelete);
}
}
@@ -219,25 +224,33 @@ public abstract class BaseHapiFhirResourceDao extends B
preDelete(resourceToDelete, entity);
// Notify interceptors
- if (theReques != null) {
- ActionRequestDetails requestDetails = new ActionRequestDetails(theReques, getContext(), theId.getResourceType(), theId);
+ if (theRequest != null) {
+ ActionRequestDetails requestDetails = new ActionRequestDetails(theRequest, getContext(), theId.getResourceType(), theId);
notifyInterceptors(RestOperationTypeEnum.DELETE, requestDetails);
}
Date updateTime = new Date();
- ResourceTable savedEntity = updateEntity(theReques, null, entity, updateTime, updateTime);
+ ResourceTable savedEntity = updateEntity(theRequest, null, entity, updateTime, updateTime);
resourceToDelete.setId(entity.getIdDt());
// Notify JPA interceptors
- if (theReques != null) {
- ActionRequestDetails requestDetails = new ActionRequestDetails(theReques, getContext(), theId.getResourceType(), theId);
- theReques.getRequestOperationCallback().resourceDeleted(resourceToDelete);
+ if (theRequest != null) {
+ ActionRequestDetails requestDetails = new ActionRequestDetails(theRequest, getContext(), theId.getResourceType(), theId);
+ theRequest.getRequestOperationCallback().resourceDeleted(resourceToDelete);
}
for (IServerInterceptor next : getConfig().getInterceptors()) {
if (next instanceof IServerOperationInterceptor) {
- ((IServerOperationInterceptor) next).resourceDeleted(theReques, resourceToDelete);
+ ((IServerOperationInterceptor) next).resourceDeleted(theRequest, resourceToDelete);
}
}
+ TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
+ @Override
+ public void beforeCommit(boolean readOnly) {
+ HookParams hookParams = new HookParams()
+ .add(IBaseResource.class, resourceToDelete);
+ myInterceptorBroadcaster.callHooks(Pointcut.OP_PRECOMMIT_RESOURCE_DELETED, hookParams);
+ }
+ });
DaoMethodOutcome outcome = toMethodOutcome(savedEntity, resourceToDelete).setCreated(true);
@@ -320,6 +333,14 @@ public abstract class BaseHapiFhirResourceDao extends B
((IServerOperationInterceptor) next).resourceDeleted(theRequest, resourceToDelete);
}
}
+ TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
+ @Override
+ public void beforeCommit(boolean readOnly) {
+ HookParams hookParams = new HookParams()
+ .add(IBaseResource.class, resourceToDelete);
+ myInterceptorBroadcaster.callHooks(Pointcut.OP_PRECOMMIT_RESOURCE_DELETED, hookParams);
+ }
+ });
}
IBaseOperationOutcome oo;
@@ -422,6 +443,9 @@ public abstract class BaseHapiFhirResourceDao extends B
((IServerOperationInterceptor) next).resourcePreCreate(theRequest, theResource);
}
}
+ HookParams hookParams = new HookParams()
+ .add(IBaseResource.class, theResource);
+ myInterceptorBroadcaster.callHooks(Pointcut.OP_PRESTORAGE_RESOURCE_CREATED, hookParams);
// Perform actual DB update
ResourceTable updatedEntity = updateEntity(theRequest, theResource, entity, null, thePerformIndexing, thePerformIndexing, theUpdateTime, false, thePerformIndexing);
@@ -465,6 +489,14 @@ public abstract class BaseHapiFhirResourceDao extends B
}
}
}
+ TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() {
+ @Override
+ public void beforeCommit(boolean readOnly) {
+ HookParams hookParams = new HookParams()
+ .add(IBaseResource.class, theResource);
+ myInterceptorBroadcaster.callHooks(Pointcut.OP_PRECOMMIT_RESOURCE_CREATED, hookParams);
+ }
+ });
DaoMethodOutcome outcome = toMethodOutcome(entity, theResource).setCreated(true);
if (!thePerformIndexing) {
@@ -752,7 +784,6 @@ public abstract class BaseHapiFhirResourceDao extends B
return retVal;
}
- @SuppressWarnings("JpaQlInspection")
@Override
public MT metaGetOperation(Class theType, RequestDetails theRequestDetails) {
// Notify interceptors
@@ -943,8 +974,7 @@ public abstract class BaseHapiFhirResourceDao extends B
if (entity == null) {
if (theId.hasVersionIdPart()) {
- TypedQuery q = myEntityManager
- .createQuery("SELECT t from ResourceHistoryTable t WHERE t.myResourceId = :RID AND t.myResourceType = :RTYP AND t.myResourceVersion = :RVER", ResourceHistoryTable.class);
+ TypedQuery q = myEntityManager.createQuery("SELECT t from ResourceHistoryTable t WHERE t.myResourceId = :RID AND t.myResourceType = :RTYP AND t.myResourceVersion = :RVER", ResourceHistoryTable.class);
q.setParameter("RID", pid);
q.setParameter("RTYP", myResourceName);
q.setParameter("RVER", theId.getVersionIdPartAsLong());
@@ -1304,7 +1334,7 @@ public abstract class BaseHapiFhirResourceDao extends B
/*
* Otherwise, we're not in a transaction
*/
- ResourceTable savedEntity = updateInternal(theRequestDetails, theResource, thePerformIndexing, theForceUpdateVersion, theRequestDetails, entity, resourceId, oldResource);
+ ResourceTable savedEntity = updateInternal(theRequestDetails, theResource, thePerformIndexing, theForceUpdateVersion, entity, resourceId, oldResource);
DaoMethodOutcome outcome = toMethodOutcome(savedEntity, theResource).setCreated(false);
if (!thePerformIndexing) {
@@ -1319,13 +1349,13 @@ public abstract class BaseHapiFhirResourceDao extends B
}
@Override
- public DaoMethodOutcome update(T theResource, String theMatchUrl, boolean thePerformIndexing, RequestDetails theRequestDetails) {
- return update(theResource, theMatchUrl, thePerformIndexing, false, theRequestDetails);
+ public DaoMethodOutcome update(T theResource, String theMatchUrl, RequestDetails theRequestDetails) {
+ return update(theResource, theMatchUrl, true, theRequestDetails);
}
@Override
- public DaoMethodOutcome update(T theResource, String theMatchUrl, RequestDetails theRequestDetails) {
- return update(theResource, theMatchUrl, true, theRequestDetails);
+ public DaoMethodOutcome update(T theResource, String theMatchUrl, boolean thePerformIndexing, RequestDetails theRequestDetails) {
+ return update(theResource, theMatchUrl, thePerformIndexing, false, theRequestDetails);
}
/**
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java
index a0e0766db0d..383df71a802 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoConfig.java
@@ -143,7 +143,6 @@ public class DaoConfig {
private boolean myDisableHashBasedSearches;
private boolean myEnableInMemorySubscriptionMatching = true;
private ClientIdStrategyEnum myResourceClientIdStrategy = ClientIdStrategyEnum.ALPHANUMERIC;
- private boolean mySubscriptionMatchingEnabled = true;
/**
* Constructor
@@ -530,7 +529,7 @@ public class DaoConfig {
* This may be used to optionally register server interceptors directly against the DAOs.
*/
public void setInterceptors(IServerInterceptor... theInterceptor) {
- setInterceptors(new ArrayList());
+ setInterceptors(new ArrayList<>());
if (theInterceptor != null && theInterceptor.length != 0) {
getInterceptors().addAll(Arrays.asList(theInterceptor));
}
@@ -1308,8 +1307,7 @@ public class DaoConfig {
public void setSearchPreFetchThresholds(List thePreFetchThresholds) {
Validate.isTrue(thePreFetchThresholds.size() > 0, "thePreFetchThresholds must not be empty");
int last = 0;
- for (Integer nextInteger : thePreFetchThresholds) {
- int nextInt = nextInteger.intValue();
+ for (Integer nextInt : thePreFetchThresholds) {
Validate.isTrue(nextInt > 0 || nextInt == -1, nextInt + " is not a valid prefetch threshold");
Validate.isTrue(nextInt != last, "Prefetch thresholds must be sequential");
Validate.isTrue(nextInt > last || nextInt == -1, "Prefetch thresholds must be sequential");
@@ -1398,7 +1396,7 @@ public class DaoConfig {
*/
public boolean isSubscriptionMatchingEnabled() {
- return mySubscriptionMatchingEnabled;
+ return myModelConfig.isSubscriptionMatchingEnabled();
}
/**
@@ -1407,9 +1405,8 @@ public class DaoConfig {
* @since 3.7.0
*/
-
public void setSubscriptionMatchingEnabled(boolean theSubscriptionMatchingEnabled) {
- mySubscriptionMatchingEnabled = theSubscriptionMatchingEnabled;
+ myModelConfig.setSubscriptionMatchingEnabled(theSubscriptionMatchingEnabled);
}
public ModelConfig getModelConfig() {
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoSearchParamProvider.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoSearchParamProvider.java
index 638643d6413..961c06021be 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoSearchParamProvider.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/DaoSearchParamProvider.java
@@ -44,12 +44,8 @@ public class DaoSearchParamProvider implements ISearchParamProvider {
}
@Override
- public void refreshCache(BaseSearchParamRegistry theSearchParamRegistry, long theRefreshInterval) {
+ public int refreshCache(BaseSearchParamRegistry theSearchParamRegistry, long theRefreshInterval) {
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
- txTemplate.execute(t->{
- theSearchParamRegistry.doRefresh(theRefreshInterval);
- return null;
- });
-
+ return txTemplate.execute(t-> theSearchParamRegistry.doRefresh(theRefreshInterval));
}
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2.java
index 32bdbe3a77f..9db169e2236 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/FhirSystemDaoDstu2.java
@@ -233,7 +233,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao {
Integer originalOrder = originalRequestOrder.get(nextReqEntry);
Entry nextRespEntry = response.getEntry().get(originalOrder);
- ServletSubRequestDetails requestDetails = new ServletSubRequestDetails();
+ ServletSubRequestDetails requestDetails = new ServletSubRequestDetails(theRequestDetails);
requestDetails.setServletRequest(theRequestDetails.getServletRequest());
requestDetails.setRequestType(RequestTypeEnum.GET);
requestDetails.setServer(theRequestDetails.getServer());
@@ -492,7 +492,7 @@ public class FhirSystemDaoDstu2 extends BaseHapiFhirSystemDao {
InstantDt deletedInstantOrNull = ResourceMetadataKeyEnum.DELETED_AT.get(nextResource);
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
if (theUpdatedEntities.contains(nextOutcome.getEntity())) {
- updateInternal(theRequestDetails, nextResource, true, false, theRequestDetails, nextOutcome.getEntity(), nextResource.getIdElement(), nextOutcome.getPreviousResource());
+ updateInternal(theRequestDetails, nextResource, true, false, nextOutcome.getEntity(), nextResource.getIdElement(), nextOutcome.getPreviousResource());
} else if (!theNonUpdatedEntities.contains(nextOutcome.getEntity())) {
updateEntity(theRequestDetails, nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, true, false, theUpdateTime, false, true);
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java
index cdcb55bb342..a5187798ee0 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/SearchBuilder.java
@@ -80,7 +80,6 @@ import org.hl7.fhir.instance.model.api.IIdType;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;
-import org.thymeleaf.util.ListUtils;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
@@ -100,7 +99,6 @@ import static org.apache.commons.lang3.StringUtils.*;
* The SearchBuilder is responsible for actually forming the SQL query that handles
* searches for resources
*/
-@SuppressWarnings("JpaQlInspection")
@Component
@Scope("prototype")
public class SearchBuilder implements ISearchBuilder {
@@ -386,7 +384,8 @@ public class SearchBuilder implements ISearchBuilder {
List codePredicates = new ArrayList<>();
- for (IQueryParameterType nextOr : theList) {
+ for (int orIdx = 0; orIdx < theList.size(); orIdx++) {
+ IQueryParameterType nextOr = theList.get(orIdx);
if (nextOr instanceof ReferenceParam) {
ReferenceParam ref = (ReferenceParam) nextOr;
@@ -497,15 +496,16 @@ public class SearchBuilder implements ISearchBuilder {
boolean foundChainMatch = false;
- String chain = ref.getChain();
- String remainingChain = null;
- int chainDotIndex = chain.indexOf('.');
- if (chainDotIndex != -1) {
- remainingChain = chain.substring(chainDotIndex + 1);
- chain = chain.substring(0, chainDotIndex);
- }
-
for (Class extends IBaseResource> nextType : resourceTypes) {
+
+ String chain = ref.getChain();
+ String remainingChain = null;
+ int chainDotIndex = chain.indexOf('.');
+ if (chainDotIndex != -1) {
+ remainingChain = chain.substring(chainDotIndex + 1);
+ chain = chain.substring(0, chainDotIndex);
+ }
+
RuntimeResourceDefinition typeDef = myContext.getResourceDefinition(nextType);
String subResourceName = typeDef.getName();
@@ -532,37 +532,29 @@ public class SearchBuilder implements ISearchBuilder {
}
}
- IQueryParameterType chainValue;
- if (remainingChain != null) {
- if (param == null || param.getParamType() != RestSearchParameterTypeEnum.REFERENCE) {
- ourLog.debug("Type {} parameter {} is not a reference, can not chain {}", nextType.getSimpleName(), chain, remainingChain);
+ ArrayList orValues = Lists.newArrayList();
+
+ for (IQueryParameterType next : theList) {
+ String nextValue = next.getValueAsQueryToken(myContext);
+ IQueryParameterType chainValue = mapReferenceChainToRawParamType(remainingChain, param, theParamName, qualifier, nextType, chain, isMeta, nextValue);
+ if (chainValue == null) {
continue;
}
-
- chainValue = new ReferenceParam();
- chainValue.setValueAsQueryToken(myContext, theParamName, qualifier, resourceId);
- ((ReferenceParam) chainValue).setChain(remainingChain);
- } else if (isMeta) {
- IQueryParameterType type = myMatchUrlService.newInstanceType(chain);
- type.setValueAsQueryToken(myContext, theParamName, qualifier, resourceId);
- chainValue = type;
- } else {
- chainValue = toParameterType(param, qualifier, resourceId);
+ foundChainMatch = true;
+ orValues.add(chainValue);
}
- foundChainMatch = true;
-
Subquery subQ = myResourceTableQuery.subquery(Long.class);
Root subQfrom = subQ.from(ResourceTable.class);
subQ.select(subQfrom.get("myId").as(Long.class));
List> andOrParams = new ArrayList<>();
- andOrParams.add(Collections.singletonList(chainValue));
+ andOrParams.add(orValues);
/*
* We're doing a chain call, so push the current query root
* and predicate list down and put new ones at the top of the
- * stack and run a subuery
+ * stack and run a subquery
*/
Root stackRoot = myResourceTableRoot;
ArrayList stackPredicates = myPredicates;
@@ -574,9 +566,11 @@ public class SearchBuilder implements ISearchBuilder {
// Create the subquery predicates
myPredicates.add(myBuilder.equal(myResourceTableRoot.get("myResourceType"), subResourceName));
myPredicates.add(myBuilder.isNull(myResourceTableRoot.get("myDeleted")));
- searchForIdsWithAndOr(subResourceName, chain, andOrParams);
- subQ.where(toArray(myPredicates));
+ if (foundChainMatch) {
+ searchForIdsWithAndOr(subResourceName, chain, andOrParams);
+ subQ.where(toArray(myPredicates));
+ }
/*
* Pop the old query root and predicate list back
@@ -594,6 +588,10 @@ public class SearchBuilder implements ISearchBuilder {
if (!foundChainMatch) {
throw new InvalidRequestException(myContext.getLocalizer().getMessage(BaseHapiFhirResourceDao.class, "invalidParameterChain", theParamName + '.' + ref.getChain()));
}
+
+ myPredicates.add(myBuilder.or(toArray(codePredicates)));
+ return;
+
}
} else {
@@ -605,6 +603,28 @@ public class SearchBuilder implements ISearchBuilder {
myPredicates.add(myBuilder.or(toArray(codePredicates)));
}
+ private IQueryParameterType mapReferenceChainToRawParamType(String remainingChain, RuntimeSearchParam param, String theParamName, String qualifier, Class extends IBaseResource> nextType, String chain, boolean isMeta, String resourceId) {
+ IQueryParameterType chainValue;
+ if (remainingChain != null) {
+ if (param == null || param.getParamType() != RestSearchParameterTypeEnum.REFERENCE) {
+ ourLog.debug("Type {} parameter {} is not a reference, can not chain {}", nextType.getSimpleName(), chain, remainingChain);
+ return null;
+ }
+
+ chainValue = new ReferenceParam();
+ chainValue.setValueAsQueryToken(myContext, theParamName, qualifier, resourceId);
+ ((ReferenceParam) chainValue).setChain(remainingChain);
+ } else if (isMeta) {
+ IQueryParameterType type = myMatchUrlService.newInstanceType(chain);
+ type.setValueAsQueryToken(myContext, theParamName, qualifier, resourceId);
+ chainValue = type;
+ } else {
+ chainValue = toParameterType(param, qualifier, resourceId);
+ }
+
+ return chainValue;
+ }
+
private void addPredicateResourceId(List> theValues) {
for (List extends IQueryParameterType> nextValue : theValues) {
Set orPids = new HashSet<>();
@@ -795,24 +815,27 @@ public class SearchBuilder implements ISearchBuilder {
private void addPredicateToken(String theResourceName, String theParamName, List extends IQueryParameterType> theList) {
- Join join = createOrReuseJoin(JoinEnum.TOKEN, theParamName);
-
if (theList.get(0).getMissing() != null) {
+ Join join = createOrReuseJoin(JoinEnum.TOKEN, theParamName);
addPredicateParamMissing(theResourceName, theParamName, theList.get(0).getMissing(), join);
return;
}
List codePredicates = new ArrayList<>();
+ Join join = null;
for (IQueryParameterType nextOr : theList) {
if (nextOr instanceof TokenParam) {
TokenParam id = (TokenParam) nextOr;
if (id.isText()) {
addPredicateString(theResourceName, theParamName, theList);
- continue;
+ break;
}
}
+ if (join == null) {
+ join = createOrReuseJoin(JoinEnum.TOKEN, theParamName);
+ }
Predicate singleCode = createPredicateToken(nextOr, theResourceName, theParamName, myBuilder, join);
codePredicates.add(singleCode);
}
@@ -973,38 +996,34 @@ public class SearchBuilder implements ISearchBuilder {
@SuppressWarnings("unchecked")
private Join createOrReuseJoin(JoinEnum theType, String theSearchParameterName) {
- Join join = null;
-
- switch (theType) {
- case DATE:
- join = myResourceTableRoot.join("myParamsDate", JoinType.LEFT);
- break;
- case NUMBER:
- join = myResourceTableRoot.join("myParamsNumber", JoinType.LEFT);
- break;
- case QUANTITY:
- join = myResourceTableRoot.join("myParamsQuantity", JoinType.LEFT);
- break;
- case REFERENCE:
- join = myResourceTableRoot.join("myResourceLinks", JoinType.LEFT);
- break;
- case STRING:
- join = myResourceTableRoot.join("myParamsString", JoinType.LEFT);
- break;
- case URI:
- join = myResourceTableRoot.join("myParamsUri", JoinType.LEFT);
- break;
- case TOKEN:
- join = myResourceTableRoot.join("myParamsToken", JoinType.LEFT);
- break;
- }
-
JoinKey key = new JoinKey(theSearchParameterName, theType);
- if (!myIndexJoins.containsKey(key)) {
- myIndexJoins.put(key, join);
- }
-
- return (Join) join;
+ return (Join) myIndexJoins.computeIfAbsent(key, k -> {
+ Join join = null;
+ switch (theType) {
+ case DATE:
+ join = myResourceTableRoot.join("myParamsDate", JoinType.LEFT);
+ break;
+ case NUMBER:
+ join = myResourceTableRoot.join("myParamsNumber", JoinType.LEFT);
+ break;
+ case QUANTITY:
+ join = myResourceTableRoot.join("myParamsQuantity", JoinType.LEFT);
+ break;
+ case REFERENCE:
+ join = myResourceTableRoot.join("myResourceLinks", JoinType.LEFT);
+ break;
+ case STRING:
+ join = myResourceTableRoot.join("myParamsString", JoinType.LEFT);
+ break;
+ case URI:
+ join = myResourceTableRoot.join("myParamsUri", JoinType.LEFT);
+ break;
+ case TOKEN:
+ join = myResourceTableRoot.join("myParamsToken", JoinType.LEFT);
+ break;
+ }
+ return join;
+ });
}
private Predicate createPredicateDate(IQueryParameterType theParam, String theResourceName, String theParamName, CriteriaBuilder theBuilder, From, ResourceIndexedSearchParamDate> theFrom) {
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/TransactionProcessor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/TransactionProcessor.java
index 898895ede5a..ea8b95368d5 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/TransactionProcessor.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/TransactionProcessor.java
@@ -89,6 +89,52 @@ public class TransactionProcessor {
@Autowired
private DaoRegistry myDaoRegistry;
+ public BUNDLE transaction(RequestDetails theRequestDetails, BUNDLE theRequest) {
+ if (theRequestDetails != null) {
+ IServerInterceptor.ActionRequestDetails requestDetails = new IServerInterceptor.ActionRequestDetails(theRequestDetails, theRequest, "Bundle", null);
+ myDao.notifyInterceptors(RestOperationTypeEnum.TRANSACTION, requestDetails);
+ }
+
+ String actionName = "Transaction";
+ BUNDLE response = processTransactionAsSubRequest((ServletRequestDetails) theRequestDetails, theRequest, actionName);
+
+ return response;
+ }
+
+ public BUNDLE collection(final RequestDetails theRequestDetails, BUNDLE theRequest) {
+ String transactionType = myVersionAdapter.getBundleType(theRequest);
+
+ if (!org.hl7.fhir.r4.model.Bundle.BundleType.COLLECTION.toCode().equals(transactionType)) {
+ throw new InvalidRequestException("Can not process collection Bundle of type: " + transactionType);
+ }
+
+ ourLog.info("Beginning storing collection with {} resources", myVersionAdapter.getEntries(theRequest).size());
+ long start = System.currentTimeMillis();
+
+ TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
+ txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
+
+ BUNDLE resp = myVersionAdapter.createBundle(org.hl7.fhir.r4.model.Bundle.BundleType.BATCHRESPONSE.toCode());
+
+ List resources = new ArrayList<>();
+ for (final BUNDLEENTRY nextRequestEntry : myVersionAdapter.getEntries(theRequest)) {
+ IBaseResource resource = myVersionAdapter.getResource(nextRequestEntry);
+ resources.add(resource);
+ }
+
+ BUNDLE transactionBundle = myVersionAdapter.createBundle("transaction");
+ for (IBaseResource next : resources) {
+ BUNDLEENTRY entry = myVersionAdapter.addEntry(transactionBundle);
+ myVersionAdapter.setResource(entry, next);
+ myVersionAdapter.setRequestVerb(entry, "PUT");
+ myVersionAdapter.setRequestUrl(entry, next.getIdElement().toUnqualifiedVersionless().getValue());
+ }
+
+ transaction(theRequestDetails, transactionBundle);
+
+ return resp;
+ }
+
private void populateEntryWithOperationOutcome(BaseServerResponseException caughtEx, BUNDLEENTRY nextEntry) {
myVersionAdapter.populateEntryWithOperationOutcome(caughtEx, nextEntry);
}
@@ -160,16 +206,6 @@ public class TransactionProcessor {
myDao = theDao;
}
- public BUNDLE transaction(RequestDetails theRequestDetails, BUNDLE theRequest) {
- if (theRequestDetails != null) {
- IServerInterceptor.ActionRequestDetails requestDetails = new IServerInterceptor.ActionRequestDetails(theRequestDetails, theRequest, "Bundle", null);
- myDao.notifyInterceptors(RestOperationTypeEnum.TRANSACTION, requestDetails);
- }
-
- String actionName = "Transaction";
- return processTransactionAsSubRequest((ServletRequestDetails) theRequestDetails, theRequest, actionName);
- }
-
private BUNDLE processTransactionAsSubRequest(ServletRequestDetails theRequestDetails, BUNDLE theRequest, String theActionName) {
BaseHapiFhirDao.markRequestAsProcessingSubRequest(theRequestDetails);
try {
@@ -179,40 +215,6 @@ public class TransactionProcessor {
}
}
- public BUNDLE collection(final RequestDetails theRequestDetails, BUNDLE theRequest) {
- String transactionType = myVersionAdapter.getBundleType(theRequest);
-
- if (!org.hl7.fhir.r4.model.Bundle.BundleType.COLLECTION.toCode().equals(transactionType)) {
- throw new InvalidRequestException("Can not process collection Bundle of type: " + transactionType);
- }
-
- ourLog.info("Beginning storing collection with {} resources", myVersionAdapter.getEntries(theRequest).size());
- long start = System.currentTimeMillis();
-
- TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
- txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
-
- BUNDLE resp = myVersionAdapter.createBundle(org.hl7.fhir.r4.model.Bundle.BundleType.BATCHRESPONSE.toCode());
-
- List resources = new ArrayList<>();
- for (final BUNDLEENTRY nextRequestEntry : myVersionAdapter.getEntries(theRequest)) {
- IBaseResource resource = myVersionAdapter.getResource(nextRequestEntry);
- resources.add(resource);
- }
-
- BUNDLE transactionBundle = myVersionAdapter.createBundle("transaction");
- for (IBaseResource next : resources) {
- BUNDLEENTRY entry = myVersionAdapter.addEntry(transactionBundle);
- myVersionAdapter.setResource(entry, next);
- myVersionAdapter.setRequestVerb(entry, "PUT");
- myVersionAdapter.setRequestUrl(entry, next.getIdElement().toUnqualifiedVersionless().getValue());
- }
-
- transaction(theRequestDetails, transactionBundle);
-
- return resp;
- }
-
private BUNDLE batch(final RequestDetails theRequestDetails, BUNDLE theRequest) {
ourLog.info("Beginning batch with {} resources", myVersionAdapter.getEntries(theRequest).size());
long start = System.currentTimeMillis();
@@ -234,8 +236,7 @@ public class TransactionProcessor {
BUNDLE subRequestBundle = myVersionAdapter.createBundle(org.hl7.fhir.r4.model.Bundle.BundleType.TRANSACTION.toCode());
myVersionAdapter.addEntry(subRequestBundle, nextRequestEntry);
- BUNDLE subResponseBundle = processTransactionAsSubRequest((ServletRequestDetails) theRequestDetails, subRequestBundle, "Batch sub-request");
- return subResponseBundle;
+ return processTransactionAsSubRequest((ServletRequestDetails) theRequestDetails, subRequestBundle, "Batch sub-request");
};
try {
@@ -384,7 +385,7 @@ public class TransactionProcessor {
Integer originalOrder = originalRequestOrder.get(nextReqEntry);
BUNDLEENTRY nextRespEntry = myVersionAdapter.getEntries(response).get(originalOrder);
- ServletSubRequestDetails requestDetails = new ServletSubRequestDetails();
+ ServletSubRequestDetails requestDetails = new ServletSubRequestDetails(theRequestDetails);
requestDetails.setServletRequest(theRequestDetails.getServletRequest());
requestDetails.setRequestType(RequestTypeEnum.GET);
requestDetails.setServer(theRequestDetails.getServer());
@@ -472,10 +473,6 @@ public class TransactionProcessor {
return p.parseResource(theResource.getClass(), p.encodeResourceToString(theResource));
}
- public void setEntityManager(EntityManager theEntityManager) {
- myEntityManager = theEntityManager;
- }
-
private void validateDependencies() {
Validate.notNull(myEntityManager);
Validate.notNull(myContext);
@@ -526,7 +523,7 @@ public class TransactionProcessor {
}
}
- if (nextResourceId.hasIdPart() && nextResourceId.getIdPart().matches("[a-zA-Z]+\\:.*") && !isPlaceholder(nextResourceId)) {
+ if (nextResourceId.hasIdPart() && nextResourceId.getIdPart().matches("[a-zA-Z]+:.*") && !isPlaceholder(nextResourceId)) {
throw new InvalidRequestException("Invalid placeholder ID found: " + nextResourceId.getIdPart() + " - Must be of the form 'urn:uuid:[uuid]' or 'urn:oid:[oid]'");
}
@@ -631,7 +628,7 @@ public class TransactionProcessor {
version = ParameterUtil.parseETagValue(myVersionAdapter.getEntryRequestIfMatch(nextReqEntry));
}
res.setId(newIdType(parts.getResourceType(), parts.getResourceId(), version));
- outcome = resourceDao.update(res, null, false, theRequestDetails);
+ outcome = resourceDao.update(res, null, false, false, theRequestDetails);
} else {
res.setId((String) null);
String matchUrl;
@@ -641,7 +638,7 @@ public class TransactionProcessor {
matchUrl = parts.getResourceType();
}
matchUrl = performIdSubstitutionsInMatchUrl(theIdSubstitutions, matchUrl);
- outcome = resourceDao.update(res, matchUrl, false, theRequestDetails);
+ outcome = resourceDao.update(res, matchUrl, false, false, theRequestDetails);
if (Boolean.TRUE.equals(outcome.getCreated())) {
conditionalRequestUrls.put(matchUrl, res.getClass());
}
@@ -727,7 +724,7 @@ public class TransactionProcessor {
Date deletedTimestampOrNull = deletedInstantOrNull != null ? deletedInstantOrNull.getValue() : null;
if (updatedEntities.contains(nextOutcome.getEntity())) {
- myDao.updateInternal(theRequestDetails, nextResource, true, false, theRequestDetails, nextOutcome.getEntity(), nextResource.getIdElement(), nextOutcome.getPreviousResource());
+ myDao.updateInternal(theRequestDetails, nextResource, true, false, nextOutcome.getEntity(), nextResource.getIdElement(), nextOutcome.getPreviousResource());
} else if (!nonUpdatedEntities.contains(nextOutcome.getEntity())) {
myDao.updateEntity(theRequestDetails, nextResource, nextOutcome.getEntity(), deletedTimestampOrNull, true, false, theUpdateTime, false, true);
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/SearchParamWithInlineReferencesExtractor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/SearchParamWithInlineReferencesExtractor.java
index 0990ac67708..00eaf381447 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/SearchParamWithInlineReferencesExtractor.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/dao/index/SearchParamWithInlineReferencesExtractor.java
@@ -99,7 +99,7 @@ public class SearchParamWithInlineReferencesExtractor {
extractInlineReferences(theResource);
- myResourceLinkExtractor.extractResourceLinks(theParams, theEntity, theResource, theUpdateTime, myDaoResourceLinkResolver);
+ myResourceLinkExtractor.extractResourceLinks(theParams, theEntity, theResource, theUpdateTime, myDaoResourceLinkResolver, true);
/*
* If the existing resource already has links and those match links we still want, use them instead of removing them and re adding them
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/ServletSubRequestDetails.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/ServletSubRequestDetails.java
index 3ba5e226b4d..1fba4b84008 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/ServletSubRequestDetails.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/provider/ServletSubRequestDetails.java
@@ -29,11 +29,25 @@ import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
public class ServletSubRequestDetails extends ServletRequestDetails {
- private Map> myHeaders = new HashMap<>();
+ private Map> myHeaders = new HashMap<>();
+
+ /**
+ * Constructor
+ *
+ * @param theRequestDetails The parent request details
+ */
+ public ServletSubRequestDetails(ServletRequestDetails theRequestDetails) {
+ if (theRequestDetails != null) {
+ Map> headers = theRequestDetails.getHeaders();
+ for (Map.Entry> next : headers.entrySet()) {
+ myHeaders.put(next.getKey().toLowerCase(), next.getValue());
+ }
+ }
+ }
public void addHeader(String theName, String theValue) {
String lowerCase = theName.toLowerCase();
- ArrayList list = myHeaders.get(lowerCase);
+ List list = myHeaders.get(lowerCase);
if (list == null) {
list = new ArrayList<>();
myHeaders.put(lowerCase, list);
@@ -43,7 +57,7 @@ public class ServletSubRequestDetails extends ServletRequestDetails {
@Override
public String getHeader(String theName) {
- ArrayList list = myHeaders.get(theName.toLowerCase());
+ List list = myHeaders.get(theName.toLowerCase());
if (list == null || list.isEmpty()) {
return null;
}
@@ -52,7 +66,7 @@ public class ServletSubRequestDetails extends ServletRequestDetails {
@Override
public List getHeaders(String theName) {
- ArrayList list = myHeaders.get(theName.toLowerCase());
+ List list = myHeaders.get(theName.toLowerCase());
if (list == null || list.isEmpty()) {
return null;
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/reindex/ResourceReindexingSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/reindex/ResourceReindexingSvcImpl.java
index 2ab5fccfcfc..1ba5db9825d 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/reindex/ResourceReindexingSvcImpl.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/reindex/ResourceReindexingSvcImpl.java
@@ -391,7 +391,6 @@ public class ResourceReindexingSvcImpl implements IResourceReindexingSvc {
});
}
- @SuppressWarnings("JpaQlInspection")
private void markResourceAsIndexingFailed(final long theId) {
TransactionTemplate txTemplate = new TransactionTemplate(myTxManager);
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW);
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/warm/CacheWarmingSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/warm/CacheWarmingSvcImpl.java
index ef8a738891e..d2970ec6af3 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/warm/CacheWarmingSvcImpl.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/search/warm/CacheWarmingSvcImpl.java
@@ -26,9 +26,9 @@ import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.DaoRegistry;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
-import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
-import ca.uhn.fhir.parser.DataFormatException;
+import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
+import ca.uhn.fhir.util.UrlUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
@@ -77,7 +77,7 @@ public class CacheWarmingSvcImpl implements ICacheWarmingSvc {
private void refreshNow(WarmCacheEntry theCacheEntry) {
String nextUrl = theCacheEntry.getUrl();
- RuntimeResourceDefinition resourceDef = parseUrlResourceType(myCtx, nextUrl);
+ RuntimeResourceDefinition resourceDef = UrlUtil.parseUrlResourceType(myCtx, nextUrl);
IFhirResourceDao> callingDao = myDaoRegistry.getResourceDao(resourceDef.getName());
String queryPart = parseWarmUrlParamPart(nextUrl);
SearchParameterMap responseCriteriaUrl = myMatchUrlService.translateMatchUrl(queryPart, resourceDef);
@@ -93,20 +93,6 @@ public class CacheWarmingSvcImpl implements ICacheWarmingSvc {
return theNextUrl.substring(paramIndex);
}
- /**
- * TODO: this method probably belongs in a utility class, not here
- *
- * @throws DataFormatException If the resource type is not known
- */
- public static RuntimeResourceDefinition parseUrlResourceType(FhirContext theCtx, String theUrl) throws DataFormatException {
- int paramIndex = theUrl.indexOf('?');
- String resourceName = theUrl.substring(0, paramIndex);
- if (resourceName.contains("/")) {
- resourceName = resourceName.substring(resourceName.lastIndexOf('/') + 1);
- }
- return theCtx.getResourceDefinition(resourceName);
- }
-
@PostConstruct
public void start() {
initCacheMap();
@@ -120,7 +106,7 @@ public class CacheWarmingSvcImpl implements ICacheWarmingSvc {
// Validate
parseWarmUrlParamPart(next.getUrl());
- parseUrlResourceType(myCtx, next.getUrl());
+ UrlUtil.parseUrlResourceType(myCtx, next.getUrl());
myCacheEntryToNextRefresh.put(next, 0L);
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/IResourceModifiedConsumer.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/IResourceModifiedConsumer.java
new file mode 100644
index 00000000000..20c31732dbd
--- /dev/null
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/IResourceModifiedConsumer.java
@@ -0,0 +1,27 @@
+package ca.uhn.fhir.jpa.subscription;
+
+/*-
+ * #%L
+ * HAPI FHIR JPA Server
+ * %%
+ * Copyright (C) 2014 - 2019 University Health Network
+ * %%
+ * 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.subscription.module.ResourceModifiedMessage;
+
+public interface IResourceModifiedConsumer {
+ void submitResourceModified(ResourceModifiedMessage theMsg);
+}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionActivatingInterceptor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionActivatingInterceptor.java
index 19b6e3ba1c1..a86607801da 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionActivatingInterceptor.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionActivatingInterceptor.java
@@ -26,17 +26,20 @@ import ca.uhn.fhir.jpa.config.BaseConfig;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.DaoRegistry;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
-import ca.uhn.fhir.jpa.search.warm.CacheWarmingSvcImpl;
+import ca.uhn.fhir.jpa.model.interceptor.api.Hook;
+import ca.uhn.fhir.jpa.model.interceptor.api.Interceptor;
+import ca.uhn.fhir.jpa.model.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
-import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionCanonicalizer;
import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionRegistry;
+import ca.uhn.fhir.jpa.subscription.module.matcher.SubscriptionMatchingStrategy;
+import ca.uhn.fhir.jpa.subscription.module.matcher.SubscriptionStrategyEvaluator;
import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
-import ca.uhn.fhir.rest.api.server.RequestDetails;
+import ca.uhn.fhir.parser.DataFormatException;
+import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
-import ca.uhn.fhir.rest.server.interceptor.ServerOperationInterceptorAdapter;
import ca.uhn.fhir.util.SubscriptionUtil;
import com.google.common.annotations.VisibleForTesting;
import org.hl7.fhir.instance.model.Subscription;
@@ -68,7 +71,8 @@ import java.util.concurrent.TimeUnit;
*/
@Service
@Lazy
-public class SubscriptionActivatingInterceptor extends ServerOperationInterceptorAdapter {
+@Interceptor(manualRegistration = true)
+public class SubscriptionActivatingInterceptor {
private Logger ourLog = LoggerFactory.getLogger(SubscriptionActivatingInterceptor.class);
private static boolean ourWaitForSubscriptionActivationSynchronouslyForUnitTest;
@@ -92,6 +96,8 @@ public class SubscriptionActivatingInterceptor extends ServerOperationIntercepto
private MatchUrlService myMatchUrlService;
@Autowired
private DaoConfig myDaoConfig;
+ @Autowired
+ private SubscriptionStrategyEvaluator mySubscriptionStrategyEvaluator;
public boolean activateOrRegisterSubscriptionIfRequired(final IBaseResource theSubscription) {
// Grab the value for "Subscription.channel.type" so we can see if this
@@ -156,10 +162,10 @@ public class SubscriptionActivatingInterceptor extends ServerOperationIntercepto
}
}
-
private boolean activateSubscription(String theActiveStatus, final IBaseResource theSubscription, String theRequestedStatus) {
IFhirResourceDao subscriptionDao = myDaoRegistry.getSubscriptionDao();
IBaseResource subscription = subscriptionDao.read(theSubscription.getIdElement());
+ subscription.setId(subscription.getIdElement().toVersionless());
ourLog.info("Activating subscription {} from status {} to {}", subscription.getIdElement().toUnqualified().getValue(), theRequestedStatus, theActiveStatus);
try {
@@ -180,56 +186,71 @@ public class SubscriptionActivatingInterceptor extends ServerOperationIntercepto
submitResourceModified(theNewResource, ResourceModifiedMessage.OperationTypeEnum.UPDATE);
}
- @Override
- public void resourceCreated(RequestDetails theRequest, IBaseResource theResource) {
- submitResourceModified(theResource, ResourceModifiedMessage.OperationTypeEnum.CREATE);
+ @Hook(Pointcut.OP_PRESTORAGE_RESOURCE_CREATED)
+ public void addStrategyTagCreated(IBaseResource theResource) {
+ if (isSubscription(theResource)) {
+ validateCriteriaAndAddStrategy(theResource);
+ }
}
- @Override
- public void resourceDeleted(RequestDetails theRequest, IBaseResource theResource) {
- submitResourceModified(theResource, ResourceModifiedMessage.OperationTypeEnum.DELETE);
+ @Hook(Pointcut.OP_PRESTORAGE_RESOURCE_UPDATED)
+ public void addStrategyTagUpdated(IBaseResource theOldResource, IBaseResource theNewResource) {
+ if (isSubscription(theNewResource)) {
+ validateCriteriaAndAddStrategy(theNewResource);
+ }
}
- @Override
- public void resourceUpdated(RequestDetails theRequest, IBaseResource theOldResource, IBaseResource theNewResource) {
+ // TODO KHS add third type of strategy DISABLED if that subscription type is disabled on this server
+ public void validateCriteriaAndAddStrategy(final IBaseResource theResource) {
+ String criteria = mySubscriptionCanonicalizer.getCriteria(theResource);
+ try {
+ SubscriptionMatchingStrategy strategy = mySubscriptionStrategyEvaluator.determineStrategy(criteria);
+ mySubscriptionCanonicalizer.setMatchingStrategyTag(myFhirContext, theResource, strategy);
+ } catch (InvalidRequestException | DataFormatException e) {
+ throw new UnprocessableEntityException("Invalid subscription criteria submitted: " + criteria + " " + e.getMessage());
+ }
+ }
+
+ @Hook(Pointcut.OP_PRECOMMIT_RESOURCE_UPDATED)
+ public void resourceUpdated(IBaseResource theOldResource, IBaseResource theNewResource) {
submitResourceModified(theNewResource, ResourceModifiedMessage.OperationTypeEnum.UPDATE);
}
+ @Hook(Pointcut.OP_PRECOMMIT_RESOURCE_CREATED)
+ public void resourceCreated(IBaseResource theResource) {
+ submitResourceModified(theResource, ResourceModifiedMessage.OperationTypeEnum.CREATE);
+ }
+
+ @Hook(Pointcut.OP_PRECOMMIT_RESOURCE_DELETED)
+ public void resourceDeleted(IBaseResource theResource) {
+ submitResourceModified(theResource, ResourceModifiedMessage.OperationTypeEnum.DELETE);
+ }
+
private void submitResourceModified(IBaseResource theNewResource, ResourceModifiedMessage.OperationTypeEnum theOperationType) {
- submitResourceModified(new ResourceModifiedMessage(myFhirContext, theNewResource, theOperationType));
+ if (isSubscription(theNewResource)) {
+ submitResourceModified(new ResourceModifiedMessage(myFhirContext, theNewResource, theOperationType));
+ }
+ }
+
+ private boolean isSubscription(IBaseResource theNewResource) {
+ RuntimeResourceDefinition resourceDefinition = myFhirContext.getResourceDefinition(theNewResource);
+ return ResourceTypeEnum.SUBSCRIPTION.getCode().equals(resourceDefinition.getName());
}
private void submitResourceModified(final ResourceModifiedMessage theMsg) {
- IIdType id = theMsg.getId(myFhirContext);
- if (!id.getResourceType().equals(ResourceTypeEnum.SUBSCRIPTION.getCode())) {
- return;
- }
switch (theMsg.getOperationType()) {
case DELETE:
- mySubscriptionRegistry.unregisterSubscription(id);
+ mySubscriptionRegistry.unregisterSubscription(theMsg.getId(myFhirContext));
break;
case CREATE:
case UPDATE:
- final IBaseResource subscription = theMsg.getNewPayload(myFhirContext);
- validateCriteria(subscription);
- activateAndRegisterSubscriptionIfRequiredInTransaction(subscription);
+ activateAndRegisterSubscriptionIfRequiredInTransaction(theMsg.getNewPayload(myFhirContext));
break;
default:
break;
}
}
- public void validateCriteria(final IBaseResource theResource) {
- CanonicalSubscription subscription = mySubscriptionCanonicalizer.canonicalize(theResource);
- String criteria = subscription.getCriteriaString();
- try {
- RuntimeResourceDefinition resourceDef = CacheWarmingSvcImpl.parseUrlResourceType(myFhirContext, criteria);
- myMatchUrlService.translateMatchUrl(criteria, resourceDef);
- } catch (InvalidRequestException e) {
- throw new UnprocessableEntityException("Invalid subscription criteria submitted: " + criteria + " " + e.getMessage());
- }
- }
-
private void activateAndRegisterSubscriptionIfRequiredInTransaction(IBaseResource theSubscription) {
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
txTemplate.execute(new TransactionCallbackWithoutResult() {
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionInterceptorLoader.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionInterceptorLoader.java
index d3b68502b9a..5af1faf0591 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionInterceptorLoader.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionInterceptorLoader.java
@@ -21,6 +21,7 @@ package ca.uhn.fhir.jpa.subscription;
*/
import ca.uhn.fhir.jpa.dao.DaoConfig;
+import ca.uhn.fhir.jpa.model.interceptor.api.IInterceptorRegistry;
import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionLoader;
import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionRegistry;
import com.google.common.annotations.VisibleForTesting;
@@ -37,52 +38,44 @@ import java.util.Set;
public class SubscriptionInterceptorLoader {
private static final Logger ourLog = LoggerFactory.getLogger(SubscriptionInterceptorLoader.class);
+ @Autowired
private SubscriptionMatcherInterceptor mySubscriptionMatcherInterceptor;
+ @Autowired
private SubscriptionActivatingInterceptor mySubscriptionActivatingInterceptor;
-
@Autowired
DaoConfig myDaoConfig;
@Autowired
+ private SubscriptionRegistry mySubscriptionRegistry;
+ @Autowired
private ApplicationContext myAppicationContext;
@Autowired
- private SubscriptionRegistry mySubscriptionRegistry;
+ private IInterceptorRegistry myInterceptorRegistry;
public void registerInterceptors() {
Set supportedSubscriptionTypes = myDaoConfig.getSupportedSubscriptionTypes();
if (!supportedSubscriptionTypes.isEmpty()) {
loadSubscriptions();
-
ourLog.info("Registering subscription activating interceptor");
- myDaoConfig.registerInterceptor(mySubscriptionActivatingInterceptor);
+ myInterceptorRegistry.registerInterceptor(mySubscriptionActivatingInterceptor);
}
if (myDaoConfig.isSubscriptionMatchingEnabled()) {
+ mySubscriptionMatcherInterceptor.start();
ourLog.info("Registering subscription matcher interceptor");
-
- if (mySubscriptionMatcherInterceptor == null) {
- mySubscriptionMatcherInterceptor = myAppicationContext.getBean(SubscriptionMatcherInterceptor.class);
- }
-
- myDaoConfig.registerInterceptor(mySubscriptionMatcherInterceptor);
-
+ myInterceptorRegistry.registerInterceptor(mySubscriptionMatcherInterceptor);
}
}
private void loadSubscriptions() {
ourLog.info("Loading subscriptions into the SubscriptionRegistry...");
- // Load subscriptions into the SubscriptionRegistry
+ // Activate scheduled subscription loads into the SubscriptionRegistry
myAppicationContext.getBean(SubscriptionLoader.class);
ourLog.info("...{} subscriptions loaded", mySubscriptionRegistry.size());
-
- // Once subscriptions have been loaded, now
- if (mySubscriptionActivatingInterceptor == null) {
- mySubscriptionActivatingInterceptor = myAppicationContext.getBean(SubscriptionActivatingInterceptor.class);
- }
}
@VisibleForTesting
- public void unregisterInterceptorsForUnitTest() {
- myDaoConfig.unregisterInterceptor(mySubscriptionActivatingInterceptor);
- myDaoConfig.unregisterInterceptor(mySubscriptionMatcherInterceptor);
+ void unregisterInterceptorsForUnitTest() {
+ myInterceptorRegistry.unregisterInterceptor(mySubscriptionActivatingInterceptor);
+ myInterceptorRegistry.unregisterInterceptor(mySubscriptionMatcherInterceptor);
}
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionMatcherInterceptor.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionMatcherInterceptor.java
index 988814d7349..94d4fc65600 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionMatcherInterceptor.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionMatcherInterceptor.java
@@ -1,14 +1,16 @@
package ca.uhn.fhir.jpa.subscription;
import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.jpa.model.interceptor.api.Hook;
+import ca.uhn.fhir.jpa.model.interceptor.api.Interceptor;
+import ca.uhn.fhir.jpa.model.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.subscription.module.LinkedBlockingQueueSubscribableChannel;
import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionChannelFactory;
import ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceModifiedJsonMessage;
import ca.uhn.fhir.jpa.subscription.module.subscriber.SubscriptionMatchingSubscriber;
-import ca.uhn.fhir.rest.api.server.RequestDetails;
-import ca.uhn.fhir.rest.server.interceptor.ServerOperationInterceptorAdapter;
import com.google.common.annotations.VisibleForTesting;
+import org.apache.commons.lang3.Validate;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -17,7 +19,6 @@ import org.springframework.context.annotation.Lazy;
import org.springframework.messaging.SubscribableChannel;
import org.springframework.stereotype.Component;
-import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
/*-
@@ -42,9 +43,11 @@ import javax.annotation.PreDestroy;
@Component
@Lazy
-public class SubscriptionMatcherInterceptor extends ServerOperationInterceptorAdapter {
+@Interceptor(manualRegistration = true)
+public class SubscriptionMatcherInterceptor implements IResourceModifiedConsumer {
private Logger ourLog = LoggerFactory.getLogger(SubscriptionMatcherInterceptor.class);
+ private static final String SUBSCRIPTION_MATCHING_CHANNEL_NAME = "subscription-matching";
static final String SUBSCRIPTION_STATUS = "Subscription.status";
static final String SUBSCRIPTION_TYPE = "Subscription.channel.type";
private SubscribableChannel myProcessingChannel;
@@ -63,32 +66,36 @@ public class SubscriptionMatcherInterceptor extends ServerOperationInterceptorAd
super();
}
- @PostConstruct
public void start() {
if (myProcessingChannel == null) {
- myProcessingChannel = mySubscriptionChannelFactory.newMatchingChannel("subscription-matching");
+ myProcessingChannel = mySubscriptionChannelFactory.newMatchingChannel(SUBSCRIPTION_MATCHING_CHANNEL_NAME);
}
myProcessingChannel.subscribe(mySubscriptionMatchingSubscriber);
+ ourLog.info("Subscription Matching Subscriber subscribed to Matching Channel {} with name {}", myProcessingChannel.getClass().getName(), SUBSCRIPTION_MATCHING_CHANNEL_NAME);
+
}
@SuppressWarnings("unused")
@PreDestroy
public void preDestroy() {
- myProcessingChannel.unsubscribe(mySubscriptionMatchingSubscriber);
+
+ if (myProcessingChannel != null) {
+ myProcessingChannel.unsubscribe(mySubscriptionMatchingSubscriber);
+ }
}
- @Override
- public void resourceCreated(RequestDetails theRequest, IBaseResource theResource) {
+ @Hook(Pointcut.OP_PRECOMMIT_RESOURCE_CREATED)
+ public void resourceCreated(IBaseResource theResource) {
submitResourceModified(theResource, ResourceModifiedMessage.OperationTypeEnum.CREATE);
}
- @Override
- public void resourceDeleted(RequestDetails theRequest, IBaseResource theResource) {
+ @Hook(Pointcut.OP_PRECOMMIT_RESOURCE_DELETED)
+ public void resourceDeleted(IBaseResource theResource) {
submitResourceModified(theResource, ResourceModifiedMessage.OperationTypeEnum.DELETE);
}
- @Override
- public void resourceUpdated(RequestDetails theRequest, IBaseResource theOldResource, IBaseResource theNewResource) {
+ @Hook(Pointcut.OP_PRECOMMIT_RESOURCE_UPDATED)
+ public void resourceUpdated(IBaseResource theOldResource, IBaseResource theNewResource) {
submitResourceModified(theNewResource, ResourceModifiedMessage.OperationTypeEnum.UPDATE);
}
@@ -97,8 +104,9 @@ public class SubscriptionMatcherInterceptor extends ServerOperationInterceptorAd
submitResourceModified(msg);
}
- protected void sendToProcessingChannel(final ResourceModifiedMessage theMessage) {
+ private void sendToProcessingChannel(final ResourceModifiedMessage theMessage) {
ourLog.trace("Sending resource modified message to processing channel");
+ Validate.notNull(myProcessingChannel, "A SubscriptionMatcherInterceptor has been registered without calling start() on it.");
myProcessingChannel.send(new ResourceModifiedJsonMessage(theMessage));
}
@@ -109,12 +117,13 @@ public class SubscriptionMatcherInterceptor extends ServerOperationInterceptorAd
/**
* This is an internal API - Use with caution!
*/
+ @Override
public void submitResourceModified(final ResourceModifiedMessage theMsg) {
sendToProcessingChannel(theMsg);
}
@VisibleForTesting
- public LinkedBlockingQueueSubscribableChannel getProcessingChannelForUnitTest() {
+ LinkedBlockingQueueSubscribableChannel getProcessingChannelForUnitTest() {
return (LinkedBlockingQueueSubscribableChannel) myProcessingChannel;
}
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionTriggeringSvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionTriggeringSvcImpl.java
index bda9ec74f4b..4eed304ff7c 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionTriggeringSvcImpl.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/SubscriptionTriggeringSvcImpl.java
@@ -27,7 +27,6 @@ import ca.uhn.fhir.jpa.dao.DaoRegistry;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
import ca.uhn.fhir.jpa.provider.SubscriptionTriggeringProvider;
import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc;
-import ca.uhn.fhir.jpa.search.warm.CacheWarmingSvcImpl;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
@@ -42,6 +41,7 @@ import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.util.ParametersUtil;
import ca.uhn.fhir.util.StopWatch;
+import ca.uhn.fhir.util.UrlUtil;
import ca.uhn.fhir.util.ValidateUtil;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.Validate;
@@ -55,15 +55,15 @@ import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.instance.model.api.IPrimitiveType;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.context.ApplicationContext;
-import org.springframework.context.ApplicationContextAware;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;
import javax.annotation.PostConstruct;
-import java.util.*;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.UUID;
import java.util.concurrent.*;
import java.util.stream.Collectors;
@@ -72,10 +72,10 @@ import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
@Service
-public class SubscriptionTriggeringSvcImpl implements ISubscriptionTriggeringSvc, ApplicationContextAware {
+public class SubscriptionTriggeringSvcImpl implements ISubscriptionTriggeringSvc {
private static final Logger ourLog = LoggerFactory.getLogger(SubscriptionTriggeringProvider.class);
- public static final int DEFAULT_MAX_SUBMIT = 10000;
+ private static final int DEFAULT_MAX_SUBMIT = 10000;
@Autowired
private FhirContext myFhirContext;
@@ -88,11 +88,10 @@ public class SubscriptionTriggeringSvcImpl implements ISubscriptionTriggeringSvc
@Autowired
private MatchUrlService myMatchUrlService;
@Autowired
- private SubscriptionMatcherInterceptor mySubscriptionMatcherInterceptor;
+ private IResourceModifiedConsumer myResourceModifiedConsumer;
private final List myActiveJobs = new ArrayList<>();
private int myMaxSubmitPerPass = DEFAULT_MAX_SUBMIT;
- private ApplicationContext myAppCtx;
private ExecutorService myExecutorService;
@Override
@@ -105,7 +104,7 @@ public class SubscriptionTriggeringSvcImpl implements ISubscriptionTriggeringSvc
if (theSubscriptionId != null) {
IFhirResourceDao> subscriptionDao = myDaoRegistry.getSubscriptionDao();
IIdType subscriptionId = theSubscriptionId;
- if (subscriptionId.hasResourceType() == false) {
+ if (!subscriptionId.hasResourceType()) {
subscriptionId = subscriptionId.withResourceType(ResourceTypeEnum.SUBSCRIPTION.getCode());
}
subscriptionDao.read(subscriptionId);
@@ -128,7 +127,7 @@ public class SubscriptionTriggeringSvcImpl implements ISubscriptionTriggeringSvc
// Search URLs must be valid
for (StringParam next : searchUrls) {
- if (next.getValue().contains("?") == false) {
+ if (!next.getValue().contains("?")) {
throw new InvalidRequestException("Search URL is not valid (must be in the form \"[resource type]?[optional params]\")");
}
}
@@ -163,7 +162,7 @@ public class SubscriptionTriggeringSvcImpl implements ISubscriptionTriggeringSvc
return;
}
- String activeJobIds = myActiveJobs.stream().map(t -> t.getJobId()).collect(Collectors.joining(", "));
+ String activeJobIds = myActiveJobs.stream().map(SubscriptionTriggeringJobDetails::getJobId).collect(Collectors.joining(", "));
ourLog.info("Starting pass: currently have {} active job IDs: {}", myActiveJobs.size(), activeJobIds);
SubscriptionTriggeringJobDetails activeJob = myActiveJobs.get(0);
@@ -210,7 +209,7 @@ public class SubscriptionTriggeringSvcImpl implements ISubscriptionTriggeringSvc
// If we don't have an active search started, and one needs to be.. start it
if (isBlank(theJobDetails.getCurrentSearchUuid()) && theJobDetails.getRemainingSearchUrls().size() > 0 && totalSubmitted < myMaxSubmitPerPass) {
String nextSearchUrl = theJobDetails.getRemainingSearchUrls().remove(0);
- RuntimeResourceDefinition resourceDef = CacheWarmingSvcImpl.parseUrlResourceType(myFhirContext, nextSearchUrl);
+ RuntimeResourceDefinition resourceDef = UrlUtil.parseUrlResourceType(myFhirContext, nextSearchUrl);
String queryPart = nextSearchUrl.substring(nextSearchUrl.indexOf('?'));
String resourceType = resourceDef.getName();
@@ -290,7 +289,7 @@ public class SubscriptionTriggeringSvcImpl implements ISubscriptionTriggeringSvc
private Future submitResource(String theSubscriptionId, String theResourceIdToTrigger) {
org.hl7.fhir.r4.model.IdType resourceId = new org.hl7.fhir.r4.model.IdType(theResourceIdToTrigger);
- IFhirResourceDao extends IBaseResource> dao = myDaoRegistry.getResourceDao(resourceId.getResourceType());
+ IFhirResourceDao dao = myDaoRegistry.getResourceDao(resourceId.getResourceType());
IBaseResource resourceToTrigger = dao.read(resourceId);
return submitResource(theSubscriptionId, resourceToTrigger);
@@ -306,7 +305,7 @@ public class SubscriptionTriggeringSvcImpl implements ISubscriptionTriggeringSvc
return myExecutorService.submit(() -> {
for (int i = 0; ; i++) {
try {
- mySubscriptionMatcherInterceptor.submitResourceModified(msg);
+ myResourceModifiedConsumer.submitResourceModified(msg);
break;
} catch (Exception e) {
if (i >= 3) {
@@ -329,11 +328,6 @@ public class SubscriptionTriggeringSvcImpl implements ISubscriptionTriggeringSvc
}
}
- @Override
- public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
- myAppCtx = applicationContext;
- }
-
/**
* Sets the maximum number of resources that will be submitted in a single pass
*/
@@ -346,7 +340,6 @@ public class SubscriptionTriggeringSvcImpl implements ISubscriptionTriggeringSvc
myMaxSubmitPerPass = maxSubmitPerPass;
}
- @SuppressWarnings("unchecked")
@PostConstruct
public void start() {
LinkedBlockingQueue executorQueue = new LinkedBlockingQueue<>(1000);
@@ -393,67 +386,67 @@ public class SubscriptionTriggeringSvcImpl implements ISubscriptionTriggeringSvc
private String myCurrentSearchResourceType;
private int myCurrentSearchLastUploadedIndex;
- public Integer getCurrentSearchCount() {
+ Integer getCurrentSearchCount() {
return myCurrentSearchCount;
}
- public void setCurrentSearchCount(Integer theCurrentSearchCount) {
+ void setCurrentSearchCount(Integer theCurrentSearchCount) {
myCurrentSearchCount = theCurrentSearchCount;
}
- public String getCurrentSearchResourceType() {
+ String getCurrentSearchResourceType() {
return myCurrentSearchResourceType;
}
- public void setCurrentSearchResourceType(String theCurrentSearchResourceType) {
+ void setCurrentSearchResourceType(String theCurrentSearchResourceType) {
myCurrentSearchResourceType = theCurrentSearchResourceType;
}
- public String getJobId() {
+ String getJobId() {
return myJobId;
}
- public void setJobId(String theJobId) {
+ void setJobId(String theJobId) {
myJobId = theJobId;
}
- public String getSubscriptionId() {
+ String getSubscriptionId() {
return mySubscriptionId;
}
- public void setSubscriptionId(String theSubscriptionId) {
+ void setSubscriptionId(String theSubscriptionId) {
mySubscriptionId = theSubscriptionId;
}
- public List getRemainingResourceIds() {
+ List getRemainingResourceIds() {
return myRemainingResourceIds;
}
- public void setRemainingResourceIds(List theRemainingResourceIds) {
+ void setRemainingResourceIds(List theRemainingResourceIds) {
myRemainingResourceIds = theRemainingResourceIds;
}
- public List getRemainingSearchUrls() {
+ List getRemainingSearchUrls() {
return myRemainingSearchUrls;
}
- public void setRemainingSearchUrls(List theRemainingSearchUrls) {
+ void setRemainingSearchUrls(List theRemainingSearchUrls) {
myRemainingSearchUrls = theRemainingSearchUrls;
}
- public String getCurrentSearchUuid() {
+ String getCurrentSearchUuid() {
return myCurrentSearchUuid;
}
- public void setCurrentSearchUuid(String theCurrentSearchUuid) {
+ void setCurrentSearchUuid(String theCurrentSearchUuid) {
myCurrentSearchUuid = theCurrentSearchUuid;
}
- public int getCurrentSearchLastUploadedIndex() {
+ int getCurrentSearchLastUploadedIndex() {
return myCurrentSearchLastUploadedIndex;
}
- public void setCurrentSearchLastUploadedIndex(int theCurrentSearchLastUploadedIndex) {
+ void setCurrentSearchLastUploadedIndex(int theCurrentSearchLastUploadedIndex) {
myCurrentSearchLastUploadedIndex = theCurrentSearchLastUploadedIndex;
}
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbcache/DaoSubscriptionProvider.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbcache/DaoSubscriptionProvider.java
index 97a5e46dc5a..18725dbe386 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbcache/DaoSubscriptionProvider.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbcache/DaoSubscriptionProvider.java
@@ -42,10 +42,7 @@ public class DaoSubscriptionProvider implements ISubscriptionProvider {
@Override
public IBundleProvider search(SearchParameterMap theMap) {
IFhirResourceDao subscriptionDao = myDaoRegistry.getSubscriptionDao();
- RequestDetails req = new ServletSubRequestDetails();
- req.setSubRequest(true);
-
- return subscriptionDao.search(theMap, req);
+ return subscriptionDao.search(theMap);
}
@Override
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbmatcher/CompositeInMemoryDaoSubscriptionMatcher.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbmatcher/CompositeInMemoryDaoSubscriptionMatcher.java
index eec2462fd2c..4e084ba642b 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbmatcher/CompositeInMemoryDaoSubscriptionMatcher.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbmatcher/CompositeInMemoryDaoSubscriptionMatcher.java
@@ -21,10 +21,11 @@ package ca.uhn.fhir.jpa.subscription.dbmatcher;
*/
import ca.uhn.fhir.jpa.dao.DaoConfig;
+import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
import ca.uhn.fhir.jpa.subscription.module.matcher.ISubscriptionMatcher;
-import ca.uhn.fhir.jpa.subscription.module.matcher.SubscriptionMatchResult;
import ca.uhn.fhir.jpa.subscription.module.matcher.InMemorySubscriptionMatcher;
+import ca.uhn.fhir.jpa.subscription.module.matcher.SubscriptionMatchResult;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
@@ -43,16 +44,19 @@ public class CompositeInMemoryDaoSubscriptionMatcher implements ISubscriptionMat
}
@Override
- public SubscriptionMatchResult match(String criteria, ResourceModifiedMessage msg) {
+ public SubscriptionMatchResult match(CanonicalSubscription theSubscription, ResourceModifiedMessage theMsg) {
SubscriptionMatchResult result;
if (myDaoConfig.isEnableInMemorySubscriptionMatching()) {
- result = myInMemorySubscriptionMatcher.match(criteria, msg);
- if (!result.supported()) {
- ourLog.info("Criteria {} not supported by InMemoryMatcher: {}. Reverting to DatabaseMatcher", criteria, result.getUnsupportedReason());
- result = myDaoSubscriptionMatcher.match(criteria, msg);
+ result = myInMemorySubscriptionMatcher.match(theSubscription, theMsg);
+ if (result.supported()) {
+ // TODO KHS test
+ result.setInMemory(true);
+ } else {
+ ourLog.info("Criteria {} for Subscription {} not supported by InMemoryMatcher: {}. Reverting to DatabaseMatcher", theSubscription.getCriteriaString(), theSubscription.getIdElementString(), result.getUnsupportedReason());
+ result = myDaoSubscriptionMatcher.match(theSubscription, theMsg);
}
} else {
- result = myDaoSubscriptionMatcher.match(criteria, msg);
+ result = myDaoSubscriptionMatcher.match(theSubscription, theMsg);
}
return result;
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbmatcher/DaoSubscriptionMatcher.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbmatcher/DaoSubscriptionMatcher.java
index eca40b9b2b7..8b5281bffb5 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbmatcher/DaoSubscriptionMatcher.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/subscription/dbmatcher/DaoSubscriptionMatcher.java
@@ -24,14 +24,13 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.context.RuntimeResourceDefinition;
import ca.uhn.fhir.jpa.dao.DaoRegistry;
import ca.uhn.fhir.jpa.dao.IFhirResourceDao;
-import ca.uhn.fhir.jpa.provider.ServletSubRequestDetails;
import ca.uhn.fhir.jpa.searchparam.MatchUrlService;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
+import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
import ca.uhn.fhir.jpa.subscription.module.matcher.ISubscriptionMatcher;
import ca.uhn.fhir.jpa.subscription.module.matcher.SubscriptionMatchResult;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
-import ca.uhn.fhir.rest.api.server.RequestDetails;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.slf4j.Logger;
@@ -49,10 +48,11 @@ public class DaoSubscriptionMatcher implements ISubscriptionMatcher {
MatchUrlService myMatchUrlService;
@Override
- public SubscriptionMatchResult match(String criteria, ResourceModifiedMessage msg) {
- IIdType id = msg.getId(myCtx);
+ public SubscriptionMatchResult match(CanonicalSubscription theSubscription, ResourceModifiedMessage theMsg) {
+ IIdType id = theMsg.getId(myCtx);
String resourceType = id.getResourceType();
String resourceId = id.getIdPart();
+ String criteria = theSubscription.getCriteriaString();
// run the subscriptions query and look for matches, add the id as part of the criteria to avoid getting matches of previous resources rather than the recent resource
criteria += "&_id=" + resourceType + "/" + resourceId;
@@ -61,23 +61,20 @@ public class DaoSubscriptionMatcher implements ISubscriptionMatcher {
ourLog.debug("Subscription check found {} results for query: {}", results.size(), criteria);
- return new SubscriptionMatchResult(results.size() > 0, "DATABASE");
+ return SubscriptionMatchResult.fromBoolean(results.size() > 0);
}
/**
* Search based on a query criteria
*/
- protected IBundleProvider performSearch(String theCriteria) {
+ private IBundleProvider performSearch(String theCriteria) {
IFhirResourceDao> subscriptionDao = myDaoRegistry.getSubscriptionDao();
RuntimeResourceDefinition responseResourceDef = subscriptionDao.validateCriteriaAndReturnResourceDefinition(theCriteria);
SearchParameterMap responseCriteriaUrl = myMatchUrlService.translateMatchUrl(theCriteria, responseResourceDef);
- RequestDetails req = new ServletSubRequestDetails();
- req.setSubRequest(true);
-
IFhirResourceDao extends IBaseResource> responseDao = myDaoRegistry.getResourceDao(responseResourceDef.getImplementingClass());
responseCriteriaUrl.setLoadSynchronousUpTo(1);
- return responseDao.search(responseCriteriaUrl, req);
+ return responseDao.search(responseCriteriaUrl);
}
}
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java
index 0c1938637e8..a606b38c2a4 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/term/BaseHapiTerminologySvcImpl.java
@@ -25,9 +25,9 @@ import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.IFhirResourceDaoCodeSystem;
import ca.uhn.fhir.jpa.dao.data.*;
-import ca.uhn.fhir.jpa.model.entity.*;
import ca.uhn.fhir.jpa.entity.*;
import ca.uhn.fhir.jpa.entity.TermConceptParentChildLink.RelationshipTypeEnum;
+import ca.uhn.fhir.jpa.model.entity.ResourceTable;
import ca.uhn.fhir.jpa.util.ScrollableResultsIterator;
import ca.uhn.fhir.rest.api.server.RequestDetails;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
@@ -137,6 +137,8 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
private int myFetchSize = DEFAULT_FETCH_SIZE;
private ApplicationContext myApplicationContext;
private TransactionTemplate myTxTemplate;
+ @Autowired
+ private PlatformTransactionManager myTransactionManager;
/**
* @param theAdd If true, add the code. If false, remove the code.
@@ -368,9 +370,6 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
}
}
- @Autowired
- private PlatformTransactionManager myTransactionManager;
-
@Override
@Transactional
public void deleteConceptMapAndChildren(ResourceTable theResourceTable) {
@@ -391,7 +390,7 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
TransactionTemplate txTemplate = new TransactionTemplate(myTransactionManager);
txTemplate.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
- txTemplate.execute(t->{
+ txTemplate.execute(t -> {
theDao.deleteInBatch(link);
return null;
});
@@ -1190,6 +1189,22 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
termConceptMap.setResource(theResourceTable);
termConceptMap.setUrl(theConceptMap.getUrl());
+ String source = theConceptMap.hasSourceUriType() ? theConceptMap.getSourceUriType().getValueAsString() : null;
+ String target = theConceptMap.hasTargetUriType() ? theConceptMap.getTargetUriType().getValueAsString() : null;
+
+ /*
+ * If this is a mapping between "resources" instead of purely between
+ * "concepts" (this is a weird concept that is technically possible, at least as of
+ * FHIR R4), don't try to store the mappings.
+ *
+ * See here for a description of what that is:
+ * http://hl7.org/fhir/conceptmap.html#bnr
+ */
+ if ("StructureDefinition".equals(new IdType(source).getResourceType()) ||
+ "StructureDefinition".equals(new IdType(target).getResourceType())) {
+ return;
+ }
+
/*
* For now we always delete old versions. At some point, it would be nice to allow configuration to keep old versions.
*/
@@ -1202,11 +1217,9 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
Optional optionalExistingTermConceptMapByUrl = myConceptMapDao.findTermConceptMapByUrl(conceptMapUrl);
if (!optionalExistingTermConceptMapByUrl.isPresent()) {
try {
- String source = theConceptMap.hasSourceUriType() ? theConceptMap.getSourceUriType().getValueAsString() : null;
if (isNotBlank(source)) {
termConceptMap.setSource(source);
}
- String target = theConceptMap.hasTargetUriType() ? theConceptMap.getTargetUriType().getValueAsString() : null;
if (isNotBlank(target)) {
termConceptMap.setTarget(target);
}
@@ -1244,12 +1257,12 @@ public abstract class BaseHapiTerminologySvcImpl implements IHapiTerminologySvc,
if (element.hasTarget()) {
TermConceptMapGroupElementTarget termConceptMapGroupElementTarget;
- for (ConceptMap.TargetElementComponent target : element.getTarget()) {
+ for (ConceptMap.TargetElementComponent elementTarget : element.getTarget()) {
termConceptMapGroupElementTarget = new TermConceptMapGroupElementTarget();
termConceptMapGroupElementTarget.setConceptMapGroupElement(termConceptMapGroupElement);
- termConceptMapGroupElementTarget.setCode(target.getCode());
- termConceptMapGroupElementTarget.setDisplay(target.getDisplay());
- termConceptMapGroupElementTarget.setEquivalence(target.getEquivalence());
+ termConceptMapGroupElementTarget.setCode(elementTarget.getCode());
+ termConceptMapGroupElementTarget.setDisplay(elementTarget.getDisplay());
+ termConceptMapGroupElementTarget.setEquivalence(elementTarget.getEquivalence());
myConceptMapGroupElementTargetDao.save(termConceptMapGroupElementTarget);
if (codesSaved++ % 250 == 0) {
diff --git a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/TestUtil.java b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/TestUtil.java
index 0f41138cc20..1cd6d7098cf 100644
--- a/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/TestUtil.java
+++ b/hapi-fhir-jpaserver-base/src/main/java/ca/uhn/fhir/jpa/util/TestUtil.java
@@ -25,11 +25,15 @@ import com.google.common.collect.ImmutableSet;
import com.google.common.reflect.ClassPath;
import com.google.common.reflect.ClassPath.ClassInfo;
import org.apache.commons.lang3.Validate;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.r4.model.InstantType;
+import org.hl7.fhir.r4.model.Patient;
import javax.persistence.*;
import java.io.IOException;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Field;
+import java.util.Date;
import java.util.HashSet;
import java.util.Set;
@@ -165,10 +169,21 @@ public class TestUtil {
ourLog.info("Sleeping for {}ms", timeToSleep);
Thread.sleep(timeToSleep);
} catch (InterruptedException theE) {
- theE.printStackTrace();
+ ourLog.error("Interrupted", theE);
}
}
}
+ public static void clearAllStaticFieldsForUnitTest() {
+ ca.uhn.fhir.util.TestUtil.clearAllStaticFieldsForUnitTest();
+ }
+
+ public static InstantType getTimestamp(IBaseResource resource) {
+ return new InstantType(new Date(resource.getMeta().getLastUpdated().getTime()));
+ }
+
+ public static void sleepOneClick() {
+ sleepAtLeast(1);
+ }
}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/CaptureQueriesListener.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/CaptureQueriesListener.java
new file mode 100644
index 00000000000..c4dc2cbe04c
--- /dev/null
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/CaptureQueriesListener.java
@@ -0,0 +1,92 @@
+package ca.uhn.fhir.jpa.config;
+
+import net.ttddyy.dsproxy.ExecutionInfo;
+import net.ttddyy.dsproxy.QueryInfo;
+import net.ttddyy.dsproxy.proxy.ParameterSetOperation;
+import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
+import org.hibernate.engine.jdbc.internal.BasicFormatterImpl;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.stream.Collectors;
+
+public class CaptureQueriesListener implements ProxyDataSourceBuilder.SingleQueryExecution {
+
+ private static final LinkedList LAST_N_QUERIES = new LinkedList<>();
+
+ @Override
+ public void execute(ExecutionInfo execInfo, List queryInfoList) {
+ synchronized (LAST_N_QUERIES) {
+ for (QueryInfo next : queryInfoList) {
+ String sql = next.getQuery();
+ List params;
+ if (next.getParametersList().size() > 0 && next.getParametersList().get(0).size() > 0) {
+ List values = next
+ .getParametersList()
+ .get(0);
+ params = values.stream()
+ .map(t -> t.getArgs()[1])
+ .map(t -> t != null ? t.toString() : "NULL")
+ .collect(Collectors.toList());
+ } else {
+ params = new ArrayList<>();
+ }
+ LAST_N_QUERIES.add(0, new Query(sql, params));
+ }
+ while (LAST_N_QUERIES.size() > 100) {
+ LAST_N_QUERIES.removeLast();
+ }
+ }
+ }
+
+ public static class Query {
+ private final String myThreadName = Thread.currentThread().getName();
+ private final String mySql;
+ private final List myParams;
+
+ Query(String theSql, List theParams) {
+ mySql = theSql;
+ myParams = Collections.unmodifiableList(theParams);
+ }
+
+ public String getThreadName() {
+ return myThreadName;
+ }
+
+ public String getSql(boolean theInlineParams, boolean theFormat) {
+ String retVal = mySql;
+ if (theFormat) {
+ retVal = new BasicFormatterImpl().format(retVal);
+ }
+
+ if (theInlineParams) {
+ List nextParams = new ArrayList<>(myParams);
+ while (retVal.contains("?") && nextParams.size() > 0) {
+ int idx = retVal.indexOf("?");
+ retVal = retVal.substring(0, idx) + nextParams.remove(0) + retVal.substring(idx + 1);
+ }
+ }
+
+ return retVal;
+
+ }
+
+ }
+
+ public static void clear() {
+ synchronized (LAST_N_QUERIES) {
+ LAST_N_QUERIES.clear();
+ }
+ }
+
+ /**
+ * Index 0 is newest!
+ */
+ public static ArrayList getLastNQueries() {
+ synchronized (LAST_N_QUERIES) {
+ return new ArrayList<>(LAST_N_QUERIES);
+ }
+ }
+}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestR4Config.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestR4Config.java
index d9fcc5773cf..e432dd66a9c 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestR4Config.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/config/TestR4Config.java
@@ -100,6 +100,7 @@ public class TestR4Config extends BaseJavaConfigR4 {
// .logSlowQueryBySlf4j(10, TimeUnit.SECONDS)
// .countQuery(new ThreadQueryCountHolder())
.beforeQuery(new BlockLargeNumbersOfParamsListener())
+ .afterQuery(new CaptureQueriesListener())
.countQuery(singleQueryCountHolder())
.build();
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java
index eb040fcba84..290c3194f31 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/BaseJpaTest.java
@@ -1,7 +1,10 @@
package ca.uhn.fhir.jpa.dao;
import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.jpa.config.CaptureQueriesListener;
import ca.uhn.fhir.jpa.entity.TermConcept;
+import ca.uhn.fhir.jpa.model.interceptor.api.IInterceptorRegistry;
+import ca.uhn.fhir.jpa.model.interceptor.api.Pointcut;
import ca.uhn.fhir.jpa.provider.SystemProviderDstu2Test;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc;
@@ -51,7 +54,9 @@ import java.sql.Connection;
import java.sql.SQLException;
import java.util.*;
import java.util.concurrent.Callable;
+import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.function.Supplier;
import java.util.stream.Collectors;
import static ca.uhn.fhir.util.TestUtil.randomizeLocale;
@@ -84,10 +89,13 @@ public abstract class BaseJpaTest {
protected IRequestOperationCallback myRequestOperationCallback = mock(IRequestOperationCallback.class);
@Autowired
protected DatabaseBackedPagingProvider myDatabaseBackedPagingProvider;
+ @Autowired
+ protected IInterceptorRegistry myInterceptorRegistry;
@After
public void afterPerformCleanup() {
BaseHapiFhirResourceDao.setDisableIncrementOnUpdateForUnitTest(false);
+ CaptureQueriesListener.clear();
}
@After
@@ -128,6 +136,12 @@ public abstract class BaseJpaTest {
when(mySrd.getHeaders(eq(JpaConstants.HEADER_META_SNAPSHOT_MODE))).thenReturn(new ArrayList<>());
}
+ protected CountDownLatch registerLatchHookInterceptor(int theCount, Pointcut theLatchPointcut) {
+ CountDownLatch deliveryLatch = new CountDownLatch(theCount);
+ myInterceptorRegistry.registerAnonymousHookForUnitTest(theLatchPointcut, Integer.MAX_VALUE, t -> deliveryLatch.countDown());
+ return deliveryLatch;
+ }
+
protected abstract FhirContext getContext();
protected abstract PlatformTransactionManager getTxManager();
@@ -431,6 +445,20 @@ public abstract class BaseJpaTest {
}
}
+ public static void waitForTrue(Supplier theList) {
+ StopWatch sw = new StopWatch();
+ while (!theList.get() && sw.getMillis() <= 16000) {
+ try {
+ Thread.sleep(50);
+ } catch (InterruptedException theE) {
+ throw new Error(theE);
+ }
+ }
+ if (sw.getMillis() >= 16000) {
+ fail("Waited " + sw.toString() + " and is still false");
+ }
+ }
+
public static void waitForSize(int theTarget, Callable theCallable) throws Exception {
waitForSize(theTarget, 10000, theCallable);
}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/BaseJpaDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/BaseJpaDstu2Test.java
index d08e7b3b9cc..428bf928507 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/BaseJpaDstu2Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/BaseJpaDstu2Test.java
@@ -56,7 +56,7 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest {
@Qualifier("myResourceCountsCache")
protected ResourceCountCache myResourceCountsCache;
@Autowired
- protected ISearchParamRegistry mySearchParamRegsitry;
+ protected ISearchParamRegistry mySearchParamRegistry;
@Autowired
protected ApplicationContext myAppCtx;
@Autowired
@@ -181,8 +181,6 @@ public abstract class BaseJpaDstu2Test extends BaseJpaTest {
@Qualifier("myValueSetDaoDstu2")
protected IFhirResourceDaoValueSet myValueSetDao;
@Autowired
- private ISearchParamRegistry mySearchParamRegistry;
- @Autowired
protected SubscriptionLoader mySubscriptionLoader;
@Before
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchCustomSearchParamTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchCustomSearchParamTest.java
index 90c00800444..6d93836ec5b 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchCustomSearchParamTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchCustomSearchParamTest.java
@@ -2,8 +2,8 @@ package ca.uhn.fhir.jpa.dao.dstu2;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
-import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
+import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.api.ExtensionDt;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.dstu2.composite.CodeableConceptDt;
@@ -70,7 +70,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
threadIdSp.setXpathUsage(XPathUsageTypeEnum.NORMAL);
threadIdSp.setStatus(ConformanceResourceStatusEnum.ACTIVE);
mySearchParameterDao.create(threadIdSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Communication com = new Communication();
com.setStatus(CommunicationStatusEnum.IN_PROGRESS);
@@ -163,7 +163,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
sp.setStatus(ConformanceResourceStatusEnum.ACTIVE);
mySearchParameterDao.create(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Practitioner pract = new Practitioner();
pract.setId("A");
@@ -194,7 +194,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
eyeColourSp.setStatus(ConformanceResourceStatusEnum.ACTIVE);
mySearchParameterDao.create(eyeColourSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p1 = new Patient();
p1.setActive(true);
@@ -215,7 +215,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
attendingSp.addTarget(ResourceTypeEnum.PRACTITIONER);
IIdType spId = mySearchParameterDao.create(attendingSp, mySrd).getId().toUnqualifiedVersionless();
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Practitioner p1 = new Practitioner();
p1.getName().addFamily("P1");
@@ -265,7 +265,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
identifierSp.setStatus(ConformanceResourceStatusEnum.RETIRED);
mySearchParameterDao.create(identifierSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p = new Patient();
p.addName().addGiven("G");
@@ -307,7 +307,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
identifierSp.setStatus(ConformanceResourceStatusEnum.RETIRED);
mySearchParameterDao.create(identifierSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p = new Patient();
p.addName().addGiven("G");
@@ -339,7 +339,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.addTarget(ResourceTypeEnum.ORGANIZATION);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p1 = new Patient();
p1.addName().addFamily("P1");
@@ -382,7 +382,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.addTarget(ResourceTypeEnum.PATIENT);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p1 = new Patient();
p1.addName().addFamily("P1");
@@ -435,7 +435,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.setStatus(ConformanceResourceStatusEnum.ACTIVE);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p1 = new Patient();
p1.addName().addFamily("P1");
@@ -489,7 +489,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
eyeColourSp.setStatus(ConformanceResourceStatusEnum.ACTIVE);
mySearchParameterDao.create(eyeColourSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p1 = new Patient();
p1.setActive(true);
@@ -522,7 +522,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.addTarget(ResourceTypeEnum.ORGANIZATION);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient patient = new Patient();
patient.addName().addFamily("P2");
@@ -558,7 +558,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.addTarget(ResourceTypeEnum.ORGANIZATION);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient patient = new Patient();
patient.addName().addFamily("P2");
@@ -594,7 +594,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.setStatus(ConformanceResourceStatusEnum.ACTIVE);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Appointment apt = new Appointment();
apt.setStatus(AppointmentStatusEnum.ARRIVED);
@@ -635,7 +635,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.setStatus(ConformanceResourceStatusEnum.ACTIVE);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient patient = new Patient();
patient.addName().addFamily("P2");
@@ -671,7 +671,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.setStatus(ConformanceResourceStatusEnum.ACTIVE);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient patient = new Patient();
patient.addName().addFamily("P2");
@@ -708,7 +708,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.addTarget(ResourceTypeEnum.APPOINTMENT);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Appointment apt = new Appointment();
apt.setStatus(AppointmentStatusEnum.ARRIVED);
@@ -747,7 +747,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.setStatus(ConformanceResourceStatusEnum.ACTIVE);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Appointment apt = new Appointment();
apt.setStatus(AppointmentStatusEnum.ARRIVED);
@@ -789,7 +789,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.addTarget(ResourceTypeEnum.OBSERVATION);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Appointment apt = new Appointment();
apt.setStatus(AppointmentStatusEnum.ARRIVED);
@@ -830,7 +830,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.setStatus(ConformanceResourceStatusEnum.ACTIVE);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient patient = new Patient();
patient.addName().addFamily("P2");
@@ -867,7 +867,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
fooSp.setStatus(ConformanceResourceStatusEnum.ACTIVE);
IIdType spId = mySearchParameterDao.create(fooSp, mySrd).getId().toUnqualifiedVersionless();
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient pat = new Patient();
pat.addIdentifier().setSystem("FOO123").setValue("BAR678");
@@ -912,7 +912,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
IIdType spId = mySearchParameterDao.create(fooSp, mySrd).getId().toUnqualifiedVersionless();
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient pat = new Patient();
pat.addIdentifier().setSystem("http://AAA").setValue("BAR678");
@@ -957,7 +957,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
fooSp.setStatus(ConformanceResourceStatusEnum.ACTIVE);
IIdType spId = mySearchParameterDao.create(fooSp, mySrd).getId().toUnqualifiedVersionless();
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient pat = new Patient();
pat.setGender(AdministrativeGenderEnum.MALE);
@@ -988,7 +988,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
// Delete the param
mySearchParameterDao.delete(spId, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
myResourceReindexingSvc.markAllResourcesForReindexing();
myResourceReindexingSvc.forceReindexingPass();
myResourceReindexingSvc.forceReindexingPass();
@@ -1016,7 +1016,7 @@ public class FhirResourceDaoDstu2SearchCustomSearchParamTest extends BaseJpaDstu
fooSp.setStatus(ConformanceResourceStatusEnum.DRAFT);
mySearchParameterDao.create(fooSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient pat = new Patient();
pat.setGender(AdministrativeGenderEnum.MALE);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchNoFtTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchNoFtTest.java
index 7bfd40cfb5c..bfa828616d7 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchNoFtTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu2/FhirResourceDaoDstu2SearchNoFtTest.java
@@ -5,6 +5,7 @@ import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.dao.data.ISearchParamPresentDao;
import ca.uhn.fhir.jpa.model.entity.*;
+import ca.uhn.fhir.jpa.util.TestUtil;
import ca.uhn.fhir.model.api.*;
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
import ca.uhn.fhir.model.dstu2.composite.*;
@@ -19,7 +20,6 @@ import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
-import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
@@ -374,6 +374,9 @@ public class FhirResourceDaoDstu2SearchNoFtTest extends BaseJpaDstu2Test {
patient.addIdentifier().setSystem("urn:system").setValue("001");
id1 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
+
+ TestUtil.sleepOneClick();
+
long betweenTime = System.currentTimeMillis();
IIdType id2;
{
@@ -820,8 +823,6 @@ public class FhirResourceDaoDstu2SearchNoFtTest extends BaseJpaDstu2Test {
@Test
public void testSearchLastUpdatedParamWithComparator() throws InterruptedException {
- String methodName = "testSearchLastUpdatedParamWithComparator";
-
IIdType id0;
{
Patient patient = new Patient();
@@ -829,18 +830,16 @@ public class FhirResourceDaoDstu2SearchNoFtTest extends BaseJpaDstu2Test {
id0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
- int sleep = 100;
-
long start = System.currentTimeMillis();
- Thread.sleep(sleep);
+ TestUtil.sleepOneClick();
- DateTimeDt beforeAny = new DateTimeDt(new Date(), TemporalPrecisionEnum.MILLI);
IIdType id1a;
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
id1a = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
+ TestUtil.sleepOneClick();
IIdType id1b;
{
Patient patient = new Patient();
@@ -853,11 +852,12 @@ public class FhirResourceDaoDstu2SearchNoFtTest extends BaseJpaDstu2Test {
InstantDt id1bpublished = ResourceMetadataKeyEnum.PUBLISHED.get(myPatientDao.read(id1b, mySrd));
ourLog.info("Res 3: {}", id1bpublished.getValueAsString());
- Thread.sleep(sleep);
+ TestUtil.sleepOneClick();
long end = System.currentTimeMillis();
SearchParameterMap params;
Date startDate = new Date(start);
+ TestUtil.sleepOneClick();
Date endDate = new Date(end);
DateTimeDt startDateTime = new DateTimeDt(startDate, TemporalPrecisionEnum.MILLI);
DateTimeDt endDateTime = new DateTimeDt(endDate, TemporalPrecisionEnum.MILLI);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java
index 25f1dd08211..c01ecfb9d17 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/BaseJpaDstu3Test.java
@@ -56,7 +56,7 @@ import java.io.IOException;
import java.io.InputStream;
import java.util.Map;
-import static org.junit.Assert.*;
+import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
@RunWith(SpringJUnit4ClassRunner.class)
@@ -215,7 +215,7 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest {
@Autowired
protected ISearchParamPresenceSvc mySearchParamPresenceSvc;
@Autowired
- protected ISearchParamRegistry mySearchParamRegsitry;
+ protected ISearchParamRegistry mySearchParamRegistry;
@Autowired
protected IStaleSearchDeletingSvc myStaleSearchDeletingSvc;
@Autowired
@@ -256,8 +256,6 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest {
protected ITermConceptMapGroupElementTargetDao myTermConceptMapGroupElementTargetDao;
@Autowired
private JpaValidationSupportChainDstu3 myJpaValidationSupportChainDstu3;
- @Autowired
- protected ISearchParamRegistry mySearchParamRegistry;
@After()
public void afterCleanupDao() {
@@ -306,7 +304,7 @@ public abstract class BaseJpaDstu3Test extends BaseJpaTest {
@Before
@Transactional()
public void beforePurgeDatabase() {
- purgeDatabase(myDaoConfig, mySystemDao, myResourceReindexingSvc, mySearchCoordinatorSvc, mySearchParamRegsitry);
+ purgeDatabase(myDaoConfig, mySystemDao, myResourceReindexingSvc, mySearchCoordinatorSvc, mySearchParamRegistry);
}
@Before
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchCustomSearchParamTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchCustomSearchParamTest.java
index cb52de87033..c9916d62c22 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchCustomSearchParamTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchCustomSearchParamTest.java
@@ -139,7 +139,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
sp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
org.hl7.fhir.dstu3.model.Practitioner pract = new org.hl7.fhir.dstu3.model.Practitioner();
pract.setId("A");
@@ -169,7 +169,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
eyeColourSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(eyeColourSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p1 = new Patient();
p1.setActive(true);
@@ -191,7 +191,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
attendingSp.getTarget().add(new CodeType("Practitioner"));
IIdType spId = mySearchParameterDao.create(attendingSp, mySrd).getId().toUnqualifiedVersionless();
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Practitioner p1 = new Practitioner();
p1.addName().setFamily("P1");
@@ -231,7 +231,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
threadIdSp.setXpathUsage(SearchParameter.XPathUsageType.NORMAL);
threadIdSp.setStatus(Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(threadIdSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Communication com = new Communication();
com.setStatus(Communication.CommunicationStatus.INPROGRESS);
@@ -277,7 +277,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
sp.addTarget("Condition");
sp.addTarget("Observation");
mySearchParameterDao.create(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Condition condition = new Condition();
condition.getCode().setText("A condition");
@@ -313,7 +313,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
sp.setType(Enumerations.SearchParamType.TOKEN);
sp.setExpression("MedicationRequest.reasonCode | ProcedureRequest.reasonCode");
mySearchParameterDao.create(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
MedicationRequest mr = new MedicationRequest();
mr.addReasonCode().addCoding().setSystem("foo").setCode("bar");
@@ -343,7 +343,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.getTarget().add(new CodeType("Organization"));
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p1 = new Patient();
p1.addName().setFamily("P1");
@@ -387,7 +387,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.getTarget().add(new CodeType("Patient"));
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p1 = new Patient();
p1.addName().setFamily("P1");
@@ -441,7 +441,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p1 = new Patient();
p1.addName().setFamily("P1");
@@ -496,7 +496,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
eyeColourSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(eyeColourSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p1 = new Patient();
p1.setActive(true);
@@ -530,7 +530,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.getTarget().add(new CodeType("Organization"));
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient patient = new Patient();
patient.addName().setFamily("P2");
@@ -568,7 +568,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.getTarget().add(new CodeType("Organization"));
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient patient = new Patient();
patient.addName().setFamily("P2");
@@ -605,7 +605,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Appointment apt = new Appointment();
apt.setStatus(AppointmentStatus.ARRIVED);
@@ -647,7 +647,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient patient = new Patient();
patient.addName().setFamily("P2");
@@ -684,7 +684,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient patient = new Patient();
patient.addName().setFamily("P2");
@@ -722,7 +722,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.getTarget().add(new CodeType("Appointment"));
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Appointment apt = new Appointment();
apt.setStatus(AppointmentStatus.ARRIVED);
@@ -764,7 +764,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Appointment apt = new Appointment();
apt.setStatus(AppointmentStatus.ARRIVED);
@@ -807,7 +807,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.getTarget().add(new CodeType("Observation"));
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Appointment apt = new Appointment();
apt.setStatus(AppointmentStatus.ARRIVED);
@@ -849,7 +849,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
siblingSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient patient = new Patient();
patient.addName().setFamily("P2");
@@ -886,7 +886,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
displaySp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(displaySp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
MedicationStatement ms1 = new MedicationStatement();
ms1.setMedication(new CodeableConcept());
@@ -919,7 +919,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(sp));
mySearchParameterDao.create(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Specimen specimen = new Specimen();
specimen.setId("#FOO");
@@ -962,7 +962,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
IIdType spId = mySearchParameterDao.create(fooSp, mySrd).getId().toUnqualifiedVersionless();
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient pat = new Patient();
pat.setGender(AdministrativeGender.MALE);
@@ -993,7 +993,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
// Delete the param
mySearchParameterDao.delete(spId, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
myResourceReindexingSvc.forceReindexingPass();
myResourceReindexingSvc.forceReindexingPass();
@@ -1021,7 +1021,7 @@ public class FhirResourceDaoDstu3SearchCustomSearchParamTest extends BaseJpaDstu
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.DRAFT);
mySearchParameterDao.create(fooSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient pat = new Patient();
pat.setGender(AdministrativeGender.MALE);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchNoFtTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchNoFtTest.java
index 5ebda85d4df..77bdfa62ed1 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchNoFtTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchNoFtTest.java
@@ -13,6 +13,7 @@ import javax.servlet.http.HttpServletRequest;
import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
+import ca.uhn.fhir.jpa.util.TestUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.dstu3.model.*;
@@ -40,7 +41,6 @@ import ca.uhn.fhir.rest.api.SortSpec;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
-import ca.uhn.fhir.util.TestUtil;
@SuppressWarnings("unchecked")
public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
@@ -667,6 +667,9 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
id1 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
long betweenTime = System.currentTimeMillis();
+
+ TestUtil.sleepOneClick();
+
IIdType id2;
{
Patient patient = new Patient();
@@ -1020,7 +1023,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
patient.addName().setFamily("testSearchLanguageParam").addGiven("Joe");
id1 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
-
+ TestUtil.sleepOneClick();
Date betweenTime = new Date();
IIdType id2;
@@ -1196,10 +1199,9 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
id0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
- int sleep = 100;
-
+ TestUtil.sleepOneClick();
long start = System.currentTimeMillis();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(sleep);
+ TestUtil.sleepOneClick();
IIdType id1a;
{
@@ -1218,7 +1220,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
ourLog.info("Res 2: {}", myPatientDao.read(id1a, mySrd).getMeta().getLastUpdatedElement().getValueAsString());
ourLog.info("Res 3: {}", myPatientDao.read(id1b, mySrd).getMeta().getLastUpdatedElement().getValueAsString());
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(sleep);
+ TestUtil.sleepOneClick();
long end = System.currentTimeMillis();
SearchParameterMap map;
@@ -1615,18 +1617,18 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
obs01.setSubject(new Reference(patientId01));
IIdType obsId01 = myObservationDao.create(obs01, mySrd).getId().toUnqualifiedVersionless();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(1);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
Date between = new Date();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(1);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
Observation obs02 = new Observation();
obs02.setEffective(new DateTimeType(new Date()));
obs02.setSubject(new Reference(locId01));
IIdType obsId02 = myObservationDao.create(obs02, mySrd).getId().toUnqualifiedVersionless();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(1);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
Date after = new Date();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(1);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
ourLog.info("P1[{}] L1[{}] Obs1[{}] Obs2[{}]", new Object[] { patientId01, locId01, obsId01, obsId02 });
@@ -1853,15 +1855,15 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
patient.addName().setFamily("Tester_testSearchStringParam").addGiven("Joe");
pid1 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
+ TestUtil.sleepOneClick();
Date between = new Date();
- Thread.sleep(10);
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("002");
patient.addName().setFamily("Tester_testSearchStringParam").addGiven("John");
pid2 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
- Thread.sleep(10);
+ TestUtil.sleepOneClick();
Date after = new Date();
SearchParameterMap params;
@@ -2871,6 +2873,8 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
tag1id = myOrganizationDao.create(org, mySrd).getId().toUnqualifiedVersionless();
}
+ TestUtil.sleepOneClick();
+
Date betweenDate = new Date();
IIdType tag2id;
@@ -3193,7 +3197,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
p01.addName().setFamily("B").addGiven("A");
String id1 = myPatientDao.create(p01).getId().toUnqualifiedVersionless().getValue();
- Thread.sleep(10);
+ TestUtil.sleepOneClick();
// Numeric ID
Patient p02 = new Patient();
@@ -3203,7 +3207,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
p02.addName().setFamily("Z").addGiven("Z");
String id2 = myPatientDao.create(p02).getId().toUnqualifiedVersionless().getValue();
- Thread.sleep(10);
+ TestUtil.sleepOneClick();
// Forced ID
Patient pAB = new Patient();
@@ -3213,7 +3217,7 @@ public class FhirResourceDaoDstu3SearchNoFtTest extends BaseJpaDstu3Test {
pAB.addName().setFamily("A").addGiven("B");
myPatientDao.update(pAB);
- Thread.sleep(10);
+ TestUtil.sleepOneClick();
// Forced ID
Patient pAA = new Patient();
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchPageExpiryTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchPageExpiryTest.java
index 90b19eaaa53..779e8175506 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchPageExpiryTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3SearchPageExpiryTest.java
@@ -6,6 +6,7 @@ import ca.uhn.fhir.jpa.dao.data.ISearchDao;
import ca.uhn.fhir.jpa.dao.r4.FhirResourceDaoR4SearchPageExpiryTest;
import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.search.StaleSearchDeletingSvcImpl;
+import ca.uhn.fhir.jpa.util.TestUtil;
import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.StringParam;
@@ -29,7 +30,6 @@ import org.springframework.transaction.support.TransactionTemplate;
import java.util.Date;
import java.util.concurrent.atomic.AtomicLong;
-import static ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.*;
@@ -105,8 +105,7 @@ public class FhirResourceDaoDstu3SearchPageExpiryTest extends BaseJpaDstu3Test {
}
assertEquals(searchUuid1, searchUuid2);
- sleepAtLeast(501);
-
+ TestUtil.sleepAtLeast(501);
// We're now past 500ms so we shouldn't reuse the search
final String searchUuid3;
@@ -277,7 +276,7 @@ public class FhirResourceDaoDstu3SearchPageExpiryTest extends BaseJpaDstu3Test {
}
assertEquals(searchUuid1, searchUuid2);
- sleepAtLeast(501);
+ TestUtil.sleepAtLeast(501);
// We're now past 500ms so we shouldn't reuse the search
@@ -363,7 +362,7 @@ public class FhirResourceDaoDstu3SearchPageExpiryTest extends BaseJpaDstu3Test {
}
});
if (search == null) {
- sleepAtLeast(100);
+ TestUtil.sleepAtLeast(100);
}
}
assertNotNull("Search " + bundleProvider.getUuid() + " not found on disk after 10 seconds", search);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3Test.java
index d8b94a50f9f..0d41ad30e2c 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3Test.java
@@ -2867,21 +2867,21 @@ public class FhirResourceDaoDstu3Test extends BaseJpaDstu3Test {
p.addName().setFamily(methodName);
IIdType id1 = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(1);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
p = new Patient();
p.addIdentifier().setSystem("urn:system2").setValue(methodName);
p.addName().setFamily(methodName);
IIdType id2 = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(1);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
p = new Patient();
p.addIdentifier().setSystem("urn:system3").setValue(methodName);
p.addName().setFamily(methodName);
IIdType id3 = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(1);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
p = new Patient();
p.addIdentifier().setSystem("urn:system4").setValue(methodName);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3UniqueSearchParamTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3UniqueSearchParamTest.java
index 2fb1336f5f0..e648d839c7a 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3UniqueSearchParamTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3UniqueSearchParamTest.java
@@ -2,11 +2,10 @@ package ca.uhn.fhir.jpa.dao.dstu3;
import ca.uhn.fhir.jpa.dao.SearchBuilder;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
-import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
-import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedCompositeStringUnique;
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
-import ca.uhn.fhir.jpa.util.JpaConstants;
+import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
+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.TokenParam;
@@ -82,7 +81,7 @@ public class FhirResourceDaoDstu3UniqueSearchParamTest extends BaseJpaDstu3Test
.setValue(new BooleanType(true));
mySearchParameterDao.update(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
}
private void createUniqueIndexCoverageBeneficiary() {
@@ -121,7 +120,7 @@ public class FhirResourceDaoDstu3UniqueSearchParamTest extends BaseJpaDstu3Test
.setUrl(SearchParamConstants.EXT_SP_UNIQUE)
.setValue(new BooleanType(true));
mySearchParameterDao.update(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
}
private void createUniqueNameAndManagingOrganizationSps() {
@@ -159,13 +158,13 @@ public class FhirResourceDaoDstu3UniqueSearchParamTest extends BaseJpaDstu3Test
.setValue(new BooleanType(true));
mySearchParameterDao.update(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
}
@Test
public void testDetectUniqueSearchParams() {
createUniqueBirthdateAndGenderSps();
- List params = mySearchParamRegsitry.getActiveUniqueSearchParams("Patient");
+ List params = mySearchParamRegistry.getActiveUniqueSearchParams("Patient");
assertEquals(1, params.size());
assertEquals(params.get(0).isUnique(), true);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3UpdateTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3UpdateTest.java
index 51089f210d4..ae9c5f521c9 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3UpdateTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3UpdateTest.java
@@ -306,7 +306,7 @@ public class FhirResourceDaoDstu3UpdateTest extends BaseJpaDstu3Test {
assertEquals("1", outcome.getId().getVersionIdPart());
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
Date now = new Date();
Patient retrieved = myPatientDao.read(outcome.getId(), mySrd);
InstantType updated = retrieved.getMeta().getLastUpdatedElement().copy();
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValidateTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValidateTest.java
index 9c60aea71f1..9e297d4d916 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValidateTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/dstu3/FhirResourceDaoDstu3ValidateTest.java
@@ -4,6 +4,7 @@ import static org.hamcrest.Matchers.containsString;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.fail;
+import ca.uhn.fhir.jpa.util.TestUtil;
import ca.uhn.fhir.rest.api.EncodingEnum;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.ValidationModeEnum;
@@ -11,7 +12,6 @@ import ca.uhn.fhir.rest.server.exceptions.PreconditionFailedException;
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.StopWatch;
-import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.io.IOUtils;
import org.hl7.fhir.dstu3.model.*;
import org.hl7.fhir.dstu3.model.Bundle.BundleEntryComponent;
@@ -25,8 +25,6 @@ import org.junit.Test;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
-import static ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast;
-
public class FhirResourceDaoDstu3ValidateTest extends BaseJpaDstu3Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(FhirResourceDaoDstu3ValidateTest.class);
@@ -64,7 +62,7 @@ public class FhirResourceDaoDstu3ValidateTest extends BaseJpaDstu3Test {
MethodOutcome results = myQuestionnaireResponseDao.validate(qr, null, null, null, null, null, null);
ourLog.info(myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(results.getOperationOutcome()));
- sleepAtLeast(2500);
+ TestUtil.sleepAtLeast(2500);
try {
myQuestionnaireResponseDao.validate(qr, null, null, null, null, null, null);
fail();
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/BaseJpaR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/BaseJpaR4Test.java
index e020fb031d4..0da4e00e6d0 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/BaseJpaR4Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/BaseJpaR4Test.java
@@ -8,13 +8,14 @@ import ca.uhn.fhir.jpa.dao.dstu2.FhirResourceDaoDstu2SearchNoFtTest;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
+import ca.uhn.fhir.jpa.model.interceptor.api.IInterceptorRegistry;
import ca.uhn.fhir.jpa.provider.r4.JpaSystemProviderR4;
import ca.uhn.fhir.jpa.search.DatabaseBackedPagingProvider;
import ca.uhn.fhir.jpa.search.ISearchCoordinatorSvc;
import ca.uhn.fhir.jpa.search.IStaleSearchDeletingSvc;
import ca.uhn.fhir.jpa.search.reindex.IResourceReindexingSvc;
import ca.uhn.fhir.jpa.search.warm.ICacheWarmingSvc;
-import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
+import ca.uhn.fhir.jpa.searchparam.registry.BaseSearchParamRegistry;
import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionRegistry;
import ca.uhn.fhir.jpa.term.BaseHapiTerminologySvcImpl;
import ca.uhn.fhir.jpa.term.IHapiTerminologySvc;
@@ -150,6 +151,8 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
protected IFhirResourceDao myRiskAssessmentDao;
protected IServerInterceptor myInterceptor;
@Autowired
+ protected IInterceptorRegistry myInterceptorRegistry;
+ @Autowired
@Qualifier("myLocationDaoR4")
protected IFhirResourceDao myLocationDao;
@Autowired
@@ -226,7 +229,7 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
@Qualifier("mySearchParameterDaoR4")
protected IFhirResourceDao mySearchParameterDao;
@Autowired
- protected ISearchParamRegistry mySearchParamRegsitry;
+ protected BaseSearchParamRegistry mySearchParamRegistry;
@Autowired
protected IStaleSearchDeletingSvc myStaleSearchDeletingSvc;
@Autowired
@@ -285,6 +288,8 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
myDaoConfig.setReuseCachedSearchResultsForMillis(new DaoConfig().getReuseCachedSearchResultsForMillis());
myDaoConfig.setSuppressUpdatesWithNoChange(new DaoConfig().isSuppressUpdatesWithNoChange());
myDaoConfig.setAllowContainsSearches(new DaoConfig().isAllowContainsSearches());
+
+ myInterceptorRegistry.clearAnonymousHookForUnitTest();
}
@After
@@ -326,7 +331,7 @@ public abstract class BaseJpaR4Test extends BaseJpaTest {
@Transactional()
public void beforePurgeDatabase() throws InterruptedException {
final EntityManager entityManager = this.myEntityManager;
- purgeDatabase(myDaoConfig, mySystemDao, myResourceReindexingSvc, mySearchCoordinatorSvc, mySearchParamRegsitry);
+ purgeDatabase(myDaoConfig, mySystemDao, myResourceReindexingSvc, mySearchCoordinatorSvc, mySearchParamRegistry);
}
@Before
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchCustomSearchParamTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchCustomSearchParamTest.java
index 612f8256aa2..4b87e0d55e4 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchCustomSearchParamTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchCustomSearchParamTest.java
@@ -2,8 +2,8 @@ package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
-import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamToken;
+import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.*;
@@ -163,7 +163,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
sp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
org.hl7.fhir.r4.model.Practitioner pract = new org.hl7.fhir.r4.model.Practitioner();
pract.setId("A");
@@ -193,7 +193,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
eyeColourSp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(eyeColourSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p1 = new Patient();
p1.setActive(true);
@@ -215,7 +215,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
attendingSp.getTarget().add(new CodeType("Practitioner"));
IIdType spId = mySearchParameterDao.create(attendingSp, mySrd).getId().toUnqualifiedVersionless();
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Practitioner p1 = new Practitioner();
p1.addName().setFamily("P1");
@@ -265,7 +265,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
identifierSp.setStatus(Enumerations.PublicationStatus.RETIRED);
mySearchParameterDao.create(identifierSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p = new Patient();
p.addName().addGiven("G");
@@ -305,7 +305,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
identifierSp.setStatus(Enumerations.PublicationStatus.RETIRED);
mySearchParameterDao.create(identifierSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p = new Patient();
p.addName().addGiven("G");
@@ -342,7 +342,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
sp.addTarget("Condition");
sp.addTarget("Observation");
mySearchParameterDao.create(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Condition condition = new Condition();
condition.getCode().setText("A condition");
@@ -378,7 +378,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
sp.setType(Enumerations.SearchParamType.TOKEN);
sp.setExpression("MedicationRequest.reasonCode | ServiceRequest.reasonCode");
mySearchParameterDao.create(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
MedicationRequest mr = new MedicationRequest();
mr.addReasonCode().addCoding().setSystem("foo").setCode("bar");
@@ -425,7 +425,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
siblingSp.getTarget().add(new CodeType("Organization"));
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p1 = new Patient();
p1.addName().setFamily("P1");
@@ -469,7 +469,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
siblingSp.getTarget().add(new CodeType("Patient"));
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p1 = new Patient();
p1.addName().setFamily("P1");
@@ -523,7 +523,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
siblingSp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p1 = new Patient();
p1.addName().setFamily("P1");
@@ -577,7 +577,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
eyeColourSp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(eyeColourSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p1 = new Patient();
p1.setActive(true);
@@ -611,7 +611,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
siblingSp.getTarget().add(new CodeType("Organization"));
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient patient = new Patient();
patient.addName().setFamily("P2");
@@ -649,7 +649,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
siblingSp.getTarget().add(new CodeType("Organization"));
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient patient = new Patient();
patient.addName().setFamily("P2");
@@ -686,7 +686,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
siblingSp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Appointment apt = new Appointment();
apt.setStatus(AppointmentStatus.ARRIVED);
@@ -739,7 +739,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
txTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus theArg0) {
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
}
});
@@ -783,7 +783,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
siblingSp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient patient = new Patient();
patient.addName().setFamily("P2");
@@ -821,7 +821,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
siblingSp.getTarget().add(new CodeType("Appointment"));
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Appointment apt = new Appointment();
apt.setStatus(AppointmentStatus.ARRIVED);
@@ -863,7 +863,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
siblingSp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Appointment apt = new Appointment();
apt.setStatus(AppointmentStatus.ARRIVED);
@@ -906,7 +906,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
siblingSp.getTarget().add(new CodeType("Observation"));
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Appointment apt = new Appointment();
apt.setStatus(AppointmentStatus.ARRIVED);
@@ -948,7 +948,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
siblingSp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(siblingSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient patient = new Patient();
patient.addName().setFamily("P2");
@@ -986,7 +986,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
fooSp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.ACTIVE);
IIdType spId = mySearchParameterDao.create(fooSp, mySrd).getId().toUnqualifiedVersionless();
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient pat = new Patient();
pat.addIdentifier().setSystem("FOO123").setValue("BAR678");
@@ -1030,7 +1030,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
fooSp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.ACTIVE);
IIdType spId = mySearchParameterDao.create(fooSp, mySrd).getId().toUnqualifiedVersionless();
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient pat = new Patient();
pat.addIdentifier().setSystem("http://AAA").setValue("BAR678");
@@ -1074,7 +1074,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
sp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Specimen specimen = new Specimen();
specimen.setId("#FOO");
@@ -1117,7 +1117,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
fooSp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.ACTIVE);
IIdType spId = mySearchParameterDao.create(fooSp, mySrd).getId().toUnqualifiedVersionless();
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient pat = new Patient();
pat.setGender(AdministrativeGender.MALE);
@@ -1148,7 +1148,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
// Delete the param
mySearchParameterDao.delete(spId, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
myResourceReindexingSvc.forceReindexingPass();
// Try with custom gender SP
@@ -1175,7 +1175,7 @@ public class FhirResourceDaoR4SearchCustomSearchParamTest extends BaseJpaR4Test
fooSp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.DRAFT);
mySearchParameterDao.create(fooSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient pat = new Patient();
pat.setGender(AdministrativeGender.MALE);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java
index f49b54e57bf..096aff201a7 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoFtTest.java
@@ -1,9 +1,11 @@
package ca.uhn.fhir.jpa.dao.r4;
+import ca.uhn.fhir.jpa.config.CaptureQueriesListener;
import ca.uhn.fhir.jpa.dao.DaoConfig;
+import ca.uhn.fhir.jpa.model.entity.*;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap.EverythingModeEnum;
-import ca.uhn.fhir.jpa.model.entity.*;
+import ca.uhn.fhir.jpa.util.TestUtil;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
import ca.uhn.fhir.parser.StrictErrorHandler;
@@ -12,7 +14,7 @@ import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
-import ca.uhn.fhir.util.TestUtil;
+import com.google.common.collect.Lists;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IAnyResource;
@@ -39,6 +41,7 @@ import java.io.IOException;
import java.math.BigDecimal;
import java.nio.charset.StandardCharsets;
import java.util.*;
+import java.util.stream.Collectors;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*;
@@ -53,6 +56,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
myDaoConfig.setReuseCachedSearchResultsForMillis(new DaoConfig().getReuseCachedSearchResultsForMillis());
myDaoConfig.setFetchSizeDefaultMaximum(new DaoConfig().getFetchSizeDefaultMaximum());
myDaoConfig.setAllowContainsSearches(new DaoConfig().isAllowContainsSearches());
+ myDaoConfig.setSearchPreFetchThresholds(new DaoConfig().getSearchPreFetchThresholds());
}
@Before
@@ -151,16 +155,16 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
List ids;
Date beforeAll = new Date();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
Organization org = new Organization();
org.setName("O1");
org.setId("O1");
myOrganizationDao.update(org);
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
Date beforePatient = new Date();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
Patient p = new Patient();
p.setId("P1");
@@ -168,7 +172,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
p.setManagingOrganization(new Reference("Organization/O1"));
myPatientDao.update(p);
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
Date afterAll = new Date();
// Search with between date (should still return Organization even though
@@ -216,7 +220,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
myOrganizationDao.update(org);
Date beforeAll = new Date();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
Patient p = new Patient();
p.setId("P1");
@@ -224,17 +228,17 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
p.setManagingOrganization(new Reference("Organization/O1"));
myPatientDao.update(p);
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
Date beforeOrg = new Date();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
org = new Organization();
org.setActive(true);
org.setId("O1");
myOrganizationDao.update(org);
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
Date afterAll = new Date();
// Everything should come back
@@ -614,7 +618,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
expect1.setResource(resource);
expect1.calculateHashes();
- assertThat("Got: \"" + results.toString()+"\"", results, containsInAnyOrder(expect0, expect1));
+ assertThat("Got: \"" + results.toString() + "\"", results, containsInAnyOrder(expect0, expect1));
}
});
}
@@ -889,7 +893,11 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
patient.addIdentifier().setSystem("urn:system").setValue("001");
id1 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
+
+ TestUtil.sleepOneClick();
+
long betweenTime = System.currentTimeMillis();
+
IIdType id2;
{
Patient patient = new Patient();
@@ -1056,7 +1064,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
QuantityParam v1 = new QuantityParam(ParamPrefixEnum.GREATERTHAN_OR_EQUALS, 150, "http://bar", "code1");
SearchParameterMap map = new SearchParameterMap().setLoadSynchronous(true).add(param, v1);
IBundleProvider result = myObservationDao.search(map);
- assertThat("Got: "+ toUnqualifiedVersionlessIdValues(result), toUnqualifiedVersionlessIdValues(result), containsInAnyOrder(id1.getValue()));
+ assertThat("Got: " + toUnqualifiedVersionlessIdValues(result), toUnqualifiedVersionlessIdValues(result), containsInAnyOrder(id1.getValue()));
}
}
@@ -1088,7 +1096,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
CompositeParam val = new CompositeParam<>(v0, v1);
SearchParameterMap map = new SearchParameterMap().setLoadSynchronous(true).add(param, val);
IBundleProvider result = myObservationDao.search(map);
- assertThat("Got: "+ toUnqualifiedVersionlessIdValues(result), toUnqualifiedVersionlessIdValues(result), containsInAnyOrder(id2.getValue()));
+ assertThat("Got: " + toUnqualifiedVersionlessIdValues(result), toUnqualifiedVersionlessIdValues(result), containsInAnyOrder(id2.getValue()));
}
{
TokenParam v0 = new TokenParam("http://foo", "code1");
@@ -1136,6 +1144,40 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
}
+ /**
+ * See #1174
+ */
+ @Test
+ public void testSearchDateInSavedSearch() {
+ for (int i = 1; i <= 9; i++) {
+ Patient p1 = new Patient();
+ p1.getBirthDateElement().setValueAsString("1980-01-0" + i);
+ String id1 = myPatientDao.create(p1).getId().toUnqualifiedVersionless().getValue();
+ }
+
+ myDaoConfig.setSearchPreFetchThresholds(Lists.newArrayList(3, 6, 10));
+
+ {
+ // Don't load synchronous
+ SearchParameterMap map = new SearchParameterMap();
+ map.setLastUpdated(new DateRangeParam().setUpperBound(new DateParam(ParamPrefixEnum.LESSTHAN, "2022-01-01")));
+ IBundleProvider found = myPatientDao.search(map);
+ Set dates = new HashSet<>();
+ for (int i = 0; i < 9; i++) {
+ Patient nextResource = (Patient) found.getResources(i, i + 1).get(0);
+ dates.add(nextResource.getBirthDateElement().getValueAsString());
+ }
+
+ assertThat(dates, hasItems(
+ "1980-01-01",
+ "1980-01-09"
+ ));
+
+ assertFalse(map.isLoadSynchronous());
+ assertNull(map.getLoadSynchronousUpTo());
+ }
+ }
+
/**
* #222
*/
@@ -1264,8 +1306,12 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
id1 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
+ TestUtil.sleepOneClick();
+
Date betweenTime = new Date();
+ TestUtil.sleepOneClick();
+
IIdType id2;
{
Patient patient = new Patient();
@@ -1439,10 +1485,11 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
id0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
- int sleep = 100;
+ TestUtil.sleepOneClick();
long start = System.currentTimeMillis();
- Thread.sleep(sleep);
+
+ TestUtil.sleepOneClick();
IIdType id1a;
{
@@ -1450,6 +1497,9 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
patient.addIdentifier().setSystem("urn:system").setValue("001");
id1a = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
+
+ TestUtil.sleepOneClick();
+
IIdType id1b;
{
Patient patient = new Patient();
@@ -1461,7 +1511,8 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
ourLog.info("Res 2: {}", myPatientDao.read(id1a, mySrd).getMeta().getLastUpdatedElement().getValueAsString());
ourLog.info("Res 3: {}", myPatientDao.read(id1b, mySrd).getMeta().getLastUpdatedElement().getValueAsString());
- Thread.sleep(sleep);
+ TestUtil.sleepOneClick();
+
long end = System.currentTimeMillis();
SearchParameterMap map;
@@ -1487,7 +1538,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
map = new SearchParameterMap();
map.setLastUpdated(new DateRangeParam(new DateParam(ParamPrefixEnum.GREATERTHAN, startDateTime.getValue()),
- new DateParam(ParamPrefixEnum.LESSTHAN, myPatientDao.read(id1b, mySrd).getMeta().getLastUpdatedElement().getValue())));
+ new DateParam(ParamPrefixEnum.LESSTHAN, TestUtil.getTimestamp(myPatientDao.read(id1b, mySrd)))));
ourLog.info("Searching: {}", map.getLastUpdated());
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), containsInAnyOrder(id1a));
}
@@ -1857,15 +1908,15 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
obs01.setSubject(new Reference(patientId01));
IIdType obsId01 = myObservationDao.create(obs01, mySrd).getId().toUnqualifiedVersionless();
+ TestUtil.sleepOneClick();
Date between = new Date();
- Thread.sleep(10);
Observation obs02 = new Observation();
obs02.setEffective(new DateTimeType(new Date()));
obs02.setSubject(new Reference(locId01));
IIdType obsId02 = myObservationDao.create(obs02, mySrd).getId().toUnqualifiedVersionless();
- Thread.sleep(10);
+ TestUtil.sleepOneClick();
Date after = new Date();
ourLog.info("P1[{}] L1[{}] Obs1[{}] Obs2[{}]", patientId01, locId01, obsId01, obsId02);
@@ -1988,15 +2039,16 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
patient.addName().setFamily("Tester_testSearchStringParam").addGiven("Joe");
pid1 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
+ TestUtil.sleepOneClick();
Date between = new Date();
- Thread.sleep(10);
+
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("002");
patient.addName().setFamily("Tester_testSearchStringParam").addGiven("John");
pid2 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
- Thread.sleep(10);
+ TestUtil.sleepOneClick();
Date after = new Date();
SearchParameterMap params;
@@ -2146,6 +2198,51 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
}
+ @Test
+ public void testSearchLinkToken() {
+ // /fhirapi/MedicationRequest?category=community&identifier=urn:oid:2.16.840.1.113883.3.7418.12.3%7C&intent=order&medication.code:text=calcitriol,hectorol,Zemplar,rocaltrol,vectical,vitamin%20D,doxercalciferol,paricalcitol&status=active,completed
+
+ Medication m = new Medication();
+ m.getCode().setText("valueb");
+ myMedicationDao.create(m);
+
+ MedicationRequest mr = new MedicationRequest();
+ mr.addCategory().addCoding().setCode("community");
+ mr.addIdentifier().setSystem("urn:oid:2.16.840.1.113883.3.7418.12.3").setValue("1");
+ mr.setIntent(MedicationRequest.MedicationRequestIntent.ORDER);
+ mr.setMedication(new Reference(m.getId()));
+ myMedicationRequestDao.create(mr);
+
+ SearchParameterMap sp = new SearchParameterMap();
+ sp.setLoadSynchronous(true);
+ sp.add("category", new TokenParam("community"));
+ sp.add("identifier", new TokenParam("urn:oid:2.16.840.1.113883.3.7418.12.3", "1"));
+ sp.add("intent", new TokenParam("order"));
+ ReferenceParam param1 = new ReferenceParam("valuea").setChain("code:text");
+ ReferenceParam param2 = new ReferenceParam("valueb").setChain("code:text");
+ ReferenceParam param3 = new ReferenceParam("valuec").setChain("code:text");
+ sp.add("medication", new ReferenceOrListParam().addOr(param1).addOr(param2).addOr(param3));
+
+ IBundleProvider retrieved = myMedicationRequestDao.search(sp);
+ assertEquals(1, retrieved.size().intValue());
+
+ List queries = CaptureQueriesListener
+ .getLastNQueries()
+ .stream()
+ .filter(t -> t.getThreadName().equals("main"))
+ .filter(t -> t.getSql(false, false).toLowerCase().contains("select"))
+ .filter(t -> t.getSql(false, false).toLowerCase().contains("token"))
+ .map(t -> t.getSql(true, true))
+ .collect(Collectors.toList());
+
+ ourLog.info("Queries:\n {}", queries.stream().findFirst());
+
+ String searchQuery = queries.get(0);
+ assertEquals(searchQuery, 3, StringUtils.countMatches(searchQuery.toUpperCase(), "HFJ_SPIDX_TOKEN"));
+ assertEquals(searchQuery, 5, StringUtils.countMatches(searchQuery.toUpperCase(), "LEFT OUTER JOIN"));
+ }
+
+
@Test
public void testSearchTokenParam() {
Patient patient = new Patient();
@@ -2966,6 +3063,8 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
tag1id = myOrganizationDao.create(org, mySrd).getId().toUnqualifiedVersionless();
}
+ TestUtil.sleepOneClick();
+
Date betweenDate = new Date();
IIdType tag2id;
@@ -3298,7 +3397,7 @@ public class FhirResourceDaoR4SearchNoFtTest extends BaseJpaR4Test {
"Observation/YES21",
"Observation/YES22",
"Observation/YES23"
- ));
+ ));
}
private void createObservationWithEffective(String theId, String theEffective) {
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoHashesTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoHashesTest.java
index ff2144142d3..9d2c7036f75 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoHashesTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchNoHashesTest.java
@@ -4,6 +4,7 @@ import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap.EverythingModeEnum;
import ca.uhn.fhir.jpa.model.entity.*;
+import ca.uhn.fhir.jpa.util.TestUtil;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
import ca.uhn.fhir.parser.StrictErrorHandler;
@@ -12,7 +13,6 @@ import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
import ca.uhn.fhir.rest.server.exceptions.MethodNotAllowedException;
-import ca.uhn.fhir.util.TestUtil;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.hl7.fhir.instance.model.api.IAnyResource;
@@ -153,16 +153,16 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
List ids;
Date beforeAll = new Date();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
Organization org = new Organization();
org.setName("O1");
org.setId("O1");
myOrganizationDao.update(org);
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
Date beforePatient = new Date();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
Patient p = new Patient();
p.setId("P1");
@@ -170,7 +170,7 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
p.setManagingOrganization(new Reference("Organization/O1"));
myPatientDao.update(p);
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
Date afterAll = new Date();
// Search with between date (should still return Organization even though
@@ -218,7 +218,7 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
myOrganizationDao.update(org);
Date beforeAll = new Date();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
Patient p = new Patient();
p.setId("P1");
@@ -226,17 +226,17 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
p.setManagingOrganization(new Reference("Organization/O1"));
myPatientDao.update(p);
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
Date beforeOrg = new Date();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
org = new Organization();
org.setActive(true);
org.setId("O1");
myOrganizationDao.update(org);
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(100);
+ ca.uhn.fhir.jpa.util.TestUtil.sleepOneClick();
Date afterAll = new Date();
// Everything should come back
@@ -891,6 +891,7 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
patient.addIdentifier().setSystem("urn:system").setValue("001");
id1 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
+ TestUtil.sleepOneClick();
long betweenTime = System.currentTimeMillis();
IIdType id2;
{
@@ -1266,6 +1267,8 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
id1 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
+ TestUtil.sleepOneClick();
+
Date betweenTime = new Date();
IIdType id2;
@@ -1349,8 +1352,7 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
public void testSearchLastUpdatedParam() throws InterruptedException {
String methodName = "testSearchLastUpdatedParam";
- int sleep = 100;
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(sleep);
+ TestUtil.sleepOneClick();
DateTimeType beforeAny = new DateTimeType(new Date(), TemporalPrecisionEnum.MILLI);
IIdType id1a;
@@ -1368,9 +1370,9 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
id1b = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(1100);
+ TestUtil.sleepAtLeast(1100);
DateTimeType beforeR2 = new DateTimeType(new Date(), TemporalPrecisionEnum.MILLI);
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(1100);
+ TestUtil.sleepAtLeast(1100);
IIdType id2;
{
@@ -1441,10 +1443,11 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
id0 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
- int sleep = 100;
+ TestUtil.sleepOneClick();
long start = System.currentTimeMillis();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(sleep);
+
+ TestUtil.sleepOneClick();
IIdType id1a;
{
@@ -1452,6 +1455,9 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
patient.addIdentifier().setSystem("urn:system").setValue("001");
id1a = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
+
+ TestUtil.sleepOneClick();
+
IIdType id1b;
{
Patient patient = new Patient();
@@ -1463,11 +1469,13 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
ourLog.info("Res 2: {}", myPatientDao.read(id1a, mySrd).getMeta().getLastUpdatedElement().getValueAsString());
ourLog.info("Res 3: {}", myPatientDao.read(id1b, mySrd).getMeta().getLastUpdatedElement().getValueAsString());
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(sleep);
+ TestUtil.sleepOneClick();
+
long end = System.currentTimeMillis();
SearchParameterMap map;
Date startDate = new Date(start);
+ TestUtil.sleepOneClick();
Date endDate = new Date(end);
DateTimeType startDateTime = new DateTimeType(startDate, TemporalPrecisionEnum.MILLI);
DateTimeType endDateTime = new DateTimeType(endDate, TemporalPrecisionEnum.MILLI);
@@ -1489,7 +1497,7 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
map = new SearchParameterMap();
map.setLastUpdated(new DateRangeParam(new DateParam(ParamPrefixEnum.GREATERTHAN, startDateTime.getValue()),
- new DateParam(ParamPrefixEnum.LESSTHAN, myPatientDao.read(id1b, mySrd).getMeta().getLastUpdatedElement().getValue())));
+ new DateParam(ParamPrefixEnum.LESSTHAN, TestUtil.getTimestamp(myPatientDao.read(id1b, mySrd)))));
ourLog.info("Searching: {}", map.getLastUpdated());
assertThat(toUnqualifiedVersionlessIds(myPatientDao.search(map)), containsInAnyOrder(id1a));
}
@@ -1860,14 +1868,14 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
IIdType obsId01 = myObservationDao.create(obs01, mySrd).getId().toUnqualifiedVersionless();
Date between = new Date();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(10);
+ TestUtil.sleepOneClick();
Observation obs02 = new Observation();
obs02.setEffective(new DateTimeType(new Date()));
obs02.setSubject(new Reference(locId01));
IIdType obsId02 = myObservationDao.create(obs02, mySrd).getId().toUnqualifiedVersionless();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(10);
+ TestUtil.sleepOneClick();
Date after = new Date();
ourLog.info("P1[{}] L1[{}] Obs1[{}] Obs2[{}]", patientId01, locId01, obsId01, obsId02);
@@ -1990,15 +1998,16 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
patient.addName().setFamily("Tester_testSearchStringParam").addGiven("Joe");
pid1 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
+ TestUtil.sleepOneClick();
Date between = new Date();
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(10);
+ TestUtil.sleepOneClick();
{
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("002");
patient.addName().setFamily("Tester_testSearchStringParam").addGiven("John");
pid2 = myPatientDao.create(patient, mySrd).getId().toUnqualifiedVersionless();
}
- ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast(10);
+ TestUtil.sleepOneClick();
Date after = new Date();
SearchParameterMap params;
@@ -2945,6 +2954,8 @@ public class FhirResourceDaoR4SearchNoHashesTest extends BaseJpaR4Test {
tag1id = myOrganizationDao.create(org, mySrd).getId().toUnqualifiedVersionless();
}
+ TestUtil.sleepOneClick();
+
Date betweenDate = new Date();
IIdType tag2id;
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchPageExpiryTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchPageExpiryTest.java
index aa99e4dbb4b..1dd6c8a479d 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchPageExpiryTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4SearchPageExpiryTest.java
@@ -6,6 +6,7 @@ import ca.uhn.fhir.jpa.dao.data.ISearchDao;
import ca.uhn.fhir.jpa.entity.Search;
import ca.uhn.fhir.jpa.entity.SearchStatusEnum;
import ca.uhn.fhir.jpa.search.StaleSearchDeletingSvcImpl;
+import ca.uhn.fhir.jpa.util.TestUtil;
import ca.uhn.fhir.util.StopWatch;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.StringParam;
@@ -29,7 +30,6 @@ import javax.annotation.Nullable;
import java.util.Date;
import java.util.concurrent.atomic.AtomicLong;
-import static ca.uhn.fhir.jpa.util.TestUtil.sleepAtLeast;
import static org.hamcrest.Matchers.containsInAnyOrder;
import static org.junit.Assert.*;
@@ -100,7 +100,7 @@ public class FhirResourceDaoR4SearchPageExpiryTest extends BaseJpaR4Test {
}
assertEquals(searchUuid1, searchUuid2);
- sleepAtLeast(501);
+ TestUtil.sleepAtLeast(501);
// We're now past 500ms so we shouldn't reuse the search
@@ -274,7 +274,7 @@ public class FhirResourceDaoR4SearchPageExpiryTest extends BaseJpaR4Test {
}
assertEquals(searchUuid1, searchUuid2);
- sleepAtLeast(501);
+ TestUtil.sleepAtLeast(501);
// We're now past 500ms so we shouldn't reuse the search
@@ -360,7 +360,7 @@ public class FhirResourceDaoR4SearchPageExpiryTest extends BaseJpaR4Test {
}
});
if (search == null) {
- sleepAtLeast(100);
+ TestUtil.sleepAtLeast(100);
}
}
assertNotNull("Search " + bundleProvider.getUuid() + " not found on disk after 10 seconds", search);
@@ -407,7 +407,7 @@ public class FhirResourceDaoR4SearchPageExpiryTest extends BaseJpaR4Test {
for (int i = 0; i < 20 && search == null; i++) {
search = theSearchEntityDao.findByUuid(theUuid);
if (search == null || search.getStatus() == SearchStatusEnum.LOADING) {
- sleepAtLeast(100);
+ TestUtil.sleepAtLeast(100);
}
}
assertNotNull(search);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4Test.java
index f75d4a5fbba..ea6c924d38b 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4Test.java
@@ -10,6 +10,7 @@ import ca.uhn.fhir.jpa.model.entity.*;
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
+import ca.uhn.fhir.jpa.util.TestUtil;
import ca.uhn.fhir.model.api.Include;
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
@@ -20,7 +21,6 @@ import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.exceptions.*;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
-import ca.uhn.fhir.util.TestUtil;
import com.google.common.base.Charsets;
import com.google.common.collect.Lists;
import org.apache.commons.io.IOUtils;
@@ -3159,16 +3159,22 @@ public class FhirResourceDaoR4Test extends BaseJpaR4Test {
p.addName().setFamily(methodName);
IIdType id1 = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
+ TestUtil.sleepOneClick();
+
p = new Patient();
p.addIdentifier().setSystem("urn:system2").setValue(methodName);
p.addName().setFamily(methodName);
IIdType id2 = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
+ TestUtil.sleepOneClick();
+
p = new Patient();
p.addIdentifier().setSystem("urn:system3").setValue(methodName);
p.addName().setFamily(methodName);
IIdType id3 = myPatientDao.create(p, mySrd).getId().toUnqualifiedVersionless();
+ TestUtil.sleepOneClick();
+
p = new Patient();
p.addIdentifier().setSystem("urn:system4").setValue(methodName);
p.addName().setFamily(methodName);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UniqueSearchParamTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UniqueSearchParamTest.java
index 34a042446d0..c8cbded65c3 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UniqueSearchParamTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UniqueSearchParamTest.java
@@ -8,7 +8,6 @@ import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
import ca.uhn.fhir.jpa.searchparam.SearchParamConstants;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
-import ca.uhn.fhir.jpa.util.JpaConstants;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.DateParam;
import ca.uhn.fhir.rest.param.TokenParam;
@@ -97,7 +96,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
.setValue(new BooleanType(true));
mySearchParameterDao.update(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
SearchBuilder.resetLastHandlerMechanismForUnitTest();
}
@@ -139,7 +138,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
.setUrl(SearchParamConstants.EXT_SP_UNIQUE)
.setValue(new BooleanType(true));
mySearchParameterDao.update(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
}
@@ -168,7 +167,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
.setUrl(SearchParamConstants.EXT_SP_UNIQUE)
.setValue(new BooleanType(true));
mySearchParameterDao.update(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
}
@@ -197,7 +196,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
.setUrl(SearchParamConstants.EXT_SP_UNIQUE)
.setValue(new BooleanType(true));
mySearchParameterDao.update(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
}
@@ -226,7 +225,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
.setUrl(SearchParamConstants.EXT_SP_UNIQUE)
.setValue(new BooleanType(true));
mySearchParameterDao.update(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
}
private void createUniqueNameAndManagingOrganizationSps() {
@@ -264,7 +263,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
.setValue(new BooleanType(true));
mySearchParameterDao.update(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
}
private void createUniqueObservationSubjectDateCode() {
@@ -316,13 +315,13 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
.setValue(new BooleanType(true));
mySearchParameterDao.update(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
}
@Test
public void testDetectUniqueSearchParams() {
createUniqueBirthdateAndGenderSps();
- List params = mySearchParamRegsitry.getActiveUniqueSearchParams("Patient");
+ List params = mySearchParamRegistry.getActiveUniqueSearchParams("Patient");
assertEquals(1, params.size());
assertTrue(params.get(0).isUnique());
@@ -474,7 +473,7 @@ public class FhirResourceDaoR4UniqueSearchParamTest extends BaseJpaR4Test {
myResourceIndexedCompositeStringUniqueDao.deleteAll();
- assertEquals(1, mySearchParamRegsitry.getActiveUniqueSearchParams("Observation").size());
+ assertEquals(1, mySearchParamRegistry.getActiveUniqueSearchParams("Observation").size());
myResourceReindexingSvc.markAllResourcesForReindexing();
myResourceReindexingSvc.forceReindexingPass();
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UpdateTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UpdateTest.java
index aa6008ccc73..9301cbd1c59 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UpdateTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/FhirResourceDaoR4UpdateTest.java
@@ -2,6 +2,7 @@ package ca.uhn.fhir.jpa.dao.r4;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
+import ca.uhn.fhir.jpa.util.TestUtil;
import ca.uhn.fhir.model.primitive.InstantDt;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.RestOperationTypeEnum;
@@ -12,7 +13,6 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.ResourceNotFoundException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor.ActionRequestDetails;
-import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.instance.model.api.IBaseResource;
import org.hl7.fhir.instance.model.api.IIdType;
import org.hl7.fhir.r4.model.*;
@@ -313,12 +313,15 @@ public class FhirResourceDaoR4UpdateTest extends BaseJpaR4Test {
assertEquals("1", outcome.getId().getVersionIdPart());
+ TestUtil.sleepOneClick();
+
Date now = new Date();
+
Patient retrieved = myPatientDao.read(outcome.getId(), mySrd);
- InstantType updated = retrieved.getMeta().getLastUpdatedElement().copy();
+ InstantType updated = TestUtil.getTimestamp(retrieved);
assertTrue(updated.before(now));
- Thread.sleep(1000);
+ TestUtil.sleepOneClick();
reset(myInterceptor);
retrieved.getIdentifier().get(0).setValue("002");
@@ -335,17 +338,18 @@ public class FhirResourceDaoR4UpdateTest extends BaseJpaR4Test {
assertEquals("Patient", details.getResourceType());
assertEquals(Patient.class, details.getResource().getClass());
+ TestUtil.sleepOneClick();
Date now2 = new Date();
Patient retrieved2 = myPatientDao.read(outcome.getId().toVersionless(), mySrd);
assertEquals("2", retrieved2.getIdElement().getVersionIdPart());
assertEquals("002", retrieved2.getIdentifier().get(0).getValue());
- InstantType updated2 = retrieved2.getMeta().getLastUpdatedElement();
+ InstantType updated2 = TestUtil.getTimestamp(retrieved2);
assertTrue(updated2.after(now));
assertTrue(updated2.before(now2));
- Thread.sleep(2000);
+ TestUtil.sleepOneClick();
/*
* Get history
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/SearchParamExtractorR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/SearchParamExtractorR4Test.java
index e34761975e2..3597e4b0b99 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/SearchParamExtractorR4Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/dao/r4/SearchParamExtractorR4Test.java
@@ -7,7 +7,6 @@ import ca.uhn.fhir.jpa.model.entity.*;
import ca.uhn.fhir.jpa.searchparam.JpaRuntimeSearchParam;
import ca.uhn.fhir.jpa.searchparam.extractor.PathAndRef;
import ca.uhn.fhir.jpa.searchparam.extractor.SearchParamExtractorR4;
-import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamProvider;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.r4.hapi.ctx.DefaultProfileValidationSupport;
@@ -71,11 +70,6 @@ public class SearchParamExtractorR4Test {
throw new UnsupportedOperationException();
}
- @Override
- public void refreshCacheIfNecessary() {
- // nothing
- }
-
@Override
public void requestRefresh() {
// nothing
@@ -90,11 +84,6 @@ public class SearchParamExtractorR4Test {
public Collection getSearchParamsByResourceType(RuntimeResourceDefinition theResourceDef) {
return null;
}
-
- @Override
- public void setSearchParamProviderForUnitTest(ISearchParamProvider theSearchParamProvider) {
- // nothing
- }
};
}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/SystemProviderDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/SystemProviderDstu2Test.java
index ae52fbdfcd3..af487089ba1 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/SystemProviderDstu2Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/SystemProviderDstu2Test.java
@@ -211,9 +211,11 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
obs.getCode().setText("ZXCVBNM ASDFGHJKL QWERTYUIOPASDFGHJKL");
myObservationDao.update(obs, mySrd);
+ // Try to wait for the indexing to complete
+ waitForSize(2, ()-> fetchSuggestionCount(ptId));
+
HttpGet get = new HttpGet(ourServerBase + "/$suggest-keywords?context=Patient/" + ptId.getIdPart() + "/$everything&searchParam=_content&text=zxc&_pretty=true&_format=xml");
- CloseableHttpResponse http = ourHttpClient.execute(get);
- try {
+ try (CloseableHttpResponse http = ourHttpClient.execute(get)) {
assertEquals(200, http.getStatusLine().getStatusCode());
String output = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
ourLog.info(output);
@@ -225,8 +227,16 @@ public class SystemProviderDstu2Test extends BaseJpaDstu2Test {
assertEquals("score", parameters.getParameter().get(0).getPart().get(1).getName());
assertEquals(new DecimalDt("1.0"), parameters.getParameter().get(0).getPart().get(1).getValue());
- } finally {
- http.close();
+ }
+ }
+
+ private Number fetchSuggestionCount(IIdType thePtId) throws IOException {
+ HttpGet get = new HttpGet(ourServerBase + "/$suggest-keywords?context=Patient/" + thePtId.getIdPart() + "/$everything&searchParam=_content&text=zxc&_pretty=true&_format=xml");
+ try (CloseableHttpResponse http = ourHttpClient.execute(get)) {
+ assertEquals(200, http.getStatusLine().getStatusCode());
+ String output = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
+ Parameters parameters = ourCtx.newXmlParser().parseResource(Parameters.class, output);
+ return parameters.getParameter().size();
}
}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderCustomSearchParamDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderCustomSearchParamDstu3Test.java
index 1297e57e86e..8346d0afc05 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderCustomSearchParamDstu3Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/dstu3/ResourceProviderCustomSearchParamDstu3Test.java
@@ -1,37 +1,43 @@
package ca.uhn.fhir.jpa.provider.dstu3;
-import static org.hamcrest.Matchers.contains;
-import static org.hamcrest.Matchers.containsString;
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-import java.util.*;
-
+import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.entity.ResourceReindexJobEntity;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
-import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
-import org.apache.commons.io.IOUtils;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.hl7.fhir.dstu3.model.*;
-import org.hl7.fhir.dstu3.model.CapabilityStatement.*;
-import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender;
-import org.hl7.fhir.dstu3.model.Observation.ObservationStatus;
-import org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType;
-import org.hl7.fhir.instance.model.api.IIdType;
-import org.junit.*;
-import org.springframework.transaction.TransactionStatus;
-import org.springframework.transaction.support.TransactionCallbackWithoutResult;
-import org.springframework.transaction.support.TransactionTemplate;
-
-import ca.uhn.fhir.jpa.dao.*;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
+import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.gclient.ReferenceClientParam;
import ca.uhn.fhir.rest.gclient.TokenClientParam;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.TestUtil;
+import org.apache.commons.io.IOUtils;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.hl7.fhir.dstu3.model.*;
+import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestComponent;
+import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestResourceComponent;
+import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent;
+import org.hl7.fhir.dstu3.model.Enumerations.AdministrativeGender;
+import org.hl7.fhir.dstu3.model.Observation.ObservationStatus;
+import org.hl7.fhir.dstu3.model.SearchParameter.XPathUsageType;
+import org.hl7.fhir.instance.model.api.IIdType;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.support.TransactionCallbackWithoutResult;
+import org.springframework.transaction.support.TransactionTemplate;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.*;
public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProviderDstu3Test {
@@ -56,7 +62,7 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv
super.beforeResetConfig();
myModelConfig.setDefaultSearchParamsCanBeOverridden(new ModelConfig().isDefaultSearchParamsCanBeOverridden());
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
}
private Map extractSearchParams(CapabilityStatement conformance, String resType) {
@@ -142,7 +148,7 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv
txTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus theStatus) {
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
}
});
@@ -198,7 +204,7 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.RETIRED);
mySearchParameterDao.create(fooSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
conformance = ourClient
.fetchConformance()
@@ -259,7 +265,7 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv
attendingSp.getTarget().add(new CodeType("Practitioner"));
IIdType spId = mySearchParameterDao.create(attendingSp, mySrd).getId().toUnqualifiedVersionless();
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Practitioner p1 = new Practitioner();
p1.addName().setFamily("P1");
@@ -309,7 +315,7 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv
.resource(eyeColourSp)
.execute();
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p1 = new Patient();
p1.setActive(true);
@@ -351,7 +357,7 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(fooSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient pat = new Patient();
pat.setGender(AdministrativeGender.MALE);
@@ -395,7 +401,7 @@ public class ResourceProviderCustomSearchParamDstu3Test extends BaseResourceProv
fooSp.setStatus(org.hl7.fhir.dstu3.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(fooSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient pat = new Patient();
pat.setGender(AdministrativeGender.MALE);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/AuthorizationInterceptorResourceProviderR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/AuthorizationInterceptorResourceProviderR4Test.java
index 00125a6cbc3..347aab83d0e 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/AuthorizationInterceptorResourceProviderR4Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/AuthorizationInterceptorResourceProviderR4Test.java
@@ -4,6 +4,8 @@ import ca.uhn.fhir.model.primitive.IdDt;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.MethodOutcome;
import ca.uhn.fhir.rest.api.server.RequestDetails;
+import ca.uhn.fhir.rest.client.interceptor.SimpleRequestHeaderInterceptor;
+import ca.uhn.fhir.rest.server.exceptions.AuthenticationException;
import ca.uhn.fhir.rest.server.exceptions.ForbiddenOperationException;
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.interceptor.IServerInterceptor;
@@ -28,6 +30,7 @@ import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import static org.hamcrest.Matchers.in;
import static org.hamcrest.Matchers.startsWith;
import static org.junit.Assert.*;
@@ -148,6 +151,58 @@ public class AuthorizationInterceptorResourceProviderR4Test extends BaseResource
}
+ @Test
+ public void testReadInTransaction() {
+
+ Patient patient = new Patient();
+ patient.addIdentifier().setSystem("http://uhn.ca/mrns").setValue("100");
+ patient.addName().setFamily("Tester").addGiven("Raghad");
+ IIdType id = ourClient.update().resource(patient).conditionalByUrl("Patient?identifier=http://uhn.ca/mrns|100").execute().getId().toUnqualifiedVersionless();
+
+ ourRestServer.registerInterceptor(new AuthorizationInterceptor(PolicyEnum.DENY) {
+ @Override
+ public List buildRuleList(RequestDetails theRequestDetails) {
+ String authHeader = theRequestDetails.getHeader("Authorization");
+ if (!"Bearer AAA".equals(authHeader)) {
+ throw new AuthenticationException("Invalid auth header: " + authHeader);
+ }
+ return new RuleBuilder()
+ .allow().transaction().withAnyOperation().andApplyNormalRules().andThen()
+ .allow().read().resourcesOfType(Patient.class).withAnyId()
+ .build();
+ }
+ });
+
+ SimpleRequestHeaderInterceptor interceptor = new SimpleRequestHeaderInterceptor("Authorization", "Bearer AAA");
+ try {
+ ourClient.registerInterceptor(interceptor);
+
+ Bundle bundle;
+ Bundle responseBundle;
+
+ // Read
+ bundle = new Bundle();
+ bundle.setType(Bundle.BundleType.TRANSACTION);
+ bundle.addEntry().getRequest().setMethod(Bundle.HTTPVerb.GET).setUrl(id.getValue());
+ responseBundle = ourClient.transaction().withBundle(bundle).execute();
+ patient = (Patient) responseBundle.getEntry().get(0).getResource();
+ assertEquals("Tester", patient.getNameFirstRep().getFamily());
+
+ // Search
+ bundle = new Bundle();
+ bundle.setType(Bundle.BundleType.TRANSACTION);
+ bundle.addEntry().getRequest().setMethod(Bundle.HTTPVerb.GET).setUrl("Patient?");
+ responseBundle = ourClient.transaction().withBundle(bundle).execute();
+ responseBundle = (Bundle) responseBundle.getEntry().get(0).getResource();
+ patient = (Patient) responseBundle.getEntry().get(0).getResource();
+ assertEquals("Tester", patient.getNameFirstRep().getFamily());
+
+ } finally {
+ ourClient.unregisterInterceptor(interceptor);
+ }
+
+ }
+
/**
* See #751
*/
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java
index 7d5ec840386..b08bafd86a8 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/BaseResourceProviderR4Test.java
@@ -59,14 +59,14 @@ public abstract class BaseResourceProviderR4Test extends BaseJpaR4Test {
protected static RestfulServer ourRestServer;
protected static String ourServerBase;
protected static SearchParamRegistryR4 ourSearchParamRegistry;
- protected static DatabaseBackedPagingProvider ourPagingProvider;
+ private static DatabaseBackedPagingProvider ourPagingProvider;
protected static ISearchDao mySearchEntityDao;
protected static ISearchCoordinatorSvc mySearchCoordinatorSvc;
- protected static GenericWebApplicationContext ourWebApplicationContext;
- protected static SubscriptionMatcherInterceptor ourSubscriptionMatcherInterceptor;
+ private static GenericWebApplicationContext ourWebApplicationContext;
+ private static SubscriptionMatcherInterceptor ourSubscriptionMatcherInterceptor;
private static Server ourServer;
protected IGenericClient ourClient;
- protected ResourceCountCache ourResourceCountsCache;
+ ResourceCountCache ourResourceCountsCache;
private TerminologyUploaderProviderR4 myTerminologyUploaderProvider;
private Object ourGraphQLProvider;
private boolean ourRestHookSubscriptionInterceptorRequested;
@@ -162,6 +162,7 @@ public abstract class BaseResourceProviderR4Test extends BaseJpaR4Test {
mySearchEntityDao = wac.getBean(ISearchDao.class);
ourSearchParamRegistry = wac.getBean(SearchParamRegistryR4.class);
ourSubscriptionMatcherInterceptor = wac.getBean(SubscriptionMatcherInterceptor.class);
+ ourSubscriptionMatcherInterceptor.start();
myFhirCtx.getRestfulClientFactory().setSocketTimeout(5000000);
@@ -204,7 +205,7 @@ public abstract class BaseResourceProviderR4Test extends BaseJpaR4Test {
fail("Failed to init subscriptions");
}
try {
- mySubscriptionLoader.initSubscriptions();
+ mySubscriptionLoader.syncSubscriptions();
break;
} catch (ResourceVersionConflictException e) {
Thread.sleep(250);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/HookInterceptorR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/HookInterceptorR4Test.java
new file mode 100644
index 00000000000..74c9f355e40
--- /dev/null
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/HookInterceptorR4Test.java
@@ -0,0 +1,110 @@
+package ca.uhn.fhir.jpa.provider.r4;
+
+import ca.uhn.fhir.jpa.model.interceptor.api.Pointcut;
+import ca.uhn.fhir.rest.api.MethodOutcome;
+import ca.uhn.fhir.util.TestUtil;
+import org.hl7.fhir.instance.model.api.IBaseResource;
+import org.hl7.fhir.instance.model.api.IIdType;
+import org.hl7.fhir.r4.model.Patient;
+import org.junit.AfterClass;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+
+public class HookInterceptorR4Test extends BaseResourceProviderR4Test {
+
+ private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(HookInterceptorR4Test.class);
+
+ @Test
+ public void testOP_PRESTORAGE_RESOURCE_CREATED_ModifyResource() {
+ myInterceptorRegistry.registerAnonymousHookForUnitTest(Pointcut.OP_PRESTORAGE_RESOURCE_CREATED, t->{
+ Patient contents = (Patient) t.get(IBaseResource.class, 0);
+ contents.getNameFirstRep().setFamily("NEWFAMILY");
+ });
+
+ Patient p = new Patient();
+ p.getNameFirstRep().setFamily("OLDFAMILY");
+ MethodOutcome outcome = ourClient.create().resource(p).execute();
+
+ // Response reflects change, stored resource also does
+ Patient responsePatient = (Patient) outcome.getResource();
+ assertEquals("NEWFAMILY", responsePatient.getNameFirstRep().getFamily());
+ responsePatient = ourClient.read().resource(Patient.class).withId(outcome.getId()).execute();
+ assertEquals("NEWFAMILY", responsePatient.getNameFirstRep().getFamily());
+
+ }
+
+ @Test
+ public void testOP_PRECOMMIT_RESOURCE_CREATED_ModifyResource() {
+ myInterceptorRegistry.registerAnonymousHookForUnitTest(Pointcut.OP_PRECOMMIT_RESOURCE_CREATED, t->{
+ Patient contents = (Patient) t.get(IBaseResource.class, 0);
+ contents.getNameFirstRep().setFamily("NEWFAMILY");
+ });
+
+ Patient p = new Patient();
+ p.getNameFirstRep().setFamily("OLDFAMILY");
+ MethodOutcome outcome = ourClient.create().resource(p).execute();
+
+ // Response reflects change, stored resource does not
+ Patient responsePatient = (Patient) outcome.getResource();
+ assertEquals("NEWFAMILY", responsePatient.getNameFirstRep().getFamily());
+ responsePatient = ourClient.read().resource(Patient.class).withId(outcome.getId()).execute();
+ assertEquals("OLDFAMILY", responsePatient.getNameFirstRep().getFamily());
+
+ }
+
+ @Test
+ public void testOP_PRESTORAGE_RESOURCE_UPDATED_ModifyResource() {
+ Patient p = new Patient();
+ p.setActive(true);
+ IIdType id = ourClient.create().resource(p).execute().getId();
+
+ myInterceptorRegistry.registerAnonymousHookForUnitTest(Pointcut.OP_PRESTORAGE_RESOURCE_UPDATED, t->{
+ Patient contents = (Patient) t.get(IBaseResource.class, 1);
+ contents.getNameFirstRep().setFamily("NEWFAMILY");
+ });
+
+ p = new Patient();
+ p.setId(id);
+ p.getNameFirstRep().setFamily("OLDFAMILY");
+ MethodOutcome outcome = ourClient.update().resource(p).execute();
+
+ // Response reflects change, stored resource also does
+ Patient responsePatient = (Patient) outcome.getResource();
+ assertEquals("NEWFAMILY", responsePatient.getNameFirstRep().getFamily());
+ responsePatient = ourClient.read().resource(Patient.class).withId(outcome.getId()).execute();
+ assertEquals("NEWFAMILY", responsePatient.getNameFirstRep().getFamily());
+
+ }
+
+ @Test
+ public void testOP_PRECOMMIT_RESOURCE_UPDATED_ModifyResource() {
+ Patient p = new Patient();
+ p.setActive(true);
+ IIdType id = ourClient.create().resource(p).execute().getId();
+
+ myInterceptorRegistry.registerAnonymousHookForUnitTest(Pointcut.OP_PRECOMMIT_RESOURCE_UPDATED, t->{
+ Patient contents = (Patient) t.get(IBaseResource.class, 1);
+ contents.getNameFirstRep().setFamily("NEWFAMILY");
+ });
+
+ p = new Patient();
+ p.setId(id);
+ p.getNameFirstRep().setFamily("OLDFAMILY");
+ MethodOutcome outcome = ourClient.update().resource(p).execute();
+
+ // Response reflects change, stored resource does not
+ Patient responsePatient = (Patient) outcome.getResource();
+ assertEquals("NEWFAMILY", responsePatient.getNameFirstRep().getFamily());
+ responsePatient = ourClient.read().resource(Patient.class).withId(outcome.getId()).execute();
+ assertEquals("OLDFAMILY", responsePatient.getNameFirstRep().getFamily());
+
+ }
+
+ @AfterClass
+ public static void afterClassClearContext() {
+ TestUtil.clearAllStaticFieldsForUnitTest();
+ }
+
+
+}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderCustomSearchParamR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderCustomSearchParamR4Test.java
index 953aed5ef72..a1b8c1aabaf 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderCustomSearchParamR4Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderCustomSearchParamR4Test.java
@@ -1,37 +1,43 @@
package ca.uhn.fhir.jpa.provider.r4;
-import static org.hamcrest.Matchers.contains;
-import static org.hamcrest.Matchers.containsString;
-import static org.junit.Assert.*;
-
-import java.io.IOException;
-import java.util.*;
-
+import ca.uhn.fhir.jpa.dao.BaseHapiFhirDao;
import ca.uhn.fhir.jpa.entity.ResourceReindexJobEntity;
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
-import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
-import org.apache.commons.io.IOUtils;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.hl7.fhir.r4.model.*;
-import org.hl7.fhir.r4.model.CapabilityStatement.*;
-import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender;
-import org.hl7.fhir.r4.model.Observation.ObservationStatus;
-import org.hl7.fhir.r4.model.SearchParameter.XPathUsageType;
-import org.hl7.fhir.instance.model.api.IIdType;
-import org.junit.*;
-import org.springframework.transaction.TransactionStatus;
-import org.springframework.transaction.support.TransactionCallbackWithoutResult;
-import org.springframework.transaction.support.TransactionTemplate;
-
-import ca.uhn.fhir.jpa.dao.*;
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
+import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.gclient.ReferenceClientParam;
import ca.uhn.fhir.rest.gclient.TokenClientParam;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.TestUtil;
+import org.apache.commons.io.IOUtils;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpGet;
+import org.hl7.fhir.instance.model.api.IIdType;
+import org.hl7.fhir.r4.model.*;
+import org.hl7.fhir.r4.model.CapabilityStatement.CapabilityStatementRestComponent;
+import org.hl7.fhir.r4.model.CapabilityStatement.CapabilityStatementRestResourceComponent;
+import org.hl7.fhir.r4.model.CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent;
+import org.hl7.fhir.r4.model.Enumerations.AdministrativeGender;
+import org.hl7.fhir.r4.model.Observation.ObservationStatus;
+import org.hl7.fhir.r4.model.SearchParameter.XPathUsageType;
+import org.junit.After;
+import org.junit.AfterClass;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.transaction.TransactionStatus;
+import org.springframework.transaction.support.TransactionCallbackWithoutResult;
+import org.springframework.transaction.support.TransactionTemplate;
+
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import static org.hamcrest.Matchers.contains;
+import static org.hamcrest.Matchers.containsString;
+import static org.junit.Assert.*;
public class ResourceProviderCustomSearchParamR4Test extends BaseResourceProviderR4Test {
@@ -56,7 +62,7 @@ public class ResourceProviderCustomSearchParamR4Test extends BaseResourceProvide
super.beforeResetConfig();
myModelConfig.setDefaultSearchParamsCanBeOverridden(new ModelConfig().isDefaultSearchParamsCanBeOverridden());
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
}
private Map extractSearchParams(CapabilityStatement conformance, String resType) {
@@ -142,7 +148,7 @@ public class ResourceProviderCustomSearchParamR4Test extends BaseResourceProvide
txTemplate.execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus theStatus) {
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
}
});
@@ -198,7 +204,7 @@ public class ResourceProviderCustomSearchParamR4Test extends BaseResourceProvide
fooSp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.RETIRED);
mySearchParameterDao.create(fooSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
conformance = ourClient
.fetchConformance()
@@ -260,7 +266,7 @@ public class ResourceProviderCustomSearchParamR4Test extends BaseResourceProvide
attendingSp.getTarget().add(new CodeType("Practitioner"));
IIdType spId = mySearchParameterDao.create(attendingSp, mySrd).getId().toUnqualifiedVersionless();
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Practitioner p1 = new Practitioner();
p1.addName().setFamily("P1");
@@ -310,7 +316,7 @@ public class ResourceProviderCustomSearchParamR4Test extends BaseResourceProvide
.resource(eyeColourSp)
.execute();
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient p1 = new Patient();
p1.setActive(true);
@@ -352,7 +358,7 @@ public class ResourceProviderCustomSearchParamR4Test extends BaseResourceProvide
fooSp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(fooSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient pat = new Patient();
pat.setGender(AdministrativeGender.MALE);
@@ -396,7 +402,7 @@ public class ResourceProviderCustomSearchParamR4Test extends BaseResourceProvide
fooSp.setStatus(org.hl7.fhir.r4.model.Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(fooSp, mySrd);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
Patient pat = new Patient();
pat.setGender(AdministrativeGender.MALE);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderInterceptorR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderInterceptorR4Test.java
index 4b644ca3458..138a175e572 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderInterceptorR4Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderInterceptorR4Test.java
@@ -366,6 +366,7 @@ public class ResourceProviderInterceptorR4Test extends BaseResourceProviderR4Tes
}
+
private void transaction(Bundle theBundle) throws IOException {
String resource = myFhirCtx.newXmlParser().encodeResourceToString(theBundle);
HttpPost post = new HttpPost(ourServerBase + "/");
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4CacheTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4CacheTest.java
index 1792f9fe300..dd4eb173b2f 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4CacheTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4CacheTest.java
@@ -2,12 +2,12 @@ package ca.uhn.fhir.jpa.provider.r4;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.search.SearchCoordinatorSvcImpl;
+import ca.uhn.fhir.jpa.util.TestUtil;
import ca.uhn.fhir.parser.StrictErrorHandler;
import ca.uhn.fhir.rest.api.CacheControlDirective;
import ca.uhn.fhir.rest.api.Constants;
import ca.uhn.fhir.rest.client.interceptor.CapturingInterceptor;
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
-import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.r4.model.Bundle;
import org.hl7.fhir.r4.model.Patient;
import org.junit.After;
@@ -160,12 +160,18 @@ public class ResourceProviderR4CacheTest extends BaseResourceProviderR4Test {
Date beforeFirst = new Date();
+ TestUtil.sleepOneClick();
+
Bundle results1 = ourClient.search().forResource("Patient").where(Patient.FAMILY.matches().value("FAM")).returnBundle(Bundle.class).execute();
+
+ TestUtil.sleepOneClick();
+
assertEquals(1, results1.getEntry().size());
assertEquals(1, mySearchEntityDao.count());
assertThat(myCapturingInterceptor.getLastResponse().getHeaders(Constants.HEADER_X_CACHE), empty());
- assertThat(results1.getMeta().getLastUpdated(), greaterThan(beforeFirst));
- assertThat(results1.getMeta().getLastUpdated(), lessThan(new Date()));
+ Date results1Date = TestUtil.getTimestamp(results1).getValue();
+ assertThat(results1Date, greaterThan(beforeFirst));
+ assertThat(results1Date, lessThan(new Date()));
assertThat(results1.getId(), not(blankOrNullString()));
Patient pt2 = new Patient();
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java
index ec5c4fcd125..aee27813903 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/ResourceProviderR4Test.java
@@ -37,6 +37,7 @@ import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
+import ca.uhn.fhir.jpa.util.TestUtil;
import ca.uhn.fhir.rest.api.PreferReturnEnum;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
@@ -116,13 +117,13 @@ import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.rest.server.interceptor.RequestValidatingInterceptor;
import ca.uhn.fhir.util.StopWatch;
-import ca.uhn.fhir.util.TestUtil;
import ca.uhn.fhir.util.UrlUtil;
@SuppressWarnings("Duplicates")
public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(ResourceProviderR4Test.class);
+ public static final int LARGE_NUMBER = 77;
private SearchCoordinatorSvcImpl mySearchCoordinatorSvcRaw;
private CapturingInterceptor myCapturingInterceptor = new CapturingInterceptor();
@@ -198,6 +199,34 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
}
+ @Test
+ public void testSearchFetchPageBeyondEnd() {
+ for (int i = 0; i < 10; i++) {
+ Organization o = new Organization();
+ o.setId("O" + i);
+ o.setName("O" + i);
+ IIdType oid = ourClient.update().resource(o).execute().getId().toUnqualifiedVersionless();
+ }
+
+ Bundle output = ourClient
+ .search()
+ .forResource("Organization")
+ .count(3)
+ .returnBundle(Bundle.class)
+ .execute();
+
+ String nextPageUrl = output.getLink("next").getUrl();
+ String url = nextPageUrl.replace("_getpagesoffset=3", "_getpagesoffset=999");
+ ourLog.info("Going to request URL: {}", url);
+
+ output = ourClient
+ .loadPage()
+ .byUrl(url)
+ .andReturnBundle(Bundle.class)
+ .execute();
+ assertEquals(0, output.getEntry().size());
+
+ }
@Test
public void testDeleteConditional() {
@@ -945,6 +974,19 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
}
}
+
+ @Test
+ @Ignore
+ public void testQuery() throws IOException {
+ ourLog.info("** Performing Search");
+ HttpGet read = new HttpGet(ourServerBase + "/MedicationRequest?category=community&identifier=urn:oid:2.16.840.1.113883.3.7418.12.3%7C&intent=order&medication.code:text=calcitriol,hectorol,Zemplar,rocaltrol,vectical,vitamin%20D,doxercalciferol,paricalcitol&status=active,completed");
+ try (CloseableHttpResponse response = ourHttpClient.execute(read)) {
+ ourLog.info(response.toString());
+ }
+ ourLog.info("** DONE Performing Search");
+
+ }
+
@Test
public void testDeleteResourceConditional1() throws IOException {
String methodName = "testDeleteResourceConditional1";
@@ -1714,7 +1756,7 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
p.setActive(true);
IIdType id = ourClient.create().resource(p).execute().getId().toUnqualifiedVersionless();
- for (int i = 1; i < 77; i++) {
+ for (int i = 1; i < LARGE_NUMBER; i++) {
Observation obs = new Observation();
obs.setId("A" + StringUtils.leftPad(Integer.toString(i), 2, '0'));
obs.setSubject(new Reference(id));
@@ -1752,8 +1794,8 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
}
assertThat(ids, hasItem(id.getIdPart()));
- assertEquals(77, ids.size());
- for (int i = 1; i < 77; i++) {
+ assertEquals(LARGE_NUMBER, ids.size());
+ for (int i = 1; i < LARGE_NUMBER; i++) {
assertThat(ids.size() + " ids: " + ids, ids, hasItem("A" + StringUtils.leftPad(Integer.toString(i), 2, '0')));
}
}
@@ -3646,6 +3688,8 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
Search search1 = newTxTemplate().execute(theStatus -> mySearchEntityDao.findByUuid(uuid1));
Date lastReturned1 = search1.getSearchLastReturned();
+ TestUtil.sleepOneClick();
+
Bundle result2 = ourClient
.search()
.forResource("Organization")
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/SystemProviderR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/SystemProviderR4Test.java
index 137d05f9492..3c4300011c7 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/SystemProviderR4Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/provider/r4/SystemProviderR4Test.java
@@ -279,6 +279,9 @@ public class SystemProviderR4Test extends BaseJpaR4Test {
obs.getCode().setText("ZXCVBNM ASDFGHJKL QWERTYUIOPASDFGHJKL");
myObservationDao.update(obs, mySrd);
+ // Try to wait for the indexing to complete
+ waitForSize(2, ()-> fetchSuggestionCount(ptId));
+
HttpGet get = new HttpGet(ourServerBase + "/$suggest-keywords?context=Patient/" + ptId.getIdPart() + "/$everything&searchParam=_content&text=zxc&_pretty=true&_format=xml");
CloseableHttpResponse http = ourHttpClient.execute(get);
try {
@@ -298,6 +301,16 @@ public class SystemProviderR4Test extends BaseJpaR4Test {
}
}
+ private Number fetchSuggestionCount(IIdType thePtId) throws IOException {
+ HttpGet get = new HttpGet(ourServerBase + "/$suggest-keywords?context=Patient/" + thePtId.getIdPart() + "/$everything&searchParam=_content&text=zxc&_pretty=true&_format=xml");
+ try (CloseableHttpResponse http = ourHttpClient.execute(get)) {
+ assertEquals(200, http.getStatusLine().getStatusCode());
+ String output = IOUtils.toString(http.getEntity().getContent(), StandardCharsets.UTF_8);
+ Parameters parameters = ourCtx.newXmlParser().parseResource(Parameters.class, output);
+ return parameters.getParameter().size();
+ }
+ }
+
@Test
public void testSuggestKeywordsInvalid() throws Exception {
Patient patient = new Patient();
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionsR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionsR4Test.java
index 49a7ea6b1e9..46f47e283a0 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionsR4Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/BaseSubscriptionsR4Test.java
@@ -89,16 +89,22 @@ public abstract class BaseSubscriptionsR4Test extends BaseResourceProviderR4Test
ourHeaders.clear();
// Delete all Subscriptions
- Bundle allSubscriptions = ourClient.search().forResource(Subscription.class).returnBundle(Bundle.class).execute();
- for (IBaseResource next : BundleUtil.toListOfResources(myFhirCtx, allSubscriptions)) {
- ourClient.delete().resource(next).execute();
+ if (ourClient != null) {
+ Bundle allSubscriptions = ourClient.search().forResource(Subscription.class).returnBundle(Bundle.class).execute();
+ for (IBaseResource next : BundleUtil.toListOfResources(myFhirCtx, allSubscriptions)) {
+ ourClient.delete().resource(next).execute();
+ }
+ waitForActivatedSubscriptionCount(0);
}
- waitForActivatedSubscriptionCount(0);
LinkedBlockingQueueSubscribableChannel processingChannel = mySubscriptionMatcherInterceptor.getProcessingChannelForUnitTest();
- processingChannel.clearInterceptorsForUnitTest();
+ if (processingChannel != null) {
+ processingChannel.clearInterceptorsForUnitTest();
+ }
myCountingInterceptor = new CountingInterceptor();
- processingChannel.addInterceptorForUnitTest(myCountingInterceptor);
+ if (processingChannel != null) {
+ processingChannel.addInterceptorForUnitTest(myCountingInterceptor);
+ }
}
@@ -147,9 +153,8 @@ public abstract class BaseSubscriptionsR4Test extends BaseResourceProviderR4Test
observation.setStatus(Observation.ObservationStatus.FINAL);
- MethodOutcome methodOutcome = ourClient.create().resource(observation).execute();
-
- observation.setId(methodOutcome.getId());
+ IIdType id = myObservationDao.create(observation).getId();
+ observation.setId(id);
return observation;
}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/FhirClientSearchParamProviderTest.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/FhirClientSearchParamProviderTest.java
index 6af748eda5d..6385b506216 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/FhirClientSearchParamProviderTest.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/FhirClientSearchParamProviderTest.java
@@ -1,7 +1,6 @@
package ca.uhn.fhir.jpa.subscription;
import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamProvider;
-import ca.uhn.fhir.jpa.searchparam.registry.ISearchParamRegistry;
import ca.uhn.fhir.jpa.subscription.module.standalone.FhirClientSearchParamProvider;
import ca.uhn.fhir.rest.api.MethodOutcome;
import org.hl7.fhir.r4.model.Coding;
@@ -17,8 +16,6 @@ import static org.junit.Assert.assertEquals;
public class FhirClientSearchParamProviderTest extends BaseSubscriptionsR4Test {
- @Autowired
- ISearchParamRegistry mySearchParamRegistry;
@Autowired
ISearchParamProvider origSearchParamProvider;
@@ -44,7 +41,7 @@ public class FhirClientSearchParamProviderTest extends BaseSubscriptionsR4Test {
sp.setXpathUsage(SearchParameter.XPathUsageType.NORMAL);
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
createSubscription(criteria, "application/json");
waitForActivatedSubscriptionCount(1);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/NotificationServlet.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/NotificationServlet.java
new file mode 100644
index 00000000000..7abb32a3831
--- /dev/null
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/NotificationServlet.java
@@ -0,0 +1,39 @@
+package ca.uhn.fhir.jpa.subscription;
+
+import javax.servlet.http.HttpServlet;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+import java.util.concurrent.atomic.AtomicLong;
+
+/**
+ * Receives subscription notification without payloads.
+ */
+public class NotificationServlet extends HttpServlet {
+ private static final long serialVersionUID = 5957950857980374719L;
+
+ private final AtomicLong receivedNotificationCount = new AtomicLong();
+
+ private final List receivedAuthorizationHeaders = Collections.synchronizedList(new ArrayList<>());
+
+ @Override
+ protected void doPost(HttpServletRequest req, HttpServletResponse resp) {
+ receivedNotificationCount.incrementAndGet();
+ receivedAuthorizationHeaders.add(req.getHeader("Authorization"));
+ }
+
+ public long getReceivedNotificationCount() {
+ return receivedNotificationCount.get();
+ }
+
+ public List getReceivedAuthorizationHeaders() {
+ return receivedAuthorizationHeaders;
+ }
+
+ public void reset() {
+ receivedNotificationCount.set(0);
+ receivedAuthorizationHeaders.clear();
+ }
+}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/module/matcher/InMemorySubscriptionMatcherTestR4.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/module/matcher/InMemorySubscriptionMatcherTestR4.java
index 65d3daa91c1..290f2300a9b 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/module/matcher/InMemorySubscriptionMatcherTestR4.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/module/matcher/InMemorySubscriptionMatcherTestR4.java
@@ -4,9 +4,9 @@ import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.config.TestR4Config;
import ca.uhn.fhir.jpa.model.entity.ResourceIndexedSearchParamString;
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
+import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
import ca.uhn.fhir.jpa.subscription.module.ResourceModifiedMessage;
import ca.uhn.fhir.model.api.TemporalPrecisionEnum;
-import ca.uhn.fhir.rest.api.server.IBundleProvider;
import ca.uhn.fhir.rest.param.*;
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
import org.apache.commons.lang3.StringUtils;
@@ -35,28 +35,41 @@ public class InMemorySubscriptionMatcherTestR4 {
@Autowired
InMemorySubscriptionMatcher myInMemorySubscriptionMatcher;
@Autowired
+ SubscriptionStrategyEvaluator mySubscriptionStrategyEvaluator;
+ @Autowired
FhirContext myContext;
- private SubscriptionMatchResult match(IBaseResource resource, SearchParameterMap params) {
- String criteria = params.toNormalizedQueryString(myContext);
- ourLog.info("Criteria: <{}>", criteria);
- return myInMemorySubscriptionMatcher.match(criteria, resource);
- }
-
- private void assertUnsupported(IBaseResource resource, SearchParameterMap params) {
- assertFalse(match(resource, params).supported());
- }
-
- private void assertMatched(IBaseResource resource, SearchParameterMap params) {
+ private void assertMatched(Resource resource, SearchParameterMap params) {
SubscriptionMatchResult result = match(resource, params);
assertTrue(result.getUnsupportedReason(), result.supported());
assertTrue(result.matched());
+ assertEquals(SubscriptionMatchingStrategy.IN_MEMORY, mySubscriptionStrategyEvaluator.determineStrategy(getCriteria(resource, params)));
}
- private void assertNotMatched(IBaseResource resource, SearchParameterMap params) {
+ private void assertNotMatched(Resource resource, SearchParameterMap params) {
SubscriptionMatchResult result = match(resource, params);
assertTrue(result.getUnsupportedReason(), result.supported());
assertFalse(result.matched());
+ assertEquals(SubscriptionMatchingStrategy.IN_MEMORY, mySubscriptionStrategyEvaluator.determineStrategy(getCriteria(resource, params)));
+ }
+
+ private SubscriptionMatchResult match(Resource theResource, SearchParameterMap theParams) {
+ return match(getCriteria(theResource, theParams), theResource);
+ }
+
+ private String getCriteria(Resource theResource, SearchParameterMap theParams) {
+ return theResource.getResourceType().name() + theParams.toNormalizedQueryString(myContext);
+ }
+
+ private SubscriptionMatchResult match(String criteria, Resource theResource) {
+ ourLog.info("Criteria: <{}>", criteria);
+ return myInMemorySubscriptionMatcher.match(criteria, theResource);
+ }
+
+ private void assertUnsupported(Resource resource, SearchParameterMap theParams) {
+ SubscriptionMatchResult result = match(resource, theParams);
+ assertFalse(result.supported());
+ assertEquals(SubscriptionMatchingStrategy.DATABASE, mySubscriptionStrategyEvaluator.determineStrategy(getCriteria(resource, theParams)));
}
/*
@@ -92,7 +105,6 @@ public class InMemorySubscriptionMatcherTestR4 {
SearchParameterMap params = new SearchParameterMap();
params.add("_has", new HasParam("Observation", "subject", "identifier", "urn:system|FOO"));
- String criteria = params.toNormalizedQueryString(myContext);
assertUnsupported(patient, params);
}
@@ -129,7 +141,7 @@ public class InMemorySubscriptionMatcherTestR4 {
TokenParam v0 = new TokenParam("foo", "testSearchCompositeParamN01");
StringParam v1 = new StringParam("testSearchCompositeParamS01");
- CompositeParam val = new CompositeParam(v0, v1);
+ CompositeParam val = new CompositeParam<>(v0, v1);
SearchParameterMap params = new SearchParameterMap().setLoadSynchronous(true).add(Observation.SP_CODE_VALUE_STRING, val);
assertUnsupported(o1, params);
}
@@ -169,11 +181,11 @@ public class InMemorySubscriptionMatcherTestR4 {
}
@Test
- public void testIdNotSupported() {
+ public void testIdSupported() {
Observation o1 = new Observation();
SearchParameterMap params = new SearchParameterMap();
params.add("_id", new StringParam("testSearchForUnknownAlphanumericId"));
- assertUnsupported(o1, params);
+ assertNotMatched(o1, params);
}
@Test
@@ -189,7 +201,7 @@ public class InMemorySubscriptionMatcherTestR4 {
}
@Test
- public void testSearchLastUpdatedParamUnsupported() throws InterruptedException {
+ public void testSearchLastUpdatedParamUnsupported() {
String methodName = "testSearchLastUpdatedParam";
DateTimeType today = new DateTimeType(new Date(), TemporalPrecisionEnum.DAY);
Patient patient = new Patient();
@@ -293,12 +305,12 @@ public class InMemorySubscriptionMatcherTestR4 {
@Test
public void testSearchQuantityWrongParam() {
Condition c1 = new Condition();
- c1.setAbatement(new Range().setLow((SimpleQuantity) new SimpleQuantity().setValue(1L)).setHigh((SimpleQuantity) new SimpleQuantity().setValue(1L)));
+ c1.setAbatement(new Range().setLow(new SimpleQuantity().setValue(1L)).setHigh(new SimpleQuantity().setValue(1L)));
SearchParameterMap params = new SearchParameterMap().setLoadSynchronous(true).add(Condition.SP_ABATEMENT_AGE, new QuantityParam("1"));
assertMatched(c1, params);
Condition c2 = new Condition();
- c2.setOnset(new Range().setLow((SimpleQuantity) new SimpleQuantity().setValue(1L)).setHigh((SimpleQuantity) new SimpleQuantity().setValue(1L)));
+ c2.setOnset(new Range().setLow(new SimpleQuantity().setValue(1L)).setHigh(new SimpleQuantity().setValue(1L)));
params = new SearchParameterMap().add(Condition.SP_ONSET_AGE, new QuantityParam("1"));
assertMatched(c2, params);
@@ -380,13 +392,16 @@ public class InMemorySubscriptionMatcherTestR4 {
params.add(Patient.SP_FAMILY, new StringParam("testSearchNameParam01Fam"));
try {
String criteria = params.toNormalizedQueryString(myContext);
+ CanonicalSubscription subscription = new CanonicalSubscription();
+ subscription.setCriteriaString(criteria);
+ subscription.setIdElement(new IdType("Subscription", 123L));
ResourceModifiedMessage msg = new ResourceModifiedMessage(myContext, patient, ResourceModifiedMessage.OperationTypeEnum.CREATE);
msg.setSubscriptionId("Subscription/123");
msg.setId(new IdType("Patient/ABC"));
- SubscriptionMatchResult result = myInMemorySubscriptionMatcher.match(criteria, msg);
+ SubscriptionMatchResult result = myInMemorySubscriptionMatcher.match(subscription, msg);
fail();
- } catch (InternalErrorException e){
- assertEquals("Failure processing resource ID[Patient/ABC] for subscription ID[Subscription/123]: Invalid resource reference found at path[Patient.managingOrganization] - Does not contain resource type - urn:uuid:13720262-b392-465f-913e-54fb198ff954", e.getMessage());
+ } catch (AssertionError e){
+ assertEquals("Reference at managingOrganization is invalid: urn:uuid:13720262-b392-465f-913e-54fb198ff954", e.getMessage());
}
}
@@ -410,7 +425,7 @@ public class InMemorySubscriptionMatcherTestR4 {
}
@Test
- public void testSearchStringParam() throws Exception {
+ public void testSearchStringParam() {
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester_testSearchStringParam").addGiven("Joe");
@@ -565,13 +580,11 @@ public class InMemorySubscriptionMatcherTestR4 {
@Test
public void testSearchTokenWithNotModifierUnsupported() {
- String male, female;
Patient patient = new Patient();
patient.addIdentifier().setSystem("urn:system").setValue("001");
patient.addName().setFamily("Tester").addGiven("Joe");
patient.setGender(Enumerations.AdministrativeGender.MALE);
- List patients;
SearchParameterMap params;
params = new SearchParameterMap();
@@ -636,7 +649,6 @@ public class InMemorySubscriptionMatcherTestR4 {
o2.setValue(q2);
SearchParameterMap map;
- IBundleProvider found;
QuantityParam param;
map = new SearchParameterMap();
@@ -678,9 +690,7 @@ public class InMemorySubscriptionMatcherTestR4 {
Patient pt1 = new Patient();
pt1.addName().setFamily("ABCDEFGHIJK");
- List ids;
SearchParameterMap map;
- IBundleProvider results;
// Contains = true
map = new SearchParameterMap();
@@ -871,7 +881,7 @@ public class InMemorySubscriptionMatcherTestR4 {
map.add(Observation.SP_DATE, new DateParam("2011-01-02"));
for (Observation obs : nlist) {
-// assertNotMatched(obs, map);
+ assertNotMatched(obs, map);
}
for (Observation obs : ylist) {
ourLog.info("Obs {} has time {}", obs.getId(), obs.getEffectiveDateTimeType().getValue().toString());
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookActivatesPreExistingSubscriptionsR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookActivatesPreExistingSubscriptionsR4Test.java
index 8d34fd1f8c2..aa14fad52c7 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookActivatesPreExistingSubscriptionsR4Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookActivatesPreExistingSubscriptionsR4Test.java
@@ -57,7 +57,7 @@ public class RestHookActivatesPreExistingSubscriptionsR4Test extends BaseResourc
@Before
public void beforeSetSubscriptionActivatingInterceptor() {
SubscriptionActivatingInterceptor.setWaitForSubscriptionActivationSynchronouslyForUnitTest(true);
- mySubscriptionLoader.initSubscriptions();
+ mySubscriptionLoader.syncSubscriptions();
}
@@ -109,7 +109,7 @@ public class RestHookActivatesPreExistingSubscriptionsR4Test extends BaseResourc
createSubscription(criteria2, payload, ourListenerServerBase);
mySubscriptionTestUtil.registerRestHookInterceptor();
- mySubscriptionLoader.initSubscriptions();
+ mySubscriptionLoader.syncSubscriptions();
sendObservation(code, "SNOMED-CT");
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestDstu2Test.java
index 2a79125a84e..e03232a251b 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestDstu2Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestDstu2Test.java
@@ -113,10 +113,8 @@ public class RestHookTestDstu2Test extends BaseResourceProviderDstu2Test {
observation.setStatus(ObservationStatusEnum.FINAL);
- MethodOutcome methodOutcome = ourClient.create().resource(observation).execute();
-
- String observationId = methodOutcome.getId().getIdPart();
- observation.setId(observationId);
+ IIdType id = myObservationDao.create(observation).getId();
+ observation.setId(id);
return observation;
}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestDstu3Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestDstu3Test.java
index 97716aac54f..42bbad344fc 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestDstu3Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestDstu3Test.java
@@ -4,7 +4,10 @@ package ca.uhn.fhir.jpa.subscription.resthook;
import ca.uhn.fhir.context.FhirContext;
import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.provider.dstu3.BaseResourceProviderDstu3Test;
+import ca.uhn.fhir.jpa.subscription.NotificationServlet;
import ca.uhn.fhir.jpa.subscription.SubscriptionTestUtil;
+import ca.uhn.fhir.jpa.subscription.module.cache.SubscriptionConstants;
+import ca.uhn.fhir.jpa.subscription.module.matcher.SubscriptionMatchingStrategy;
import ca.uhn.fhir.rest.annotation.Create;
import ca.uhn.fhir.rest.annotation.ResourceParam;
import ca.uhn.fhir.rest.annotation.Update;
@@ -49,6 +52,8 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
@Autowired
private SubscriptionTestUtil mySubscriptionTestUtil;
+ private static NotificationServlet ourNotificationServlet;
+ private static String ourNotificationListenerServer;
@After
public void afterUnregisterRestHookListener() {
@@ -79,9 +84,15 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
ourCreatedObservations.clear();
ourUpdatedObservations.clear();
ourContentTypes.clear();
+ ourNotificationServlet.reset();
}
- private Subscription createSubscription(String theCriteria, String thePayload, String theEndpoint) throws InterruptedException {
+ private Subscription createSubscription(String criteria, String payload, String endpoint) throws InterruptedException {
+ return createSubscription(criteria, payload, endpoint, null);
+ }
+
+ private Subscription createSubscription(String theCriteria, String thePayload, String theEndpoint,
+ List headers) throws InterruptedException {
Subscription subscription = new Subscription();
subscription.setReason("Monitor new neonatal function (note, age will be determined by the monitor)");
subscription.setStatus(Subscription.SubscriptionStatus.REQUESTED);
@@ -91,15 +102,17 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
channel.setType(Subscription.SubscriptionChannelType.RESTHOOK);
channel.setPayload(thePayload);
channel.setEndpoint(theEndpoint);
+ if (headers != null) {
+ channel.setHeader(headers);
+ }
subscription.setChannel(channel);
MethodOutcome methodOutcome = ourClient.create().resource(subscription).execute();
- subscription.setId(methodOutcome.getId().getIdPart());
mySubscriptionIds.add(methodOutcome.getId());
waitForQueueToDrain();
- return subscription;
+ return (Subscription)methodOutcome.getResource();
}
private Observation sendObservation(String code, String system) {
@@ -120,6 +133,55 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
return observation;
}
+ @Test
+ public void testRestHookSubscription() throws Exception {
+ String code = "1000000050";
+ String criteria1 = "Observation?code=SNOMED-CT|" + code + "&_format=xml";
+ String criteria2 = "Observation?code=SNOMED-CT|" + code + "111&_format=xml";
+
+ createSubscription(criteria1, null, ourNotificationListenerServer,
+ Collections.singletonList(new StringType("Authorization: abc-def")));
+ createSubscription(criteria2, null, ourNotificationListenerServer);
+
+ sendObservation(code, "SNOMED-CT");
+
+ // Should see 1 subscription notification with authorization header
+ waitForSize(1, ourNotificationServlet.getReceivedAuthorizationHeaders());
+ Assert.assertEquals(1, ourNotificationServlet.getReceivedNotificationCount());
+ Assert.assertEquals("abc-def", ourNotificationServlet.getReceivedAuthorizationHeaders().get(0));
+ ourNotificationServlet.reset();
+
+ sendObservation(code, "SNOMED-CT");
+
+ // Should see 1 subscription notification with authorization header
+ waitForSize(1, ourNotificationServlet.getReceivedAuthorizationHeaders());
+ Assert.assertEquals(1, ourNotificationServlet.getReceivedNotificationCount());
+ Assert.assertEquals("abc-def", ourNotificationServlet.getReceivedAuthorizationHeaders().get(0));
+ ourNotificationServlet.reset();
+
+ Observation observationTemp3 = sendObservation(code, "SNOMED-CT");
+
+ /// Should see 1 subscription notification with authorization header
+ waitForSize(1, ourNotificationServlet.getReceivedAuthorizationHeaders());
+ Assert.assertEquals(1, ourNotificationServlet.getReceivedNotificationCount());
+ Assert.assertEquals("abc-def", ourNotificationServlet.getReceivedAuthorizationHeaders().get(0));
+ ourNotificationServlet.reset();
+
+ Observation observation3 = ourClient.read(Observation.class, observationTemp3.getId());
+ CodeableConcept codeableConcept = new CodeableConcept();
+ observation3.setCode(codeableConcept);
+ Coding coding = codeableConcept.addCoding();
+ coding.setCode(code + "111");
+ coding.setSystem("SNOMED-CT");
+ ourClient.update().resource(observation3).withId(observation3.getIdElement()).execute();
+
+ // Should see 2 subscription notifications with and without authorization header
+ waitForSize(1, ourNotificationServlet.getReceivedAuthorizationHeaders());
+ Assert.assertEquals(1, ourNotificationServlet.getReceivedNotificationCount());
+ Assert.assertNull(ourNotificationServlet.getReceivedAuthorizationHeaders().get(0));
+ ourNotificationServlet.reset();
+ }
+
@Test
public void testRestHookSubscriptionApplicationFhirJson() throws Exception {
String payload = "application/fhir+json";
@@ -291,7 +353,7 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
waitForSize(0, ourCreatedObservations);
waitForSize(5, ourUpdatedObservations);
- Assert.assertFalse(subscription1.getId().equals(subscription2.getId()));
+ Assert.assertNotEquals(subscription1.getId(), subscription2.getId());
Assert.assertFalse(observation1.getId().isEmpty());
Assert.assertFalse(observation2.getId().isEmpty());
}
@@ -353,16 +415,70 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
mySubscriptionTestUtil.waitForQueueToDrain();
}
+ @Test
+ public void testSubscriptionActivatesInMemoryTag() throws Exception {
+ String payload = "application/fhir+xml";
+
+ String code = "1000000050";
+ String criteria1 = "Observation?code=SNOMED-CT|" + code + "&_format=xml";
+
+ Subscription subscriptionOrig = createSubscription(criteria1, payload, ourListenerServerBase);
+ IdType subscriptionId = subscriptionOrig.getIdElement();
+
+ assertEquals(Subscription.SubscriptionStatus.REQUESTED, subscriptionOrig.getStatus());
+ List tags = subscriptionOrig.getMeta().getTag();
+ assertEquals(1, tags.size());
+ Coding tag = tags.get(0);
+ assertEquals(SubscriptionConstants.EXT_SUBSCRIPTION_MATCHING_STRATEGY, tag.getSystem());
+ assertEquals(SubscriptionMatchingStrategy.IN_MEMORY.toString(), tag.getCode());
+ assertEquals("In-memory", tag.getDisplay());
+
+ Subscription subscriptionActivated = ourClient.read().resource(Subscription.class).withId(subscriptionId.toUnqualifiedVersionless()).execute();
+ assertEquals(Subscription.SubscriptionStatus.ACTIVE, subscriptionActivated.getStatus());
+ tags = subscriptionActivated.getMeta().getTag();
+ assertEquals(1, tags.size());
+ tag = tags.get(0);
+ assertEquals(SubscriptionConstants.EXT_SUBSCRIPTION_MATCHING_STRATEGY, tag.getSystem());
+ assertEquals(SubscriptionMatchingStrategy.IN_MEMORY.toString(), tag.getCode());
+ assertEquals("In-memory", tag.getDisplay());
+ }
+
+ @Test
+ public void testSubscriptionActivatesDatabaseTag() throws Exception {
+ String payload = "application/fhir+xml";
+
+ Subscription subscriptionOrig = createSubscription("Observation?code=17861-6&context.type=IHD", payload, ourListenerServerBase);
+ IdType subscriptionId = subscriptionOrig.getIdElement();
+
+ List tags = subscriptionOrig.getMeta().getTag();
+ assertEquals(1, tags.size());
+ Coding tag = tags.get(0);
+ assertEquals(SubscriptionConstants.EXT_SUBSCRIPTION_MATCHING_STRATEGY, tag.getSystem());
+ assertEquals(SubscriptionMatchingStrategy.DATABASE.toString(), tag.getCode());
+ assertEquals("Database", tag.getDisplay());
+
+ Subscription subscription = ourClient.read().resource(Subscription.class).withId(subscriptionId.toUnqualifiedVersionless()).execute();
+ assertEquals(Subscription.SubscriptionStatus.ACTIVE, subscription.getStatus());
+ tags = subscription.getMeta().getTag();
+ assertEquals(1, tags.size());
+ tag = tags.get(0);
+ assertEquals(SubscriptionConstants.EXT_SUBSCRIPTION_MATCHING_STRATEGY, tag.getSystem());
+ assertEquals(SubscriptionMatchingStrategy.DATABASE.toString(), tag.getCode());
+ assertEquals("Database", tag.getDisplay());
+ }
+
@BeforeClass
public static void startListenerServer() throws Exception {
ourListenerPort = PortUtil.findFreePort();
ourListenerRestServer = new RestfulServer(FhirContext.forDstu3());
ourListenerServerBase = "http://localhost:" + ourListenerPort + "/fhir/context";
+ ourNotificationListenerServer = "http://localhost:" + ourListenerPort + "/fhir/subscription";
ObservationListener obsListener = new ObservationListener();
ourListenerRestServer.setResourceProviders(obsListener);
ourListenerServer = new Server(ourListenerPort);
+ ourNotificationServlet = new NotificationServlet();
ServletContextHandler proxyHandler = new ServletContextHandler();
proxyHandler.setContextPath("/");
@@ -370,6 +486,9 @@ public class RestHookTestDstu3Test extends BaseResourceProviderDstu3Test {
ServletHolder servletHolder = new ServletHolder();
servletHolder.setServlet(ourListenerRestServer);
proxyHandler.addServlet(servletHolder, "/fhir/context/*");
+ servletHolder = new ServletHolder();
+ servletHolder.setServlet(ourNotificationServlet);
+ proxyHandler.addServlet(servletHolder, "/fhir/subscription");
ourListenerServer.setHandler(proxyHandler);
ourListenerServer.start();
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestR4Test.java
index 3c9dbf46061..6299816a0df 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestR4Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestR4Test.java
@@ -23,6 +23,7 @@ import java.util.concurrent.TimeUnit;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.hasItem;
+import static org.hamcrest.Matchers.matchesPattern;
import static org.junit.Assert.*;
/**
@@ -112,6 +113,39 @@ public class RestHookTestR4Test extends BaseSubscriptionsR4Test {
}
+ @Test
+ public void testPlaceholderReferencesInTransactionAreResolvedCorrectly() throws Exception {
+
+ String payload = "application/fhir+json";
+ String code = "1000000050";
+ String criteria1 = "Observation?";
+ createSubscription(criteria1, payload);
+ waitForActivatedSubscriptionCount(1);
+
+ // Create a transaction that should match
+ Bundle bundle = new Bundle();
+ bundle.setType(Bundle.BundleType.TRANSACTION);
+
+ Patient patient = new Patient();
+ patient.setId(IdType.newRandomUuid());
+ patient.getIdentifierFirstRep().setSystem("foo").setValue("AAA");
+ bundle.addEntry().setResource(patient).getRequest().setMethod(Bundle.HTTPVerb.POST).setUrl("Patient");
+
+ Observation observation = new Observation();
+ observation.getIdentifierFirstRep().setSystem("foo").setValue("1");
+ observation.getCode().addCoding().setCode(code).setSystem("SNOMED-CT");
+ observation.setStatus(Observation.ObservationStatus.FINAL);
+ observation.getSubject().setReference(patient.getId());
+ bundle.addEntry().setResource(observation).getRequest().setMethod(Bundle.HTTPVerb.POST).setUrl("Observation");
+
+ // Send the transaction
+ mySystemDao.transaction(null, bundle);
+
+ waitForSize(1, ourUpdatedObservations);
+
+ assertThat(ourUpdatedObservations.get(0).getSubject().getReference(), matchesPattern("Patient/[0-9]+"));
+ }
+
@Test
public void testUpdatesHaveCorrectMetadataUsingTransactions() throws Exception {
String payload = "application/fhir+json";
@@ -206,7 +240,7 @@ public class RestHookTestR4Test extends BaseSubscriptionsR4Test {
waitForActivatedSubscriptionCount(1);
for (int i = 0; i < 5; i++) {
- int changes = this.mySubscriptionLoader.doInitSubscriptionsForUnitTest();
+ int changes = this.mySubscriptionLoader.doSyncSubscriptionsForUnitTest();
assertEquals(0, changes);
}
}
@@ -874,7 +908,7 @@ public class RestHookTestR4Test extends BaseSubscriptionsR4Test {
sp.setXpathUsage(SearchParameter.XPathUsageType.NORMAL);
sp.setStatus(Enumerations.PublicationStatus.ACTIVE);
mySearchParameterDao.create(sp);
- mySearchParamRegsitry.forceRefresh();
+ mySearchParamRegistry.forceRefresh();
createSubscription(criteria, "application/json");
waitForActivatedSubscriptionCount(1);
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test.java
index 599ee55a986..40794bb4e88 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test.java
@@ -69,7 +69,7 @@ public class RestHookTestWithInterceptorRegisteredToDaoConfigDstu2Test extends B
ourCreatedObservations.clear();
ourUpdatedObservations.clear();
- mySubscriptionLoader.initSubscriptions();
+ mySubscriptionLoader.syncSubscriptions();
}
private void waitForQueueToDrain() throws InterruptedException {
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookWithInterceptorR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookWithInterceptorR4Test.java
new file mode 100644
index 00000000000..441802a9f4a
--- /dev/null
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/subscription/resthook/RestHookWithInterceptorR4Test.java
@@ -0,0 +1,186 @@
+package ca.uhn.fhir.jpa.subscription.resthook;
+
+import ca.uhn.fhir.context.FhirContext;
+import ca.uhn.fhir.jpa.config.StoppableSubscriptionDeliveringRestHookSubscriber;
+import ca.uhn.fhir.jpa.model.interceptor.api.Hook;
+import ca.uhn.fhir.jpa.model.interceptor.api.IInterceptorRegistry;
+import ca.uhn.fhir.jpa.model.interceptor.api.Interceptor;
+import ca.uhn.fhir.jpa.model.interceptor.api.Pointcut;
+import ca.uhn.fhir.jpa.subscription.BaseSubscriptionsR4Test;
+import ca.uhn.fhir.jpa.subscription.module.CanonicalSubscription;
+import ca.uhn.fhir.jpa.subscription.module.subscriber.ResourceDeliveryMessage;
+import ca.uhn.fhir.rest.api.Constants;
+import ca.uhn.fhir.rest.api.MethodOutcome;
+import org.hl7.fhir.r4.model.IdType;
+import org.hl7.fhir.r4.model.Observation;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.test.context.ContextConfiguration;
+
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
+import static org.hamcrest.Matchers.hasItem;
+import static org.junit.Assert.*;
+
+/**
+ * Test the rest-hook subscriptions
+ */
+@ContextConfiguration(classes = {RestHookWithInterceptorR4Test.MyTestCtxConfig.class})
+public class RestHookWithInterceptorR4Test extends BaseSubscriptionsR4Test {
+
+ private static final Logger ourLog = LoggerFactory.getLogger(RestHookWithInterceptorR4Test.class);
+ private static boolean ourNextModifyResourceId;
+ private static boolean ourNextBeforeRestHookDeliveryReturn;
+ private static boolean ourHitBeforeRestHookDelivery;
+ private static boolean ourNextAfterRestHookDeliveryReturn;
+ private static boolean ourHitAfterRestHookDelivery;
+ private static boolean ourNextAddHeader;
+ private static FhirContext ourCtx = FhirContext.forR4();
+
+ @Autowired
+ StoppableSubscriptionDeliveringRestHookSubscriber myStoppableSubscriptionDeliveringRestHookSubscriber;
+
+ @After
+ public void cleanupStoppableSubscriptionDeliveringRestHookSubscriber() {
+ myStoppableSubscriptionDeliveringRestHookSubscriber.setCountDownLatch(null);
+ myStoppableSubscriptionDeliveringRestHookSubscriber.unPause();
+ }
+
+ @Override
+ @Before
+ public void before() throws Exception {
+ super.before();
+ ourNextModifyResourceId = false;
+ ourNextAddHeader = false;
+ ourNextBeforeRestHookDeliveryReturn = true;
+ ourNextAfterRestHookDeliveryReturn = true;
+ ourHitBeforeRestHookDelivery = false;
+ ourHitAfterRestHookDelivery = false;
+ }
+
+ @Test
+ public void testBeforeRestHookDelivery_ModifyResourceId() throws Exception {
+ ourNextModifyResourceId = true;
+
+ // Create a subscription
+ CountDownLatch registerLatch = registerLatchHookInterceptor(1, Pointcut.SUBSCRIPTION_AFTER_ACTIVE_SUBSCRIPTION_REGISTERED);
+ createSubscription("Observation?status=final", "application/fhir+json");
+ registerLatch.await(10, TimeUnit.SECONDS);
+
+ // Creating a matching resource
+ CountDownLatch deliveryLatch = registerLatchHookInterceptor(1, Pointcut.SUBSCRIPTION_AFTER_REST_HOOK_DELIVERY);
+ sendObservation();
+ deliveryLatch.await(10, TimeUnit.SECONDS);
+
+ assertEquals(0, ourCreatedObservations.size());
+ assertEquals(1, ourUpdatedObservations.size());
+ assertEquals(Constants.CT_FHIR_JSON_NEW, ourContentTypes.get(0));
+ assertEquals("Observation/A", ourUpdatedObservations.get(0).getId());
+ assertTrue(ourHitBeforeRestHookDelivery);
+ assertTrue(ourHitAfterRestHookDelivery);
+ }
+
+ @Test
+ public void testBeforeRestHookDelivery_AddHeader() throws Exception {
+ ourNextAddHeader = true;
+
+ // Create a subscription
+ CountDownLatch registerLatch = registerLatchHookInterceptor(1, Pointcut.SUBSCRIPTION_AFTER_ACTIVE_SUBSCRIPTION_REGISTERED);
+ createSubscription("Observation?status=final", "application/fhir+json");
+ registerLatch.await(10, TimeUnit.SECONDS);
+
+ // Creating a matching resource
+ CountDownLatch deliveryLatch = registerLatchHookInterceptor(1, Pointcut.SUBSCRIPTION_AFTER_REST_HOOK_DELIVERY);
+ sendObservation();
+ deliveryLatch.await(10, TimeUnit.SECONDS);
+
+ assertEquals(0, ourCreatedObservations.size());
+ assertEquals(1, ourUpdatedObservations.size());
+ assertEquals(Constants.CT_FHIR_JSON_NEW, ourContentTypes.get(0));
+ assertTrue(ourHitBeforeRestHookDelivery);
+ assertTrue(ourHitAfterRestHookDelivery);
+ assertThat(ourHeaders, hasItem("X-Foo: Bar"));
+ }
+
+
+ @Test
+ public void testBeforeRestHookDelivery_AbortDelivery() throws Exception {
+ ourNextBeforeRestHookDeliveryReturn = false;
+
+ // Create a subscription
+ CountDownLatch registerLatch = registerLatchHookInterceptor(1, Pointcut.SUBSCRIPTION_AFTER_ACTIVE_SUBSCRIPTION_REGISTERED);
+ createSubscription("Observation?status=final", "application/fhir+json");
+ registerLatch.await(10, TimeUnit.SECONDS);
+
+ sendObservation();
+
+ Thread.sleep(1000);
+ assertEquals(0, ourUpdatedObservations.size());
+ }
+
+ protected Observation sendObservation() {
+ Observation observation = new Observation();
+ observation.setStatus(Observation.ObservationStatus.FINAL);
+ MethodOutcome methodOutcome = ourClient.create().resource(observation).execute();
+ observation.setId(methodOutcome.getId());
+ return observation;
+ }
+
+ @Configuration
+ static class MyTestCtxConfig {
+
+ @Autowired
+ private IInterceptorRegistry myInterceptorRegistry;
+
+ @Bean
+ public MyTestInterceptor interceptor() {
+ MyTestInterceptor retVal = new MyTestInterceptor();
+ myInterceptorRegistry.registerInterceptor(retVal);
+ return retVal;
+ }
+
+ }
+
+ /**
+ * Interceptor class
+ */
+ @Interceptor
+ public static class MyTestInterceptor {
+
+ /**
+ * Constructor
+ */
+ public MyTestInterceptor() {
+ ourLog.info("Creating interceptor");
+ }
+
+ @Hook(Pointcut.SUBSCRIPTION_BEFORE_REST_HOOK_DELIVERY)
+ public boolean beforeRestHookDelivery(ResourceDeliveryMessage theDeliveryMessage, CanonicalSubscription theSubscription) {
+ if (ourNextModifyResourceId) {
+ theDeliveryMessage.getPayload(ourCtx).setId(new IdType("Observation/A"));
+ }
+ if (ourNextAddHeader) {
+ theSubscription.addHeader("X-Foo: Bar");
+ }
+
+ ourHitBeforeRestHookDelivery = true;
+ return ourNextBeforeRestHookDeliveryReturn;
+ }
+
+ @Hook(Pointcut.SUBSCRIPTION_AFTER_REST_HOOK_DELIVERY)
+ public boolean afterRestHookDelivery(ResourceDeliveryMessage theDeliveryMessage, CanonicalSubscription theSubscription) {
+ ourHitAfterRestHookDelivery = true;
+ return ourNextAfterRestHookDeliveryReturn;
+ }
+
+ }
+
+
+}
diff --git a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java
index bbec7646802..785de25822c 100644
--- a/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java
+++ b/hapi-fhir-jpaserver-base/src/test/java/ca/uhn/fhir/jpa/term/TerminologySvcImplR4Test.java
@@ -1,5 +1,6 @@
package ca.uhn.fhir.jpa.term;
+import ca.uhn.fhir.jpa.dao.DaoConfig;
import ca.uhn.fhir.jpa.dao.r4.BaseJpaR4Test;
import ca.uhn.fhir.jpa.entity.TermConceptMap;
import ca.uhn.fhir.jpa.entity.TermConceptMapGroup;
@@ -8,12 +9,11 @@ import ca.uhn.fhir.jpa.entity.TermConceptMapGroupElementTarget;
import ca.uhn.fhir.rest.server.exceptions.UnprocessableEntityException;
import ca.uhn.fhir.util.TestUtil;
import org.hl7.fhir.instance.model.api.IIdType;
+import org.hl7.fhir.r4.model.CanonicalType;
import org.hl7.fhir.r4.model.ConceptMap;
import org.hl7.fhir.r4.model.Enumerations.ConceptMapEquivalence;
import org.hl7.fhir.r4.model.UriType;
-import org.junit.AfterClass;
-import org.junit.Rule;
-import org.junit.Test;
+import org.junit.*;
import org.junit.rules.ExpectedException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,11 +32,26 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
public final ExpectedException expectedException = ExpectedException.none();
private IIdType myConceptMapId;
- private void persistConceptMap() {
+ @Before
+ public void before() {
+ myDaoConfig.setAllowExternalReferences(true);
+ }
+
+ @After
+ public void after() {
+ myDaoConfig.setAllowExternalReferences(new DaoConfig().isAllowExternalReferences());
+ }
+
+ private void createAndPersistConceptMap() {
+ ConceptMap conceptMap = createConceptMap();
+ persistConceptMap(conceptMap);
+ }
+
+ private void persistConceptMap(ConceptMap theConceptMap) {
new TransactionTemplate(myTxManager).execute(new TransactionCallbackWithoutResult() {
@Override
protected void doInTransactionWithoutResult(TransactionStatus theStatus) {
- myConceptMapId = myConceptMapDao.create(createConceptMap(), mySrd).getId().toUnqualifiedVersionless();
+ myConceptMapId = myConceptMapDao.create(theConceptMap, mySrd).getId().toUnqualifiedVersionless();
}
});
}
@@ -63,6 +78,17 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
}
+
+ @Test
+ public void testCreateConceptMapWithVirtualSourceSystem() {
+ ConceptMap conceptMap = createConceptMap();
+ conceptMap.getGroup().forEach(t->t.setSource(null));
+ conceptMap.setSource(new CanonicalType("http://hl7.org/fhir/uv/livd/StructureDefinition/loinc-livd"));
+
+ persistConceptMap(conceptMap);
+
+ }
+
@Test
public void testCreateConceptMapWithMissingTargetSystems() {
@@ -113,17 +139,17 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testDuplicateConceptMapUrls() {
- persistConceptMap();
+ createAndPersistConceptMap();
expectedException.expect(UnprocessableEntityException.class);
expectedException.expectMessage("Can not create multiple ConceptMap resources with ConceptMap.url \"http://example.com/my_concept_map\", already have one with resource ID: ConceptMap/" + myConceptMapId.getIdPart());
- persistConceptMap();
+ createAndPersistConceptMap();
}
@Test
public void testStoreTermConceptMapAndChildren() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -301,7 +327,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateByCodeSystemsAndSourceCodeOneToMany() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -355,7 +381,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateByCodeSystemsAndSourceCodeOneToOne() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -429,7 +455,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateByCodeSystemsAndSourceCodeUnmapped() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -482,7 +508,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateUsingPredicatesWithCodeOnly() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -550,7 +576,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateUsingPredicatesWithSourceAndTargetSystem2() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -598,7 +624,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateUsingPredicatesWithSourceAndTargetSystem3() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -658,7 +684,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateUsingPredicatesWithSourceSystem() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -728,7 +754,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateUsingPredicatesWithSourceSystemAndVersion1() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -776,7 +802,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateUsingPredicatesWithSourceSystemAndVersion3() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -836,7 +862,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateUsingPredicatesWithSourceValueSet() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -906,7 +932,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateUsingPredicatesWithTargetValueSet() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -976,7 +1002,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateWithReverse() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -1025,7 +1051,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateWithReverseByCodeSystemsAndSourceCodeUnmapped() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -1048,7 +1074,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateWithReverseUsingPredicatesWithCodeOnly() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -1104,7 +1130,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateWithReverseUsingPredicatesWithSourceAndTargetSystem1() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -1153,7 +1179,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateWithReverseUsingPredicatesWithSourceAndTargetSystem4() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -1202,7 +1228,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateWithReverseUsingPredicatesWithSourceSystem() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -1260,7 +1286,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateWithReverseUsingPredicatesWithSourceSystemAndVersion() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -1320,7 +1346,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateWithReverseUsingPredicatesWithSourceValueSet() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
@@ -1378,7 +1404,7 @@ public class TerminologySvcImplR4Test extends BaseJpaR4Test {
@Test
public void testTranslateWithReverseUsingPredicatesWithTargetValueSet() {
- persistConceptMap();
+ createAndPersistConceptMap();
ConceptMap conceptMap = myConceptMapDao.read(myConceptMapId);
ourLog.info("ConceptMap:\n" + myFhirCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(conceptMap));
diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddIdGeneratorTask.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddIdGeneratorTask.java
index b498db1faeb..3930baa42b4 100644
--- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddIdGeneratorTask.java
+++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddIdGeneratorTask.java
@@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory;
import java.sql.SQLException;
import java.util.Set;
+import java.util.stream.Collectors;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
@@ -78,7 +79,13 @@ public class AddIdGeneratorTask extends BaseTask {
}
if (isNotBlank(sql)) {
- if (JdbcUtils.getSequenceNames(getConnectionProperties()).contains(myGeneratorName)) {
+ Set sequenceNames =
+ JdbcUtils.getSequenceNames(getConnectionProperties())
+ .stream()
+ .map(String::toLowerCase)
+ .collect(Collectors.toSet());
+ ourLog.debug("Currently have sequences: {}", sequenceNames);
+ if (sequenceNames.contains(myGeneratorName.toLowerCase())) {
ourLog.info("Sequence {} already exists - No action performed", myGeneratorName);
return;
}
diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddTableRawSqlTask.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddTableRawSqlTask.java
index 1da758bae16..b273992fae4 100644
--- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddTableRawSqlTask.java
+++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/taskdef/AddTableRawSqlTask.java
@@ -35,6 +35,7 @@ public class AddTableRawSqlTask extends BaseTableTask {
private static final Logger ourLog = LoggerFactory.getLogger(AddTableRawSqlTask.class);
private Map> myDriverToSqls = new HashMap<>();
+ private List myDriverNeutralSqls = new ArrayList<>();
public void addSql(DriverTypeEnum theDriverType, @Language("SQL") String theSql) {
Validate.notNull(theDriverType);
@@ -52,9 +53,11 @@ public class AddTableRawSqlTask extends BaseTableTask {
return;
}
- List sqlStatements = myDriverToSqls.get(getDriverType());
+ List sqlStatements = myDriverToSqls.computeIfAbsent(getDriverType(), t -> new ArrayList<>());
+ sqlStatements.addAll(myDriverNeutralSqls);
+
ourLog.info("Going to create table {} using {} SQL statements", getTableName(), sqlStatements.size());
- getConnectionProperties().getTxTemplate().execute(t->{
+ getConnectionProperties().getTxTemplate().execute(t -> {
JdbcTemplate jdbcTemplate = getConnectionProperties().newJdbcTemplate();
for (String nextSql : sqlStatements) {
@@ -65,4 +68,9 @@ public class AddTableRawSqlTask extends BaseTableTask {
});
}
+
+ public void addSql(String theSql) {
+ Validate.notBlank("theSql must not be null", theSql);
+ myDriverNeutralSqls.add(theSql);
+ }
}
diff --git a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/BaseMigrationTasks.java b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/BaseMigrationTasks.java
index abc4d262037..d041155d70f 100644
--- a/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/BaseMigrationTasks.java
+++ b/hapi-fhir-jpaserver-migrate/src/main/java/ca/uhn/fhir/jpa/migrate/tasks/api/BaseMigrationTasks.java
@@ -329,6 +329,10 @@ public class BaseMigrationTasks {
myTask.addSql(theDriverTypeEnum, theSql);
return this;
}
+
+ public void addSql(@Language("SQL") String theSql) {
+ myTask.addSql(theSql);
+ }
}
public class BuilderAddTableByColumns implements IAcceptsTasks {
diff --git a/hapi-fhir-jpaserver-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/ArbitrarySqlTaskTest.java b/hapi-fhir-jpaserver-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/ArbitrarySqlTaskTest.java
index 9dbce75c8c7..da5da3f13d5 100644
--- a/hapi-fhir-jpaserver-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/ArbitrarySqlTaskTest.java
+++ b/hapi-fhir-jpaserver-migrate/src/test/java/ca/uhn/fhir/jpa/migrate/taskdef/ArbitrarySqlTaskTest.java
@@ -1,6 +1,8 @@
package ca.uhn.fhir.jpa.migrate.taskdef;
+import ca.uhn.fhir.jpa.migrate.tasks.api.BaseMigrationTasks;
import ca.uhn.fhir.jpa.model.entity.SearchParamPresent;
+import ca.uhn.fhir.util.VersionEnum;
import org.junit.Test;
import java.util.List;
@@ -66,4 +68,35 @@ public class ArbitrarySqlTaskTest extends BaseTest {
getMigrator().migrate();
}
+
+ private static class TestUpdateTasks extends BaseMigrationTasks {
+
+ public TestUpdateTasks() {
+ Builder v = forVersion(VersionEnum.V3_5_0);
+ v
+ .addTableRawSql("A")
+ .addSql("delete from TEST_UPDATE_TASK where RES_TYPE = 'Patient'");
+ }
+
+
+ }
+
+
+ @Test
+ public void testUpdateTask() {
+ executeSql("create table TEST_UPDATE_TASK (PID bigint not null, RES_TYPE varchar(255), PARAM_NAME varchar(255))");
+ executeSql("insert into TEST_UPDATE_TASK (PID, RES_TYPE, PARAM_NAME) values (1, 'Patient', 'identifier')");
+
+ List