Merge remote-tracking branch 'origin/master' into ld-20230131-subscription-validating-interceptor-remove-deprecated-methods
This commit is contained in:
commit
0a08c9fbf1
|
@ -80,16 +80,12 @@ stages:
|
|||
module: hapi-fhir-server-mdm
|
||||
- name: hapi_fhir_server_openapi
|
||||
module: hapi-fhir-server-openapi
|
||||
- name: hapi_fhir_serviceloaders
|
||||
module: hapi-fhir-serviceloaders
|
||||
- name: hapi_fhir_caching_api
|
||||
module: hapi-fhir-serviceloaders/hapi-fhir-caching-api
|
||||
- name: hapi_fhir_caching_caffeine
|
||||
module: hapi-fhir-serviceloaders/hapi-fhir-caching-caffeine
|
||||
- name: hapi_fhir_caching_guava
|
||||
module: hapi-fhir-serviceloaders/hapi-fhir-caching-guava
|
||||
- name: hapi_fhir_caching_testing
|
||||
module: hapi-fhir-serviceloaders/hapi-fhir-caching-testing
|
||||
- name: hapi_fhir_spring_boot_autoconfigure
|
||||
module: hapi-fhir-spring-boot/hapi-fhir-spring-boot-autoconfigure
|
||||
- name: hapi_fhir_spring_boot_sample_server_jersey
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -13,9 +14,6 @@
|
|||
|
||||
<name>HAPI FHIR - Deployable Artifact Parent POM</name>
|
||||
|
||||
<dependencies>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
|
@ -120,27 +118,6 @@
|
|||
</ignoredResourcePatterns>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>process-sources</phase>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<logViolationsToConsole>true</logViolationsToConsole>
|
||||
<failsOnError>true</failsOnError>
|
||||
<suppressionsLocation>${maven.multiModuleProjectDirectory}/src/checkstyle/checkstyle_suppressions.xml</suppressionsLocation>
|
||||
<enableRulesSummary>true</enableRulesSummary>
|
||||
<enableSeveritySummary>true</enableSeveritySummary>
|
||||
<consoleOutput>true</consoleOutput>
|
||||
<configLocation>${maven.multiModuleProjectDirectory}/src/checkstyle/checkstyle.xml</configLocation>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
|
@ -208,7 +185,6 @@
|
|||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<!--<goal>aggregate-jar</goal>-->
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
|
@ -252,5 +228,4 @@
|
|||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
</project>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -196,6 +196,62 @@
|
|||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
<version>1.8</version>
|
||||
<configuration>
|
||||
<target>
|
||||
<!--suppress UnresolvedMavenProperty -->
|
||||
<delete dir="${pom.basedir}/target/" includes="checkstyle*"/>
|
||||
</target>
|
||||
</configuration>
|
||||
<inherited>true</inherited>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>delete-module-cache-file</id>
|
||||
<phase>validate</phase>
|
||||
<goals>
|
||||
<goal>run</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>${maven_checkstyle_version}</version>
|
||||
<configuration>
|
||||
<!--suppress UnresolvedMavenProperty -->
|
||||
<configLocation>${maven.multiModuleProjectDirectory}/hapi-fhir-checkstyle/src/checkstyle/hapi-base-checkstyle.xml</configLocation>
|
||||
<!--suppress UnresolvedMavenProperty -->
|
||||
<suppressionsLocation>${maven.multiModuleProjectDirectory}/hapi-fhir-checkstyle/src/checkstyle/hapi-base-checkstyle-suppression.xml</suppressionsLocation>
|
||||
<inputEncoding>UTF-8</inputEncoding>
|
||||
<consoleOutput>true</consoleOutput>
|
||||
</configuration>
|
||||
<inherited>true</inherited>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>hapi-single-module-checkstyle</id>
|
||||
<phase>validate</phase>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-checkstyle</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.puppycrawl.tools</groupId>
|
||||
<artifactId>checkstyle</artifactId>
|
||||
<version>${checkstyle_version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<resource>
|
||||
|
|
|
@ -113,7 +113,9 @@ public enum VersionEnum {
|
|||
V6_2_5,
|
||||
// Dev Build
|
||||
V6_3_0,
|
||||
V6_4_0
|
||||
V6_4_0,
|
||||
V6_5_0,
|
||||
V6_6_0
|
||||
;
|
||||
|
||||
public static VersionEnum latestVersion() {
|
||||
|
|
|
@ -333,7 +333,7 @@ public class FhirValidator {
|
|||
retval.addAll(messages);
|
||||
}
|
||||
} catch (InterruptedException | ExecutionException exp) {
|
||||
throw new InternalErrorException(Msg.code(1975) + exp);
|
||||
throw new InternalErrorException(Msg.code(2246) + exp);
|
||||
}
|
||||
return retval;
|
||||
}
|
||||
|
|
|
@ -4,14 +4,14 @@
|
|||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-bom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
<name>HAPI FHIR BOM</name>
|
||||
|
||||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -18,6 +18,7 @@
|
|||
<dependency>
|
||||
<groupId>com.puppycrawl.tools</groupId>
|
||||
<artifactId>checkstyle</artifactId>
|
||||
<version>${checkstyle_version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-io</groupId>
|
||||
|
@ -34,6 +35,31 @@
|
|||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>3.2.0</version>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>com.puppycrawl.tools</groupId>
|
||||
<artifactId>checkstyle</artifactId>
|
||||
<version>${checkstyle_version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-checkstyle</artifactId>
|
||||
<!-- Remember to bump this when you upgrade the version -->
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
</build>
|
||||
|
||||
<profiles>
|
||||
<!-- For releases, we need to generate javadoc and sources JAR -->
|
||||
<profile>
|
||||
|
@ -75,5 +101,44 @@
|
|||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
<profile>
|
||||
<id>CI</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<version>${maven_checkstyle_version}</version>
|
||||
<configuration>
|
||||
<excludes>**/osgi/**/*, **/.mvn/**/*, **/.mvn_/**/*</excludes>
|
||||
<sourceDirectories>
|
||||
<!--scan base project directory to include all modules-->
|
||||
<!--suppress UnresolvedMavenProperty -->
|
||||
<directory>${maven.multiModuleProjectDirectory}/</directory>
|
||||
</sourceDirectories>
|
||||
<!--suppress UnresolvedMavenProperty -->
|
||||
<configLocation>${maven.multiModuleProjectDirectory}/hapi-fhir-checkstyle/src/checkstyle/hapi-base-checkstyle.xml</configLocation>
|
||||
<!--suppress UnresolvedMavenProperty -->
|
||||
<suppressionsLocation>${maven.multiModuleProjectDirectory}/hapi-fhir-checkstyle/src/checkstyle/hapi-base-checkstyle-suppression.xml</suppressionsLocation>
|
||||
<inputEncoding>UTF-8</inputEncoding>
|
||||
<consoleOutput>true</consoleOutput>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>checkstyle-across-all-modules</id>
|
||||
<phase>install</phase>
|
||||
<goals>
|
||||
<goal>check</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>hapi-single-module-checkstyle</id>
|
||||
<phase>none</phase>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
</profiles>
|
||||
</project>
|
||||
|
|
|
@ -1,10 +1,18 @@
|
|||
<?xml version="1.0"?>
|
||||
|
||||
<!DOCTYPE suppressions PUBLIC
|
||||
"-//Puppy Crawl//DTD Suppressions 1.1//EN"
|
||||
"http://www.puppycrawl.com/dtds/suppressions_1_1.dtd">
|
||||
"-//Checkstyle//DTD SuppressionFilter Configuration 1.2//EN"
|
||||
"https://checkstyle.org/dtds/suppressions_1_2.dtd">
|
||||
|
||||
<suppressions>
|
||||
<suppress files="[/\\]test[/\\]" checks="[a-zA-Z0-9]*" />
|
||||
<suppress files="[/\\]resources[/\\]" checks="[a-zA-Z0-9]*" />
|
||||
<suppress files="[\\/]target[\\/]" checks="[a-zA-Z0-9]*" />
|
||||
<suppress files="[\\/]hapi-fhir-docs[\\/]" checks="[a-zA-Z0-9]*" />
|
||||
<suppress files="[\\/]hapi-fhir-checkstyle[\\/]" checks="[a-zA-Z0-9]*" />
|
||||
<suppress files="[\\/]hapi-fhir-jpaserver-test-utilities[\\/]" checks="[a-zA-Z0-9]*" />
|
||||
<suppress files="[\\/]hapi-tinder-plugin[\\/]" checks="[a-zA-Z0-9]*" />
|
||||
<suppress files="[\\/]osgi[\\/]" checks="[a-zA-Z0-9]*"/>
|
||||
|
||||
<!-- Name suppressions -->
|
||||
<suppress files="Base64BinaryDt\.java" checks="AbstractClassName"/>
|
||||
<!-- TODO KHS cdr instantiates these. Remove them once cdr has been fixed. -->
|
||||
|
@ -16,4 +24,6 @@
|
|||
<suppress files="RequestDetails\.java" checks="AbstractClassName"/>
|
||||
<suppress files="RestfulClientFactory\.java" checks="AbstractClassName"/>
|
||||
<suppress files="MatchUrlService\.java" checks="AbstractClassName"/>
|
||||
<suppress files="BaseController\.java" checks="AbstractClassName"/>
|
||||
|
||||
</suppressions>
|
|
@ -0,0 +1,41 @@
|
|||
<?xml version="1.0"?>
|
||||
<!DOCTYPE module PUBLIC
|
||||
"-//Puppy Crawl//DTD Check Configuration 1.3//EN"
|
||||
"http://www.puppycrawl.com/dtds/configuration_1_3.dtd">
|
||||
|
||||
<module name="Checker">
|
||||
|
||||
<property name="severity" value="error"/>
|
||||
<property name="charset" value="UTF-8"/>
|
||||
<property name="fileExtensions" value="java, properties, xml, js, json"/>
|
||||
|
||||
<module name="TreeWalker">
|
||||
<!-- Run custom HapiErrorCodeCheck to find duplicate error codes -->
|
||||
<module name="ca.uhn.fhir.checks.HapiErrorCodeCheck"/>
|
||||
<!-- Throw error if any FIX ME is left in the code -->
|
||||
<module name="TodoComment">
|
||||
<!-- The (?i) below means Case Insensitive -->
|
||||
<property name="format" value="(?i)FIXME"/>
|
||||
</module>
|
||||
|
||||
<module name="RegexpSinglelineJava">
|
||||
<property name="format" value="System\.out\.println"/>
|
||||
<property name="ignoreComments" value="true"/>
|
||||
</module>
|
||||
<module name="RegexpSinglelineJava">
|
||||
<property name="format" value="org\.jetbrains\.annotations\.NotNull"/>
|
||||
</module>
|
||||
<module name="RegexpSinglelineJava">
|
||||
<property name="format" value="org\.jetbrains\.annotations\.Nullable"/>
|
||||
</module>
|
||||
<!-- Should always use the Spring transactional interface, per: https://stackoverflow.com/questions/26387399/javax-transaction-transactional-vs-org-springframework-transaction-annotation-tr -->
|
||||
<module name="RegexpSinglelineJava">
|
||||
<property name="format" value="javax\.transaction\.Transactional"/>
|
||||
<property name="message"
|
||||
value="Wrong @Transactional annotation used, use instead: org.springframework.transaction.annotation.Transactional"/>
|
||||
</module>
|
||||
<module name="AbstractClassName">
|
||||
<property name="format" value="^(Base|Abstract).+$"/>
|
||||
</module>
|
||||
</module>
|
||||
</module>
|
|
@ -1,6 +1,6 @@
|
|||
package ca.uhn.fhir.checks;
|
||||
|
||||
import com.puppycrawl.tools.checkstyle.StatelessCheck;
|
||||
import com.puppycrawl.tools.checkstyle.FileStatefulCheck;
|
||||
import com.puppycrawl.tools.checkstyle.api.AbstractCheck;
|
||||
import com.puppycrawl.tools.checkstyle.api.DetailAST;
|
||||
import com.puppycrawl.tools.checkstyle.api.TokenTypes;
|
||||
|
@ -9,15 +9,13 @@ import org.slf4j.LoggerFactory;
|
|||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* mvn -P CI checkstyle:check
|
||||
*/
|
||||
@StatelessCheck
|
||||
@FileStatefulCheck
|
||||
public final class HapiErrorCodeCheck extends AbstractCheck {
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(HapiErrorCodeCheck.class);
|
||||
|
||||
private static final Map<Integer, String> ourCodesUsed = new HashMap<>();
|
||||
private static final ErrorCodeCache ourCache = ErrorCodeCache.INSTANCE;
|
||||
|
||||
@Override
|
||||
public int[] getDefaultTokens() {
|
||||
|
@ -42,10 +40,6 @@ public final class HapiErrorCodeCheck extends AbstractCheck {
|
|||
}
|
||||
|
||||
private void validateMessageCode(DetailAST theAst) {
|
||||
// TODO KHS this should be done in the checkstyle plugin pom config, not here
|
||||
if (getFileContents().getFileName().contains("/generated-sources/")) {
|
||||
return;
|
||||
}
|
||||
DetailAST instantiation = theAst.getFirstChild().getFirstChild();
|
||||
// We only expect message codes on new exception instantiations
|
||||
if (TokenTypes.LITERAL_NEW != instantiation.getType()) {
|
||||
|
@ -68,14 +62,13 @@ public final class HapiErrorCodeCheck extends AbstractCheck {
|
|||
DetailAST numberNode = msgNode.getParent().getNextSibling().getFirstChild().getFirstChild();
|
||||
if (TokenTypes.NUM_INT == numberNode.getType()) {
|
||||
Integer code = Integer.valueOf(numberNode.getText());
|
||||
if (ourCodesUsed.containsKey(code)) {
|
||||
if (ourCache.containsKey(code)) {
|
||||
log(theAst.getLineNo(), "Two different exception messages call Msg.code(" +
|
||||
code +
|
||||
"). Each thrown exception throw call Msg.code() with a different code. " +
|
||||
"Previously found at: " + ourCodesUsed.get(code));
|
||||
code + "). \nEach thrown exception must call Msg.code() with a different code. " +
|
||||
"\nPreviously found at: " + ourCache.get(code));
|
||||
} else {
|
||||
String location = getFileContents().getFileName() + ":" + instantiation.getLineNo() + ":" + instantiation.getColumnNo() + "(" + code + ")";
|
||||
ourCodesUsed.put(code, location);
|
||||
String location = getFilePath() + ":" + instantiation.getLineNo() + ":" + instantiation.getColumnNo() + "(" + code + ")";
|
||||
ourCache.put(code, location);
|
||||
}
|
||||
} else {
|
||||
log(theAst.getLineNo(), "Called Msg.code() with a non-integer argument");
|
||||
|
@ -110,5 +103,30 @@ public final class HapiErrorCodeCheck extends AbstractCheck {
|
|||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public enum ErrorCodeCache {
|
||||
INSTANCE;
|
||||
|
||||
private static final Map<Integer, String> ourCodesUsed = new HashMap<>();
|
||||
|
||||
ErrorCodeCache() {
|
||||
}
|
||||
|
||||
public boolean containsKey(Integer s) {
|
||||
return ourCodesUsed.containsKey(s);
|
||||
}
|
||||
|
||||
public String get(Integer i) {
|
||||
return ourCodesUsed.get(i);
|
||||
}
|
||||
|
||||
public String put(Integer code, String location) {
|
||||
return ourCodesUsed.put(code, location);
|
||||
}
|
||||
|
||||
public Set<Integer> keySet() {
|
||||
return ourCodesUsed.keySet();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -44,12 +44,13 @@ class HapiErrorCodeCheckTest {
|
|||
// validate
|
||||
String[] errorLines = errors.toString().split("\r?\n");
|
||||
Arrays.stream(errorLines).forEach(ourLog::info);
|
||||
assertEquals(2, errorLines.length);
|
||||
assertEquals(4, errorLines.length);
|
||||
assertThat(errorLines[0], startsWith("[ERROR] "));
|
||||
assertThat(errorLines[0], endsWith("BadClass.java:7: Exception thrown that does not call Msg.code() [HapiErrorCode]"));
|
||||
assertThat(errorLines[1], startsWith("[ERROR] "));
|
||||
assertThat(errorLines[1], containsString("BadClass.java:11: Two different exception messages call Msg.code(2). Each thrown exception throw call Msg.code() with a different code."));
|
||||
assertThat(errorLines[1], containsString("BadClass.java:9:9"));
|
||||
assertThat(errorLines[1], containsString("Two different exception messages call Msg.code(2258)."));
|
||||
assertThat(errorLines[2], containsString("Each thrown exception must call Msg.code() with a different code."));
|
||||
assertThat(errorLines[3], containsString("Previously found at:"));
|
||||
}
|
||||
|
||||
private Checker buildChecker() throws CheckstyleException {
|
||||
|
|
|
@ -2,16 +2,15 @@ public class BadClass {
|
|||
public void init() throws Exception {
|
||||
int i = 1;
|
||||
if (i == 0) {
|
||||
throw new MessagingException(theMessage, Msg.code(6) + "Failure handling subscription payload", e);
|
||||
throw new MessagingException(theMessage, Msg.code(2259) + "Failure handling subscription payload", e);
|
||||
} else if (i == 1) {
|
||||
throw new RuntimeException("nocode");
|
||||
} else if (i == 2) {
|
||||
throw new RuntimeException(Msg.code(2) + "duplicate code");
|
||||
throw new RuntimeException(Msg.code(2258) + "duplicate code");
|
||||
} else if (i == 3) {
|
||||
throw new RuntimeException(Msg.code(2) + "duplicate code");
|
||||
} else if (i == 4) {
|
||||
throw new RuntimeException(Msg.code(1) + "good");
|
||||
throw new RuntimeException(Msg.code(2258) + "duplicate code");
|
||||
}
|
||||
|
||||
ClassCastException e = new ClassCastException();
|
||||
throwException(i, e);
|
||||
}
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -531,7 +531,7 @@ public abstract class BaseCommand implements Comparable<BaseCommand> {
|
|||
return Optional.of(new TlsAuthentication(keyStoreInfo, trustStoreInfo));
|
||||
}
|
||||
catch(Exception e){
|
||||
throw new RuntimeException(Msg.code(2115)+"Could not create TLS configuration options", e);
|
||||
throw new RuntimeException(Msg.code(2253)+"Could not create TLS configuration options", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -48,7 +48,7 @@ public class ValidationSupportChainCreator {
|
|||
chain.addValidationSupport(localFileValidationSupport);
|
||||
chain.addValidationSupport(new SnapshotGeneratingValidationSupport(ctx));
|
||||
} catch (IOException e) {
|
||||
throw new RuntimeException(Msg.code(2207) + "Failed to load local profile.", e);
|
||||
throw new RuntimeException(Msg.code(2254) + "Failed to load local profile.", e);
|
||||
}
|
||||
}
|
||||
if (commandLine.hasOption("r")) {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-cli</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../../hapi-deployable-pom</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -0,0 +1,7 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 4528
|
||||
title: "Three database columns have been changed from type TEXT to type OID
|
||||
when running in Postgres:
|
||||
BT2_JOB_INSTANCE.PARAMS_JSON_LOB, BT2_JOB_INSTANCE.REPORT, and BT2_WORK_CHUNK.CHUNK_DATA.
|
||||
This prevents VACUUM erasing binary objects that are still in use."
|
|
@ -0,0 +1,5 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 4483
|
||||
title: "The OverridePathBasedReferentialIntegrityForDeletesInterceptor now works on partitioned
|
||||
servers. Thanks to GitHub user @JorisHeadease for the pull request!"
|
|
@ -0,0 +1,6 @@
|
|||
---
|
||||
type: fix
|
||||
issue: 4509
|
||||
title: "References to the patient/subject in IPS documents generated using the $summary
|
||||
operation were not replaced with the bundle-local UUID assigned to the patient. Also,
|
||||
some dangling references were left in the generated bundle. This has been corrected."
|
|
@ -0,0 +1,3 @@
|
|||
---
|
||||
release-date: "2023-05-18"
|
||||
codename: "TBD"
|
|
@ -74,6 +74,37 @@ myDaoConfig.getTreatReferencesAsLogical().add("http://mysystem.com/ValueSet/cats
|
|||
myDaoConfig.getTreatReferencesAsLogical().add("http://mysystem.com/mysystem-vs-*");
|
||||
```
|
||||
|
||||
## Referential Integrity
|
||||
|
||||
Enabling referential integrity will ensure that reference values exist in the database. If the referenced entity does
|
||||
not exist, the server will return an error.
|
||||
|
||||
It is important to note that referential integrity is not enforced on database-level. The referential integrity check
|
||||
*only* validates references that are indexed by a `SearchParameter`.
|
||||
|
||||
### Enabling Referential Integrity
|
||||
Referential integrity can be configured on two levels: `write` and `delete`.
|
||||
|
||||
#### JPA Server
|
||||
```java
|
||||
@Bean
|
||||
public DaoConfig daoConfig() {
|
||||
DaoConfig retVal = new DaoConfig();
|
||||
// ... other config ...
|
||||
retVal.setEnforceReferentialIntegrityOnWrite(true);
|
||||
retVal.setEnforceReferentialIntegrityOnDelete(true);
|
||||
return retVal;
|
||||
}
|
||||
```
|
||||
#### JPA Server Starter
|
||||
This can be easily enabled in the `application.yaml` file at the following paths:
|
||||
```yaml
|
||||
hapi:
|
||||
fhir:
|
||||
enforce_referential_integrity_on_write: true
|
||||
enforce_referential_integrity_on_delete: true
|
||||
```
|
||||
|
||||
# Search Result Caching
|
||||
|
||||
By default, search results will be cached for one minute. This means that if a client performs a search for <code>Patient?name=smith</code> and gets back 500 results, if a client performs the same search within 60000 milliseconds the previously loaded search results will be returned again. This also means that any new Patient resources named "Smith" within the last minute will not be reflected in the results.
|
||||
|
|
|
@ -60,4 +60,4 @@ Built-in Narrative Templates:
|
|||
|
||||
# Credits
|
||||
|
||||
This module is based on the excellent work of Rio Bennin and Panayiotis Savva of the University of Cyprus.
|
||||
This module is based on the excellent work of Rio Bennin of Crossroads Labs, and Panayiotis Savva and Constantinos Yiasemi of the University of Cyprus.
|
||||
|
|
|
@ -11,7 +11,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.util;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.util.StopWatch;
|
||||
import com.google.common.collect.Queues;
|
||||
import net.ttddyy.dsproxy.support.ProxyDataSourceBuilder;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -549,7 +549,7 @@ public class JpaBulkExportProcessor implements IBulkExportProcessor<JpaPid> {
|
|||
Optional<RuntimeSearchParam> oPatientSearchParam = SearchParameterUtil.getOnlyPatientSearchParamForResourceType(myContext, theResource.fhirType());
|
||||
if (!oPatientSearchParam.isPresent()) {
|
||||
String errorMessage = String.format("[%s] has no search parameters that are for patients, so it is invalid for Group Bulk Export!", theResource.fhirType());
|
||||
throw new IllegalArgumentException(Msg.code(2103) + errorMessage);
|
||||
throw new IllegalArgumentException(Msg.code(2242) + errorMessage);
|
||||
} else {
|
||||
return oPatientSearchParam.get();
|
||||
}
|
||||
|
|
|
@ -452,7 +452,7 @@ public class ExtendedHSearchClauseBuilder {
|
|||
booleanStep.minimumShouldMatchNumber(1);
|
||||
return booleanStep;
|
||||
}
|
||||
throw new IllegalArgumentException(Msg.code(2025) + "Date search param does not support prefix of type: " + prefix);
|
||||
throw new IllegalArgumentException(Msg.code(2255) + "Date search param does not support prefix of type: " + prefix);
|
||||
}
|
||||
|
||||
private PredicateFinalStep generateDateInstantSearchTerms(DateParam theDateParam, PathContext theSpContext) {
|
||||
|
@ -496,7 +496,7 @@ public class ExtendedHSearchClauseBuilder {
|
|||
return ((SearchPredicateFactory) theSpContext).range().field(lowerInstantField).atMost(upperBoundAsInstant);
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(Msg.code(2026) + "Date search param does not support prefix of type: " + prefix);
|
||||
throw new IllegalArgumentException(Msg.code(2256) + "Date search param does not support prefix of type: " + prefix);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -29,6 +29,7 @@ import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
|||
import ca.uhn.fhir.jpa.api.model.DeleteConflict;
|
||||
import ca.uhn.fhir.jpa.api.model.DeleteConflictList;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import org.hl7.fhir.instance.model.api.IBaseReference;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.slf4j.Logger;
|
||||
|
@ -99,7 +100,7 @@ public class OverridePathBasedReferentialIntegrityForDeletesInterceptor {
|
|||
* Interceptor hook method. Do not invoke directly.
|
||||
*/
|
||||
@Hook(value = Pointcut.STORAGE_PRESTORAGE_DELETE_CONFLICTS, order = CascadingDeleteInterceptor.OVERRIDE_PATH_BASED_REF_INTEGRITY_INTERCEPTOR_ORDER)
|
||||
public void handleDeleteConflicts(DeleteConflictList theDeleteConflictList) {
|
||||
public void handleDeleteConflicts(DeleteConflictList theDeleteConflictList, RequestDetails requestDetails) {
|
||||
for (DeleteConflict nextConflict : theDeleteConflictList) {
|
||||
ourLog.info("Ignoring referential integrity deleting {} - Referred to from {} at path {}", nextConflict.getTargetId(), nextConflict.getSourceId(), nextConflict.getSourcePath());
|
||||
|
||||
|
@ -107,7 +108,7 @@ public class OverridePathBasedReferentialIntegrityForDeletesInterceptor {
|
|||
IdDt targetId = nextConflict.getTargetId();
|
||||
String targetIdValue = targetId.toVersionless().getValue();
|
||||
|
||||
IBaseResource sourceResource = myDaoRegistry.getResourceDao(sourceId.getResourceType()).read(sourceId);
|
||||
IBaseResource sourceResource = myDaoRegistry.getResourceDao(sourceId.getResourceType()).read(sourceId, requestDetails);
|
||||
|
||||
IFhirPath fhirPath = myFhirContext.newFhirPath();
|
||||
for (String nextPath : myPaths) {
|
||||
|
|
|
@ -113,6 +113,18 @@ public class HapiFhirJpaMigrationTasks extends BaseMigrationTasks<VersionEnum> {
|
|||
.online(true)
|
||||
.withColumns("SEARCH_PID")
|
||||
.onlyAppliesToPlatforms(NON_AUTOMATIC_FK_INDEX_PLATFORMS);
|
||||
|
||||
// fix Postgres clob types - that stupid oid driver problem is still there
|
||||
// BT2_JOB_INSTANCE.PARAMS_JSON_LOB
|
||||
version.onTable("BT2_JOB_INSTANCE")
|
||||
.migratePostgresTextClobToBinaryClob("20230208.1", "PARAMS_JSON_LOB");
|
||||
// BT2_JOB_INSTANCE.REPORT
|
||||
version.onTable("BT2_JOB_INSTANCE")
|
||||
.migratePostgresTextClobToBinaryClob("20230208.2", "REPORT");
|
||||
// BT2_WORK_CHUNK.CHUNK_DATA
|
||||
version.onTable("BT2_WORK_CHUNK")
|
||||
.migratePostgresTextClobToBinaryClob("20230208.3", "CHUNK_DATA");
|
||||
|
||||
}
|
||||
|
||||
private void init620() {
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ package ca.uhn.fhir.jpa.ips.generator;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.context.RuntimeSearchParam;
|
||||
import ca.uhn.fhir.fhirpath.IFhirPathEvaluationContext;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.api.dao.IFhirResourceDao;
|
||||
|
@ -32,6 +33,7 @@ import ca.uhn.fhir.jpa.ips.api.SectionRegistry;
|
|||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Observation;
|
||||
import ca.uhn.fhir.model.valueset.BundleEntrySearchModeEnum;
|
||||
import ca.uhn.fhir.narrative.CustomThymeleafNarrativeGenerator;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
|
@ -42,6 +44,10 @@ import ca.uhn.fhir.util.BundleBuilder;
|
|||
import ca.uhn.fhir.util.CompositionBuilder;
|
||||
import ca.uhn.fhir.util.ResourceReferenceInfo;
|
||||
import ca.uhn.fhir.util.ValidateUtil;
|
||||
import com.google.common.collect.BiMap;
|
||||
import com.google.common.collect.HashBiMap;
|
||||
import org.apache.commons.collections4.BidiMap;
|
||||
import org.apache.commons.collections4.bidimap.DualHashBidiMap;
|
||||
import org.hl7.fhir.instance.model.api.IBase;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseExtension;
|
||||
|
@ -66,6 +72,7 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static ca.uhn.fhir.jpa.term.api.ITermLoaderSvc.LOINC_URI;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
@ -114,16 +121,18 @@ public class IpsGeneratorSvcImpl implements IIpsGeneratorSvc {
|
|||
}
|
||||
|
||||
private IBaseBundle generateIpsForPatient(RequestDetails theRequestDetails, IBaseResource thePatient) {
|
||||
IIdType originalSubjectId = myFhirContext.getVersion().newIdType().setValue(thePatient.getIdElement().getValue());
|
||||
IIdType originalSubjectId = myFhirContext.getVersion().newIdType().setValue(thePatient.getIdElement().getValue()).toUnqualifiedVersionless();
|
||||
massageResourceId(null, thePatient);
|
||||
IpsContext context = new IpsContext(thePatient, originalSubjectId);
|
||||
|
||||
ResourceInclusionCollection globalResourcesToInclude = new ResourceInclusionCollection();
|
||||
globalResourcesToInclude.addResourceIfNotAlreadyPresent(thePatient, originalSubjectId.getValue());
|
||||
|
||||
IBaseResource author = myGenerationStrategy.createAuthor();
|
||||
massageResourceId(context, author);
|
||||
|
||||
CompositionBuilder compositionBuilder = createComposition(thePatient, context, author);
|
||||
|
||||
ResourceInclusionCollection globalResourcesToInclude = determineInclusions(theRequestDetails, originalSubjectId, context, compositionBuilder);
|
||||
determineInclusions(theRequestDetails, originalSubjectId, context, compositionBuilder, globalResourcesToInclude);
|
||||
|
||||
IBaseResource composition = compositionBuilder.getComposition();
|
||||
|
||||
|
@ -131,10 +140,10 @@ public class IpsGeneratorSvcImpl implements IIpsGeneratorSvc {
|
|||
CustomThymeleafNarrativeGenerator generator = newNarrativeGenerator(globalResourcesToInclude);
|
||||
generator.populateResourceNarrative(myFhirContext, composition);
|
||||
|
||||
return createCompositionDocument(thePatient, author, composition, globalResourcesToInclude);
|
||||
return createCompositionDocument(author, composition, globalResourcesToInclude);
|
||||
}
|
||||
|
||||
private IBaseBundle createCompositionDocument(IBaseResource thePatient, IBaseResource author, IBaseResource composition, ResourceInclusionCollection theResourcesToInclude) {
|
||||
private IBaseBundle createCompositionDocument(IBaseResource author, IBaseResource composition, ResourceInclusionCollection theResourcesToInclude) {
|
||||
BundleBuilder bundleBuilder = new BundleBuilder(myFhirContext);
|
||||
bundleBuilder.setType(Bundle.BundleType.DOCUMENT.toCode());
|
||||
bundleBuilder.setIdentifier("urn:ietf:rfc:4122", UUID.randomUUID().toString());
|
||||
|
@ -143,9 +152,6 @@ public class IpsGeneratorSvcImpl implements IIpsGeneratorSvc {
|
|||
// Add composition to document
|
||||
bundleBuilder.addDocumentEntry(composition);
|
||||
|
||||
// Add subject to document
|
||||
bundleBuilder.addDocumentEntry(thePatient);
|
||||
|
||||
// Add inclusion candidates
|
||||
for (IBaseResource next : theResourcesToInclude.getResources()) {
|
||||
bundleBuilder.addDocumentEntry(next);
|
||||
|
@ -158,13 +164,12 @@ public class IpsGeneratorSvcImpl implements IIpsGeneratorSvc {
|
|||
}
|
||||
|
||||
@Nonnull
|
||||
private ResourceInclusionCollection determineInclusions(RequestDetails theRequestDetails, IIdType originalSubjectId, IpsContext context, CompositionBuilder theCompositionBuilder) {
|
||||
ResourceInclusionCollection globalResourcesToInclude = new ResourceInclusionCollection();
|
||||
private ResourceInclusionCollection determineInclusions(RequestDetails theRequestDetails, IIdType originalSubjectId, IpsContext context, CompositionBuilder theCompositionBuilder, ResourceInclusionCollection theGlobalResourcesToInclude) {
|
||||
SectionRegistry sectionRegistry = myGenerationStrategy.getSectionRegistry();
|
||||
for (SectionRegistry.Section nextSection : sectionRegistry.getSections()) {
|
||||
determineInclusionsForSection(theRequestDetails, originalSubjectId, context, theCompositionBuilder, globalResourcesToInclude, nextSection);
|
||||
determineInclusionsForSection(theRequestDetails, originalSubjectId, context, theCompositionBuilder, theGlobalResourcesToInclude, nextSection);
|
||||
}
|
||||
return globalResourcesToInclude;
|
||||
return theGlobalResourcesToInclude;
|
||||
}
|
||||
|
||||
private void determineInclusionsForSection(RequestDetails theRequestDetails, IIdType theOriginalSubjectId, IpsContext theIpsContext, CompositionBuilder theCompositionBuilder, ResourceInclusionCollection theGlobalResourcesToInclude, SectionRegistry.Section theSection) {
|
||||
|
@ -216,6 +221,8 @@ public class IpsGeneratorSvcImpl implements IIpsGeneratorSvc {
|
|||
|
||||
nextCandidate = previouslyExistingResource;
|
||||
sectionResourcesToInclude.addResourceIfNotAlreadyPresent(nextCandidate, originalResourceId);
|
||||
} else if (theGlobalResourcesToInclude.hasResourceWithReplacementId(originalResourceId)) {
|
||||
sectionResourcesToInclude.addResourceIfNotAlreadyPresent(nextCandidate, originalResourceId);
|
||||
} else {
|
||||
IIdType id = myGenerationStrategy.massageResourceId(theIpsContext, nextCandidate);
|
||||
nextCandidate.setId(id);
|
||||
|
@ -228,26 +235,6 @@ public class IpsGeneratorSvcImpl implements IIpsGeneratorSvc {
|
|||
|
||||
}
|
||||
|
||||
/*
|
||||
* Update any references within the added candidates - This is important
|
||||
* because we might be replacing resource IDs before including them in
|
||||
* the summary, so we need to also update the references to those
|
||||
* resources.
|
||||
*/
|
||||
for (IBaseResource nextResource : sectionResourcesToInclude.getResources()) {
|
||||
List<ResourceReferenceInfo> references = myFhirContext.newTerser().getAllResourceReferences(nextResource);
|
||||
for (ResourceReferenceInfo nextReference : references) {
|
||||
String existingReference = nextReference.getResourceReference().getReferenceElement().getValue();
|
||||
if (isNotBlank(existingReference)) {
|
||||
existingReference = new IdType(existingReference).toUnqualifiedVersionless().getValue();
|
||||
String replacement = theGlobalResourcesToInclude.getIdSubstitution(existingReference);
|
||||
if (isNotBlank(replacement) && !replacement.equals(existingReference)) {
|
||||
nextReference.getResourceReference().setReference(replacement);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (sectionResourcesToInclude.isEmpty() && theSection.getNoInfoGenerator() != null) {
|
||||
|
@ -261,6 +248,33 @@ public class IpsGeneratorSvcImpl implements IIpsGeneratorSvc {
|
|||
sectionResourcesToInclude.addResourceIfNotAlreadyPresent(noInfoResource, id);
|
||||
}
|
||||
|
||||
/*
|
||||
* Update any references within the added candidates - This is important
|
||||
* because we might be replacing resource IDs before including them in
|
||||
* the summary, so we need to also update the references to those
|
||||
* resources.
|
||||
*/
|
||||
for (IBaseResource nextResource : sectionResourcesToInclude.getResources()) {
|
||||
List<ResourceReferenceInfo> references = myFhirContext.newTerser().getAllResourceReferences(nextResource);
|
||||
for (ResourceReferenceInfo nextReference : references) {
|
||||
String existingReference = nextReference.getResourceReference().getReferenceElement().getValue();
|
||||
if (isNotBlank(existingReference)) {
|
||||
existingReference = new IdType(existingReference).toUnqualifiedVersionless().getValue();
|
||||
String replacement = theGlobalResourcesToInclude.getIdSubstitution(existingReference);
|
||||
if (isNotBlank(replacement)) {
|
||||
if (!replacement.equals(existingReference)) {
|
||||
nextReference.getResourceReference().setReference(replacement);
|
||||
}
|
||||
} else if (theGlobalResourcesToInclude.getResourceById(existingReference) == null) {
|
||||
// If this reference doesn't point to something we have actually
|
||||
// included in the bundle, clear the reference.
|
||||
nextReference.getResourceReference().setReference(null);
|
||||
nextReference.getResourceReference().setResource(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
addSection(theSection, theCompositionBuilder, sectionResourcesToInclude, theGlobalResourcesToInclude);
|
||||
}
|
||||
|
||||
|
@ -273,6 +287,9 @@ public class IpsGeneratorSvcImpl implements IIpsGeneratorSvc {
|
|||
sectionBuilder.addCodeCoding(LOINC_URI, theSection.getSectionCode(), theSection.getSectionDisplay());
|
||||
|
||||
for (IBaseResource next : theResourcesToInclude.getResources()) {
|
||||
if (ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.get(next) == BundleEntrySearchModeEnum.INCLUDE) {
|
||||
continue;
|
||||
}
|
||||
|
||||
IBaseExtension<?, ?> narrativeLink = ((IBaseHasExtensions) next).addExtension();
|
||||
narrativeLink.setUrl("http://hl7.org/fhir/StructureDefinition/narrativeLink");
|
||||
|
@ -309,7 +326,18 @@ public class IpsGeneratorSvcImpl implements IIpsGeneratorSvc {
|
|||
|
||||
private String determinePatientCompartmentSearchParameterName(String theResourceType) {
|
||||
RuntimeResourceDefinition resourceDef = myFhirContext.getResourceDefinition(theResourceType);
|
||||
return resourceDef.getSearchParamsForCompartmentName("Patient").get(0).getName();
|
||||
Set<String> searchParams = resourceDef.getSearchParamsForCompartmentName("Patient")
|
||||
.stream()
|
||||
.map(RuntimeSearchParam::getName)
|
||||
.collect(Collectors.toSet());
|
||||
// Prefer "patient", then "subject" then anything else
|
||||
if (searchParams.contains(Observation.SP_PATIENT)) {
|
||||
return Observation.SP_PATIENT;
|
||||
}
|
||||
if (searchParams.contains(Observation.SP_SUBJECT)) {
|
||||
return Observation.SP_SUBJECT;
|
||||
}
|
||||
return searchParams.iterator().next();
|
||||
}
|
||||
|
||||
private void massageResourceId(IpsContext theIpsContext, IBaseResource theResource) {
|
||||
|
@ -514,7 +542,7 @@ public class IpsGeneratorSvcImpl implements IIpsGeneratorSvc {
|
|||
|
||||
private final List<IBaseResource> myResources = new ArrayList<>();
|
||||
private final Map<String, IBaseResource> myIdToResource = new HashMap<>();
|
||||
private final Map<String, String> myOriginalIdToNewId = new HashMap<>();
|
||||
private final BiMap<String, String> myOriginalIdToNewId = HashBiMap.create();
|
||||
|
||||
public List<IBaseResource> getResources() {
|
||||
return myResources;
|
||||
|
@ -541,7 +569,15 @@ public class IpsGeneratorSvcImpl implements IIpsGeneratorSvc {
|
|||
}
|
||||
|
||||
public IBaseResource getResourceById(IIdType theReference) {
|
||||
return myIdToResource.get(theReference.toUnqualifiedVersionless().getValue());
|
||||
return getResourceById(theReference.toUnqualifiedVersionless().getValue());
|
||||
}
|
||||
|
||||
public boolean hasResourceWithReplacementId(String theReplacementId) {
|
||||
return myOriginalIdToNewId.containsValue(theReplacementId);
|
||||
}
|
||||
|
||||
public IBaseResource getResourceById(String theReference) {
|
||||
return myIdToResource.get(theReference);
|
||||
}
|
||||
|
||||
@Nullable
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package ca.uhn.fhir.jpa.ips.generator;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.ips.api.IIpsGenerationStrategy;
|
||||
import ca.uhn.fhir.jpa.ips.provider.IpsOperationProvider;
|
||||
|
@ -8,8 +9,16 @@ import ca.uhn.fhir.jpa.ips.strategy.DefaultIpsGenerationStrategy;
|
|||
import ca.uhn.fhir.jpa.model.util.JpaConstants;
|
||||
import ca.uhn.fhir.jpa.provider.BaseResourceProviderR4Test;
|
||||
import ca.uhn.fhir.util.ClasspathUtil;
|
||||
import ca.uhn.fhir.validation.FhirValidator;
|
||||
import ca.uhn.fhir.validation.ValidationResult;
|
||||
import org.hl7.fhir.common.hapi.validation.validator.FhirInstanceValidator;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.r4.model.Bundle;
|
||||
import org.hl7.fhir.r4.model.Condition;
|
||||
import org.hl7.fhir.r4.model.MedicationStatement;
|
||||
import org.hl7.fhir.r4.model.Parameters;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.hl7.fhir.r4.model.Resource;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
@ -18,7 +27,13 @@ import org.springframework.context.annotation.Bean;
|
|||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.matchesPattern;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
|
||||
@ContextConfiguration(classes = {IpsGenerationTest.IpsConfig.class})
|
||||
public class IpsGenerationTest extends BaseResourceProviderR4Test {
|
||||
|
@ -34,6 +49,7 @@ public class IpsGenerationTest extends BaseResourceProviderR4Test {
|
|||
@AfterEach
|
||||
public void afterEach() {
|
||||
myServer.withServer(t -> t.unregisterProvider(myIpsOperationProvider));
|
||||
myDaoConfig.setResourceClientIdStrategy(DaoConfig.ClientIdStrategyEnum.ALPHANUMERIC);
|
||||
}
|
||||
|
||||
|
||||
|
@ -55,12 +71,55 @@ public class IpsGenerationTest extends BaseResourceProviderR4Test {
|
|||
.withNoParameters(Parameters.class)
|
||||
.returnResourceType(Bundle.class)
|
||||
.execute();
|
||||
|
||||
ourLog.info("Output: {}", myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(output));
|
||||
|
||||
assertEquals(37, output.getEntry().size());
|
||||
// Verify
|
||||
validateDocument(outcome);
|
||||
assertEquals(117, output.getEntry().size());
|
||||
String patientId = findFirstEntryResource(output, Patient.class, 1).getId();
|
||||
assertThat(patientId, matchesPattern("urn:uuid:.*"));
|
||||
MedicationStatement medicationStatement = findFirstEntryResource(output, MedicationStatement.class, 2);
|
||||
assertEquals(patientId, medicationStatement.getSubject().getReference());
|
||||
assertNull(medicationStatement.getInformationSource().getReference());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGenerateTinyPatientSummary() {
|
||||
myDaoConfig.setResourceClientIdStrategy(DaoConfig.ClientIdStrategyEnum.ANY);
|
||||
|
||||
Bundle sourceData = ClasspathUtil.loadCompressedResource(myFhirContext, Bundle.class, "/tiny-patient-everything.json.gz");
|
||||
sourceData.setType(Bundle.BundleType.TRANSACTION);
|
||||
for (Bundle.BundleEntryComponent nextEntry : sourceData.getEntry()) {
|
||||
nextEntry.getRequest().setMethod(Bundle.HTTPVerb.PUT);
|
||||
nextEntry.getRequest().setUrl(nextEntry.getResource().getIdElement().toUnqualifiedVersionless().getValue());
|
||||
}
|
||||
Bundle outcome = mySystemDao.transaction(mySrd, sourceData);
|
||||
ourLog.info("Created {} resources", outcome.getEntry().size());
|
||||
|
||||
Bundle output = myClient
|
||||
.operation()
|
||||
.onInstance("Patient/5342998")
|
||||
.named(JpaConstants.OPERATION_SUMMARY)
|
||||
.withNoParameters(Parameters.class)
|
||||
.returnResourceType(Bundle.class)
|
||||
.execute();
|
||||
ourLog.info("Output: {}", myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(output));
|
||||
|
||||
// Verify
|
||||
validateDocument(outcome);
|
||||
assertEquals(7, output.getEntry().size());
|
||||
String patientId = findFirstEntryResource(output, Patient.class, 1).getId();
|
||||
assertThat(patientId, matchesPattern("urn:uuid:.*"));
|
||||
assertEquals(patientId, findEntryResource(output, Condition.class, 0, 2).getSubject().getReference());
|
||||
assertEquals(patientId, findEntryResource(output, Condition.class, 1, 2).getSubject().getReference());
|
||||
}
|
||||
|
||||
private void validateDocument(Bundle theOutcome) {
|
||||
FhirValidator validator = myFhirContext.newValidator();
|
||||
validator.registerValidatorModule(new FhirInstanceValidator(myFhirContext));
|
||||
ValidationResult validation = validator.validateWithResult(theOutcome);
|
||||
assertTrue(validation.isSuccessful(), () -> myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(validation.toOperationOutcome()));
|
||||
}
|
||||
|
||||
@Configuration
|
||||
public static class IpsConfig {
|
||||
|
@ -83,5 +142,21 @@ public class IpsGenerationTest extends BaseResourceProviderR4Test {
|
|||
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private static <T extends IBaseResource> T findFirstEntryResource(Bundle theBundle, Class<T> theType, int theExpectedCount) {
|
||||
return findEntryResource(theBundle, theType, 0, theExpectedCount);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
static <T extends IBaseResource> T findEntryResource(Bundle theBundle, Class<T> theType, int index, int theExpectedCount) {
|
||||
List<Resource> resources = theBundle
|
||||
.getEntry()
|
||||
.stream()
|
||||
.map(Bundle.BundleEntryComponent::getResource)
|
||||
.filter(r -> theType.isAssignableFrom(r.getClass()))
|
||||
.toList();
|
||||
assertEquals(theExpectedCount, resources.size());
|
||||
return (T) resources.get(index);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import org.hl7.fhir.r4.model.DateTimeType;
|
|||
import org.hl7.fhir.r4.model.Device;
|
||||
import org.hl7.fhir.r4.model.DeviceUseStatement;
|
||||
import org.hl7.fhir.r4.model.DiagnosticReport;
|
||||
import org.hl7.fhir.r4.model.Encounter;
|
||||
import org.hl7.fhir.r4.model.IdType;
|
||||
import org.hl7.fhir.r4.model.Immunization;
|
||||
import org.hl7.fhir.r4.model.Medication;
|
||||
|
@ -60,12 +61,15 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static ca.uhn.fhir.jpa.ips.generator.IpsGenerationTest.findEntryResource;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.startsWith;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
@ExtendWith(MockitoExtension.class)
|
||||
|
@ -74,6 +78,8 @@ public class IpsGeneratorSvcImplTest {
|
|||
public static final String MEDICATION_ID = "Medication/tyl";
|
||||
public static final String MEDICATION_STATEMENT_ID = "MedicationStatement/meds";
|
||||
public static final String MEDICATION_STATEMENT_ID2 = "MedicationStatement/meds2";
|
||||
public static final String PATIENT_ID = "Patient/123";
|
||||
public static final String ENCOUNTER_ID = "Encounter/encounter";
|
||||
private static final List<Class<? extends IBaseResource>> RESOURCE_TYPES = Lists.newArrayList(
|
||||
AllergyIntolerance.class,
|
||||
CarePlan.class,
|
||||
|
@ -157,7 +163,7 @@ public class IpsGeneratorSvcImplTest {
|
|||
registerRemainingResourceDaos();
|
||||
|
||||
// Test
|
||||
Bundle outcome = (Bundle) mySvc.generateIps(new SystemRequestDetails(), new IdType("Patient/123"));
|
||||
Bundle outcome = (Bundle) mySvc.generateIps(new SystemRequestDetails(), new IdType(PATIENT_ID));
|
||||
|
||||
// Verify Bundle Contents
|
||||
List<String> contentResourceTypes = toEntryResourceTypeStrings(outcome);
|
||||
|
@ -170,12 +176,7 @@ public class IpsGeneratorSvcImplTest {
|
|||
|
||||
// Verify
|
||||
Composition compositions = (Composition) outcome.getEntry().get(0).getResource();
|
||||
Composition.SectionComponent section = compositions
|
||||
.getSection()
|
||||
.stream()
|
||||
.filter(t -> t.getTitle().equals(myStrategy.getSectionRegistry().getSection(IpsSectionEnum.MEDICATION_SUMMARY).getTitle()))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
Composition.SectionComponent section = findSection(compositions, IpsSectionEnum.MEDICATION_SUMMARY);
|
||||
|
||||
HtmlPage narrativeHtml = HtmlUtil.parseAsHtml(section.getText().getDivAsString());
|
||||
ourLog.info("Narrative:\n{}", narrativeHtml.asXml());
|
||||
|
@ -191,6 +192,17 @@ public class IpsGeneratorSvcImplTest {
|
|||
assertThat(row.getCell(4).asNormalizedText(), containsString("2023"));
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
private Composition.SectionComponent findSection(Composition compositions, IpsSectionEnum sectionEnum) {
|
||||
Composition.SectionComponent section = compositions
|
||||
.getSection()
|
||||
.stream()
|
||||
.filter(t -> t.getTitle().equals(myStrategy.getSectionRegistry().getSection(sectionEnum).getTitle()))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
return section;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMedicationSummary_DuplicateSecondaryResources() {
|
||||
myStrategy.setSectionRegistry(new SectionRegistry().addGlobalCustomizer(t -> t.withNoInfoGenerator(null)));
|
||||
|
@ -209,7 +221,7 @@ public class IpsGeneratorSvcImplTest {
|
|||
registerRemainingResourceDaos();
|
||||
|
||||
// Test
|
||||
Bundle outcome = (Bundle) mySvc.generateIps(new SystemRequestDetails(), new IdType("Patient/123"));
|
||||
Bundle outcome = (Bundle) mySvc.generateIps(new SystemRequestDetails(), new IdType(PATIENT_ID));
|
||||
|
||||
// Verify Bundle Contents
|
||||
List<String> contentResourceTypes = toEntryResourceTypeStrings(outcome);
|
||||
|
@ -248,7 +260,7 @@ public class IpsGeneratorSvcImplTest {
|
|||
registerRemainingResourceDaos();
|
||||
|
||||
// Test
|
||||
Bundle outcome = (Bundle) mySvc.generateIps(new SystemRequestDetails(), new IdType("Patient/123"));
|
||||
Bundle outcome = (Bundle) mySvc.generateIps(new SystemRequestDetails(), new IdType(PATIENT_ID));
|
||||
|
||||
// Verify Bundle Contents
|
||||
List<String> contentResourceTypes = toEntryResourceTypeStrings(outcome);
|
||||
|
@ -263,12 +275,7 @@ public class IpsGeneratorSvcImplTest {
|
|||
|
||||
// Verify narrative - should have 2 rows (one for each primary MedicationStatement)
|
||||
Composition compositions = (Composition) outcome.getEntry().get(0).getResource();
|
||||
Composition.SectionComponent section = compositions
|
||||
.getSection()
|
||||
.stream()
|
||||
.filter(t -> t.getTitle().equals(myStrategy.getSectionRegistry().getSection(IpsSectionEnum.MEDICATION_SUMMARY).getTitle()))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
Composition.SectionComponent section = findSection(compositions, IpsSectionEnum.MEDICATION_SUMMARY);
|
||||
|
||||
HtmlPage narrativeHtml = HtmlUtil.parseAsHtml(section.getText().getDivAsString());
|
||||
ourLog.info("Narrative:\n{}", narrativeHtml.asXml());
|
||||
|
@ -304,16 +311,11 @@ public class IpsGeneratorSvcImplTest {
|
|||
registerRemainingResourceDaos();
|
||||
|
||||
// Test
|
||||
Bundle outcome = (Bundle) mySvc.generateIps(new SystemRequestDetails(), new IdType("Patient/123"));
|
||||
Bundle outcome = (Bundle) mySvc.generateIps(new SystemRequestDetails(), new IdType(PATIENT_ID));
|
||||
|
||||
// Verify
|
||||
Composition compositions = (Composition) outcome.getEntry().get(0).getResource();
|
||||
Composition.SectionComponent section = compositions
|
||||
.getSection()
|
||||
.stream()
|
||||
.filter(t -> t.getTitle().equals(myStrategy.getSectionRegistry().getSection(IpsSectionEnum.MEDICAL_DEVICES).getTitle()))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
Composition.SectionComponent section = findSection(compositions, IpsSectionEnum.MEDICAL_DEVICES);
|
||||
|
||||
HtmlPage narrativeHtml = HtmlUtil.parseAsHtml(section.getText().getDivAsString());
|
||||
ourLog.info("Narrative:\n{}", narrativeHtml.asXml());
|
||||
|
@ -356,16 +358,11 @@ public class IpsGeneratorSvcImplTest {
|
|||
registerRemainingResourceDaos();
|
||||
|
||||
// Test
|
||||
Bundle outcome = (Bundle) mySvc.generateIps(new SystemRequestDetails(), new IdType("Patient/123"));
|
||||
Bundle outcome = (Bundle) mySvc.generateIps(new SystemRequestDetails(), new IdType(PATIENT_ID));
|
||||
|
||||
// Verify
|
||||
Composition compositions = (Composition) outcome.getEntry().get(0).getResource();
|
||||
Composition.SectionComponent section = compositions
|
||||
.getSection()
|
||||
.stream()
|
||||
.filter(t -> t.getTitle().equals(myStrategy.getSectionRegistry().getSection(IpsSectionEnum.IMMUNIZATIONS).getTitle()))
|
||||
.findFirst()
|
||||
.orElseThrow();
|
||||
Composition.SectionComponent section = findSection(compositions, IpsSectionEnum.IMMUNIZATIONS);
|
||||
|
||||
HtmlPage narrativeHtml = HtmlUtil.parseAsHtml(section.getText().getDivAsString());
|
||||
ourLog.info("Narrative:\n{}", narrativeHtml.asXml());
|
||||
|
@ -383,10 +380,82 @@ public class IpsGeneratorSvcImplTest {
|
|||
assertThat(row.getCell(6).asNormalizedText(), containsString("2023"));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testReferencesUpdatedInSecondaryInclusions() {
|
||||
// Setup Patient
|
||||
registerPatientDaoWithRead();
|
||||
|
||||
// Setup Medication + MedicationStatement
|
||||
Encounter encounter = new Encounter();
|
||||
encounter.setId(new IdType(ENCOUNTER_ID));
|
||||
encounter.setSubject(new Reference(PATIENT_ID));
|
||||
ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.put(encounter, BundleEntrySearchModeEnum.INCLUDE);
|
||||
|
||||
Condition conditionActive = new Condition();
|
||||
conditionActive.setId("Condition/conditionActive");
|
||||
conditionActive.getClinicalStatus().addCoding()
|
||||
.setSystem("http://terminology.hl7.org/CodeSystem/condition-clinical")
|
||||
.setCode("active");
|
||||
conditionActive.setSubject(new Reference(PATIENT_ID));
|
||||
conditionActive.setEncounter(new Reference(ENCOUNTER_ID));
|
||||
ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.put(conditionActive, BundleEntrySearchModeEnum.MATCH);
|
||||
|
||||
Condition conditionResolved = new Condition();
|
||||
conditionResolved.setId("Condition/conditionResolved");
|
||||
conditionResolved.getClinicalStatus().addCoding()
|
||||
.setSystem("http://terminology.hl7.org/CodeSystem/condition-clinical")
|
||||
.setCode("resolved");
|
||||
conditionResolved.setSubject(new Reference(PATIENT_ID));
|
||||
conditionResolved.setEncounter(new Reference(ENCOUNTER_ID));
|
||||
ResourceMetadataKeyEnum.ENTRY_SEARCH_MODE.put(conditionResolved, BundleEntrySearchModeEnum.MATCH);
|
||||
|
||||
// Conditions will be loaded from two sections (problem list and illness history) so
|
||||
// we return an active condition the first time and a resolved one the second
|
||||
IFhirResourceDao<Condition> conditionDao = registerResourceDaoWithNoData(Condition.class);
|
||||
when(conditionDao.search(any(), any())).thenReturn(
|
||||
new SimpleBundleProvider(Lists.newArrayList(conditionActive, encounter)),
|
||||
new SimpleBundleProvider(Lists.newArrayList(conditionResolved, encounter))
|
||||
);
|
||||
|
||||
registerRemainingResourceDaos();
|
||||
|
||||
// Test
|
||||
Bundle outcome = (Bundle) mySvc.generateIps(new SystemRequestDetails(), new IdType(PATIENT_ID));
|
||||
|
||||
// Verify cross-references
|
||||
Patient addedPatient = findEntryResource(outcome, Patient.class, 0, 1);
|
||||
assertThat(addedPatient.getId(), startsWith("urn:uuid:"));
|
||||
Condition addedCondition = findEntryResource(outcome, Condition.class, 0, 2);
|
||||
assertThat(addedCondition.getId(), startsWith("urn:uuid:"));
|
||||
Condition addedCondition2 = findEntryResource(outcome, Condition.class, 1, 2);
|
||||
assertThat(addedCondition2.getId(), startsWith("urn:uuid:"));
|
||||
Encounter addedEncounter = findEntryResource(outcome, Encounter.class, 0, 1);
|
||||
assertThat(addedEncounter.getId(), startsWith("urn:uuid:"));
|
||||
MedicationStatement addedMedicationStatement = findEntryResource(outcome, MedicationStatement.class, 0, 1);
|
||||
assertThat(addedMedicationStatement.getId(), startsWith("urn:uuid:"));
|
||||
assertEquals("no-medication-info", addedMedicationStatement.getMedicationCodeableConcept().getCodingFirstRep().getCode());
|
||||
assertEquals(addedPatient.getId(), addedCondition.getSubject().getReference());
|
||||
assertEquals(addedEncounter.getId(), addedCondition.getEncounter().getReference());
|
||||
assertEquals(addedPatient.getId(), addedEncounter.getSubject().getReference());
|
||||
assertEquals(addedPatient.getId(), addedMedicationStatement.getSubject().getReference());
|
||||
|
||||
// Verify sections
|
||||
ourLog.info("Resource: {}", myFhirContext.newJsonParser().setPrettyPrint(true).encodeResourceToString(outcome));
|
||||
verify(conditionDao, times(2)).search(any(), any());
|
||||
Composition composition = (Composition) outcome.getEntry().get(0).getResource();
|
||||
Composition.SectionComponent problemListSection = findSection(composition, IpsSectionEnum.PROBLEM_LIST);
|
||||
assertEquals(addedCondition.getId(), problemListSection.getEntry().get(0).getReference());
|
||||
assertEquals(1, problemListSection.getEntry().size());
|
||||
Composition.SectionComponent illnessHistorySection = findSection(composition, IpsSectionEnum.ILLNESS_HISTORY);
|
||||
assertEquals(addedCondition2.getId(), illnessHistorySection.getEntry().get(0).getReference());
|
||||
assertEquals(1, illnessHistorySection.getEntry().size());
|
||||
}
|
||||
|
||||
private void registerPatientDaoWithRead() {
|
||||
IFhirResourceDao<Patient> patientDao = registerResourceDaoWithNoData(Patient.class);
|
||||
Patient patient = new Patient();
|
||||
patient.setId("Patient/123");
|
||||
patient.setId(PATIENT_ID);
|
||||
when(patientDao.read(any(), any())).thenReturn(patient);
|
||||
}
|
||||
|
||||
|
@ -432,12 +501,11 @@ public class IpsGeneratorSvcImplTest {
|
|||
|
||||
@Nonnull
|
||||
private static List<String> toEntryResourceTypeStrings(Bundle outcome) {
|
||||
List<String> contentResourceTypes = outcome
|
||||
return outcome
|
||||
.getEntry()
|
||||
.stream()
|
||||
.map(t -> t.getResource().getResourceType().name())
|
||||
.collect(Collectors.toList());
|
||||
return contentResourceTypes;
|
||||
}
|
||||
|
||||
@Nonnull
|
||||
|
|
Binary file not shown.
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -0,0 +1,145 @@
|
|||
package ca.uhn.fhir.jpa.interceptor;
|
||||
|
||||
import ca.uhn.fhir.jpa.model.config.PartitionSettings;
|
||||
import ca.uhn.fhir.jpa.provider.r4.BaseMultitenantResourceProviderR4Test;
|
||||
import ca.uhn.fhir.jpa.searchparam.SearchParameterMap;
|
||||
import ca.uhn.fhir.rest.api.server.IBundleProvider;
|
||||
import ca.uhn.fhir.rest.api.server.RequestDetails;
|
||||
import ca.uhn.fhir.rest.api.server.SystemRequestDetails;
|
||||
import ca.uhn.fhir.rest.param.ReferenceParam;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceVersionConflictException;
|
||||
import org.hl7.fhir.r4.model.AuditEvent;
|
||||
import org.hl7.fhir.r4.model.IdType;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
/**
|
||||
* <p>Multitenant test version of {@link OverridePathBasedReferentialIntegrityForDeletesInterceptorTest}.</p>
|
||||
*
|
||||
* <p>Ensures the tenant is properly propagated down to the {@link ca.uhn.fhir.jpa.api.dao.DaoRegistry} when requesting
|
||||
* the conflicting resource.</p>
|
||||
*
|
||||
* <p>This test runs a subset of tests from {@link OverridePathBasedReferentialIntegrityForDeletesInterceptorTest}
|
||||
* against the {@link BaseMultitenantResourceProviderR4Test}</p>
|
||||
*/
|
||||
public class MultitenantOverridePathBasedReferentialIntegrityForDeletesInterceptorTest extends BaseMultitenantResourceProviderR4Test {
|
||||
|
||||
@Autowired
|
||||
private OverridePathBasedReferentialIntegrityForDeletesInterceptor mySvc;
|
||||
|
||||
@Autowired
|
||||
private CascadingDeleteInterceptor myCascadingDeleteInterceptor;
|
||||
|
||||
RequestDetails requestDetails = new SystemRequestDetails();
|
||||
|
||||
@BeforeEach
|
||||
public void beforeEach() {
|
||||
requestDetails.setTenantId(TENANT_A);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void after() throws Exception {
|
||||
myPartitionSettings.setAllowReferencesAcrossPartitions(PartitionSettings.CrossPartitionReferenceMode.NOT_ALLOWED);
|
||||
assertFalse(myPartitionSettings.isAllowUnqualifiedCrossPartitionReference());
|
||||
|
||||
myInterceptorRegistry.unregisterInterceptor(mySvc);
|
||||
mySvc.clearPaths();
|
||||
|
||||
super.after();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAllowDelete() {
|
||||
|
||||
mySvc.addPath("AuditEvent.agent.who");
|
||||
myInterceptorRegistry.registerInterceptor(mySvc);
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.setId("P");
|
||||
patient.setActive(true);
|
||||
myPatientDao.update(patient, requestDetails);
|
||||
|
||||
AuditEvent audit = new AuditEvent();
|
||||
audit.setId("A");
|
||||
audit.addAgent().getWho().setReference("Patient/P");
|
||||
myAuditEventDao.update(audit, requestDetails);
|
||||
|
||||
// Delete should proceed
|
||||
myPatientDao.delete(new IdType("Patient/P"), requestDetails);
|
||||
|
||||
// Make sure we're deleted
|
||||
try {
|
||||
myPatientDao.read(new IdType("Patient/P"), requestDetails);
|
||||
fail();
|
||||
} catch (ResourceGoneException e) {
|
||||
// good
|
||||
}
|
||||
|
||||
// Search should still work
|
||||
IBundleProvider searchOutcome = myAuditEventDao.search(SearchParameterMap.newSynchronous(AuditEvent.SP_AGENT, new ReferenceParam("Patient/P")), requestDetails);
|
||||
assertEquals(1, searchOutcome.size());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWrongPath() {
|
||||
mySvc.addPath("AuditEvent.identifier");
|
||||
mySvc.addPath("Patient.agent.who");
|
||||
myInterceptorRegistry.registerInterceptor(mySvc);
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.setId("P");
|
||||
patient.setActive(true);
|
||||
myPatientDao.update(patient, requestDetails);
|
||||
|
||||
AuditEvent audit = new AuditEvent();
|
||||
audit.setId("A");
|
||||
audit.addAgent().getWho().setReference("Patient/P");
|
||||
myAuditEventDao.update(audit, requestDetails);
|
||||
|
||||
// Delete should proceed
|
||||
try {
|
||||
myPatientDao.delete(new IdType("Patient/P"), requestDetails);
|
||||
fail();
|
||||
} catch (ResourceVersionConflictException e) {
|
||||
// good
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCombineWithCascadeDeleteInterceptor() {
|
||||
try {
|
||||
myInterceptorRegistry.registerInterceptor(myCascadingDeleteInterceptor);
|
||||
|
||||
mySvc.addPath("AuditEvent.agent.who");
|
||||
myInterceptorRegistry.registerInterceptor(mySvc);
|
||||
|
||||
Patient patient = new Patient();
|
||||
patient.setId("P");
|
||||
patient.setActive(true);
|
||||
myPatientDao.update(patient, requestDetails);
|
||||
|
||||
AuditEvent audit = new AuditEvent();
|
||||
audit.setId("A");
|
||||
audit.addAgent().getWho().setReference("Patient/P");
|
||||
myAuditEventDao.update(audit, requestDetails);
|
||||
|
||||
// Delete should proceed
|
||||
myPatientDao.delete(new IdType("Patient/P"), requestDetails);
|
||||
|
||||
} finally {
|
||||
myInterceptorRegistry.unregisterInterceptor(myCascadingDeleteInterceptor);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -7,11 +7,14 @@ import ca.uhn.fhir.context.support.ValidationSupportContext;
|
|||
import ca.uhn.fhir.context.support.ValueSetExpansionOptions;
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.api.model.ExpungeOptions;
|
||||
import ca.uhn.fhir.jpa.model.entity.ResourceTable;
|
||||
import ca.uhn.fhir.jpa.term.api.ITermDeferredStorageSvc;
|
||||
import ca.uhn.fhir.jpa.term.custom.CustomTerminologySet;
|
||||
import ca.uhn.fhir.jpa.util.ValueSetTestUtil;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InternalErrorException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.InvalidRequestException;
|
||||
import ca.uhn.fhir.rest.server.exceptions.ResourceGoneException;
|
||||
import org.hl7.fhir.common.hapi.validation.support.CachingValidationSupport;
|
||||
import org.hl7.fhir.instance.model.api.IIdType;
|
||||
import org.hl7.fhir.instance.model.api.IPrimitiveType;
|
||||
|
@ -19,6 +22,7 @@ import org.hl7.fhir.r5.model.CodeSystem;
|
|||
import org.hl7.fhir.r5.model.CodeType;
|
||||
import org.hl7.fhir.r5.model.CodeableConcept;
|
||||
import org.hl7.fhir.r5.model.Coding;
|
||||
import org.hl7.fhir.r5.model.Enumerations;
|
||||
import org.hl7.fhir.r5.model.IdType;
|
||||
import org.hl7.fhir.r5.model.StringType;
|
||||
import org.hl7.fhir.r5.model.UriType;
|
||||
|
@ -30,6 +34,7 @@ import org.springframework.beans.factory.annotation.Autowired;
|
|||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
|
@ -38,6 +43,7 @@ import static org.hamcrest.Matchers.stringContainsInOrder;
|
|||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||
import static org.junit.jupiter.api.Assertions.fail;
|
||||
|
||||
|
@ -56,6 +62,7 @@ public class FhirResourceDaoR5ValueSetTest extends BaseJpaR5Test {
|
|||
public void after() {
|
||||
myDaoConfig.setPreExpandValueSets(new DaoConfig().isPreExpandValueSets());
|
||||
myDaoConfig.setMaximumExpansionSize(new DaoConfig().getMaximumExpansionSize());
|
||||
myDaoConfig.setExpungeEnabled(new DaoConfig().isExpungeEnabled());
|
||||
}
|
||||
|
||||
|
||||
|
@ -248,6 +255,49 @@ public class FhirResourceDaoR5ValueSetTest extends BaseJpaR5Test {
|
|||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* See #4305
|
||||
*/
|
||||
@Test
|
||||
public void testDeleteExpungePreExpandedValueSet() {
|
||||
myDaoConfig.setExpungeEnabled(true);
|
||||
|
||||
// Create valueset
|
||||
ValueSet vs = myValidationSupport.fetchResource(ValueSet.class, "http://hl7.org/fhir/ValueSet/address-use");
|
||||
assertNotNull(vs);
|
||||
IIdType id = myValueSetDao.create(vs).getId().toUnqualifiedVersionless();
|
||||
|
||||
// Update valueset
|
||||
vs.setName("Hello");
|
||||
assertEquals("2", myValueSetDao.update(vs, mySrd).getId().getVersionIdPart());
|
||||
runInTransaction(()->{
|
||||
Optional<ResourceTable> resource = myResourceTableDao.findById(id.getIdPartAsLong());
|
||||
assertTrue(resource.isPresent());
|
||||
});
|
||||
|
||||
// Precalculate
|
||||
myTerminologyDeferredStorageSvc.saveAllDeferred();
|
||||
myTermSvc.preExpandDeferredValueSetsToTerminologyTables();
|
||||
logAllValueSets();
|
||||
|
||||
// Delete
|
||||
myValueSetDao.delete(id, mySrd);
|
||||
|
||||
// Verify it's deleted
|
||||
assertThrows(ResourceGoneException.class, ()-> myValueSetDao.read(id, mySrd));
|
||||
|
||||
// Expunge
|
||||
myValueSetDao.expunge(id, new ExpungeOptions().setExpungeDeletedResources(true).setExpungeOldVersions(true), mySrd);
|
||||
|
||||
// Verify expunged
|
||||
runInTransaction(()->{
|
||||
Optional<ResourceTable> resource = myResourceTableDao.findById(id.getIdPartAsLong());
|
||||
assertFalse(resource.isPresent());
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testExpandByValueSet_ExceedsMaxSize() {
|
||||
// Add a bunch of codes
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -20,6 +20,7 @@ package ca.uhn.fhir.jpa.util;
|
|||
* #L%
|
||||
*/
|
||||
|
||||
import ca.uhn.fhir.i18n.Msg;
|
||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||
import ca.uhn.fhir.jpa.subscription.SocketImplementation;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -53,6 +53,11 @@
|
|||
<artifactId>hapi-fhir-server-openapi</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-jpaserver-ips</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.helger</groupId>
|
||||
|
|
|
@ -12,6 +12,7 @@ import ca.uhn.fhir.jpa.bulk.export.provider.BulkDataExportProvider;
|
|||
import ca.uhn.fhir.jpa.delete.ThreadSafeResourceDeleterSvc;
|
||||
import ca.uhn.fhir.jpa.graphql.GraphQLProvider;
|
||||
import ca.uhn.fhir.jpa.interceptor.CascadingDeleteInterceptor;
|
||||
import ca.uhn.fhir.jpa.ips.provider.IpsOperationProvider;
|
||||
import ca.uhn.fhir.jpa.provider.DiffProvider;
|
||||
import ca.uhn.fhir.jpa.provider.JpaCapabilityStatementProvider;
|
||||
import ca.uhn.fhir.jpa.provider.JpaConformanceProviderDstu2;
|
||||
|
@ -152,6 +153,7 @@ public class TestRestfulServer extends RestfulServer {
|
|||
setServerConformanceProvider(confProvider);
|
||||
providers.add(myAppCtx.getBean(TerminologyUploaderProvider.class));
|
||||
providers.add(myAppCtx.getBean(GraphQLProvider.class));
|
||||
providers.add(myAppCtx.getBean(IpsOperationProvider.class));
|
||||
break;
|
||||
}
|
||||
case "R4B": {
|
||||
|
|
|
@ -2,9 +2,15 @@ package ca.uhn.fhirtest.config;
|
|||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.jpa.api.config.DaoConfig;
|
||||
import ca.uhn.fhir.jpa.api.dao.DaoRegistry;
|
||||
import ca.uhn.fhir.jpa.config.HapiJpaConfig;
|
||||
import ca.uhn.fhir.jpa.config.r4.JpaR4Config;
|
||||
import ca.uhn.fhir.jpa.config.util.HapiEntityManagerFactoryUtil;
|
||||
import ca.uhn.fhir.jpa.ips.api.IIpsGenerationStrategy;
|
||||
import ca.uhn.fhir.jpa.ips.generator.IIpsGeneratorSvc;
|
||||
import ca.uhn.fhir.jpa.ips.generator.IpsGeneratorSvcImpl;
|
||||
import ca.uhn.fhir.jpa.ips.provider.IpsOperationProvider;
|
||||
import ca.uhn.fhir.jpa.ips.strategy.DefaultIpsGenerationStrategy;
|
||||
import ca.uhn.fhir.jpa.model.dialect.HapiFhirH2Dialect;
|
||||
import ca.uhn.fhir.jpa.model.dialect.HapiFhirPostgres94Dialect;
|
||||
import ca.uhn.fhir.jpa.model.entity.ModelConfig;
|
||||
|
@ -196,5 +202,19 @@ public class TestR4Config {
|
|||
return new PropertySourcesPlaceholderConfigurer();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IIpsGenerationStrategy ipsGenerationStrategy() {
|
||||
return new DefaultIpsGenerationStrategy();
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IIpsGeneratorSvc ipsGeneratorSvc(FhirContext theFhirContext, IIpsGenerationStrategy theGenerationStrategy, DaoRegistry theDaoRegistry) {
|
||||
return new IpsGeneratorSvcImpl(theFhirContext, theGenerationStrategy, theDaoRegistry);
|
||||
}
|
||||
|
||||
@Bean
|
||||
public IpsOperationProvider ipsOperationProvider(IIpsGeneratorSvc theIpsGeneratorSvc) {
|
||||
return new IpsOperationProvider(theIpsGeneratorSvc);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -35,7 +35,7 @@ public class NicknameMatcher implements IMdmStringMatcher {
|
|||
try {
|
||||
myNicknameSvc = new NicknameSvc();
|
||||
} catch (IOException e) {
|
||||
throw new ConfigurationException(Msg.code(2078) + "Unable to load nicknames", e);
|
||||
throw new ConfigurationException(Msg.code(2234) + "Unable to load nicknames", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -814,7 +814,7 @@ public class ResponseHighlighterInterceptor {
|
|||
writeLength(theServletResponse, outputBuffer.length());
|
||||
theServletResponse.getWriter().append(" total including HTML)");
|
||||
|
||||
theServletResponse.getWriter().append(" in estimated ");
|
||||
theServletResponse.getWriter().append(" in approximately ");
|
||||
theServletResponse.getWriter().append(writeSw.toString());
|
||||
theServletResponse.getWriter().append("</div>");
|
||||
|
||||
|
|
|
@ -173,7 +173,7 @@ public class HashMapResourceProvider<T extends IBaseResource> implements IResour
|
|||
|
||||
TreeMap<Long, T> versions = myIdToVersionToResourceMap.get(theId.getIdPart());
|
||||
if (versions == null || versions.isEmpty()) {
|
||||
throw new ResourceNotFoundException(Msg.code(1979) + theId);
|
||||
throw new ResourceNotFoundException(Msg.code(2250) + theId);
|
||||
}
|
||||
|
||||
T deletedInstance = (T) myFhirContext.getResourceDefinition(myResourceType).newInstance();
|
||||
|
@ -240,7 +240,7 @@ public class HashMapResourceProvider<T extends IBaseResource> implements IResour
|
|||
public synchronized List<IBaseResource> historyInstance(@IdParam IIdType theId, RequestDetails theRequestDetails) {
|
||||
LinkedList<T> retVal = myIdToHistory.get(theId.getIdPart());
|
||||
if (retVal == null) {
|
||||
throw new ResourceNotFoundException(Msg.code(1980) + theId);
|
||||
throw new ResourceNotFoundException(Msg.code(2248) + theId);
|
||||
}
|
||||
|
||||
return fireInterceptorsAndFilterAsNeeded(retVal, theRequestDetails);
|
||||
|
@ -255,7 +255,7 @@ public class HashMapResourceProvider<T extends IBaseResource> implements IResour
|
|||
public synchronized T read(@IdParam IIdType theId, RequestDetails theRequestDetails) {
|
||||
TreeMap<Long, T> versions = myIdToVersionToResourceMap.get(theId.getIdPart());
|
||||
if (versions == null || versions.isEmpty()) {
|
||||
throw new ResourceNotFoundException(Msg.code(1981) + theId);
|
||||
throw new ResourceNotFoundException(Msg.code(2247) + theId);
|
||||
}
|
||||
|
||||
T retVal;
|
||||
|
@ -271,14 +271,14 @@ public class HashMapResourceProvider<T extends IBaseResource> implements IResour
|
|||
}
|
||||
|
||||
if (retVal == null || ResourceMetadataKeyEnum.DELETED_AT.get(retVal) != null) {
|
||||
throw new ResourceGoneException(Msg.code(1983) + theId);
|
||||
throw new ResourceGoneException(Msg.code(2244) + theId);
|
||||
}
|
||||
|
||||
myReadCount.incrementAndGet();
|
||||
|
||||
retVal = fireInterceptorsAndFilterAsNeeded(retVal, theRequestDetails);
|
||||
if (retVal == null) {
|
||||
throw new ResourceNotFoundException(Msg.code(1984) + theId);
|
||||
throw new ResourceNotFoundException(Msg.code(2243) + theId);
|
||||
}
|
||||
return retVal;
|
||||
}
|
||||
|
|
|
@ -636,7 +636,7 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
|
|||
@Read(typeName = "OperationDefinition")
|
||||
public IBaseResource readOperationDefinition(@IdParam IIdType theId, RequestDetails theRequestDetails) {
|
||||
if (theId == null || theId.hasIdPart() == false) {
|
||||
throw new ResourceNotFoundException(Msg.code(1977) + theId);
|
||||
throw new ResourceNotFoundException(Msg.code(2245) + theId);
|
||||
}
|
||||
RestfulServerConfiguration configuration = getServerConfiguration();
|
||||
Bindings bindings = configuration.provideBindings();
|
||||
|
@ -650,7 +650,7 @@ public class ServerCapabilityStatementProvider implements IServerConformanceProv
|
|||
if (searchBindings != null && !searchBindings.isEmpty()) {
|
||||
return readOperationDefinitionForNamedSearch(searchBindings);
|
||||
}
|
||||
throw new ResourceNotFoundException(Msg.code(1978) + theId);
|
||||
throw new ResourceNotFoundException(Msg.code(2249) + theId);
|
||||
}
|
||||
|
||||
private String getOperationId(IIdType theId) {
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
@ -20,7 +20,7 @@
|
|||
<dependency>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-caching-api</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.github.ben-manes.caffeine</groupId>
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-fhir-serviceloaders</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-sample-client-apache</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-sample-client-okhttp</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-sample-server-jersey</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir-spring-boot</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>hapi-fhir-spring-boot-samples</artifactId>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-fhir</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -109,7 +109,7 @@ public final class ColumnTypeToDriverTypeToSqlType {
|
|||
setColumnType(ColumnTypeEnum.CLOB, DriverTypeEnum.MARIADB_10_1, "longtext");
|
||||
setColumnType(ColumnTypeEnum.CLOB, DriverTypeEnum.MYSQL_5_7, "longtext");
|
||||
setColumnType(ColumnTypeEnum.CLOB, DriverTypeEnum.ORACLE_12C, "clob");
|
||||
setColumnType(ColumnTypeEnum.CLOB, DriverTypeEnum.POSTGRES_9_4, "text");
|
||||
setColumnType(ColumnTypeEnum.CLOB, DriverTypeEnum.POSTGRES_9_4, "oid"); // the PG driver will write oid into a `text` column
|
||||
setColumnType(ColumnTypeEnum.CLOB, DriverTypeEnum.MSSQL_2012, "varchar(MAX)");
|
||||
}
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -122,7 +122,7 @@ public class FetchResourceIdsStep implements IFirstJobStepWorker<BulkExportJobPa
|
|||
|
||||
theDataSink.recoveredError(ex.getMessage());
|
||||
|
||||
throw new JobExecutionFailedException(Msg.code(2104) + " : " + ex.getMessage());
|
||||
throw new JobExecutionFailedException(Msg.code(2239) + " : " + ex.getMessage());
|
||||
}
|
||||
|
||||
ourLog.info("Submitted {} groups of ids for processing", submissionCount);
|
||||
|
|
|
@ -98,7 +98,7 @@ public class WriteBinaryStep implements IJobStepWorker<BulkExportJobParameters,
|
|||
ex.getMessage());
|
||||
ourLog.error(errorMsg);
|
||||
|
||||
throw new JobExecutionFailedException(Msg.code(2105) + errorMsg);
|
||||
throw new JobExecutionFailedException(Msg.code(2238) + errorMsg);
|
||||
}
|
||||
|
||||
DaoMethodOutcome outcome = binaryDao.create(binary,
|
||||
|
|
|
@ -72,7 +72,7 @@ public class Batch2JobRunnerImpl implements IBatch2JobRunner {
|
|||
public Batch2JobInfo getJobInfo(String theJobId) {
|
||||
JobInstance instance = myJobCoordinator.getInstance(theJobId);
|
||||
if (instance == null) {
|
||||
throw new ResourceNotFoundException(Msg.code(2102) + " : " + theJobId);
|
||||
throw new ResourceNotFoundException(Msg.code(2240) + " : " + theJobId);
|
||||
}
|
||||
return fromJobInstanceToBatch2JobInfo(instance);
|
||||
}
|
||||
|
|
|
@ -6,7 +6,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -7,7 +7,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -4,7 +4,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -475,7 +475,7 @@ public class ServerCapabilityStatementProvider extends BaseServerCapabilityState
|
|||
if (searchBindings != null && !searchBindings.isEmpty()) {
|
||||
return readOperationDefinitionForNamedSearch(searchBindings);
|
||||
}
|
||||
throw new ResourceNotFoundException(Msg.code(1985) + theId);
|
||||
throw new ResourceNotFoundException(Msg.code(2257) + theId);
|
||||
}
|
||||
|
||||
private OperationDefinition readOperationDefinitionForNamedSearch(List<SearchMethodBinding> bindings) {
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
|
@ -5,7 +5,7 @@
|
|||
<parent>
|
||||
<groupId>ca.uhn.hapi.fhir</groupId>
|
||||
<artifactId>hapi-deployable-pom</artifactId>
|
||||
<version>6.3.14-SNAPSHOT</version>
|
||||
<version>6.5.0-SNAPSHOT</version>
|
||||
<relativePath>../hapi-deployable-pom/pom.xml</relativePath>
|
||||
</parent>
|
||||
|
||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue